├── .editorconfig ├── .gitignore ├── .jscsrc ├── README.md ├── assets ├── css │ ├── main.css │ └── uikit.almost-flat.min.css └── images │ ├── ipad-mini.png │ ├── react.png │ ├── sucker.png │ └── t-shirt.png ├── flux.tgz ├── js ├── actions │ └── ActionCreators.js ├── alt.js ├── api │ ├── products.json │ └── shop.js ├── boot.js ├── components │ ├── App.jsx │ ├── Cart.jsx │ ├── CartContainer.jsx │ ├── ProductDetail.jsx │ ├── ProductItem.jsx │ ├── ProductItemContainer.jsx │ ├── ProductsContainer.jsx │ └── ProductsList.jsx ├── flux.js ├── routing.js ├── stores │ ├── CartStore.js │ ├── ProductStore.js │ └── RouteStore.js └── utils │ └── WebAPIUtils.js ├── npm-shrinkwrap.json ├── package.json ├── server.js └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [package.json] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.md] 16 | trim_trailing_whitespace = true 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 27 | node_modules 28 | 29 | # Build Directory 30 | build 31 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "jquery", 3 | "esprima": "esprima-fb", 4 | "fileExtensions": [ 5 | ".js", 6 | ".jsx" 7 | ], 8 | "excludeFiles": [ 9 | "node_modules/**", 10 | "Dropbox/**", 11 | "lib/**", 12 | ".jscsrc/**", 13 | "data/**", 14 | "package/**", 15 | "shared/**" 16 | ], 17 | "esnext": true, 18 | "validateQuoteMarks": "'", 19 | "maximumLineLength": { 20 | "value": 120, 21 | "tabSize": 4, 22 | "allExcept": ["urlComments", "regex"] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | isomorphic-react-with-alt 3 | ========================= 4 | 5 | [](https://gitter.im/coodoo/react-alt-isomorphic-example?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | ## Preface 8 | 9 | This is an example showcasing how to build isomorphic react application with [`Alt`](https://github.com/goatslacker/alt) which utilizes the same codebase on both server and browser and able to correctly handle multiple requests at one time. 10 | 11 | Feel free to [ask questions](https://github.com/coodoo/react-alt-isomorphic-example/issues), [chat](https://gitter.im/coodoo/react-alt-isomorphic-example?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) or send over pull requests. 12 | 13 | ## Features Highlights 14 | 15 | There are already a bunch of isomorphic examples out there, what's special about this one? 16 | 17 | - it showcased __client-side routing__ using normal flux `store` (see `RouteStore.js`) 18 | 19 | - it reuses data-fetching logics, no need to dupe them on the server and trying to keep both in sync in the future 20 | 21 | - it uses `Alt` in a multiple-instance way instead of singleton, which is easier to maintain in the long run 22 | 23 | - it's implementation is extremely simple and easy to understand 24 | 25 | ## Why Isomorphic 26 | 27 | - shorter time-to-first page for better user experience 28 | 29 | - deep linking for better usability (ie: bookmarking) 30 | 31 | - SEO 32 | 33 | 34 | ## Goals 35 | 36 | - reuse same codebase on both browser and server without any modification 37 | 38 | - must be able to handle multiple requests on the server at the same time without polluting each other's data stores 39 | 40 | - the approach must be easily understandable and simple to develop and maintain 41 | 42 | - applicable to both isomorphic or browser-only applications 43 | 44 | ## Key problems solved with this approach 45 | 46 | - how to handle multiple requests at the same time since 47 | - flux store is singleton 48 | - data-fetching is async 49 | 50 | - reuse router and routing table on both ends 51 | 52 | - passing same data between browser and server to save a round trip 53 | 54 | 55 | 56 | ## Why Alt 57 | 58 | - it adheres to original flux implementation 59 | 60 | - it adds just enough abstractions to avoid boilerplate code (ie: constants) 61 | 62 | - it has nice auto-mappings between `actionCreators` and `stores` which saves time 63 | 64 | - it supports isomorphic out of the box, with both `singleton` and `multi-instance` stores 65 | 66 | - it provides `Iso` util to help with data marshalling 67 | 68 | - in short, it provides a nice balance between __simplicity and efficiency__, which helps developer to do more and faster 69 | 70 | ## How to run the sample 71 | 72 | ``` 73 | $ npm install --global babel 74 | $ npm install 75 | $ npm start 76 | ``` 77 | 78 | ## 5000ft overview 79 | 80 | Here's a 5000ft view of how a web application works on the server. 81 | 82 | When a request hits the server, we figure out what data it needs, fetch those, feed them to react app, let the app populates all stores and renders the views, when it's all done we invoke `React.renderToString` to get a html string which can be returned to the client request. 83 | 84 | One key goal here is we want to use the same codebase on both server and browser, without any modification. 85 | 86 | 87 | ## Server 88 | 89 | - see `./server.js` 90 | 91 | - although we are using `Express` here, you are free to use `koa` or any other stacks, as long as it supports javascript 92 | 93 | - index.html 94 | 95 | - notice there's no physical `index` file 96 | 97 | - index page is concatenated on the fly from `template strings` because there are variables needed to be replaced 98 | 99 | - routing 100 | 101 | - in order to avoid writing routing rules twice on both server and browser, we share the routing table (a file with plain old javascript inside) on both ends 102 | 103 | - when `server.js` first run, it reads in the routing table and create routing rules using `express router` 104 | 105 | - one added benefit of doing it this way is we get to handle `404` pages on the server, instead of delegating everything blindly to the client's router using a `catch all` rule 106 | 107 | - handling requests 108 | 109 | - when a request hits the server, it will trigger one of the routing rule defined earlier 110 | 111 | - then our app will create a new instance of `flux` which contains standalone `actionCreators` and `stores` 112 | 113 | - each request is handled by a standalone `flux` hence no two requests can interfere with each other 114 | 115 | - then it passes in the requesting url to `RouteStore` and let it fetch the data needed and do the following job inside, by doing so we just need to write data fetching logic once and use it on both sides 116 | 117 | - one thing to note is `RouteStore` returns a `promise` so that we know when react app finishes it's work inside and it's safe for us to invoke `React.renderToString` to generate the final html strings 118 | 119 | - once we get the rendered html string, we augments it with special tags and serialize fetched data with the help from `Iso` (an utility provided by `Alt` which serialize and de-serialize data on both ends) 120 | 121 | - eventually we return the rendered string to the client, completes the request and respond cycle 122 | 123 | ## Client 124 | 125 | - `flux` instance on the client side 126 | 127 | - see `flux.js` 128 | 129 | - as mentioned earlier in [Server](#server) section, we create a new `flux` instance for every incoming request to handle `actionCreators` and `stores`, we do the same on the client side by creating one `flux` instance to hold data and boot the app 130 | 131 | - inside each `flux` object it contains a standalone set of `actionCreators` and `stores` needed by the react app 132 | 133 | - this way we make sure data won't be mixed between different `stores`, hence ensuring user's privacy and security 134 | 135 | - `flux.js` handles all the heavy lifting for us, we just need to add in all needed `actionCreators` and `stores` there 136 | 137 | - one important thing to note though, we need to add `actionCreators` first so that it can be accessed later by `stores` 138 | 139 | - Booting the app 140 | 141 | - all boot scripts lives inside `boot.js`, it's the entry point to our app 142 | 143 | - just like on the server, we create a new instance of `flux` first 144 | 145 | - then restore the app states with `Iso.bootstrap()` which de-serialize data passed from server and populate the client app's `stores` 146 | 147 | 148 | - once `stores` are populated and ready, we kick start the react app by rendering it's root component along with the `flux` instance created earlier 149 | 150 | ```js 151 | React.render( React.createElement(App, {flux: flux}), container); 152 | ``` 153 | 154 | - the benefit of doing so is we get to reuse data fetched by the server in the browser, hence saving an extra API call from client to the server to fetch those data again 155 | 156 | - About the `Store` 157 | 158 | - each `store` module exposes a `class` definition by 159 | 160 | ```js 161 | module.exports = ProductStore; 162 | ``` 163 | 164 | - Unlike non-isomorphic alt implementation, which exposes a `store` instance by 165 | 166 | ```js 167 | module.exports = alt.createStore(ProductStore, 'ProductStore');` 168 | ``` 169 | 170 | - if you need to access `actionCreators` inside the stores, you can do that by: 171 | 172 | ```js 173 | ActionCreators = this.alt.getActions('ActionCreators'); 174 | ``` 175 | 176 | normally we do that once inside the `store`'s constructor and keep the reference for later use 177 | 178 | - `this.alt` is the `flux` instance we created earlier inside `flux.js`, remember that? 179 | 180 | - About the view 181 | 182 | - remember when kicking start the react app, we passed in the `flux` instance which contains all `actionCreators` and `stores` needed through out the entire app? 183 | 184 | - We need to pass that `flux` instance down to all react components so that they can access `actionCreators` and `stores` 185 | 186 | - we use an undocumented react feature called `context` to help passing down the object (just be rest assured that `context` will [stick around](https://goo.gl/W5yJbd) and it's safe to use) 187 | 188 | - in order to utilize `context`, we need to declare some variables in our root view, see `js/app.js` 189 | 190 | ```js 191 | 192 | childContextTypes: { 193 | flux: React.PropTypes.object.isRequired 194 | }, 195 | 196 | getChildContext: function() { 197 | return { flux: this.props.flux || new Error('flux not found!') }; 198 | }, 199 | 200 | ``` 201 | 202 | - then in child components, we access that piece of information from the root view like this: 203 | 204 | ```js 205 | componentWillMount() { 206 | // retrieve the flux instance passed down from root view and keep the reference 207 | flux = this.context.flux; 208 | 209 | // then we get hold of actionCreators and stores needed in this child component 210 | ActionCreators = flux.getActions('ActionCreators'); 211 | 212 | ProductStore = flux.getStore('ProductStore'); 213 | } 214 | ``` 215 | 216 | - we demonstrated writing react components in both `ES5` (`ProductItemContainer.js) and `ES6` (`ProductsContainer.js`), there are minor syntax and code structure differences you need to pay attention to 217 | 218 | - About the router 219 | 220 | - We showcased a complete client-side routing solution too 221 | 222 | - the design goal here is to treat routing just like any other `Stores`, and make sure it's cleanly decoupled from the view 223 | 224 | - `RouteStore` provides client-side routing capabilities 225 | 226 | - it encapsulate `page.js` as the inner router (which can be swap out anytime) 227 | 228 | - provides a set of APIs (public methods) which can be invoked on both server and browser 229 | 230 | - drives the app via routing rules and handlers 231 | 232 | 233 | - Notice client-side routing rules are initialized inside a `setTimeout` call and it only gets run when in a browser environment 234 | 235 | - In short, we don't intend to directly reuse the same router on both server and browser, instead we share the routing table to avoid duped work 236 | 237 | 238 | ## FAQ 239 | 240 | - why avoid using react-router? 241 | 242 | IMHO __router should not be tightly coupled with the view in any regard__, wrapping it in a `RouteStore` is more flexible and decoupled, also we get to switch out different routers in the future (we used `page.js` in this example, but we tried a bunch of other routers which all worked pretty well) 243 | 244 | - is this battle-tested? 245 | 246 | Yes, it's currently in production for some of the sites we are running 247 | 248 | - need help? 249 | 250 | - First try the `github issue` section 251 | 252 | - Second, ask in the [chat room](https://gitter.im/coodoo/react-alt-isomorphic-example) 253 | 254 | - Lastly, shoot me an [email](jeremy@pubulous.com) 255 | 256 | ## Notice 257 | 258 | - currently we are depending on a custom-built `flux dispatcher` using `npm-shrinkwrap.json` due to the version available on npm is outdated, once that's updated to the latest one we will remove the dependency. 259 | 260 | ## License 261 | 262 | MIT 263 | -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | .shop-wrap { 2 | max-width: 900px; 3 | width: 60%; 4 | margin: 20px 25px; 5 | } 6 | .cart { 7 | position: fixed; 8 | right: 50px; 9 | top: 30px; 10 | } 11 | -------------------------------------------------------------------------------- /assets/css/uikit.almost-flat.min.css: -------------------------------------------------------------------------------- 1 | /*! UIkit 2.16.2 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */ 2 | html{font:400 14px / 20px "Helvetica Neue",Helvetica,Arial,sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;background:#fff;color:#444}body{margin:0}a{background:0 0}a:active,a:hover{outline:0}.uk-link,a{color:#07d;text-decoration:none;cursor:pointer}.uk-link:hover,a:hover{color:#059;text-decoration:underline}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}:not(pre)>code,:not(pre)>kbd,:not(pre)>samp{font-size:12px;font-family:Consolas,monospace,serif;color:#d05;white-space:nowrap;padding:0 4px;border:1px solid #ddd;border-radius:3px;background:#fafafa}em{color:#d05}ins{background:#ffa;color:#444;text-decoration:none}mark{background:#ffa;color:#444}q{font-style:italic}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{max-width:100%;height:auto;-moz-box-sizing:border-box;box-sizing:border-box;border:0;vertical-align:middle}.uk-img-preserve,.uk-img-preserve img{max-width:none}svg:not(:root){overflow:hidden}address,blockquote,dl,fieldset,figure,ol,p,pre,ul{margin:0 0 15px}*+address,*+blockquote,*+dl,*+fieldset,*+figure,*+ol,*+p,*+pre,*+ul{margin-top:15px}h1,h2,h3,h4,h5,h6{margin:0 0 15px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;color:#444;text-transform:none}*+h1,*+h2,*+h3,*+h4,*+h5,*+h6{margin-top:25px}.uk-h1,h1{font-size:36px;line-height:42px}.uk-h2,h2{font-size:24px;line-height:30px}.uk-h3,h3{font-size:18px;line-height:24px}.uk-h4,h4{font-size:16px;line-height:22px}.uk-h5,h5{font-size:14px;line-height:20px}.uk-h6,h6{font-size:12px;line-height:18px}ol,ul{padding-left:30px}ol>li>ol,ol>li>ul,ul>li>ol,ul>li>ul{margin:0}dt{font-weight:700}dd{margin-left:0}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;margin:15px 0;border:0;border-top:1px solid #ddd}address{font-style:normal}blockquote{padding-left:15px;border-left:5px solid #ddd;font-size:16px;line-height:22px;font-style:italic}pre{padding:10px;background:#fafafa;font:12px / 18px Consolas,monospace,serif;color:#444;-moz-tab-size:4;tab-size:4;overflow:auto;border:1px solid #ddd;border-radius:3px}::-moz-selection{background:#39f;color:#fff;text-shadow:none}::selection{background:#39f;color:#fff;text-shadow:none}article,aside,details,figcaption,figure,footer,header,main,nav,section,summary{display:block}progress{vertical-align:baseline}[hidden],audio:not([controls]),template{display:none}iframe{border:0}@media screen and (max-width:400px){@-ms-viewport{width:device-width}}.uk-grid{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin:0 0 0 -25px;padding:0;list-style:none}.uk-grid:after,.uk-grid:before{content:"";display:block;overflow:hidden}.uk-grid:after{clear:both}.uk-grid>*{-ms-flex:none;-webkit-flex:none;flex:none;margin:0;padding-left:25px;float:left}.uk-grid>*>:last-child{margin-bottom:0}.uk-grid+.uk-grid,.uk-grid>*>.uk-panel+.uk-panel,.uk-grid>.uk-grid-margin{margin-top:25px}@media (min-width:1220px){.uk-grid:not(.uk-grid-preserve){margin-left:-35px}.uk-grid:not(.uk-grid-preserve)>*{padding-left:35px}.uk-grid:not(.uk-grid-preserve)+.uk-grid,.uk-grid:not(.uk-grid-preserve)>*>.uk-panel+.uk-panel,.uk-grid:not(.uk-grid-preserve)>.uk-grid-margin{margin-top:35px}}.uk-grid.uk-grid-small{margin-left:-10px}.uk-grid.uk-grid-small>*{padding-left:10px}.uk-grid.uk-grid-small+.uk-grid-small,.uk-grid.uk-grid-small>*>.uk-panel+.uk-panel,.uk-grid.uk-grid-small>.uk-grid-margin{margin-top:10px}.uk-grid-divider:not(:empty){margin-left:-25px;margin-right:-25px}.uk-grid-divider>*{padding-left:25px;padding-right:25px}.uk-grid-divider>[class*=uk-width-1-]:not(.uk-width-1-1):nth-child(n+2),.uk-grid-divider>[class*=uk-width-2-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-3-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-4-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-5-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-6-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-7-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-8-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-9-]:nth-child(n+2){border-left:1px solid #ddd}@media (min-width:768px){.uk-grid-divider>[class*=uk-width-medium-]:not(.uk-width-medium-1-1):nth-child(n+2){border-left:1px solid #ddd}}@media (min-width:960px){.uk-grid-divider>[class*=uk-width-large-]:not(.uk-width-large-1-1):nth-child(n+2){border-left:1px solid #ddd}}@media (min-width:1220px){.uk-grid-divider:not(.uk-grid-preserve):not(:empty){margin-left:-35px;margin-right:-35px}.uk-grid-divider:not(.uk-grid-preserve)>*{padding-left:35px;padding-right:35px}.uk-grid-divider:not(.uk-grid-preserve):empty{margin-top:35px;margin-bottom:35px}}.uk-grid-divider:empty{margin-top:25px;margin-bottom:25px;border-top:1px solid #ddd}.uk-grid-match>*{display:-ms-flexbox;display:-webkit-flex;display:flex}.uk-grid-match>*>*{-ms-flex:none;-webkit-flex:none;flex:none;-moz-box-sizing:border-box;box-sizing:border-box;width:100%}[class*=uk-grid-width]>*{-moz-box-sizing:border-box;box-sizing:border-box;width:100%}.uk-grid-width-1-2>*{width:50%}.uk-grid-width-1-3>*{width:33.333%}.uk-grid-width-1-4>*{width:25%}.uk-grid-width-1-5>*{width:20%}.uk-grid-width-1-6>*{width:16.666%}.uk-grid-width-1-10>*{width:10%}@media (min-width:480px){.uk-grid-width-small-1-2>*{width:50%}.uk-grid-width-small-1-3>*{width:33.333%}.uk-grid-width-small-1-4>*{width:25%}.uk-grid-width-small-1-5>*{width:20%}.uk-grid-width-small-1-6>*{width:16.666%}.uk-grid-width-small-1-10>*{width:10%}}@media (min-width:768px){.uk-grid-width-medium-1-2>*{width:50%}.uk-grid-width-medium-1-3>*{width:33.333%}.uk-grid-width-medium-1-4>*{width:25%}.uk-grid-width-medium-1-5>*{width:20%}.uk-grid-width-medium-1-6>*{width:16.666%}.uk-grid-width-medium-1-10>*{width:10%}}@media (min-width:960px){.uk-grid-width-large-1-2>*{width:50%}.uk-grid-width-large-1-3>*{width:33.333%}.uk-grid-width-large-1-4>*{width:25%}.uk-grid-width-large-1-5>*{width:20%}.uk-grid-width-large-1-6>*{width:16.666%}.uk-grid-width-large-1-10>*{width:10%}}@media (min-width:1220px){.uk-grid-width-xlarge-1-2>*{width:50%}.uk-grid-width-xlarge-1-3>*{width:33.333%}.uk-grid-width-xlarge-1-4>*{width:25%}.uk-grid-width-xlarge-1-5>*{width:20%}.uk-grid-width-xlarge-1-6>*{width:16.666%}.uk-grid-width-xlarge-1-10>*{width:10%}}[class*=uk-width]{-moz-box-sizing:border-box;box-sizing:border-box;width:100%}.uk-width-1-1{width:100%}.uk-width-1-2,.uk-width-2-4,.uk-width-3-6,.uk-width-5-10{width:50%}.uk-width-1-3,.uk-width-2-6{width:33.333%}.uk-width-2-3,.uk-width-4-6{width:66.666%}.uk-width-1-4{width:25%}.uk-width-3-4{width:75%}.uk-width-1-5,.uk-width-2-10{width:20%}.uk-width-2-5,.uk-width-4-10{width:40%}.uk-width-3-5,.uk-width-6-10{width:60%}.uk-width-4-5,.uk-width-8-10{width:80%}.uk-width-1-6{width:16.666%}.uk-width-5-6{width:83.333%}.uk-width-1-10{width:10%}.uk-width-3-10{width:30%}.uk-width-7-10{width:70%}.uk-width-9-10{width:90%}@media (min-width:480px){.uk-width-small-1-1{width:100%}.uk-width-small-1-2,.uk-width-small-2-4,.uk-width-small-3-6,.uk-width-small-5-10{width:50%}.uk-width-small-1-3,.uk-width-small-2-6{width:33.333%}.uk-width-small-2-3,.uk-width-small-4-6{width:66.666%}.uk-width-small-1-4{width:25%}.uk-width-small-3-4{width:75%}.uk-width-small-1-5,.uk-width-small-2-10{width:20%}.uk-width-small-2-5,.uk-width-small-4-10{width:40%}.uk-width-small-3-5,.uk-width-small-6-10{width:60%}.uk-width-small-4-5,.uk-width-small-8-10{width:80%}.uk-width-small-1-6{width:16.666%}.uk-width-small-5-6{width:83.333%}.uk-width-small-1-10{width:10%}.uk-width-small-3-10{width:30%}.uk-width-small-7-10{width:70%}.uk-width-small-9-10{width:90%}}@media (min-width:768px){.uk-width-medium-1-1{width:100%}.uk-width-medium-1-2,.uk-width-medium-2-4,.uk-width-medium-3-6,.uk-width-medium-5-10{width:50%}.uk-width-medium-1-3,.uk-width-medium-2-6{width:33.333%}.uk-width-medium-2-3,.uk-width-medium-4-6{width:66.666%}.uk-width-medium-1-4{width:25%}.uk-width-medium-3-4{width:75%}.uk-width-medium-1-5,.uk-width-medium-2-10{width:20%}.uk-width-medium-2-5,.uk-width-medium-4-10{width:40%}.uk-width-medium-3-5,.uk-width-medium-6-10{width:60%}.uk-width-medium-4-5,.uk-width-medium-8-10{width:80%}.uk-width-medium-1-6{width:16.666%}.uk-width-medium-5-6{width:83.333%}.uk-width-medium-1-10{width:10%}.uk-width-medium-3-10{width:30%}.uk-width-medium-7-10{width:70%}.uk-width-medium-9-10{width:90%}}@media (min-width:960px){.uk-width-large-1-1{width:100%}.uk-width-large-1-2,.uk-width-large-2-4,.uk-width-large-3-6,.uk-width-large-5-10{width:50%}.uk-width-large-1-3,.uk-width-large-2-6{width:33.333%}.uk-width-large-2-3,.uk-width-large-4-6{width:66.666%}.uk-width-large-1-4{width:25%}.uk-width-large-3-4{width:75%}.uk-width-large-1-5,.uk-width-large-2-10{width:20%}.uk-width-large-2-5,.uk-width-large-4-10{width:40%}.uk-width-large-3-5,.uk-width-large-6-10{width:60%}.uk-width-large-4-5,.uk-width-large-8-10{width:80%}.uk-width-large-1-6{width:16.666%}.uk-width-large-5-6{width:83.333%}.uk-width-large-1-10{width:10%}.uk-width-large-3-10{width:30%}.uk-width-large-7-10{width:70%}.uk-width-large-9-10{width:90%}}@media (min-width:768px){[class*=uk-pull-],[class*=uk-push-]{position:relative}.uk-push-1-2,.uk-push-2-4,.uk-push-3-6,.uk-push-5-10{left:50%}.uk-push-1-3,.uk-push-2-6{left:33.333%}.uk-push-2-3,.uk-push-4-6{left:66.666%}.uk-push-1-4{left:25%}.uk-push-3-4{left:75%}.uk-push-1-5,.uk-push-2-10{left:20%}.uk-push-2-5,.uk-push-4-10{left:40%}.uk-push-3-5,.uk-push-6-10{left:60%}.uk-push-4-5,.uk-push-8-10{left:80%}.uk-push-1-6{left:16.666%}.uk-push-5-6{left:83.333%}.uk-push-1-10{left:10%}.uk-push-3-10{left:30%}.uk-push-7-10{left:70%}.uk-push-9-10{left:90%}.uk-pull-1-2,.uk-pull-2-4,.uk-pull-3-6,.uk-pull-5-10{left:-50%}.uk-pull-1-3,.uk-pull-2-6{left:-33.333%}.uk-pull-2-3,.uk-pull-4-6{left:-66.666%}.uk-pull-1-4{left:-25%}.uk-pull-3-4{left:-75%}.uk-pull-1-5,.uk-pull-2-10{left:-20%}.uk-pull-2-5,.uk-pull-4-10{left:-40%}.uk-pull-3-5,.uk-pull-6-10{left:-60%}.uk-pull-4-5,.uk-pull-8-10{left:-80%}.uk-pull-1-6{left:-16.666%}.uk-pull-5-6{left:-83.333%}.uk-pull-1-10{left:-10%}.uk-pull-3-10{left:-30%}.uk-pull-7-10{left:-70%}.uk-pull-9-10{left:-90%}}.uk-panel{display:block;position:relative}.uk-panel,a.uk-panel:hover{color:inherit;text-decoration:none}.uk-panel:after,.uk-panel:before{content:"";display:table}.uk-panel:after{clear:both}.uk-panel>:not(.uk-panel-title):last-child{margin-bottom:0}.uk-panel-title{margin-top:0;margin-bottom:15px;font-size:18px;line-height:24px;font-weight:400;text-transform:none;color:#444}.uk-panel-badge{position:absolute;top:0;right:0;z-index:1}.uk-panel-box{padding:15px;background:#fafafa;color:#444;border:1px solid #ddd;border-radius:4px}.uk-panel-box .uk-panel-title,a.uk-panel-box:hover{color:#444}.uk-panel-box .uk-panel-badge{top:10px;right:10px}.uk-panel-box .uk-panel-teaser{margin:-16px -16px 15px}.uk-panel-box>.uk-nav-side{margin:0 -15px}.uk-panel-box-primary{background-color:#ebf7fd;color:#2d7091;border-color:rgba(45,112,145,.3)}.uk-panel-box-primary .uk-panel-title,a.uk-panel-box-primary:hover{color:#2d7091}.uk-panel-box-secondary{background-color:#fff;color:#444}.uk-panel-box-secondary .uk-panel-title,a.uk-panel-box-secondary:hover{color:#444}.uk-panel-hover{padding:15px;border:1px solid transparent;border-radius:4px}.uk-panel-hover:hover{background:#fafafa;color:#444;border-color:#ddd}.uk-panel-hover .uk-panel-badge{top:10px;right:10px}.uk-panel-hover .uk-panel-teaser{margin:-16px -16px 15px}.uk-panel-header .uk-panel-title{padding-bottom:10px;border-bottom:1px solid #ddd;color:#444}.uk-panel-space{padding:30px}.uk-panel-space .uk-panel-badge{top:30px;right:30px}.uk-panel+.uk-panel-divider{margin-top:50px!important}.uk-panel+.uk-panel-divider:before{content:"";display:block;position:absolute;top:-25px;left:0;right:0;border-top:1px solid #ddd}@media (min-width:1220px){.uk-panel+.uk-panel-divider{margin-top:70px!important}.uk-panel+.uk-panel-divider:before{top:-35px}}.uk-panel-box .uk-panel-teaser{border-top-left-radius:4px;border-top-right-radius:4px;overflow:hidden}.uk-article:after,.uk-article:before{content:"";display:table}.uk-article:after{clear:both}.uk-article>:last-child{margin-bottom:0}.uk-article+.uk-article{margin-top:25px}.uk-article-title{font-size:36px;line-height:42px;font-weight:400;text-transform:none}.uk-article-title a{color:inherit;text-decoration:none}.uk-article-meta{font-size:12px;line-height:18px;color:#999}.uk-article-lead{color:#444;font-size:18px;line-height:24px;font-weight:400}.uk-article-divider{margin-bottom:25px;border-color:#ddd}*+.uk-article-divider{margin-top:25px}.uk-article+.uk-article{padding-top:25px;border-top:1px solid #ddd}.uk-comment-header{margin-bottom:15px;padding:10px;border:1px solid #ddd;border-radius:4px;background:#fafafa}.uk-comment-header:after,.uk-comment-header:before{content:"";display:table}.uk-comment-header:after{clear:both}.uk-comment-avatar{margin-right:15px;float:left}.uk-comment-title{margin:5px 0 0;font-size:16px;line-height:22px}.uk-comment-meta{margin:2px 0 0;font-size:11px;line-height:16px;color:#999}.uk-comment-body{padding-left:10px;padding-right:10px}.uk-comment-body>:last-child{margin-bottom:0}.uk-comment-list{padding:0;list-style:none}.uk-comment-list .uk-comment+ul{margin:25px 0 0;list-style:none}.uk-comment-list .uk-comment+ul>li:nth-child(n+2),.uk-comment-list>li:nth-child(n+2){margin-top:25px}@media (min-width:768px){.uk-comment-list .uk-comment+ul{padding-left:100px}}.uk-comment-primary .uk-comment-header{border-color:rgba(45,112,145,.3);background-color:#ebf7fd;color:#2d7091;text-shadow:0 1px 0 #fff}.uk-nav,.uk-nav ul{margin:0;padding:0;list-style:none}.uk-nav li>a{display:block;text-decoration:none}.uk-nav>li>a{padding:5px 15px}.uk-nav ul{padding-left:15px}.uk-nav ul a{padding:2px 0}.uk-nav li>a>div{font-size:12px;line-height:18px}.uk-nav-header{padding:5px 15px;text-transform:uppercase;font-weight:700;font-size:12px}.uk-nav-header:not(:first-child){margin-top:15px}.uk-nav-divider{margin:9px 15px}ul.uk-nav-sub{padding:5px 0 5px 15px}.uk-nav-parent-icon>.uk-parent>a:after{content:"\f104";width:20px;margin-right:-10px;float:right;font-family:FontAwesome;text-align:center}.uk-nav-parent-icon>.uk-parent.uk-open>a:after{content:"\f107"}.uk-nav-side>li>a{color:#444}.uk-nav-side>li>a:focus,.uk-nav-side>li>a:hover{background:rgba(0,0,0,.03);color:#444;outline:0;box-shadow:inset 0 0 1px rgba(0,0,0,.06);text-shadow:0 -1px 0 #fff}.uk-nav-side>li.uk-active>a{background:#00a8e6;color:#fff;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-side .uk-nav-header{color:#444}.uk-nav-side .uk-nav-divider{border-top:1px solid #ddd;box-shadow:0 1px 0 #fff}.uk-nav-side ul a{color:#07d}.uk-nav-side ul a:hover{color:#059}.uk-nav-dropdown>li>a{color:#444}.uk-nav-dropdown>li>a:focus,.uk-nav-dropdown>li>a:hover{background:#00a8e6;color:#fff;outline:0;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-dropdown .uk-nav-header{color:#999}.uk-nav-dropdown .uk-nav-divider{border-top:1px solid #ddd}.uk-nav-dropdown ul a{color:#07d}.uk-nav-dropdown ul a:hover{color:#059}.uk-nav-navbar>li>a{color:#444}.uk-nav-navbar>li>a:focus,.uk-nav-navbar>li>a:hover{background:#00a8e6;color:#fff;outline:0;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-navbar .uk-nav-header{color:#999}.uk-nav-navbar .uk-nav-divider{border-top:1px solid #ddd}.uk-nav-navbar ul a{color:#07d}.uk-nav-navbar ul a:hover{color:#059}.uk-nav-offcanvas>li>a{color:#ccc;padding:10px 15px;border-top:1px solid rgba(0,0,0,.3);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-nav-offcanvas>.uk-open>a,html:not(.uk-touch) .uk-nav-offcanvas>li>a:focus,html:not(.uk-touch) .uk-nav-offcanvas>li>a:hover{background:#404040;color:#fff;outline:0}html .uk-nav.uk-nav-offcanvas>li.uk-active>a{background:#1a1a1a;color:#fff;box-shadow:inset 0 1px 3px rgba(0,0,0,.3)}.uk-nav-offcanvas .uk-nav-header{color:#777;margin-top:0;border-top:1px solid rgba(0,0,0,.3);background:#404040;box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-nav-offcanvas .uk-nav-divider{border-top:1px solid rgba(255,255,255,.01);margin:0;height:4px;background:rgba(0,0,0,.2);box-shadow:inset 0 1px 3px rgba(0,0,0,.3)}.uk-nav-offcanvas ul a{color:#ccc}html:not(.uk-touch) .uk-nav-offcanvas ul a:hover{color:#fff}.uk-nav-offcanvas{border-bottom:1px solid rgba(0,0,0,.3);box-shadow:0 1px 0 rgba(255,255,255,.05)}.uk-nav-offcanvas .uk-nav-sub{border-top:1px solid rgba(0,0,0,.3);box-shadow:inset 0 1px 0 rgba(255,255,255,.05)}.uk-navbar{background:#f5f5f5;color:#444;border:1px solid rgba(0,0,0,.06);border-radius:4px}.uk-navbar:after,.uk-navbar:before{content:"";display:table}.uk-navbar:after{clear:both}.uk-navbar-nav{margin:0;padding:0;list-style:none;float:left}.uk-navbar-nav>li{float:left;position:relative}.uk-navbar-nav>li>a{display:block;-moz-box-sizing:border-box;box-sizing:border-box;text-decoration:none;height:41px;padding:0 15px;line-height:40px;color:#444;font-size:14px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;margin-top:-1px;margin-left:-1px;border:1px solid transparent;border-bottom-width:0;text-shadow:0 1px 0 #fff}.uk-navbar-nav>li>a[href='#']{cursor:text}.uk-navbar-nav>li.uk-open>a,.uk-navbar-nav>li:hover>a,.uk-navbar-nav>li>a:focus{background-color:#fafafa;color:#444;outline:0;position:relative;z-index:1;border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-top-color:rgba(0,0,0,.1)}.uk-navbar-nav>li>a:active{background-color:#eee;color:#444;border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-top-color:rgba(0,0,0,.2)}.uk-navbar-nav>li.uk-active>a{background-color:#fafafa;color:#444;border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-top-color:rgba(0,0,0,.1)}.uk-navbar-nav .uk-navbar-nav-subtitle{line-height:28px}.uk-navbar-nav-subtitle>div{margin-top:-6px;font-size:10px;line-height:12px}.uk-navbar-brand,.uk-navbar-content,.uk-navbar-toggle{-moz-box-sizing:border-box;box-sizing:border-box;display:block;height:41px;padding:0 15px;float:left;margin-top:-1px;text-shadow:0 1px 0 #fff}.uk-navbar-brand:before,.uk-navbar-content:before,.uk-navbar-toggle:before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-navbar-content+.uk-navbar-content:not(.uk-navbar-center){padding-left:0}.uk-navbar-content>a:not([class]){color:#07d}.uk-navbar-content>a:not([class]):hover{color:#059}.uk-navbar-brand{font-size:18px;color:#444;text-decoration:none}.uk-navbar-brand:focus,.uk-navbar-brand:hover{color:#444;text-decoration:none;outline:0}.uk-navbar-toggle{font-size:18px;color:#444;text-decoration:none}.uk-navbar-toggle:focus,.uk-navbar-toggle:hover{color:#444;text-decoration:none;outline:0}.uk-navbar-toggle:after{content:"\f0c9";font-family:FontAwesome;vertical-align:middle}.uk-navbar-toggle-alt:after{content:"\f002"}.uk-navbar-center{float:none;text-align:center;max-width:50%;margin-left:auto;margin-right:auto}.uk-navbar-flip{float:right}.uk-navbar-nav:first-child>li:first-child>a{border-top-left-radius:4px;border-bottom-left-radius:4px}.uk-navbar-flip .uk-navbar-nav>li>a{margin-left:0;margin-right:-1px}.uk-navbar-flip .uk-navbar-nav:first-child>li:first-child>a{border-top-left-radius:0;border-bottom-left-radius:0}.uk-navbar-flip .uk-navbar-nav:last-child>li:last-child>a{border-top-right-radius:4px;border-bottom-right-radius:4px}.uk-navbar-attached{border-top-color:transparent;border-left-color:transparent;border-right-color:transparent;border-radius:0}.uk-navbar-attached .uk-navbar-nav>li>a{border-radius:0!important}.uk-subnav{padding:0;list-style:none;font-size:0}.uk-subnav>li{position:relative;font-size:1rem;vertical-align:top}.uk-subnav>li,.uk-subnav>li>a,.uk-subnav>li>span{display:inline-block}.uk-subnav>li:nth-child(n+2){margin-left:10px}.uk-subnav>li>a{color:#07d}.uk-subnav>li>a:hover{color:#059}.uk-subnav>li>span{color:#999}.uk-subnav-line>li:nth-child(n+2):before{content:"";display:inline-block;height:10px;margin-right:10px;border-left:1px solid #ddd}.uk-subnav-pill>li>a,.uk-subnav-pill>li>span{padding:3px 9px;text-decoration:none;border-radius:4px}.uk-subnav-pill>li>a:focus,.uk-subnav-pill>li>a:hover{background:#fafafa;color:#444;outline:0;box-shadow:0 0 0 1px rgba(0,0,0,.15)}.uk-subnav-pill>li.uk-active>a{background:#00a8e6;color:#fff;box-shadow:inset 0 0 5px rgba(0,0,0,.05)}.uk-breadcrumb{padding:0;list-style:none;font-size:0}.uk-breadcrumb>li{font-size:1rem;vertical-align:top}.uk-breadcrumb>li,.uk-breadcrumb>li>a,.uk-breadcrumb>li>span{display:inline-block}.uk-breadcrumb>li:nth-child(n+2):before{content:"/";display:inline-block;margin:0 8px}.uk-breadcrumb>li:not(.uk-active)>span{color:#999}.uk-pagination{padding:0;list-style:none;text-align:center;font-size:0}.uk-pagination:after,.uk-pagination:before{content:"";display:table}.uk-pagination:after{clear:both}.uk-pagination>li{display:inline-block;font-size:1rem;vertical-align:top}.uk-pagination>li:nth-child(n+2){margin-left:5px}.uk-pagination>li>a,.uk-pagination>li>span{display:inline-block;min-width:16px;padding:3px 5px;line-height:20px;text-decoration:none;-moz-box-sizing:content-box;box-sizing:content-box;text-align:center;border:1px solid rgba(0,0,0,.06);border-radius:4px}.uk-pagination>li>a{background:#f5f5f5;color:#444;text-shadow:0 1px 0 #fff}.uk-pagination>li>a:focus,.uk-pagination>li>a:hover{background-color:#fafafa;color:#444;outline:0;border-color:rgba(0,0,0,.16)}.uk-pagination>li>a:active{background-color:#eee;color:#444}.uk-pagination>.uk-active>span{background:#00a8e6;color:#fff;border-color:transparent;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-pagination>.uk-disabled>span{background-color:#fafafa;color:#999;border:1px solid rgba(0,0,0,.06);text-shadow:0 1px 0 #fff}.uk-pagination-previous{float:left}.uk-pagination-next{float:right}.uk-pagination-left{text-align:left}.uk-pagination-right{text-align:right}.uk-tab{margin:0;padding:0;list-style:none;border-bottom:1px solid #ddd}.uk-tab:after,.uk-tab:before{content:"";display:table}.uk-tab:after{clear:both}.uk-tab>li{margin-bottom:-1px;float:left;position:relative}.uk-tab>li>a{display:block;padding:8px 12px;border:1px solid transparent;border-bottom-width:0;color:#07d;text-decoration:none;border-radius:4px 4px 0 0;text-shadow:0 1px 0 #fff}.uk-tab>li:nth-child(n+2)>a{margin-left:5px}.uk-tab>li.uk-open>a,.uk-tab>li>a:focus,.uk-tab>li>a:hover{border-color:rgba(0,0,0,.06);background:#f5f5f5;color:#059;outline:0}.uk-tab>li.uk-open:not(.uk-active)>a,.uk-tab>li:not(.uk-active)>a:focus,.uk-tab>li:not(.uk-active)>a:hover{margin-bottom:1px;padding-bottom:7px}.uk-tab>li.uk-active>a{border-color:#ddd #ddd transparent;background:#fff;color:#444}.uk-tab>li.uk-disabled>a{color:#999;cursor:auto}.uk-tab>li.uk-disabled.uk-active>a,.uk-tab>li.uk-disabled>a:focus,.uk-tab>li.uk-disabled>a:hover{background:0 0;border-color:transparent}.uk-tab-flip>li{float:right}.uk-tab-flip>li:nth-child(n+2)>a{margin-left:0;margin-right:5px}.uk-tab>li.uk-tab-responsive>a{margin-left:0;margin-right:0}.uk-tab-responsive>a:before{content:"\f0c9\00a0";font-family:FontAwesome}.uk-tab-center{border-bottom:1px solid #ddd}.uk-tab-center-bottom{border-bottom:none;border-top:1px solid #ddd}.uk-tab-center:after,.uk-tab-center:before{content:"";display:table}.uk-tab-center:after{clear:both}.uk-tab-center .uk-tab{position:relative;right:50%;border:none;float:right}.uk-tab-center .uk-tab>li{position:relative;right:-50%}.uk-tab-center .uk-tab>li>a{text-align:center}.uk-tab-bottom{border-top:1px solid #ddd;border-bottom:none}.uk-tab-bottom>li{margin-top:-1px;margin-bottom:0}.uk-tab-bottom>li>a{padding-top:8px;padding-bottom:8px;border-bottom-width:1px;border-top-width:0}.uk-tab-bottom>li.uk-open:not(.uk-active)>a,.uk-tab-bottom>li:not(.uk-active)>a:focus,.uk-tab-bottom>li:not(.uk-active)>a:hover{margin-bottom:0;margin-top:1px;padding-bottom:8px;padding-top:7px}.uk-tab-bottom>li.uk-active>a{border-top-color:transparent;border-bottom-color:#ddd}.uk-tab-grid{margin-left:-5px;border-bottom:none;position:relative;z-index:0}.uk-tab-grid:before{display:block;position:absolute;left:5px;right:0;bottom:-1px;border-top:1px solid #ddd;z-index:-1}.uk-tab-grid>li:first-child>a{margin-left:5px}.uk-tab-grid>li>a{text-align:center}.uk-tab-grid.uk-tab-bottom{border-top:none}.uk-tab-grid.uk-tab-bottom:before{top:-1px;bottom:auto}@media (min-width:768px){.uk-tab-left,.uk-tab-right{border-bottom:none}.uk-tab-left>li,.uk-tab-right>li{margin-bottom:0;float:none}.uk-tab-left>li>a,.uk-tab-right>li>a{padding-top:8px;padding-bottom:8px}.uk-tab-left>li:nth-child(n+2)>a,.uk-tab-right>li:nth-child(n+2)>a{margin-left:0;margin-top:5px}.uk-tab-left>li.uk-active>a,.uk-tab-right>li.uk-active>a{border-color:#ddd}.uk-tab-left{border-right:1px solid #ddd}.uk-tab-left>li{margin-right:-1px}.uk-tab-left>li>a{border-bottom-width:1px;border-right-width:0}.uk-tab-left>li:not(.uk-active)>a:focus,.uk-tab-left>li:not(.uk-active)>a:hover{margin-bottom:0;margin-right:1px;padding-bottom:8px;padding-right:11px}.uk-tab-left>li.uk-active>a{border-right-color:transparent}.uk-tab-right{border-left:1px solid #ddd}.uk-tab-right>li{margin-left:-1px}.uk-tab-right>li>a{border-bottom-width:1px;border-left-width:0}.uk-tab-right>li:not(.uk-active)>a:focus,.uk-tab-right>li:not(.uk-active)>a:hover{margin-bottom:0;margin-left:1px;padding-bottom:8px;padding-left:11px}.uk-tab-right>li.uk-active>a{border-left-color:transparent}}.uk-tab-bottom>li>a{border-radius:0 0 4px 4px}@media (min-width:768px){.uk-tab-left>li>a{border-radius:4px 0 0 4px}.uk-tab-right>li>a{border-radius:0 4px 4px 0}}.uk-list{padding:0;list-style:none}.uk-list>li:after,.uk-list>li:before{content:"";display:table}.uk-list>li:after{clear:both}.uk-list>li>:last-child{margin-bottom:0}.uk-list ul{margin:0;padding-left:20px;list-style:none}.uk-list-line>li:nth-child(n+2){margin-top:5px;padding-top:5px;border-top:1px solid #ddd}.uk-list-striped>li{padding:5px;border-bottom:1px solid #ddd}.uk-list-striped>li:nth-of-type(odd){background:#fafafa}.uk-list-space>li:nth-child(n+2){margin-top:10px}.uk-list-striped>li:first-child{border-top:1px solid #ddd}@media (min-width:768px){.uk-description-list-horizontal{overflow:hidden}.uk-description-list-horizontal>dt{width:160px;float:left;clear:both;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.uk-description-list-horizontal>dd{margin-left:180px}}.uk-description-list-line>dt{font-weight:400}.uk-description-list-line>dt:nth-child(n+2){margin-top:5px;padding-top:5px;border-top:1px solid #ddd}.uk-description-list-line>dd{color:#999}.uk-table{border-collapse:collapse;border-spacing:0;width:100%;margin-bottom:15px}*+.uk-table{margin-top:15px}.uk-table td,.uk-table th{padding:8px;border-bottom:1px solid #ddd}.uk-table th{text-align:left}.uk-table td{vertical-align:top}.uk-table thead th{vertical-align:bottom}.uk-table caption,.uk-table tfoot{font-size:12px;font-style:italic}.uk-table caption{text-align:left;color:#999}.uk-table-middle,.uk-table-middle td{vertical-align:middle!important}.uk-table-striped tbody tr:nth-of-type(odd){background:#fafafa}.uk-table-condensed td{padding:4px 8px}.uk-table-hover tbody tr:hover{background:#f0f0f0}.uk-form input,.uk-form select,.uk-form textarea{-moz-box-sizing:border-box;box-sizing:border-box;margin:0;border-radius:0;font:inherit;color:inherit}.uk-form select{text-transform:none}.uk-form optgroup{font:inherit;font-weight:700}.uk-form input::-moz-focus-inner{border:0;padding:0}.uk-form input[type=checkbox],.uk-form input[type=radio]{padding:0}.uk-form input[type=checkbox]:not(:disabled),.uk-form input[type=radio]:not(:disabled){cursor:pointer}.uk-form input:not([type]),.uk-form input[type=datetime],.uk-form input[type=email],.uk-form input[type=number],.uk-form input[type=password],.uk-form input[type=search],.uk-form input[type=tel],.uk-form input[type=text],.uk-form input[type=url],.uk-form textarea{-webkit-appearance:none}.uk-form input[type=search]::-webkit-search-cancel-button,.uk-form input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.uk-form input[type=number]::-webkit-inner-spin-button,.uk-form input[type=number]::-webkit-outer-spin-button{height:auto}.uk-form fieldset{border:none;margin:0;padding:0}.uk-form textarea{overflow:auto;vertical-align:top}.uk-form ::-moz-placeholder{opacity:1}.uk-form :invalid{box-shadow:none}.uk-form input:not([type=radio]):not([type=checkbox]),.uk-form select{vertical-align:middle}.uk-form>:last-child{margin-bottom:0}.uk-form input:not([type]),.uk-form input[type=color],.uk-form input[type=date],.uk-form input[type=datetime-local],.uk-form input[type=datetime],.uk-form input[type=email],.uk-form input[type=month],.uk-form input[type=number],.uk-form input[type=password],.uk-form input[type=search],.uk-form input[type=tel],.uk-form input[type=text],.uk-form input[type=time],.uk-form input[type=url],.uk-form input[type=week],.uk-form select,.uk-form textarea{height:30px;max-width:100%;padding:4px 6px;border:1px solid #ddd;background:#fff;color:#444;-webkit-transition:all linear .2s;transition:all linear .2s;border-radius:4px}.uk-form input:not([type]):focus,.uk-form input[type=color]:focus,.uk-form input[type=date]:focus,.uk-form input[type=datetime-local]:focus,.uk-form input[type=datetime]:focus,.uk-form input[type=email]:focus,.uk-form input[type=month]:focus,.uk-form input[type=number]:focus,.uk-form input[type=password]:focus,.uk-form input[type=search]:focus,.uk-form input[type=tel]:focus,.uk-form input[type=text]:focus,.uk-form input[type=time]:focus,.uk-form input[type=url]:focus,.uk-form input[type=week]:focus,.uk-form select:focus,.uk-form textarea:focus{border-color:#99baca;outline:0;background:#f5fbfe;color:#444}.uk-form input:not([type]):disabled,.uk-form input[type=color]:disabled,.uk-form input[type=date]:disabled,.uk-form input[type=datetime-local]:disabled,.uk-form input[type=datetime]:disabled,.uk-form input[type=email]:disabled,.uk-form input[type=month]:disabled,.uk-form input[type=number]:disabled,.uk-form input[type=password]:disabled,.uk-form input[type=search]:disabled,.uk-form input[type=tel]:disabled,.uk-form input[type=text]:disabled,.uk-form input[type=time]:disabled,.uk-form input[type=url]:disabled,.uk-form input[type=week]:disabled,.uk-form select:disabled,.uk-form textarea:disabled{border-color:#ddd;background-color:#fafafa;color:#999}.uk-form :-ms-input-placeholder{color:#999!important}.uk-form ::-moz-placeholder{color:#999}.uk-form ::-webkit-input-placeholder{color:#999}.uk-form :disabled:-ms-input-placeholder{color:#999!important}.uk-form :disabled::-moz-placeholder{color:#999}.uk-form :disabled::-webkit-input-placeholder{color:#999}.uk-form legend{width:100%;border:0;padding:0 0 15px;font-size:18px;line-height:30px}.uk-form legend:after{content:"";display:block;border-bottom:1px solid #ddd;width:100%}input:not([type]).uk-form-small,input[type].uk-form-small,select.uk-form-small,textarea.uk-form-small{height:25px;padding:3px;font-size:12px}input:not([type]).uk-form-large,input[type].uk-form-large,select.uk-form-large,textarea.uk-form-large{height:40px;padding:8px 6px;font-size:16px}.uk-form select[multiple],.uk-form select[size],.uk-form textarea{height:auto}.uk-form-danger{border-color:#dc8d99!important;background:#fff7f8!important;color:#d85030!important}.uk-form-success{border-color:#8ec73b!important;background:#fafff2!important;color:#659f13!important}.uk-form-blank{border-color:transparent!important;border-style:dashed!important;background:none!important}.uk-form-blank:focus{border-color:#ddd!important}input.uk-form-width-mini{width:40px}select.uk-form-width-mini{width:65px}.uk-form-width-small{width:130px}.uk-form-width-medium{width:200px}.uk-form-width-large{width:500px}.uk-form-row:after,.uk-form-row:before{content:"";display:table}.uk-form-row:after{clear:both}.uk-form-row+.uk-form-row{margin-top:15px}.uk-form-help-inline{display:inline-block;margin:0 0 0 10px}.uk-form-help-block{margin:5px 0 0}.uk-form-controls>:first-child{margin-top:0}.uk-form-controls>:last-child{margin-bottom:0}.uk-form-controls-condensed{margin:5px 0}.uk-form-stacked .uk-form-label{display:block;margin-bottom:5px;font-weight:700}@media (max-width:959px){.uk-form-horizontal .uk-form-label{display:block;margin-bottom:5px;font-weight:700}}@media (min-width:960px){.uk-form-horizontal .uk-form-label{width:200px;margin-top:5px;float:left}.uk-form-horizontal .uk-form-controls{margin-left:215px}.uk-form-horizontal .uk-form-controls-text{padding-top:5px}}.uk-form-icon{display:inline-block;position:relative;max-width:100%}.uk-form-icon>[class*=uk-icon-]{position:absolute;top:50%;width:30px;margin-top:-7px;font-size:14px;color:#999;text-align:center;pointer-events:none}.uk-form-icon:not(.uk-form-icon-flip)>input{padding-left:30px!important}.uk-form-icon-flip>[class*=uk-icon-]{right:0}.uk-form-icon-flip>input{padding-right:30px!important}.uk-button::-moz-focus-inner{border:0;padding:0}.uk-button{-webkit-appearance:none;margin:0;border:none;overflow:visible;font:inherit;color:#444;text-transform:none;display:inline-block;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 12px;background:#f5f5f5;vertical-align:middle;line-height:28px;min-height:30px;font-size:1rem;text-decoration:none;text-align:center;border:1px solid rgba(0,0,0,.06);border-radius:4px;text-shadow:0 1px 0 #fff}.uk-button:not(:disabled){cursor:pointer}.uk-button:focus,.uk-button:hover{background-color:#fafafa;color:#444;outline:0;text-decoration:none;border-color:rgba(0,0,0,.16)}.uk-button.uk-active,.uk-button:active{background-color:#eee;color:#444}.uk-button-primary{background-color:#00a8e6;color:#fff}.uk-button-primary:focus,.uk-button-primary:hover{background-color:#35b3ee;color:#fff}.uk-button-primary.uk-active,.uk-button-primary:active{background-color:#0091ca;color:#fff}.uk-button-success{background-color:#8cc14c;color:#fff}.uk-button-success:focus,.uk-button-success:hover{background-color:#8ec73b;color:#fff}.uk-button-success.uk-active,.uk-button-success:active{background-color:#72ae41;color:#fff}.uk-button-danger{background-color:#da314b;color:#fff}.uk-button-danger:focus,.uk-button-danger:hover{background-color:#e4354f;color:#fff}.uk-button-danger.uk-active,.uk-button-danger:active{background-color:#c91032;color:#fff}.uk-button:disabled{background-color:#fafafa;color:#999;border-color:rgba(0,0,0,.06);box-shadow:none;text-shadow:0 1px 0 #fff}.uk-button-link,.uk-button-link.uk-active,.uk-button-link:active,.uk-button-link:disabled,.uk-button-link:focus,.uk-button-link:hover{border-color:transparent;background:0 0;box-shadow:none;text-shadow:none}.uk-button-link{color:#07d}.uk-button-link.uk-active,.uk-button-link:active,.uk-button-link:focus,.uk-button-link:hover{color:#059;text-decoration:underline}.uk-button-link:disabled{color:#999}.uk-button-link:focus{outline:dotted 1px}.uk-button-mini{min-height:20px;padding:0 6px;line-height:18px;font-size:11px}.uk-button-small{min-height:25px;padding:0 10px;line-height:23px;font-size:12px}.uk-button-large{min-height:40px;padding:0 15px;line-height:38px;font-size:16px;border-radius:5px}.uk-button-group{display:inline-block;vertical-align:middle;position:relative;font-size:0;white-space:nowrap}.uk-button-group>*{display:inline-block}.uk-button-group .uk-button{vertical-align:top}.uk-button-dropdown{display:inline-block;vertical-align:middle;position:relative}.uk-button-danger,.uk-button-primary,.uk-button-success{box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-button-danger:focus,.uk-button-danger:hover,.uk-button-primary:focus,.uk-button-primary:hover,.uk-button-success:focus,.uk-button-success:hover{border-color:rgba(0,0,0,.21)}.uk-button-group>.uk-button:not(:first-child):not(:last-child),.uk-button-group>div:not(:first-child):not(:last-child) .uk-button{border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-radius:0}.uk-button-group>.uk-button:first-child,.uk-button-group>div:first-child .uk-button{border-right-color:rgba(0,0,0,.1);border-top-right-radius:0;border-bottom-right-radius:0}.uk-button-group>.uk-button:last-child,.uk-button-group>div:last-child .uk-button{border-left-color:rgba(0,0,0,.1);border-top-left-radius:0;border-bottom-left-radius:0}.uk-button-group>.uk-button:nth-child(n+2),.uk-button-group>div:nth-child(n+2) .uk-button{margin-left:-1px}.uk-button-group .uk-button:active,.uk-button-group .uk-button:hover{position:relative}@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot);src:url(../fonts/fontawesome-webfont.eot?#iefix) format("embedded-opentype"),url(../fonts/fontawesome-webfont.woff) format("woff"),url(../fonts/fontawesome-webfont.ttf) format("truetype");font-weight:400;font-style:normal}[class*=uk-icon-]{font-family:FontAwesome;display:inline-block;font-weight:400;font-style:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.uk-icon-small:before{font-size:150%;vertical-align:-10%}.uk-icon-medium:before{font-size:200%;vertical-align:-16%}.uk-icon-large:before{font-size:250%;vertical-align:-22%}.uk-icon-spin{display:inline-block;-webkit-animation:uk-rotate 2s infinite linear;animation:uk-rotate 2s infinite linear}.uk-icon-button{-moz-box-sizing:border-box;box-sizing:border-box;display:inline-block;width:35px;height:35px;border-radius:100%;background:#f5f5f5;line-height:35px;color:#444;font-size:18px;text-align:center;border:1px solid #e7e7e7;text-shadow:0 1px 0 #fff}.uk-icon-button:focus,.uk-icon-button:hover{background-color:#fafafa;color:#444;text-decoration:none;outline:0;border-color:#d3d3d3}.uk-icon-button:active{background-color:#eee;color:#444}.uk-icon-glass:before{content:"\f000"}.uk-icon-music:before{content:"\f001"}.uk-icon-search:before{content:"\f002"}.uk-icon-envelope-o:before{content:"\f003"}.uk-icon-heart:before{content:"\f004"}.uk-icon-star:before{content:"\f005"}.uk-icon-star-o:before{content:"\f006"}.uk-icon-user:before{content:"\f007"}.uk-icon-film:before{content:"\f008"}.uk-icon-th-large:before{content:"\f009"}.uk-icon-th:before{content:"\f00a"}.uk-icon-th-list:before{content:"\f00b"}.uk-icon-check:before{content:"\f00c"}.uk-icon-close:before,.uk-icon-remove:before,.uk-icon-times:before{content:"\f00d"}.uk-icon-search-plus:before{content:"\f00e"}.uk-icon-search-minus:before{content:"\f010"}.uk-icon-power-off:before{content:"\f011"}.uk-icon-signal:before{content:"\f012"}.uk-icon-cog:before,.uk-icon-gear:before{content:"\f013"}.uk-icon-trash-o:before{content:"\f014"}.uk-icon-home:before{content:"\f015"}.uk-icon-file-o:before{content:"\f016"}.uk-icon-clock-o:before{content:"\f017"}.uk-icon-road:before{content:"\f018"}.uk-icon-download:before{content:"\f019"}.uk-icon-arrow-circle-o-down:before{content:"\f01a"}.uk-icon-arrow-circle-o-up:before{content:"\f01b"}.uk-icon-inbox:before{content:"\f01c"}.uk-icon-play-circle-o:before{content:"\f01d"}.uk-icon-repeat:before,.uk-icon-rotate-right:before{content:"\f01e"}.uk-icon-refresh:before{content:"\f021"}.uk-icon-list-alt:before{content:"\f022"}.uk-icon-lock:before{content:"\f023"}.uk-icon-flag:before{content:"\f024"}.uk-icon-headphones:before{content:"\f025"}.uk-icon-volume-off:before{content:"\f026"}.uk-icon-volume-down:before{content:"\f027"}.uk-icon-volume-up:before{content:"\f028"}.uk-icon-qrcode:before{content:"\f029"}.uk-icon-barcode:before{content:"\f02a"}.uk-icon-tag:before{content:"\f02b"}.uk-icon-tags:before{content:"\f02c"}.uk-icon-book:before{content:"\f02d"}.uk-icon-bookmark:before{content:"\f02e"}.uk-icon-print:before{content:"\f02f"}.uk-icon-camera:before{content:"\f030"}.uk-icon-font:before{content:"\f031"}.uk-icon-bold:before{content:"\f032"}.uk-icon-italic:before{content:"\f033"}.uk-icon-text-height:before{content:"\f034"}.uk-icon-text-width:before{content:"\f035"}.uk-icon-align-left:before{content:"\f036"}.uk-icon-align-center:before{content:"\f037"}.uk-icon-align-right:before{content:"\f038"}.uk-icon-align-justify:before{content:"\f039"}.uk-icon-list:before{content:"\f03a"}.uk-icon-dedent:before,.uk-icon-outdent:before{content:"\f03b"}.uk-icon-indent:before{content:"\f03c"}.uk-icon-video-camera:before{content:"\f03d"}.uk-icon-image:before,.uk-icon-photo:before,.uk-icon-picture-o:before{content:"\f03e"}.uk-icon-pencil:before{content:"\f040"}.uk-icon-map-marker:before{content:"\f041"}.uk-icon-adjust:before{content:"\f042"}.uk-icon-tint:before{content:"\f043"}.uk-icon-edit:before,.uk-icon-pencil-square-o:before{content:"\f044"}.uk-icon-share-square-o:before{content:"\f045"}.uk-icon-check-square-o:before{content:"\f046"}.uk-icon-arrows:before{content:"\f047"}.uk-icon-step-backward:before{content:"\f048"}.uk-icon-fast-backward:before{content:"\f049"}.uk-icon-backward:before{content:"\f04a"}.uk-icon-play:before{content:"\f04b"}.uk-icon-pause:before{content:"\f04c"}.uk-icon-stop:before{content:"\f04d"}.uk-icon-forward:before{content:"\f04e"}.uk-icon-fast-forward:before{content:"\f050"}.uk-icon-step-forward:before{content:"\f051"}.uk-icon-eject:before{content:"\f052"}.uk-icon-chevron-left:before{content:"\f053"}.uk-icon-chevron-right:before{content:"\f054"}.uk-icon-plus-circle:before{content:"\f055"}.uk-icon-minus-circle:before{content:"\f056"}.uk-icon-times-circle:before{content:"\f057"}.uk-icon-check-circle:before{content:"\f058"}.uk-icon-question-circle:before{content:"\f059"}.uk-icon-info-circle:before{content:"\f05a"}.uk-icon-crosshairs:before{content:"\f05b"}.uk-icon-times-circle-o:before{content:"\f05c"}.uk-icon-check-circle-o:before{content:"\f05d"}.uk-icon-ban:before{content:"\f05e"}.uk-icon-arrow-left:before{content:"\f060"}.uk-icon-arrow-right:before{content:"\f061"}.uk-icon-arrow-up:before{content:"\f062"}.uk-icon-arrow-down:before{content:"\f063"}.uk-icon-mail-forward:before,.uk-icon-share:before{content:"\f064"}.uk-icon-expand:before{content:"\f065"}.uk-icon-compress:before{content:"\f066"}.uk-icon-plus:before{content:"\f067"}.uk-icon-minus:before{content:"\f068"}.uk-icon-asterisk:before{content:"\f069"}.uk-icon-exclamation-circle:before{content:"\f06a"}.uk-icon-gift:before{content:"\f06b"}.uk-icon-leaf:before{content:"\f06c"}.uk-icon-fire:before{content:"\f06d"}.uk-icon-eye:before{content:"\f06e"}.uk-icon-eye-slash:before{content:"\f070"}.uk-icon-exclamation-triangle:before,.uk-icon-warning:before{content:"\f071"}.uk-icon-plane:before{content:"\f072"}.uk-icon-calendar:before{content:"\f073"}.uk-icon-random:before{content:"\f074"}.uk-icon-comment:before{content:"\f075"}.uk-icon-magnet:before{content:"\f076"}.uk-icon-chevron-up:before{content:"\f077"}.uk-icon-chevron-down:before{content:"\f078"}.uk-icon-retweet:before{content:"\f079"}.uk-icon-shopping-cart:before{content:"\f07a"}.uk-icon-folder:before{content:"\f07b"}.uk-icon-folder-open:before{content:"\f07c"}.uk-icon-arrows-v:before{content:"\f07d"}.uk-icon-arrows-h:before{content:"\f07e"}.uk-icon-bar-chart-o:before,.uk-icon-bar-chart:before{content:"\f080"}.uk-icon-twitter-square:before{content:"\f081"}.uk-icon-facebook-square:before{content:"\f082"}.uk-icon-camera-retro:before{content:"\f083"}.uk-icon-key:before{content:"\f084"}.uk-icon-cogs:before,.uk-icon-gears:before{content:"\f085"}.uk-icon-comments:before{content:"\f086"}.uk-icon-thumbs-o-up:before{content:"\f087"}.uk-icon-thumbs-o-down:before{content:"\f088"}.uk-icon-star-half:before{content:"\f089"}.uk-icon-heart-o:before{content:"\f08a"}.uk-icon-sign-out:before{content:"\f08b"}.uk-icon-linkedin-square:before{content:"\f08c"}.uk-icon-thumb-tack:before{content:"\f08d"}.uk-icon-external-link:before{content:"\f08e"}.uk-icon-sign-in:before{content:"\f090"}.uk-icon-trophy:before{content:"\f091"}.uk-icon-github-square:before{content:"\f092"}.uk-icon-upload:before{content:"\f093"}.uk-icon-lemon-o:before{content:"\f094"}.uk-icon-phone:before{content:"\f095"}.uk-icon-square-o:before{content:"\f096"}.uk-icon-bookmark-o:before{content:"\f097"}.uk-icon-phone-square:before{content:"\f098"}.uk-icon-twitter:before{content:"\f099"}.uk-icon-facebook:before{content:"\f09a"}.uk-icon-github:before{content:"\f09b"}.uk-icon-unlock:before{content:"\f09c"}.uk-icon-credit-card:before{content:"\f09d"}.uk-icon-rss:before{content:"\f09e"}.uk-icon-hdd-o:before{content:"\f0a0"}.uk-icon-bullhorn:before{content:"\f0a1"}.uk-icon-bell:before{content:"\f0f3"}.uk-icon-certificate:before{content:"\f0a3"}.uk-icon-hand-o-right:before{content:"\f0a4"}.uk-icon-hand-o-left:before{content:"\f0a5"}.uk-icon-hand-o-up:before{content:"\f0a6"}.uk-icon-hand-o-down:before{content:"\f0a7"}.uk-icon-arrow-circle-left:before{content:"\f0a8"}.uk-icon-arrow-circle-right:before{content:"\f0a9"}.uk-icon-arrow-circle-up:before{content:"\f0aa"}.uk-icon-arrow-circle-down:before{content:"\f0ab"}.uk-icon-globe:before{content:"\f0ac"}.uk-icon-wrench:before{content:"\f0ad"}.uk-icon-tasks:before{content:"\f0ae"}.uk-icon-filter:before{content:"\f0b0"}.uk-icon-briefcase:before{content:"\f0b1"}.uk-icon-arrows-alt:before{content:"\f0b2"}.uk-icon-group:before,.uk-icon-users:before{content:"\f0c0"}.uk-icon-chain:before,.uk-icon-link:before{content:"\f0c1"}.uk-icon-cloud:before{content:"\f0c2"}.uk-icon-flask:before{content:"\f0c3"}.uk-icon-cut:before,.uk-icon-scissors:before{content:"\f0c4"}.uk-icon-copy:before,.uk-icon-files-o:before{content:"\f0c5"}.uk-icon-paperclip:before{content:"\f0c6"}.uk-icon-floppy-o:before,.uk-icon-save:before{content:"\f0c7"}.uk-icon-square:before{content:"\f0c8"}.uk-icon-bars:before,.uk-icon-navicon:before,.uk-icon-reorder:before{content:"\f0c9"}.uk-icon-list-ul:before{content:"\f0ca"}.uk-icon-list-ol:before{content:"\f0cb"}.uk-icon-strikethrough:before{content:"\f0cc"}.uk-icon-underline:before{content:"\f0cd"}.uk-icon-table:before{content:"\f0ce"}.uk-icon-magic:before{content:"\f0d0"}.uk-icon-truck:before{content:"\f0d1"}.uk-icon-pinterest:before{content:"\f0d2"}.uk-icon-pinterest-square:before{content:"\f0d3"}.uk-icon-google-plus-square:before{content:"\f0d4"}.uk-icon-google-plus:before{content:"\f0d5"}.uk-icon-money:before{content:"\f0d6"}.uk-icon-caret-down:before{content:"\f0d7"}.uk-icon-caret-up:before{content:"\f0d8"}.uk-icon-caret-left:before{content:"\f0d9"}.uk-icon-caret-right:before{content:"\f0da"}.uk-icon-columns:before{content:"\f0db"}.uk-icon-sort:before,.uk-icon-unsorted:before{content:"\f0dc"}.uk-icon-sort-desc:before,.uk-icon-sort-down:before{content:"\f0dd"}.uk-icon-sort-asc:before,.uk-icon-sort-up:before{content:"\f0de"}.uk-icon-envelope:before{content:"\f0e0"}.uk-icon-linkedin:before{content:"\f0e1"}.uk-icon-rotate-left:before,.uk-icon-undo:before{content:"\f0e2"}.uk-icon-gavel:before,.uk-icon-legal:before{content:"\f0e3"}.uk-icon-dashboard:before,.uk-icon-tachometer:before{content:"\f0e4"}.uk-icon-comment-o:before{content:"\f0e5"}.uk-icon-comments-o:before{content:"\f0e6"}.uk-icon-bolt:before,.uk-icon-flash:before{content:"\f0e7"}.uk-icon-sitemap:before{content:"\f0e8"}.uk-icon-umbrella:before{content:"\f0e9"}.uk-icon-clipboard:before,.uk-icon-paste:before{content:"\f0ea"}.uk-icon-lightbulb-o:before{content:"\f0eb"}.uk-icon-exchange:before{content:"\f0ec"}.uk-icon-cloud-download:before{content:"\f0ed"}.uk-icon-cloud-upload:before{content:"\f0ee"}.uk-icon-user-md:before{content:"\f0f0"}.uk-icon-stethoscope:before{content:"\f0f1"}.uk-icon-suitcase:before{content:"\f0f2"}.uk-icon-bell-o:before{content:"\f0a2"}.uk-icon-coffee:before{content:"\f0f4"}.uk-icon-cutlery:before{content:"\f0f5"}.uk-icon-file-text-o:before{content:"\f0f6"}.uk-icon-building-o:before{content:"\f0f7"}.uk-icon-hospital-o:before{content:"\f0f8"}.uk-icon-ambulance:before{content:"\f0f9"}.uk-icon-medkit:before{content:"\f0fa"}.uk-icon-fighter-jet:before{content:"\f0fb"}.uk-icon-beer:before{content:"\f0fc"}.uk-icon-h-square:before{content:"\f0fd"}.uk-icon-plus-square:before{content:"\f0fe"}.uk-icon-angle-double-left:before{content:"\f100"}.uk-icon-angle-double-right:before{content:"\f101"}.uk-icon-angle-double-up:before{content:"\f102"}.uk-icon-angle-double-down:before{content:"\f103"}.uk-icon-angle-left:before{content:"\f104"}.uk-icon-angle-right:before{content:"\f105"}.uk-icon-angle-up:before{content:"\f106"}.uk-icon-angle-down:before{content:"\f107"}.uk-icon-desktop:before{content:"\f108"}.uk-icon-laptop:before{content:"\f109"}.uk-icon-tablet:before{content:"\f10a"}.uk-icon-mobile-phone:before,.uk-icon-mobile:before{content:"\f10b"}.uk-icon-circle-o:before{content:"\f10c"}.uk-icon-quote-left:before{content:"\f10d"}.uk-icon-quote-right:before{content:"\f10e"}.uk-icon-spinner:before{content:"\f110"}.uk-icon-circle:before{content:"\f111"}.uk-icon-mail-reply:before,.uk-icon-reply:before{content:"\f112"}.uk-icon-github-alt:before{content:"\f113"}.uk-icon-folder-o:before{content:"\f114"}.uk-icon-folder-open-o:before{content:"\f115"}.uk-icon-smile-o:before{content:"\f118"}.uk-icon-frown-o:before{content:"\f119"}.uk-icon-meh-o:before{content:"\f11a"}.uk-icon-gamepad:before{content:"\f11b"}.uk-icon-keyboard-o:before{content:"\f11c"}.uk-icon-flag-o:before{content:"\f11d"}.uk-icon-flag-checkered:before{content:"\f11e"}.uk-icon-terminal:before{content:"\f120"}.uk-icon-code:before{content:"\f121"}.uk-icon-mail-reply-all:before,.uk-icon-reply-all:before{content:"\f122"}.uk-icon-star-half-empty:before,.uk-icon-star-half-full:before,.uk-icon-star-half-o:before{content:"\f123"}.uk-icon-location-arrow:before{content:"\f124"}.uk-icon-crop:before{content:"\f125"}.uk-icon-code-fork:before{content:"\f126"}.uk-icon-chain-broken:before,.uk-icon-unlink:before{content:"\f127"}.uk-icon-question:before{content:"\f128"}.uk-icon-info:before{content:"\f129"}.uk-icon-exclamation:before{content:"\f12a"}.uk-icon-superscript:before{content:"\f12b"}.uk-icon-subscript:before{content:"\f12c"}.uk-icon-eraser:before{content:"\f12d"}.uk-icon-puzzle-piece:before{content:"\f12e"}.uk-icon-microphone:before{content:"\f130"}.uk-icon-microphone-slash:before{content:"\f131"}.uk-icon-shield:before{content:"\f132"}.uk-icon-calendar-o:before{content:"\f133"}.uk-icon-fire-extinguisher:before{content:"\f134"}.uk-icon-rocket:before{content:"\f135"}.uk-icon-maxcdn:before{content:"\f136"}.uk-icon-chevron-circle-left:before{content:"\f137"}.uk-icon-chevron-circle-right:before{content:"\f138"}.uk-icon-chevron-circle-up:before{content:"\f139"}.uk-icon-chevron-circle-down:before{content:"\f13a"}.uk-icon-html5:before{content:"\f13b"}.uk-icon-css3:before{content:"\f13c"}.uk-icon-anchor:before{content:"\f13d"}.uk-icon-unlock-alt:before{content:"\f13e"}.uk-icon-bullseye:before{content:"\f140"}.uk-icon-ellipsis-h:before{content:"\f141"}.uk-icon-ellipsis-v:before{content:"\f142"}.uk-icon-rss-square:before{content:"\f143"}.uk-icon-play-circle:before{content:"\f144"}.uk-icon-ticket:before{content:"\f145"}.uk-icon-minus-square:before{content:"\f146"}.uk-icon-minus-square-o:before{content:"\f147"}.uk-icon-level-up:before{content:"\f148"}.uk-icon-level-down:before{content:"\f149"}.uk-icon-check-square:before{content:"\f14a"}.uk-icon-pencil-square:before{content:"\f14b"}.uk-icon-external-link-square:before{content:"\f14c"}.uk-icon-share-square:before{content:"\f14d"}.uk-icon-compass:before{content:"\f14e"}.uk-icon-caret-square-o-down:before,.uk-icon-toggle-down:before{content:"\f150"}.uk-icon-caret-square-o-up:before,.uk-icon-toggle-up:before{content:"\f151"}.uk-icon-caret-square-o-right:before,.uk-icon-toggle-right:before{content:"\f152"}.uk-icon-eur:before,.uk-icon-euro:before{content:"\f153"}.uk-icon-gbp:before{content:"\f154"}.uk-icon-dollar:before,.uk-icon-usd:before{content:"\f155"}.uk-icon-inr:before,.uk-icon-rupee:before{content:"\f156"}.uk-icon-cny:before,.uk-icon-jpy:before,.uk-icon-rmb:before,.uk-icon-yen:before{content:"\f157"}.uk-icon-rouble:before,.uk-icon-rub:before,.uk-icon-ruble:before{content:"\f158"}.uk-icon-krw:before,.uk-icon-won:before{content:"\f159"}.uk-icon-bitcoin:before,.uk-icon-btc:before{content:"\f15a"}.uk-icon-file:before{content:"\f15b"}.uk-icon-file-text:before{content:"\f15c"}.uk-icon-sort-alpha-asc:before{content:"\f15d"}.uk-icon-sort-alpha-desc:before{content:"\f15e"}.uk-icon-sort-amount-asc:before{content:"\f160"}.uk-icon-sort-amount-desc:before{content:"\f161"}.uk-icon-sort-numeric-asc:before{content:"\f162"}.uk-icon-sort-numeric-desc:before{content:"\f163"}.uk-icon-thumbs-up:before{content:"\f164"}.uk-icon-thumbs-down:before{content:"\f165"}.uk-icon-youtube-square:before{content:"\f166"}.uk-icon-youtube:before{content:"\f167"}.uk-icon-xing:before{content:"\f168"}.uk-icon-xing-square:before{content:"\f169"}.uk-icon-youtube-play:before{content:"\f16a"}.uk-icon-dropbox:before{content:"\f16b"}.uk-icon-stack-overflow:before{content:"\f16c"}.uk-icon-instagram:before{content:"\f16d"}.uk-icon-flickr:before{content:"\f16e"}.uk-icon-adn:before{content:"\f170"}.uk-icon-bitbucket:before{content:"\f171"}.uk-icon-bitbucket-square:before{content:"\f172"}.uk-icon-tumblr:before{content:"\f173"}.uk-icon-tumblr-square:before{content:"\f174"}.uk-icon-long-arrow-down:before{content:"\f175"}.uk-icon-long-arrow-up:before{content:"\f176"}.uk-icon-long-arrow-left:before{content:"\f177"}.uk-icon-long-arrow-right:before{content:"\f178"}.uk-icon-apple:before{content:"\f179"}.uk-icon-windows:before{content:"\f17a"}.uk-icon-android:before{content:"\f17b"}.uk-icon-linux:before{content:"\f17c"}.uk-icon-dribbble:before{content:"\f17d"}.uk-icon-skype:before{content:"\f17e"}.uk-icon-foursquare:before{content:"\f180"}.uk-icon-trello:before{content:"\f181"}.uk-icon-female:before{content:"\f182"}.uk-icon-male:before{content:"\f183"}.uk-icon-gittip:before{content:"\f184"}.uk-icon-sun-o:before{content:"\f185"}.uk-icon-moon-o:before{content:"\f186"}.uk-icon-archive:before{content:"\f187"}.uk-icon-bug:before{content:"\f188"}.uk-icon-vk:before{content:"\f189"}.uk-icon-weibo:before{content:"\f18a"}.uk-icon-renren:before{content:"\f18b"}.uk-icon-pagelines:before{content:"\f18c"}.uk-icon-stack-exchange:before{content:"\f18d"}.uk-icon-arrow-circle-o-right:before{content:"\f18e"}.uk-icon-arrow-circle-o-left:before{content:"\f190"}.uk-icon-caret-square-o-left:before,.uk-icon-toggle-left:before{content:"\f191"}.uk-icon-dot-circle-o:before{content:"\f192"}.uk-icon-wheelchair:before{content:"\f193"}.uk-icon-vimeo-square:before{content:"\f194"}.uk-icon-try:before,.uk-icon-turkish-lira:before{content:"\f195"}.uk-icon-plus-square-o:before{content:"\f196"}.uk-icon-space-shuttle:before{content:"\f197"}.uk-icon-slack:before{content:"\f198"}.uk-icon-envelope-square:before{content:"\f199"}.uk-icon-wordpress:before{content:"\f19a"}.uk-icon-openid:before{content:"\f19b"}.uk-icon-bank:before,.uk-icon-institution:before,.uk-icon-university:before{content:"\f19c"}.uk-icon-graduation-cap:before,.uk-icon-mortar-board:before{content:"\f19d"}.uk-icon-yahoo:before{content:"\f19e"}.uk-icon-google:before{content:"\f1a0"}.uk-icon-reddit:before{content:"\f1a1"}.uk-icon-reddit-square:before{content:"\f1a2"}.uk-icon-stumbleupon-circle:before{content:"\f1a3"}.uk-icon-stumbleupon:before{content:"\f1a4"}.uk-icon-delicious:before{content:"\f1a5"}.uk-icon-digg:before{content:"\f1a6"}.uk-icon-pied-piper:before{content:"\f1a7"}.uk-icon-pied-piper-alt:before{content:"\f1a8"}.uk-icon-drupal:before{content:"\f1a9"}.uk-icon-joomla:before{content:"\f1aa"}.uk-icon-language:before{content:"\f1ab"}.uk-icon-fax:before{content:"\f1ac"}.uk-icon-building:before{content:"\f1ad"}.uk-icon-child:before{content:"\f1ae"}.uk-icon-paw:before{content:"\f1b0"}.uk-icon-spoon:before{content:"\f1b1"}.uk-icon-cube:before{content:"\f1b2"}.uk-icon-cubes:before{content:"\f1b3"}.uk-icon-behance:before{content:"\f1b4"}.uk-icon-behance-square:before{content:"\f1b5"}.uk-icon-steam:before{content:"\f1b6"}.uk-icon-steam-square:before{content:"\f1b7"}.uk-icon-recycle:before{content:"\f1b8"}.uk-icon-automobile:before,.uk-icon-car:before{content:"\f1b9"}.uk-icon-cab:before,.uk-icon-taxi:before{content:"\f1ba"}.uk-icon-tree:before{content:"\f1bb"}.uk-icon-spotify:before{content:"\f1bc"}.uk-icon-deviantart:before{content:"\f1bd"}.uk-icon-soundcloud:before{content:"\f1be"}.uk-icon-database:before{content:"\f1c0"}.uk-icon-file-pdf-o:before{content:"\f1c1"}.uk-icon-file-word-o:before{content:"\f1c2"}.uk-icon-file-excel-o:before{content:"\f1c3"}.uk-icon-file-powerpoint-o:before{content:"\f1c4"}.uk-icon-file-image-o:before,.uk-icon-file-photo-o:before,.uk-icon-file-picture-o:before{content:"\f1c5"}.uk-icon-file-archive-o:before,.uk-icon-file-zip-o:before{content:"\f1c6"}.uk-icon-file-audio-o:before,.uk-icon-file-sound-o:before{content:"\f1c7"}.uk-icon-file-movie-o:before,.uk-icon-file-video-o:before{content:"\f1c8"}.uk-icon-file-code-o:before{content:"\f1c9"}.uk-icon-vine:before{content:"\f1ca"}.uk-icon-codepen:before{content:"\f1cb"}.uk-icon-jsfiddle:before{content:"\f1cc"}.uk-icon-life-bouy:before,.uk-icon-life-buoy:before,.uk-icon-life-ring:before,.uk-icon-life-saver:before,.uk-icon-support:before{content:"\f1cd"}.uk-icon-circle-o-notch:before{content:"\f1ce"}.uk-icon-ra:before,.uk-icon-rebel:before{content:"\f1d0"}.uk-icon-empire:before,.uk-icon-ge:before{content:"\f1d1"}.uk-icon-git-square:before{content:"\f1d2"}.uk-icon-git:before{content:"\f1d3"}.uk-icon-hacker-news:before{content:"\f1d4"}.uk-icon-tencent-weibo:before{content:"\f1d5"}.uk-icon-qq:before{content:"\f1d6"}.uk-icon-wechat:before,.uk-icon-weixin:before{content:"\f1d7"}.uk-icon-paper-plane:before,.uk-icon-send:before{content:"\f1d8"}.uk-icon-paper-plane-o:before,.uk-icon-send-o:before{content:"\f1d9"}.uk-icon-history:before{content:"\f1da"}.uk-icon-circle-thin:before{content:"\f1db"}.uk-icon-header:before{content:"\f1dc"}.uk-icon-paragraph:before{content:"\f1dd"}.uk-icon-sliders:before{content:"\f1de"}.uk-icon-share-alt:before{content:"\f1e0"}.uk-icon-share-alt-square:before{content:"\f1e1"}.uk-icon-bomb:before{content:"\f1e2"}.uk-icon-futbol-o:before,.uk-icon-soccer-ball-o:before{content:"\f1e3"}.uk-icon-tty:before{content:"\f1e4"}.uk-icon-binoculars:before{content:"\f1e5"}.uk-icon-plug:before{content:"\f1e6"}.uk-icon-slideshare:before{content:"\f1e7"}.uk-icon-twitch:before{content:"\f1e8"}.uk-icon-yelp:before{content:"\f1e9"}.uk-icon-newspaper-o:before{content:"\f1ea"}.uk-icon-wifi:before{content:"\f1eb"}.uk-icon-calculator:before{content:"\f1ec"}.uk-icon-paypal:before{content:"\f1ed"}.uk-icon-google-wallet:before{content:"\f1ee"}.uk-icon-cc-visa:before{content:"\f1f0"}.uk-icon-cc-mastercard:before{content:"\f1f1"}.uk-icon-cc-discover:before{content:"\f1f2"}.uk-icon-cc-amex:before{content:"\f1f3"}.uk-icon-cc-paypal:before{content:"\f1f4"}.uk-icon-cc-stripe:before{content:"\f1f5"}.uk-icon-bell-slash:before{content:"\f1f6"}.uk-icon-bell-slash-o:before{content:"\f1f7"}.uk-icon-trash:before{content:"\f1f8"}.uk-icon-copyright:before{content:"\f1f9"}.uk-icon-at:before{content:"\f1fa"}.uk-icon-eyedropper:before{content:"\f1fb"}.uk-icon-paint-brush:before{content:"\f1fc"}.uk-icon-birthday-cake:before{content:"\f1fd"}.uk-icon-area-chart:before{content:"\f1fe"}.uk-icon-pie-chart:before{content:"\f200"}.uk-icon-line-chart:before{content:"\f201"}.uk-icon-lastfm:before{content:"\f202"}.uk-icon-lastfm-square:before{content:"\f203"}.uk-icon-toggle-off:before{content:"\f204"}.uk-icon-toggle-on:before{content:"\f205"}.uk-icon-bicycle:before{content:"\f206"}.uk-icon-bus:before{content:"\f207"}.uk-icon-ioxhost:before{content:"\f208"}.uk-icon-angellist:before{content:"\f209"}.uk-icon-cc:before{content:"\f20a"}.uk-icon-ils:before,.uk-icon-shekel:before,.uk-icon-sheqel:before{content:"\f20b"}.uk-icon-meanpath:before{content:"\f20c"}.uk-close::-moz-focus-inner{border:0;padding:0}.uk-close{-webkit-appearance:none;margin:0;border:none;overflow:visible;font:inherit;color:inherit;text-transform:none;padding:0;background:0 0;display:inline-block;-moz-box-sizing:content-box;box-sizing:content-box;width:20px;line-height:20px;text-align:center;vertical-align:middle;opacity:.3}.uk-close:after{display:block;content:"\f00d";font-family:FontAwesome}.uk-close:focus,.uk-close:hover{opacity:.5;outline:0;color:inherit;text-decoration:none;cursor:pointer}.uk-close-alt{padding:2px;border-radius:50%;background:#fff;opacity:1;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 0 6px rgba(0,0,0,.3)}.uk-close-alt:focus,.uk-close-alt:hover{opacity:1}.uk-close-alt:after{opacity:.5}.uk-close-alt:focus:after,.uk-close-alt:hover:after{opacity:.8}.uk-badge{display:inline-block;padding:0 5px;background:#00a8e6;font-size:10px;font-weight:700;line-height:14px;color:#fff;text-align:center;vertical-align:middle;text-transform:none;border:1px solid rgba(0,0,0,.06);border-radius:2px;text-shadow:0 1px 0 rgba(0,0,0,.1)}a.uk-badge:hover{color:#fff}.uk-badge-notification{-moz-box-sizing:border-box;box-sizing:border-box;min-width:18px;border-radius:500px;font-size:12px;line-height:18px}.uk-badge-success{background-color:#8cc14c}.uk-badge-warning{background-color:#faa732}.uk-badge-danger{background-color:#da314b}.uk-alert{margin-bottom:15px;padding:10px;background:#ebf7fd;color:#2d7091;border:1px solid rgba(45,112,145,.3);border-radius:4px;text-shadow:0 1px 0 #fff}*+.uk-alert{margin-top:15px}.uk-alert>:last-child{margin-bottom:0}.uk-alert h1,.uk-alert h2,.uk-alert h3,.uk-alert h4,.uk-alert h5,.uk-alert h6{color:inherit}.uk-alert>.uk-close:first-child{float:right}.uk-alert>.uk-close:first-child+*{margin-top:0}.uk-alert-success{background:#f2fae3;color:#659f13;border-color:rgba(101,159,19,.3)}.uk-alert-warning{background:#fffceb;color:#e28327;border-color:rgba(226,131,39,.3)}.uk-alert-danger{background:#fff1f0;color:#d85030;border-color:rgba(216,80,48,.3)}.uk-alert-large{padding:20px}.uk-alert-large>.uk-close:first-child{margin:-10px -10px 0 0}.uk-thumbnail{display:inline-block;max-width:100%;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:4px;border:1px solid #ddd;background:#fff;border-radius:4px}a.uk-thumbnail:focus,a.uk-thumbnail:hover{border-color:#aaa;background-color:#fff;text-decoration:none;outline:0}.uk-thumbnail-caption{padding-top:4px;text-align:center;color:#444}.uk-thumbnail-mini{width:150px}.uk-thumbnail-small{width:200px}.uk-thumbnail-medium{width:300px}.uk-thumbnail-large{width:400px}.uk-thumbnail-expand,.uk-thumbnail-expand>img{width:100%}.uk-overlay{display:inline-block;position:relative;max-width:100%;vertical-align:middle;overflow:hidden}.uk-overlay>:first-child{margin-bottom:0}.uk-overlay-area{position:absolute;top:0;bottom:0;left:0;right:0;background:rgba(0,0,0,.3);opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear;-webkit-transform:translate3d(0,0,0)}.uk-overlay-toggle.uk-hover .uk-overlay-area,.uk-overlay-toggle:hover .uk-overlay-area,.uk-overlay.uk-hover .uk-overlay-area,.uk-overlay:hover .uk-overlay-area{opacity:1}.uk-overlay-area:empty:before{content:"\f002";position:absolute;top:50%;left:50%;width:50px;height:50px;margin-top:-25px;margin-left:-25px;font-size:50px;line-height:1;font-family:FontAwesome;text-align:center;color:#fff}.uk-overlay-area:not(:empty){font-size:0}.uk-overlay-area:not(:empty):before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-overlay-area-content{display:inline-block;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;vertical-align:middle;font-size:1rem;text-align:center;padding:0 15px;color:#fff}.uk-overlay-area-content>:last-child{margin-bottom:0}.uk-overlay-area-content a:not([class]),.uk-overlay-area-content a:not([class]):hover{color:inherit}.uk-overlay-caption{position:absolute;bottom:0;left:0;right:0;padding:15px;background:rgba(0,0,0,.5);color:#fff;opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear;-webkit-transform:translate3d(0,0,0)}.uk-overlay-toggle.uk-hover .uk-overlay-caption,.uk-overlay-toggle:hover .uk-overlay-caption,.uk-overlay.uk-hover .uk-overlay-caption,.uk-overlay:hover .uk-overlay-caption{opacity:1}.uk-progress{-moz-box-sizing:border-box;box-sizing:border-box;height:20px;margin-bottom:15px;background:#f5f5f5;overflow:hidden;line-height:20px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);border-radius:4px}*+.uk-progress{margin-top:15px}.uk-progress-bar{width:0;height:100%;background:#00a8e6;float:left;-webkit-transition:width .6s ease;transition:width .6s ease;font-size:12px;color:#fff;text-align:center;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-progress-mini{height:6px}.uk-progress-small{height:12px}.uk-progress-success .uk-progress-bar{background-color:#8cc14c}.uk-progress-warning .uk-progress-bar{background-color:#faa732}.uk-progress-danger .uk-progress-bar{background-color:#da314b}.uk-progress-striped .uk-progress-bar{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: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-size:30px 30px}.uk-progress-striped.uk-active .uk-progress-bar{-webkit-animation:uk-progress-bar-stripes 2s linear infinite;animation:uk-progress-bar-stripes 2s linear infinite}@-webkit-keyframes uk-progress-bar-stripes{0%{background-position:0 0}100%{background-position:30px 0}}@keyframes uk-progress-bar-stripes{0%{background-position:0 0}100%{background-position:30px 0}}.uk-progress-mini,.uk-progress-small{border-radius:500px}[class*=uk-animation-]{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}@media screen{[data-uk-scrollspy*=uk-animation-]{opacity:0}}.uk-animation-fade{-webkit-animation-name:uk-fade;animation-name:uk-fade;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-timing-function:linear!important;animation-timing-function:linear!important}.uk-animation-scale-up{-webkit-animation-name:uk-fade-scale-02;animation-name:uk-fade-scale-02}.uk-animation-scale-down{-webkit-animation-name:uk-fade-scale-18;animation-name:uk-fade-scale-18}.uk-animation-slide-top{-webkit-animation-name:uk-fade-top;animation-name:uk-fade-top}.uk-animation-slide-bottom{-webkit-animation-name:uk-fade-bottom;animation-name:uk-fade-bottom}.uk-animation-slide-left{-webkit-animation-name:uk-fade-left;animation-name:uk-fade-left}.uk-animation-slide-right{-webkit-animation-name:uk-fade-right;animation-name:uk-fade-right}.uk-animation-scale{-webkit-animation-name:uk-scale-12;animation-name:uk-scale-12}.uk-animation-shake{-webkit-animation-name:uk-shake;animation-name:uk-shake}.uk-animation-reverse{-webkit-animation-direction:reverse;animation-direction:reverse;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}.uk-animation-15{-webkit-animation-duration:15s;animation-duration:15s}.uk-animation-top-left{-webkit-transform-origin:0 0;transform-origin:0 0}.uk-animation-top-center{-webkit-transform-origin:50% 0;transform-origin:50% 0}.uk-animation-top-right{-webkit-transform-origin:100% 0;transform-origin:100% 0}.uk-animation-middle-left{-webkit-transform-origin:0 50%;transform-origin:0 50%}.uk-animation-middle-right{-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.uk-animation-bottom-left{-webkit-transform-origin:0 100%;transform-origin:0 100%}.uk-animation-bottom-center{-webkit-transform-origin:50% 100%;transform-origin:50% 100%}.uk-animation-bottom-right{-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.uk-animation-hover:not(:hover),.uk-animation-hover:not(:hover) [class*=uk-animation-],.uk-touch .uk-animation-hover:not(.uk-hover),.uk-touch .uk-animation-hover:not(.uk-hover) [class*=uk-animation-]{-webkit-animation-name:none;animation-name:none}@-webkit-keyframes uk-fade{0%{opacity:0}100%{opacity:1}}@keyframes uk-fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes uk-fade-top{0%{opacity:0;-webkit-transform:translateY(-100%)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-fade-top{0%{opacity:0;transform:translateY(-100%)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-fade-bottom{0%{opacity:0;-webkit-transform:translateY(100%)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-fade-bottom{0%{opacity:0;transform:translateY(100%)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-fade-left{0%{opacity:0;-webkit-transform:translateX(-100%)}100%{opacity:1;-webkit-transform:translateX(0)}}@keyframes uk-fade-left{0%{opacity:0;transform:translateX(-100%)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes uk-fade-right{0%{opacity:0;-webkit-transform:translateX(100%)}100%{opacity:1;-webkit-transform:translateX(0)}}@keyframes uk-fade-right{0%{opacity:0;transform:translateX(100%)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes uk-fade-scale-02{0%{opacity:0;-webkit-transform:scale(0.2)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-02{0%{opacity:0;transform:scale(0.2)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-fade-scale-15{0%{opacity:0;-webkit-transform:scale(1.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-15{0%{opacity:0;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-fade-scale-18{0%{opacity:0;-webkit-transform:scale(1.8)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-18{0%{opacity:0;transform:scale(1.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-slide-left{0%{-webkit-transform:translateX(-100%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-right{0%{-webkit-transform:translateX(100%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-right{0%{transform:translateX(100%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-left-33{0%{-webkit-transform:translateX(33%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-left-33{0%{transform:translateX(33%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-right-33{0%{-webkit-transform:translateX(-33%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-right-33{0%{transform:translateX(-33%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-scale-12{0%{-webkit-transform:scale(1.2)}100%{-webkit-transform:scale(1)}}@keyframes uk-scale-12{0%{transform:scale(1.2)}100%{transform:scale(1)}}@-webkit-keyframes uk-rotate{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@keyframes uk-rotate{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-webkit-keyframes uk-shake{0%,100%{-webkit-transform:translateX(0)}10%{-webkit-transform:translateX(-9px)}20%{-webkit-transform:translateX(8px)}30%{-webkit-transform:translateX(-7px)}40%{-webkit-transform:translateX(6px)}50%{-webkit-transform:translateX(-5px)}60%{-webkit-transform:translateX(4px)}70%{-webkit-transform:translateX(-3px)}80%{-webkit-transform:translateX(2px)}90%{-webkit-transform:translateX(-1px)}}@keyframes uk-shake{0%,100%{transform:translateX(0)}10%{transform:translateX(-9px)}20%{transform:translateX(8px)}30%{transform:translateX(-7px)}40%{transform:translateX(6px)}50%{transform:translateX(-5px)}60%{transform:translateX(4px)}70%{transform:translateX(-3px)}80%{transform:translateX(2px)}90%{transform:translateX(-1px)}}@-webkit-keyframes uk-slide-top-fixed{0%{opacity:0;-webkit-transform:translateY(-10px)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-slide-top-fixed{0%{opacity:0;transform:translateY(-10px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-slide-bottom-fixed{0%{opacity:0;-webkit-transform:translateY(10px)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-slide-bottom-fixed{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}.uk-dropdown{display:none;position:absolute;top:100%;left:0;z-index:1020;-moz-box-sizing:border-box;box-sizing:border-box;width:200px;margin-top:5px;padding:15px;background:#fff;color:#444;font-size:1rem;vertical-align:top;border:1px solid #ddd;border-radius:4px}.uk-open>.uk-dropdown{display:block;-webkit-animation:uk-fade .2s ease-in-out;animation:uk-fade .2s ease-in-out;-webkit-transform-origin:0 0;transform-origin:0 0}.uk-dropdown-flip{left:auto;right:0}.uk-dropdown-up{top:auto;bottom:100%;margin-top:auto;margin-bottom:5px}.uk-dropdown .uk-nav{margin:0 -15px}.uk-dropdown-grid>[class*=uk-width-]>.uk-panel+.uk-panel,.uk-grid .uk-dropdown-grid+.uk-dropdown-grid{margin-top:15px}@media (min-width:768px){.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid{margin-left:-15px;margin-right:-15px}.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*=uk-width-]{padding-left:15px;padding-right:15px}.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2){border-left:1px solid #ddd}.uk-dropdown-width-2:not(.uk-dropdown-stack){width:400px}.uk-dropdown-width-3:not(.uk-dropdown-stack){width:600px}.uk-dropdown-width-4:not(.uk-dropdown-stack){width:800px}.uk-dropdown-width-5:not(.uk-dropdown-stack){width:1000px}}@media (max-width:767px){.uk-dropdown-grid>[class*=uk-width-]{width:100%}.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2){margin-top:15px}}.uk-dropdown-stack>.uk-dropdown-grid>[class*=uk-width-]{width:100%}.uk-dropdown-stack>.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2){margin-top:15px}.uk-dropdown-small{min-width:150px;width:auto;padding:5px;white-space:nowrap}.uk-dropdown-small .uk-nav{margin:0 -5px}.uk-dropdown-navbar{margin-top:6px;background:#fff;color:#444;left:-1px;border:1px solid #ddd;border-radius:4px}.uk-open>.uk-dropdown-navbar{-webkit-animation:uk-slide-top-fixed .2s ease-in-out;animation:uk-slide-top-fixed .2s ease-in-out}.uk-dropdown-scrollable{overflow-y:auto;max-height:200px}.uk-dropdown-navbar.uk-dropdown-flip{left:auto}.uk-modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1010;overflow-y:auto;-webkit-overflow-scrolling:touch;background:rgba(0,0,0,.6);opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.uk-modal.uk-open{opacity:1}.uk-modal-page,.uk-modal-page body{overflow:hidden}.uk-modal-dialog{position:relative;-moz-box-sizing:border-box;box-sizing:border-box;margin:50px auto;padding:20px;width:600px;max-width:100%;max-width:calc(100% - 20px);min-height:200px;background:#fff;opacity:0;-webkit-transform:translateY(-100px);transform:translateY(-100px);-webkit-transition:opacity .3s linear,-webkit-transform .3s ease-out;transition:opacity .3s linear,transform .3s ease-out;border-radius:4px;box-shadow:0 0 10px rgba(0,0,0,.3)}@media (max-width:767px){.uk-modal-dialog{width:auto;margin:10px auto}}.uk-open .uk-modal-dialog{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}.uk-modal-dialog>:not([class*=uk-modal-]):last-child{margin-bottom:0}.uk-modal-dialog>.uk-close:first-child{margin:-10px -10px 0 0;float:right}.uk-modal-dialog>.uk-close:first-child+:not([class*=uk-modal-]){margin-top:0}.uk-modal-dialog-lightbox{margin:15px auto;padding:0;max-width:95%;max-width:calc(100% - 30px);border-radius:0}.uk-modal-dialog-lightbox>.uk-close:first-child{position:absolute;top:-12px;right:-12px;margin:0;float:none}@media (max-width:767px){.uk-modal-dialog-lightbox>.uk-close:first-child{top:-7px;right:-7px}}@media (min-width:768px){.uk-modal-dialog-large{width:930px}}@media (min-width:1220px){.uk-modal-dialog-large{width:1130px}}.uk-modal-header{margin:-20px -20px 15px;padding:20px;border-bottom:1px solid #ddd;border-radius:4px 4px 0 0;background:#fafafa}.uk-modal-footer{margin:15px -20px -20px;padding:20px;border-top:1px solid #ddd;border-radius:0 0 4px 4px;background:#fafafa}.uk-modal-footer>:last-child,.uk-modal-header>:last-child{margin-bottom:0}.uk-modal-caption{position:absolute;left:0;right:0;bottom:-20px;margin-bottom:-10px;color:#fff;text-align:center}.uk-modal-spinner{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-size:25px;color:#ddd}.uk-modal-spinner:after{content:"\f110";font-family:FontAwesome;-webkit-animation:uk-rotate 2s infinite linear;animation:uk-rotate 2s infinite linear}.uk-offcanvas{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;touch-action:none;background:rgba(0,0,0,.1)}.uk-offcanvas.uk-active{display:block}.uk-offcanvas-page{position:fixed;-webkit-transition:margin-left .3s ease-in-out;transition:margin-left .3s ease-in-out}.uk-offcanvas-bar{position:fixed;top:0;bottom:0;left:0;-webkit-transform:translateX(-100%);transform:translateX(-100%);z-index:1001;width:270px;max-width:100%;background:#333;overflow-y:auto;-webkit-overflow-scrolling:touch;-webkit-transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;-ms-scroll-chaining:none}.uk-offcanvas.uk-active .uk-offcanvas-bar.uk-offcanvas-bar-show{-webkit-transform:translateX(0%);transform:translateX(0%)}.uk-offcanvas-bar-flip{left:auto;right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.uk-offcanvas .uk-panel{margin:20px 15px;color:#777;text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-offcanvas .uk-panel a:not([class]),.uk-offcanvas .uk-panel-title{color:#ccc}.uk-offcanvas .uk-panel a:not([class]):hover{color:#fff}.uk-offcanvas-bar:after{content:"";display:block;position:absolute;top:0;bottom:0;right:0;width:1px;background:rgba(0,0,0,.6);box-shadow:0 0 5px 2px rgba(0,0,0,.6)}.uk-offcanvas-bar-flip:after{right:auto;left:0;width:1px;background:rgba(0,0,0,.6);box-shadow:0 0 5px 2px rgba(0,0,0,.6)}.uk-switcher{margin:0;padding:0;list-style:none}.uk-switcher>:not(.uk-active){display:none}.uk-tooltip{display:none;position:absolute;z-index:1030;-moz-box-sizing:border-box;box-sizing:border-box;max-width:200px;padding:5px 8px;background:#333;color:rgba(255,255,255,.7);font-size:12px;line-height:18px;text-align:center;border-radius:3px;text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-tooltip:after{content:"";display:block;position:absolute;width:0;height:0;border:5px dashed #333}.uk-tooltip-top-left:after,.uk-tooltip-top-right:after,.uk-tooltip-top:after{bottom:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent;border-top-color:#333}.uk-tooltip-bottom-left:after,.uk-tooltip-bottom-right:after,.uk-tooltip-bottom:after{top:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent;border-bottom-color:#333}.uk-tooltip-bottom:after,.uk-tooltip-top:after{left:50%;margin-left:-5px}.uk-tooltip-bottom-left:after,.uk-tooltip-top-left:after{left:10px}.uk-tooltip-bottom-right:after,.uk-tooltip-top-right:after{right:10px}.uk-tooltip-left:after{right:-5px;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent;border-left-color:#333}.uk-tooltip-right:after{left:-5px;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent;border-right-color:#333}.uk-text-small{font-size:11px;line-height:16px}.uk-text-large{font-size:18px;line-height:24px;font-weight:400}.uk-text-bold{font-weight:700}.uk-text-muted{color:#999!important}.uk-text-primary{color:#2d7091!important}.uk-text-success{color:#659f13!important}.uk-text-warning{color:#e28327!important}.uk-text-danger{color:#d85030!important}.uk-text-contrast{color:#fff!important}.uk-text-left{text-align:left!important}.uk-text-right{text-align:right!important}.uk-text-center{text-align:center!important}.uk-text-justify{text-align:justify!important}.uk-text-top{vertical-align:top!important}.uk-text-middle{vertical-align:middle!important}.uk-text-bottom{vertical-align:bottom!important}@media (max-width:959px){.uk-text-center-medium{text-align:center!important}.uk-text-left-medium{text-align:left!important}}@media (max-width:767px){.uk-text-center-small{text-align:center!important}.uk-text-left-small{text-align:left!important}}.uk-text-nowrap{white-space:nowrap}.uk-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.uk-text-break{word-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.uk-container{-moz-box-sizing:border-box;box-sizing:border-box;max-width:980px;padding:0 25px}@media (min-width:1220px){.uk-container{max-width:1200px;padding:0 35px}}.uk-container:after,.uk-container:before{content:"";display:table}.uk-container:after{clear:both}.uk-container-center{margin-left:auto;margin-right:auto}.uk-clearfix:before{content:"";display:table-cell}.uk-clearfix:after{content:"";display:table;clear:both}.uk-nbfc{overflow:hidden}.uk-nbfc-alt{display:table-cell;width:10000px}.uk-float-left{float:left}.uk-float-right{float:right}[class*=uk-float-]{max-width:100%}[class*=uk-align-]{display:block;margin-bottom:15px}.uk-align-left{margin-right:15px;float:left}.uk-align-right{margin-left:15px;float:right}@media (min-width:768px){.uk-align-medium-left{margin-right:15px;margin-bottom:15px;float:left}.uk-align-medium-right{margin-left:15px;margin-bottom:15px;float:right}}.uk-align-center{margin-left:auto;margin-right:auto}.uk-vertical-align{font-size:0}.uk-vertical-align:before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-vertical-align-bottom,.uk-vertical-align-middle{display:inline-block;max-width:100%;font-size:1rem}.uk-vertical-align-middle{vertical-align:middle}.uk-vertical-align-bottom{vertical-align:bottom}[class*=uk-height]{-moz-box-sizing:border-box;box-sizing:border-box}.uk-height-1-1{height:100%}.uk-height-viewport{height:100vh;min-height:600px}.uk-responsive-height,.uk-responsive-width{-moz-box-sizing:border-box;box-sizing:border-box}.uk-responsive-width{max-width:100%!important;height:auto}.uk-responsive-height{max-height:100%;width:auto}.uk-margin{margin-bottom:15px}*+.uk-margin{margin-top:15px}.uk-margin-top{margin-top:15px!important}.uk-margin-bottom{margin-bottom:15px!important}.uk-margin-left{margin-left:15px!important}.uk-margin-right{margin-right:15px!important}.uk-margin-large{margin-bottom:50px}*+.uk-margin-large{margin-top:50px}.uk-margin-large-top{margin-top:50px!important}.uk-margin-large-bottom{margin-bottom:50px!important}.uk-margin-large-left{margin-left:50px!important}.uk-margin-large-right{margin-right:50px!important}.uk-margin-small{margin-bottom:5px}*+.uk-margin-small{margin-top:5px}.uk-margin-small-top{margin-top:5px!important}.uk-margin-small-bottom{margin-bottom:5px!important}.uk-margin-small-left{margin-left:5px!important}.uk-margin-small-right{margin-right:5px!important}.uk-margin-remove{margin:0!important}.uk-margin-top-remove{margin-top:0!important}.uk-margin-bottom-remove{margin-bottom:0!important}.uk-border-circle{border-radius:50%}.uk-border-rounded{border-radius:5px}@media (min-width:768px){.uk-heading-large{font-size:52px;line-height:64px}}.uk-link-muted,.uk-link-muted a,.uk-link-muted a:hover,.uk-link-muted:hover{color:#444}.uk-link-reset,.uk-link-reset a,.uk-link-reset a:hover,.uk-link-reset:hover{color:inherit;text-decoration:none}.uk-scrollable-text{height:300px;overflow-y:scroll;-webkit-overflow-scrolling:touch;resize:both}.uk-scrollable-box{-moz-box-sizing:border-box;box-sizing:border-box;height:170px;padding:10px;border:1px solid #ddd;overflow:auto;-webkit-overflow-scrolling:touch;resize:both;border-radius:3px}.uk-scrollable-box>:last-child{margin-bottom:0}.uk-overflow-container{overflow:auto;-webkit-overflow-scrolling:touch}.uk-overflow-container>:last-child{margin-bottom:0}.uk-position-bottom,.uk-position-top{position:absolute!important;width:100%}.uk-position-top{top:0}.uk-position-bottom{bottom:0}.uk-position-cover{position:absolute;top:0;bottom:0;left:0;right:0}.uk-position-relative{position:relative!important}.uk-display-block{display:block!important}.uk-display-inline{display:inline!important}.uk-display-inline-block{display:inline-block!important}@media (min-width:960px){.uk-hidden-large,.uk-visible-medium,.uk-visible-small{display:none!important}}@media (min-width:768px) and (max-width:959px){.uk-hidden-medium,.uk-visible-large,.uk-visible-small{display:none!important}}@media (max-width:767px){.uk-hidden-small,.uk-visible-large,.uk-visible-medium{display:none!important}}.uk-hidden{display:none!important;visibility:hidden!important}.uk-invisible{visibility:hidden!important}.uk-visible-hover:hover .uk-hidden,.uk-visible-hover:hover .uk-invisible{display:block!important;visibility:visible!important}.uk-visible-hover-inline:hover .uk-hidden,.uk-visible-hover-inline:hover .uk-invisible{display:inline-block!important;visibility:visible!important}.uk-notouch .uk-hidden-notouch,.uk-touch .uk-hidden-touch{display:none!important}@media print{*{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}} -------------------------------------------------------------------------------- /assets/images/ipad-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coodoo/react-alt-isomorphic-example/3ab1cdddf2b26795e3ebe41ca28f48495c2fd968/assets/images/ipad-mini.png -------------------------------------------------------------------------------- /assets/images/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coodoo/react-alt-isomorphic-example/3ab1cdddf2b26795e3ebe41ca28f48495c2fd968/assets/images/react.png -------------------------------------------------------------------------------- /assets/images/sucker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coodoo/react-alt-isomorphic-example/3ab1cdddf2b26795e3ebe41ca28f48495c2fd968/assets/images/sucker.png -------------------------------------------------------------------------------- /assets/images/t-shirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coodoo/react-alt-isomorphic-example/3ab1cdddf2b26795e3ebe41ca28f48495c2fd968/assets/images/t-shirt.png -------------------------------------------------------------------------------- /flux.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coodoo/react-alt-isomorphic-example/3ab1cdddf2b26795e3ebe41ca28f48495c2fd968/flux.tgz -------------------------------------------------------------------------------- /js/actions/ActionCreators.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var k = "ff"; 4 | 5 | var WebAPIUtils = require('../utils/WebAPIUtils'); 6 | var Promise = require('es6-promise').Promise; 7 | 8 | class ActionCreators { 9 | 10 | constructor() { 11 | 12 | // 方便法門,自動生成三支 public action 供操作 13 | this.generateActions( 14 | 'receiveProducts', 15 | 'addToCart', 16 | 'finishCheckout', 17 | 'loadAllProducts', 18 | 'loadOneProduct' 19 | ); 20 | } 21 | 22 | // 23 | readAll(resolve) { 24 | 25 | var that = this; 26 | 27 | // 這樣 server 上才知道何時 data fetching 已完成,可以 react.renderToString() 了 28 | return WebAPIUtils 29 | 30 | .getAllProducts() 31 | 32 | .then(function success(arr) { 33 | // console.log( '\n ActionCreators 取回 products: ', arr ); 34 | // action 取完資料後,必然是送入 Store 中保存,才能讓 view 更新 35 | // that.actions.loadAllProducts(arr); 36 | that.alt.getActions('ActionCreators').loadAllProducts(arr); 37 | }) 38 | } 39 | 40 | // 41 | readOne(id) { 42 | 43 | // 返還 Promise 出去, 44 | // 這樣 server 上才知道何時 data fetching 已完成,可以 react.renderToString() 了 45 | return WebAPIUtils 46 | 47 | .getOneProduct(id) 48 | 49 | .then(product => { 50 | 51 | // action 取完資料後,必然是送入 Store 中保存,才能讓 view 更新 52 | this.alt.getActions('ActionCreators').loadOneProduct(product); 53 | 54 | }) 55 | 56 | } 57 | 58 | // 這支沒辦法自動生成,因為多了操作 WebAPIUtil 指令 59 | cartCheckout(products) { 60 | var that = this; 61 | 62 | // 注意因此要自已 dispatch() 事件,這裏廣播的事件名稱就是 cartCheckout, 將來對應到 store 裏的 onCartCheckout handler 63 | this.dispatch(products); 64 | WebAPIUtils.checkoutProducts(products) 65 | .then(function(products) { 66 | // jxnote: 不能用 this.dispatch(),因為會 actionType 名稱會抓成 cartCheckout 67 | that.actions.finishCheckout(products); 68 | }) 69 | } 70 | } 71 | 72 | module.exports = ActionCreators; 73 | // alt.createActions(ActionsCreators, exports); 74 | -------------------------------------------------------------------------------- /js/alt.js: -------------------------------------------------------------------------------- 1 | 2 | // 用這方式來確保是 singleton,等同於 Alt.getInstance() 3 | var Alt = require('alt'); 4 | module.exports = new Alt(); 5 | -------------------------------------------------------------------------------- /js/api/products.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"id": 1, "title": "iPad 4 Mini", "price": 500.01, "inventory": 2, "image": "/assets/images/ipad-mini.png"}, 3 | {"id": 2, "title": "H&M T-Shirt White", "price": 10.99, "inventory": 10, "image": "/assets/images/t-shirt.png"}, 4 | {"id": 3, "title": "Charli XCX - Sucker CD", "price": 19.99, "inventory": 5, "image": "/assets/images/sucker.png"} 5 | ] 6 | -------------------------------------------------------------------------------- /js/api/shop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mocking client-server processing 3 | */ 4 | 'use strict'; 5 | 6 | var Shop = exports; 7 | 8 | var _products = require('./products.json'); 9 | 10 | var TIMEOUT = 100; 11 | 12 | Shop.getProducts = function (timeout) { 13 | timeout = timeout || TIMEOUT; 14 | return new Promise( (resolve, reject) => { 15 | setTimeout(function () { 16 | resolve(_products); 17 | }, timeout); 18 | 19 | }) 20 | }; 21 | 22 | Shop.getOneProduct = function (id, timeout) { 23 | 24 | timeout = timeout || TIMEOUT; 25 | 26 | return new Promise( (resolve, reject) => { 27 | 28 | setTimeout(function () { 29 | 30 | for(let item of _products ){ 31 | if( item.id == id ){ 32 | resolve(item); 33 | } 34 | } 35 | 36 | // 如果走到這一行,代表前面找不到需要的商品,自然就拋錯了 37 | // console.log( 'shop > 失敗' ); 38 | reject( 'Product not found' ); 39 | 40 | }, timeout); 41 | 42 | }) 43 | }; 44 | 45 | Shop.buyProducts = function (payload, timeout) { 46 | timeout = timeout || TIMEOUT; 47 | 48 | return new Promise( (resolve, reject) => { 49 | setTimeout(function () { 50 | resolve(payload); 51 | }, timeout); 52 | 53 | }) 54 | }; 55 | -------------------------------------------------------------------------------- /js/boot.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('es5-shim'); 4 | require('es5-shim/es5-sham'); 5 | 6 | var React = require('react'); 7 | var App = require('./components/App.jsx'); 8 | 9 | var Iso = require('iso'); 10 | var Flux = require('./flux'); 11 | var flux = new Flux(); 12 | 13 | // 這是 client app 負責將 server encode 好的資料還還並灌入 store 中 14 | Iso.bootstrap(function (state, meta, container) { 15 | 16 | flux.bootstrap(state); 17 | 18 | // 注意這裏將 flux instance 做為參數傳入 react app 內了 19 | React.render( React.createElement(App, {flux: flux}), container); 20 | }); 21 | 22 | // 示範如果不需 isomorphic 時,此手法仍可當作一般 flux 來啟動程式 23 | // flux.bootstrap(state); 24 | // React.render( React.createElement(App, {flux: flux}), document.querySelector('#container') ); 25 | -------------------------------------------------------------------------------- /js/components/App.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var React = require('react'); 4 | var CartContainer = require('./CartContainer.jsx'); 5 | var ProductsContainer = require('./ProductsContainer.jsx'); 6 | var ProductsDetail = require('./ProductDetail.jsx'); 7 | 8 | // 9 | var App = React.createClass({ 10 | 11 | // root view 將 flux 物件設入 context 中 12 | // 所有 child component 即可存取 13 | childContextTypes: { 14 | flux: React.PropTypes.object.isRequired 15 | }, 16 | 17 | getChildContext: function() { 18 | // console.log( '\n\n取 getChildContext() 時的 props: ', this.props ); 19 | return { 20 | flux: this.props.flux || new Error('flux not found!') 21 | }; 22 | }, 23 | 24 | _getStateFromStores: function() { 25 | return { 26 | currentView: this.RouteStore.getCurrentView(), 27 | currentProduct: this.ProductStore.getCurrentProduct(), 28 | products: this.ProductStore.getProducts() 29 | } 30 | }, 31 | 32 | 33 | getInitialState: function() { 34 | this.RouteStore = this.props.flux.getStore('RouteStore'); 35 | this.ProductStore = this.props.flux.getStore('ProductStore'); 36 | return this._getStateFromStores(); 37 | }, 38 | 39 | componentDidMount: function() { 40 | this.RouteStore.listen(this._onChange); 41 | this.ProductStore.listen(this._onChange); 42 | }, 43 | 44 | componentWillUnmount: function() { 45 | this.RouteStore.unlisten(this._onChange); 46 | this.ProductStore.unlisten(this._onChange); 47 | }, 48 | 49 | _onChange: function() { 50 | this.setState(this._getStateFromStores()); 51 | }, 52 | 53 | render: function() { 54 | 55 | var view; 56 | 57 | if (this.state.currentView == 'master') { 58 | view = < ProductsContainer / > ; 59 | } else { 60 | view = < ProductsDetail 61 | product = { 62 | this.state.currentProduct 63 | } 64 | />; 65 | } 66 | 67 | return ( < div > { 68 | view 69 | } < CartContainer / > 70 | < /div> 71 | ); 72 | } 73 | 74 | }); 75 | 76 | module.exports = App; 77 | -------------------------------------------------------------------------------- /js/components/Cart.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var React = require('react'); 4 | 5 | var Product = React.createClass({ 6 | 7 | render: function () { 8 | return