diff --git a/.gitignore b/.gitignore index f1e3d20..ebfa74d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,252 +1,35 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj +lib-cov +*.seed *.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc +*.csv +*.dat +*.out +*.pid +*.gz +*.swp -# Chutzpah Test files -_Chutzpah* +pids +logs +results +tmp -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb +#Build +public/css/main.css -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap +# API keys and secrets +.env -# TFS 2012 Local Workspace -$tf/ +# Dependency directory +node_modules +bower_components -# Guidance Automation Toolkit -*.gpState +# Editors +.idea +*.iml -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user +# OS metadata +.DS_Store +Thumbs.db -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml +# Ignore built ts files +dist/**/* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c52fcf5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ + +{ + "language": "node_js", + "node_js": "6", + "services": [ + "mongodb" + ], + "script": [ + "npm run build", + "npm run test" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..52d934b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "type": "node", + "request": "launch", + "name": "Debug", + "program": "${workspaceRoot}/dist/server.js", + "smartStep": true, + "outFiles": [ + "../dist/**/*.js" + ], + "protocol": "inspector" + } + ] +} + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bbd793f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/dist": true + }, + "typescript.referencesCodeLens.enabled": true, + "tslint.ignoreDefinitionFiles": false, + "tslint.autoFixOnSave": true, + "tslint.exclude": "**/node_modules/**/*" +} \ No newline at end of file diff --git a/README.md b/README.md index 8624b3d..13f9f75 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,440 @@ -# Contributing +Express TypeScript Starter +======================= -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +[![Dependency Status](https://david-dm.org/bowdenk7/express-typescript-starter.svg)](https://david-dm.org/bowdenk7/express-typescript-starter) [![Build Status](https://travis-ci.org/bowdenk7/express-typescript-starter.svg?branch=master)](https://travis-ci.org/bowdenk7/express-typescript-starter) + +**Live Demo**: TODO + +# Pre-reqs +- Install [Node.js](https://nodejs.org/en/) +- Install [MongoDB](https://docs.mongodb.com/manual/installation/) +- Install [VS Code](https://code.visualstudio.com/) + +# Getting started +- Clone the repository +``` +git clone --depth=1 https://github.com/bowdenk7/express-typescript-starter.git +``` +- Install dependencies +``` +cd +npm install +``` +- Start your mongoDB server (you'll probably want another command prompt) +``` +mongod +``` +- Build and run the project +``` +npm start +``` +Navigate to `http://localhost:3000` + +# TypeScript + Node +The main purpose of this repository is to show a good end-to-end project setup and workflow for writing Node code in TypeScript. +I will try to keep this as up-to-date as possible, but community contributions and recommendations for improvements are encourage and will be most welcome. + +In the next few sections I will call out everything that changes when adding TypeScript to an Express project. +Note that all of this has already been setup for this project, but feel free to use this as a reference for converting other Node.js project to TypeScript. + +> **Note on editors!** - TypeScript has great support in [every editor](http://www.typescriptlang.org/index.html#download-links), but this project has been pre-configured for use with [VS Code](https://code.visualstudio.com/). +Throughout the README I'll try to call out specific places where VS code really shines or where this project has been setup to take advantage of specific features. + +## Getting TypeScript +TypeScript itself is simple to add to any project with `npm`. +``` +npm install -D typescript +``` +If you're using VS Code then you're good to go! +VS Code will detect and use the TypeScript version you have installed in your `node_modules` folder. +For other editors, make sure you have the corresponding [TypeScript plugin](http://www.typescriptlang.org/index.html#download-links). + +## Project Structure +The most obvious difference in a TypeScript + Node project is the folder structure. +In a TypeScript project, you it's best to have separate _source_ and _distributable_ files. +TypeScript (`.ts`) files live in your `src` folder and after compilation are output as JavaScript (`.js`) in the `dist` folder. +The `test` and `views` folders remain top level as expected. + +The full folder structure of this app is explained below: + +> **Note!** Make sure you have already built the app using `npm run build` or `yarn run build` + +| Name | Description | +| ------------------------ | --------------------------------------------------------------------------------------------- | +| **.vscode** | Contains VS Code specific settings | +| **dist** | Contains the distributable (or output) from your TypeScript build. This is the code you ship | +| **node_modules** | Contains all your npm dependencies | +| **src** | Contains your source code that will be compiled to the dist dir | +| **src/config** | Passport authentication strategies and login middleware. Add other complex config code here | +| **src/controllers** | Controllers define functions that respond to various http requests | +| **src/models** | Models define Mongoose schemas that will be used in storing and retrieving data from MongoDB | +| **src/public** | Static assets that will be used client side | +| **src/types** | Holds .d.ts files not found on DefinitelyTyped. Covered more in this [section](#) | +| **src**/server.ts | Entry point to your express app | +| **test** | Contains your tests. Seperate from source because there is a different build process. | +| **views** | Views define how your app renders on the client. In this case we're using pug | +| .env.example | API keys, tokens, passwords, database URI. Clone this, but don't check it in to public repos. | +| .travis.yml | Used to configure Travis CI build | +| .copyStaticAssets.js | Build script that copies images, fonts, and JS libs to the dist folder | +| package.json | File that contains npm dependencies as well as [build scripts](#what-if-a-library-isnt-on-definitelytyped) | +| tsconfig.json | Config settings for compiling server code written in TypeScript | +| tsconfig.tests.json | Config settings for compiling tests written in TypeScript | +| tslint.json | Config settings for TSLint code style checking | +| yarn.lock | Contains same dependency version info as package.json, but used with yarn | + +## Building the project +It is rare for JavaScript projects not to have some kind of build pipeline these days, however Node projects typically have the least amount build configuration. +Because of this I've tried to keep the build as simple as possible. +If you're concerned about compile time, the main watch task takes ~2s to refresh. + +### Configuring TypeScript compilation +TypeScript uses the file `tsconfig.json` to adjust project compile options. +Let's dissect this project's `tsconfig.json`, starting with the `compilerOptions` which details how your project is compiled. + +```json + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": true, + "moduleResolution": "node", + "sourceMap": true, + "outDir": "dist", + "baseUrl": ".", + "paths": { + "*": [ + "node_modules/*", + "src/types/*" + ] + } + }, +``` + +| `compilerOptions` | Description | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------ | +| `"module": "commonjs"` | The **output** module type (in your `.js` files). Node uses commonjs, so that is what we use | +| `"target": "es6"` | The output language level. Node supports ES6, so we can target that here | +| `"noImplicitAny": true` | Enables a stricter setting which throws errors when something has a default `any` value | +| `"moduleResolution": "node"` | TypeScript attempts to mimic Node's module resolution strategy. Read more [here](https://www.typescriptlang.org/docs/handbook/module-resolution.html#node) | +| `"sourceMap": true` | We want source maps to be output along side our JavaScript. See the [debugging](#debugging) section | +| `"outDir": "dist"` | Location to output `.js` files after compilation | +| `"baseUrl": "."` | Part of configuring module resolution. See [path mapping section](#installing-dts-files-from-definitelytyped) | +| `paths: {...}` | Part of configuring module resolution. See [path mapping section](#installing-dts-files-from-definitelytyped) | + + + +The rest of the file define the TypeScript project context. +The project context is basically a set of options that determine which files are compiled when the compiler is invoked with a specific `tsconfig.json`. +In this case, we use the following to define our project context: +```json + "include": [ + "src/**/*" + ] +``` +`include` takes an array of glob patterns of files to include in the compilation. +This project is fairly simple and all of our .ts files are under the `src` folder. +For more complex setups, you can include an `exclude` array of glob patterns that removes specific files from the set defined with `include`. +There is also a `files` option which takes an array of individual file names which overrides both `include` and `exclude`. + + +### Running the build +All the different build steps are orchestrated via [npm scripts](https://docs.npmjs.com/misc/scripts). +Npm scripts basically allow us to call (and chain) terminal commands via npm. +This is nice because most JavaScript tools have easy to use command line utilities allowing us to not need grunt or gulp to manage our builds. +If you open `package.json`, you will see a `scripts` section with all the different scripts you can call. +To call a script, simply run `npm run ` (or `yarn run **Note!** Because we're using `"noImplicitAny": true`, we are required to have a `.d.ts` file for **every** library we use. While you could set `noImplicitAny` to `false` to silence errors about missing `.d.ts` files, it is a best practice to have a `.d.ts` file for every library. (Even the `.d.ts` file is [basically empty!](#writing-a-dts-file)) + +### Installing `.d.ts` files from DefinitelyTyped +For the most part, you'll find `.d.ts` files for the libraries you are using on DefinitelyTyped. +These `.d.ts` files can be easily installed into your project by using the npm scope `@types`. +For example, if we want the `.d.ts` file for jQuery, we can do so with `npm install --save-dev @types/jquery`. + +> **Note!** Be sure to add `--save-dev` (or `-D`) to your `npm install`. `.d.ts` files are project dependencies, but only used at compile time and thus should be dev dependencies. + +In this template, all the `.d.ts` files have already been added to `devDependencies` in `package.json`, so you will get everything you need after running your first `npm install`. +Once `.d.ts` files have been installed using npm, you should see them in your `node_modules/@types` folder. +The compiler will always look in this folder for `.d.ts` files when resolving JavaScript libraries. + +### What if a library isn't on DefinitelyTyped? +If you try to install a `.d.ts` file from `@types` and it isn't found, or you check DefinitelyTyped and cannot find a specific library, you will want to create your own `.d.ts file`. +In the `src` folder of this project, you'll find the `types` folder which holds the `.d.ts` files that aren't on DefinitelyTyped (or weren't as of the time of this writing). + +#### Setting up TypeScript to look for `.d.ts` files in another folder +The compiler knows to look in `node_modules/@types` by default, but to help the compiler find our own `.d.ts` files we have to configure path mapping in our `tsconfig.json`. +Path mapping can get pretty confusing, but the basic idea is that the TypeScript compiler will look in specific places, in a specific order when resolving modules, and we have the ability to tell the compiler exactly how to do it. +In the `tsconfig.json` for this project you'll see the following: +```json +"baseUrl": ".", +"paths": { + "*": [ + "src/types/*" + ] +} +``` +This tells the TypeScript compiler that in addition to looking in `node_modules/@types` for every import (`*`) also look in our own `.d.ts` file location `` + `src/types/*`. +So when we write something like: +```ts +import * as lusca from "lusca"; +``` +First the compiler will look for a `d.ts` file in `node_modules/@types` and then when it doesn't find one look in `src/types` and find our file `lusca.d.ts`. + +#### Using `dts-gen` +Unless you are familiar with `.d.ts` files, I strongly recommend trying to use the tool [dts-gen](https://github.com/Microsoft/dts-gen) first. +The [README](https://github.com/Microsoft/dts-gen#dts-gen-a-typescript-definition-file-generator) does a great job explaining how to use the tool, and for most cases, you'll get an excellent scaffold of a `.d.ts` file to start with. +In this project, `bcrypt-nodejs.d.ts`, `fbgraph.d.ts`, and `lusca.d.ts` were all generated using `dts-gen`. + +#### Writing a `.d.ts` file +If generating a `.d.ts` using `dts-gen` isn't working, [you should tell me about it first](TODO-survey-link), but then you can create your own `.d.ts` file. + +If you just want to silence the compiler for the time being, create a file called `.d.ts` in your `types` folder and then add this line of code: +```ts +declare module ""; +``` + +If you want to invest some time into making a great `.d.ts` file that will give you great type checking and IntelliSense, the TypeScript website has great [docs on authoring `.d.ts` files](http://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html). + +#### Contributing to DefinitelyTyped +The reason it's so easy to get great `.d.ts` files for most libraries is that developers like you contribute their work back to DefinitelyTyped. +Contributing `.d.ts` files is a great way to get into the open source community if it's something you've never tried before, and as soon as your changes are accepted, every other developer in the world has access to your work. + +If you're interested in giving it a shot, check out the [guidance on DefinitelyTyped](https://github.com/definitelyTyped/DefinitelyTyped/#how-can-i-contribute). +If you're not interested, [you should tell me why](TODO-survey-link) so we can help make it easier in the future! + +### Summary of `.d.ts` management +In general if you stick to the following steps you should have minimal `.d.ts` issues; +1. After installing any npm package as a dependency or dev dependency, immediately try to install the `.d.ts` file via `@types`. +2. If the library has a `.d.ts` file on DefinitelyTyped, the install will succeed and you are done. +If the install fails because the package doesn't exist, continue to step 3. +3. Make sure you project is [configured for supplying your own `d.ts` files](#setting-up-typescript-to-look-for-dts-files-in-another-folder) +4. Try to [generate a `.d.ts` file with dts-gen](#using-dts-gen). +If it succeeds, you are done. +If not, continue to step 5. +5. Create a file called `.d.ts` in your `types` folder. +6. Add the following code: +```ts +declare module ""; +``` +7. At this point everything should compile with no errors and you can either improve the types in the `.d.ts` file by following this [guide on authoring `.d.ts` files](http://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html) or continue with no types. +8. If you are still having issues, let me know by sending me an email or pinging me on twitter, I will help you. + +## Debugging +Debugging TypeScript is exactly like debugging JavaScript with one caveat, you need source maps. + +### Source maps +Source maps allow you to drop break points in your TypeScript source code and have that break point be hit by the JavaScript that is being executed at runtime. + +> **Note!** - Source maps aren't specific to TypeScript. +Anytime JavaScript is transformed (transpiled, compiled, optimized, minified, etc) you need source maps so that the code that is executed at runtime can be _mapped_ back to the source that generated it. + +The best part of source maps is when configured correctly, you don't even know they exist! So let's take a look at how we do that in this project. + +#### Configuring source maps +First you need to make sure your `tsconfig.json` has source map generation enabled: +```json +"compilerOptions" { + "sourceMaps": true +} +``` +With this option enabled, next to every `.js` file that the TypeScript compiler outputs there will be a `.map.js` file as well. +This `.map.js` file provides the information necessary to map back to the source `.ts` file while debugging. + +> **Note!** - It is also possible to generate "inline" source maps using `"inlineSourceMap": true`. +This is more common when writing client side code because some bundlers need inline source maps to preserve the mapping through the bundle. +Because we are writing Node.js code, we don't have to worry about this. + +### Using the debugger in VS Code +Debugging is one of the places where VS Code really shines over other editors. +Node.js debugging in VS Code is easy to setup and even easier to use. +This project comes pre-configured with everything you need to get started. + +When you hit `F5` in VS Code, it looks for a top level `.vscode` folder with a `launch.json` file. +In this file, you can tell VS Code exactly what you want to do: + +```json +{ + "type": "node", + "request": "launch", + "name": "Debug", + "program": "${workspaceRoot}/dist/server.js", + "smartStep": true, + "outFiles": [ + "../dist/**/*.js" + ], + "protocol": "inspector" +} +``` +This is mostly identical to the "Node.js: Launch Program" template with a couple minor changes: + +| `launch.json` Options | Description | +| ----------------------------------------------- | --------------------------------------------------------------- | +| `"program": "${workspaceRoot}/dist/server.js",` | Modified to point to our entry point in `dist` | +| `"smartStep": true,` | Won't step into code that doesn't have a source map | +| `"outFiles": [...]` | Specify where output files are dropped. Use with source maps | +| `"protocol": inspector,` | Use the new Node debug protocal because we're on the latest node| + +With this file in place, you can hit `F5` to serve the project with the debugger already attached. +Now just set your breakpoints and go! + +> Warning! Make sure you don't have the project already running from another command line. +VS Code will try to launch on the same port and error out. +Likewise be sure to stop the debugger before returning to your normal `npm start` process. + +## Testing +For this project, I chose [Jest](https://facebook.github.io/jest/) as our test framework. +While Mocha is probably more common, Mocha seems to be looking for a new maintainer and setting up TypeScript testing in Jest is wicked simple. + +### Install the components +To add TypeScript + Jest support, first install a few npm packages: +``` +npm install -D jest ts-jest +``` +`jest` is the testing framework itself, and `ts-jest` is just a simple function to make running TypeScript tests a little easier. + +### Configure Jest +Jest's configuration lives in `package.json`, so let's open it up and add the following code: +```json +"jest": { + "globals": { + "__TS_CONFIG__": "tsconfig.json" + }, + "moduleFileExtensions": [ + "ts", + "js" + ], + "transform": { + "^.+\\.(ts)$": "./node_modules/ts-jest/preprocessor.js" + }, + "testMatch": [ + "**/test/**/*.test.(ts|js)" + ], + "testEnvironment": "node" + }, +``` +Basically we are telling Jest that we want it to consume all files that match the pattern `"**/test/**/*.test.(ts|js)"` (all `.test.ts`/`.test.js` files in the `test` folder), but we want to preprocess the `.ts` files first. +This preprocess step is very flexible, but in our case, we just want to compile our TypeScript to JavaScript using our `tsconfig.json`. +This all happens in memory when you run the tests, so there are no output `.js` test files for you to manage. + +### Running tests + + +### Writing tests +Writing tests for web apps has entire books dedicated to it and best practices are strongly influenced by personal style, so I'm deliberately avoiding discussing how or when to write tests in this guide. +However, if prescriptive guidance on testing is something that you're interested in, [let me know](TODO-survey-link), I'll do some homework and get back to you. + +## Using ES6 Modules + +## Adding types + +## Configuring your VS Code environment + +### Project settings + +### Extensions + +#### TSLint + +#### Spellcheck + +## TSLint +TSLint is a code linter which mainly helps catch minor code quality and style issues. +TSLint is very similar to ESLint or JSLint but is built with TypeScript in mind. + +### TSLint rules +Like most linters, TSLint has a wide set of configurable rules as well as support for custom rule sets. +All rules are configured through `tslint.json`. +In this project, we are using a fairly basic set of rules with no additional custom rules. +The settings are largely based off the TSLint settings that we use to develop TypeScript itself. + +### Running TSLint +Like the rest of our build steps, we use npm scripts to invoke TSLint. +To run TSLint you can call the main build script or just the TSLint task. +``` +npm run build // runs full build including TSLint +npm run tslint // runs only TSLint +``` +Notice that TSLint is not a part of the main watch task. +It can be annoying for TSLint to clutter the output window while in the middle of writing a function, so I elected to only run it only during the full build. +If you are interesting in seeing TSLint feedback as soon as possible, I strongly recommend the [TSLint extension in VS Code](). + +# Dependencies +Dependencies are managed through `package.json`. +In that file you'll find two sections: +## `dependencies` + +| Package | Description | +| ------------------------------- | --------------------------------------------------------------------- | +| async | Utility library that provides asynchronous control flow. | +| bcrypt-nodejs | Library for hashing and salting user passwords. | +| body-parser | Express 4 middleware. | +| compression | Express 4 middleware. | +| connect-mongo | MongoDB session store for Express. | +| dotenv | Loads environment variables from .env file. | +| errorhandler | Express 4 middleware. | +| express | Node.js web framework. | +| express-flash | Provides flash messages for Express. | +| express-session | Express 4 middleware. | +| express-validator | Easy form validation for Express. | +| fbgraph | Facebook Graph API library. | +| lusca | CSRF middleware. | +| mongoose | MongoDB ODM. | +| morgan | Express 4 middleware. | +| nodemailer | Node.js library for sending emails. | +| passport | Simple and elegant authentication library for node.js | +| passport-facebook | Sign-in with Facebook plugin. | +| passport-local | Sign-in with Username and Password plugin. | +| pug (jade) | Template engine for Express. | +| request | Simplified HTTP request library. | + +## `devDependencies` + +| Package | Description | +| ------------------------------- | --------------------------------------------------------------------- | +| concurrently | Utility that manages multiple concurrent tasks. Used with npm scripts | +| jest | Reports real-time server metrics for Express. | +| node-sass | GitHub API library. | +| supertest | HTTP assertion library. | +| ts-test | Instagram API library. | +| tslint | Linter (similar to ESLint) for TypeScript files | +| typescript | JavaScript compiler/type checker that boosts JavaScript productivity | + +To install or update these dependencies you can use either `npm` or `yarn`. + +# Other +Here is a section of miscellaneous tips. + +## Yarn vs NPM + +[Yarn](https://yarnpkg.com/en/) is a new JavaScript package manager that builds off of npm. +It is not a replacement for npm, however it does provide a few advantages over npm in some cases. + +Yarn is generally faster and has a few extra features like `yarn why ` which will tell you which package required a specific dependency. +Yarn also doesn't clutter your command prompt when your npm scripts return with status 1. +For these reasons I would personally recommend downloading and giving Yarn a shot. +That said, everything in this template can be used with npm as well. + +# Hackathon Start Project +A majority of this quick start's content was inspired or adapted from Sahat's excellent [Hackathon Starter project](https://github.com/sahat/hackathon-starter). \ No newline at end of file diff --git a/copyStaticAssets.js b/copyStaticAssets.js new file mode 100644 index 0000000..23c11e2 --- /dev/null +++ b/copyStaticAssets.js @@ -0,0 +1,5 @@ +var shell = require('shelljs'); + +shell.cp('-R', 'src/public/js/lib', 'dist/public/js/lib'); +shell.cp('-R', 'src/public/fonts', 'dist/public/fonts'); +shell.cp('-R', 'src/public/images', 'dist/public/images'); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..c12c69d --- /dev/null +++ b/package.json @@ -0,0 +1,93 @@ +{ + "name": "express-typescript-starter", + "version": "0.1.0", + "description": "A starting point for Node.js express apps with TypeScript", + "repository": { + "type": "git", + "url": "https://github.com/sahat/hackathon-starter.git" + }, + "author": "Bowden Kelly", + "license": "MIT", + "scripts": { + "start": "npm run build && npm run watch", + "build": "npm run build-sass && npm run build-ts && npm run tslint && npm run copy-static-assets", + "serve": "node dist/server.js", + "watch": "concurrently -k -p \"[{name}]\" -n \"Sass,TypeScript,Node\" -c \"yellow.bold,cyan.bold,green.bold\" \"npm run watch-sass\" \"npm run watch-ts\" \"nodemon dist/server.js\"", + "test": "jest --forceExit", + "build-ts": "tsc", + "watch-ts": "tsc -w", + "build-sass": "node-sass src/public/css/main.scss dist/public/css/main.css", + "watch-sass": "node-sass -w src/public/css/main.scss dist/public/css/main.css", + "tslint": "tslint -c tslint.json -p tsconfig.json", + "copy-static-assets": "node copyStaticAssets.js" + }, + "jest": { + "globals": { + "__TS_CONFIG__": "tsconfig.json" + }, + "moduleFileExtensions": [ + "ts", + "js" + ], + "transform": { + "^.+\\.(ts|tsx)$": "./node_modules/ts-jest/preprocessor.js" + }, + "testMatch": [ + "**/test/**/*.test.(ts|js)" + ], + "testEnvironment": "node" + }, + "dependencies": { + "async": "^2.1.2", + "bcrypt-nodejs": "^0.0.3", + "body-parser": "^1.15.2", + "compression": "^1.6.2", + "connect-mongo": "^1.3.2", + "dotenv": "^2.0.0", + "errorhandler": "^1.4.3", + "express": "^4.14.0", + "express-flash": "^0.0.2", + "express-session": "^1.14.2", + "express-validator": "^3.1.3", + "fbgraph": "^1.3.0", + "lodash": "^4.17.4", + "lusca": "^1.4.1", + "mongoose": "^4.6.6", + "morgan": "^1.7.0", + "nodemailer": "^2.6.4", + "passport": "0.3.2", + "passport-facebook": "^2.1.1", + "passport-local": "^1.0.0", + "pug": "^2.0.0-beta6", + "request": "^2.78.0" + }, + "devDependencies": { + "@types/async": "^2.0.40", + "@types/body-parser": "^1.16.2", + "@types/connect-mongo": "0.0.32", + "@types/dotenv": "^2.0.20", + "@types/errorhandler": "0.0.30", + "@types/express": "^4.0.35", + "@types/express-session": "0.0.32", + "@types/jest": "^19.2.2", + "@types/jquery": "^2.0.41", + "@types/lodash": "^4.14.63", + "@types/mongodb": "^2.1.43", + "@types/mongoose": "^4.7.9", + "@types/morgan": "^1.7.32", + "@types/node": "^7.0.12", + "@types/nodemailer": "^1.3.32", + "@types/passport": "^0.3.3", + "@types/passport-facebook": "^2.1.3", + "@types/request": "0.0.42", + "@types/supertest": "^2.0.0", + "concurrently": "^3.4.0", + "jest": "^19.0.2", + "node-sass": "^4.5.2", + "shelljs": "^0.7.7", + "supertest": "^2.0.1", + "ts-jest": "^19.0.8", + "tslint": "^5.0.0", + "typescript": "^2.2.2" + } +} diff --git a/src/config/passport.ts b/src/config/passport.ts new file mode 100644 index 0000000..92d7bc8 --- /dev/null +++ b/src/config/passport.ts @@ -0,0 +1,142 @@ +import * as passport from "passport"; +import * as request from "request"; +import * as passportLocal from "passport-local"; +import * as passportFacebook from "passport-facebook"; +import * as _ from "lodash"; + +// import { User, UserType } from '../models/User'; +import { default as User } from "../models/User"; +import {Request, Response, NextFunction} from "express"; + +const LocalStrategy = passportLocal.Strategy; +const FacebookStrategy = passportFacebook.Strategy; + +passport.serializeUser((user, done) => { + done(undefined, user.id); +}); + +passport.deserializeUser((id, done) => { + User.findById(id, (err, user) => { + done(err, user); + }); +}); + + +/** + * Sign in using Email and Password. + */ +passport.use(new LocalStrategy({ usernameField: "email" }, (email, password, done) => { + User.findOne({ email: email.toLowerCase() }, (err, user: any) => { + if (err) { return done(err); } + if (!user) { + return done(undefined, false, { message: `Email ${email} not found.` }); + } + user.comparePassword(password, (err: Error, isMatch: boolean) => { + if (err) { return done(err); } + if (isMatch) { + return done(undefined, user); + } + return done(undefined, false, { message: "Invalid email or password." }); + }); + }); +})); + + +/** + * OAuth Strategy Overview + * + * - User is already logged in. + * - Check if there is an existing account with a provider id. + * - If there is, return an error message. (Account merging not supported) + * - Else link new OAuth account with currently logged-in user. + * - User is not logged in. + * - Check if it's a returning user. + * - If returning user, sign in and we are done. + * - Else check if there is an existing account with user's email. + * - If there is, return an error message. + * - Else create a new account. + */ + + +/** + * Sign in with Facebook. + */ +passport.use(new FacebookStrategy({ + clientID: process.env.FACEBOOK_ID, + clientSecret: process.env.FACEBOOK_SECRET, + callbackURL: "/auth/facebook/callback", + profileFields: ["name", "email", "link", "locale", "timezone"], + passReqToCallback: true +}, (req: any, accessToken, refreshToken, profile, done) => { + if (req.user) { + User.findOne({ facebook: profile.id }, (err, existingUser) => { + if (err) { return done(err); } + if (existingUser) { + req.flash("errors", { msg: "There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account." }); + done(err); + } else { + User.findById(req.user.id, (err, user: any) => { + if (err) { return done(err); } + user.facebook = profile.id; + user.tokens.push({ kind: "facebook", accessToken }); + user.profile.name = user.profile.name || `${profile.name.givenName} ${profile.name.familyName}`; + user.profile.gender = user.profile.gender || profile._json.gender; + user.profile.picture = user.profile.picture || `https://graph.facebook.com/${profile.id}/picture?type=large`; + user.save((err: Error) => { + req.flash("info", { msg: "Facebook account has been linked." }); + done(err, user); + }); + }); + } + }); + } else { + User.findOne({ facebook: profile.id }, (err, existingUser) => { + if (err) { return done(err); } + if (existingUser) { + return done(undefined, existingUser); + } + User.findOne({ email: profile._json.email }, (err, existingEmailUser) => { + if (err) { return done(err); } + if (existingEmailUser) { + req.flash("errors", { msg: "There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings." }); + done(err); + } else { + const user: any = new User(); + user.email = profile._json.email; + user.facebook = profile.id; + user.tokens.push({ kind: "facebook", accessToken }); + user.profile.name = `${profile.name.givenName} ${profile.name.familyName}`; + user.profile.gender = profile._json.gender; + user.profile.picture = `https://graph.facebook.com/${profile.id}/picture?type=large`; + user.profile.location = (profile._json.location) ? profile._json.location.name : ""; + user.save((err: Error) => { + done(err, user); + }); + } + }); + }); + } +})); + +/** + * Login Required middleware. + */ +export let isAuthenticated = (req: Request, res: Response, next: NextFunction) => { + if (req.isAuthenticated()) { + return next(); + } + res.redirect("/login"); +}; + +/** + * Authorization Required middleware. + */ +export let isAuthorized = (req: Request, res: Response, next: NextFunction) => { + const provider = req.path.split("/").slice(-1)[0]; + + if (_.find(req.user.tokens, { kind: provider })) { + next(); + } else { + res.redirect(`/auth/${provider}`); + } +}; diff --git a/src/controllers/api.ts b/src/controllers/api.ts new file mode 100644 index 0000000..478cea3 --- /dev/null +++ b/src/controllers/api.ts @@ -0,0 +1,33 @@ +"use strict"; + +import * as async from "async"; +import * as request from "request"; +import * as graph from "fbgraph"; +import {Response, Request, NextFunction} from "express"; + + +/** + * GET /api + * List of API examples. + */ +export let getApi = (req: Request, res: Response) => { + res.render("api/index", { + title: "API Examples" + }); +}; + +/** + * GET /api/facebook + * Facebook API example. + */ +export let getFacebook = (req: Request, res: Response, next: NextFunction) => { + const token = req.user.tokens.find((token: any) => token.kind === "facebook"); + graph.setAccessToken(token.accessToken); + graph.get(`${req.user.facebook}?fields=id,name,email,first_name,last_name,gender,link,locale,timezone`, (err: Error, results: graph.FacebookUser) => { + if (err) { return next(err); } + res.render("api/facebook", { + title: "Facebook API", + profile: results + }); + }); +}; diff --git a/src/controllers/contact.ts b/src/controllers/contact.ts new file mode 100644 index 0000000..d4a5067 --- /dev/null +++ b/src/controllers/contact.ts @@ -0,0 +1,53 @@ +import * as nodemailer from "nodemailer"; +import {Request, Response} from "express"; + +const transporter = nodemailer.createTransport({ + service: "SendGrid", + auth: { + user: process.env.SENDGRID_USER, + pass: process.env.SENDGRID_PASSWORD + } +}); + +/** + * GET /contact + * Contact form page. + */ +export let getContact = (req: Request, res: Response) => { + res.render("contact", { + title: "Contact" + }); +}; + +/** + * POST /contact + * Send a contact form via Nodemailer. + */ +export let postContact = (req: Request, res: Response) => { + req.assert("name", "Name cannot be blank").notEmpty(); + req.assert("email", "Email is not valid").isEmail(); + req.assert("message", "Message cannot be blank").notEmpty(); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/contact"); + } + + const mailOptions = { + to: "your@email.com", + from: `${req.body.name} <${req.body.email}>`, + subject: "Contact Form", + text: req.body.message + }; + + transporter.sendMail(mailOptions, (err) => { + if (err) { + req.flash("errors", { msg: err.message }); + return res.redirect("/contact"); + } + req.flash("success", { msg: "Email has been sent successfully!" }); + res.redirect("/contact"); + }); +}; diff --git a/src/controllers/home.ts b/src/controllers/home.ts new file mode 100644 index 0000000..8fe6526 --- /dev/null +++ b/src/controllers/home.ts @@ -0,0 +1,12 @@ +import {Request, Response} from "express"; + +/** + * GET / + * Home page. + */ +export let index = (req: Request, res: Response) => { + res.render("home", { + title: "Home" + }); +}; + diff --git a/src/controllers/user.ts b/src/controllers/user.ts new file mode 100644 index 0000000..8334ad0 --- /dev/null +++ b/src/controllers/user.ts @@ -0,0 +1,380 @@ +import * as async from "async"; +import * as crypto from "crypto"; +import * as nodemailer from "nodemailer"; +import * as passport from "passport"; +import {default as User, UserModel, AuthToken} from "../models/User"; +import {Request, Response, NextFunction} from "express"; +import {LocalStrategyInfo} from "passport-local"; +import { WriteError } from "mongodb"; +const request = require("express-validator"); + + +/** + * GET /login + * Login page. + */ +export let getLogin = (req: Request, res: Response) => { + if (req.user) { + return res.redirect("/"); + } + res.render("account/login", { + title: "Login" + }); +}; + +/** + * POST /login + * Sign in using email and password. + */ +export let postLogin = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Email is not valid").isEmail(); + req.assert("password", "Password cannot be blank").notEmpty(); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/login"); + } + + passport.authenticate("local", (err: Error, user: UserModel, info: LocalStrategyInfo) => { + if (err) { return next(err); } + if (!user) { + req.flash("errors", info); + return res.redirect("/login"); + } + req.logIn(user, (err) => { + if (err) { return next(err); } + req.flash("success", { msg: "Success! You are logged in." }); + res.redirect(req.session.returnTo || "/"); + }); + })(req, res, next); +}; + +/** + * GET /logout + * Log out. + */ +export let logout = (req: Request, res: Response) => { + req.logout(); + res.redirect("/"); +}; + +/** + * GET /signup + * Signup page. + */ +export let getSignup = (req: Request, res: Response) => { + if (req.user) { + return res.redirect("/"); + } + res.render("account/signup", { + title: "Create Account" + }); +}; + +/** + * POST /signup + * Create a new local account. + */ +export let postSignup = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Email is not valid").isEmail(); + req.assert("password", "Password must be at least 4 characters long").len(4); + req.assert("confirmPassword", "Passwords do not match").equals(req.body.password); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/signup"); + } + + const user = new User({ + email: req.body.email, + password: req.body.password + }); + + User.findOne({ email: req.body.email }, (err, existingUser) => { + if (err) { return next(err); } + if (existingUser) { + req.flash("errors", { msg: "Account with that email address already exists." }); + return res.redirect("/signup"); + } + user.save((err) => { + if (err) { return next(err); } + req.logIn(user, (err) => { + if (err) { + return next(err); + } + res.redirect("/"); + }); + }); + }); +}; + +/** + * GET /account + * Profile page. + */ +export let getAccount = (req: Request, res: Response) => { + res.render("account/profile", { + title: "Account Management" + }); +}; + +/** + * POST /account/profile + * Update profile information. + */ +export let postUpdateProfile = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Please enter a valid email address.").isEmail(); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/account"); + } + + User.findById(req.user.id, (err, user: UserModel) => { + if (err) { return next(err); } + user.email = req.body.email || ""; + user.profile.name = req.body.name || ""; + user.profile.gender = req.body.gender || ""; + user.profile.location = req.body.location || ""; + user.profile.website = req.body.website || ""; + user.save((err: WriteError) => { + if (err) { + if (err.code === 11000) { + req.flash("errors", { msg: "The email address you have entered is already associated with an account." }); + return res.redirect("/account"); + } + return next(err); + } + req.flash("success", { msg: "Profile information has been updated." }); + res.redirect("/account"); + }); + }); +}; + +/** + * POST /account/password + * Update current password. + */ +export let postUpdatePassword = (req: Request, res: Response, next: NextFunction) => { + req.assert("password", "Password must be at least 4 characters long").len(4); + req.assert("confirmPassword", "Passwords do not match").equals(req.body.password); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/account"); + } + + User.findById(req.user.id, (err, user: UserModel) => { + if (err) { return next(err); } + user.password = req.body.password; + user.save((err: WriteError) => { + if (err) { return next(err); } + req.flash("success", { msg: "Password has been changed." }); + res.redirect("/account"); + }); + }); +}; + +/** + * POST /account/delete + * Delete user account. + */ +export let postDeleteAccount = (req: Request, res: Response, next: NextFunction) => { + User.remove({ _id: req.user.id }, (err) => { + if (err) { return next(err); } + req.logout(); + req.flash("info", { msg: "Your account has been deleted." }); + res.redirect("/"); + }); +}; + +/** + * GET /account/unlink/:provider + * Unlink OAuth provider. + */ +export let getOauthUnlink = (req: Request, res: Response, next: NextFunction) => { + const provider = req.params.provider; + User.findById(req.user.id, (err, user: any) => { + if (err) { return next(err); } + user[provider] = undefined; + user.tokens = user.tokens.filter((token: AuthToken) => token.kind !== provider); + user.save((err: WriteError) => { + if (err) { return next(err); } + req.flash("info", { msg: `${provider} account has been unlinked.` }); + res.redirect("/account"); + }); + }); +}; + +/** + * GET /reset/:token + * Reset Password page. + */ +export let getReset = (req: Request, res: Response, next: NextFunction) => { + if (req.isAuthenticated()) { + return res.redirect("/"); + } + User + .findOne({ passwordResetToken: req.params.token }) + .where("passwordResetExpires").gt(Date.now()) + .exec((err, user) => { + if (err) { return next(err); } + if (!user) { + req.flash("errors", { msg: "Password reset token is invalid or has expired." }); + return res.redirect("/forgot"); + } + res.render("account/reset", { + title: "Password Reset" + }); + }); +}; + +/** + * POST /reset/:token + * Process the reset password request. + */ +export let postReset = (req: Request, res: Response, next: NextFunction) => { + req.assert("password", "Password must be at least 4 characters long.").len(4); + req.assert("confirm", "Passwords must match.").equals(req.body.password); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("back"); + } + + async.waterfall([ + function resetPassword(done: Function) { + User + .findOne({ passwordResetToken: req.params.token }) + .where("passwordResetExpires").gt(Date.now()) + .exec((err, user: any) => { + if (err) { return next(err); } + if (!user) { + req.flash("errors", { msg: "Password reset token is invalid or has expired." }); + return res.redirect("back"); + } + user.password = req.body.password; + user.passwordResetToken = undefined; + user.passwordResetExpires = undefined; + user.save((err: WriteError) => { + if (err) { return next(err); } + req.logIn(user, (err) => { + done(err, user); + }); + }); + }); + }, + function sendResetPasswordEmail(user: UserModel, done: Function) { + const transporter = nodemailer.createTransport({ + service: "SendGrid", + auth: { + user: process.env.SENDGRID_USER, + pass: process.env.SENDGRID_PASSWORD + } + }); + const mailOptions = { + to: user.email, + from: "express-ts@starter.com", + subject: "Your password has been changed", + text: `Hello,\n\nThis is a confirmation that the password for your account ${user.email} has just been changed.\n` + }; + transporter.sendMail(mailOptions, (err) => { + req.flash("success", { msg: "Success! Your password has been changed." }); + done(err); + }); + } + ], (err) => { + if (err) { return next(err); } + res.redirect("/"); + }); +}; + +/** + * GET /forgot + * Forgot Password page. + */ +export let getForgot = (req: Request, res: Response) => { + if (req.isAuthenticated()) { + return res.redirect("/"); + } + res.render("account/forgot", { + title: "Forgot Password" + }); +}; + +/** + * POST /forgot + * Create a random token, then the send user an email with a reset link. + */ +export let postForgot = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Please enter a valid email address.").isEmail(); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", errors); + return res.redirect("/forgot"); + } + + async.waterfall([ + function createRandomToken(done: Function) { + crypto.randomBytes(16, (err, buf) => { + const token = buf.toString("hex"); + done(err, token); + }); + }, + function setRandomToken(token: AuthToken, done: Function) { + User.findOne({ email: req.body.email }, (err, user: any) => { + if (err) { return done(err); } + if (!user) { + req.flash("errors", { msg: "Account with that email address does not exist." }); + return res.redirect("/forgot"); + } + user.passwordResetToken = token; + user.passwordResetExpires = Date.now() + 3600000; // 1 hour + user.save((err: WriteError) => { + done(err, token, user); + }); + }); + }, + function sendForgotPasswordEmail(token: AuthToken, user: UserModel, done: Function) { + const transporter = nodemailer.createTransport({ + service: "SendGrid", + auth: { + user: process.env.SENDGRID_USER, + pass: process.env.SENDGRID_PASSWORD + } + }); + const mailOptions = { + to: user.email, + from: "hackathon@starter.com", + subject: "Reset your password on Hackathon Starter", + text: `You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n + Please click on the following link, or paste this into your browser to complete the process:\n\n + http://${req.headers.host}/reset/${token}\n\n + If you did not request this, please ignore this email and your password will remain unchanged.\n` + }; + transporter.sendMail(mailOptions, (err) => { + req.flash("info", { msg: `An e-mail has been sent to ${user.email} with further instructions.` }); + done(err); + }); + } + ], (err) => { + if (err) { return next(err); } + res.redirect("/forgot"); + }); +}; diff --git a/src/models/User.ts b/src/models/User.ts new file mode 100644 index 0000000..dc7008b --- /dev/null +++ b/src/models/User.ts @@ -0,0 +1,90 @@ +import * as bcrypt from "bcrypt-nodejs"; +import * as crypto from "crypto"; +import * as mongoose from "mongoose"; + +export type UserModel = mongoose.Document & { + email: string, + password: string, + passwordResetToken: string, + passwordResetExpires: Date, + + facebook: string, + tokens: AuthToken[], + + profile: { + name: string, + gender: string, + location: string, + website: string, + picture: string + }, + + comparePassword: (candidatePassword: string, cb: (err: any, isMatch: any) => {}) => void, + gravatar: (size: number) => string +}; + +export type AuthToken = { + accessToken: string, + kind: string +}; + +const userSchema = new mongoose.Schema({ + email: { type: String, unique: true }, + password: String, + passwordResetToken: String, + passwordResetExpires: Date, + + facebook: String, + twitter: String, + google: String, + tokens: Array, + + profile: { + name: String, + gender: String, + location: String, + website: String, + picture: String + } +}, { timestamps: true }); + +/** + * Password hash middleware. + */ +userSchema.pre("save", function save(next) { + const user = this; + if (!user.isModified("password")) { return next(); } + bcrypt.genSalt(10, (err, salt) => { + if (err) { return next(err); } + bcrypt.hash(user.password, salt, undefined, (err: mongoose.Error, hash) => { + if (err) { return next(err); } + user.password = hash; + next(); + }); + }); +}); + +userSchema.methods.comparePassword = function(candidatePassword: string, cb: (err: any, isMatch: any) => {}) { + bcrypt.compare(candidatePassword, this.password, (err: mongoose.Error , isMatch: boolean) => { + cb(err, isMatch); + }); +}; + + +/** + * Helper method for getting user's gravatar. + */ +userSchema.methods.gravatar = function(size: number) { + if (!size) { + size = 200; + } + if (!this.email) { + return `https://gravatar.com/avatar/?s=${size}&d=retro`; + } + const md5 = crypto.createHash("md5").update(this.email).digest("hex"); + return `https://gravatar.com/avatar/${md5}?s=${size}&d=retro`; +}; + +// export const User: UserType = mongoose.model('User', userSchema); +const User = mongoose.model("User", userSchema); +export default User; \ No newline at end of file diff --git a/src/public/css/lib/bootstrap-social.scss b/src/public/css/lib/bootstrap-social.scss new file mode 100644 index 0000000..2f2f367 --- /dev/null +++ b/src/public/css/lib/bootstrap-social.scss @@ -0,0 +1,115 @@ +/* + * Social Buttons for Bootstrap + * + * Copyright 2013-2015 Panayiotis Lipiridis + * Licensed under the MIT License + * + * https://github.com/lipis/bootstrap-social + */ + +$bs-height-base: ($line-height-computed + $padding-base-vertical * 2); +$bs-height-lg: (floor($font-size-large * $line-height-base) + $padding-large-vertical * 2); +$bs-height-sm: (floor($font-size-small * 1.5) + $padding-small-vertical * 2); +$bs-height-xs: (floor($font-size-small * 1.2) + $padding-small-vertical + 1); + +.btn-social { + position: relative; + padding-left: ($bs-height-base + $padding-base-horizontal); + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + > :first-child { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: $bs-height-base; + line-height: ($bs-height-base + 2); + font-size: 1.6em; + text-align: center; + border-right: 1px solid rgba(0, 0, 0, 0.2); + } + &.btn-lg { + padding-left: ($bs-height-lg + $padding-large-horizontal); + > :first-child { + line-height: $bs-height-lg; + width: $bs-height-lg; + font-size: 1.8em; + } + } + &.btn-sm { + padding-left: ($bs-height-sm + $padding-small-horizontal); + > :first-child { + line-height: $bs-height-sm; + width: $bs-height-sm; + font-size: 1.4em; + } + } + &.btn-xs { + padding-left: ($bs-height-xs + $padding-small-horizontal); + > :first-child { + line-height: $bs-height-xs; + width: $bs-height-xs; + font-size: 1.2em; + } + } +} + +.btn-social-icon { + @extend .btn-social; + height: ($bs-height-base + 2); + width: ($bs-height-base + 2); + padding: 0; + > :first-child { + border: none; + text-align: center; + width: 100%!important; + } + &.btn-lg { + height: $bs-height-lg; + width: $bs-height-lg; + padding-left: 0; + padding-right: 0; + } + &.btn-sm { + height: ($bs-height-sm + 2); + width: ($bs-height-sm + 2); + padding-left: 0; + padding-right: 0; + } + &.btn-xs { + height: ($bs-height-xs + 2); + width: ($bs-height-xs + 2); + padding-left: 0; + padding-right: 0; + } +} + +@mixin btn-social($color-bg, $color: #fff) { + background-color: $color-bg; + @include button-variant($color, $color-bg, rgba(0,0,0,.2)); +} + + +.btn-adn { @include btn-social(#d87a68); } +.btn-bitbucket { @include btn-social(#205081); } +.btn-dropbox { @include btn-social(#1087dd); } +.btn-facebook { @include btn-social(#3b5998); } +.btn-flickr { @include btn-social(#ff0084); } +.btn-foursquare { @include btn-social(#f94877); } +.btn-github { @include btn-social(#444444); } +.btn-google { @include btn-social(#dd4b39); } +.btn-instagram { @include btn-social(#3f729b); } +.btn-linkedin { @include btn-social(#007bb6); } +.btn-microsoft { @include btn-social(#2672ec); } +.btn-odnoklassniki { @include btn-social(#f4731c); } +.btn-openid { @include btn-social(#f7931e); } +.btn-pinterest { @include btn-social(#cb2027); } +.btn-reddit { @include btn-social(#eff7ff, #000); } +.btn-soundcloud { @include btn-social(#ff5500); } +.btn-tumblr { @include btn-social(#2c4762); } +.btn-twitter { @include btn-social(#55acee); } +.btn-vimeo { @include btn-social(#1ab7ea); } +.btn-vk { @include btn-social(#587ea3); } +.btn-yahoo { @include btn-social(#720e9e); } diff --git a/src/public/css/lib/bootstrap/_alerts.scss b/src/public/css/lib/bootstrap/_alerts.scss new file mode 100644 index 0000000..7d1e1fd --- /dev/null +++ b/src/public/css/lib/bootstrap/_alerts.scss @@ -0,0 +1,73 @@ +// +// Alerts +// -------------------------------------------------- + + +// Base styles +// ------------------------- + +.alert { + padding: $alert-padding; + margin-bottom: $line-height-computed; + border: 1px solid transparent; + border-radius: $alert-border-radius; + + // Headings for larger alerts + h4 { + margin-top: 0; + // Specified for the h4 to prevent conflicts of changing $headings-color + color: inherit; + } + + // Provide class for links that match alerts + .alert-link { + font-weight: $alert-link-font-weight; + } + + // Improve alignment and spacing of inner content + > p, + > ul { + margin-bottom: 0; + } + + > p + p { + margin-top: 5px; + } +} + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissible { + padding-right: ($alert-padding + 20); + + // Adjust close link position + .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } +} + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +.alert-success { + @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text); +} + +.alert-info { + @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text); +} + +.alert-warning { + @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text); +} + +.alert-danger { + @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text); +} diff --git a/src/public/css/lib/bootstrap/_badges.scss b/src/public/css/lib/bootstrap/_badges.scss new file mode 100644 index 0000000..70002e0 --- /dev/null +++ b/src/public/css/lib/bootstrap/_badges.scss @@ -0,0 +1,68 @@ +// +// Badges +// -------------------------------------------------- + + +// Base class +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: $font-size-small; + font-weight: $badge-font-weight; + color: $badge-color; + line-height: $badge-line-height; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: $badge-bg; + border-radius: $badge-border-radius; + + // Empty badges collapse automatically (not available in IE8) + &:empty { + display: none; + } + + // Quick fix for badges in buttons + .btn & { + position: relative; + top: -1px; + } + + .btn-xs &, + .btn-group-xs > .btn & { + top: 0; + padding: 1px 5px; + } + + // [converter] extracted a& to a.badge + + // Account for badges in navs + .list-group-item.active > &, + .nav-pills > .active > a > & { + color: $badge-active-color; + background-color: $badge-active-bg; + } + + .list-group-item > & { + float: right; + } + + .list-group-item > & + & { + margin-right: 5px; + } + + .nav-pills > li > a > & { + margin-left: 3px; + } +} + +// Hover state, but only for links +a.badge { + &:hover, + &:focus { + color: $badge-link-hover-color; + text-decoration: none; + cursor: pointer; + } +} diff --git a/src/public/css/lib/bootstrap/_breadcrumbs.scss b/src/public/css/lib/bootstrap/_breadcrumbs.scss new file mode 100644 index 0000000..b61f0c7 --- /dev/null +++ b/src/public/css/lib/bootstrap/_breadcrumbs.scss @@ -0,0 +1,28 @@ +// +// Breadcrumbs +// -------------------------------------------------- + + +.breadcrumb { + padding: $breadcrumb-padding-vertical $breadcrumb-padding-horizontal; + margin-bottom: $line-height-computed; + list-style: none; + background-color: $breadcrumb-bg; + border-radius: $border-radius-base; + + > li { + display: inline-block; + + + li:before { + // [converter] Workaround for https://github.com/sass/libsass/issues/1115 + $nbsp: "\00a0"; + content: "#{$breadcrumb-separator}#{$nbsp}"; // Unicode space added since inline-block means non-collapsing white-space + padding: 0 5px; + color: $breadcrumb-color; + } + } + + > .active { + color: $breadcrumb-active-color; + } +} diff --git a/src/public/css/lib/bootstrap/_button-groups.scss b/src/public/css/lib/bootstrap/_button-groups.scss new file mode 100644 index 0000000..baaacc4 --- /dev/null +++ b/src/public/css/lib/bootstrap/_button-groups.scss @@ -0,0 +1,244 @@ +// +// Button groups +// -------------------------------------------------- + +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; // match .btn alignment given font-size hack above + > .btn { + position: relative; + float: left; + // Bring the "active" button to the front + &:hover, + &:focus, + &:active, + &.active { + z-index: 2; + } + } +} + +// Prevent double borders when buttons are next to each other +.btn-group { + .btn + .btn, + .btn + .btn-group, + .btn-group + .btn, + .btn-group + .btn-group { + margin-left: -1px; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + margin-left: -5px; // Offset the first child's margin + @include clearfix; + + .btn, + .btn-group, + .input-group { + float: left; + } + > .btn, + > .btn-group, + > .input-group { + margin-left: 5px; + } +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match +.btn-group > .btn:first-child { + margin-left: 0; + &:not(:last-child):not(.dropdown-toggle) { + @include border-right-radius(0); + } +} +// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + @include border-left-radius(0); +} + +// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + @include border-right-radius(0); + } +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-left-radius(0); +} + +// On active and open, don't show outline +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-xs > .btn { @extend .btn-xs; } +.btn-group-sm > .btn { @extend .btn-sm; } +.btn-group-lg > .btn { @extend .btn-lg; } + + +// Split button dropdowns +// ---------------------- + +// Give the line between buttons some depth +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +// The clickable button for toggling the menu +// Remove the gradient and set the same inset shadow as the :active state +.btn-group.open .dropdown-toggle { + @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + @include box-shadow(none); + } +} + + +// Reposition the caret +.btn .caret { + margin-left: 0; +} +// Carets in other button sizes +.btn-lg .caret { + border-width: $caret-width-large $caret-width-large 0; + border-bottom-width: 0; +} +// Upside down carets for .dropup +.dropup .btn-lg .caret { + border-width: 0 $caret-width-large $caret-width-large; +} + + +// Vertical button groups +// ---------------------- + +.btn-group-vertical { + > .btn, + > .btn-group, + > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; + } + + // Clear floats so dropdown menus can be properly placed + > .btn-group { + @include clearfix; + > .btn { + float: none; + } + } + + > .btn + .btn, + > .btn + .btn-group, + > .btn-group + .btn, + > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; + } +} + +.btn-group-vertical > .btn { + &:not(:first-child):not(:last-child) { + border-radius: 0; + } + &:first-child:not(:last-child) { + @include border-top-radius($btn-border-radius-base); + @include border-bottom-radius(0); + } + &:last-child:not(:first-child) { + @include border-top-radius(0); + @include border-bottom-radius($btn-border-radius-base); + } +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + @include border-bottom-radius(0); + } +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-top-radius(0); +} + + +// Justified button groups +// ---------------------- + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; + > .btn, + > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + > .btn-group .btn { + width: 100%; + } + + > .btn-group .dropdown-menu { + left: auto; + } +} + + +// Checkbox and radio options +// +// In order to support the browser's form validation feedback, powered by the +// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use +// `display: none;` or `visibility: hidden;` as that also hides the popover. +// Simply visually hiding the inputs via `opacity` would leave them clickable in +// certain cases which is prevented by using `clip` and `pointer-events`. +// This way, we ensure a DOM element is visible to position the popover from. +// +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. + +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } +} diff --git a/src/public/css/lib/bootstrap/_buttons.scss b/src/public/css/lib/bootstrap/_buttons.scss new file mode 100644 index 0000000..6452b70 --- /dev/null +++ b/src/public/css/lib/bootstrap/_buttons.scss @@ -0,0 +1,168 @@ +// +// Buttons +// -------------------------------------------------- + + +// Base styles +// -------------------------------------------------- + +.btn { + display: inline-block; + margin-bottom: 0; // For input.btn + font-weight: $btn-font-weight; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid transparent; + white-space: nowrap; + @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $btn-border-radius-base); + @include user-select(none); + + &, + &:active, + &.active { + &:focus, + &.focus { + @include tab-focus; + } + } + + &:hover, + &:focus, + &.focus { + color: $btn-default-color; + text-decoration: none; + } + + &:active, + &.active { + outline: 0; + background-image: none; + @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + } + + &.disabled, + &[disabled], + fieldset[disabled] & { + cursor: $cursor-disabled; + @include opacity(.65); + @include box-shadow(none); + } + + // [converter] extracted a& to a.btn +} + +a.btn { + &.disabled, + fieldset[disabled] & { + pointer-events: none; // Future-proof disabling of clicks on `` elements + } +} + + +// Alternate buttons +// -------------------------------------------------- + +.btn-default { + @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border); +} +.btn-primary { + @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border); +} +// Success appears as green +.btn-success { + @include button-variant($btn-success-color, $btn-success-bg, $btn-success-border); +} +// Info appears as blue-green +.btn-info { + @include button-variant($btn-info-color, $btn-info-bg, $btn-info-border); +} +// Warning appears as orange +.btn-warning { + @include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border); +} +// Danger and error appear as red +.btn-danger { + @include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border); +} + + +// Link buttons +// ------------------------- + +// Make a button look and behave like a link +.btn-link { + color: $link-color; + font-weight: normal; + border-radius: 0; + + &, + &:active, + &.active, + &[disabled], + fieldset[disabled] & { + background-color: transparent; + @include box-shadow(none); + } + &, + &:hover, + &:focus, + &:active { + border-color: transparent; + } + &:hover, + &:focus { + color: $link-hover-color; + text-decoration: $link-hover-decoration; + background-color: transparent; + } + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus { + color: $btn-link-disabled-color; + text-decoration: none; + } + } +} + + +// Button Sizes +// -------------------------------------------------- + +.btn-lg { + // line-height: ensure even-numbered height of button next to large input + @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $btn-border-radius-large); +} +.btn-sm { + // line-height: ensure proper height of button next to small input + @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small); +} +.btn-xs { + @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small); +} + + +// Block button +// -------------------------------------------------- + +.btn-block { + display: block; + width: 100%; +} + +// Vertically space out multiple block buttons +.btn-block + .btn-block { + margin-top: 5px; +} + +// Specificity overrides +input[type="submit"], +input[type="reset"], +input[type="button"] { + &.btn-block { + width: 100%; + } +} diff --git a/src/public/css/lib/bootstrap/_carousel.scss b/src/public/css/lib/bootstrap/_carousel.scss new file mode 100644 index 0000000..753d881 --- /dev/null +++ b/src/public/css/lib/bootstrap/_carousel.scss @@ -0,0 +1,270 @@ +// +// Carousel +// -------------------------------------------------- + + +// Wrapper for the slide container and indicators +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; + + > .item { + display: none; + position: relative; + @include transition(.6s ease-in-out left); + + // Account for jankitude on images + > img, + > a > img { + @include img-responsive; + line-height: 1; + } + + // WebKit CSS3 transforms for supported devices + @media all and (transform-3d), (-webkit-transform-3d) { + @include transition-transform(0.6s ease-in-out); + @include backface-visibility(hidden); + @include perspective(1000px); + + &.next, + &.active.right { + @include translate3d(100%, 0, 0); + left: 0; + } + &.prev, + &.active.left { + @include translate3d(-100%, 0, 0); + left: 0; + } + &.next.left, + &.prev.right, + &.active { + @include translate3d(0, 0, 0); + left: 0; + } + } + } + + > .active, + > .next, + > .prev { + display: block; + } + + > .active { + left: 0; + } + + > .next, + > .prev { + position: absolute; + top: 0; + width: 100%; + } + + > .next { + left: 100%; + } + > .prev { + left: -100%; + } + > .next.left, + > .prev.right { + left: 0; + } + + > .active.left { + left: -100%; + } + > .active.right { + left: 100%; + } + +} + +// Left/right controls for nav +// --------------------------- + +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: $carousel-control-width; + @include opacity($carousel-control-opacity); + font-size: $carousel-control-font-size; + color: $carousel-control-color; + text-align: center; + text-shadow: $carousel-text-shadow; + background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug + // We can't have this transition here because WebKit cancels the carousel + // animation if you trip this while in the middle of another animation. + + // Set gradients for backgrounds + &.left { + @include gradient-horizontal($start-color: rgba(0,0,0,.5), $end-color: rgba(0,0,0,.0001)); + } + &.right { + left: auto; + right: 0; + @include gradient-horizontal($start-color: rgba(0,0,0,.0001), $end-color: rgba(0,0,0,.5)); + } + + // Hover/focus state + &:hover, + &:focus { + outline: 0; + color: $carousel-control-color; + text-decoration: none; + @include opacity(.9); + } + + // Toggles + .icon-prev, + .icon-next, + .glyphicon-chevron-left, + .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; + } + .icon-prev, + .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; + } + .icon-next, + .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; + } + .icon-prev, + .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; + } + + + .icon-prev { + &:before { + content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) + } + } + .icon-next { + &:before { + content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) + } + } +} + +// Optional indicator pips +// +// Add an unordered list with the following class and add a list item for each +// slide your carousel holds. + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; + + li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid $carousel-indicator-border-color; + border-radius: 10px; + cursor: pointer; + + // IE8-9 hack for event handling + // + // Internet Explorer 8-9 does not support clicks on elements without a set + // `background-color`. We cannot use `filter` since that's not viewed as a + // background color by the browser. Thus, a hack is needed. + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer + // + // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we + // set alpha transparency for the best results possible. + background-color: #000 \9; // IE8 + background-color: rgba(0,0,0,0); // IE9 + } + .active { + margin: 0; + width: 12px; + height: 12px; + background-color: $carousel-indicator-active-bg; + } +} + +// Optional captions +// ----------------------------- +// Hidden by default for smaller viewports +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: $carousel-caption-color; + text-align: center; + text-shadow: $carousel-text-shadow; + & .btn { + text-shadow: none; // No shadow for button elements in carousel-caption + } +} + + +// Scale up controls for tablets and up +@media screen and (min-width: $screen-sm-min) { + + // Scale up the controls a smidge + .carousel-control { + .glyphicon-chevron-left, + .glyphicon-chevron-right, + .icon-prev, + .icon-next { + width: ($carousel-control-font-size * 1.5); + height: ($carousel-control-font-size * 1.5); + margin-top: ($carousel-control-font-size / -2); + font-size: ($carousel-control-font-size * 1.5); + } + .glyphicon-chevron-left, + .icon-prev { + margin-left: ($carousel-control-font-size / -2); + } + .glyphicon-chevron-right, + .icon-next { + margin-right: ($carousel-control-font-size / -2); + } + } + + // Show and left align the captions + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + // Move up the indicators + .carousel-indicators { + bottom: 20px; + } +} diff --git a/src/public/css/lib/bootstrap/_close.scss b/src/public/css/lib/bootstrap/_close.scss new file mode 100644 index 0000000..3b74d8a --- /dev/null +++ b/src/public/css/lib/bootstrap/_close.scss @@ -0,0 +1,36 @@ +// +// Close icons +// -------------------------------------------------- + + +.close { + float: right; + font-size: ($font-size-base * 1.5); + font-weight: $close-font-weight; + line-height: 1; + color: $close-color; + text-shadow: $close-text-shadow; + @include opacity(.2); + + &:hover, + &:focus { + color: $close-color; + text-decoration: none; + cursor: pointer; + @include opacity(.5); + } + + // [converter] extracted button& to button.close +} + +// Additional properties for button version +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} diff --git a/src/public/css/lib/bootstrap/_code.scss b/src/public/css/lib/bootstrap/_code.scss new file mode 100644 index 0000000..caa5f06 --- /dev/null +++ b/src/public/css/lib/bootstrap/_code.scss @@ -0,0 +1,69 @@ +// +// Code (inline and block) +// -------------------------------------------------- + + +// Inline and block code styles +code, +kbd, +pre, +samp { + font-family: $font-family-monospace; +} + +// Inline code +code { + padding: 2px 4px; + font-size: 90%; + color: $code-color; + background-color: $code-bg; + border-radius: $border-radius-base; +} + +// User input typically entered via keyboard +kbd { + padding: 2px 4px; + font-size: 90%; + color: $kbd-color; + background-color: $kbd-bg; + border-radius: $border-radius-small; + box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + + kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; + } +} + +// Blocks of code +pre { + display: block; + padding: (($line-height-computed - 1) / 2); + margin: 0 0 ($line-height-computed / 2); + font-size: ($font-size-base - 1); // 14px to 13px + line-height: $line-height-base; + word-break: break-all; + word-wrap: break-word; + color: $pre-color; + background-color: $pre-bg; + border: 1px solid $pre-border-color; + border-radius: $border-radius-base; + + // Account for some code outputs that place code tags in pre tags + code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } +} + +// Enable scrollable blocks of code +.pre-scrollable { + max-height: $pre-scrollable-max-height; + overflow-y: scroll; +} diff --git a/src/public/css/lib/bootstrap/_component-animations.scss b/src/public/css/lib/bootstrap/_component-animations.scss new file mode 100644 index 0000000..ca3b43c --- /dev/null +++ b/src/public/css/lib/bootstrap/_component-animations.scss @@ -0,0 +1,37 @@ +// +// Component animations +// -------------------------------------------------- + +// Heads up! +// +// We don't use the `.opacity()` mixin here since it causes a bug with text +// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. + +.fade { + opacity: 0; + @include transition(opacity .15s linear); + &.in { + opacity: 1; + } +} + +.collapse { + display: none; + + &.in { display: block; } + // [converter] extracted tr&.in to tr.collapse.in + // [converter] extracted tbody&.in to tbody.collapse.in +} + +tr.collapse.in { display: table-row; } + +tbody.collapse.in { display: table-row-group; } + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + @include transition-property(height, visibility); + @include transition-duration(.35s); + @include transition-timing-function(ease); +} diff --git a/src/public/css/lib/bootstrap/_dropdowns.scss b/src/public/css/lib/bootstrap/_dropdowns.scss new file mode 100644 index 0000000..aac8459 --- /dev/null +++ b/src/public/css/lib/bootstrap/_dropdowns.scss @@ -0,0 +1,216 @@ +// +// Dropdown menus +// -------------------------------------------------- + + +// Dropdown arrow/caret +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: $caret-width-base dashed; + border-top: $caret-width-base solid \9; // IE8 + border-right: $caret-width-base solid transparent; + border-left: $caret-width-base solid transparent; +} + +// The dropdown wrapper (div) +.dropup, +.dropdown { + position: relative; +} + +// Prevent the focus on the dropdown toggle when closing dropdowns +.dropdown-toggle:focus { + outline: 0; +} + +// The dropdown menu (ul) +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: $zindex-dropdown; + display: none; // none by default, but block on "open" of the menu + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; // override default ul + list-style: none; + font-size: $font-size-base; + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + background-color: $dropdown-bg; + border: 1px solid $dropdown-fallback-border; // IE8 fallback + border: 1px solid $dropdown-border; + border-radius: $border-radius-base; + @include box-shadow(0 6px 12px rgba(0,0,0,.175)); + background-clip: padding-box; + + // Aligns the dropdown menu to right + // + // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` + &.pull-right { + right: 0; + left: auto; + } + + // Dividers (basically an hr) within the dropdown + .divider { + @include nav-divider($dropdown-divider-bg); + } + + // Links within the dropdown menu + > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: $line-height-base; + color: $dropdown-link-color; + white-space: nowrap; // prevent links from randomly breaking onto new lines + } +} + +// Hover/Focus state +.dropdown-menu > li > a { + &:hover, + &:focus { + text-decoration: none; + color: $dropdown-link-hover-color; + background-color: $dropdown-link-hover-bg; + } +} + +// Active state +.dropdown-menu > .active > a { + &, + &:hover, + &:focus { + color: $dropdown-link-active-color; + text-decoration: none; + outline: 0; + background-color: $dropdown-link-active-bg; + } +} + +// Disabled state +// +// Gray out text and ensure the hover/focus state remains gray + +.dropdown-menu > .disabled > a { + &, + &:hover, + &:focus { + color: $dropdown-link-disabled-color; + } + + // Nuke hover/focus effects + &:hover, + &:focus { + text-decoration: none; + background-color: transparent; + background-image: none; // Remove CSS gradient + @include reset-filter; + cursor: $cursor-disabled; + } +} + +// Open state for the dropdown +.open { + // Show the menu + > .dropdown-menu { + display: block; + } + + // Remove the outline when :focus is triggered + > a { + outline: 0; + } +} + +// Menu positioning +// +// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown +// menu with the parent. +.dropdown-menu-right { + left: auto; // Reset the default from `.dropdown-menu` + right: 0; +} +// With v3, we enabled auto-flipping if you have a dropdown within a right +// aligned nav component. To enable the undoing of that, we provide an override +// to restore the default dropdown menu alignment. +// +// This is only for left-aligning a dropdown menu within a `.navbar-right` or +// `.pull-right` nav component. +.dropdown-menu-left { + left: 0; + right: auto; +} + +// Dropdown section headers +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: $font-size-small; + line-height: $line-height-base; + color: $dropdown-header-color; + white-space: nowrap; // as with > li > a +} + +// Backdrop to catch body clicks on mobile, etc. +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: ($zindex-dropdown - 10); +} + +// Right aligned dropdowns +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// +// Just add .dropup after the standard .dropdown class and you're set, bro. +// TODO: abstract this so that the navbar fixed styles are not placed here? + +.dropup, +.navbar-fixed-bottom .dropdown { + // Reverse the caret + .caret { + border-top: 0; + border-bottom: $caret-width-base dashed; + border-bottom: $caret-width-base solid \9; // IE8 + content: ""; + } + // Different positioning for bottom up menu + .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; + } +} + + +// Component alignment +// +// Reiterate per navbar.less and the modified component alignment there. + +@media (min-width: $grid-float-breakpoint) { + .navbar-right { + .dropdown-menu { + right: 0; left: auto; + } + // Necessary for overrides of the default right aligned menu. + // Will remove come v4 in all likelihood. + .dropdown-menu-left { + left: 0; right: auto; + } + } +} diff --git a/src/public/css/lib/bootstrap/_forms.scss b/src/public/css/lib/bootstrap/_forms.scss new file mode 100644 index 0000000..11ba109 --- /dev/null +++ b/src/public/css/lib/bootstrap/_forms.scss @@ -0,0 +1,617 @@ +// +// Forms +// -------------------------------------------------- + + +// Normalize non-controls +// +// Restyle and baseline non-control form elements. + +fieldset { + padding: 0; + margin: 0; + border: 0; + // Chrome and Firefox set a `min-width: min-content;` on fieldsets, + // so we reset that to ensure it behaves more like a standard block element. + // See https://github.com/twbs/bootstrap/issues/12359. + min-width: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: $line-height-computed; + font-size: ($font-size-base * 1.5); + line-height: inherit; + color: $legend-color; + border: 0; + border-bottom: 1px solid $legend-border-color; +} + +label { + display: inline-block; + max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) + margin-bottom: 5px; + font-weight: bold; +} + + +// Normalize form controls +// +// While most of our form styles require extra classes, some basic normalization +// is required to ensure optimum display with or without those classes to better +// address browser inconsistencies. + +// Override content-box in Normalize (* isn't specific enough) +input[type="search"] { + @include box-sizing(border-box); +} + +// Position radios and checkboxes better +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; // IE8-9 + line-height: normal; +} + +input[type="file"] { + display: block; +} + +// Make range inputs behave like textual form controls +input[type="range"] { + display: block; + width: 100%; +} + +// Make multiple select elements height not fixed +select[multiple], +select[size] { + height: auto; +} + +// Focus for file, radio, and checkbox +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + @include tab-focus; +} + +// Adjust output element +output { + display: block; + padding-top: ($padding-base-vertical + 1); + font-size: $font-size-base; + line-height: $line-height-base; + color: $input-color; +} + + +// Common form controls +// +// Shared size and type resets for form controls. Apply `.form-control` to any +// of the following form controls: +// +// select +// textarea +// input[type="text"] +// input[type="password"] +// input[type="datetime"] +// input[type="datetime-local"] +// input[type="date"] +// input[type="month"] +// input[type="time"] +// input[type="week"] +// input[type="number"] +// input[type="email"] +// input[type="url"] +// input[type="search"] +// input[type="tel"] +// input[type="color"] + +.form-control { + display: block; + width: 100%; + height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) + padding: $padding-base-vertical $padding-base-horizontal; + font-size: $font-size-base; + line-height: $line-height-base; + color: $input-color; + background-color: $input-bg; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid $input-border; + border-radius: $input-border-radius; // Note: This has no effect on s in CSS. + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); + + // Customize the `:focus` state to imitate native WebKit styles. + @include form-control-focus; + + // Placeholder + @include placeholder; + + // Unstyle the caret on `` background color +$input-bg: #fff !default; +//** `` background color +$input-bg-disabled: $gray-lighter !default; + +//** Text color for ``s +$input-color: $gray !default; +//** `` border color +$input-border: #ccc !default; + +// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on ``s in CSS. +$input-border-radius: $border-radius-base !default; +//** Large `.form-control` border radius +$input-border-radius-large: $border-radius-large !default; +//** Small `.form-control` border radius +$input-border-radius-small: $border-radius-small !default; + +//** Border color for inputs on focus +$input-border-focus: #66afe9 !default; + +//** Placeholder text color +$input-color-placeholder: #999 !default; + +//** Default `.form-control` height +$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default; +//** Large `.form-control` height +$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default; +//** Small `.form-control` height +$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default; + +//** `.form-group` margin +$form-group-margin-bottom: 15px !default; + +$legend-color: $gray-dark !default; +$legend-border-color: #e5e5e5 !default; + +//** Background color for textual input addons +$input-group-addon-bg: $gray-lighter !default; +//** Border color for textual input addons +$input-group-addon-border-color: $input-border !default; + +//** Disabled cursor for form controls and buttons. +$cursor-disabled: not-allowed !default; + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +$dropdown-bg: #fff !default; +//** Dropdown menu `border-color`. +$dropdown-border: rgba(0,0,0,.15) !default; +//** Dropdown menu `border-color` **for IE8**. +$dropdown-fallback-border: #ccc !default; +//** Divider color for between dropdown items. +$dropdown-divider-bg: #e5e5e5 !default; + +//** Dropdown link text color. +$dropdown-link-color: $gray-dark !default; +//** Hover color for dropdown links. +$dropdown-link-hover-color: darken($gray-dark, 5%) !default; +//** Hover background for dropdown links. +$dropdown-link-hover-bg: #f5f5f5 !default; + +//** Active dropdown menu item text color. +$dropdown-link-active-color: $component-active-color !default; +//** Active dropdown menu item background color. +$dropdown-link-active-bg: $component-active-bg !default; + +//** Disabled dropdown menu item background color. +$dropdown-link-disabled-color: $gray-light !default; + +//** Text color for headers within dropdown menus. +$dropdown-header-color: $gray-light !default; + +//** Deprecated `$dropdown-caret-color` as of v3.1.0 +$dropdown-caret-color: #000 !default; + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +$zindex-navbar: 1000 !default; +$zindex-dropdown: 1000 !default; +$zindex-popover: 1060 !default; +$zindex-tooltip: 1070 !default; +$zindex-navbar-fixed: 1030 !default; +$zindex-modal-background: 1040 !default; +$zindex-modal: 1050 !default; + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +//** Deprecated `$screen-xs` as of v3.0.1 +$screen-xs: 480px !default; +//** Deprecated `$screen-xs-min` as of v3.2.0 +$screen-xs-min: $screen-xs !default; +//** Deprecated `$screen-phone` as of v3.0.1 +$screen-phone: $screen-xs-min !default; + +// Small screen / tablet +//** Deprecated `$screen-sm` as of v3.0.1 +$screen-sm: 768px !default; +$screen-sm-min: $screen-sm !default; +//** Deprecated `$screen-tablet` as of v3.0.1 +$screen-tablet: $screen-sm-min !default; + +// Medium screen / desktop +//** Deprecated `$screen-md` as of v3.0.1 +$screen-md: 992px !default; +$screen-md-min: $screen-md !default; +//** Deprecated `$screen-desktop` as of v3.0.1 +$screen-desktop: $screen-md-min !default; + +// Large screen / wide desktop +//** Deprecated `$screen-lg` as of v3.0.1 +$screen-lg: 1200px !default; +$screen-lg-min: $screen-lg !default; +//** Deprecated `$screen-lg-desktop` as of v3.0.1 +$screen-lg-desktop: $screen-lg-min !default; + +// So media queries don't overlap when required, provide a maximum +$screen-xs-max: ($screen-sm-min - 1) !default; +$screen-sm-max: ($screen-md-min - 1) !default; +$screen-md-max: ($screen-lg-min - 1) !default; + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +$grid-columns: 12 !default; +//** Padding between columns. Gets divided in half for the left and right. +$grid-gutter-width: 30px !default; +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +$grid-float-breakpoint: $screen-sm-min !default; +//** Point at which the navbar begins collapsing. +$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default; + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +$container-tablet: (720px + $grid-gutter-width) !default; +//** For `$screen-sm-min` and up. +$container-sm: $container-tablet !default; + +// Medium screen / desktop +$container-desktop: (940px + $grid-gutter-width) !default; +//** For `$screen-md-min` and up. +$container-md: $container-desktop !default; + +// Large screen / wide desktop +$container-large-desktop: (1140px + $grid-gutter-width) !default; +//** For `$screen-lg-min` and up. +$container-lg: $container-large-desktop !default; + + +//== Navbar +// +//## + +// Basics of a navbar +$navbar-height: 50px !default; +$navbar-margin-bottom: $line-height-computed !default; +$navbar-border-radius: $border-radius-base !default; +$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; +$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default; +$navbar-collapse-max-height: 340px !default; + +$navbar-default-color: #777 !default; +$navbar-default-bg: #f8f8f8 !default; +$navbar-default-border: darken($navbar-default-bg, 6.5%) !default; + +// Navbar links +$navbar-default-link-color: #777 !default; +$navbar-default-link-hover-color: #333 !default; +$navbar-default-link-hover-bg: transparent !default; +$navbar-default-link-active-color: #555 !default; +$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%) !default; +$navbar-default-link-disabled-color: #ccc !default; +$navbar-default-link-disabled-bg: transparent !default; + +// Navbar brand label +$navbar-default-brand-color: $navbar-default-link-color !default; +$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%) !default; +$navbar-default-brand-hover-bg: transparent !default; + +// Navbar toggle +$navbar-default-toggle-hover-bg: #ddd !default; +$navbar-default-toggle-icon-bar-bg: #888 !default; +$navbar-default-toggle-border-color: #ddd !default; + + +//=== Inverted navbar +// Reset inverted navbar basics +$navbar-inverse-color: lighten($gray-light, 15%) !default; +$navbar-inverse-bg: #222 !default; +$navbar-inverse-border: darken($navbar-inverse-bg, 10%) !default; + +// Inverted navbar links +$navbar-inverse-link-color: lighten($gray-light, 15%) !default; +$navbar-inverse-link-hover-color: #fff !default; +$navbar-inverse-link-hover-bg: transparent !default; +$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color !default; +$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%) !default; +$navbar-inverse-link-disabled-color: #444 !default; +$navbar-inverse-link-disabled-bg: transparent !default; + +// Inverted navbar brand label +$navbar-inverse-brand-color: $navbar-inverse-link-color !default; +$navbar-inverse-brand-hover-color: #fff !default; +$navbar-inverse-brand-hover-bg: transparent !default; + +// Inverted navbar toggle +$navbar-inverse-toggle-hover-bg: #333 !default; +$navbar-inverse-toggle-icon-bar-bg: #fff !default; +$navbar-inverse-toggle-border-color: #333 !default; + + +//== Navs +// +//## + +//=== Shared nav styles +$nav-link-padding: 10px 15px !default; +$nav-link-hover-bg: $gray-lighter !default; + +$nav-disabled-link-color: $gray-light !default; +$nav-disabled-link-hover-color: $gray-light !default; + +//== Tabs +$nav-tabs-border-color: #ddd !default; + +$nav-tabs-link-hover-border-color: $gray-lighter !default; + +$nav-tabs-active-link-hover-bg: $body-bg !default; +$nav-tabs-active-link-hover-color: $gray !default; +$nav-tabs-active-link-hover-border-color: #ddd !default; + +$nav-tabs-justified-link-border-color: #ddd !default; +$nav-tabs-justified-active-link-border-color: $body-bg !default; + +//== Pills +$nav-pills-border-radius: $border-radius-base !default; +$nav-pills-active-link-hover-bg: $component-active-bg !default; +$nav-pills-active-link-hover-color: $component-active-color !default; + + +//== Pagination +// +//## + +$pagination-color: $link-color !default; +$pagination-bg: #fff !default; +$pagination-border: #ddd !default; + +$pagination-hover-color: $link-hover-color !default; +$pagination-hover-bg: $gray-lighter !default; +$pagination-hover-border: #ddd !default; + +$pagination-active-color: #fff !default; +$pagination-active-bg: $brand-primary !default; +$pagination-active-border: $brand-primary !default; + +$pagination-disabled-color: $gray-light !default; +$pagination-disabled-bg: #fff !default; +$pagination-disabled-border: #ddd !default; + + +//== Pager +// +//## + +$pager-bg: $pagination-bg !default; +$pager-border: $pagination-border !default; +$pager-border-radius: 15px !default; + +$pager-hover-bg: $pagination-hover-bg !default; + +$pager-active-bg: $pagination-active-bg !default; +$pager-active-color: $pagination-active-color !default; + +$pager-disabled-color: $pagination-disabled-color !default; + + +//== Jumbotron +// +//## + +$jumbotron-padding: 30px !default; +$jumbotron-color: inherit !default; +$jumbotron-bg: $gray-lighter !default; +$jumbotron-heading-color: inherit !default; +$jumbotron-font-size: ceil(($font-size-base * 1.5)) !default; +$jumbotron-heading-font-size: ceil(($font-size-base * 4.5)) !default; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #3c763d !default; +$state-success-bg: #dff0d8 !default; +$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) !default; + +$state-info-text: #31708f !default; +$state-info-bg: #d9edf7 !default; +$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) !default; + +$state-warning-text: #8a6d3b !default; +$state-warning-bg: #fcf8e3 !default; +$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) !default; + +$state-danger-text: #a94442 !default; +$state-danger-bg: #f2dede !default; +$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) !default; + + +//== Tooltips +// +//## + +//** Tooltip max width +$tooltip-max-width: 200px !default; +//** Tooltip text color +$tooltip-color: #fff !default; +//** Tooltip background color +$tooltip-bg: #000 !default; +$tooltip-opacity: .9 !default; + +//** Tooltip arrow width +$tooltip-arrow-width: 5px !default; +//** Tooltip arrow color +$tooltip-arrow-color: $tooltip-bg !default; + + +//== Popovers +// +//## + +//** Popover body background color +$popover-bg: #fff !default; +//** Popover maximum width +$popover-max-width: 276px !default; +//** Popover border color +$popover-border-color: rgba(0,0,0,.2) !default; +//** Popover fallback border color +$popover-fallback-border-color: #ccc !default; + +//** Popover title background color +$popover-title-bg: darken($popover-bg, 3%) !default; + +//** Popover arrow width +$popover-arrow-width: 10px !default; +//** Popover arrow color +$popover-arrow-color: $popover-bg !default; + +//** Popover outer arrow width +$popover-arrow-outer-width: ($popover-arrow-width + 1) !default; +//** Popover outer arrow color +$popover-arrow-outer-color: fade_in($popover-border-color, 0.05) !default; +//** Popover outer arrow fallback color +$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default; + + +//== Labels +// +//## + +//** Default label background color +$label-default-bg: $gray-light !default; +//** Primary label background color +$label-primary-bg: $brand-primary !default; +//** Success label background color +$label-success-bg: $brand-success !default; +//** Info label background color +$label-info-bg: $brand-info !default; +//** Warning label background color +$label-warning-bg: $brand-warning !default; +//** Danger label background color +$label-danger-bg: $brand-danger !default; + +//** Default label text color +$label-color: #fff !default; +//** Default text color of a linked label +$label-link-hover-color: #fff !default; + + +//== Modals +// +//## + +//** Padding applied to the modal body +$modal-inner-padding: 15px !default; + +//** Padding applied to the modal title +$modal-title-padding: 15px !default; +//** Modal title line-height +$modal-title-line-height: $line-height-base !default; + +//** Background color of modal content area +$modal-content-bg: #fff !default; +//** Modal content border color +$modal-content-border-color: rgba(0,0,0,.2) !default; +//** Modal content border color **for IE8** +$modal-content-fallback-border-color: #999 !default; + +//** Modal backdrop background color +$modal-backdrop-bg: #000 !default; +//** Modal backdrop opacity +$modal-backdrop-opacity: .5 !default; +//** Modal header border color +$modal-header-border-color: #e5e5e5 !default; +//** Modal footer border color +$modal-footer-border-color: $modal-header-border-color !default; + +$modal-lg: 900px !default; +$modal-md: 600px !default; +$modal-sm: 300px !default; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-padding: 15px !default; +$alert-border-radius: $border-radius-base !default; +$alert-link-font-weight: bold !default; + +$alert-success-bg: $state-success-bg !default; +$alert-success-text: $state-success-text !default; +$alert-success-border: $state-success-border !default; + +$alert-info-bg: $state-info-bg !default; +$alert-info-text: $state-info-text !default; +$alert-info-border: $state-info-border !default; + +$alert-warning-bg: $state-warning-bg !default; +$alert-warning-text: $state-warning-text !default; +$alert-warning-border: $state-warning-border !default; + +$alert-danger-bg: $state-danger-bg !default; +$alert-danger-text: $state-danger-text !default; +$alert-danger-border: $state-danger-border !default; + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +$progress-bg: #f5f5f5 !default; +//** Progress bar text color +$progress-bar-color: #fff !default; +//** Variable for setting rounded corners on progress bar. +$progress-border-radius: $border-radius-base !default; + +//** Default progress bar color +$progress-bar-bg: $brand-primary !default; +//** Success progress bar color +$progress-bar-success-bg: $brand-success !default; +//** Warning progress bar color +$progress-bar-warning-bg: $brand-warning !default; +//** Danger progress bar color +$progress-bar-danger-bg: $brand-danger !default; +//** Info progress bar color +$progress-bar-info-bg: $brand-info !default; + + +//== List group +// +//## + +//** Background color on `.list-group-item` +$list-group-bg: #fff !default; +//** `.list-group-item` border color +$list-group-border: #ddd !default; +//** List group border radius +$list-group-border-radius: $border-radius-base !default; + +//** Background color of single list items on hover +$list-group-hover-bg: #f5f5f5 !default; +//** Text color of active list items +$list-group-active-color: $component-active-color !default; +//** Background color of active list items +$list-group-active-bg: $component-active-bg !default; +//** Border color of active list elements +$list-group-active-border: $list-group-active-bg !default; +//** Text color for content within active list items +$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; + +//** Text color of disabled list items +$list-group-disabled-color: $gray-light !default; +//** Background color of disabled list items +$list-group-disabled-bg: $gray-lighter !default; +//** Text color for content within disabled list items +$list-group-disabled-text-color: $list-group-disabled-color !default; + +$list-group-link-color: #555 !default; +$list-group-link-hover-color: $list-group-link-color !default; +$list-group-link-heading-color: #333 !default; + + +//== Panels +// +//## + +$panel-bg: #fff !default; +$panel-body-padding: 15px !default; +$panel-heading-padding: 10px 15px !default; +$panel-footer-padding: $panel-heading-padding !default; +$panel-border-radius: $border-radius-base !default; + +//** Border color for elements within panels +$panel-inner-border: #ddd !default; +$panel-footer-bg: #f5f5f5 !default; + +$panel-default-text: $gray-dark !default; +$panel-default-border: #ddd !default; +$panel-default-heading-bg: #f5f5f5 !default; + +$panel-primary-text: #fff !default; +$panel-primary-border: $brand-primary !default; +$panel-primary-heading-bg: $brand-primary !default; + +$panel-success-text: $state-success-text !default; +$panel-success-border: $state-success-border !default; +$panel-success-heading-bg: $state-success-bg !default; + +$panel-info-text: $state-info-text !default; +$panel-info-border: $state-info-border !default; +$panel-info-heading-bg: $state-info-bg !default; + +$panel-warning-text: $state-warning-text !default; +$panel-warning-border: $state-warning-border !default; +$panel-warning-heading-bg: $state-warning-bg !default; + +$panel-danger-text: $state-danger-text !default; +$panel-danger-border: $state-danger-border !default; +$panel-danger-heading-bg: $state-danger-bg !default; + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +$thumbnail-padding: 4px !default; +//** Thumbnail background color +$thumbnail-bg: $body-bg !default; +//** Thumbnail border color +$thumbnail-border: #ddd !default; +//** Thumbnail border radius +$thumbnail-border-radius: $border-radius-base !default; + +//** Custom text color for thumbnail captions +$thumbnail-caption-color: $text-color !default; +//** Padding around the thumbnail caption +$thumbnail-caption-padding: 9px !default; + + +//== Wells +// +//## + +$well-bg: #f5f5f5 !default; +$well-border: darken($well-bg, 7%) !default; + + +//== Badges +// +//## + +$badge-color: #fff !default; +//** Linked badge text color on hover +$badge-link-hover-color: #fff !default; +$badge-bg: $gray-light !default; + +//** Badge text color in active nav link +$badge-active-color: $link-color !default; +//** Badge background color in active nav link +$badge-active-bg: #fff !default; + +$badge-font-weight: bold !default; +$badge-line-height: 1 !default; +$badge-border-radius: 10px !default; + + +//== Breadcrumbs +// +//## + +$breadcrumb-padding-vertical: 8px !default; +$breadcrumb-padding-horizontal: 15px !default; +//** Breadcrumb background color +$breadcrumb-bg: #f5f5f5 !default; +//** Breadcrumb text color +$breadcrumb-color: #ccc !default; +//** Text color of current page in the breadcrumb +$breadcrumb-active-color: $gray-light !default; +//** Textual separator for between breadcrumb elements +$breadcrumb-separator: "/" !default; + + +//== Carousel +// +//## + +$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; + +$carousel-control-color: #fff !default; +$carousel-control-width: 15% !default; +$carousel-control-opacity: .5 !default; +$carousel-control-font-size: 20px !default; + +$carousel-indicator-active-bg: #fff !default; +$carousel-indicator-border-color: #fff !default; + +$carousel-caption-color: #fff !default; + + +//== Close +// +//## + +$close-font-weight: bold !default; +$close-color: #000 !default; +$close-text-shadow: 0 1px 0 #fff !default; + + +//== Code +// +//## + +$code-color: #c7254e !default; +$code-bg: #f9f2f4 !default; + +$kbd-color: #fff !default; +$kbd-bg: #333 !default; + +$pre-bg: #f5f5f5 !default; +$pre-color: $gray-dark !default; +$pre-border-color: #ccc !default; +$pre-scrollable-max-height: 340px !default; + + +//== Type +// +//## + +//** Horizontal offset for forms and lists. +$component-offset-horizontal: 180px !default; +//** Text muted color +$text-muted: $gray-light !default; +//** Abbreviations and acronyms border color +$abbr-border-color: $gray-light !default; +//** Headings small color +$headings-small-color: $gray-light !default; +//** Blockquote small color +$blockquote-small-color: $gray-light !default; +//** Blockquote font size +$blockquote-font-size: ($font-size-base * 1.25) !default; +//** Blockquote border color +$blockquote-border-color: $gray-lighter !default; +//** Page header border color +$page-header-border-color: $gray-lighter !default; +//** Width of horizontal description list titles +$dl-horizontal-offset: $component-offset-horizontal !default; +//** Point at which .dl-horizontal becomes horizontal +$dl-horizontal-breakpoint: $grid-float-breakpoint !default; +//** Horizontal line color. +$hr-border: $gray-lighter !default; diff --git a/src/public/css/lib/bootstrap/_wells.scss b/src/public/css/lib/bootstrap/_wells.scss new file mode 100644 index 0000000..b865711 --- /dev/null +++ b/src/public/css/lib/bootstrap/_wells.scss @@ -0,0 +1,29 @@ +// +// Wells +// -------------------------------------------------- + + +// Base class +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: $well-bg; + border: 1px solid $well-border; + border-radius: $border-radius-base; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); + blockquote { + border-color: #ddd; + border-color: rgba(0,0,0,.15); + } +} + +// Sizes +.well-lg { + padding: 24px; + border-radius: $border-radius-large; +} +.well-sm { + padding: 9px; + border-radius: $border-radius-small; +} diff --git a/src/public/css/lib/bootstrap/bootstrap.scss b/src/public/css/lib/bootstrap/bootstrap.scss new file mode 100644 index 0000000..2195ff2 --- /dev/null +++ b/src/public/css/lib/bootstrap/bootstrap.scss @@ -0,0 +1,56 @@ +/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/blob/master/LICENSE) + */ + +// Core variables and mixins +@import "variables"; +@import "mixins"; + +// Reset and dependencies +@import "normalize"; +@import "print"; +@import "glyphicons"; + +// Core CSS +@import "scaffolding"; +@import "type"; +@import "code"; +@import "grid"; +@import "tables"; +@import "forms"; +@import "buttons"; + +// Components +@import "component-animations"; +@import "dropdowns"; +@import "button-groups"; +@import "input-groups"; +@import "navs"; +@import "navbar"; +@import "breadcrumbs"; +@import "pagination"; +@import "pager"; +@import "labels"; +@import "badges"; +@import "jumbotron"; +@import "thumbnails"; +@import "alerts"; +@import "progress-bars"; +@import "media"; +@import "list-group"; +@import "panels"; +@import "responsive-embed"; +@import "wells"; +@import "close"; + +// Components w/ JavaScript +@import "modals"; +@import "tooltip"; +@import "popovers"; +@import "carousel"; + +// Utility classes +@import "utilities"; +@import "responsive-utilities"; diff --git a/src/public/css/lib/bootstrap/mixins/_alerts.scss b/src/public/css/lib/bootstrap/mixins/_alerts.scss new file mode 100644 index 0000000..3faf0b5 --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_alerts.scss @@ -0,0 +1,14 @@ +// Alerts + +@mixin alert-variant($background, $border, $text-color) { + background-color: $background; + border-color: $border; + color: $text-color; + + hr { + border-top-color: darken($border, 5%); + } + .alert-link { + color: darken($text-color, 10%); + } +} diff --git a/src/public/css/lib/bootstrap/mixins/_background-variant.scss b/src/public/css/lib/bootstrap/mixins/_background-variant.scss new file mode 100644 index 0000000..4c7769e --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_background-variant.scss @@ -0,0 +1,12 @@ +// Contextual backgrounds + +// [converter] $parent hack +@mixin bg-variant($parent, $color) { + #{$parent} { + background-color: $color; + } + a#{$parent}:hover, + a#{$parent}:focus { + background-color: darken($color, 10%); + } +} diff --git a/src/public/css/lib/bootstrap/mixins/_border-radius.scss b/src/public/css/lib/bootstrap/mixins/_border-radius.scss new file mode 100644 index 0000000..ce19499 --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_border-radius.scss @@ -0,0 +1,18 @@ +// Single side border-radius + +@mixin border-top-radius($radius) { + border-top-right-radius: $radius; + border-top-left-radius: $radius; +} +@mixin border-right-radius($radius) { + border-bottom-right-radius: $radius; + border-top-right-radius: $radius; +} +@mixin border-bottom-radius($radius) { + border-bottom-right-radius: $radius; + border-bottom-left-radius: $radius; +} +@mixin border-left-radius($radius) { + border-bottom-left-radius: $radius; + border-top-left-radius: $radius; +} diff --git a/src/public/css/lib/bootstrap/mixins/_buttons.scss b/src/public/css/lib/bootstrap/mixins/_buttons.scss new file mode 100644 index 0000000..b93f84b --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_buttons.scss @@ -0,0 +1,65 @@ +// Button variants +// +// Easily pump out default styles, as well as :hover, :focus, :active, +// and disabled options for all buttons + +@mixin button-variant($color, $background, $border) { + color: $color; + background-color: $background; + border-color: $border; + + &:focus, + &.focus { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 25%); + } + &:hover { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 12%); + } + &:active, + &.active, + .open > &.dropdown-toggle { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 12%); + + &:hover, + &:focus, + &.focus { + color: $color; + background-color: darken($background, 17%); + border-color: darken($border, 25%); + } + } + &:active, + &.active, + .open > &.dropdown-toggle { + background-image: none; + } + &.disabled, + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus, + &.focus { + background-color: $background; + border-color: $border; + } + } + + .badge { + color: $background; + background-color: $color; + } +} + +// Button sizes +@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { + padding: $padding-vertical $padding-horizontal; + font-size: $font-size; + line-height: $line-height; + border-radius: $border-radius; +} diff --git a/src/public/css/lib/bootstrap/mixins/_center-block.scss b/src/public/css/lib/bootstrap/mixins/_center-block.scss new file mode 100644 index 0000000..e06fb5e --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_center-block.scss @@ -0,0 +1,7 @@ +// Center-align a block level element + +@mixin center-block() { + display: block; + margin-left: auto; + margin-right: auto; +} diff --git a/src/public/css/lib/bootstrap/mixins/_clearfix.scss b/src/public/css/lib/bootstrap/mixins/_clearfix.scss new file mode 100644 index 0000000..dc3e2ab --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_clearfix.scss @@ -0,0 +1,22 @@ +// Clearfix +// +// For modern browsers +// 1. The space content is one way to avoid an Opera bug when the +// contenteditable attribute is included anywhere else in the document. +// Otherwise it causes space to appear at the top and bottom of elements +// that are clearfixed. +// 2. The use of `table` rather than `block` is only necessary if using +// `:before` to contain the top-margins of child elements. +// +// Source: http://nicolasgallagher.com/micro-clearfix-hack/ + +@mixin clearfix() { + &:before, + &:after { + content: " "; // 1 + display: table; // 2 + } + &:after { + clear: both; + } +} diff --git a/src/public/css/lib/bootstrap/mixins/_forms.scss b/src/public/css/lib/bootstrap/mixins/_forms.scss new file mode 100644 index 0000000..277aa5f --- /dev/null +++ b/src/public/css/lib/bootstrap/mixins/_forms.scss @@ -0,0 +1,88 @@ +// Form validation states +// +// Used in forms.less to generate the form validation CSS for warnings, errors, +// and successes. + +@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) { + // Color the label and help text + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label { + color: $text-color; + } + // Set the border and box shadow on specific inputs to match + .form-control { + border-color: $border-color; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work + &:focus { + border-color: darken($border-color, 10%); + $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); + @include box-shadow($shadow); + } + } + // Set validation states also for addons + .input-group-addon { + color: $text-color; + border-color: $border-color; + background-color: $background-color; + } + // Optional feedback icon + .form-control-feedback { + color: $text-color; + } +} + + +// Form control focus state +// +// Generate a customized focus state and for any input with the specified color, +// which defaults to the `$input-border-focus` variable. +// +// We highly encourage you to not customize the default value, but instead use +// this to tweak colors on an as-needed basis. This aesthetic change is based on +// WebKit's default styles, but applicable to a wider range of browsers. Its +// usability and accessibility should be taken into account with any change. +// +// Example usage: change the default blue border and shadow to white for better +// contrast against a dark gray background. +@mixin form-control-focus($color: $input-border-focus) { + $color-rgba: rgba(red($color), green($color), blue($color), .6); + &:focus { + border-color: $color; + outline: 0; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); + } +} + +// Form control sizing +// +// Relative text size, padding, and border-radii changes for form controls. For +// horizontal sizing, wrap controls in the predefined grid classes. `` background color +$input-bg: #fff !default; +//** `` background color +$input-bg-disabled: $gray-lighter !default; + +//** Text color for ``s +$input-color: $text-color !default; +//** `` border color +$input-border: #dce4ec !default; + +// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on ``s in CSS. +$input-border-radius: $border-radius-base !default; +//** Large `.form-control` border radius +$input-border-radius-large: $border-radius-large !default; +//** Small `.form-control` border radius +$input-border-radius-small: $border-radius-small !default; + +//** Border color for inputs on focus +$input-border-focus: $brand-primary !default; + +//** Placeholder text color +$input-color-placeholder: #acb6c0 !default; + +//** Default `.form-control` height +$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 4) !default; +//** Large `.form-control` height +$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 4) !default; +//** Small `.form-control` height +$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 4) !default; + +//** `.form-group` margin +$form-group-margin-bottom: 15px !default; + +$legend-color: $text-color !default; +$legend-border-color: transparent !default; + +//** Background color for textual input addons +$input-group-addon-bg: $gray-lighter !default; +//** Border color for textual input addons +$input-group-addon-border-color: $input-border !default; + +//** Disabled cursor for form controls and buttons. +$cursor-disabled: not-allowed !default; + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +$dropdown-bg: #fff !default; +//** Dropdown menu `border-color`. +$dropdown-border: rgba(0,0,0,.15) !default; +//** Dropdown menu `border-color` **for IE8**. +$dropdown-fallback-border: #ccc !default; +//** Divider color for between dropdown items. +$dropdown-divider-bg: #e5e5e5 !default; + +//** Dropdown link text color. +$dropdown-link-color: $gray-dark !default; +//** Hover color for dropdown links. +$dropdown-link-hover-color: #fff !default; +//** Hover background for dropdown links. +$dropdown-link-hover-bg: $component-active-bg !default; + +//** Active dropdown menu item text color. +$dropdown-link-active-color: #fff !default; +//** Active dropdown menu item background color. +$dropdown-link-active-bg: $component-active-bg !default; + +//** Disabled dropdown menu item background color. +$dropdown-link-disabled-color: $gray-light !default; + +//** Text color for headers within dropdown menus. +$dropdown-header-color: $gray-light !default; + +//** Deprecated `$dropdown-caret-color` as of v3.1.0 +$dropdown-caret-color: #000 !default; + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +$zindex-navbar: 1000 !default; +$zindex-dropdown: 1000 !default; +$zindex-popover: 1060 !default; +$zindex-tooltip: 1070 !default; +$zindex-navbar-fixed: 1030 !default; +$zindex-modal-background: 1040 !default; +$zindex-modal: 1050 !default; + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +//** Deprecated `$screen-xs` as of v3.0.1 +$screen-xs: 480px !default; +//** Deprecated `$screen-xs-min` as of v3.2.0 +$screen-xs-min: $screen-xs !default; +//** Deprecated `$screen-phone` as of v3.0.1 +$screen-phone: $screen-xs-min !default; + +// Small screen / tablet +//** Deprecated `$screen-sm` as of v3.0.1 +$screen-sm: 768px !default; +$screen-sm-min: $screen-sm !default; +//** Deprecated `$screen-tablet` as of v3.0.1 +$screen-tablet: $screen-sm-min !default; + +// Medium screen / desktop +//** Deprecated `$screen-md` as of v3.0.1 +$screen-md: 992px !default; +$screen-md-min: $screen-md !default; +//** Deprecated `$screen-desktop` as of v3.0.1 +$screen-desktop: $screen-md-min !default; + +// Large screen / wide desktop +//** Deprecated `$screen-lg` as of v3.0.1 +$screen-lg: 1200px !default; +$screen-lg-min: $screen-lg !default; +//** Deprecated `$screen-lg-desktop` as of v3.0.1 +$screen-lg-desktop: $screen-lg-min !default; + +// So media queries don't overlap when required, provide a maximum +$screen-xs-max: ($screen-sm-min - 1) !default; +$screen-sm-max: ($screen-md-min - 1) !default; +$screen-md-max: ($screen-lg-min - 1) !default; + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +$grid-columns: 12 !default; +//** Padding between columns. Gets divided in half for the left and right. +$grid-gutter-width: 30px !default; +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +$grid-float-breakpoint: $screen-sm-min !default; +//** Point at which the navbar begins collapsing. +$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default; + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +$container-tablet: (720px + $grid-gutter-width) !default; +//** For `$screen-sm-min` and up. +$container-sm: $container-tablet !default; + +// Medium screen / desktop +$container-desktop: (940px + $grid-gutter-width) !default; +//** For `$screen-md-min` and up. +$container-md: $container-desktop !default; + +// Large screen / wide desktop +$container-large-desktop: (1140px + $grid-gutter-width) !default; +//** For `$screen-lg-min` and up. +$container-lg: $container-large-desktop !default; + + +//== Navbar +// +//## + +// Basics of a navbar +$navbar-height: 60px !default; +$navbar-margin-bottom: $line-height-computed !default; +$navbar-border-radius: $border-radius-base !default; +$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; +$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default; +$navbar-collapse-max-height: 340px !default; + +$navbar-default-color: #fff !default; +$navbar-default-bg: $brand-primary !default; +$navbar-default-border: transparent !default; + +// Navbar links +$navbar-default-link-color: #fff !default; +$navbar-default-link-hover-color: $brand-success !default; +$navbar-default-link-hover-bg: transparent !default; +$navbar-default-link-active-color: #fff !default; +$navbar-default-link-active-bg: darken($navbar-default-bg, 10%) !default; +$navbar-default-link-disabled-color: #ccc !default; +$navbar-default-link-disabled-bg: transparent !default; + +// Navbar brand label +$navbar-default-brand-color: $navbar-default-link-color !default; +$navbar-default-brand-hover-color: $navbar-default-link-hover-color !default; +$navbar-default-brand-hover-bg: transparent !default; + +// Navbar toggle +$navbar-default-toggle-hover-bg: darken($navbar-default-bg, 10%) !default; +$navbar-default-toggle-icon-bar-bg: #fff !default; +$navbar-default-toggle-border-color: darken($navbar-default-bg, 10%) !default; + + +//=== Inverted navbar +// Reset inverted navbar basics +$navbar-inverse-color: #fff !default; +$navbar-inverse-bg: $brand-success !default; +$navbar-inverse-border: transparent !default; + +// Inverted navbar links +$navbar-inverse-link-color: #fff !default; +$navbar-inverse-link-hover-color: $brand-primary !default; +$navbar-inverse-link-hover-bg: transparent !default; +$navbar-inverse-link-active-color: #fff !default; +$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 5%) !default; +$navbar-inverse-link-disabled-color: #ccc !default; +$navbar-inverse-link-disabled-bg: transparent !default; + +// Inverted navbar brand label +$navbar-inverse-brand-color: $navbar-inverse-link-color !default; +$navbar-inverse-brand-hover-color: $navbar-inverse-link-hover-color !default; +$navbar-inverse-brand-hover-bg: transparent !default; + +// Inverted navbar toggle +$navbar-inverse-toggle-hover-bg: darken($navbar-inverse-bg, 10%) !default; +$navbar-inverse-toggle-icon-bar-bg: #fff !default; +$navbar-inverse-toggle-border-color: darken($navbar-inverse-bg, 10%) !default; + + +//== Navs +// +//## + +//=== Shared nav styles +$nav-link-padding: 10px 15px !default; +$nav-link-hover-bg: $gray-lighter !default; + +$nav-disabled-link-color: $gray-light !default; +$nav-disabled-link-hover-color: $gray-light !default; + +//== Tabs +$nav-tabs-border-color: $gray-lighter !default; + +$nav-tabs-link-hover-border-color: $gray-lighter !default; + +$nav-tabs-active-link-hover-bg: $body-bg !default; +$nav-tabs-active-link-hover-color: $brand-primary !default; +$nav-tabs-active-link-hover-border-color: $gray-lighter !default; + +$nav-tabs-justified-link-border-color: $gray-lighter !default; +$nav-tabs-justified-active-link-border-color: $body-bg !default; + +//== Pills +$nav-pills-border-radius: $border-radius-base !default; +$nav-pills-active-link-hover-bg: $component-active-bg !default; +$nav-pills-active-link-hover-color: $component-active-color !default; + + +//== Pagination +// +//## + +$pagination-color: #fff !default; +$pagination-bg: $brand-success !default; +$pagination-border: transparent !default; + +$pagination-hover-color: #fff !default; +$pagination-hover-bg: darken($brand-success, 15%) !default; +$pagination-hover-border: transparent !default; + +$pagination-active-color: #fff !default; +$pagination-active-bg: darken($brand-success, 15%) !default; +$pagination-active-border: transparent !default; + +$pagination-disabled-color: $gray-lighter !default; +$pagination-disabled-bg: lighten($brand-success, 15%) !default; +$pagination-disabled-border: transparent !default; + + +//== Pager +// +//## + +$pager-bg: $pagination-bg !default; +$pager-border: $pagination-border !default; +$pager-border-radius: 15px !default; + +$pager-hover-bg: $pagination-hover-bg !default; + +$pager-active-bg: $pagination-active-bg !default; +$pager-active-color: $pagination-active-color !default; + +$pager-disabled-color: #fff !default; + + +//== Jumbotron +// +//## + +$jumbotron-padding: 30px !default; +$jumbotron-color: inherit !default; +$jumbotron-bg: $gray-lighter !default; +$jumbotron-heading-color: inherit !default; +$jumbotron-font-size: ceil(($font-size-base * 1.5)) !default; +$jumbotron-heading-font-size: ceil(($font-size-base * 4.5)) !default; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #fff !default; +$state-success-bg: $brand-success !default; +$state-success-border: $brand-success !default; + +$state-info-text: #fff !default; +$state-info-bg: $brand-info !default; +$state-info-border: $brand-info !default; + +$state-warning-text: #fff !default; +$state-warning-bg: $brand-warning !default; +$state-warning-border: $brand-warning !default; + +$state-danger-text: #fff !default; +$state-danger-bg: $brand-danger !default; +$state-danger-border: $brand-danger !default; + + +//== Tooltips +// +//## + +//** Tooltip max width +$tooltip-max-width: 200px !default; +//** Tooltip text color +$tooltip-color: #fff !default; +//** Tooltip background color +$tooltip-bg: #000 !default; +$tooltip-opacity: .9 !default; + +//** Tooltip arrow width +$tooltip-arrow-width: 5px !default; +//** Tooltip arrow color +$tooltip-arrow-color: $tooltip-bg !default; + + +//== Popovers +// +//## + +//** Popover body background color +$popover-bg: #fff !default; +//** Popover maximum width +$popover-max-width: 276px !default; +//** Popover border color +$popover-border-color: rgba(0,0,0,.2) !default; +//** Popover fallback border color +$popover-fallback-border-color: #ccc !default; + +//** Popover title background color +$popover-title-bg: darken($popover-bg, 3%) !default; + +//** Popover arrow width +$popover-arrow-width: 10px !default; +//** Popover arrow color +$popover-arrow-color: $popover-bg !default; + +//** Popover outer arrow width +$popover-arrow-outer-width: ($popover-arrow-width + 1) !default; +//** Popover outer arrow color +$popover-arrow-outer-color: fadein($popover-border-color, 5%) !default; +//** Popover outer arrow fallback color +$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default; + + +//== Labels +// +//## + +//** Default label background color +$label-default-bg: $btn-default-bg !default; +//** Primary label background color +$label-primary-bg: $brand-primary !default; +//** Success label background color +$label-success-bg: $brand-success !default; +//** Info label background color +$label-info-bg: $brand-info !default; +//** Warning label background color +$label-warning-bg: $brand-warning !default; +//** Danger label background color +$label-danger-bg: $brand-danger !default; + +//** Default label text color +$label-color: #fff !default; +//** Default text color of a linked label +$label-link-hover-color: #fff !default; + + +//== Modals +// +//## + +//** Padding applied to the modal body +$modal-inner-padding: 20px !default; + +//** Padding applied to the modal title +$modal-title-padding: 15px !default; +//** Modal title line-height +$modal-title-line-height: $line-height-base !default; + +//** Background color of modal content area +$modal-content-bg: #fff !default; +//** Modal content border color +$modal-content-border-color: rgba(0,0,0,.2) !default; +//** Modal content border color **for IE8** +$modal-content-fallback-border-color: #999 !default; + +//** Modal backdrop background color +$modal-backdrop-bg: #000 !default; +//** Modal backdrop opacity +$modal-backdrop-opacity: .5 !default; +//** Modal header border color +$modal-header-border-color: #e5e5e5 !default; +//** Modal footer border color +$modal-footer-border-color: $modal-header-border-color !default; + +$modal-lg: 900px !default; +$modal-md: 600px !default; +$modal-sm: 300px !default; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-padding: 15px !default; +$alert-border-radius: $border-radius-base !default; +$alert-link-font-weight: bold !default; + +$alert-success-bg: $state-success-bg !default; +$alert-success-text: $state-success-text !default; +$alert-success-border: $state-success-border !default; + +$alert-info-bg: $state-info-bg !default; +$alert-info-text: $state-info-text !default; +$alert-info-border: $state-info-border !default; + +$alert-warning-bg: $state-warning-bg !default; +$alert-warning-text: $state-warning-text !default; +$alert-warning-border: $state-warning-border !default; + +$alert-danger-bg: $state-danger-bg !default; +$alert-danger-text: $state-danger-text !default; +$alert-danger-border: $state-danger-border !default; + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +$progress-bg: $gray-lighter !default; +//** Progress bar text color +$progress-bar-color: #fff !default; +//** Variable for setting rounded corners on progress bar. +$progress-border-radius: $border-radius-base !default; + +//** Default progress bar color +$progress-bar-bg: $brand-primary !default; +//** Success progress bar color +$progress-bar-success-bg: $brand-success !default; +//** Warning progress bar color +$progress-bar-warning-bg: $brand-warning !default; +//** Danger progress bar color +$progress-bar-danger-bg: $brand-danger !default; +//** Info progress bar color +$progress-bar-info-bg: $brand-info !default; + + +//== List group +// +//## + +//** Background color on `.list-group-item` +$list-group-bg: #fff !default; +//** `.list-group-item` border color +$list-group-border: $gray-lighter !default; +//** List group border radius +$list-group-border-radius: $border-radius-base !default; + +//** Background color of single list items on hover +$list-group-hover-bg: $gray-lighter !default; +//** Text color of active list items +$list-group-active-color: $component-active-color !default; +//** Background color of active list items +$list-group-active-bg: $component-active-bg !default; +//** Border color of active list elements +$list-group-active-border: $list-group-active-bg !default; +//** Text color for content within active list items +$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; + +//** Text color of disabled list items +$list-group-disabled-color: $gray-light !default; +//** Background color of disabled list items +$list-group-disabled-bg: $gray-lighter !default; +//** Text color for content within disabled list items +$list-group-disabled-text-color: $list-group-disabled-color !default; + +$list-group-link-color: #555 !default; +$list-group-link-hover-color: $list-group-link-color !default; +$list-group-link-heading-color: #333 !default; + + +//== Panels +// +//## + +$panel-bg: #fff !default; +$panel-body-padding: 15px !default; +$panel-heading-padding: 10px 15px !default; +$panel-footer-padding: $panel-heading-padding !default; +$panel-border-radius: $border-radius-base !default; + +//** Border color for elements within panels +$panel-inner-border: $gray-lighter !default; +$panel-footer-bg: $gray-lighter !default; + +$panel-default-text: $text-color !default; +$panel-default-border: $gray-lighter !default; +$panel-default-heading-bg: $gray-lighter !default; + +$panel-primary-text: #fff !default; +$panel-primary-border: $brand-primary !default; +$panel-primary-heading-bg: $brand-primary !default; + +$panel-success-text: $state-success-text !default; +$panel-success-border: $state-success-border !default; +$panel-success-heading-bg: $state-success-bg !default; + +$panel-info-text: $state-info-text !default; +$panel-info-border: $state-info-border !default; +$panel-info-heading-bg: $state-info-bg !default; + +$panel-warning-text: $state-warning-text !default; +$panel-warning-border: $state-warning-border !default; +$panel-warning-heading-bg: $state-warning-bg !default; + +$panel-danger-text: $state-danger-text !default; +$panel-danger-border: $state-danger-border !default; +$panel-danger-heading-bg: $state-danger-bg !default; + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +$thumbnail-padding: 4px !default; +//** Thumbnail background color +$thumbnail-bg: $body-bg !default; +//** Thumbnail border color +$thumbnail-border: $gray-lighter !default; +//** Thumbnail border radius +$thumbnail-border-radius: $border-radius-base !default; + +//** Custom text color for thumbnail captions +$thumbnail-caption-color: $text-color !default; +//** Padding around the thumbnail caption +$thumbnail-caption-padding: 9px !default; + + +//== Wells +// +//## + +$well-bg: $gray-lighter !default; +$well-border: transparent !default; + + +//== Badges +// +//## + +$badge-color: #fff !default; +//** Linked badge text color on hover +$badge-link-hover-color: #fff !default; +$badge-bg: $brand-primary !default; + +//** Badge text color in active nav link +$badge-active-color: $brand-primary !default; +//** Badge background color in active nav link +$badge-active-bg: #fff !default; + +$badge-font-weight: bold !default; +$badge-line-height: 1 !default; +$badge-border-radius: 10px !default; + + +//== Breadcrumbs +// +//## + +$breadcrumb-padding-vertical: 8px !default; +$breadcrumb-padding-horizontal: 15px !default; +//** Breadcrumb background color +$breadcrumb-bg: $gray-lighter !default; +//** Breadcrumb text color +$breadcrumb-color: #ccc !default; +//** Text color of current page in the breadcrumb +$breadcrumb-active-color: $gray !default; +//** Textual separator for between breadcrumb elements +$breadcrumb-separator: "/" !default; + + +//== Carousel +// +//## + +$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; + +$carousel-control-color: #fff !default; +$carousel-control-width: 15% !default; +$carousel-control-opacity: .5 !default; +$carousel-control-font-size: 20px !default; + +$carousel-indicator-active-bg: #fff !default; +$carousel-indicator-border-color: #fff !default; + +$carousel-caption-color: #fff !default; + + +//== Close +// +//## + +$close-font-weight: bold !default; +$close-color: #000 !default; +$close-text-shadow: none !default; + + +//== Code +// +//## + +$code-color: #c7254e !default; +$code-bg: #f9f2f4 !default; + +$kbd-color: #fff !default; +$kbd-bg: #333 !default; + +$pre-bg: $gray-lighter !default; +$pre-color: $gray-dark !default; +$pre-border-color: #ccc !default; +$pre-scrollable-max-height: 340px !default; + + +//== Type +// +//## + +//** Horizontal offset for forms and lists. +$component-offset-horizontal: 180px !default; +//** Text muted color +$text-muted: $gray-light !default; +//** Abbreviations and acronyms border color +$abbr-border-color: $gray-light !default; +//** Headings small color +$headings-small-color: $gray-light !default; +//** Blockquote small color +$blockquote-small-color: $gray-light !default; +//** Blockquote font size +$blockquote-font-size: ($font-size-base * 1.25) !default; +//** Blockquote border color +$blockquote-border-color: $gray-lighter !default; +//** Page header border color +$page-header-border-color: transparent !default; +//** Width of horizontal description list titles +$dl-horizontal-offset: $component-offset-horizontal !default; +//** Point at which .dl-horizontal becomes horizontal +$dl-horizontal-breakpoint: $grid-float-breakpoint !default; +//** Horizontal line color. +$hr-border: $gray-lighter !default; diff --git a/src/public/css/themes/gsdk/gsdk.scss b/src/public/css/themes/gsdk/gsdk.scss new file mode 100644 index 0000000..27dc80a --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk.scss @@ -0,0 +1,29 @@ +/*! + * Copyright 2016 Creative Tim (http://www.creative-tim.com) + * Licensed under MIT (https://github.com/timcreative/get-shit-done/blob/master/LICENSE.md) + */ + +@import "gsdk/variables"; +@import "gsdk/mixins"; +@import "gsdk/typography"; + +// Core CSS +@import "gsdk/misc"; +@import "gsdk/buttons"; +@import "gsdk/inputs"; +@import "gsdk/sliders"; +@import "gsdk/alerts"; +@import "gsdk/labels-and-progress-bars"; +@import "gsdk/tooltips"; +@import "gsdk/navbars"; + + +// Fancy Stuff +@import "gsdk/dropdown"; +@import "gsdk/social-buttons"; +@import "gsdk/tabs-navs-pagination"; +@import "gsdk/collapse"; +@import "gsdk/carousel"; +@import "gsdk/modal"; +@import "gsdk/responsive"; + diff --git a/src/public/css/themes/gsdk/gsdk/_alerts.scss b/src/public/css/themes/gsdk/gsdk/_alerts.scss new file mode 100644 index 0000000..3bb19e8 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_alerts.scss @@ -0,0 +1,37 @@ +.alert{ + border: 0; + border-radius: 0; + color: #FFFFFF; + padding: 10px 15px; + font-size: 14px; + + .container &{ + border-radius: 4px; + + } + .navbar &{ + border-radius: 0; + left: 0; + position: absolute; + right: 0; + top: 85px; + width: 100%; + z-index: 3; + } + .navbar:not(.navbar-transparent) &{ + top: 70px; + } +} +.alert-info{ + background-color: $azure-navbar; +} +.alert-success { + background-color: $green-navbar; +} +.alert-warning { + background-color: $orange-navbar; +} +.alert-danger { + background-color: $red-navbar; +} + diff --git a/src/public/css/themes/gsdk/gsdk/_buttons.scss b/src/public/css/themes/gsdk/gsdk/_buttons.scss new file mode 100644 index 0000000..c85bb61 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_buttons.scss @@ -0,0 +1,108 @@ +.btn{ + color: $white-color; + font-weight: $font-weight-normal; + padding: $padding-base-vertical $padding-base-horizontal; + @include opacity(1); + + @include btn-styles($default-color, $default-states-color); + + &:hover, + &:focus{ + @include opacity(1); + outline: 0 !important; + color: $white-color; + } + &:active, + &.active, + .open > &.dropdown-toggle { + @include box-shadow(none); + outline: 0 !important; + color: $white-color; + } + + .caret{ + border-top-color: $white-color; + } + +} + +// Apply the mixin to the buttons +//.btn-default { @include btn-styles($default-color, $default-states-color); } +.btn-primary { @include btn-styles($primary-color, $primary-states-color); } +.btn-success { @include btn-styles($success-color, $success-states-color); } +.btn-info { @include btn-styles($info-color, $info-states-color); } +.btn-warning { @include btn-styles($warning-color, $warning-states-color); } +.btn-danger { @include btn-styles($danger-color, $danger-states-color); } +.btn-neutral { + @include btn-styles($white-color, $white-color); + + &:active, + &.active, + .open > &.dropdown-toggle{ + background-color: $white-color; + color: $default-color; + } + + &.btn-link:active, + &.btn-link.active{ + background-color: transparent; + } +} + +.btn{ + &:disabled, + &[disabled], + &.disabled{ + @include opacity(.5); + } +} +.btn-border, +.btn-round, +.btn-link{ + background-color: $transparent-bg; + @include opacity(.8); +} +.btn-border{ + border-width: $border-thick; +} +.btn-round{ + border-width: $border-thin; + border-radius: $btn-round-radius !important; + padding: $padding-round-vertical $padding-round-horizontal; +} +.btn-link{ + border: $none; + font-size: $font-size-medium; + padding: $padding-base-vertical $padding-base-horizontal; + + &:hover, + &:focus, + &:active{ + text-decoration: none; + } +} +.btn-lg{ + @include btn-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large); + font-weight: $font-weight-normal; +} +.btn-sm{ + @include btn-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small); +} +.btn-xs { + @include btn-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $border-radius-small); +} +.btn-wd { + min-width: 140px; +} +.btn-group.select{ + width: 100%; +} +.btn-group.select .btn{ + text-align: left; +} +.btn-group.select .caret{ + position: absolute; + top: 50%; + margin-top: -1px; + right: 8px; +} diff --git a/src/public/css/themes/gsdk/gsdk/_carousel.scss b/src/public/css/themes/gsdk/gsdk/_carousel.scss new file mode 100644 index 0000000..d8aefc6 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_carousel.scss @@ -0,0 +1,24 @@ +.carousel-control{ +// width: 8%; + &.left, + &.right{ + background-image: none; + } + .fa{ + font-size: 35px; + } + .fa, + .icon-prev, + .icon-next{ + display: inline-block; + position: absolute; + top: 50%; + z-index: 5; + margin-top: -17px; + margin-left: -9px; + } +} +.carousel-inner > .item { + transition: left 1200ms cubic-bezier(0.455, 0.03, 0.4, 0.955) 0s; + -webkit-transition: left 1200ms cubic-bezier(0.455, 0.03, 0.4, 0.955) 0s; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_collapse.scss b/src/public/css/themes/gsdk/gsdk/_collapse.scss new file mode 100644 index 0000000..a849227 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_collapse.scss @@ -0,0 +1,34 @@ +.panel-group{ + .panel { + border: 0; + border-bottom: 1px solid $medium-gray; + box-shadow: none; + } + .panel-default > .panel-heading { + background-color: $white-color; + border-color: $white-color; + } + .panel{ + border-radius: 0; + } + .panel-title{ + font-size: $font-size-h5; + } + .panel-title a:hover, .panel-title a:focus{ + text-decoration: none; + } + .gsdk-collapse{ + display: block; + height: 0px; + visibility: visible; + overflow: hidden; + transition: all 400ms; + } + .panel-title a:hover, + .panel-title a:focus{ + color: $default-states-color; + } + .panel-default > .panel-heading + .panel-collapse.gsdk-collapse > .panel-body { + box-shadow: inset 0 7px 10px -7px rgba(0,0,0,0.14); + } +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_dropdown.scss b/src/public/css/themes/gsdk/gsdk/_dropdown.scss new file mode 100644 index 0000000..d9f4784 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_dropdown.scss @@ -0,0 +1,51 @@ +.dropdown-menu{ + margin: 0; + padding: 0; + border-radius: $border-radius-extreme; + z-index: 9000; + @include box-shadow($dropdown-shadow); + + > li > a { + padding: $padding-base-vertical $padding-base-horizontal; + color: #333333; + } + > li > a:focus{ + outline: 0 !important; + } + + > li:first-child > a{ + border-top-left-radius: $border-radius-extreme; + border-top-right-radius: $border-radius-extreme; + } + + > li:last-child > a{ + border-bottom-left-radius: $border-radius-extreme; + border-bottom-right-radius: $border-radius-extreme; + } + + > li > a:hover, + > li > a:focus { + background-color: $smoke-bg; + color: #333333; + opacity: 1; + text-decoration: none; + } + + > .active > a{ + &, + &:focus, + &:hover{ + background-color: $info-bg; + } + } +} + + +//fix bug for the select items in btn-group +.btn-group.select{ + overflow: hidden; +} +.btn-group.select.open{ + overflow: visible; +} + diff --git a/src/public/css/themes/gsdk/gsdk/_inputs.scss b/src/public/css/themes/gsdk/gsdk/_inputs.scss new file mode 100644 index 0000000..d3c1064 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_inputs.scss @@ -0,0 +1,149 @@ +.form-control::-moz-placeholder{ + @include placeholder($medium-gray,1); +} +.form-control:-moz-placeholder{ + @include placeholder($medium-gray,1); +} +.form-control::-webkit-input-placeholder{ + @include placeholder($medium-gray,1); +} +.form-control:-ms-input-placeholder{ + @include placeholder($medium-gray,1); +} + + +.form-control { + background-color: $white-bg; + border: 1px solid $medium-gray; + border-radius: $border-radius-base; + color: #444444; + + @include input-size($padding-base-vertical, $padding-base-horizontal, $height-base); + @include box-shadow(none); + + &:focus{ + background-color: $white-bg; + border: 1px solid $dark-gray; + @include box-shadow(none); + outline: 0 !important; + } + + .has-success &, + .has-error &, + .has-success &:focus, + .has-error &:focus{ + border-color: $light-gray; + @include box-shadow(none); + } + + .has-success &{ + color: $success-color; + &:focus{ + border-color: $success-color; + } + } + + .has-error &{ + color: $danger-color; + &:focus{ + border-color: $danger-color; + } + } + + & + .form-control-feedback{ + border-radius: $border-radius-large; + font-size: $font-size-base; + padding: 0 12px 0 0; + position: absolute; + right: 25px; + top: 13px; + vertical-align: middle; + } + + .open > &{ + border-radius: $border-radius-base $border-radius-base 0 0; + border-bottom-color: transparent; + } +} + +.input-lg{ + height: 55px; + padding: $padding-large-vertical $padding-large-horizontal; +} + +.has-error{ + .form-control-feedback{ + color: $danger-color; + } +} +.has-success{ + .form-control-feedback{ + color: $success-color + } +} + + +.input-group-addon { + background-color: $white-color; + border: 1px solid $light-gray; + border-radius: $border-radius-base; + + -webkit-transition: all 300ms linear; + -moz-transition: all 300ms linear; + -o-transition: all 300ms linear; + -ms-transition: all 300ms linear; + transition: all 300ms linear; + + .has-success &, + .has-error &{ + background-color: $white-color; + border: 1px solid $light-gray; + } + .has-error .form-control:focus + &{ + border-color: $danger-color; + color: $danger-color; + } + .has-success .form-control:focus + &{ + border-color: $success-color; + color: $success-color; + } + .form-control:focus + &, + .form-control:focus ~ &{ + background-color: $white-color; + border-color: $dark-gray; + } +} + +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { + border-right: 0 none; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child) { + border-left: 0 none; +} +.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { + background-color: $light-gray; + color: $default-color; + cursor: not-allowed; +} + +.input-group-btn .btn{ + border-width: $border-thin; + padding: $padding-round-vertical $padding-base-horizontal; +} +.input-group-btn .btn-default:not(.btn-fill){ + border-color: $medium-gray; +} + +.input-group-btn:last-child > .btn{ + margin-left: 0; +} + +.input-group-focus .input-group-addon{ + border-color: $dark-gray; +} diff --git a/src/public/css/themes/gsdk/gsdk/_labels-and-progress-bars.scss b/src/public/css/themes/gsdk/gsdk/_labels-and-progress-bars.scss new file mode 100644 index 0000000..f341126 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_labels-and-progress-bars.scss @@ -0,0 +1,63 @@ +/* Labels & Progress-bar */ +.label{ + padding: 0.2em 0.6em 0.2em; + border: 1px solid #999999; + border-radius: 3px; + color: #999999; + background-color: #FFFFFF; + font-weight: 500; + font-size: 11px; + text-transform: uppercase; + display: inline-block; + margin-bottom: 3px; +} +.label-primary{ + border-color: $primary-color; + color: $primary-color; +} +.label-info{ + border-color: $info-color; + color: $info-color; +} +.label-success{ + border-color: $success-color; + color: $success-color; +} +.label-warning{ + border-color: $warning-color; + color: $warning-color; +} +.label-danger{ + border-color: $danger-color; + color: $danger-color; +} +.label.label-fill{ + color: #FFFFFF; +} +.label-primary.label-fill, .progress-bar, .progress-bar-primary{ + background-color: $primary-color; +} +.label-info.label-fill, .progress-bar-info{ + background-color: $info-color; +} +.label-success.label-fill, .progress-bar-success{ + background-color: $success-color; +} +.label-warning.label-fill, .progress-bar-warning{ + background-color: $warning-color; +} +.label-danger.label-fill, .progress-bar-danger{ + background-color: $danger-color; +} +.label-default.label-fill{ + background-color: #999999; +} +.progress { + background-color: #E5E5E5; + border-radius: 3px; + box-shadow: none; + height: 4px; +} +.progress-thin{ + height: 2px; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_misc.scss b/src/public/css/themes/gsdk/gsdk/_misc.scss new file mode 100644 index 0000000..b91afa6 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_misc.scss @@ -0,0 +1,106 @@ +/* General overwrite */ +body{ + font-family: "Helvetica Neue","Open Sans",Arial,sans-serif; +} +.main{ + background-color: #FFFFFF; + position: relative; +} +a{ + color: $info-color; + + &:hover, &:focus{ + color: $info-states-color; + text-decoration: none; + } +} + +a:focus, a:active, +button::-moz-focus-inner, +input[type="reset"]::-moz-focus-inner, +input[type="button"]::-moz-focus-inner, +input[type="submit"]::-moz-focus-inner, +select::-moz-focus-inner, +input[type="file"] > input[type="button"]::-moz-focus-inner { + outline : 0; +} +.ui-slider-handle:focus, +.navbar-toggle { + outline : 0 !important; +} + +/* Animations */ +.form-control, +.input-group-addon, +.tagsinput, +.navbar, +.navbar .alert{ + @include transition($general-transition-time, linear); +} + +.fa{ + width: 18px; + text-align: center; +} +.margin-top{ + margin-top: 50px; +} + + +/* CT colors */ +.ct-blue, +.ct-blue.checkbox.checked .second-icon, +.ct-blue.checkbox.checked, +.ct-blue.radio.checked .second-icon, +.ct-blue.radio.checked{ + color: $primary-color; +} +.ct-azzure, +.ct-azzure.checkbox.checked .second-icon, +.ct-azzure.radio.checked .second-icon, +.ct-azzure.checkbox.checked, +.ct-azzure.radio.checked{ + color: $info-color; +} +.ct-green, +.ct-green.checkbox.checked .second-icon, +.ct-green.radio.checked .second-icon, +.ct-green.checkbox.checked, +.ct-green.radio.checked{ + color: $success-color; +} +.ct-orange, +.ct-orange.checkbox.checked .second-icon, +.ct-orange.radio.checked .second-icon, +.ct-orange.checkbox.checked, +.ct-orange.radio.checked{ + color: $warning-color; +} +.ct-red, +.ct-red.checkbox.checked .second-icon, +.ct-red.radio.checked .second-icon, +.ct-red.checkbox.checked, +.ct-red.radio.checked{ + color: $danger-color; +} +input.ct-blue + span.switch-left, +input.ct-blue + span + label + span.switch-right{ + background-color: $primary-color; +} +input.ct-azzure + span.switch-left, +input.ct-azure + span + label + span.switch-right{ + background-color: $info-color; +} +input.ct-green + span.switch-left, +input.ct-green + span + label + span.switch-right{ + background-color: $success-color; +} +input.ct-orange + span.switch-left, +input.ct-orange + span + label + span.switch-right{ + background-color: $warning-color; +} +input.ct-red + span.switch-left, +input.ct-red + span + label + span.switch-right{ + background-color: $danger-color; +} + diff --git a/src/public/css/themes/gsdk/gsdk/_mixins.scss b/src/public/css/themes/gsdk/gsdk/_mixins.scss new file mode 100644 index 0000000..6b20407 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_mixins.scss @@ -0,0 +1,13 @@ +//Utilities + +@import "mixins/transparency"; +@import "mixins/vendor-prefixes"; + +//Components + +@import "mixins/buttons"; +@import "mixins/inputs"; +@import "mixins/labels"; +@import "mixins/tabs"; +@import "mixins/navbars"; + diff --git a/src/public/css/themes/gsdk/gsdk/_modal.scss b/src/public/css/themes/gsdk/gsdk/_modal.scss new file mode 100644 index 0000000..df98642 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_modal.scss @@ -0,0 +1,53 @@ +.modal-header { + border: 0 none; +} +.modal-content { + border: 0 none; + border-radius: 10px; + box-shadow: 0 0 15px rgba(0, 0, 0, 0.15), 0 0 1px 1px rgba(0, 0, 0, 0.1); +} +.modal-dialog { + padding-top: 60px; +} +.modal-footer { + border-top: 0 none; + padding: 5px 10px; + text-align: right; + .btn{ + font-size: 16px; + } + .btn-default.btn-simple{ + font-weight: 400; + } + .divider { + background-color: #DDDDDD; + display: inline-block; + float: inherit; + height: 26px; + margin: 8px -3px; + position: absolute; + width: 1px; + } + + +} +.modal-footer .modal-footer +.modal.fade .modal-dialog { + transform: none; + -webkit-transform: none; + -moz-transform: none; +} +.modal.in { +// opacity: 0.25; + .modal-dialog { + transform: none; + -webkit-transform: none; + -moz-transform: none; + } +} + +.modal-footer +.modal.fade .modal-dialog { + transform: none; +} + diff --git a/src/public/css/themes/gsdk/gsdk/_navbars.scss b/src/public/css/themes/gsdk/gsdk/_navbars.scss new file mode 100644 index 0000000..0d24e21 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_navbars.scss @@ -0,0 +1,274 @@ +.nav { + > li{ + > a:hover, + > a:focus{ + background-color: transparent; + } + } +} +.navbar{ + border: $none; + font-size: $font-size-navbar; + transition: all 0.4s; + -webkit-transition: all 0.4s; + + .navbar-brand { + font-weight: $font-weight-bold; + margin: $navbar-margin-brand; + padding: $navbar-padding-brand; + font-size: $font-size-large-navbar; + } + .navbar-nav{ + > li > a { + padding: $navbar-padding-a; + margin: $navbar-margin-a; + } + > li > a.btn{ + margin: $navbar-margin-a-btn; + padding: $padding-base-vertical $padding-base-horizontal; + } + > li > a.btn-round{ + margin: $navbar-margin-a-btn-round; + } + > li > a [class^="fa"]{ + font-size: $font-size-large + 1; + position: relative; + top: 1px; + } + } + .btn{ + margin: $navbar-margin-btn; + font-size: $font-size-base; + } + .btn-simple{ + font-size: $font-size-medium; + } + .caret{ + // @include center-item(); + } + + +} + +.navbar-nav > li > .dropdown-menu{ + border-radius: $border-radius-extreme; + margin-top: -5px; +} + +.navbar-transparent, [class*="navbar-ct"]{ + .navbar-brand{ + color: $white-color; + @include opacity(.9); + + &:focus, + &:hover{ + background-color: transparent; + color: $white-color; + @include opacity(1); + } + } + + .navbar-nav{ + > li > a:not(.btn), + > li > a.btn-default{ + color: $white-color; + border-color: $white-color; + @include opacity(0.8); + } + + > li > a.btn-default:hover, + > li > a.btn-default:focus{ + border-color: $white-color; + @include opacity(1); + } + + > .active > a:not(.btn), + > .active > a:hover:not(.btn), + > .active > a:focus:not(.btn), + > li > a:hover:not(.btn), + > li > a:focus:not(.btn){ + background-color: transparent; + border-radius: 3px; + color: $white-color; + @include opacity(1); + } + .nav > li > a.btn:hover{ + background-color: transparent; + } + + > .dropdown > a .caret, + > .dropdown > a:hover .caret, + > .dropdown > a:focus .caret{ + border-bottom-color: $white-color; + border-top-color: $white-color; + } + + > .open > a, + > .open > a:hover, + > .open > a:focus { + background-color: transparent; + color: $white-color; + @include opacity(1); + } + } + + .btn-default{ + color: $white-color; + border-color: $white-color; + } + .btn-default.btn-fill{ + color: $dark-gray; + background-color: $white-color; + @include opacity(.9); + } + .btn-default.btn-fill:hover, + .btn-default.btn-fill:focus, + .btn-default.btn-fill:active, + .btn-default.btn-fill.active, + .open .dropdown-toggle.btn-fill.btn-default{ + border-color: $white-color; + @include opacity(1); + } + + .navbar-toggle .icon-bar{ + background-color: $white-color !important; + } +} + +.navbar-toggle:hover, +.navbar-toggle:focus { + background-color: transparent; +} + +/* +.navbar-transparent{ + .dropdown-menu .divider{ + background-color: rgba($white-color,.2); + } +} +*/ + +.navbar-inverse{ + .navbar-toggle:hover, + .navbar-toggle:focus { + background-color: transparent; + } + .navbar-nav > .open > a{ + &, + &:focus, + &:hover{ + background-color: transparent; + } + } +} + +.nav-open .nav .caret{ + border-bottom-color: $white-color; + border-top-color: $white-color; +} + +.navbar-default { + background-color: $white-navbar; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + + .navbar-nav{ + > .active > a, + > .active > a:not(.btn):hover, + > .active > a:not(.btn):focus, + > li > a:not(.btn):hover, + > li > a:not(.btn):focus { + background-color: transparent; + border-radius: 3px; + color: $info-color; + @include opacity(1); + } + + > .dropdown > a:hover .caret, + > .dropdown > a:focus .caret { + border-bottom-color: $info-color; + border-top-color: $info-color; + + } + + > .open > a, + > .open > a:hover, + > .open > a:focus{ + background-color: transparent; + color: $info-color; + } + + .navbar-toggle:hover,.navbar-toggle:focus { + background-color: transparent; + } + + } + + &:not(.navbar-transparent) .btn-default:hover{ + color: $info-color; + border-color: $info-color; + } + &:not(.navbar-transparent) .btn-neutral, + &:not(.navbar-transparent) .btn-neutral:hover, + &:not(.navbar-transparent) .btn-neutral:active{ + color: $dark-gray; + } + + .navbar-toggle:hover, + .navbar-toggle:focus { + background-color: transparent; + } +} + +.navbar-form{ + @include box-shadow(none); + .form-control{ + @include light-form(); + height: 22px; + font-size: $font-size-navbar; + line-height: $line-height-general; + color: $light-gray; + } + .navbar-transparent & .form-control, + [class*="navbar-ct"] & .form-control{ + color: $white-color; + border: $none; + border-bottom: 1px solid rgba($white-color,.6); + } + +} + +.navbar-ct-blue{ + @include navbar-color($blue-navbar); +} +.navbar-ct-azzure{ + @include navbar-color($azure-navbar); +} +.navbar-ct-green{ + @include navbar-color($green-navbar); +} +.navbar-ct-orange{ + @include navbar-color($orange-navbar); +} +.navbar-ct-red{ + @include navbar-color($red-navbar); +} + +.navbar-transparent{ + padding-top: 15px; + background-color: transparent; + border-bottom: 1px solid transparent; +} + +.navbar-toggle{ + margin-top: 19px; + margin-bottom: 19px; + border: $none; + + .icon-bar { + background-color: $white-color; + } + .navbar-collapse, + .navbar-form { + border-color: transparent; + } +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_responsive.scss b/src/public/css/themes/gsdk/gsdk/_responsive.scss new file mode 100644 index 0000000..1b77db0 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_responsive.scss @@ -0,0 +1,257 @@ + +@media (min-width: 768px){ + .navbar-form { + margin-top: 21px; + margin-bottom: 21px; + padding-left: 5px; + padding-right: 5px; + } + .navbar-search-form{ + display: none; + } + .navbar-nav > li > .dropdown-menu, + .dropdown .dropdown-menu{ + @include transform-scale(0); + @include transition($slow-transition-time, $transition-bezier); + @include opacity(0); + visibility: hidden; + display: block; + } + .navbar-nav > li.open > .dropdown-menu, + .dropdown.open .dropdown-menu{ + @include transform-scale(1); + @include transform-origin($dropdown-coordinates); + @include opacity(1); + visibility: visible; + } + + .navbar-nav > li > .dropdown-menu:before{ + border-bottom: 11px solid rgba(0, 0, 0, 0.2); + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + content: ""; + display: inline-block; + position: absolute; + left: 12px; + top: -11px; + } + .navbar-nav > li > .dropdown-menu:after { + border-bottom: 11px solid #FFFFFF; + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + content: ""; + display: inline-block; + position: absolute; + left: 12px; + top: -10px; + } + + .navbar-nav.navbar-right > li > .dropdown-menu:before{ + left: auto; + right: 12px; + } + + .navbar-nav.navbar-right > li > .dropdown-menu:after{ + left: auto; + right: 12px; + } + + .footer:not(.footer-big){ + nav > ul{ + li:first-child{ + margin-left: 0; + } + } + } + + .nav-open .navbar-collapse{ + @include transform-translate-x(0px); + } + .nav-open .navbar .container{ + @include transform-translate-x(-200px); + } + + .navbar-burger{ + .container{ + padding: 0 15px; + } + .navbar-header{ + width: 100%; + } + .navbar-toggle{ + display: block; + margin-right: 0; + } + + &.navbar .navbar-collapse.collapse, + &.navbar .navbar-collapse.collapse.in, + &.navbar .navbar-collapse.collapsing{ + display: none !important; + } + } +} + +/* Changes for small display */ + +@media (max-width: 767px){ + .navbar-transparent{ + padding-top: 0px; + background-color: rgba(0, 0, 0, 0.45); + } + + .body-click { + right: 230px; + } + + body{ + position: relative; + + & > .navbar-collapse { + width: 230px; + @include transform-translate-x(230px); + } + } + + .navbar{ + .container{ + width: 100%; + position: relative; + @include transform-translate-x(0px); + @include transition (0.50s, cubic-bezier(0.685, 0.0473, 0.346, 1)); + + .nav-open &{ + @include transform-translate-x(-230px); + } + } + + .navbar-collapse.collapse, + .navbar .navbar-collapse.collapse.in, + .navbar .navbar-collapse.collapsing{ + display: none !important; + } + } + + .nav-open .navbar-collapse{ + @include transform-translate-x(0px); + } + + .navbar-toggle .icon-bar{ + display: block; + position: relative; + background: $white-color; + width: 24px; + height: 2px; + border-radius: 1px; + margin: 0 auto; + } + + .navbar-default .navbar-toggle .icon-bar{ + background-color: $default-color; + } + + .navbar-header .navbar-toggle { + margin-top: 17px; + margin-bottom: 17px; + width: 40px; + height: 40px; + } + .bar1, + .bar2, + .bar3 { + outline: 1px solid transparent; + } + .bar1 { + top: 0px; + @include bar-animation($topbar-back); + } + .bar2 { + opacity: 1; + } + .bar3 { + bottom: 0px; + @include bar-animation($bottombar-back); + } + .toggled .bar1 { + top: 6px; + @include bar-animation($topbar-x); + } + .toggled .bar2 { + opacity: 0; + } + .toggled .bar3 { + bottom: 6px; + @include bar-animation($bottombar-x); + } + + @include topbar-x-rotation(); + @include topbar-back-rotation(); + @include bottombar-x-rotation(); + @include bottombar-back-rotation(); + + @-webkit-keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} + } + @-moz-keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} + } + @keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} + } + + [class*="navbar-"] .navbar-nav { + & > li > a, + > li > a:hover, + > li > a:focus, + .active > a, + .active > a:hover, + .active > a:focus, + .open .dropdown-menu > li > a, + .open .dropdown-menu > li > a:hover, + .open .dropdown-menu > li > a:focus, + .navbar-nav .open .dropdown-menu > li > a:active { +// color: white; + } + + & > li > a, + > li > a:hover, + > li > a:focus, + .open .dropdown-menu > li > a, + .open .dropdown-menu > li > a:hover, + .open .dropdown-menu > li > a:focus{ + opacity: .7; + background: transparent; + } + + &.navbar-nav .open .dropdown-menu > li > a:active { + opacity: 1; + } + + & .dropdown > a{ + &:hover .caret { + border-bottom-color: #777; + border-top-color: #777; + } + &:active .caret { + border-bottom-color: white; + border-top-color: white; + } + } + } + .dropdown-menu { + display: none; + } + .navbar-fixed-top { + -webkit-backface-visibility: hidden; + } + .navbar-toggle:hover, + .navbar-toggle:focus { + background-color: transparent !important; + } + .btn.dropdown-toggle{ + margin-bottom: 0; + } + +} diff --git a/src/public/css/themes/gsdk/gsdk/_sliders.scss b/src/public/css/themes/gsdk/gsdk/_sliders.scss new file mode 100644 index 0000000..51df094 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_sliders.scss @@ -0,0 +1,218 @@ + +/*! + * jQuery UI Slider 1.10.4 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/slider/#theming + */ +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* For IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: 4px; +} +.ui-slider-horizontal .ui-slider-handle { + margin-left: -10px; + top: -7px; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-size: 1.1em/*{fsDefault}*/; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-size: 1em; +} +.ui-widget-content { + background-color: #E5E5E5; +} +.ui-widget-content a { + color: #222222/*{fcContent}*/; +} +.ui-widget-header { + background: #999999; + color: #222222; + font-weight: bold; +} +.ui-widget-header a { + color: #222222; +} + +.slider-primary .ui-widget-header{ + background-color: #3472F7; +} +.slider-info .ui-widget-header{ + background-color: #2C93FF; +} +.slider-success .ui-widget-header{ + background-color: #05AE0E; +} +.slider-warning .ui-widget-header{ + background-color: #FF9500; +} +.slider-danger .ui-widget-header{ + background-color: #FF3B30; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + background: rgb(255,255,255); /* Old browsers */ + background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,242,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(241,241,242,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,242,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,242,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,242,1) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,242,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f1f1f2',GradientType=0 ); /* IE6-9 */ + + border-radius: 50%; + box-shadow: 0 1px 1px #FFFFFF inset, 0 1px 2px rgba(0, 0, 0, 0.4); + height:15px; + width:15px; + cursor:pointer; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #555555/*{fcDefault}*/; + text-decoration: none; +} + +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited { + color: #212121/*{fcHover}*/; + text-decoration: none; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #212121/*{fcActive}*/; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fcefa1; + background: #fbf9ee; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid $danger-color/*{borderColorError}*/; + background-color: $danger-color; + color: $danger-color/*{fcError}*/; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: $danger-color/*{fcError}*/; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: $danger-color/*{fcError}*/; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_social-buttons.scss b/src/public/css/themes/gsdk/gsdk/_social-buttons.scss new file mode 100644 index 0000000..6cb22e9 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_social-buttons.scss @@ -0,0 +1,93 @@ +.btn-social { + opacity: 0.85; + padding: 8px 9px; + + .fa { + font-size: 18px; + vertical-align: middle; + display: inline-block; + } + + &.btn-round { + padding: 9px 10px; + } + + &.btn-simple { + padding: 9px 5px; + font-size: 16px; + + .fa{ + font-size: 20px; + position: relative; + top: -2px; + width: 24px; + } + } + +} + +@mixin btn-social($color){ + + color: $white-color; + background-color: $color; + border-color: $color; + opacity: 0.9; + + &:hover, + &:focus, + &:active, + &.active, + .open > &.dropdown-toggle{ + background-color: $color; + border-color: $color; + color: $white-color; + opacity: 1; + } + + &.btn-border{ + border-color: $color; + color: $color; + + &:hover, + &:focus, + &:active, + &.active, + .open > &.dropdown-toggle { + background-color: $transparent-bg; + color: $color; + border-color: $color; + opacity: 1; + } + + &:disabled, + &[disabled], + &.disabled { + background-color: $transparent-bg; + border-color: $color; + } + } + + +} + +.btn-adn { @include btn-social(#d87a68); } +.btn-bitbucket { @include btn-social(#205081); } +.btn-dropbox { @include btn-social(#1087dd); } +.btn-facebook { @include btn-social(#3b5998); } +.btn-flickr { @include btn-social(#ff0084); } +.btn-foursquare { @include btn-social(#f94877); } +.btn-github { @include btn-social(#444444); } +.btn-google { @include btn-social(#dd4b39); } +.btn-instagram { @include btn-social(#3f729b); } +.btn-linkedin { @include btn-social(#007bb6); } +.btn-microsoft { @include btn-social(#2672ec); } +.btn-odnoklassniki { @include btn-social(#f4731c); } +.btn-openid { @include btn-social(#f7931e); } +.btn-pinterest { @include btn-social(#cb2027); } +.btn-reddit { @include btn-social(#eff7ff); } +.btn-soundcloud { @include btn-social(#ff5500); } +.btn-tumblr { @include btn-social(#2c4762); } +.btn-twitter { @include btn-social(#55acee); } +.btn-vimeo { @include btn-social(#1ab7ea); } +.btn-vk { @include btn-social(#587ea3); } +.btn-yahoo { @include btn-social(#720e9e); } \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_tabs-navs-pagination.scss b/src/public/css/themes/gsdk/gsdk/_tabs-navs-pagination.scss new file mode 100644 index 0000000..a28d371 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_tabs-navs-pagination.scss @@ -0,0 +1,122 @@ +/* Navigation menu */ +.nav-pills { + > li + li { + margin-left: 0; + } + > li > a { + border: 1px solid $info-color; + border-radius: 0; + color: $info-color; + margin-left: -1px; + + &:hover, + &:focus{ + background-color: #F5F5F5; + } + } + > li.active > a, + > li.active > a:hover, + > li.active > a:focus { + background-color: $info-color; + color: #FFFFFF !important; + } + > li:first-child > a{ + border-radius: $border-radius-base 0 0 $border-radius-base; + margin: 0; + } + > li:last-child > a{ + border-radius: 0 $border-radius-base $border-radius-base 0; + } +} + +// style for pagination +.pagination.pagination-no-border > li > a, +.pagination.pagination-no-border > li > span{ + border: 0; +} +.pagination > li > a, .pagination > li > span, .pagination > li:first-child > a, .pagination > li:first-child > span, .pagination > li:last-child > a, .pagination > li:last-child > span{ + border-radius: 50%; + margin: 0 2px; + color: $default-states-color; +} +.pagination > li.active > a, .pagination > li.active > span, .pagination > li.active > a:hover, .pagination > li.active > span:hover, .pagination > li.active > a:focus, .pagination > li.active > span:focus { + background-color: $info-color; + border: 0; + color: #FFFFFF; + padding: 7px 13px; +} + +.nav-pills.ct-blue > li.active > a, +.nav-pills.ct-blue > li.active > a:hover, +.nav-pills.ct-blue > li.active > a:focus, +.pagination.ct-blue > li.active > a, +.pagination.ct-blue > li.active > span, +.pagination.ct-blue > li.active > a:hover, +.pagination.ct-blue > li.active > span:hover, +.pagination.ct-blue > li.active > a:focus, +.pagination.ct-blue > li.active > span:focus{ + background-color: $primary-color; +} + +.nav-pills.ct-azzure > li.active > a, +.nav-pills.ct-azzure > li.active > a:hover, +.nav-pills.ct-azzure > li.active > a:focus, +.pagination.ct-azzure > li.active > a, +.pagination.ct-azzure > li.active > span, +.pagination.ct-azzure > li.active > a:hover, +.pagination.ct-azzure > li.active > span:hover, +.pagination.ct-azzure > li.active > a:focus, +.pagination.ct-azzure > li.active > span:focus{ + background-color: $info-color; +} + +.nav-pills.ct-green > li.active > a, +.nav-pills.ct-green > li.active > a:hover, +.nav-pills.ct-green > li.active > a:focus, +.pagination.ct-green > li.active > a, +.pagination.ct-green > li.active > span, +.pagination.ct-green > li.active > a:hover, +.pagination.ct-green > li.active > span:hover, +.pagination.ct-green > li.active > a:focus, +.pagination.ct-green > li.active > span:focus{ + background-color: $success-color; +} + +.nav-pills.ct-orange > li.active > a, +.nav-pills.ct-orange > li.active > a:hover, +.nav-pills.ct-orange > li.active > a:focus, +.pagination.ct-orange > li.active > a, +.pagination.ct-orange > li.active > span, +.pagination.ct-orange > li.active > a:hover, +.pagination.ct-orange > li.active > span:hover, +.pagination.ct-orange > li.active > a:focus, +.pagination.ct-orange > li.active > span:focus{ + background-color: $warning-color; +} + +.nav-pills.ct-red > li.active > a, +.nav-pills.ct-red > li.active > a:hover, +.nav-pills.ct-red > li.active > a:focus, +.pagination.ct-red > li.active > a, +.pagination.ct-red > li.active > span, +.pagination.ct-red > li.active > a:hover, +.pagination.ct-red > li.active > span:hover, +.pagination.ct-red > li.active > a:focus, +.pagination.ct-red > li.active > span:focus{ + background-color: $danger-color; +} +.nav-pills.ct-blue > li > a { + @include pill-style($primary-color); +} +.nav-pills.ct-azzure > li > a { + @include pill-style($info-color); +} +.nav-pills.ct-green > li > a { + @include pill-style($success-color); +} +.nav-pills.ct-orange > li > a { + @include pill-style($warning-color); +} +.nav-pills.ct-red > li > a { + @include pill-style($danger-color); +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_tooltips.scss b/src/public/css/themes/gsdk/gsdk/_tooltips.scss new file mode 100644 index 0000000..9aaf018 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_tooltips.scss @@ -0,0 +1,107 @@ +.tooltip { + font-size: $font-size-base; + font-weight: $font-weight-bold; + + &.top { + margin-top: -11px; + padding: 0; + } + &.top .tooltip-inner:after { + border-top: 11px solid #FAE6A4; + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + bottom: -10px; + } + &.top .tooltip-inner:before { + border-top: 11px solid rgba(0, 0, 0, 0.2); + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + bottom: -11px; + } + &.bottom { + margin-top: 11px; + padding: 0; + } + &.bottom .tooltip-inner:after { + border-bottom: 11px solid #FAE6A4; + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + top: -10px; + } + &.bottom .tooltip-inner:before { + border-bottom: 11px solid rgba(0, 0, 0, 0.2); + border-left: 11px solid rgba(0, 0, 0, 0); + border-right: 11px solid rgba(0, 0, 0, 0); + top: -11px; + } + &.left{ + margin-left: -11px; + padding: 0; + } + &.left .tooltip-inner:after { + border-left: 11px solid #FAE6A4; + border-top: 11px solid rgba(0, 0, 0, 0); + border-bottom: 11px solid rgba(0, 0, 0, 0); + right: -10px; + left: auto; + margin-left: 0; + } + &.left .tooltip-inner:before { + border-left: 11px solid rgba(0, 0, 0, 0.2); + border-top: 11px solid rgba(0, 0, 0, 0); + border-bottom: 11px solid rgba(0, 0, 0, 0); + right: -11px; + left: auto; + margin-left: 0; + } + &.right{ + margin-left: 11px; + padding: 0; + } + &.right .tooltip-inner:after { + border-right: 11px solid #FAE6A4; + border-top: 11px solid rgba(0, 0, 0, 0); + border-bottom: 11px solid rgba(0, 0, 0, 0); + left: -10px; + top: 0; + margin-left: 0; + } + &.right .tooltip-inner:before { + border-right: 11px solid rgba(0, 0, 0, 0.2); + border-top: 11px solid rgba(0, 0, 0, 0); + border-bottom: 11px solid rgba(0, 0, 0, 0); + left: -11px; + top: 0; + margin-left: 0; + } +} + +.tooltip-arrow{ + display: none; + opacity: 0; +} +.tooltip-inner { + background-color: #FAE6A4; + border-radius: 4px; + box-shadow: 0 1px 13px rgba(0, 0, 0, 0.14), 0 0 0 1px rgba(115, 71, 38, 0.23); + color: #734726; + max-width: 260px; + min-width: 86px; + padding: 6px 10px; + text-align: center; + text-decoration: none; +} +.tooltip-inner:after { + content: ""; + display: inline-block; + left: 100%; + margin-left: -60%; + position: absolute; +} +.tooltip-inner:before { + content: ""; + display: inline-block; + left: 100%; + margin-left: -60%; + position: absolute; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/_typography.scss b/src/public/css/themes/gsdk/gsdk/_typography.scss new file mode 100644 index 0000000..ceff1cc --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_typography.scss @@ -0,0 +1,73 @@ +/* Font Smoothing */ + +h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6, p, .navbar, .brand, .btn-simple, a, .td-name, td{ + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: "Helvetica Neue","Open Sans",Arial,sans-serif; +} + +h1, .h1, h2, .h2, h3, .h3, h4, .h4{ + font-weight: $font-weight-normal; + margin: $margin-large-vertical 0 $margin-base-vertical; +} + +h1, .h1 { + font-size: $font-size-h1; +} +h2, .h2{ + font-size: $font-size-h2; +} +h3, .h3{ + font-size: $font-size-h3; + margin: 20px 0 10px; +} +h4, .h4{ + font-size: $font-size-h4; + line-height: 30px; +} +h5, .h5 { + font-size: $font-size-h5; + margin-bottom: 15px; +} +h6, .h6{ + font-size: $font-size-h6; + font-weight: $font-weight-bold; + text-transform: uppercase; +} +p{ + font-size: $font-paragraph; + line-height: $line-height-general; +} + +h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { + color: $dark-gray; + font-weight: $font-weight-light; + line-height: $line-height-general; +} + +h1 small, h2 small, h3 small, h1 .small, h2 .small, h3 .small { + font-size: 60%; +} + +h1 .subtitle{ + display: block; + font-family: 'Grand Hotel',cursive; + margin: 0 0 $margin-large-vertical; +} + +.text-primary, .text-primary:hover{ + color: $primary-color !important; +} +.text-info, .text-info:hover{ + color: $info-color !important; +} +.text-success, .text-success:hover{ + color: $success-color !important; +} +.text-warning, .text-warning:hover{ + color: $warning-color !important; +} +.text-danger, .text-danger:hover{ + color: $danger-color !important; +} + diff --git a/src/public/css/themes/gsdk/gsdk/_variables.scss b/src/public/css/themes/gsdk/gsdk/_variables.scss new file mode 100644 index 0000000..1d4f527 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/_variables.scss @@ -0,0 +1,195 @@ +//== Buttons +// +//## For each of Bootstrap's buttons, define text, background and border color. + +$none: 0 !default; +$border-thin: 1px !default; +$border-thick: 2px !default; + +$white-color: #FFFFFF !default; +$white-bg: #FFFFFF !default; + +$smoke-bg: #F5F5F5 !default; + +$black-bg: rgba(30,30,30,.97) !default; + +$black-color: #333333 !default; +$black-hr: #444444 !default; + +$light-gray: #E3E3E3 !default; +$medium-gray: #DDDDDD !default; +$dark-gray: #9A9A9A !default; + +$transparent-bg: transparent !default; + +$default-color: #888888 !default; +$default-bg: #888888 !default; +$default-states-color: #777777 !default; + +$primary-color: #3472F7 !default; +$primary-bg: #3472F7 !default; +$primary-states-color: #1D62F0 !default; + +$success-color: #05AE0E !default; +$success-bg: #05AE0E !default; +$success-states-color: #049F0C !default; + +$info-color: #2CA8FF !default; +$info-bg: #2CA8FF !default; +$info-states-color: #109CFF !default; + +$warning-color: #FF9500 !default; +$warning-bg: #FF9500 !default; +$warning-states-color: #ED8D00 !default; + + +$danger-color: #FF3B30 !default; +$danger-bg: #FF3B30 !default; +$danger-states-color: #EE2D20 !default; + + + +$link-disabled-color: #666666 !default; + + +/* light colors */ +$light-blue: rgba($primary-color, .2); +$light-azure: rgba($info-color, .2); +$light-green: rgba($success-color, .2); +$light-orange: rgba($warning-color, .2); +$light-red: rgba($danger-color, .2); + + +//== Components +// + +$padding-base-vertical: 8px !default; +$padding-base-horizontal: 16px !default; + +$padding-round-vertical: 9px !default; +$padding-round-horizontal: 18px !default; + +$padding-simple-vertical: 10px !default; +$padding-simple-horizontal: 18px !default; + +$padding-large-vertical: 14px !default; +$padding-large-horizontal: 30px !default; + +$padding-small-vertical: 5px !default; +$padding-small-horizontal: 10px !default; + +$padding-xs-vertical: 1px !default; +$padding-xs-horizontal: 5px !default; + +$padding-label-vertical: 2px !default; +$padding-label-horizontal: 12px !default; + +$margin-large-vertical: 30px !default; +$margin-base-vertical: 15px !default; + +$margin-bottom: 0 0 10px 0 !default; +$border-radius-small: 3px !default; +$border-radius-base: 4px !default; +$border-radius-large: 6px !default; +$border-radius-extreme: 10px !default; + +$border-radius-large-top: $border-radius-large $border-radius-large 0 0 !default; +$border-radius-large-bottom: 0 0 $border-radius-large $border-radius-large !default; + +$btn-round-radius: 30px !default; + +$height-base: 40px !default; + +$font-size-base: 14px !default; +$font-size-small: 12px !default; +$font-size-medium: 16px !default; +$font-size-large: 18px !default; +$font-size-large-navbar: 20px !default; + +$font-size-h1: 52px !default; +$font-size-h2: 36px !default; +$font-size-h3: 28px !default; +$font-size-h4: 22px !default; +$font-size-h5: 18px !default; +$font-size-h6: 14px !default; +$font-paragraph: 16px !default; +$font-size-navbar: 16px !default; +$font-size-small: 12px !default; + +$font-weight-light: 300 !default; +$font-weight-normal: 400 !default; +$font-weight-semi: 500 !default; +$font-weight-bold: 600 !default; + +$line-height-general: 1.5 !default; +$line-height: 20px !default; +$line-height-lg: 54px !default; + + +$border-radius-top: 10px 10px 0 0 !default; +$border-radius-bottom: 0 0 10px 10px !default; + +$dropdown-shadow: 1px 2px 3px rgba(0, 0, 0, 0.125); + +$general-transition-time: 300ms !default; + +$slow-transition-time: 370ms !default; +$dropdown-coordinates: 29px -50px !default; + +$fast-transition-time: 150ms !default; +$select-coordinates: 50% -40px !default; + +$transition-linear: linear !default; +$transition-bezier: cubic-bezier(0.34, 1.61, 0.7, 1) !default; +$transition-ease: ease 0s; + +$navbar-padding-a: 10px 15px; +$navbar-margin-a: 15px 3px; + +$padding-social-a: 10px 5px; + +$navbar-margin-a-btn: 15px 3px; +$navbar-margin-a-btn-round: 16px 3px; + +$navbar-padding-a-icons: 6px 15px; +$navbar-margin-a-icons: 6px 3px; + +$navbar-padding-brand: 20px 15px; +$navbar-margin-brand: 5px 0px; + +$navbar-margin-brand-icons: 12px auto; + +$navbar-margin-btn: 15px 3px; + + + +$height-icon-sm: 32px; +$width-icon-sm: 32px; +$padding-icon-sm: 4px; +$border-radius-icon-sm: 7px; + +$height-icon-message: 40px; +$width-icon-message: 40px; + +$height-icon-message-sm: 20px; +$width-icon-message-sm: 20px; + + +$white-navbar: rgba(#FFFFFF, .96); +$blue-navbar: rgba(#34ACDC, .98); +$azure-navbar: rgba(#5BCAFF, .98); +$green-navbar: rgba(#4CD964, .98); +$orange-navbar: rgba(#FF9500, .98); +$red-navbar: rgba(#FF4C40, .98); + + + +$topbar-x: topbar-x !default; +$topbar-back: topbar-back !default; +$bottombar-x: bottombar-x !default; +$bottombar-back: bottombar-back !default; + + + + + diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_buttons.scss b/src/public/css/themes/gsdk/gsdk/mixins/_buttons.scss new file mode 100644 index 0000000..c24fccc --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_buttons.scss @@ -0,0 +1,73 @@ +// Mixin for generating new styles +@mixin btn-styles($btn-color, $btn-states-color) { + + background-color: $btn-color; + border-color: $btn-color; + + &:hover, + &:focus, + &:active, + &.active, + .open > &.dropdown-toggle{ + background-color: $btn-states-color; + border-color: $btn-states-color; + } + + &.btn-border, + &.btn-round, + &.btn-link{ + border-color: $btn-color; + color: $btn-color; + + &:hover, + &:focus, + &:active, + &.active, + &:active:focus, + &:active:hover, + &.active:focus, + &.active:hover, + .open > &.dropdown-toggle, + .open > &.dropdown-toggle:focus, + .open > &.dropdown-toggle:hover { + background-color: $transparent-bg; + color: $btn-states-color; + border-color: $btn-states-color; + } + + &.disabled, + &:disabled, + &[disabled], + fieldset[disabled] & { + &, + &:hover, + &:focus, + &.focus, + &:active, + &.active { + background-color: $transparent-bg; + border-color: $btn-color; + } + } + + .caret{ + border-top-color: $btn-color; + } + } +} + + +@mixin btn-size($padding-vertical, $padding-horizontal, $font-size, $border){ + font-size: $font-size; + border-radius: $border; + padding: $padding-vertical $padding-horizontal; + + &.btn-round{ + padding: $padding-vertical + 1 $padding-horizontal; + } + + &.btn-link{ + padding: $padding-vertical + 2 $padding-horizontal; + } + +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_inputs.scss b/src/public/css/themes/gsdk/gsdk/mixins/_inputs.scss new file mode 100644 index 0000000..870c918 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_inputs.scss @@ -0,0 +1,17 @@ +@mixin input-size($padding-vertical, $padding-horizontal, $height){ + padding: $padding-vertical $padding-horizontal; + height: $height; +} + +@mixin placeholder($color, $opacity){ + color: $color; + @include opacity(1); +} + +@mixin light-form(){ + border-radius: 0; + border:0; + padding: 0; + background-color: transparent; + +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_labels.scss b/src/public/css/themes/gsdk/gsdk/mixins/_labels.scss new file mode 100644 index 0000000..8a2bdd5 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_labels.scss @@ -0,0 +1,21 @@ +@mixin label-style(){ + padding: $padding-label-vertical $padding-label-horizontal; + border: 1px solid $default-color; + border-radius: $border-radius-small; + color: $default-color; + font-weight: $font-weight-semi; + font-size: $font-size-small; + text-transform: uppercase; + display: inline-block; + vertical-align: middle; +} + +@mixin label-color($color){ + border-color: $color; + color: $color; +} +@mixin label-color-fill($color){ + border-color: $color; + color: $white-color; + background-color: $color; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_navbars.scss b/src/public/css/themes/gsdk/gsdk/mixins/_navbars.scss new file mode 100644 index 0000000..6f50046 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_navbars.scss @@ -0,0 +1,11 @@ +@mixin navbar-color($color){ + background-color: $color; +} + +@mixin center-item(){ + left: 0; + right: 0; + margin-right: auto; + margin-left: auto; + position: absolute; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_tabs.scss b/src/public/css/themes/gsdk/gsdk/mixins/_tabs.scss new file mode 100644 index 0000000..edf6f58 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_tabs.scss @@ -0,0 +1,4 @@ +@mixin pill-style($color){ + border: 1px solid $color; + color: $color; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_transparency.scss b/src/public/css/themes/gsdk/gsdk/mixins/_transparency.scss new file mode 100644 index 0000000..da32b74 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_transparency.scss @@ -0,0 +1,20 @@ +// Opacity + +@mixin opacity($opacity) { + opacity: $opacity; + // IE8 filter + $opacity-ie: ($opacity * 100); + filter: #{alpha(opacity=$opacity-ie)}; +} + +@mixin black-filter($opacity){ + top: 0; + left: 0; + height: 100%; + width: 100%; + position: absolute; + background-color: rgba(17,17,17,$opacity); + display: block; + content: ""; + z-index: 1; +} \ No newline at end of file diff --git a/src/public/css/themes/gsdk/gsdk/mixins/_vendor-prefixes.scss b/src/public/css/themes/gsdk/gsdk/mixins/_vendor-prefixes.scss new file mode 100644 index 0000000..da70771 --- /dev/null +++ b/src/public/css/themes/gsdk/gsdk/mixins/_vendor-prefixes.scss @@ -0,0 +1,177 @@ +// User select +// For selecting text on the page + +@mixin user-select($select) { + -webkit-user-select: $select; + -moz-user-select: $select; + -ms-user-select: $select; // IE10+ + user-select: $select; +} + +@mixin box-shadow($shadow...) { + -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1 + box-shadow: $shadow; +} + +// Box sizing +@mixin box-sizing($boxmodel) { + -webkit-box-sizing: $boxmodel; + -moz-box-sizing: $boxmodel; + box-sizing: $boxmodel; +} + + +@mixin transition($time, $type){ + -webkit-transition: all $time $type; + -moz-transition: all $time $type; + -o-transition: all $time $type; + -ms-transition: all $time $type; + transition: all $time $type; +} + +@mixin transform-scale($value){ + -webkit-transform: scale($value); + -moz-transform: scale($value); + -o-transform: scale($value); + -ms-transform: scale($value); + transform: scale($value); +} + +@mixin transform-translate-x($value){ + -webkit-transform: translate3d($value, 0, 0); + -moz-transform: translate3d($value, 0, 0); + -o-transform: translate3d($value, 0, 0); + -ms-transform: translate3d($value, 0, 0); + transform: translate3d($value, 0, 0); +} + +@mixin transform-origin($coordinates){ + -webkit-transform-origin: $coordinates; + -moz-transform-origin: $coordinates; + -o-transform-origin: $coordinates; + -ms-transform-origin: $coordinates; + transform-origin: $coordinates; +} + +@mixin icon-gradient ($top-color, $bottom-color){ + background: $top-color; + background: -moz-linear-gradient(top, $top-color 0%, $bottom-color 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,$top-color), color-stop(100%,$bottom-color)); + background: -webkit-linear-gradient(top, $top-color 0%,$bottom-color 100%); + background: -o-linear-gradient(top, $top-color 0%,$bottom-color 100%); + background: -ms-linear-gradient(top, $top-color 0%,$bottom-color 100%); + background: linear-gradient(to bottom, $top-color 0%,$bottom-color 100%); +} + +@mixin vertical-align { + position: relative; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); +} + +@mixin rotate-180(){ + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +@mixin bar-animation($type){ + -webkit-animation: $type 500ms linear 0s; + -moz-animation: $type 500ms linear 0s; + animation: $type 500ms 0s; + -webkit-animation-fill-mode: forwards; + -moz-animation-fill-mode: forwards; + animation-fill-mode: forwards; +} + +@mixin topbar-x-rotation(){ + @keyframes topbar-x { + 0% {top: 0px; transform: rotate(0deg); } + 45% {top: 6px; transform: rotate(145deg); } + 75% {transform: rotate(130deg); } + 100% {transform: rotate(135deg); } + } + @-webkit-keyframes topbar-x { + 0% {top: 0px; -webkit-transform: rotate(0deg); } + 45% {top: 6px; -webkit-transform: rotate(145deg); } + 75% {-webkit-transform: rotate(130deg); } + 100% { -webkit-transform: rotate(135deg); } + } + @-moz-keyframes topbar-x { + 0% {top: 0px; -moz-transform: rotate(0deg); } + 45% {top: 6px; -moz-transform: rotate(145deg); } + 75% {-moz-transform: rotate(130deg); } + 100% { -moz-transform: rotate(135deg); } + } +} + +@mixin topbar-back-rotation(){ + @keyframes topbar-back { + 0% { top: 6px; transform: rotate(135deg); } + 45% { transform: rotate(-10deg); } + 75% { transform: rotate(5deg); } + 100% { top: 0px; transform: rotate(0); } + } + + @-webkit-keyframes topbar-back { + 0% { top: 6px; -webkit-transform: rotate(135deg); } + 45% { -webkit-transform: rotate(-10deg); } + 75% { -webkit-transform: rotate(5deg); } + 100% { top: 0px; -webkit-transform: rotate(0); } + } + + @-moz-keyframes topbar-back { + 0% { top: 6px; -moz-transform: rotate(135deg); } + 45% { -moz-transform: rotate(-10deg); } + 75% { -moz-transform: rotate(5deg); } + 100% { top: 0px; -moz-transform: rotate(0); } + } +} + +@mixin bottombar-x-rotation(){ + @keyframes bottombar-x { + 0% {bottom: 0px; transform: rotate(0deg);} + 45% {bottom: 6px; transform: rotate(-145deg);} + 75% {transform: rotate(-130deg);} + 100% {transform: rotate(-135deg);} + } + @-webkit-keyframes bottombar-x { + 0% {bottom: 0px; -webkit-transform: rotate(0deg);} + 45% {bottom: 6px; -webkit-transform: rotate(-145deg);} + 75% {-webkit-transform: rotate(-130deg);} + 100% {-webkit-transform: rotate(-135deg);} + } + @-moz-keyframes bottombar-x { + 0% {bottom: 0px; -moz-transform: rotate(0deg);} + 45% {bottom: 6px; -moz-transform: rotate(-145deg);} + 75% {-moz-transform: rotate(-130deg);} + 100% {-moz-transform: rotate(-135deg);} + } +} + +@mixin bottombar-back-rotation{ + @keyframes bottombar-back { + 0% { bottom: 6px;transform: rotate(-135deg);} + 45% { transform: rotate(10deg);} + 75% { transform: rotate(-5deg);} + 100% { bottom: 0px;transform: rotate(0);} + } + @-webkit-keyframes bottombar-back { + 0% {bottom: 6px;-webkit-transform: rotate(-135deg);} + 45% {-webkit-transform: rotate(10deg);} + 75% {-webkit-transform: rotate(-5deg);} + 100% {bottom: 0px;-webkit-transform: rotate(0);} + } + @-moz-keyframes bottombar-back { + 0% {bottom: 6px;-moz-transform: rotate(-135deg);} + 45% {-moz-transform: rotate(10deg);} + 75% {-moz-transform: rotate(-5deg);} + 100% {bottom: 0px;-moz-transform: rotate(0);} + } + +} + + diff --git a/src/public/css/themes/modern/_modern.scss b/src/public/css/themes/modern/_modern.scss new file mode 100644 index 0000000..6591b57 --- /dev/null +++ b/src/public/css/themes/modern/_modern.scss @@ -0,0 +1,94 @@ +@import "../../lib/bootstrap-social"; + +// Footer +// ------------------------- + +footer { + color: #fff; + background-color: $gray-darker; + + a:hover { + color: #fff; + } +} + +// Typography +// ------------------------- + +a { + transition: all .4s cubic-bezier(.24,.45,.46,.92); + + &:hover { + text-decoration: none; + } +} + +ul, +p { + font-size: 14px; +} + +.text-danger { + color: $brand-danger; +} + +// Dropdowns +// ------------------------- + +.dropdown-menu > li > a { + font-weight: 300; +} + +// Buttons +// ------------------------- + +.btn { + padding: 10px 16px; + border: 0; + border-radius: 3px; + transition: all .4s cubic-bezier(.24,.45,.46,.92); + + &:hover { + color: #fff; + background-color: $gray-darker; + } +} + +.btn-social { + padding: 10px 50px; + + :first-child { + width: 38px; + line-height: 38px; + } +} + +.btn-link { + + &:hover { + color: $gray-darker; + text-decoration: none; + background-color: transparent; + } +} + +// Form states and alerts +// ------------------------- + +.alert { + color: #fff; +} + +// Navbar +// ------------------------- + +.navbar-default { + border: 0; + box-shadow: 0 1px 5px rgba(0,0,0,.15); + + .navbar-nav { + > li > a { + transition: color .4s cubic-bezier(.24,.45,.46,.92); + } + } +} diff --git a/src/public/css/themes/modern/_variables.scss b/src/public/css/themes/modern/_variables.scss new file mode 100644 index 0000000..41acee3 --- /dev/null +++ b/src/public/css/themes/modern/_variables.scss @@ -0,0 +1,68 @@ +@import url("http://fonts.googleapis.com/css?family=Montserrat:400,700"); + +// Colors +// ------------------------- + +$gray-lighter: #f5f5f5; +$gray-light: #e0e0e0; +$gray: #737373; +$gray-dark: #404040; +$gray-darker: #121212; + +$brand-primary: #2ac5ee; +$brand-success: #0f9d58; +$brand-warning: #f4b400; +$brand-danger: #d80017; +$brand-info: #5bc0dd; + +// Typography +// ------------------------- + +$font-size-base: 13px; +$headings-font-family: 'Montserrat', sans-serif; +$headings-font-weight: 700; +$text-color: $gray-darker; +$link-color: $brand-primary; +$link-hover-color: $gray-darker; + +// Dropdowns +// ------------------------- + +$dropdown-link-color: $gray-darker; + +// Buttons +// ------------------------- + +$btn-default-bg: $gray-lighter; +$btn-default-color: $gray-darker; + +// Forms +// ------------------------- + +$input-border-radius: 2px; +$input-border-focus: #999; +$input-border: #f0f0f0; +$input-color: #444; +$input-color-placeholder: #999; +$input-height-base: 44px; + +// Form states and alerts +// ------------------------- + +$state-success-bg: $brand-success; +$state-info-bg: $brand-primary; +$state-warning-bg: $brand-warning; +$state-danger-bg: $brand-danger; + +// Navbar +// ------------------------- + +$navbar-height: 50px; +$navbar-default-bg: rgba(255,255,255,0.95); +$navbar-default-link-color: $gray-darker; +$navbar-default-link-active-color: $brand-primary; +$navbar-default-link-active-bg: transparent; +$navbar-default-link-hover-color: $brand-primary; +$navbar-default-link-hover-bg: transparent; +$navbar-default-brand-color: $gray-darker; +$navbar-default-brand-hover-color: $brand-primary; \ No newline at end of file diff --git a/src/public/fonts/FontAwesome.otf b/src/public/fonts/FontAwesome.otf new file mode 100644 index 0000000..d4de13e Binary files /dev/null and b/src/public/fonts/FontAwesome.otf differ diff --git a/src/public/fonts/fontawesome-webfont.eot b/src/public/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..c7b00d2 Binary files /dev/null and b/src/public/fonts/fontawesome-webfont.eot differ diff --git a/src/public/fonts/fontawesome-webfont.svg b/src/public/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..8b66187 --- /dev/null +++ b/src/public/fonts/fontawesome-webfont.svg @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/public/fonts/fontawesome-webfont.ttf b/src/public/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..f221e50 Binary files /dev/null and b/src/public/fonts/fontawesome-webfont.ttf differ diff --git a/src/public/fonts/fontawesome-webfont.woff b/src/public/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..6e7483c Binary files /dev/null and b/src/public/fonts/fontawesome-webfont.woff differ diff --git a/src/public/fonts/fontawesome-webfont.woff2 b/src/public/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..7eb74fd Binary files /dev/null and b/src/public/fonts/fontawesome-webfont.woff2 differ diff --git a/src/public/images/favicon.png b/src/public/images/favicon.png new file mode 100644 index 0000000..c0058e2 Binary files /dev/null and b/src/public/images/favicon.png differ diff --git a/src/public/js/lib/bootstrap.min.js b/src/public/js/lib/bootstrap.min.js new file mode 100644 index 0000000..9bcd2fc --- /dev/null +++ b/src/public/js/lib/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/src/public/js/lib/jquery-3.1.1.min.js b/src/public/js/lib/jquery-3.1.1.min.js new file mode 100644 index 0000000..5c82cc0 --- /dev/null +++ b/src/public/js/lib/jquery-3.1.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="
",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; +}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("