├── demo ├── favicon.ico ├── content │ └── img │ │ ├── ps-logo.png │ │ └── ractive-logo.png ├── scripts │ ├── release │ │ └── app.min.js.gz │ ├── vendor │ │ └── bootstrap │ │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── js │ │ │ ├── npm.js │ │ │ └── bootstrap.min.js │ │ │ └── css │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.css │ │ │ └── bootstrap-theme.css.map │ ├── app.purs │ └── ui │ │ └── Ractive │ │ ├── Ractive.purs │ │ └── Ractive.js ├── styles │ └── demo.css ├── index.js └── index.html ├── Tutorial.md ├── psc-package.json ├── bower.json ├── .gitignore ├── LICENSE ├── package.json ├── src └── Effect │ ├── Redux.purs │ └── Redux.js ├── README.md ├── Gulpfile.js ├── webpack.config.js ├── docs ├── Middleware.md └── Tutorial.md └── test └── Main.purs /demo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/favicon.ico -------------------------------------------------------------------------------- /Tutorial.md: -------------------------------------------------------------------------------- 1 | Moved to: Tutorial -------------------------------------------------------------------------------- /demo/content/img/ps-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/content/img/ps-logo.png -------------------------------------------------------------------------------- /demo/content/img/ractive-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/content/img/ractive-logo.png -------------------------------------------------------------------------------- /demo/scripts/release/app.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/scripts/release/app.min.js.gz -------------------------------------------------------------------------------- /demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/purescript-redux/HEAD/demo/scripts/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /psc-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-redux", 3 | "set": "psc-0.12.2", 4 | "source": "https://github.com/purescript/package-sets.git", 5 | "depends": [ 6 | "psci-support", 7 | "prelude" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /demo/styles/demo.css: -------------------------------------------------------------------------------- 1 | /* a few simple styles */ 2 | .app-panel { 3 | padding-top: 2em; 4 | padding-left: 5em; 5 | } 6 | 7 | .app-logo { 8 | position: relative; 9 | padding-left: 6.5em; 10 | } 11 | 12 | .component-footer { 13 | padding-left: 9em; 14 | } 15 | 16 | .ractive-logo { 17 | position: relative; 18 | padding-left: 12em; 19 | } -------------------------------------------------------------------------------- /demo/scripts/vendor/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-redux", 3 | "version": "0.1.5", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/brakmic/purescript-redux.git" 7 | }, 8 | "moduleType": [ 9 | "node" 10 | ], 11 | "keywords": [ 12 | "redux", 13 | "react", 14 | "purescript", 15 | "bindings" 16 | ], 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "output" 22 | ], 23 | "dependencies": { 24 | "purescript-prelude": "^4.1.0" 25 | }, 26 | "devDependencies": { 27 | "purescript-debug": "^4.0.0", 28 | "purescript-random": "^4.0.0", 29 | "purescript-console": "^4.2.0", 30 | "purescript-exceptions": "^4.0.0", 31 | "purescript-unsafe-coerce": "^4.0.0", 32 | "purescript-quickcheck": "^5.0.0" 33 | }, 34 | "license": "MIT" 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules 29 | 30 | /bower_components/ 31 | /.pulp-cache/ 32 | /output/ 33 | /.psci* 34 | /src/.webpack.js 35 | /dist/ 36 | 37 | # Optional npm cache directory 38 | .npm 39 | 40 | # Optional REPL history 41 | .node_repl_history 42 | 43 | # no pursuit.json 44 | pursuit.json 45 | 46 | # no psc-ide port 47 | .psc-ide-port 48 | 49 | .vscode/ 50 | 51 | /.psc-package/ 52 | /.psci_modules/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Harris Brakmic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var Hapi = require('hapi'); 3 | var path = require('path'); 4 | var server = new Hapi.Server(); 5 | var Inert = require('inert'); 6 | 7 | server.connection({ port: 8080 }); 8 | 9 | server.register(Inert, function () {}); 10 | 11 | server.route({ 12 | path: '/content/{filename*}', 13 | method: 'GET', 14 | handler: { 15 | directory: { 16 | path: 'demo/content', 17 | listing: false 18 | } 19 | } 20 | }); 21 | server.route({ 22 | path: '/styles/{filename*}', 23 | method: 'GET', 24 | handler: { 25 | directory: { 26 | path: 'demo/styles', 27 | listing: false 28 | } 29 | } 30 | }); 31 | server.route({ 32 | path: '/scripts/{filename*}', 33 | method: 'GET', 34 | handler: { 35 | directory: { 36 | path: 'demo/scripts', 37 | listing: false 38 | } 39 | } 40 | }); 41 | server.route({ 42 | path: '/{p*}', 43 | method: 'GET', 44 | handler: function(request, reply) { 45 | reply.file('demo/index.html'); 46 | } 47 | }); 48 | 49 | /* start server */ 50 | server.start(function() { 51 | console.log('Server running at:', server.info.uri); 52 | }); 53 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 29 | 30 | 31 | 32 | 33 |
48 |
49 | ### Running
50 |
51 | *NodeJS + Hapi*
52 | ```shell
53 | npm start
54 | ```
55 | *then open* http://localhost:8080
56 |
57 | ### Demo App
58 |
59 |
60 |
61 | ### Usage
62 |
63 | See the Tutorial.
64 |
65 | ### License
66 |
67 | MIT
68 |
--------------------------------------------------------------------------------
/Gulpfile.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var gulp = require('gulp');
3 | var run = require('gulp-run');
4 | var del = require('del');
5 | var changed = require('gulp-changed');
6 | var webpack = require('webpack-stream');
7 | var config = require('./webpack.config.js');
8 | var purescript = require('gulp-purescript');
9 | var projectRoot = __dirname + '/';
10 | var srcRoot = 'src/';
11 | var destRoot = 'dest/';
12 | var releaseRoot = 'demo/scripts/release';
13 |
14 | var sources = [
15 | "src/**/*.purs",
16 | "test/**/*.purs",
17 | "bower_components/purescript-*/src/**/*.purs",
18 | ];
19 |
20 | var foreigns = [
21 | "src/**/*.js",
22 | "bower_components/purescript-*/src/**/*.js"
23 | ];
24 |
25 | var demoSources = [
26 | "demo/scripts/**/*.purs",
27 | "src/**/*.purs",
28 | "bower_components/purescript-*/src/**/*.purs",
29 | ];
30 |
31 | var demoForeigns = [
32 | "src/**/*.js",
33 | "demo/scripts/ui/**/*.js",
34 | "bower_components/purescript-*/src/**/*.js"
35 | ];
36 |
37 | gulp.task('webpack', function() {
38 | return gulp.src('output/DemoApp.WithRedux/index.js')
39 | .pipe(webpack(config))
40 | .pipe(gulp.dest('./demo/scripts/release/'));
41 | });
42 |
43 | gulp.task("make", function () {
44 | return purescript.compile({ src: sources, ffi: foreigns });
45 | });
46 |
47 | gulp.task("make-demo", function () {
48 | return purescript.compile({ src: demoSources, ffi: demoForeigns });
49 | });
50 |
51 | gulp.task("bundle", ["make"], function () {
52 | return purescript.bundle({ src: "output/**/*.js", output: "dist/bundle.js" });
53 | });
54 |
55 | gulp.task("bundle-demo", ["make-demo"], function () {
56 | return purescript.bundle({ src: "output/DemoApp.WithRedux/**/*.js", output: "dist/demo/bundle.js" });
57 | });
58 |
59 | gulp.task("docs", function () {
60 | return purescript.docs({
61 | src: sources,
62 | docgen: {
63 | "Name.Of.Module1": "docs/Name/Of/Module1.md",
64 | "Name.Of.Module2": "docs/Name/Of/Module2.md"
65 | }
66 | });
67 | });
68 |
69 | gulp.task("dotpsci-demo", function () {
70 | return purescript.psci({ src: demoSources, ffi: demoForeigns })
71 | .pipe(gulp.dest("."));
72 | });
73 |
74 | gulp.task("dotpsci", function () {
75 | return purescript.psci({ src: sources, ffi: foreigns })
76 | .pipe(gulp.dest("."));
77 | });
78 |
79 | gulp.task('clean', function (cb) {
80 | del([releaseRoot + '**/*'], function (err, deletedFiles) {
81 | if(err){
82 | console.log('Error during deletion: ' + err);
83 | }
84 | });
85 | cb();
86 | });
87 |
88 | gulp.task("test", ["make"], function() {
89 | return purescript.bundle({ src: "output/**/*.js", main: "Test.Main" })
90 | .pipe(run("node"));
91 | });
92 |
93 |
94 | gulp.task("build-demo", ["bundle-demo", "dotpsci-demo","webpack"]);
95 | gulp.task("default", ["bundle", "dotpsci"]);
96 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var webpack = require('webpack');
3 | var AsyncUglifyJs = require("async-uglify-js-webpack-plugin");
4 | var path = require('path');
5 | var fs = require("fs");
6 | var CompressionPlugin = require('compression-webpack-plugin');
7 | var root = __dirname + '/';
8 | var npmRoot = root + 'node_modules/';
9 | var nodeScripts = root + 'node_modules/';
10 |
11 | var config = {
12 | cache: false,
13 | entry: {
14 | 'app': path.resolve(__dirname, 'output/DemoApp.WithRedux/index.js')
15 | },
16 | output: {
17 | path: path.resolve(__dirname, 'demo/scripts/release'),
18 | filename: '[name].min.js',
19 | sourceMapFilename: '[name].min.js.map',
20 | library: ['DemoApp','redux']
21 | },
22 | module: {
23 |
24 | loaders: [
25 | ]
26 | },
27 | resolve: {
28 | extensions: ['', '.js', '.es6', '.es6.js', '.jsx', '.json', '.ts', '.css', '.html', '.ract'],
29 | modulesDirectories: ['node_modules', 'bower_components','output'],
30 | alias: {
31 | }
32 | },
33 | plugins: [
34 | new CompressionPlugin({
35 | asset : '{file}.gz',
36 | algorithm : 'gzip',
37 | regExp : /\.js$|\.html$/,
38 | threshold : 10240,
39 | minRatio : 0.8
40 | }),
41 | new webpack.ProvidePlugin({
42 | 'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
43 | })
44 | ]
45 | };
46 | if (process.env.NODE_ENV === 'production') {
47 | config.plugins = config.plugins.concat([
48 | new webpack.DefinePlugin({
49 | 'process.env': {
50 | NODE_ENV: JSON.stringify('production')
51 | }
52 | }),
53 | new AsyncUglifyJs({
54 | delay: 5000,
55 | minifyOptions: {
56 | mangle: false,
57 | warnings: true,
58 | compress: {
59 | sequences : true, // join consecutive statemets with the “comma operator”
60 | properties : true, // optimize property access: a["foo"] → a.foo
61 | dead_code : true, // discard unreachable code
62 | drop_debugger : true, // discard “debugger” statements
63 | unsafe : false, // some unsafe optimizations (see below)
64 | conditionals : true, // optimize if-s and conditional expressions
65 | comparisons : true, // optimize comparisons
66 | evaluate : true, // evaluate constant expressions
67 | booleans : true, // optimize boolean expressions
68 | loops : true, // optimize loops
69 | unused : true, // drop unused variables/functions
70 | hoist_funs : true, // hoist function declarations
71 | hoist_vars : false, // hoist variable declarations
72 | if_return : true, // optimize if-s followed by return/continue
73 | join_vars : true, // join var declarations
74 | cascade : true, // try to cascade `right` into `left` in sequences
75 | side_effects : true, // drop side-effect-free statements
76 | warnings : true, // warn about potentially dangerous optimizations/code
77 | }
78 | },
79 | logger: false,
80 | done: function(path, originalContents) { }
81 | }),
82 | new webpack.optimize.DedupePlugin(),
83 | new webpack.optimize.OccurenceOrderPlugin(true)
84 | ]);
85 | } else {
86 | config.devtool = '#source-map';
87 | config.debug = true;
88 | }
89 |
90 | config.useMemoryFs = true;
91 | config.progress = true;
92 |
93 | module.exports = config;
--------------------------------------------------------------------------------
/docs/Middleware.md:
--------------------------------------------------------------------------------
1 | ## Writing Redux-Middleware in PureScript
2 |
3 | ## A simple Logger
4 |
5 | We will write a logger in PureScript that is similar to the one from the original Redux' middleware docs.
6 |
7 | It looks like this:
8 |
9 | ```haskell
10 | simpleLogger :: forall a e. Store ->
11 | (Next) ->
12 | { "type" :: String, "payload" :: String | a } ->
13 | Eff (
14 | reduxM :: ReduxM,
15 | console :: CONSOLE
16 | | e
17 | )
18 | { "type" :: String, "payload" :: String | a }
19 | simpleLogger = \store next action -> do
20 | log ("Middleware (Logger) :: Action: " <>
21 | action.type <> ", payload: " <>
22 | action.payload)
23 | (next action)
24 | ```
25 |
26 | It's a function that takes:
27 |
28 | - a `Store` (more precisely: a stripped-down of it comprising only of: `getState` & `dispatch`)
29 | - the `Next` dispatcher call from the chain
30 | - and an `Action` to be dispatched (it comprises of two mandatory fields: `type` & `payload`)
31 |
32 | This function does nothing exceptionally complex but one thing is mandatory for every middleware: calling `next` with the given `Action`,
33 | or in PureScript lingo: the application of `next` to `Action`. The return value will be yet another `dispatch` function which then will be executed by another middleware in the chain and so on until it reaches the end and the original Redux' `dispatch` gets called.
34 |
35 | This last dispatch call will activate a **chain reaction** so that every registered middleware will execute its own logic while the `action`s fly though Redux.
36 |
37 | ### Registering the Middleware
38 |
39 | The application one or more middlewares mandates the usage of `Store`-creation functions which are different from those we saw in the Tutorial.
40 |
41 | ```haskell
42 | -- | Create an array of middlewares
43 | let middlewares = [ (simpleLogger) ]
44 | -- | Initialize a Redux Store while building up a chain of middlewares
45 | store <- (applyMiddleware middlewares counter 1)
46 | ```
47 |
48 | We create an array of middlewares and call the `applyMiddleware` function which expects this array, a valid `dispatcher` and an optional `initial state`. Here we simply continue to usage
49 | our `counter` function from the Tutorial and give `1` as the initial value.
50 |
51 | The function `applyMiddleware` is a `foreign import` mapping to the original Redux' applyMiddleware.
52 |
53 | ```haskell
54 | foreign import applyMiddleware :: forall a b c d. Array a -> (b -> Action c d -> b) -> b -> ReduxEff Store
55 | ```
56 |
57 | As with the PureScript version the imported `applyMiddleware` expects an array of middlewares, a `dispatcher` and an optional `initial state`. It returns an *effectful* Store which is a stripped down version of the full Redux' Store API containing only `getState` & `dispatch`.
58 |
59 | ## Using the Middleware
60 |
61 | Now when we execute an `Action` our middleware-logger will get a change to hook into the processing chain and execute its own logic.
62 |
63 |
64 |
65 | ## Important notice
66 |
67 | The currently implemented mappings & logic for the Middleware API are highly experimental (and very buggy!).
68 |
69 | Therefore, please, consider it a moving target.
70 |
--------------------------------------------------------------------------------
/demo/scripts/app.purs:
--------------------------------------------------------------------------------
1 | module DemoApp.WithRedux where
2 |
3 | import Prelude (Unit, bind, unit, pure, discard, (-), (+), (<>))
4 | import Unsafe.Coerce (unsafeCoerce)
5 | import Effect (Effect)
6 | import Effect.Console (log)
7 | import Effect.Ractive (Data(Data), Ractive, get, on, ractive)
8 | import Effect.Redux (Next, Store, subscribe, applyMiddleware, getState, dispatch)
9 |
10 | -- | A simple reducer accepting two actions: INCREMENT, DECREMENT
11 | counter :: forall a. Int -> { "type" :: String | a } -> Int
12 | counter = \v t -> case t.type of
13 | "INCREMENT" -> v + 1
14 | "DECREMENT" -> v - 1
15 | _ -> v
16 |
17 | -- | Event handler for handling button clicks
18 | onIncrementClicked :: forall event.
19 | Ractive ->
20 | event ->
21 | Effect Unit
22 | onIncrementClicked = \r e -> do
23 | store <- (get "store" r)
24 | action <- (dispatch { "type" : "INCREMENT", payload: "TEST INCR" } store)
25 | pure unit
26 |
27 | -- | Event handler for handling button clicks
28 | onDecrementClicked :: forall event.
29 | Ractive ->
30 | event ->
31 | Effect Unit
32 | onDecrementClicked = \r e -> do
33 | store <- (get "store" r)
34 | action <- (dispatch { "type" : "DECREMENT", payload: "TEST DECR" } store)
35 | pure unit
36 |
37 | -- | A simple listener for displaying current state
38 | numericListener :: Store -> Effect Unit
39 | numericListener = \store -> do
40 | currentState <- (getState store)
41 | log ("STATE: " <> (unsafeCoerce currentState))
42 |
43 | -- | This is a middleware for logging
44 | -- | It receives a subset of the Store API (getState & dispatch) and processes `actions`
45 | simpleLogger :: forall a. Store ->
46 | (Next) ->
47 | { "type" :: String, "payload" :: String | a } ->
48 | Effect { "type" :: String, "payload" :: String | a }
49 | simpleLogger = \store next action -> do
50 | log ("Middleware (Logger) :: Action: " <>
51 | action.type <> ", payload: " <>
52 | action.payload)
53 | (next action)
54 |
55 | -- | The app starts here
56 | main :: Effect Unit
57 | main = do
58 | -- | Create an array of middlewares
59 | let middlewares = [ simpleLogger ]
60 | -- | Initialize a Redux Store while building up a chain of middlewares
61 | store <- (applyMiddleware middlewares counter 1)
62 |
63 | -- | ALTERNATIVE (without middleware)
64 | -- | Create a Redux Store by wiring up the `counter` Reducer and
65 | -- | the initial state `1`
66 | ---store <- (createStore counter 1)
67 |
68 | -- | Define UI's properties (RactiveJS)
69 | -- | Notice the presence of the property `store`. This is where we
70 | -- | save the reference to our Redux store. On each button click this
71 | -- | property will be used to change the app's state.
72 | let appSettings = Data {
73 | template : "#template",
74 | el : "#app",
75 | "data" : {
76 | library : "Redux",
77 | language : "PureScript",
78 | logoUrl : "./content/img/ps-logo.png",
79 | message : "Click on the PureScript Logo!",
80 | "store" : store,
81 | uiLib : "RactiveJS",
82 | counter : 0,
83 | numbers : []
84 | }
85 | }
86 | -- | Instantiate the UI
87 | ract <- ractive appSettings
88 |
89 | -- | Subscribe with listener `numericListener`
90 | (subscribe (numericListener store) store)
91 |
92 | -- Register event-handlers
93 | _ <- on "increment-clicked" (onIncrementClicked ract) ract
94 | _ <- on "decrement-clicked" (onDecrementClicked ract) ract
95 |
96 | log "Demo App with Redux!"
97 |
--------------------------------------------------------------------------------
/docs/Tutorial.md:
--------------------------------------------------------------------------------
1 | # Tutorial
2 |
3 | Apps using Redux maintain their whole state in an *object tree* inside a **single** store. To manipulate
4 | such states one has to emit `actions` which are plain JavaScript objects containg the `type` of
5 | the given action and optionally other properties, like `payload` etc.
6 |
7 | To register a store we use `createStore` and give it a `reducer` and an optional `state`
8 | as arguments.
9 |
10 | In the example below register a new store by using two arguments `counter` (the reducer)
11 | and `1` (the initial state)
12 |
13 | **Hint**: *PureScript doesn't have functions that take more than one argument! I'm using JavaScript terms here
14 | because Redux is written in JavaScript.*
15 |
16 | ```haskell
17 | store <- (createStore counter 1)
18 | ```
19 |
20 | A `reducer` is a function that takes a `state` and an `action` and returns a new `state`. This is
21 | how our reducer looks like. It's written as a `lambda` function (a `callback` in JS) which is always
22 | indicated with an `\` (it resembles the small greek lambda letter λ).
23 |
24 | ```haskell
25 | counter :: Int -> Action -> Int
26 | counter = \v t -> case t.type of
27 | "INCREMENT" -> v + 1
28 | "DECREMENT" -> v - 1
29 | _ -> v
30 | ```
31 |
32 | Redux' Actions are just plain POJOs.
33 |
34 | ```haskell
35 | { "type" : "INCREMENT", payload: "TEST INCR" }
36 | ```
37 |
38 | The definition is located in `src/Control/Monad/Eff/Redux/Redux.purs` together with our FFI imports.
39 |
40 | ```haskell
41 | type Action a = {
42 | "type" :: String
43 | | a
44 | }
45 | [...]
46 | foreign import createStore :: forall a b. (a -> Action b -> a) -> a -> ReduxEff Store
47 | foreign import subscribe :: forall e. (Eff e Unit) -> Store -> ReduxEff Unit
48 | foreign import dispatch :: forall a. Action a -> Store -> ReduxEff (Action a)
49 | foreign import getState :: forall a. Store -> ReduxEff a
50 | foreign import replaceReducer :: Reducer -> Store -> ReduxEff Unit
51 | ```
52 |
53 | We also want to be informed about any state changes. Therefore we define yet another callback called `numericListener`.
54 |
55 | ```haskell
56 | numericListener :: forall e. Store -> Eff (reduxM :: ReduxM, console :: CONSOLE | e) Unit
57 | numericListener = \store -> do
58 | currentState <- (getState store)
59 | log ("STATE: " <> (unsafeCoerce currentState))
60 | ```
61 |
62 | We register it by using Redux' `subscribe` function.
63 |
64 | ```haskell
65 | (subscribe (numericListener store) store)
66 | ```
67 |
68 | **Hint**: The argument `store` is used to *curry* the `numericListener` callback.
69 |
70 | And finally we register two event handlers to react to button clicks. Here we're using RactiveJS and
71 | its proxy events.
72 |
73 | *This is not mandatory as you can use any other UI-Library or Framework instead.*
74 |
75 | ```haskell
76 | on "increment-clicked" (onIncrementClicked ract) ract
77 | on "decrement-clicked" (onDecrementClicked ract) ract
78 | ```
79 |
80 | Our event handler functions have the same mechanics. Only their `action` types are different.
81 |
82 | First, we get our **store** reference from the RactiveJS component via `get "store"`. Then we use Redux'
83 | function `dispatch` to, well, *dispatch* a new action of type `INCREMENT`. Of course, we give it the
84 | `store` instance too.
85 |
86 | **Hint**: *PureScript natively supports JavaScript's objects.*
87 |
88 | That's why we can simply write **{ "type" : "INCREMENT" }** *without any extra calls or conversions. Just use the good old POJOs.* :smile:
89 |
90 | ```haskell
91 | onIncrementClicked = \r e -> do
92 | store <- (get "store" r)
93 | log "DISPATCH: INCREMENT"
94 | action <- (dispatch { "type" : "INCREMENT", payload: "TEST INCR" } store)
95 | pure unit
96 | ```
97 |
98 | This is how the demo app works.
99 |
100 | Basically, it's a combination of a *predictable container* (Redux) with *real* pure functions and hostility towards any side-effects (PureScript).
101 |
--------------------------------------------------------------------------------
/demo/scripts/ui/Ractive/Ractive.purs:
--------------------------------------------------------------------------------
1 | module Effect.Ractive where
2 |
3 | import Prelude (Unit)
4 | import Effect (Effect)
5 | import Data.Maybe (Maybe)
6 | import Data.Function.Uncurried (Fn1, Fn2, Fn3, runFn1, runFn2, runFn3)
7 |
8 | data Data a b = Data {
9 | template :: String,
10 | "data" :: { | a}
11 | |
12 | b -- optional properties like "components", "partials", "el" etc.
13 | }
14 |
15 | type Event = {
16 | node :: DOMNode,
17 | original :: DOMEvent,
18 | keypath :: String,
19 | context :: {
20 | name :: String
21 | }
22 | }
23 |
24 | type ObserverEventData a b = {
25 | newValue :: a,
26 | oldValue :: b,
27 | keyPath :: String
28 | }
29 |
30 | type RactiveEventCallback = forall a. Ractive -> Event -> Effect a
31 |
32 | type RactiveObserverCallback = forall a b c. a -> b -> String -> Effect c
33 |
34 | type ObserverOptions = {
35 | init :: Boolean,
36 | defer :: Boolean,
37 | context :: Ractive
38 | }
39 |
40 | -- findComponents API params
41 |
42 | type FindAllOptions = {
43 | live :: Boolean
44 | }
45 |
46 | type FindAllComponentsOptions = {
47 | live :: Boolean
48 | }
49 |
50 | -- end of findComponents API params
51 |
52 | -- animate API params
53 |
54 | type StepFunction = forall t value. t -> value -> Effect Unit
55 |
56 | type CompleteFunction = forall t value. t -> value -> Effect Unit
57 |
58 | type EasingFunction = forall t value. t -> value -> Effect Unit
59 |
60 | data EasingParam = String | AnimateEasingFunction
61 |
62 | type AnimateOptions = {
63 | duration :: Number,
64 | easing :: Easing,
65 | step :: StepFunction,
66 | complete :: CompleteFunction
67 | }
68 |
69 | -- end of anima API params
70 |
71 | data RenderQuery = RQString String | RQNode DOMNode
72 |
73 | foreign import data DOMEvent :: Type
74 |
75 | foreign import data DOMNode :: Type
76 |
77 | foreign import data RactiveM :: Type
78 |
79 | foreign import data Ractive :: Type
80 |
81 | foreign import data Text :: Type
82 |
83 | foreign import data Element :: Type
84 |
85 | foreign import data Cancellable :: Type
86 |
87 | foreign import data Easing :: Type
88 |
89 | -- | Foreign Imports
90 |
91 | foreign import ractive :: forall a b. Data a b -> Effect Ractive
92 | foreign import extend :: forall a b. Data a b -> Effect Ractive
93 |
94 | foreign import on :: forall a. String -> (Event -> Effect a) -> Ractive -> Effect Cancellable
95 | foreign import off :: Maybe String -> Maybe RactiveEventCallback -> Ractive -> Effect Ractive
96 |
97 | foreign import get :: forall a. String -> Ractive -> Effect a
98 | foreign import set :: forall a. String -> a -> Ractive -> Effect Unit
99 |
100 | foreign import push :: forall a b. String -> a -> Maybe (b -> (Effect Unit)) -> Ractive -> Effect Unit
101 | foreign import pop :: forall a. String -> Maybe (a -> (Effect Unit)) -> Ractive -> Effect Unit
102 |
103 | foreign import observe :: forall a b. String -> (a -> b -> String -> (Effect Unit)) -> Maybe ObserverOptions -> Ractive -> Effect Cancellable
104 | foreign import observeOnce :: forall a b. String -> (a -> b -> String -> (Effect Unit)) -> Maybe ObserverOptions -> Ractive -> Effect Cancellable
105 |
106 | foreign import find :: String -> Ractive -> Effect DOMNode
107 | foreign import findAll :: String -> Maybe FindAllOptions -> Ractive -> Effect (Array DOMNode)
108 |
109 | foreign import findComponent :: String -> Ractive -> Effect Ractive
110 | foreign import findAllComponents :: String -> Maybe FindAllComponentsOptions -> Ractive -> Effect (Array Ractive)
111 |
112 | foreign import add :: forall a. String -> Maybe Number -> Maybe (Ractive -> Effect a) -> Ractive -> Effect Unit
113 | foreign import subtract :: forall a. String -> Maybe Number -> Maybe (Ractive -> Effect a) -> Ractive -> Effect Unit
114 |
115 | foreign import animate :: forall a. String -> a -> Maybe AnimateOptions -> Ractive -> Effect Unit
116 |
117 | foreign import ractiveFromDataImpl :: forall a b. Fn1 (Data a b) (Effect Ractive)
118 |
119 | foreign import setPartialImpl :: Fn3 String String Ractive (Effect Unit)
120 |
121 | foreign import getPartialImpl :: Fn2 String Ractive (Effect String)
122 |
123 | foreign import updateModelImpl :: Fn1 Ractive (Effect Unit)
124 |
125 | foreign import renderByIdImpl :: Fn2 String Ractive (Effect Unit)
126 |
127 | -- | End Foreign Imports
128 |
129 | ractiveFromData :: forall a b. Data a b -> Effect Ractive
130 | ractiveFromData = runFn1 ractiveFromDataImpl
131 |
132 | setPartial :: String -> String -> Ractive -> Effect Unit
133 | setPartial = runFn3 setPartialImpl
134 |
135 | getPartial :: String -> Ractive -> Effect String
136 | getPartial = runFn2 getPartialImpl
137 |
138 | updateModel :: Ractive -> Effect Unit
139 | updateModel = runFn1 updateModelImpl
140 |
141 | renderById :: String -> Ractive -> Effect Unit
142 | renderById = runFn2 renderByIdImpl
143 |
--------------------------------------------------------------------------------
/src/Effect/Redux.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var Redux = require('redux');
4 | var createStoreInternal = Redux.createStore;
5 | var applyMiddlewareInternal = Redux.applyMiddleware;
6 | var combineReducersInternal = Redux.combineReducers;
7 |
8 | //`createStore` needs a 2-parameter, pure function for creating a new store.
9 | //The `initialState` can be used to 'rehydrate' the client state.
10 | var _createStore = function(reducer){
11 | return function(initialState){
12 | return function(){
13 | var _reducer = extractReducer(reducer);
14 | var store = createStoreInternal(_reducer, initialState);
15 | return store;
16 | };
17 | };
18 | };
19 |
20 | //To get information about state changes via registered `listeners`.
21 | //http://redux.js.org/docs/api/Store.html#subscribe
22 | var _subscribe = function(callback){
23 | return function(store){
24 | return function(){
25 | store.subscribe(callback);
26 | return {};
27 | };
28 | };
29 | };
30 |
31 | //Dispatches an action. A Redux-based app never changes its state directly but
32 | //instead via so-called `actions` / `action creators`
33 | //http://redux.js.org/docs/api/Store.html#dispatch
34 | var _dispatch = function(action){
35 | return function(store){
36 | return function(){
37 | var act = {};
38 | if(action){
39 | if(action.value0){
40 | act = store.dispatch(action.value0);
41 | }else{
42 | act = store.dispatch(action);
43 | }
44 | }
45 | return act;
46 | };
47 | };
48 | }
49 |
50 | //Returns the current state
51 | //http://redux.js.org/docs/api/Store.html#getState
52 | var _getState = function(store){
53 | return function(){
54 | var s = store.getState();
55 | return s;
56 | };
57 | };
58 |
59 | //For replacing the current reducer.
60 | //http://redux.js.org/docs/api/Store.html#replaceReducer
61 | var _replaceReducer = function(store){
62 | return function(nextReducer){
63 | return function(){
64 | var _nextReducer = extractReducer(nextReducer);
65 | store.replaceReducer(_nextReducer);
66 | };
67 | };
68 | };
69 | //For injecting 3rd-party extensions between dispatch and reducer.
70 | //http://redux.js.org/docs/advanced/Middleware.html
71 | var _applyMiddleware = function(middlewares){
72 | var all = [],
73 | store;
74 | return function(reducer){
75 | return function(initialState){
76 | return function(){
77 | for (var i = 0; i < middlewares.length; ++i) {
78 | all.push(extractMiddleware(middlewares[i]));
79 | }
80 | store = createStoreInternal(extractReducer(reducer), initialState, applyMiddlewareInternal.apply(null, all));
81 | return store;
82 | };
83 | };
84 | };
85 | };
86 | //For combining separate `reducing functions` int one reducer
87 | //http://redux.js.org/docs/api/combineReducers.html
88 | var combineReducers = function(reducers){
89 | return function(){
90 | var combined = combineReducersInternal(reducers);
91 | return combined;
92 | };
93 | };
94 |
95 | //** TODO **
96 | var bindActionCreators = function(){
97 | return {};
98 | };
99 |
100 | var compose = function(){
101 | return {};
102 | };
103 | //**TODO**
104 |
105 | //INTERNALS
106 |
107 | var extractReducer = function(reducer){
108 | return function(a, b) {
109 | return reducer(a)(b)
110 | }
111 | };
112 | //The `next` call is the dispatcher call and by default PureScript puts an additional ()-call after
113 | //its completion (this is how PureScript wrapps effects from JS side). To maintain this extra call
114 | //on the JS side we wrap the original next(action)-call into an additional function call.
115 | var wrapNextDispatch = function(next){
116 | return function(action){
117 | return function(){
118 | next(action);
119 | };
120 | };
121 | };
122 | //---------------------------- EXPERIMENTAL -------------------------------------------
123 | //Create a complete middleware function chain so redux can properly register it.
124 | //There are three interleaved functions calls: store=>next=>action
125 | //The `store` is not a complete store but a shrinked version of it containing only: getState & dispatch
126 | //The `next` is the next dispatch call in the hierarchy
127 | //The `action` is the next action to be dispatched by the current `next` dispatcher
128 | var extractMiddleware = function(middleware){
129 | return function(store){
130 | return function(next){
131 | return function(action){
132 | var nxt = wrapNextDispatch(next);
133 | return middleware(store)(nxt)(action)();
134 | }
135 | };
136 | };
137 | };
138 | //-------------------------- END OF EXPERIMENTAL ---------------------------------------
139 |
140 | //END OF INTERNALS
141 |
142 | module.exports = {
143 | createStore : _createStore,
144 | subscribe : _subscribe,
145 | dispatch : _dispatch,
146 | getState : _getState,
147 | replaceReducer : _replaceReducer,
148 | combineReducers : combineReducers,
149 | applyMiddleware : _applyMiddleware
150 | };
151 |
--------------------------------------------------------------------------------
/test/Main.purs:
--------------------------------------------------------------------------------
1 | module Test.Main where
2 |
3 | import Prelude
4 | import Test.QuickCheck (quickCheck, (===))
5 | import Unsafe.Coerce (unsafeCoerce)
6 | import Effect (Effect)
7 | import Effect.Redux (Store, Next, applyMiddleware, combineReducers, getState, dispatch)
8 | import Debug.Trace (traceM)
9 |
10 | -- | A simple reducer reacting to two actions: INCREMENT, DECREMENT
11 | counter :: forall a. Int ->
12 | { "type" :: String
13 | , "payload" :: String
14 | | a } -> Int
15 | counter = \v t -> case t.type of
16 | "INCREMENT" -> v + 1
17 | "DECREMENT" -> v - 1
18 | _ -> v
19 |
20 | -- | Additional redeucer to test combineReducer() API
21 | counterSquared :: forall a. Int ->
22 | { "type" :: String
23 | , "payload" :: String
24 | | a } -> Int
25 | counterSquared = \v t -> case t.type of
26 | "SQUARE_INC" -> v + (v * v)
27 | "SQUARE_DEC" -> v - (v * v)
28 | _ -> v
29 |
30 | -- | Additional redeucer to test combineReducer() API
31 | counterDoubled :: forall a. Int ->
32 | { "type" :: String
33 | , "payload" :: String
34 | | a } -> Int
35 | counterDoubled = \v t -> case t.type of
36 | "DOUBLE_INC" -> v + (v * 2)
37 | "DOUBLE_DEC" -> v - (v * 2)
38 | _ -> v
39 |
40 | -- | This is a middleware for logging
41 | -- | It receives a subset of the Store API (getState & dispatch) and processes `actions`
42 | simpleLogger :: forall a. Store ->
43 | (Next) ->
44 | { "type" :: String, "payload" :: String | a } ->
45 | Effect { "type" :: String, "payload" :: String | a }
46 | simpleLogger = \store next action -> do
47 | traceM $ "Middleware (Logger) :: Action: " <>
48 | action.type <> ", payload: " <>
49 | action.payload
50 | (next action)
51 |
52 | -- | A simple listener for displaying current state
53 | numericListener :: Store -> Effect Unit
54 | numericListener = \store -> do
55 | currentState <- (getState store)
56 | traceM $ "STATE: " <> (unsafeCoerce currentState)
57 |
58 | -- | Wrapper for testing the 'counter'-reducer
59 | testReducer :: forall a. Int ->
60 | { "type" :: String
61 | , "payload" :: String
62 | | a } -> Boolean
63 | testReducer v a = (counter v a) /= v
64 |
65 | -- | Wrapper for testing the 'square counter'-reducer
66 | testSquareReducer :: forall a. Int ->
67 | { "type" :: String
68 | , "payload" :: String
69 | | a } -> Boolean
70 | testSquareReducer v a = (counterSquared v a) /= v
71 |
72 | -- | Wrapper for testing the 'double counter'-reducer
73 | testDoubleReducer :: forall a. Int ->
74 | { "type" :: String
75 | , "payload" :: String
76 | | a } -> Boolean
77 | testDoubleReducer v a = (counterDoubled v a) /= v
78 |
79 | -- | Test middleware by sending actions which lead to state chages
80 | testMiddleware :: Int -> Store -> Effect Unit
81 | testMiddleware v store = do
82 | actInc <- (dispatch { "type" : "INCREMENT", payload: v} store)
83 | currentState <- (getState store)
84 | traceM $ "STATE: " <> currentState
85 | actDec <- (dispatch { "type" : "DECREMENT", payload: v} store)
86 | currentState2 <- (getState store)
87 | traceM $ "STATE: " <> currentState2
88 | pure unit
89 |
90 | main :: Effect Unit
91 | main = do
92 | -- | Preparation
93 | --let reducers = [ counterDoubled, counterSquared ]
94 | let middlewares = [ simpleLogger ]
95 | let increment = { "type" : "INCREMENT", "payload" : "VALUE_INCR" }
96 | let decrement = { "type" : "DECREMENT", "payload" : "VALUE_DECR" }
97 | let squareInc = { "type" : "SQUARE_INC", "payload" : "VALUE_SQUARE_INC" }
98 | let squareDec = { "type" : "SQUARE_DEC", "payload" : "VALUE_SQUARE_DEC" }
99 | let doubleInc = { "type" : "DOUBLE_INC", "payload" : "VALUE_DOUBLE_DEC" }
100 | let doubleDec = { "type" : "DOUBLE_DEC", "payload" : "VALUE_DOUBLE_DEC" }
101 |
102 | traceM "\r\n[TESTING] combineReducers()"
103 | let combined = (combineReducers [ counterDoubled, counterSquared ])
104 |
105 | traceM "\r\n[TESTING] applyMiddleware()"
106 | -- | Try to init a new container with middleware
107 | store <- (applyMiddleware middlewares counter 1)
108 | -- | Test reducer
109 | traceM "\r\n[TESTING] reducer (+1 INC and DEC)"
110 | quickCheck \n -> (testReducer n increment) === true
111 | quickCheck \n -> (testReducer n decrement) === true
112 | traceM "\r\n[TESTING] square reducer (^2 INC and DEC)"
113 | quickCheck \n -> (testSquareReducer n squareInc) === true
114 | quickCheck \n -> (testSquareReducer n squareDec) === true
115 | traceM "\r\n[TESTING] double reducer (*2 INC and DEC)"
116 | quickCheck \n -> (testDoubleReducer n doubleInc) === true
117 | quickCheck \n -> (testDoubleReducer n doubleDec) === true
118 |
119 | traceM "\r\n[TESTING] middleware"
120 | -- | Test middleware
121 | (testMiddleware 1 store)
122 |
--------------------------------------------------------------------------------
/demo/scripts/ui/Ractive/Ractive.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // module Control.Monad.Eff.Ractive
4 |
5 | var Ractive = require('ractive');
6 |
7 | //-- an ugly helper function for wiring up of callbacks
8 | // used in push/pop APIs
9 | var createCallback = function(api, callback){
10 | var cb = null;
11 | if(callback &&
12 | callback.constructor &&
13 | callback.constructor.name == 'Nothing'){
14 | cb = function(ignore){
15 | var ignr = ignore.then(function(){
16 | return {};
17 | }).catch(function(error){
18 | console.log(api + ' failed, error: ' + error);
19 | });
20 | var ret = function(){
21 | return ignr;
22 | };
23 | return ret;
24 | };
25 | } else {
26 | cb = function(val){
27 | return function(){
28 | val.then(function(v){
29 | callback.value0(v)();
30 | }).catch(function(err){
31 | console.log(err);
32 | });
33 | return {};
34 | }
35 | };
36 | }
37 | return cb;
38 | };
39 | // -- end of ugly helper function
40 |
41 | // -- extract Ractive component settings
42 |
43 | var extractSettings = function(settings){
44 | return settings.value0;
45 | }
46 |
47 | // -- end of extract Ractive component settings
48 |
49 | var observe = function(selector){
50 | return function(handler){
51 | return function(options){
52 | if(options.constructor &&
53 | options.constructor.name == 'Just'){
54 | options = options.value0;
55 | } else if(options.constructor &&
56 | options.constructor.name == 'Nothing'){
57 | options = null;
58 | }
59 | return function(ractive){
60 | return function(){
61 | var cancellable = null;
62 | if(options){
63 | cancellable = ractive.observe(selector, function(n,o,kp){
64 | return handler(n)(o)(kp)(this);
65 | }, options);
66 | }else{
67 | cancellable = ractive.observe(selector, function(n,o,kp){
68 | return handler(n)(o)(kp)(this);
69 | });
70 | }
71 | return cancellable;
72 | };
73 | };
74 | };
75 | };
76 | };
77 |
78 | var observeOnce = function(selector){
79 | return function(handler){
80 | return function(options){
81 | if(options.constructor &&
82 | options.constructor.name == 'Just'){
83 | options = options.value0;
84 | } else if(options.constructor &&
85 | options.constructor.name == 'Nothing'){
86 | options = null;
87 | }
88 | return function(ractive){
89 | return function(){
90 | var cancellable = null;
91 | if(options){
92 | cancellable = ractive.observeOnce(selector, function(n,o,kp){
93 | return handler(n)(o)(kp)(this);
94 | }, options);
95 | }else{
96 | cancellable = ractive.observeOnce(selector, function(n,o,kp){
97 | return handler(n)(o)(kp)(this);
98 | });
99 | }
100 | return cancellable;
101 | };
102 | };
103 | };
104 | };
105 | }
106 |
107 | var get = function(selector){
108 | return function(ractive){
109 | return function(){
110 | var data = ractive.get(selector);
111 | return data;
112 | };
113 | };
114 | };
115 |
116 | var set = function(selector) {
117 | return function(value) {
118 | return function(ractive) {
119 | return function () {
120 | ractive.set(selector, value);
121 | return {};
122 | };
123 | };
124 | };
125 | };
126 |
127 | var on = function(event) {
128 | return function(handler) {
129 | return function(ractive) {
130 | return function() {
131 | var cancellable = ractive.on(event, function(ev){
132 | return handler(ev)(this);
133 | });
134 | return cancellable;
135 | };
136 | };
137 | };
138 | };
139 |
140 | var off = function(event){
141 | return function(handler){
142 | return function(ractive){
143 | return function(){
144 | var chainable = null;
145 | if(event.constructor &&
146 | event.constructor.name == 'Just'){
147 | chainable = ractive.off(event.value0);
148 | }else if(event.constructor &&
149 | event.constructor.name == 'Nothing'){
150 | chainable = ractive.off();
151 | }else{
152 | chainable = ractive.off(event.value0,handler.constructor());
153 | }
154 | return chainable;
155 | };
156 | };
157 | };
158 | };
159 |
160 | var push = function(keypath){
161 | return function(value){
162 | return function(callback){
163 | var cb = createCallback('push', callback);
164 | return function(ractive){
165 | return function(){
166 | var ok = ractive.push(keypath, value).then(function(v){
167 | // console.log('push, ractive promise: ' + v);
168 | }).catch(function(err){
169 | console.log('push failed, error: ' + err);
170 | });
171 | cb(ok)();
172 | return {};
173 | };
174 | };
175 | };
176 | };
177 | };
178 |
179 | var pop = function(keypath){
180 | return function(callback){
181 | var cb = createCallback('pop', callback);
182 | return function(ractive){
183 | return function(){
184 | var ok = ractive.pop(keypath).then(function(r){
185 | return r;
186 | }).catch(function(err){
187 | console.log('pop failed, error: ' + err);
188 | });
189 | cb(ok)();
190 | return {};
191 | };
192 | };
193 | };
194 | };
195 |
196 | var find = function(selector){
197 | return function(ractive){
198 | return function(){
199 | var node = ractive.find(selector);
200 | return node;
201 | };
202 | };
203 | };
204 |
205 | var findAll = function(selector){
206 | return function(options){
207 | return function(ractive){
208 | return function(){
209 | var elements = null;
210 | if(options &&
211 | options.constructor &&
212 | options.constructor.name == 'Nothing'){
213 | elements = ractive.findAll(selector);
214 | }else{
215 | elements = ractive.findAll(selector, options.value0);
216 | }
217 | return elements;
218 | };
219 | };
220 | };
221 | };
222 |
223 | var add = function(keypath){
224 | return function(number){
225 | var num = 1;
226 | if(number &&
227 | number.constructor &&
228 | number.constructor.name != 'Nothing'){
229 | num = number.value0;
230 | }
231 | return function(callback){
232 | var cb = createCallback('add', callback);
233 | return function(ractive){
234 | return function(){
235 | var ok = ractive.add(keypath, num).then(function(r){
236 | return r;
237 | }).catch(function(err){
238 | console.log('add failed, error: ' + err);
239 | });
240 | cb(ok)();
241 | return {};
242 | };
243 | };
244 | };
245 | };
246 | };
247 |
248 | var subtract = function(keypath){
249 | return function(number){
250 | var num = 1;
251 | if(number &&
252 | number.constructor &&
253 | number.constructor.name != 'Nothing'){
254 | num = number.value0;
255 | }
256 | return function(callback){
257 | var cb = createCallback('subtract', callback);
258 | return function(ractive){
259 | return function(){
260 | var ok = ractive.subtract(keypath, num).then(function(r){
261 | return r;
262 | }).catch(function(err){
263 | console.log('subtract failed, error: ' + err);
264 | });
265 | cb(ok)();
266 | return {};
267 | };
268 | };
269 | };
270 | };
271 | };
272 |
273 | var findComponent = function(name){
274 | return function(ractive){
275 | return function(){
276 | var component = ractive.findComponent(name);
277 | return component;
278 | }
279 | };
280 | };
281 |
282 | var findAllComponents = function(name){
283 | return function(options){
284 | if(options &&
285 | options.constructor &&
286 | options.constructor.name == 'Nothing'){
287 | options = null;
288 | }else{
289 | options = options.value0;
290 | }
291 | return function(ractive){
292 | return function(){
293 | var allComponents = null;
294 | if(options){
295 | allComponents = ractive.findAllComponents(name, options);
296 | }else{
297 | allComponents = ractive.find(name);
298 | }
299 | return allComponents;
300 | };
301 | };
302 | };
303 | };
304 |
305 | var animate = function(keypath){
306 | return function(value){
307 | return function(options){
308 | return function(ractive){
309 | return function(){
310 | if(options &&
311 | options.constructor &&
312 | options.constructor.name != 'Nothing'){
313 | ractive.animate(keypath,value,options).then(function(){
314 |
315 | }).catch(function(err){
316 | console.log('animate failed, error: ' + err);
317 | });
318 | }else{
319 | ractive.animate(keypath, value).then(function(){
320 |
321 | }).catch(function(err){
322 | console.log('animate failed, error: ' + err);
323 | });
324 | }
325 | return {};
326 | };
327 | };
328 | };
329 | };
330 | };
331 |
332 | var ractive = function(settings){
333 | return function(){
334 | var s = extractSettings(settings);
335 | return new Ractive(s);
336 | };
337 | };
338 |
339 | var extend = function(settings){
340 | return function(){
341 | var s = extractSettings(settings);
342 | var r = Ractive.extend(s);
343 | return r;
344 | };
345 | }
346 |
347 | var ractiveFromDataImpl = function(data) {
348 | return new Ractive(data);
349 | }
350 |
351 | var setPartialImpl = function(selector, value, ractive) {
352 | ractive.partials[selector] = value;
353 | }
354 |
355 | var getPartialImpl = function(selector, ractive) {
356 | return ractive.partials[selector];
357 | }
358 |
359 | var updateModelImpl = function(ractive) {
360 | ractive.updateModel();
361 | }
362 |
363 | var renderByIdImpl = function(id, ractive) {
364 | ractive.render(id);
365 | }
366 |
367 | module.exports = {
368 | get : get,
369 | set : set,
370 | on : on,
371 | off : off,
372 | push : push,
373 | pop : pop,
374 | observe : observe,
375 | observeOnce : observeOnce,
376 | find : find,
377 | findAll : findAll,
378 | findComponent : findComponent,
379 | findAllComponents : findAllComponents,
380 | add : add,
381 | subtract : subtract,
382 | ractive : ractive,
383 | ractiveFromDataImpl : ractiveFromDataImpl,
384 | setPartialImpl : setPartialImpl,
385 | getPartialImpl : getPartialImpl,
386 | renderByIdImpl : renderByIdImpl,
387 | updateModelImpl : updateModelImpl,
388 | extend : extend,
389 | animate : animate
390 | }
391 |
--------------------------------------------------------------------------------
/demo/scripts/vendor/bootstrap/css/bootstrap-theme.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.4 (http://getbootstrap.com)
3 | * Copyright 2011-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary:disabled,.btn-primary[disabled]{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
--------------------------------------------------------------------------------
/demo/scripts/vendor/bootstrap/css/bootstrap-theme.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.4 (http://getbootstrap.com)
3 | * Copyright 2011-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | .btn-default,
8 | .btn-primary,
9 | .btn-success,
10 | .btn-info,
11 | .btn-warning,
12 | .btn-danger {
13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
16 | }
17 | .btn-default:active,
18 | .btn-primary:active,
19 | .btn-success:active,
20 | .btn-info:active,
21 | .btn-warning:active,
22 | .btn-danger:active,
23 | .btn-default.active,
24 | .btn-primary.active,
25 | .btn-success.active,
26 | .btn-info.active,
27 | .btn-warning.active,
28 | .btn-danger.active {
29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
31 | }
32 | .btn-default .badge,
33 | .btn-primary .badge,
34 | .btn-success .badge,
35 | .btn-info .badge,
36 | .btn-warning .badge,
37 | .btn-danger .badge {
38 | text-shadow: none;
39 | }
40 | .btn:active,
41 | .btn.active {
42 | background-image: none;
43 | }
44 | .btn-default {
45 | text-shadow: 0 1px 0 #fff;
46 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
47 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
48 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
49 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
50 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
51 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
52 | background-repeat: repeat-x;
53 | border-color: #dbdbdb;
54 | border-color: #ccc;
55 | }
56 | .btn-default:hover,
57 | .btn-default:focus {
58 | background-color: #e0e0e0;
59 | background-position: 0 -15px;
60 | }
61 | .btn-default:active,
62 | .btn-default.active {
63 | background-color: #e0e0e0;
64 | border-color: #dbdbdb;
65 | }
66 | .btn-default.disabled,
67 | .btn-default:disabled,
68 | .btn-default[disabled] {
69 | background-color: #e0e0e0;
70 | background-image: none;
71 | }
72 | .btn-primary {
73 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
74 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
75 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
76 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
77 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
78 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
79 | background-repeat: repeat-x;
80 | border-color: #245580;
81 | }
82 | .btn-primary:hover,
83 | .btn-primary:focus {
84 | background-color: #265a88;
85 | background-position: 0 -15px;
86 | }
87 | .btn-primary:active,
88 | .btn-primary.active {
89 | background-color: #265a88;
90 | border-color: #245580;
91 | }
92 | .btn-primary.disabled,
93 | .btn-primary:disabled,
94 | .btn-primary[disabled] {
95 | background-color: #265a88;
96 | background-image: none;
97 | }
98 | .btn-success {
99 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
100 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
101 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
102 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
103 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
104 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
105 | background-repeat: repeat-x;
106 | border-color: #3e8f3e;
107 | }
108 | .btn-success:hover,
109 | .btn-success:focus {
110 | background-color: #419641;
111 | background-position: 0 -15px;
112 | }
113 | .btn-success:active,
114 | .btn-success.active {
115 | background-color: #419641;
116 | border-color: #3e8f3e;
117 | }
118 | .btn-success.disabled,
119 | .btn-success:disabled,
120 | .btn-success[disabled] {
121 | background-color: #419641;
122 | background-image: none;
123 | }
124 | .btn-info {
125 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
126 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
127 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
128 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
129 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
130 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
131 | background-repeat: repeat-x;
132 | border-color: #28a4c9;
133 | }
134 | .btn-info:hover,
135 | .btn-info:focus {
136 | background-color: #2aabd2;
137 | background-position: 0 -15px;
138 | }
139 | .btn-info:active,
140 | .btn-info.active {
141 | background-color: #2aabd2;
142 | border-color: #28a4c9;
143 | }
144 | .btn-info.disabled,
145 | .btn-info:disabled,
146 | .btn-info[disabled] {
147 | background-color: #2aabd2;
148 | background-image: none;
149 | }
150 | .btn-warning {
151 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
152 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
153 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
154 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
155 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
156 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
157 | background-repeat: repeat-x;
158 | border-color: #e38d13;
159 | }
160 | .btn-warning:hover,
161 | .btn-warning:focus {
162 | background-color: #eb9316;
163 | background-position: 0 -15px;
164 | }
165 | .btn-warning:active,
166 | .btn-warning.active {
167 | background-color: #eb9316;
168 | border-color: #e38d13;
169 | }
170 | .btn-warning.disabled,
171 | .btn-warning:disabled,
172 | .btn-warning[disabled] {
173 | background-color: #eb9316;
174 | background-image: none;
175 | }
176 | .btn-danger {
177 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
178 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
179 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
180 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
181 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
182 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
183 | background-repeat: repeat-x;
184 | border-color: #b92c28;
185 | }
186 | .btn-danger:hover,
187 | .btn-danger:focus {
188 | background-color: #c12e2a;
189 | background-position: 0 -15px;
190 | }
191 | .btn-danger:active,
192 | .btn-danger.active {
193 | background-color: #c12e2a;
194 | border-color: #b92c28;
195 | }
196 | .btn-danger.disabled,
197 | .btn-danger:disabled,
198 | .btn-danger[disabled] {
199 | background-color: #c12e2a;
200 | background-image: none;
201 | }
202 | .thumbnail,
203 | .img-thumbnail {
204 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
205 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
206 | }
207 | .dropdown-menu > li > a:hover,
208 | .dropdown-menu > li > a:focus {
209 | background-color: #e8e8e8;
210 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
211 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
212 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
213 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
214 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
215 | background-repeat: repeat-x;
216 | }
217 | .dropdown-menu > .active > a,
218 | .dropdown-menu > .active > a:hover,
219 | .dropdown-menu > .active > a:focus {
220 | background-color: #2e6da4;
221 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
222 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
223 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
224 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
225 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
226 | background-repeat: repeat-x;
227 | }
228 | .navbar-default {
229 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
230 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
231 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
232 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
233 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
234 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
235 | background-repeat: repeat-x;
236 | border-radius: 4px;
237 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
238 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
239 | }
240 | .navbar-default .navbar-nav > .open > a,
241 | .navbar-default .navbar-nav > .active > a {
242 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
243 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
244 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
245 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
246 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
247 | background-repeat: repeat-x;
248 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
249 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
250 | }
251 | .navbar-brand,
252 | .navbar-nav > li > a {
253 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
254 | }
255 | .navbar-inverse {
256 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
257 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
258 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
259 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
260 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
261 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
262 | background-repeat: repeat-x;
263 | }
264 | .navbar-inverse .navbar-nav > .open > a,
265 | .navbar-inverse .navbar-nav > .active > a {
266 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
267 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
268 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
269 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
270 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
271 | background-repeat: repeat-x;
272 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
273 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
274 | }
275 | .navbar-inverse .navbar-brand,
276 | .navbar-inverse .navbar-nav > li > a {
277 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
278 | }
279 | .navbar-static-top,
280 | .navbar-fixed-top,
281 | .navbar-fixed-bottom {
282 | border-radius: 0;
283 | }
284 | @media (max-width: 767px) {
285 | .navbar .navbar-nav .open .dropdown-menu > .active > a,
286 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
287 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
288 | color: #fff;
289 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
290 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
291 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
292 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
293 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
294 | background-repeat: repeat-x;
295 | }
296 | }
297 | .alert {
298 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
299 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
300 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
301 | }
302 | .alert-success {
303 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
304 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
305 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
306 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
307 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
308 | background-repeat: repeat-x;
309 | border-color: #b2dba1;
310 | }
311 | .alert-info {
312 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
313 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
314 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
315 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
316 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
317 | background-repeat: repeat-x;
318 | border-color: #9acfea;
319 | }
320 | .alert-warning {
321 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
322 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
323 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
324 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
325 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
326 | background-repeat: repeat-x;
327 | border-color: #f5e79e;
328 | }
329 | .alert-danger {
330 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
331 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
332 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
333 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
334 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
335 | background-repeat: repeat-x;
336 | border-color: #dca7a7;
337 | }
338 | .progress {
339 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
340 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
342 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
344 | background-repeat: repeat-x;
345 | }
346 | .progress-bar {
347 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
348 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
349 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
350 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
351 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
352 | background-repeat: repeat-x;
353 | }
354 | .progress-bar-success {
355 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
356 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
357 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
358 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
359 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
360 | background-repeat: repeat-x;
361 | }
362 | .progress-bar-info {
363 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
364 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
365 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
366 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
367 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
368 | background-repeat: repeat-x;
369 | }
370 | .progress-bar-warning {
371 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
372 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
374 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
376 | background-repeat: repeat-x;
377 | }
378 | .progress-bar-danger {
379 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
380 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
381 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
382 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
383 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
384 | background-repeat: repeat-x;
385 | }
386 | .progress-bar-striped {
387 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
388 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
389 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
390 | }
391 | .list-group {
392 | border-radius: 4px;
393 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
394 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
395 | }
396 | .list-group-item.active,
397 | .list-group-item.active:hover,
398 | .list-group-item.active:focus {
399 | text-shadow: 0 -1px 0 #286090;
400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
405 | background-repeat: repeat-x;
406 | border-color: #2b669a;
407 | }
408 | .list-group-item.active .badge,
409 | .list-group-item.active:hover .badge,
410 | .list-group-item.active:focus .badge {
411 | text-shadow: none;
412 | }
413 | .panel {
414 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
415 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
416 | }
417 | .panel-default > .panel-heading {
418 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
419 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
420 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
421 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
422 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
423 | background-repeat: repeat-x;
424 | }
425 | .panel-primary > .panel-heading {
426 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
427 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
428 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
429 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
430 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
431 | background-repeat: repeat-x;
432 | }
433 | .panel-success > .panel-heading {
434 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
435 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
436 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
437 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
438 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
439 | background-repeat: repeat-x;
440 | }
441 | .panel-info > .panel-heading {
442 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
443 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
444 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
445 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
446 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
447 | background-repeat: repeat-x;
448 | }
449 | .panel-warning > .panel-heading {
450 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
451 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
453 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
455 | background-repeat: repeat-x;
456 | }
457 | .panel-danger > .panel-heading {
458 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
459 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
461 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
463 | background-repeat: repeat-x;
464 | }
465 | .well {
466 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
467 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
469 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
471 | background-repeat: repeat-x;
472 | border-color: #dcdcdc;
473 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
474 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
475 | }
476 | /*# sourceMappingURL=bootstrap-theme.css.map */
477 |
--------------------------------------------------------------------------------
/demo/scripts/vendor/bootstrap/js/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.4 (http://getbootstrap.com)
3 | * Copyright 2011-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 | 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)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(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){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(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.4",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);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.4",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)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},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")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&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);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).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.4",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"));return a>this.$items.length-1||0>a?void 0: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(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0: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.4",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){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(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 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.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b);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("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27|32)/.test(b.which)&&!/input|textarea/i.test(b.target.tagName)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g&&27!=b.which||g&&27==b.which)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(b.target);38==b.which&&j>0&&j--,40==b.which&&j