├── test
├── mocha.opts
├── babel-mocha.js
├── Store-test.js
├── ActionCreator-test.js
└── EventEmitter-test.js
├── src
├── App.js
├── ActionCreator.js
├── Store.js
├── EventEmitter.js
└── Component.js
├── index.html
├── README.md
├── LICENSE
├── package.json
└── .gitignore
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --require ./test/babel-mocha.js
--------------------------------------------------------------------------------
/test/babel-mocha.js:
--------------------------------------------------------------------------------
1 | require("babel/register")({
2 | plugins: ["babel-plugin-espower"]
3 | });
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import React from "react"
4 | import Component from './Component';
5 | React.render(
6 | React.createElement(Component),
7 | document.body
8 | );
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mini-flux
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/ActionCreator.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | export default class ActionCreator {
4 | constructor(dispatcher) {
5 | this.dispatcher = dispatcher;
6 | }
7 |
8 | // "Emit" event ----> Store
9 | countUp(data) {
10 | this.dispatcher.emit("countUp", data);
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Store.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import Emitter from "./EventEmitter"
4 | class Store extends Emitter {
5 | constructor(dispatcher) {
6 | super();
7 | this.count = 0;
8 | // <--- observe event.
9 | dispatcher.on("countUp", this.onCountUp.bind(this));
10 | }
11 |
12 | getCount() {
13 | return this.count;
14 | }
15 |
16 | onCountUp(count) {
17 | if (this.count === count) {
18 | return;
19 | }
20 | this.count = count;
21 | // emit "CHANGE" ---> self
22 | this.emit("CHANGE");
23 | }
24 | }
25 | export default Store;
--------------------------------------------------------------------------------
/test/Store-test.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import assert from "power-assert"
4 | import Store from "../src/Store"
5 | import EventEmitter from "../src/EventEmitter"
6 | describe("Store", function () {
7 | var instance;
8 | var dispatcher;
9 | beforeEach(function () {
10 | dispatcher = new EventEmitter();
11 | instance = new Store(dispatcher);
12 | });
13 | describe("onCountUp", function () {
14 | it("should emit `CHANGE` event", function (done) {
15 | var expectedCount = 42;
16 | instance.on("CHANGE", done);
17 | dispatcher.emit("countUp", expectedCount);
18 | });
19 | });
20 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mini-flux
2 |
3 | mini flux implementation for DEMO.
4 |
5 | - No dependent library
6 | - Use EventEmitter only.(not use Flux's Dispatch)
7 | - just mean that this implement not handle order of events
8 |
9 |
10 | ## Installation
11 |
12 | npm install
13 |
14 | ## Usage
15 |
16 | npm run build
17 | open index.html
18 |
19 | ## Test
20 |
21 | npm test
22 |
23 | ## Contributing
24 |
25 | 1. Fork it!
26 | 2. Create your feature branch: `git checkout -b my-new-feature`
27 | 3. Commit your changes: `git commit -am 'Add some feature'`
28 | 4. Push to the branch: `git push origin my-new-feature`
29 | 5. Submit a pull request :D
30 |
31 | ## License
32 |
33 | MIT
34 |
--------------------------------------------------------------------------------
/test/ActionCreator-test.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import assert from "power-assert"
4 | import ActionCreator from "../src/ActionCreator"
5 | import EventEmitter from "../src/EventEmitter"
6 | describe("ActionCreator", function () {
7 | var dispatcher;
8 | var action;
9 | beforeEach(function () {
10 | dispatcher = new EventEmitter();
11 | action = new ActionCreator(dispatcher);
12 | });
13 | describe("countUp", function () {
14 | it("should emit `countUp` event", function (done) {
15 | var expectedCount = 42;
16 | dispatcher.on("countUp", function (count) {
17 | assert.equal(count, expectedCount);
18 | done();
19 | });
20 | action.countUp(expectedCount);
21 | });
22 | });
23 | });
--------------------------------------------------------------------------------
/src/EventEmitter.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | /*
4 | Simple EventEmitter
5 | */
6 | export default class EventEmitter {
7 | constructor() {
8 | this._handlers = {};
9 | }
10 |
11 | on(type, handler) {
12 | if (typeof this._handlers[type] === 'undefined') {
13 | this._handlers[type] = [];
14 | }
15 |
16 | this._handlers[type].push(handler);
17 | }
18 |
19 | emit(type, data) {
20 | var handlers = this._handlers[type] || [];
21 | for (var i = 0; i < handlers.length; i++) {
22 | var handler = handlers[i];
23 | handler.call(this, data);
24 | }
25 | }
26 |
27 | off(type, handler) {
28 | var handlers = this._handlers[type] || [];
29 | for (var i = 0; i < handlers.length; i++) {
30 | var ownHandler = handlers[i];
31 | if (ownHandler === handler) {
32 | handlers.splice(i, 1);
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 azu
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/Component.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import React from "react"
4 | import ActionCreator from "./ActionCreator"
5 | import Store from "./Store"
6 | import EventEmitter from "./EventEmitter"
7 |
8 | var dispatcher = new EventEmitter();
9 | var action = new ActionCreator(dispatcher);
10 | var store = new Store(dispatcher);
11 |
12 | export default class Component extends React.Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = {count: store.getCount()};
16 | // <- Observe store's change
17 | store.on("CHANGE", () => {
18 | this._onChange();
19 | });
20 | }
21 |
22 | _onChange() {
23 | this.setState({count: store.getCount()});
24 | }
25 |
26 | tick() {
27 | action.countUp(this.state.count + 1);
28 | }
29 |
30 | render() {
31 | return (
32 |
33 |
34 |
35 |
36 | Count: {this.state.count}
37 |
38 |
39 | );
40 | }
41 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mini-flux",
3 | "repository": {
4 | "type": "git",
5 | "url": "https://github.com/azu/mini-flux.git"
6 | },
7 | "author": "azu",
8 | "email": "azuciao@gmail.com",
9 | "homepage": "https://github.com/azu/mini-flux",
10 | "license": "MIT",
11 | "bugs": {
12 | "url": "https://github.com/azu/mini-flux/issues"
13 | },
14 | "version": "1.0.0",
15 | "description": "mini flux implementation for DEMO.",
16 | "main": "index.js",
17 | "directories": {
18 | "test": "test"
19 | },
20 | "scripts": {
21 | "build": "browserify -d -e src/App.js -t [ babelify --loose es6.classes ] -o build.js",
22 | "watch": "watchify -d -e src/App.js -t [ babelify --loose es6.classes ] -o build.js",
23 | "test": "mocha test/**/*.js"
24 | },
25 | "devDependencies": {
26 | "babel": "^5.1.11",
27 | "babel-core": "^5.1.11",
28 | "babel-plugin-espower": "^0.2.1",
29 | "babelify": "^6.0.2",
30 | "browserify": "^9.0.8",
31 | "mocha": "^2.2.4",
32 | "power-assert": "^0.11.0",
33 | "watchify": "^3.1.1"
34 | },
35 | "dependencies": {
36 | "react": "^0.13.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/test/EventEmitter-test.js:
--------------------------------------------------------------------------------
1 | // LICENSE : MIT
2 | "use strict";
3 | import assert from "power-assert"
4 | import EventEmitter from "../src/EventEmitter"
5 | describe("EventEmitter", function () {
6 | var emitter;
7 | beforeEach(function () {
8 | emitter = new EventEmitter();
9 | });
10 | describe("#on", function () {
11 | it("should set event handler to the key", function (done) {
12 | var key = "event-key";
13 | emitter.on(key, function () {
14 | done();
15 | });
16 | emitter.emit(key)
17 | });
18 | });
19 | describe("#emit", function () {
20 | it("should pass data to the handlers", function (done) {
21 | var key = "event-key";
22 | var passingData = {"key": "value"};
23 | emitter.on(key, function (data) {
24 | assert.deepEqual(data, passingData);
25 | done();
26 | });
27 | emitter.emit(key, passingData)
28 | });
29 | });
30 | describe("#off", function () {
31 | it("should unset event handler ", function (done) {
32 | var key = "event-key";
33 | var handler = function () {
34 | done(new Error("should not called"))
35 | };
36 | emitter.on(key, handler);
37 | emitter.off(key, handler);
38 | emitter.emit(key);
39 | emitter.on(key, done);
40 | emitter.emit(key);
41 | });
42 | });
43 | });
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### https://raw.github.com/github/gitignore/408c616ae0ad8f4b8101d8e876b9b67ac6b14059/Node.gitignore
2 |
3 | # Logs
4 | logs
5 | *.log
6 |
7 | # Runtime data
8 | pids
9 | *.pid
10 | *.seed
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19 | .grunt
20 |
21 | # node-waf configuration
22 | .lock-wscript
23 |
24 | # Compiled binary addons (http://nodejs.org/api/addons.html)
25 | build/Release
26 |
27 | # Dependency directory
28 | # Commenting this out is preferred by some people, see
29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
30 | node_modules
31 |
32 |
33 | ### https://raw.github.com/github/gitignore/408c616ae0ad8f4b8101d8e876b9b67ac6b14059/Global/JetBrains.gitignore
34 |
35 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
36 |
37 | *.iml
38 |
39 | ## Directory-based project format:
40 | .idea/
41 | # if you remove the above rule, at least ignore the following:
42 |
43 | # User-specific stuff:
44 | # .idea/workspace.xml
45 | # .idea/tasks.xml
46 | # .idea/dictionaries
47 |
48 | # Sensitive or high-churn files:
49 | # .idea/dataSources.ids
50 | # .idea/dataSources.xml
51 | # .idea/sqlDataSources.xml
52 | # .idea/dynamic.xml
53 | # .idea/uiDesigner.xml
54 |
55 | # Gradle:
56 | # .idea/gradle.xml
57 | # .idea/libraries
58 |
59 | # Mongo Explorer plugin:
60 | # .idea/mongoSettings.xml
61 |
62 | ## File-based project format:
63 | *.ipr
64 | *.iws
65 |
66 | ## Plugin-specific files:
67 |
68 | # IntelliJ
69 | out/
70 |
71 | # mpeltonen/sbt-idea plugin
72 | .idea_modules/
73 |
74 | # JIRA plugin
75 | atlassian-ide-plugin.xml
76 |
77 | # Crashlytics plugin (for Android Studio and IntelliJ)
78 | com_crashlytics_export_strings.xml
79 | crashlytics.properties
80 | crashlytics-build.properties
81 |
82 |
83 |
84 | build.js
--------------------------------------------------------------------------------