├── .bowerrc ├── .editorconfig ├── .gitignore ├── .jshintrc ├── README.md ├── bower.json ├── gulpfile.js ├── package.json └── src ├── NewsList.txt ├── app ├── actions.js ├── app.js ├── components │ ├── Badge.js │ ├── BookDetial.js │ └── DeleteCartItem.js ├── constants.js ├── pages │ ├── BooksCart.js │ ├── BooksList.js │ ├── Index.js │ └── NotFound.js ├── services │ └── APIServices.js └── stores │ ├── BookStore.js │ └── NewsStore.js ├── assets └── styles │ └── main.css ├── bookList.txt ├── index.html ├── robots.txt └── scripts └── app.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "src/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### OSX ### 2 | .DS_Store 3 | 4 | ### Windows ### 5 | # Windows image file caches 6 | Thumbs.db 7 | ehthumbs.db 8 | 9 | node_modules/ 10 | /dist 11 | /src/bower_components/ -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 4, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "undef": true, 16 | "strict": true, 17 | "globals": { 18 | "$": false, 19 | "moment": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | fluxxor_router 2 | ============== 3 | 4 | fluxxor and react-router practice 5 | 6 | demo :https://dl.dropboxusercontent.com/u/64049607/fluxxor_router/index.html 7 | 8 | more :http://www.checkme.tw/wordpress/react-fluxxor/ 9 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fluxxor-diy", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Mitch Chen " 6 | ], 7 | "dependencies": { 8 | "jquery": "~2.1.0", 9 | "bootstrap": "~3.2.0", 10 | "Cookies": "", 11 | "moment": "", 12 | "es5-shim": "", 13 | "es6-shim": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | $ = require('gulp-load-plugins')(), 5 | connect = $.connectMulti, 6 | wiredep = require('wiredep').stream, 7 | devServer = connect(), 8 | proServer = connect(); 9 | 10 | gulp.task('connect-dev', devServer.server({ 11 | root: ['src'], 12 | port: 8989, 13 | livereload: true 14 | })); 15 | 16 | gulp.task('connect-pro', proServer.server({ 17 | root: ['dist'], 18 | port: 9090, 19 | livereload: true 20 | })); 21 | 22 | gulp.task('clean', function() { 23 | return gulp.src(['dist'], {read: false}) 24 | .pipe($.rimraf()); 25 | }); 26 | 27 | gulp.task('lint', function() { 28 | return gulp.src(['src/app/*.js', 'src/app/**/*.js']) 29 | .pipe($.jshint('.jshintrc')) 30 | .pipe($.jshint.reporter('jshint-stylish')); 31 | }); 32 | 33 | gulp.task('robots', function() { 34 | gulp.src('src/robots.txt') 35 | .pipe(gulp.dest('dist/')); 36 | }); 37 | 38 | gulp.task('static', function() { 39 | gulp.src('src/static/*') 40 | .pipe(gulp.dest('dist/static/')); 41 | }); 42 | 43 | gulp.task('config', function() { 44 | gulp.src('src/config/*') 45 | .pipe(gulp.dest('dist/config/')); 46 | }); 47 | 48 | gulp.task('fonts', function() { 49 | gulp.src('src/bower_components/bootstrap/dist/fonts/*') 50 | .pipe(gulp.dest('dist/assets/fonts')); 51 | }); 52 | 53 | gulp.task('images', function() { 54 | gulp.src('src/assets/images/*') 55 | .pipe(gulp.dest('dist/assets/images')); 56 | }); 57 | 58 | gulp.task('styles', function() { 59 | gulp.src('src/assets/styles/*.css') 60 | .pipe(gulp.dest('dist/assets/styles')); 61 | }); 62 | 63 | gulp.task('base', ['robots', 'static', 'config', 'fonts', 'images', 'styles']); 64 | 65 | gulp.task('scripts', ['lint'], function() { 66 | return gulp.src(['src/app/app.js']) 67 | .pipe($.browserify({ 68 | transform: ['reactify'], 69 | extensions: ['.jsx'] 70 | })) 71 | .on('prebundle', function(bundler) { 72 | bundler.require('react'); 73 | }) 74 | .pipe(gulp.dest('dist/scripts/')) 75 | .pipe($.size()); 76 | }); 77 | 78 | gulp.task('html', ['base', 'scripts'], function() { 79 | var assets = $.useref.assets(); 80 | return gulp.src('src/*.html') 81 | .pipe(assets) 82 | .pipe(assets.restore()) 83 | .pipe($.useref()) 84 | .pipe(gulp.dest('dist')) 85 | .pipe($.size()); 86 | }); 87 | 88 | gulp.task('compress', ['html'], function() { 89 | gulp.src(['dist/scripts/app.js', 'dist/scripts/vendor.js']) 90 | .pipe($.uglify()) 91 | .pipe(gulp.dest('dist/scripts/')); 92 | }); 93 | 94 | gulp.task('wiredep', function() { 95 | gulp.src('src/*.html') 96 | .pipe(wiredep({ 97 | directory: 'src/bower_components', 98 | ignorePath: 'src/' 99 | })) 100 | .pipe(gulp.dest('src')); 101 | }); 102 | 103 | gulp.task('browserify', ['lint'], function() { 104 | return gulp.src(['src/app/app.js']) 105 | .pipe($.browserify({ 106 | transform: ['reactify'], 107 | extensions: ['.jsx'] 108 | })) 109 | .on('prebundle', function(bundler) { 110 | bundler.require('react'); 111 | }) 112 | .pipe(gulp.dest('src/scripts/')) 113 | .pipe($.size()); 114 | }); 115 | 116 | gulp.task('refresh', ['browserify'], function() { 117 | gulp.src('src/scripts/app.js') 118 | .pipe(devServer.reload()); 119 | }); 120 | 121 | gulp.task('watch', ['connect-dev'], function() { 122 | gulp.watch([ 123 | 'src/*.html', 124 | 'src/assets/styles/*.css', 125 | 'src/assets/images/*', 126 | 'src/app/*.js', 127 | 'src/app/**/*.js' 128 | ], function(event) { 129 | return gulp.src(event.path) 130 | .pipe(devServer.reload()); 131 | }); 132 | 133 | gulp.watch(['src/app/*.js', 'src/app/**/*.js'], ['refresh']); 134 | gulp.watch('bower.json', ['wiredep']); 135 | }); 136 | 137 | gulp.task('development', ['browserify'], function() { 138 | gulp.start('watch'); 139 | }); 140 | 141 | gulp.task('build', ['compress'], function() { 142 | gulp.start('connect-pro'); 143 | }); 144 | 145 | gulp.task('production', ['clean'], function() { 146 | gulp.start('build'); 147 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fluxxor-diy", 3 | "version": "0.0.1", 4 | "devDependencies": { 5 | "fluxxor": "~1.5.1", 6 | "gulp": "~3.8.8", 7 | "gulp-autoprefixer": "~1.0.0", 8 | "gulp-bower": "0.0.6", 9 | "gulp-browserify": "~0.5.0", 10 | "gulp-connect-multi": "^1.0.8", 11 | "gulp-jshint": "~1.8.4", 12 | "gulp-load-plugins": "~0.6.0", 13 | "gulp-rimraf": "~0.1.0", 14 | "gulp-size": "~1.1.0", 15 | "gulp-uglify": "1.0.1", 16 | "gulp-useref": "~1.0.1", 17 | "gulp-util": "^3.0.2", 18 | "jshint-stylish": "0.4.0", 19 | "react": "^0.12.x", 20 | "react-router": "~0.11.6", 21 | "reactify": "~0.15.2", 22 | "wiredep": "~1.8.5" 23 | }, 24 | "engines": { 25 | "node": ">=0.10.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/NewsList.txt: -------------------------------------------------------------------------------- 1 | { 2 | "result":1, 3 | "msg":"sucess", 4 | "newsList":[ 5 | { 6 | "date":"2015/1/1", 7 | "title":"NEWS Title A", 8 | "summary":"NEWS A summary........" 9 | }, 10 | { 11 | "date":"2015/1/2", 12 | "title":"NEWS Title B", 13 | "summary":"NEWS B summary........" 14 | }, 15 | { 16 | "date":"2015/1/3", 17 | "title":"NEWS Title C", 18 | "summary":"NEWS C summary........" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/app/actions.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | var Constants = require('./constants'), 5 | APIServices= require('./services/APIServices'); 6 | 7 | var actions={ 8 | //Namespaced Actions 9 | user:{ 10 | login: function() { }, 11 | logout: function(){ } 12 | }, 13 | getNewsList:function(){ 14 | APIServices.getNewsList().then( 15 | function(res){ 16 | this.dispatch(Constants.LOAD_NEWS_LIST_SUCCESS,{data:res}); 17 | }.bind(this), 18 | function(err) { 19 | 20 | }.bind(this) 21 | ); 22 | }, 23 | getBookList:function(){ 24 | //if should add start event listener , you can add actions 25 | //this.dispatch(Constants.LOAD_BOOK_LIST,{msg:'get book list'}); 26 | APIServices.getBookList().then( 27 | function(res){ 28 | this.dispatch(Constants.LOAD_BOOK_LIST_SUCCESS,{data:res}); 29 | }.bind(this), 30 | function(err) { 31 | this.dispatch(Constants.LOAD_FAIL,{res:err}); 32 | }.bind(this) 33 | ); 34 | }, 35 | addCart:function(book){ 36 | this.dispatch(Constants.ADD_CART,{book:book}); 37 | }, 38 | deleteCart:function(book){ 39 | this.dispatch(Constants.DELETE_CART,{book:book}); 40 | } 41 | }; 42 | module.exports=actions; -------------------------------------------------------------------------------- /src/app/app.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | Addons = require('react/addons'), 7 | //router 8 | Router = require('react-router'), 9 | Route = Router.Route, 10 | DefaultRoute = Router.DefaultRoute, 11 | RouteHandler = Router.RouteHandler, 12 | NotFoundRoute = Router.NotFoundRoute, 13 | Redirect = Router.Redirect, 14 | Link = Router.Link, 15 | //fluxxor 16 | Fluxxor = require('fluxxor'), 17 | FluxMixin = Fluxxor.FluxMixin(React), 18 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 19 | Constants = require('./constants'), 20 | Actions = require('./actions'), 21 | BookStore = require('./stores/BookStore'), 22 | NewsStore = require('./stores/NewsStore'), 23 | //page 24 | Index=require('./pages/Index'), 25 | NotFound=require('./pages/NotFound'), 26 | BooksList=require('./pages/BooksList'), 27 | BooksCart=require('./pages/BooksCart'), 28 | //components 29 | BookDetial=require('./components/BookDetial'), 30 | Badge=require('./components/Badge'), 31 | //app 32 | App; 33 | 34 | /* 35 | *fluxxor 36 | */ 37 | var stores = { 38 | BookStore:new BookStore(), 39 | NewsStore:new NewsStore() 40 | }; 41 | 42 | var flux = new Fluxxor.Flux(stores,Actions); 43 | 44 | flux.on('dispatch', function(type, payload) { 45 | if (console && console.log) { 46 | console.log('[Dispatch]', type, payload); 47 | } 48 | }); 49 | 50 | App = React.createClass({ 51 | mixins: [FluxMixin], 52 | componentDidMount: function(){ 53 | this.getFlux().actions.getBookList(); 54 | this.getFlux().actions.getNewsList(); 55 | }, 56 | render: function() { 57 | return ( 58 | /*jshint ignore:start */ 59 |
60 |
61 | 68 |
69 | {/* this is the important part */} 70 | 71 |
72 | /*jshint ignore:end */ 73 | ); 74 | } 75 | }); 76 | 77 | var routes = ( 78 | /*jshint ignore:start */ 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | /*jshint ignore:end */ 89 | ); 90 | /*jshint ignore:start */ 91 | Router.run(routes, function (Handler,state) { 92 | React.render(, document.getElementById('app')); 93 | }); 94 | /*jshint ignore:end */ 95 | 96 | -------------------------------------------------------------------------------- /src/app/components/Badge.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | CX = React.addons.classSet, 7 | //fluxxor 8 | Fluxxor = require('fluxxor'), 9 | FluxMixin = Fluxxor.FluxMixin(React), 10 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 11 | BookStore = require('../stores/BookStore'), 12 | Badge; 13 | 14 | Badge = React.createClass({ 15 | mixins: [FluxMixin, StoreWatchMixin('BookStore')], 16 | getStateFromFlux: function() { 17 | var flux = this.getFlux(); 18 | return flux.store('BookStore').getBooksCart(); 19 | }, 20 | render: function() { 21 | var hiedClass = CX({ 22 | 'hide': this.state.cartsList.length > 0 ? false : true, 23 | 'badge': true 24 | }); 25 | return( 26 | /*jshint ignore:start */ 27 | {this.state.cartsList.length} 28 | /*jshint ignore:end */ 29 | ); 30 | } 31 | }); 32 | 33 | module.exports = Badge; -------------------------------------------------------------------------------- /src/app/components/BookDetial.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | CX = React.addons.classSet, 7 | //router 8 | Router = require('react-router'), 9 | Route = Router.Route, 10 | //fluxxor 11 | Fluxxor = require('fluxxor'), 12 | FluxMixin = Fluxxor.FluxMixin(React), 13 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 14 | Constants = require('../constants'), 15 | Actions = require('../actions'), 16 | BookStore = require('../stores/BookStore'), 17 | BooksDetial; 18 | 19 | BooksDetial = React.createClass({ 20 | mixins: [Router.Navigation,Router.State,FluxMixin, StoreWatchMixin('BookStore')], 21 | getStateFromFlux: function() { 22 | var flux = this.getFlux(); 23 | return flux.store('BookStore').getBooksList(); 24 | }, 25 | componentWillMount: function() { 26 | if(this.state.booksList.length === 0){ 27 | this.transitionTo('/'); 28 | } 29 | }, 30 | _addSelectBook: function(book) { 31 | this.getFlux().actions.addCart(book); 32 | }, 33 | _removeSelectBook: function(book) { 34 | this.getFlux().actions.deleteCart(book); 35 | }, 36 | render:function() { 37 | var selectId = this.getParams().selectId, 38 | book = this.state.booksList.filter(function(book) { 39 | return book.id === selectId; 40 | }), 41 | addClass = CX({ 42 | 'hide': book[0].select || false, 43 | 'btn btn-default':true 44 | }), 45 | removeClass = CX({ 46 | 'hide': !book[0].select || false, 47 | 'btn btn-default':true 48 | }); 49 | return( 50 | /*jshint ignore:start */ 51 |
52 | 詳細資料: 53 |

