├── .meteor ├── .gitignore ├── release ├── platforms ├── .finished-upgraders ├── .id ├── packages └── versions ├── server ├── publications.cjsx ├── methods │ └── bundle.cjsx ├── data_auth.cjsx └── seeds.cjsx ├── client ├── style │ ├── bundler.css │ ├── imports │ │ ├── _imports.sass │ │ └── _media-queries.sass │ ├── common │ │ ├── footer.sass │ │ ├── icon-button.sass │ │ └── header.sass │ ├── home │ │ ├── carousel.sass │ │ ├── bundle-thumbnail.sass │ │ ├── bundle-list.sass │ │ └── home.sass │ ├── admin │ │ ├── main.sass │ │ └── index.sass │ ├── auth │ │ ├── login.sass │ │ └── signup.sass │ └── style.sass ├── models │ ├── bundle.cjsx │ └── model │ │ └── model.cjsx ├── components │ ├── common │ │ ├── footer.cjsx │ │ ├── icon-button.cjsx │ │ └── header.cjsx │ ├── home │ │ ├── carousel.cjsx │ │ ├── bundle-thumbnail.cjsx │ │ ├── bundle-list.cjsx │ │ └── home.cjsx │ ├── admin │ │ ├── main.cjsx │ │ ├── index.cjsx │ │ └── create.cjsx │ ├── mixins │ │ └── validation.cjsx │ ├── app.cjsx │ └── auth │ │ ├── login.cjsx │ │ └── signup.cjsx ├── bundler.cjsx ├── bundler.html ├── actions.cjsx ├── stores │ ├── errors_store.cjsx │ ├── bundle_store.cjsx │ └── authentication_store.cjsx └── router.cjsx ├── public ├── images │ └── hero.jpg └── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ ├── glyphicons-halflings-regular.woff2 │ └── glyphicons-halflings-regular.svg ├── lib ├── namespace.cjsx ├── builders.cjsx ├── classnames.js └── vendor │ ├── css │ └── normalize.css │ └── js │ └── reflux.js ├── scss.json └── collections └── bundles.cjsx /.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /server/publications.cjsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.1.0.2 2 | -------------------------------------------------------------------------------- /.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /client/style/bundler.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | -------------------------------------------------------------------------------- /client/style/imports/_imports.sass: -------------------------------------------------------------------------------- 1 | @import "media-queries" 2 | -------------------------------------------------------------------------------- /client/style/common/footer.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .footer 4 | padding: 15px 10px 5 | -------------------------------------------------------------------------------- /client/models/bundle.cjsx: -------------------------------------------------------------------------------- 1 | class Models.Bundle extends Models.Model 2 | method: 'createBundle' 3 | -------------------------------------------------------------------------------- /client/style/home/carousel.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .carousel 4 | img 5 | width: 100% 6 | -------------------------------------------------------------------------------- /public/images/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/bundler/master/public/images/hero.jpg -------------------------------------------------------------------------------- /lib/namespace.cjsx: -------------------------------------------------------------------------------- 1 | @Stores = {} 2 | @Components = {} 3 | @Collections = {} 4 | @Mixins = {} 5 | @Models = {} 6 | -------------------------------------------------------------------------------- /scss.json: -------------------------------------------------------------------------------- 1 | { 2 | "enableAutoprefixer": true, 3 | "includePaths": [ 4 | "client/style/imports" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/bundler/master/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/bundler/master/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/bundler/master/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/bundler/master/public/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /client/models/model/model.cjsx: -------------------------------------------------------------------------------- 1 | class Models.Model 2 | constructor: -> 3 | @attrs = {} 4 | 5 | save: (callback) -> 6 | Meteor.call @method, @attrs, callback 7 | -------------------------------------------------------------------------------- /server/methods/bundle.cjsx: -------------------------------------------------------------------------------- 1 | Meteor.methods 2 | createBundle: (attrs) -> 3 | Collections.Bundles.insert attrs 4 | 5 | editBundle: -> 6 | 7 | deleteBundle: -> 8 | -------------------------------------------------------------------------------- /client/style/admin/main.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .admin-main 4 | .table-header 5 | display: flex 6 | justify-content: flex-end 7 | margin: 0 10px 10px 8 | -------------------------------------------------------------------------------- /client/components/common/footer.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Footer' 3 | 4 | render: -> 5 | return 8 | -------------------------------------------------------------------------------- /client/bundler.cjsx: -------------------------------------------------------------------------------- 1 | if Meteor.isClient 2 | Meteor.startup -> 3 | Utils.buildStores() 4 | Utils.buildComponents() 5 | 6 | Actions.indexBundle() 7 | 8 | _.defer Router.start 9 | -------------------------------------------------------------------------------- /client/bundler.html: -------------------------------------------------------------------------------- 1 | 2 | bundler 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/components/home/carousel.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Carousel' 3 | 4 | render: -> 5 |
6 | I am a carousel 7 |
8 | -------------------------------------------------------------------------------- /client/components/admin/main.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Admin.Main' 3 | 4 | render: -> 5 |
6 | {@props.children} 7 |
8 | -------------------------------------------------------------------------------- /client/style/common/icon-button.sass: -------------------------------------------------------------------------------- 1 | .icon-button 2 | .badge 3 | color: white 4 | background-color: transparent 5 | padding-right: 3px 6 | padding-left: 3px 7 | 8 | span:last-of-type 9 | padding-right: 5px 10 | -------------------------------------------------------------------------------- /client/actions.cjsx: -------------------------------------------------------------------------------- 1 | @Actions = Reflux.createActions [ 2 | 'indexBundle', 3 | 'getBundle', 4 | 'createBundle', 5 | 'removeBundle', 6 | 'createUser', 7 | 'logoutUser', 8 | 'loginUser', 9 | 'clearErrors', 10 | 'addError' 11 | ] 12 | -------------------------------------------------------------------------------- /client/style/imports/_media-queries.sass: -------------------------------------------------------------------------------- 1 | @mixin largescreen 2 | @media(max-width: 1024px) 3 | @content 4 | 5 | @mixin mediumscreen 6 | @media(max-width: 768px) 7 | @content 8 | 9 | @mixin smallscreen 10 | @media(max-width: 568px) 11 | @content 12 | -------------------------------------------------------------------------------- /client/components/mixins/validation.cjsx: -------------------------------------------------------------------------------- 1 | Mixins.Validation = 2 | componentWillMount: -> 3 | Actions.clearErrors() 4 | 5 | errors: -> 6 | return null unless @state.error 7 | 8 |
9 | {@state.error?.reason} 10 |
11 | -------------------------------------------------------------------------------- /client/style/home/bundle-thumbnail.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .bundle-thumbnail 4 | display: inline-block 5 | background: #FEFEFE 6 | border: 2px solid #FAFAFA 7 | margin: 0 2px 15px 8 | min-width: 100% 9 | column-break-inside: avoid 10 | padding: 15px 11 | padding-bottom: 5px 12 | -------------------------------------------------------------------------------- /.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | -------------------------------------------------------------------------------- /client/style/home/bundle-list.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .bundle-list 4 | column-count: 4 5 | column-gap: 15px 6 | column-fill: auto 7 | 8 | @include largescreen 9 | column-count: 3 10 | 11 | @include mediumscreen 12 | column-count: 2 13 | 14 | @include smallscreen 15 | column-count: 1 16 | -------------------------------------------------------------------------------- /client/components/home/bundle-thumbnail.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'BundleThumbnail' 3 | 4 | render: -> 5 |
6 | 7 |
8 |
{@props.title}
9 |
10 |
11 | -------------------------------------------------------------------------------- /client/stores/errors_store.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createStore -> 2 | name: 'Errors' 3 | listenables: Actions 4 | error: null 5 | 6 | onAddError: (error) -> 7 | @error = error 8 | @emitChange() 9 | 10 | onClearErrors: -> 11 | @error = null 12 | @emitChange() 13 | 14 | emitChange: -> 15 | @trigger error: @error 16 | -------------------------------------------------------------------------------- /client/components/home/bundle-list.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'BundleList' 3 | 4 | render: -> 5 |
6 | {@thumbnails()} 7 |
8 | 9 | thumbnails: -> 10 | for bundle in @props.bundles 11 | 12 | -------------------------------------------------------------------------------- /collections/bundles.cjsx: -------------------------------------------------------------------------------- 1 | @Collections.Bundles = new Mongo.Collection 'bundles' 2 | 3 | Bundle = new SimpleSchema 4 | title: 5 | type: String 6 | max: 200 7 | # youtubeId: 8 | # type: String 9 | # createdBy: 10 | # type: String 11 | # likes: 12 | # type: Number 13 | 14 | @Collections.Bundles.attachSchema Bundle 15 | -------------------------------------------------------------------------------- /.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 8eak8a1l76mxrqnpo69 8 | -------------------------------------------------------------------------------- /client/components/common/icon-button.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'IconButton' 3 | 4 | render: -> 5 | 11 | -------------------------------------------------------------------------------- /server/data_auth.cjsx: -------------------------------------------------------------------------------- 1 | sameAuthor: (userId, document) -> 2 | userId is document.createdBy 3 | 4 | Collections.Bundles.allow 5 | insert: (userId, document) -> 6 | sameAuthor userId, document 7 | 8 | update: (userId, document) -> 9 | sameAuthor userId, document 10 | 11 | remove: (userId, document) -> 12 | sameAuthor userId, document 13 | -------------------------------------------------------------------------------- /client/style/admin/index.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .admin-index 4 | padding-left: 0 5 | 6 | li 7 | display: block 8 | border: 1px solid #eee 9 | border-bottom: none 10 | display: flex 11 | padding: 10px 12 | flex-direction: row 13 | justify-content: space-between 14 | 15 | li:last-of-type 16 | border-bottom: 1px solid #eee 17 | -------------------------------------------------------------------------------- /client/style/auth/login.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .authentication-login 4 | display: flex 5 | justify-content: center 6 | align-items: center 7 | 8 | input 9 | outline-width: 0 10 | padding: 2px 11 | 12 | form > div 13 | margin-bottom: 10px 14 | 15 | label 16 | width: 70px 17 | 18 | button 19 | display: block 20 | margin: auto 21 | -------------------------------------------------------------------------------- /client/style/auth/signup.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .authentication-signup 4 | display: flex 5 | justify-content: center 6 | align-items: center 7 | 8 | input 9 | outline-width: 0 10 | padding: 2px 11 | 12 | form > div 13 | margin-bottom: 10px 14 | 15 | label 16 | width: 120px 17 | 18 | button 19 | display: block 20 | margin: auto 21 | -------------------------------------------------------------------------------- /client/style/home/home.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .app-content 4 | section 5 | margin-bottom: 70px 6 | 7 | section .row-wrapper 8 | max-width: 70em 9 | margin: 0 auto 10 | 11 | .notes 12 | display: flex 13 | flex-direction: row 14 | flex-wrap: wrap 15 | justify-content: space-between 16 | 17 | .thumbnail 18 | width: 300px 19 | margin-bottom: 0 20 | text-align: center 21 | -------------------------------------------------------------------------------- /.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-platform 8 | autopublish 9 | insecure 10 | jhartma:cjsx 11 | reactrouter:react-router 12 | aldeed:collection2 13 | accounts-base 14 | accounts-password 15 | fourseven:scss 16 | -------------------------------------------------------------------------------- /client/components/app.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'App' 3 | mixins: [ 4 | Reflux.connect Stores.Authentication 5 | ReactRouter.Navigation 6 | ] 7 | 8 | componentWillMount: -> 9 | window.navigate = @transitionTo 10 | 11 | render: -> 12 | content = @props.children or 13 | 14 |
15 | 16 | {content} 17 | 18 |
19 | -------------------------------------------------------------------------------- /client/style/common/header.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | .header 4 | display: flex 5 | justify-content: space-between 6 | align-items: center 7 | flex-wrap: wrap 8 | 9 | @include mediumscreen 10 | justify-content: center 11 | text-align: center 12 | 13 | h1 14 | display: inline-block 15 | 16 | .nav-button-wrapper 17 | display: flex 18 | 19 | .nav-button 20 | margin-left: 25px 21 | font-size: 16px 22 | 23 | @include mediumscreen 24 | text-align: center 25 | min-width: 100% 26 | 27 | .nav-button 28 | min-width: 20% 29 | margin: auto 30 | -------------------------------------------------------------------------------- /server/seeds.cjsx: -------------------------------------------------------------------------------- 1 | bundles = [ 2 | title: 'Awesome Kit1' 3 | , 4 | title: 'Awesome Kit2' 5 | , 6 | title: 'Awesome Kit3' 7 | , 8 | title: 'Awesome Kit4' 9 | , 10 | title: 'Awesome Kit5' 11 | , 12 | title: 'Awesome Kit6' 13 | , 14 | title: 'Awesome Kit7' 15 | , 16 | title: 'Awesome Kit8' 17 | , 18 | title: 'Awesome Kit9' 19 | , 20 | title: 'Awesome Kit10' 21 | , 22 | title: 'Awesome Kit11' 23 | , 24 | title: 'Awesome Kit12' 25 | ] 26 | 27 | if @Collections.Bundles.find().fetch().length < 3 28 | for bundle in bundles 29 | @Collections.Bundles.insert bundle 30 | -------------------------------------------------------------------------------- /client/stores/bundle_store.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createStore -> 2 | name: 'Bundle' 3 | data: [] 4 | listenables: Actions 5 | 6 | getInitialState: -> 7 | bundles: @data 8 | 9 | init: -> 10 | @collection = Collections.Bundles 11 | Tracker.autorun @onIndexBundle 12 | 13 | fetchAll: -> 14 | @data = @collection.find().fetch() 15 | @emitChange() 16 | 17 | onIndexBundle: -> 18 | @fetchAll() 19 | 20 | onCreateBundle: (model) -> 21 | model.save (error) -> 22 | if error 23 | Actions.addError error 24 | else 25 | navigate '/admin/index' 26 | Actions.clearErrors() 27 | 28 | onRemoveBundle: (id) -> 29 | @collection.remove id 30 | 31 | emitChange: -> 32 | @trigger bundles: @data 33 | -------------------------------------------------------------------------------- /lib/builders.cjsx: -------------------------------------------------------------------------------- 1 | @Utils = {} 2 | 3 | do => 4 | _storeSpecs = [] 5 | _componentSpecs = [] 6 | 7 | Utils.createComponent = (spec) -> 8 | _componentSpecs.push spec 9 | 10 | Utils.buildComponents = -> 11 | for spec in _componentSpecs 12 | spec = spec() 13 | namespace = spec.name.split '.' 14 | if namespace.length is 2 15 | Components[namespace[0]] ||= {} 16 | Components[namespace[0]][namespace[1]] = React.createClass spec 17 | else 18 | Components[spec.name] = React.createClass spec 19 | 20 | Utils.createStore = (spec) -> 21 | _storeSpecs.push spec 22 | 23 | Utils.buildStores = -> 24 | for spec in _storeSpecs 25 | spec = spec() 26 | Stores[spec.name] = Reflux.createStore spec 27 | -------------------------------------------------------------------------------- /client/router.cjsx: -------------------------------------------------------------------------------- 1 | {Router, Route, @Link} = ReactRouter 2 | {history} = ReactRouter.lib.BrowserHistory 3 | 4 | requireAuth = (nextState, transition) -> 5 | unless Meteor.user() 6 | transition.to '/login' 7 | 8 | requireAdmin = (transition) -> 9 | 10 | @Router = 11 | start: -> 12 | React.render 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | , document.body 22 | -------------------------------------------------------------------------------- /client/style/style.sass: -------------------------------------------------------------------------------- 1 | @import "imports" 2 | 3 | html 4 | height: 100% 5 | 6 | .no-gutter 7 | margin-left: -15px 8 | margin-right: -15px 9 | 10 | @include mediumscreen 11 | margin-left: -40px 12 | margin-right: -40px 13 | 14 | .bundler-app 15 | display: flex 16 | height: 100% 17 | flex-direction: column 18 | 19 | .header, 20 | .footer 21 | flex: none 22 | 23 | .app-container 24 | display: flex 25 | flex: 1 0 auto 26 | flex-direction: column 27 | padding: 0 15px 28 | 29 | .header 30 | order: -1 31 | 32 | .app-content 33 | flex: 1 34 | margin-top: 15px 35 | 36 | .app-left-nav 37 | padding: 1em 38 | 39 | @include mediumscreen 40 | .app-container 41 | flex-direction: row 42 | 43 | .app-content 44 | padding: 0 20px 45 | margin: 0 46 | 47 | .app-left-nav 48 | flex: 0 0 12em 49 | -------------------------------------------------------------------------------- /client/components/admin/index.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Admin.Index' 3 | mixins: [ Reflux.connect Stores.Bundle ] 4 | 5 | render: -> 6 |
7 | {@tableHeader()} 8 |
    9 | {@renderBundle bundle for bundle in @state.bundles} 10 |
11 |
12 | 13 | renderBundle: (bundle) -> 14 |
  • 15 |
    {bundle.title}
    16 | 20 |
  • 21 | 22 | tableHeader: -> 23 |
    24 | 25 | 26 | Add 27 | 28 | 29 |
    30 | 31 | onRemoveClick: (_id) -> 32 | Actions.removeBundle _id 33 | -------------------------------------------------------------------------------- /client/stores/authentication_store.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createStore -> 2 | name: 'Authentication' 3 | listenables: Actions 4 | 5 | init: -> 6 | Tracker.autorun @emitChange 7 | @emitChange() 8 | 9 | getInitialState: -> 10 | user: null 11 | 12 | onGetUser: -> 13 | @emitChange() 14 | 15 | onLoginUser: (props) -> 16 | { email, password } = props 17 | Meteor.loginWithPassword email, password, @onAuthenticationSuccess 18 | 19 | onLogoutUser: -> 20 | Meteor.logout() 21 | 22 | onCreateUser: (props) -> 23 | Actions.clearErrors() 24 | Accounts.createUser _.pick(props, 'email', 'username', 'password'), 25 | @onAuthenticationSuccess 26 | 27 | onAuthenticationSuccess: (error) -> 28 | if error 29 | Actions.addError error 30 | else 31 | navigate '/' 32 | @emitChange() 33 | Actions.clearErrors() 34 | 35 | emitChange: -> 36 | @trigger user: Meteor.user() 37 | -------------------------------------------------------------------------------- /client/components/admin/create.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Admin.Create' 3 | mixins: [ 4 | Reflux.connect Stores.Errors 5 | Mixins.Validation 6 | ] 7 | 8 | getInitialState: -> 9 | bundle: new Models.Bundle 10 | 11 | render: -> 12 | console.log @state 13 |
    14 |

    New Bundle

    15 |
    16 | {@errors()} 17 | 18 | {@input 'title', 'Title'} 19 | 20 |
    21 |
    22 | 23 | input: (property, label) -> 24 |
    25 | 26 | 31 |
    32 | 33 | handleChange: (property, event) -> 34 | @state.bundle.attrs[property] = event.target.value 35 | @setState bundle: @state.bundle 36 | 37 | handleSubmit: (e) -> 38 | e.preventDefault() 39 | Actions.createBundle @state.bundle 40 | -------------------------------------------------------------------------------- /client/components/common/header.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Header' 3 | 4 | render: -> 5 | return
    6 | 7 |

    8 | Bundler 9 |

    10 | 11 |
    12 | 13 | Admin Create 14 | 15 | {@authenticationLink()} 16 |
    17 |
    18 | 19 | authenticationLink: -> 20 | if @props.user 21 | [ 22 | 23 | Account 24 | 25 | 26 | Log Out 27 | 28 | ] 29 | else 30 | [ 31 | 32 | Log in 33 | 34 | 35 | Sign up 36 | 37 | ] 38 | 39 | handleLogoutClick: -> 40 | Actions.logoutUser() 41 | -------------------------------------------------------------------------------- /lib/classnames.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Copyright (c) 2015 Jed Watson. 3 | Licensed under the MIT License (MIT), see 4 | http://jedwatson.github.io/classnames 5 | */ 6 | 7 | if(Meteor.isClient){ 8 | (function () { 9 | 'use strict'; 10 | 11 | function classNames () { 12 | 13 | var classes = ''; 14 | 15 | for (var i = 0; i < arguments.length; i++) { 16 | var arg = arguments[i]; 17 | if (!arg) continue; 18 | 19 | var argType = typeof arg; 20 | 21 | if ('string' === argType || 'number' === argType) { 22 | classes += ' ' + arg; 23 | 24 | } else if (Array.isArray(arg)) { 25 | classes += ' ' + classNames.apply(null, arg); 26 | 27 | } else if ('object' === argType) { 28 | for (var key in arg) { 29 | if (arg.hasOwnProperty(key) && arg[key]) { 30 | classes += ' ' + key; 31 | } 32 | } 33 | } 34 | } 35 | 36 | return classes.substr(1); 37 | } 38 | 39 | if (typeof module !== 'undefined' && module.exports) { 40 | module.exports = classNames; 41 | } else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd){ 42 | // AMD. Register as an anonymous module. 43 | define(function () { 44 | return classNames; 45 | }); 46 | } else { 47 | window.classNames = classNames; 48 | } 49 | 50 | }()); 51 | } 52 | -------------------------------------------------------------------------------- /client/components/auth/login.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Authentication.Login' 3 | mixins: [ 4 | Reflux.connect Stores.Errors 5 | Mixins.Validation 6 | ] 7 | 8 | getInitialState: -> 9 | email: '' 10 | password: '' 11 | 12 | render: -> 13 |
    14 |
    15 | {@errors()} 16 |
    17 | 18 | 24 |
    25 | 26 |
    27 | 28 | 34 |
    35 | 36 | 37 |
    38 |
    39 | 40 | handleSubmit: (e) -> 41 | e.preventDefault() 42 | Actions.clearErrors() 43 | Actions.loginUser @state 44 | 45 | handleChange: (prop, event) -> 46 | state = {} 47 | state[prop] = event.target.value 48 | @setState state 49 | -------------------------------------------------------------------------------- /client/components/home/home.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Home' 3 | mixins: [ Reflux.connect Stores.Bundle ] 4 | 5 | componentDidMount: -> 6 | Actions.indexBundle() 7 | 8 | render: -> 9 |
    10 |
    11 | 12 |
    13 |
    14 |
    15 | {@notes()} 16 |
    17 |
    18 |
    19 | 20 |
    21 |
    22 | 23 | notes: -> 24 | for note, i in @_notes() 25 |
    26 |
    27 |
    {note.headline}
    28 |
    29 |
    30 | 31 | onChange: (event, payload) -> 32 | @setState bundles: payload 33 | 34 | _notes: -> 35 | [ 36 | { 37 | headline: 'Something' 38 | text: 'This is a great site This is a great site This is a great site' 39 | image: '' 40 | } 41 | { 42 | headline: 'Something' 43 | text: 'This is a great site This is a great site This is a great site' 44 | image: '' 45 | } 46 | { 47 | headline: 'Something' 48 | text: 'This is a great site This is a great site This is a great site' 49 | image: '' 50 | } 51 | ] 52 | -------------------------------------------------------------------------------- /.meteor/versions: -------------------------------------------------------------------------------- 1 | accounts-base@1.2.0 2 | accounts-password@1.1.1 3 | aldeed:collection2@2.3.3 4 | aldeed:simple-schema@1.3.3 5 | autopublish@1.0.3 6 | autoupdate@1.2.1 7 | babel-compiler@5.8.3_1 8 | babel-runtime@0.1.2 9 | base64@1.0.3 10 | binary-heap@1.0.3 11 | blaze@2.1.2 12 | blaze-tools@1.0.3 13 | boilerplate-generator@1.0.3 14 | callback-hook@1.0.3 15 | check@1.0.5 16 | coffeescript@1.0.6 17 | cosmos:browserify@0.5.0 18 | ddp@1.1.0 19 | deps@1.0.7 20 | ejson@1.0.6 21 | email@1.0.6 22 | fastclick@1.0.3 23 | fourseven:scss@3.2.0 24 | geojson-utils@1.0.3 25 | html-tools@1.0.4 26 | htmljs@1.0.4 27 | http@1.1.0 28 | id-map@1.0.3 29 | insecure@1.0.3 30 | jhartma:cjsx@2.4.1 31 | jquery@1.11.3_2 32 | json@1.0.3 33 | jsx@0.1.5 34 | launch-screen@1.0.2 35 | livedata@1.0.13 36 | localstorage@1.0.3 37 | logging@1.0.7 38 | meteor@1.1.6 39 | meteor-platform@1.2.2 40 | minifiers@1.1.5 41 | minimongo@1.0.8 42 | mobile-status-bar@1.0.3 43 | mongo@1.1.0 44 | npm-bcrypt@0.7.8_2 45 | observe-sequence@1.0.6 46 | ordered-dict@1.0.3 47 | random@1.0.3 48 | react@0.1.4 49 | react-meteor-data@0.1.2 50 | react-runtime@0.13.3_2 51 | react-runtime-dev@0.13.3_2 52 | react-runtime-prod@0.13.3_1 53 | reactive-dict@1.1.0 54 | reactive-var@1.0.5 55 | reactrouter:react-router@0.1.2 56 | reload@1.1.3 57 | retry@1.0.3 58 | routepolicy@1.0.5 59 | service-configuration@1.0.4 60 | session@1.1.0 61 | sha@1.0.3 62 | spacebars@1.0.6 63 | spacebars-compiler@1.0.6 64 | srp@1.0.3 65 | templating@1.1.1 66 | tracker@1.0.7 67 | ui@1.0.6 68 | underscore@1.0.3 69 | url@1.0.4 70 | webapp@1.2.0 71 | webapp-hashing@1.0.3 72 | -------------------------------------------------------------------------------- /client/components/auth/signup.cjsx: -------------------------------------------------------------------------------- 1 | Utils.createComponent -> 2 | name: 'Authentication.Signup' 3 | mixins: [ 4 | Reflux.connect Stores.Errors 5 | Mixins.Validation 6 | ] 7 | 8 | getInitialState: -> 9 | username: '' 10 | email: '' 11 | password: '' 12 | passwordConfirm: '' 13 | 14 | render: -> 15 |
    16 |
    17 | {@errors()} 18 |
    19 | 20 | 26 |
    27 | 28 |
    29 | 30 | 36 |
    37 | 38 |
    39 | 40 | 46 |
    47 | 48 |
    49 | 50 | 56 |
    57 | 58 | 59 |
    60 |
    61 | 62 | handleSubmit: (e) -> 63 | e.preventDefault() 64 | Actions.createUser @state 65 | 66 | handleChange: (prop, event) -> 67 | state = {} 68 | state[prop] = event.target.value 69 | @setState state 70 | -------------------------------------------------------------------------------- /lib/vendor/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /lib/vendor/js/reflux.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Reflux = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0 && 588 | this.children.indexOf('failed') >= 0; 589 | 590 | if (!canHandlePromise){ 591 | throw new Error('Publisher must have "completed" and "failed" child publishers'); 592 | } 593 | 594 | promise.then(function(response) { 595 | return me.completed(response); 596 | }, function(error) { 597 | return me.failed(error); 598 | }); 599 | }, 600 | 601 | /** 602 | * Subscribes the given callback for action triggered, which should 603 | * return a promise that in turn is passed to `this.promise` 604 | * 605 | * @param {Function} callback The callback to register as event handler 606 | */ 607 | listenAndPromise: function(callback, bindContext) { 608 | var me = this; 609 | bindContext = bindContext || this; 610 | this.willCallPromise = (this.willCallPromise || 0) + 1; 611 | 612 | var removeListen = this.listen(function() { 613 | 614 | if (!callback) { 615 | throw new Error('Expected a function returning a promise but got ' + callback); 616 | } 617 | 618 | var args = arguments, 619 | promise = callback.apply(bindContext, args); 620 | return me.promise.call(me, promise); 621 | }, bindContext); 622 | 623 | return function () { 624 | me.willCallPromise--; 625 | removeListen.call(me); 626 | }; 627 | 628 | }, 629 | 630 | /** 631 | * Publishes an event using `this.emitter` (if `shouldEmit` agrees) 632 | */ 633 | trigger: function() { 634 | var args = arguments, 635 | pre = this.preEmit.apply(this, args); 636 | args = pre === undefined ? args : _.isArguments(pre) ? pre : [].concat(pre); 637 | if (this.shouldEmit.apply(this, args)) { 638 | this.emitter.emit(this.eventLabel, args); 639 | } 640 | }, 641 | 642 | /** 643 | * Tries to publish the event on the next tick 644 | */ 645 | triggerAsync: function(){ 646 | var args = arguments,me = this; 647 | _.nextTick(function() { 648 | me.trigger.apply(me, args); 649 | }); 650 | }, 651 | 652 | /** 653 | * Returns a Promise for the triggered action 654 | * 655 | * @return {Promise} 656 | * Resolved by completed child action. 657 | * Rejected by failed child action. 658 | * If listenAndPromise'd, then promise associated to this trigger. 659 | * Otherwise, the promise is for next child action completion. 660 | */ 661 | triggerPromise: function(){ 662 | var me = this; 663 | var args = arguments; 664 | 665 | var canHandlePromise = 666 | this.children.indexOf('completed') >= 0 && 667 | this.children.indexOf('failed') >= 0; 668 | 669 | var promise = _.createPromise(function(resolve, reject) { 670 | // If `listenAndPromise` is listening 671 | // patch `promise` w/ context-loaded resolve/reject 672 | if (me.willCallPromise) { 673 | _.nextTick(function() { 674 | var old_promise_method = me.promise; 675 | me.promise = function (promise) { 676 | promise.then(resolve, reject); 677 | // Back to your regularly schedule programming. 678 | me.promise = old_promise_method; 679 | return me.promise.apply(me, arguments); 680 | }; 681 | me.trigger.apply(me, args); 682 | }); 683 | return; 684 | } 685 | 686 | if (canHandlePromise) { 687 | var removeSuccess = me.completed.listen(function(args) { 688 | removeSuccess(); 689 | removeFailed(); 690 | resolve(args); 691 | }); 692 | 693 | var removeFailed = me.failed.listen(function(args) { 694 | removeSuccess(); 695 | removeFailed(); 696 | reject(args); 697 | }); 698 | } 699 | 700 | me.triggerAsync.apply(me, args); 701 | 702 | if (!canHandlePromise) { 703 | resolve(); 704 | } 705 | }); 706 | 707 | return promise; 708 | } 709 | }; 710 | 711 | },{"./utils":18}],7:[function(require,module,exports){ 712 | /** 713 | * A module of methods that you want to include in all stores. 714 | * This module is consumed by `createStore`. 715 | */ 716 | module.exports = { 717 | }; 718 | 719 | },{}],8:[function(require,module,exports){ 720 | module.exports = function(store, definition) { 721 | for (var name in definition) { 722 | if (Object.getOwnPropertyDescriptor && Object.defineProperty) { 723 | var propertyDescriptor = Object.getOwnPropertyDescriptor(definition, name); 724 | 725 | if (!propertyDescriptor.value || typeof propertyDescriptor.value !== 'function' || !definition.hasOwnProperty(name)) { 726 | continue; 727 | } 728 | 729 | store[name] = definition[name].bind(store); 730 | } else { 731 | var property = definition[name]; 732 | 733 | if (typeof property !== 'function' || !definition.hasOwnProperty(name)) { 734 | continue; 735 | } 736 | 737 | store[name] = property.bind(store); 738 | } 739 | } 740 | 741 | return store; 742 | }; 743 | 744 | },{}],9:[function(require,module,exports){ 745 | var ListenerMethods = require('./ListenerMethods'), 746 | ListenerMixin = require('./ListenerMixin'), 747 | _ = require('./utils'); 748 | 749 | module.exports = function(listenable,key){ 750 | return { 751 | getInitialState: function(){ 752 | if (!_.isFunction(listenable.getInitialState)) { 753 | return {}; 754 | } else if (key === undefined) { 755 | return listenable.getInitialState(); 756 | } else { 757 | return _.object([key],[listenable.getInitialState()]); 758 | } 759 | }, 760 | componentDidMount: function(){ 761 | _.extend(this,ListenerMethods); 762 | var me = this, cb = (key === undefined ? this.setState : function(v){ 763 | if (typeof me.isMounted === "undefined" || me.isMounted() === true) { 764 | me.setState(_.object([key],[v])); 765 | } 766 | }); 767 | this.listenTo(listenable,cb); 768 | }, 769 | componentWillUnmount: ListenerMixin.componentWillUnmount 770 | }; 771 | }; 772 | 773 | },{"./ListenerMethods":4,"./ListenerMixin":5,"./utils":18}],10:[function(require,module,exports){ 774 | var ListenerMethods = require('./ListenerMethods'), 775 | ListenerMixin = require('./ListenerMixin'), 776 | _ = require('./utils'); 777 | 778 | module.exports = function(listenable, key, filterFunc) { 779 | filterFunc = _.isFunction(key) ? key : filterFunc; 780 | return { 781 | getInitialState: function() { 782 | if (!_.isFunction(listenable.getInitialState)) { 783 | return {}; 784 | } else if (_.isFunction(key)) { 785 | return filterFunc.call(this, listenable.getInitialState()); 786 | } else { 787 | // Filter initial payload from store. 788 | var result = filterFunc.call(this, listenable.getInitialState()); 789 | if (typeof(result) !== "undefined") { 790 | return _.object([key], [result]); 791 | } else { 792 | return {}; 793 | } 794 | } 795 | }, 796 | componentDidMount: function() { 797 | _.extend(this, ListenerMethods); 798 | var me = this; 799 | var cb = function(value) { 800 | if (_.isFunction(key)) { 801 | me.setState(filterFunc.call(me, value)); 802 | } else { 803 | var result = filterFunc.call(me, value); 804 | me.setState(_.object([key], [result])); 805 | } 806 | }; 807 | 808 | this.listenTo(listenable, cb); 809 | }, 810 | componentWillUnmount: ListenerMixin.componentWillUnmount 811 | }; 812 | }; 813 | 814 | 815 | },{"./ListenerMethods":4,"./ListenerMixin":5,"./utils":18}],11:[function(require,module,exports){ 816 | var _ = require('./utils'), 817 | ActionMethods = require('./ActionMethods'), 818 | PublisherMethods = require('./PublisherMethods'), 819 | Keep = require('./Keep'), 820 | allowed = {preEmit:1,shouldEmit:1}; 821 | 822 | /** 823 | * Creates an action functor object. It is mixed in with functions 824 | * from the `PublisherMethods` mixin. `preEmit` and `shouldEmit` may 825 | * be overridden in the definition object. 826 | * 827 | * @param {Object} definition The action object definition 828 | */ 829 | var createAction = function(definition) { 830 | 831 | definition = definition || {}; 832 | if (!_.isObject(definition)){ 833 | definition = {actionName: definition}; 834 | } 835 | 836 | for(var a in ActionMethods){ 837 | if (!allowed[a] && PublisherMethods[a]) { 838 | throw new Error("Cannot override API method " + a + 839 | " in Reflux.ActionMethods. Use another method name or override it on Reflux.PublisherMethods instead." 840 | ); 841 | } 842 | } 843 | 844 | for(var d in definition){ 845 | if (!allowed[d] && PublisherMethods[d]) { 846 | throw new Error("Cannot override API method " + d + 847 | " in action creation. Use another method name or override it on Reflux.PublisherMethods instead." 848 | ); 849 | } 850 | } 851 | 852 | definition.children = definition.children || []; 853 | if (definition.asyncResult){ 854 | definition.children = definition.children.concat(["completed","failed"]); 855 | } 856 | 857 | var i = 0, childActions = {}; 858 | for (; i < definition.children.length; i++) { 859 | var name = definition.children[i]; 860 | childActions[name] = createAction(name); 861 | } 862 | 863 | var context = _.extend({ 864 | eventLabel: "action", 865 | emitter: new _.EventEmitter(), 866 | _isAction: true 867 | }, PublisherMethods, ActionMethods, definition); 868 | 869 | var functor = function() { 870 | var triggerType = functor.sync ? "trigger" : 871 | ( _.environment.hasPromises ? "triggerPromise" : "triggerAsync" ); 872 | return functor[triggerType].apply(functor, arguments); 873 | }; 874 | 875 | _.extend(functor,childActions,context); 876 | 877 | Keep.createdActions.push(functor); 878 | 879 | return functor; 880 | 881 | }; 882 | 883 | module.exports = createAction; 884 | 885 | },{"./ActionMethods":2,"./Keep":3,"./PublisherMethods":6,"./utils":18}],12:[function(require,module,exports){ 886 | var _ = require('./utils'), 887 | Keep = require('./Keep'), 888 | mixer = require('./mixer'), 889 | allowed = {preEmit:1,shouldEmit:1}, 890 | bindMethods = require('./bindMethods'); 891 | 892 | /** 893 | * Creates an event emitting Data Store. It is mixed in with functions 894 | * from the `ListenerMethods` and `PublisherMethods` mixins. `preEmit` 895 | * and `shouldEmit` may be overridden in the definition object. 896 | * 897 | * @param {Object} definition The data store object definition 898 | * @returns {Store} A data store instance 899 | */ 900 | module.exports = function(definition) { 901 | 902 | var StoreMethods = require('./StoreMethods'), 903 | PublisherMethods = require('./PublisherMethods'), 904 | ListenerMethods = require('./ListenerMethods'); 905 | 906 | definition = definition || {}; 907 | 908 | for(var a in StoreMethods){ 909 | if (!allowed[a] && (PublisherMethods[a] || ListenerMethods[a])){ 910 | throw new Error("Cannot override API method " + a + 911 | " in Reflux.StoreMethods. Use another method name or override it on Reflux.PublisherMethods / Reflux.ListenerMethods instead." 912 | ); 913 | } 914 | } 915 | 916 | for(var d in definition){ 917 | if (!allowed[d] && (PublisherMethods[d] || ListenerMethods[d])){ 918 | throw new Error("Cannot override API method " + d + 919 | " in store creation. Use another method name or override it on Reflux.PublisherMethods / Reflux.ListenerMethods instead." 920 | ); 921 | } 922 | } 923 | 924 | definition = mixer(definition); 925 | 926 | function Store() { 927 | var i=0, arr; 928 | this.subscriptions = []; 929 | this.emitter = new _.EventEmitter(); 930 | this.eventLabel = "change"; 931 | bindMethods(this, definition); 932 | if (this.init && _.isFunction(this.init)) { 933 | this.init(); 934 | } 935 | if (this.listenables){ 936 | arr = [].concat(this.listenables); 937 | for(;i < arr.length;i++){ 938 | this.listenToMany(arr[i]); 939 | } 940 | } 941 | } 942 | 943 | _.extend(Store.prototype, ListenerMethods, PublisherMethods, StoreMethods, definition); 944 | 945 | var store = new Store(); 946 | Keep.createdStores.push(store); 947 | 948 | return store; 949 | }; 950 | 951 | },{"./Keep":3,"./ListenerMethods":4,"./PublisherMethods":6,"./StoreMethods":7,"./bindMethods":8,"./mixer":17,"./utils":18}],13:[function(require,module,exports){ 952 | exports.ActionMethods = require('./ActionMethods'); 953 | 954 | exports.ListenerMethods = require('./ListenerMethods'); 955 | 956 | exports.PublisherMethods = require('./PublisherMethods'); 957 | 958 | exports.StoreMethods = require('./StoreMethods'); 959 | 960 | exports.createAction = require('./createAction'); 961 | 962 | exports.createStore = require('./createStore'); 963 | 964 | exports.connect = require('./connect'); 965 | 966 | exports.connectFilter = require('./connectFilter'); 967 | 968 | exports.ListenerMixin = require('./ListenerMixin'); 969 | 970 | exports.listenTo = require('./listenTo'); 971 | 972 | exports.listenToMany = require('./listenToMany'); 973 | 974 | 975 | var maker = require('./joins').staticJoinCreator; 976 | 977 | exports.joinTrailing = exports.all = maker("last"); // Reflux.all alias for backward compatibility 978 | 979 | exports.joinLeading = maker("first"); 980 | 981 | exports.joinStrict = maker("strict"); 982 | 983 | exports.joinConcat = maker("all"); 984 | 985 | var _ = exports.utils = require('./utils'); 986 | 987 | exports.EventEmitter = _.EventEmitter; 988 | 989 | exports.Promise = _.Promise; 990 | 991 | /** 992 | * Convenience function for creating a set of actions 993 | * 994 | * @param definitions the definitions for the actions to be created 995 | * @returns an object with actions of corresponding action names 996 | */ 997 | exports.createActions = function(definitions) { 998 | var actions = {}; 999 | for (var k in definitions){ 1000 | if (definitions.hasOwnProperty(k)) { 1001 | var val = definitions[k], 1002 | actionName = _.isObject(val) ? k : val; 1003 | 1004 | actions[actionName] = exports.createAction(val); 1005 | } 1006 | } 1007 | return actions; 1008 | }; 1009 | 1010 | /** 1011 | * Sets the eventmitter that Reflux uses 1012 | */ 1013 | exports.setEventEmitter = function(ctx) { 1014 | exports.EventEmitter = _.EventEmitter = ctx; 1015 | }; 1016 | 1017 | 1018 | /** 1019 | * Sets the Promise library that Reflux uses 1020 | */ 1021 | exports.setPromise = function(ctx) { 1022 | exports.Promise = _.Promise = ctx; 1023 | }; 1024 | 1025 | 1026 | /** 1027 | * Sets the Promise factory that creates new promises 1028 | * @param {Function} factory has the signature `function(resolver) { return [new Promise]; }` 1029 | */ 1030 | exports.setPromiseFactory = function(factory) { 1031 | _.createPromise = factory; 1032 | }; 1033 | 1034 | 1035 | /** 1036 | * Sets the method used for deferring actions and stores 1037 | */ 1038 | exports.nextTick = function(nextTick) { 1039 | _.nextTick = nextTick; 1040 | }; 1041 | 1042 | /** 1043 | * Provides the set of created actions and stores for introspection 1044 | */ 1045 | exports.__keep = require('./Keep'); 1046 | 1047 | /** 1048 | * Warn if Function.prototype.bind not available 1049 | */ 1050 | if (!Function.prototype.bind) { 1051 | console.error( 1052 | 'Function.prototype.bind not available. ' + 1053 | 'ES5 shim required. ' + 1054 | 'https://github.com/spoike/refluxjs#es5' 1055 | ); 1056 | } 1057 | 1058 | },{"./ActionMethods":2,"./Keep":3,"./ListenerMethods":4,"./ListenerMixin":5,"./PublisherMethods":6,"./StoreMethods":7,"./connect":9,"./connectFilter":10,"./createAction":11,"./createStore":12,"./joins":14,"./listenTo":15,"./listenToMany":16,"./utils":18}],14:[function(require,module,exports){ 1059 | /** 1060 | * Internal module used to create static and instance join methods 1061 | */ 1062 | 1063 | var slice = Array.prototype.slice, 1064 | _ = require("./utils"), 1065 | createStore = require("./createStore"), 1066 | strategyMethodNames = { 1067 | strict: "joinStrict", 1068 | first: "joinLeading", 1069 | last: "joinTrailing", 1070 | all: "joinConcat" 1071 | }; 1072 | 1073 | /** 1074 | * Used in `index.js` to create the static join methods 1075 | * @param {String} strategy Which strategy to use when tracking listenable trigger arguments 1076 | * @returns {Function} A static function which returns a store with a join listen on the given listenables using the given strategy 1077 | */ 1078 | exports.staticJoinCreator = function(strategy){ 1079 | return function(/* listenables... */) { 1080 | var listenables = slice.call(arguments); 1081 | return createStore({ 1082 | init: function(){ 1083 | this[strategyMethodNames[strategy]].apply(this,listenables.concat("triggerAsync")); 1084 | } 1085 | }); 1086 | }; 1087 | }; 1088 | 1089 | /** 1090 | * Used in `ListenerMethods.js` to create the instance join methods 1091 | * @param {String} strategy Which strategy to use when tracking listenable trigger arguments 1092 | * @returns {Function} An instance method which sets up a join listen on the given listenables using the given strategy 1093 | */ 1094 | exports.instanceJoinCreator = function(strategy){ 1095 | return function(/* listenables..., callback*/){ 1096 | _.throwIf(arguments.length < 2,'Cannot create a join with less than 2 listenables!'); 1097 | var listenables = slice.call(arguments), 1098 | callback = listenables.pop(), 1099 | numberOfListenables = listenables.length, 1100 | join = { 1101 | numberOfListenables: numberOfListenables, 1102 | callback: this[callback]||callback, 1103 | listener: this, 1104 | strategy: strategy 1105 | }, i, cancels = [], subobj; 1106 | for (i = 0; i < numberOfListenables; i++) { 1107 | _.throwIf(this.validateListening(listenables[i])); 1108 | } 1109 | for (i = 0; i < numberOfListenables; i++) { 1110 | cancels.push(listenables[i].listen(newListener(i,join),this)); 1111 | } 1112 | reset(join); 1113 | subobj = {listenable: listenables}; 1114 | subobj.stop = makeStopper(subobj,cancels,this); 1115 | this.subscriptions = (this.subscriptions || []).concat(subobj); 1116 | return subobj; 1117 | }; 1118 | }; 1119 | 1120 | // ---- internal join functions ---- 1121 | 1122 | function makeStopper(subobj,cancels,context){ 1123 | return function() { 1124 | var i, subs = context.subscriptions, 1125 | index = (subs ? subs.indexOf(subobj) : -1); 1126 | _.throwIf(index === -1,'Tried to remove join already gone from subscriptions list!'); 1127 | for(i=0;i < cancels.length; i++){ 1128 | cancels[i](); 1129 | } 1130 | subs.splice(index, 1); 1131 | }; 1132 | } 1133 | 1134 | function reset(join) { 1135 | join.listenablesEmitted = new Array(join.numberOfListenables); 1136 | join.args = new Array(join.numberOfListenables); 1137 | } 1138 | 1139 | function newListener(i,join) { 1140 | return function() { 1141 | var callargs = slice.call(arguments); 1142 | if (join.listenablesEmitted[i]){ 1143 | switch(join.strategy){ 1144 | case "strict": throw new Error("Strict join failed because listener triggered twice."); 1145 | case "last": join.args[i] = callargs; break; 1146 | case "all": join.args[i].push(callargs); 1147 | } 1148 | } else { 1149 | join.listenablesEmitted[i] = true; 1150 | join.args[i] = (join.strategy==="all"?[callargs]:callargs); 1151 | } 1152 | emitIfAllListenablesEmitted(join); 1153 | }; 1154 | } 1155 | 1156 | function emitIfAllListenablesEmitted(join) { 1157 | for (var i = 0; i < join.numberOfListenables; i++) { 1158 | if (!join.listenablesEmitted[i]) { 1159 | return; 1160 | } 1161 | } 1162 | join.callback.apply(join.listener,join.args); 1163 | reset(join); 1164 | } 1165 | 1166 | },{"./createStore":12,"./utils":18}],15:[function(require,module,exports){ 1167 | var ListenerMethods = require('./ListenerMethods'); 1168 | 1169 | /** 1170 | * A mixin factory for a React component. Meant as a more convenient way of using the `ListenerMixin`, 1171 | * without having to manually set listeners in the `componentDidMount` method. 1172 | * 1173 | * @param {Action|Store} listenable An Action or Store that should be 1174 | * listened to. 1175 | * @param {Function|String} callback The callback to register as event handler 1176 | * @param {Function|String} defaultCallback The callback to register as default handler 1177 | * @returns {Object} An object to be used as a mixin, which sets up the listener for the given listenable. 1178 | */ 1179 | module.exports = function(listenable,callback,initial){ 1180 | return { 1181 | /** 1182 | * Set up the mixin before the initial rendering occurs. Import methods from `ListenerMethods` 1183 | * and then make the call to `listenTo` with the arguments provided to the factory function 1184 | */ 1185 | componentDidMount: function() { 1186 | for(var m in ListenerMethods){ 1187 | if (this[m] !== ListenerMethods[m]){ 1188 | if (this[m]){ 1189 | throw "Can't have other property '"+m+"' when using Reflux.listenTo!"; 1190 | } 1191 | this[m] = ListenerMethods[m]; 1192 | } 1193 | } 1194 | this.listenTo(listenable,callback,initial); 1195 | }, 1196 | /** 1197 | * Cleans up all listener previously registered. 1198 | */ 1199 | componentWillUnmount: ListenerMethods.stopListeningToAll 1200 | }; 1201 | }; 1202 | 1203 | },{"./ListenerMethods":4}],16:[function(require,module,exports){ 1204 | var ListenerMethods = require('./ListenerMethods'); 1205 | 1206 | /** 1207 | * A mixin factory for a React component. Meant as a more convenient way of using the `listenerMixin`, 1208 | * without having to manually set listeners in the `componentDidMount` method. This version is used 1209 | * to automatically set up a `listenToMany` call. 1210 | * 1211 | * @param {Object} listenables An object of listenables 1212 | * @returns {Object} An object to be used as a mixin, which sets up the listeners for the given listenables. 1213 | */ 1214 | module.exports = function(listenables){ 1215 | return { 1216 | /** 1217 | * Set up the mixin before the initial rendering occurs. Import methods from `ListenerMethods` 1218 | * and then make the call to `listenTo` with the arguments provided to the factory function 1219 | */ 1220 | componentDidMount: function() { 1221 | for(var m in ListenerMethods){ 1222 | if (this[m] !== ListenerMethods[m]){ 1223 | if (this[m]){ 1224 | throw "Can't have other property '"+m+"' when using Reflux.listenToMany!"; 1225 | } 1226 | this[m] = ListenerMethods[m]; 1227 | } 1228 | } 1229 | this.listenToMany(listenables); 1230 | }, 1231 | /** 1232 | * Cleans up all listener previously registered. 1233 | */ 1234 | componentWillUnmount: ListenerMethods.stopListeningToAll 1235 | }; 1236 | }; 1237 | 1238 | },{"./ListenerMethods":4}],17:[function(require,module,exports){ 1239 | var _ = require('./utils'); 1240 | 1241 | module.exports = function mix(def) { 1242 | var composed = { 1243 | init: [], 1244 | preEmit: [], 1245 | shouldEmit: [] 1246 | }; 1247 | 1248 | var updated = (function mixDef(mixin) { 1249 | var mixed = {}; 1250 | if (mixin.mixins) { 1251 | mixin.mixins.forEach(function (subMixin) { 1252 | _.extend(mixed, mixDef(subMixin)); 1253 | }); 1254 | } 1255 | _.extend(mixed, mixin); 1256 | Object.keys(composed).forEach(function (composable) { 1257 | if (mixin.hasOwnProperty(composable)) { 1258 | composed[composable].push(mixin[composable]); 1259 | } 1260 | }); 1261 | return mixed; 1262 | }(def)); 1263 | 1264 | if (composed.init.length > 1) { 1265 | updated.init = function () { 1266 | var args = arguments; 1267 | composed.init.forEach(function (init) { 1268 | init.apply(this, args); 1269 | }, this); 1270 | }; 1271 | } 1272 | if (composed.preEmit.length > 1) { 1273 | updated.preEmit = function () { 1274 | return composed.preEmit.reduce(function (args, preEmit) { 1275 | var newValue = preEmit.apply(this, args); 1276 | return newValue === undefined ? args : [newValue]; 1277 | }.bind(this), arguments); 1278 | }; 1279 | } 1280 | if (composed.shouldEmit.length > 1) { 1281 | updated.shouldEmit = function () { 1282 | var args = arguments; 1283 | return !composed.shouldEmit.some(function (shouldEmit) { 1284 | return !shouldEmit.apply(this, args); 1285 | }, this); 1286 | }; 1287 | } 1288 | Object.keys(composed).forEach(function (composable) { 1289 | if (composed[composable].length === 1) { 1290 | updated[composable] = composed[composable][0]; 1291 | } 1292 | }); 1293 | 1294 | return updated; 1295 | }; 1296 | 1297 | },{"./utils":18}],18:[function(require,module,exports){ 1298 | exports.environment = {}; 1299 | 1300 | /* 1301 | * isObject, extend, isFunction, isArguments are taken from undescore/lodash in 1302 | * order to remove the dependency 1303 | */ 1304 | var isObject = exports.isObject = function(obj) { 1305 | var type = typeof obj; 1306 | return type === 'function' || type === 'object' && !!obj; 1307 | }; 1308 | 1309 | exports.extend = function(obj) { 1310 | if (!isObject(obj)) { 1311 | return obj; 1312 | } 1313 | var source, prop; 1314 | for (var i = 1, length = arguments.length; i < length; i++) { 1315 | source = arguments[i]; 1316 | for (prop in source) { 1317 | if (Object.getOwnPropertyDescriptor && Object.defineProperty) { 1318 | var propertyDescriptor = Object.getOwnPropertyDescriptor(source, prop); 1319 | Object.defineProperty(obj, prop, propertyDescriptor); 1320 | } else { 1321 | obj[prop] = source[prop]; 1322 | } 1323 | } 1324 | } 1325 | return obj; 1326 | }; 1327 | 1328 | exports.isFunction = function(value) { 1329 | return typeof value === 'function'; 1330 | }; 1331 | 1332 | exports.EventEmitter = require('eventemitter3'); 1333 | 1334 | exports.nextTick = function(callback) { 1335 | setTimeout(callback, 0); 1336 | }; 1337 | 1338 | exports.capitalize = function(string){ 1339 | return string.charAt(0).toUpperCase()+string.slice(1); 1340 | }; 1341 | 1342 | exports.callbackName = function(string){ 1343 | return "on"+exports.capitalize(string); 1344 | }; 1345 | 1346 | exports.object = function(keys,vals){ 1347 | var o={}, i=0; 1348 | for(;i < keys.length; i++){ 1349 | o[keys[i]] = vals[i]; 1350 | } 1351 | return o; 1352 | }; 1353 | 1354 | try { 1355 | exports.Promise = Promise; 1356 | exports.createPromise = function(resolver) { 1357 | return new exports.Promise(resolver); 1358 | }; 1359 | } catch (err) { 1360 | // ReferenceError, Promise is not defined 1361 | exports.Promise = null; 1362 | exports.createPromise = function() {}; 1363 | } 1364 | exports.environment.hasPromises = !!exports.Promise; 1365 | 1366 | exports.isArguments = function(value) { 1367 | return typeof value === 'object' && ('callee' in value) && typeof value.length === 'number'; 1368 | }; 1369 | 1370 | exports.throwIf = function(val,msg){ 1371 | if (val){ 1372 | throw Error(msg||val); 1373 | } 1374 | }; 1375 | 1376 | },{"eventemitter3":1}]},{},[13])(13) 1377 | }); 1378 | -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | --------------------------------------------------------------------------------