[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\ntrim_trailing_whitespace = true\ncharset = utf-8\n\n[*.js]\nindent_size = 4\n\n[{package.json,.travis.yml}]\nindent_size = 2\n"
  },
  {
    "path": ".gitignore",
    "content": "# Node.JS specifics\n\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\n\nnpm-debug.log\nnode_modules\n\n# MacOSX specifics\n.DS_Store\n\n# Build artifacts\ntmp\nbower_components\ncomponents\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "module.exports = function(grunt) {\n\n    var options = {\n        port: 8080\n    };\n\n    grunt.initConfig({\n        options: options,\n        pkg: grunt.file.readJSON('package.json'),\n        connect: {\n            server: {\n                options: {\n                    port: options.port,\n                    base: '.'\n                }\n            }\n        },\n        open: {\n            server: {\n                path: 'http://localhost:<%= options.port %>/'\n            }\n        },\n        watch: {\n\n        }\n    });\n\n    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);\n\n    grunt.registerTask('default', ['connect', 'open', 'watch']);    \n};"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"reflux-todo\",\n  \"version\": \"0.0.1\",\n  \"dependencies\": {\n    \"todomvc-app-css\": \"~1.0.1\",\n    \"reflux\": \"~0.2.4\",\n    \"react\": \"~0.12.2\",\n    \"lodash\": \"~3.0.1\",\n    \"react-router\": \"~0.11.6\"\n  }\n}\n"
  },
  {
    "path": "css/app.css",
    "content": "/* base.css overrides */\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <title>ReactJS + RefluxJS • TodoMVC</title>\n    <link rel=\"stylesheet\" href=\"bower_components/todomvc-app-css/index.css\">\n    <!-- CSS overrides - remove if you don't need it -->\n    <link rel=\"stylesheet\" href=\"css/app.css\">\n</head>\n<body>\n    <section id=\"todoapp\">\n        <!-- Bootstrap code will add components here, see js/components.jsx.js -->\n    </section>\n    <footer id=\"info\">\n        <p>Double-click to edit a todo</p>\n        <!-- Remove the below line ↓ -->\n        <p>Template by <a href=\"http://github.com/sindresorhus\">Sindre Sorhus</a></p>\n        <!-- Change this out with your name and url ↓ -->\n        <p>Created by <a href=\"https://github.com/spoike/refluxjs\">Mikael Brassman</a></p>\n        <!--<p>Part of <a href=\"http://todomvc.com\">TodoMVC</a></p>-->\n    </footer>\n    <!-- Scripts here. Don't remove this ↓ -->\n    <!-- <script src=\"bower_components/todomvc-common/base.js\"></script> -->\n    <script src=\"bower_components/react/react-with-addons.js\"></script>\n    <script src=\"bower_components/react-router/dist/react-router.js\"></script>\n    <script src=\"bower_components/react/JSXTransformer.js\"></script>\n    <script src=\"bower_components/lodash/lodash.js\"></script>\n    <script src=\"bower_components/reflux/dist/reflux.js\"></script>\n    <script src=\"js/actions.js\"></script>\n    <script src=\"js/store.js\"></script>\n    <script type=\"text/jsx\" src=\"js/components.jsx.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "js/actions.js",
    "content": "(function(Reflux, global) {\n    'use strict';\n\n    // Each action is like an event channel for one specific event. Actions are called by components.\n    // The store is listening to all actions, and the components in turn are listening to the store.\n    // Thus the flow is: User interaction -> component calls action -> store reacts and triggers -> components update\n\n    global.TodoActions = Reflux.createActions([\n        \"toggleItem\",     // called by button in TodoItem\n        \"toggleAllItems\", // called by button in TodoMain (even though you'd think TodoHeader)\n        \"addItem\",        // called by hitting enter in field in TodoHeader\n        \"removeItem\",     // called by button in TodoItem\n        \"clearCompleted\", // called by button in TodoFooter\n        \"editItem\"        // called by finishing edit in TodoItem\n    ]);\n\n})(window.Reflux, window);\n"
  },
  {
    "path": "js/components.jsx.js",
    "content": "/** @jsx React.DOM */\n\n(function(React, ReactRouter, Reflux, TodoActions, todoListStore, global) {\n\n    // Renders a single Todo item in the list\n    // Used in TodoMain\n    var TodoItem = React.createClass({\n        propTypes: {\n            label: React.PropTypes.string.isRequired,\n            isComplete: React.PropTypes.bool.isRequired,\n            id: React.PropTypes.number\n        },\n        mixins: [React.addons.LinkedStateMixin], // exposes this.linkState used in render\n        getInitialState: function() {\n            return {};\n        },\n        handleToggle: function(evt) {\n            TodoActions.toggleItem(this.props.id);\n        },\n        handleEditStart: function(evt) {\n            evt.preventDefault();\n            // because of linkState call in render, field will get value from this.state.editValue\n            this.setState({\n                isEditing: true,\n                editValue: this.props.label\n            }, function() {\n                this.refs.editInput.getDOMNode().focus();\n            });\n        },\n        handleValueChange: function(evt) {\n            var text = this.state.editValue; // because of the linkState call in render, this is the contents of the field\n            // we pressed enter, if text isn't empty we blur the field which will cause a save\n            if (evt.which === 13 && text) {\n                this.refs.editInput.getDOMNode().blur();\n            }\n            // pressed escape. set editing to false before blurring so we won't save\n            else if (evt.which === 27) {\n                this.setState({ isEditing: false },function(){\n                    this.refs.editInput.getDOMNode().blur();\n                });\n            }\n        },\n        handleBlur: function() {\n            var text = this.state.editValue; // because of the linkState call in render, this is the contents of the field\n            // unless we're not editing (escape was pressed) or text is empty, save!\n            if (this.state.isEditing && text) {\n                TodoActions.editItem(this.props.id, text);\n            }\n            // whatever the outcome, if we left the field we're not editing anymore\n            this.setState({isEditing:false});\n        },\n        handleDestroy: function() {\n            TodoActions.removeItem(this.props.id);\n        },\n        render: function() {\n            var classes = React.addons.classSet({\n                'completed': this.props.isComplete,\n                'editing': this.state.isEditing\n            });\n            return (\n                <li className={classes}>\n                    <div className=\"view\">\n                        <input className=\"toggle\" type=\"checkbox\" checked={!!this.props.isComplete} onChange={this.handleToggle} />\n                        <label onDoubleClick={this.handleEditStart}>{this.props.label}</label>\n                        <button className=\"destroy\" onClick={this.handleDestroy}></button>\n                    </div>\n                    <input ref=\"editInput\" className=\"edit\" valueLink={this.linkState('editValue')} onKeyUp={this.handleValueChange} onBlur={this.handleBlur} />\n                </li>\n            );\n        }\n    });\n\n    // Renders the todo list as well as the toggle all button\n    // Used in TodoApp\n    var TodoMain = React.createClass({\n        mixins: [ ReactRouter.State ],\n        propTypes: {\n            list: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,\n        },\n        toggleAll: function(evt) {\n            TodoActions.toggleAllItems(evt.target.checked);\n        },\n        render: function() {\n            var filteredList;\n            switch(this.getPath()){\n                case '/completed':\n                    filteredList = _.filter(this.props.list,function(item){ return item.isComplete; });\n                    break;\n                case '/active':\n                    filteredList = _.filter(this.props.list,function(item){ return !item.isComplete; });\n                    break;\n                default:\n                    filteredList = this.props.list;\n            }\n            var classes = React.addons.classSet({\n                \"hidden\": this.props.list.length < 1\n            });\n            return (\n                <section id=\"main\" className={classes}>\n                    <input id=\"toggle-all\" type=\"checkbox\" onChange={this.toggleAll} />\n                    <label htmlFor=\"toggle-all\">Mark all as complete</label>\n                    <ul id=\"todo-list\">\n                        { filteredList.map(function(item){\n                            return <TodoItem label={item.label} isComplete={item.isComplete} id={item.key} key={item.key}/>;\n                        })}\n                    </ul>\n                </section>\n            );\n        }\n    });\n\n    // Renders the headline and the form for creating new todos.\n    // Used in TodoApp\n    // Observe that the toogleall button is NOT rendered here, but in TodoMain (it is then moved up to the header with CSS)\n    var TodoHeader = React.createClass({\n        handleValueChange: function(evt) {\n            var text = evt.target.value;\n            if (evt.which === 13 && text) { // hit enter, create new item if field isn't empty\n                TodoActions.addItem(text);\n                evt.target.value = '';\n            } else if (evt.which === 27) { // hit escape, clear without creating\n                evt.target.value = '';\n            }\n        },\n        render: function() {\n            return (\n                <header id=\"header\">\n                    <h1>todos</h1>\n                    <input id=\"new-todo\" placeholder=\"What needs to be done?\" autoFocus onKeyUp={this.handleValueChange}/>\n                </header>\n            );\n        }\n    });\n\n    // Renders the bottom item count, navigation bar and clearallcompleted button\n    // Used in TodoApp\n    var TodoFooter = React.createClass({\n        propTypes: {\n            list: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,\n        },\n        render: function() {\n            var nbrcompleted = _.filter(this.props.list, \"isComplete\").length,\n                nbrtotal = this.props.list.length,\n                nbrincomplete = nbrtotal-nbrcompleted,\n                clearButtonClass = React.addons.classSet({hidden: nbrcompleted < 1}),\n                footerClass = React.addons.classSet({hidden: !nbrtotal }),\n                completedLabel = \"Clear completed (\" + nbrcompleted + \")\",\n                itemsLeftLabel = nbrincomplete === 1 ? \" item left\" : \" items left\";\n            return (\n                <footer id=\"footer\" className={footerClass}>\n                    <span id=\"todo-count\"><strong>{nbrincomplete}</strong>{itemsLeftLabel}</span>\n                    <ul id=\"filters\">\n                        <li>\n                            <ReactRouter.Link activeClassName=\"selected\" to=\"All\">All</ReactRouter.Link>\n                        </li>\n                        <li>\n                            <ReactRouter.Link activeClassName=\"selected\" to=\"Active\">Active</ReactRouter.Link>\n                        </li>\n                        <li>\n                            <ReactRouter.Link activeClassName=\"selected\" to=\"Completed\">Completed</ReactRouter.Link>\n                        </li>\n                    </ul>\n                    <button id=\"clear-completed\" className={clearButtonClass} onClick={TodoActions.clearCompleted}>{completedLabel}</button>\n                </footer>\n            );\n        }\n    });\n\n    // Renders the full application\n    // RouteHandler will always be TodoMain, but with different 'showing' prop (all/completed/active)\n    var TodoApp = React.createClass({\n        // this will cause setState({list:updatedlist}) whenever the store does trigger(updatedlist)\n        mixins: [Reflux.connect(todoListStore,\"list\")],\n\n        render: function() {\n            return (\n                <div>\n                    <TodoHeader />\n                    <ReactRouter.RouteHandler list={this.state.list} />\n                    <TodoFooter list={this.state.list} />\n                </div>\n            );\n        }\n    });\n\n    var routes = (\n        <ReactRouter.Route handler={TodoApp}>\n            <ReactRouter.Route name=\"All\" path=\"/\" handler={TodoMain} />\n            <ReactRouter.Route name=\"Completed\" path=\"/completed\" handler={TodoMain} />\n            <ReactRouter.Route name=\"Active\" path=\"/active\" handler={TodoMain} />\n        </ReactRouter.Route>\n    );\n\n    ReactRouter.run(routes, function(Handler) {\n        React.render(<Handler/>, document.getElementById('todoapp'));\n    });\n\n})(window.React, window.ReactRouter, window.Reflux, window.TodoActions, window.todoListStore, window);\n"
  },
  {
    "path": "js/store.js",
    "content": "(function(Reflux, TodoActions, global) {\n    'use strict';\n\n    // some variables and helpers for our fake database stuff\n    var todoCounter = 0,\n        localStorageKey = \"todos\";\n\n    function getItemByKey(list,itemKey){\n        return _.find(list, function(item) {\n            return item.key === itemKey;\n        });\n    }\n\n    global.todoListStore = Reflux.createStore({\n        // this will set up listeners to all publishers in TodoActions, using onKeyname (or keyname) as callbacks\n        listenables: [TodoActions],\n        onEditItem: function(itemKey, newLabel) {\n            var foundItem = getItemByKey(this.list,itemKey);\n            if (!foundItem) {\n                return;\n            }\n            foundItem.label = newLabel;\n            this.updateList(this.list);\n        },\n        onAddItem: function(label) {\n            this.updateList([{\n                key: todoCounter++,\n                created: new Date(),\n                isComplete: false,\n                label: label\n            }].concat(this.list));\n        },\n        onRemoveItem: function(itemKey) {\n            this.updateList(_.filter(this.list,function(item){\n                return item.key!==itemKey;\n            }));\n        },\n        onToggleItem: function(itemKey) {\n            var foundItem = getItemByKey(this.list,itemKey);\n            if (foundItem) {\n                foundItem.isComplete = !foundItem.isComplete;\n                this.updateList(this.list);\n            }\n        },\n        onToggleAllItems: function(checked) {\n            this.updateList(_.map(this.list, function(item) {\n                item.isComplete = checked;\n                return item;\n            }));\n        },\n        onClearCompleted: function() {\n            this.updateList(_.filter(this.list, function(item) {\n                return !item.isComplete;\n            }));\n        },\n        // called whenever we change a list. normally this would mean a database API call\n        updateList: function(list){\n            localStorage.setItem(localStorageKey, JSON.stringify(list));\n            // if we used a real database, we would likely do the below in a callback\n            this.list = list;\n            this.trigger(list); // sends the updated list to all listening components (TodoApp)\n        },\n        // this will be called by all listening components as they register their listeners\n        getInitialState: function() {\n            var loadedList = localStorage.getItem(localStorageKey);\n            if (!loadedList) {\n                // If no list is in localstorage, start out with a default one\n                this.list = [{\n                    key: todoCounter++,\n                    created: new Date(),\n                    isComplete: false,\n                    label: 'Rule the web'\n                }];\n            } else {\n                this.list = _.map(JSON.parse(loadedList), function(item) {\n                    // just resetting the key property for each todo item\n                    item.key = todoCounter++;\n                    return item;\n                });\n            }\n            return this.list;\n        }\n    });\n\n})(window.Reflux, window.TodoActions, window);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"reflux-todo\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Todo example for the reflux project\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"prepublish\": \"bower install\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"grunt\": \"^0.4.5\",\n    \"grunt-contrib-connect\": \"^0.8.0\",\n    \"grunt-contrib-watch\": \"^0.6.1\",\n    \"grunt-open\": \"^0.2.3\",\n    \"matchdep\": \"^0.3.0\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# ReactJS w. RefluxJS TodoMVC Example\n\n> A simple library for uni-directional dataflow application architecture inspired by ReactJS [Flux](http://facebook.github.io/react/blog/2014/05/06/flux.html)\n\n> _[RefluxJS](https://github.com/spoike/refluxjs)_\n\n\n## Implementation\n\nTODO\n\n## Running\n\nInstall dependencies with bower and npm. You'll first need to have [bower](http://bower.io/) and [npm](npmjs.org) installed to do so. Then run the following:\n\n```\nbower install && npm install\n```\n\nThis project comes with a grunt task to runs a [`connect`](https://github.com/gruntjs/grunt-contrib-connect) web server and opens up the web browser for you. Just run:\n\n```\ngrunt\n```\n\n## Credit\n\nThis TodoMVC application was created by [Mikael Brassman](https://github.com/spoike/refluxjs).\n"
  },
  {
    "path": "readme_template.md",
    "content": "# Template • [TodoMVC](http://todomvc.com)\n\n\n\n## Getting Started\n\nRead the [App Specification](https://github.com/tastejs/todomvc/blob/master/app-spec.md) before touching the template.\n\n\n## Need help?\n\nFeel free to contact [Sindre](https://github.com/sindresorhus) or [Pascal](https://github.com/passy) if you have any questions or need help with the template.\n\n\n## Credit\n\nCreated by [Sindre Sorhus](http://sindresorhus.com)\n"
  }
]