書名:{book[0].name} 作者:{book[0].author}

54 | add Cart 55 | remove Cart 56 |
57 | /*jshint ignore:end */ 58 | ); 59 | } 60 | }); 61 | 62 | module.exports = BooksDetial; -------------------------------------------------------------------------------- /src/app/components/DeleteCartItem.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | DeleteCartItem; 7 | 8 | DeleteCartItem = React.createClass({ 9 | propTypes: { 10 | deleteCarts : React.PropTypes.func, 11 | book : React.PropTypes.object.isRequired 12 | }, 13 | getDefaultProps: function() { 14 | return { 15 | deleteCarts:function(){}, 16 | book: {} 17 | }; 18 | }, 19 | deleteBook: function(){ 20 | this.props.deleteCarts(this.props.book); 21 | }, 22 | render: function(){ 23 | return ( 24 | /*jshint ignore:start */ 25 |
  • 26 | 書名:{this.props.book.name} 作者:{this.props.book.author} 27 | Delete 28 |
  • 29 | /*jshint ignore:end */ 30 | ); 31 | } 32 | }); 33 | 34 | module.exports = DeleteCartItem; -------------------------------------------------------------------------------- /src/app/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Constants = { 4 | LOAD_NEWS_LIST_SUCCESS:'LOAD_NEWS_LIST_SUCCESS', 5 | LOAD_BOOK_LIST_SUCCESS:'LOAD_BOOK_LIST_SUCCESS', 6 | 7 | LOAD_FAIL:'LOAD_FAIL', 8 | 9 | ADD_CART: 'ADD_CART', 10 | DELETE_CART: 'DELETE_CART' 11 | }; 12 | module.exports=Constants; -------------------------------------------------------------------------------- /src/app/pages/BooksCart.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | //fluxxor 7 | Fluxxor = require('fluxxor'), 8 | FluxMixin = Fluxxor.FluxMixin(React), 9 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 10 | 11 | DeleteCartItem = require('../components/DeleteCartItem'), 12 | BooksCart; 13 | 14 | BooksCart = React.createClass({ 15 | /*jshint ignore:start */ 16 | mixins: [FluxMixin, StoreWatchMixin('BookStore')], 17 | /*jshint ignore:end */ 18 | getStateFromFlux: function() { 19 | var flux = this.getFlux(); 20 | return flux.store('BookStore').getBooksCart(); 21 | }, 22 | deleteCarts: function(book){ 23 | this.getFlux().actions.deleteCart(book); 24 | }, 25 | render: function () { 26 | var that = this; 27 | return ( 28 | /*jshint ignore:start */ 29 |
    30 |

    Books Cart

    31 |
      32 | {this.state.cartsList.map(function(book,i){ 33 | return 34 | }.bind(that) 35 | )} 36 |
    37 |
    38 | /*jshint ignore:end */ 39 | ); 40 | } 41 | }); 42 | 43 | module.exports = BooksCart; -------------------------------------------------------------------------------- /src/app/pages/BooksList.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | CX = React.addons.classSet, 7 | //router 8 | Router = require('react-router'), 9 | Route = Router.Route, 10 | RouteHandler = Router.RouteHandler, 11 | Link = Router.Link, 12 | //fluxxor 13 | Fluxxor = require('fluxxor'), 14 | FluxMixin = Fluxxor.FluxMixin(React), 15 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 16 | 17 | BooksList; 18 | 19 | BooksList = React.createClass({ 20 | mixins: [Router.Navigation,Router.State,FluxMixin, StoreWatchMixin('BookStore')], 21 | getStateFromFlux: function() { 22 | var flux = this.getFlux(); 23 | return flux.store('BookStore').getBooksList (); 24 | }, 25 | componentWillMount: function() { 26 | if(!this.getParams().selectId){ 27 | this.transitionTo('/BooksList/1'); 28 | } 29 | }, 30 | render: function() { 31 | return ( 32 | /*jshint ignore:start */ 33 |
    34 |

    Books List

    35 |
      36 | {this.state.booksList.map(function(book,i){ 37 | var spanClass=CX({ 38 | 'glyphicon glyphicon-shopping-cart': book.select 39 | }); 40 | return ( 41 |
    • 42 | {book.name} 43 | 44 |
    • 45 | ); 46 | })} 47 |
    48 |
    49 | 50 |
    51 |
    52 | /*jshint ignore:end */ 53 | ); 54 | } 55 | }); 56 | 57 | module.exports = BooksList; -------------------------------------------------------------------------------- /src/app/pages/Index.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | //fluxxor 7 | Fluxxor = require('fluxxor'), 8 | FluxMixin = Fluxxor.FluxMixin(React), 9 | StoreWatchMixin = Fluxxor.StoreWatchMixin, 10 | Index; 11 | 12 | Index = React.createClass({ 13 | mixins: [FluxMixin, StoreWatchMixin('BookStore','NewsStore')], 14 | getStateFromFlux: function() { 15 | var flux = this.getFlux(); 16 | return { 17 | book : flux.store('BookStore').getBooksList(), 18 | news : flux.store('NewsStore').getNewsList() 19 | }; 20 | }, 21 | render: function () { 22 | return ( 23 | /*jshint ignore:start */ 24 |
    25 |

    NEWS

    26 |
      27 | {this.state.news.newsList.map(function(news,i){ 28 | return ( 29 |
    • 30 | {news.date} - {news.title} - {news.summary} 31 |
    • 32 | )} 33 | )} 34 |
    35 |

    Books

    36 |
      37 | {this.state.book.booksList.map(function(book,i){ 38 | return ( 39 |
    • 40 | 書名:{book.name} 作者:{book.author} 41 | more 42 |
    • 43 | )} 44 | )} 45 |
    46 |
    47 | /*jshint ignore:end */ 48 | ); 49 | } 50 | }); 51 | module.exports = Index; -------------------------------------------------------------------------------- /src/app/pages/NotFound.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | 'use strict'; 4 | 5 | var React = require('react'), 6 | NotFound; 7 | 8 | NotFound = React.createClass({ 9 | render: function () { 10 | return ( 11 | /*jshint ignore:start */ 12 |
    13 |

    Not Found

    14 |
    15 | /*jshint ignore:end */ 16 | ); 17 | } 18 | }); 19 | module.exports = NotFound; -------------------------------------------------------------------------------- /src/app/services/APIServices.js: -------------------------------------------------------------------------------- 1 | /* 2 | * API Services 3 | */ 4 | 'use strict'; 5 | 6 | var APIServices; 7 | 8 | APIServices = (function() { 9 | var API = { 10 | NEWSLIST: 'NewsList.txt', 11 | BOOKLIST: 'bookList.txt' 12 | }; 13 | return { 14 | getJson: function(args){ 15 | var promise= $.ajax({ 16 | dataType: 'json', 17 | url: args.path, 18 | }); 19 | return promise; 20 | }, 21 | getNewsList: function() { 22 | var args = { 23 | path: API.NEWSLIST 24 | }, 25 | promise = this.getJson(args); 26 | return promise; 27 | }, 28 | getBookList: function() { 29 | var args = { 30 | path: API.BOOKLIST 31 | }, 32 | promise = this.getJson(args); 33 | return promise; 34 | } 35 | }; 36 | })(); 37 | 38 | module.exports = APIServices; 39 | -------------------------------------------------------------------------------- /src/app/stores/BookStore.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Fluxxor = require('fluxxor'), 4 | Constants = require('../constants'), 5 | BookStore; 6 | BookStore = Fluxxor.createStore({ 7 | initialize : function(){ 8 | this.booksList = []; 9 | this.cartsList = []; 10 | this.bindActions( 11 | Constants.LOAD_BOOK_LIST_SUCCESS,this.onLoadBookListSucess, 12 | Constants.LOAD_FAIL,this.onloadFail, 13 | 14 | Constants.ADD_CART,this.onAddCart, 15 | Constants.DELETE_CART,this.onDeleteCart 16 | ); 17 | }, 18 | onLoadBookListSucess:function(res){ 19 | this.booksList = res.data.bookList; 20 | this.emit('change'); 21 | }, 22 | onloadFail:function(res){ 23 | this.emit('change'); 24 | }, 25 | onAddCart:function(playload){ 26 | var idx = this.booksList.indexOf(playload.book); 27 | this.cartsList.push(playload.book); 28 | this.booksList[idx].select = true; 29 | this.emit('change'); 30 | }, 31 | onDeleteCart:function(playload){ 32 | var idx = this.cartsList.indexOf(playload.book); 33 | this.cartsList.splice(idx,1); 34 | idx = this.booksList.indexOf(playload.book); 35 | this.booksList[idx].select = false; 36 | this.emit('change'); 37 | }, 38 | getBooksList: function() { 39 | return { 40 | booksList: this.booksList 41 | }; 42 | }, 43 | getBooksCart: function(){ 44 | return { 45 | cartsList: this.cartsList 46 | }; 47 | } 48 | }); 49 | 50 | module.exports=BookStore; -------------------------------------------------------------------------------- /src/app/stores/NewsStore.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Fluxxor = require('fluxxor'), 4 | Constants = require('../constants'), 5 | NewsStore; 6 | NewsStore = Fluxxor.createStore({ 7 | initialize : function(){ 8 | this.newsList = []; 9 | this.bindActions( 10 | Constants.LOAD_NEWS_LIST_SUCCESS,this.onLoadNewsListSucess 11 | ); 12 | }, 13 | onLoadNewsListSucess:function(res){ 14 | this.newsList = res.data.newsList; 15 | this.emit('change'); 16 | }, 17 | getNewsList: function(){ 18 | return { 19 | newsList: this.newsList 20 | }; 21 | } 22 | }); 23 | 24 | module.exports=NewsStore; -------------------------------------------------------------------------------- /src/assets/styles/main.css: -------------------------------------------------------------------------------- 1 | /* Main.css */ -------------------------------------------------------------------------------- /src/bookList.txt: -------------------------------------------------------------------------------- 1 | { 2 | "result":1, 3 | "msg":"sucess", 4 | "bookList":[ 5 | { 6 | "id":"1", 7 | "name":"book1", 8 | "author":"author A" 9 | }, 10 | { 11 | "id":"2", 12 | "name":"book2", 13 | "author":"author B" 14 | }, 15 | { 16 | "id":"3", 17 | "name":"book3", 18 | "author":"author C" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | fluxxor-router 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 |
    26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | --------------------------------------------------------------------------------