├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── TODO ├── arch.png ├── css └── react-object-inspector.css ├── dist ├── main.bundle.js └── worker.bundle.js ├── index.html ├── js ├── constants │ └── TodoFilters.js ├── dom │ ├── TodoApp.js │ ├── common │ │ ├── BusinessLayerLoader.js │ │ ├── FakeStore.js │ │ ├── ForkMe.js │ │ ├── StoreView.jsx │ │ └── initBridge.js │ ├── index.jsx │ └── todomvc-common │ │ └── index.css └── domless │ ├── AppDispatcher.js │ ├── BaseStore.js │ ├── TodoActions.js │ ├── TodoConstants.js │ ├── todoStore.js │ └── worker.js ├── package.json ├── style.css └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 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 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 29 | node_modules 30 | .idea 31 | 32 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | "use strict"; 3 | grunt.initConfig({ 4 | exec: { 5 | webpack: 'webpack --watch &' 6 | }, 7 | "http-server": { 8 | dev: { 9 | root: "./", 10 | port: 8000, 11 | host: "0.0.0.0", 12 | showDir: true, 13 | autoIndex: true, 14 | runInBackground: true 15 | } 16 | }, 17 | watch: { 18 | reload: { 19 | files: ["dist/**", "index.html"], 20 | options: { 21 | livereload: true 22 | } 23 | }, 24 | css: { 25 | files: ["style.css"], 26 | options: { 27 | livereload: true 28 | } 29 | } 30 | } 31 | }); 32 | 33 | grunt.loadNpmTasks('grunt-http-server'); 34 | grunt.loadNpmTasks("grunt-contrib-watch"); 35 | grunt.loadNpmTasks('grunt-exec'); 36 | 37 | grunt.registerTask("webpackWatch", ["exec:webpack"]); 38 | grunt.registerTask("default", ["http-server", "webpackWatch", "watch"]); 39 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Narendra Sisodiya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Flux inside Web Workers 2 | 3 | ![alt pic](https://raw.githubusercontent.com/nsisodiya/flux-inside-web-workers/master/arch.png) 4 | 5 | # Demo 6 | 7 | [http://nsisodiya.github.io/flux-inside-web-workers](http://nsisodiya.github.io/flux-inside-web-workers) 8 | 9 | # Blog 10 | 11 | [https://medium.com/@nsisodiya/flux-inside-web-workers-cc51fb463882](https://medium.com/@nsisodiya/flux-inside-web-workers-cc51fb463882) 12 | 13 | ## Requirements 14 | 15 | ```bash 16 | npm install -g grunt-cli 17 | npm install -g webpack 18 | ``` 19 | ## Execution 20 | 21 | ```bash 22 | git clone git@github.com:nsisodiya/flux-inside-web-workers.git 23 | cd flux-inside-web-workers 24 | npm install 25 | grunt 26 | ``` 27 | ## Bridge API 28 | In this project, I am using https://github.com/nsisodiya/bl-layer-loader for BL Layer and UI Layer communication ! -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | //TODO - multiple Stores, 2 | //TODO - Add localStorage ! 3 | //TODO - have FLUX on Server side 4 | 5 | 6 | //TODO - store.off when componentdidUmount 7 | //TODO = Double Click to Edit 8 | //TODO = Routing 9 | //TODO = Test Cases ! 10 | -------------------------------------------------------------------------------- /arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsisodiya/flux-inside-web-workers/75416aa00d33bb46fe2afed2a358a45f1b8eb7f9/arch.png -------------------------------------------------------------------------------- /css/react-object-inspector.css: -------------------------------------------------------------------------------- 1 | .ObjectInspector { 2 | font-family: Menlo, monospace; 3 | font-size: 11px; 4 | line-height: 14px; 5 | cursor: default; 6 | } 7 | 8 | .ObjectInspector-unselectable { 9 | -webkit-touch-callout: none; 10 | -webkit-user-select: none; 11 | -khtml-user-select: none; 12 | -moz-user-select: none; 13 | -ms-user-select: none; 14 | -o-user-select: none; 15 | user-select: none; 16 | } 17 | 18 | .ObjectInspector-expand-control { 19 | color: #6e6e6e; 20 | font-size: 10px; 21 | margin-right: 3px; 22 | white-space: pre; 23 | } 24 | 25 | .ObjectInspector-property { 26 | padding-top: 2px; 27 | } 28 | 29 | .ObjectInspector-object-name { 30 | color: rgb(136, 19, 145); 31 | } 32 | 33 | .ObjectInspector-object-value-null, .ObjectInspector-object-value-undefined { 34 | color: rgb(128, 128, 128); 35 | } 36 | 37 | .ObjectInspector-object-value-string { 38 | color: rgb(196, 26, 22); 39 | } 40 | 41 | .ObjectInspector-object-value-number, .ObjectInspector-object-value-boolean { 42 | color: rgb(28, 0, 207); 43 | } 44 | 45 | .ObjectInspector-object-value-function-keyword { 46 | color: rgb(170, 13, 145); 47 | font-style: italic; 48 | } 49 | 50 | .ObjectInspector-object-value-function-name { 51 | font-style: italic; 52 | } 53 | 54 | .ObjectInspector-object-preview { 55 | font-style: italic; 56 | } 57 | 58 | .ObjectInspector-property-nodes-container { 59 | padding-left: 12px 60 | } 61 | -------------------------------------------------------------------------------- /dist/worker.bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | 29 | 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = ""; 38 | 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ({ 44 | 45 | /***/ 0: 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | 'use strict'; 49 | 50 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 51 | 52 | var _blLayerLoader = __webpack_require__(161); 53 | 54 | var _blLayerLoader2 = _interopRequireDefault(_blLayerLoader); 55 | 56 | var todostore = __webpack_require__(167); 57 | var TodoActions = __webpack_require__(175); 58 | 59 | var bridge = _blLayerLoader2['default'].getBLBridge(); 60 | 61 | todostore.on('change', function () { 62 | bridge.post("/stores/TodoStore/updateState", todostore.getState()); 63 | }); 64 | 65 | bridge.on("/stores/TodoStore/getInitialState", function (payload, sendBack) { 66 | sendBack(todostore.getState()); 67 | }); 68 | 69 | //TODO , support : Syntax 70 | //bridge.on("/actions/TodoActions/:method", function (payload, sendBack, path) { 71 | // var method = path.params.method 72 | // path.url = "/actions/TodoActions/addTodo" 73 | // path.matchedUrl = "/actions/TodoActions/:method" 74 | // TodoActions[method].call(TodoActions, payload); 75 | //}); 76 | 77 | bridge.on("/actions/TodoActions/addTodo", function (payload, sendBack, path) { 78 | TodoActions.addTodo(payload); 79 | }); 80 | 81 | bridge.on("/actions/TodoActions/markComplete", function (payload, sendBack, path) { 82 | TodoActions.markComplete(payload); 83 | }); 84 | 85 | bridge.on("/actions/TodoActions/remove", function (payload, sendBack, path) { 86 | TodoActions.remove(payload); 87 | }); 88 | 89 | bridge.on("/actions/TodoActions/removeAllCompleted", function (payload, sendBack, path) { 90 | TodoActions.removeAllCompleted(); 91 | }); 92 | 93 | bridge.on("/actions/TodoActions/edit", function (payload, sendBack, path) { 94 | TodoActions.edit(payload.id, payload.text); 95 | }); 96 | 97 | bridge.on("/actions/TodoActions/markUnComplete", function (payload, sendBack, path) { 98 | TodoActions.markUnComplete(payload); 99 | }); 100 | 101 | bridge.on("/actions/TodoActions/markAllUnComplete", function (payload, sendBack, path) { 102 | TodoActions.markAllUnComplete(); 103 | }); 104 | 105 | bridge.on("/actions/TodoActions/markAllComplete", function (payload, sendBack, path) { 106 | TodoActions.markAllComplete(); 107 | }); 108 | 109 | bridge.on("/actions/TodoActions/onShow", function (payload, sendBack, path) { 110 | TodoActions.onShow(payload); 111 | }); 112 | 113 | /***/ }, 114 | 115 | /***/ 3: 116 | /***/ function(module, exports) { 117 | 118 | // shim for using process in browser 119 | 120 | 'use strict'; 121 | 122 | var process = module.exports = {}; 123 | var queue = []; 124 | var draining = false; 125 | var currentQueue; 126 | var queueIndex = -1; 127 | 128 | function cleanUpNextTick() { 129 | draining = false; 130 | if (currentQueue.length) { 131 | queue = currentQueue.concat(queue); 132 | } else { 133 | queueIndex = -1; 134 | } 135 | if (queue.length) { 136 | drainQueue(); 137 | } 138 | } 139 | 140 | function drainQueue() { 141 | if (draining) { 142 | return; 143 | } 144 | var timeout = setTimeout(cleanUpNextTick); 145 | draining = true; 146 | 147 | var len = queue.length; 148 | while (len) { 149 | currentQueue = queue; 150 | queue = []; 151 | while (++queueIndex < len) { 152 | if (currentQueue) { 153 | currentQueue[queueIndex].run(); 154 | } 155 | } 156 | queueIndex = -1; 157 | len = queue.length; 158 | } 159 | currentQueue = null; 160 | draining = false; 161 | clearTimeout(timeout); 162 | } 163 | 164 | process.nextTick = function (fun) { 165 | var args = new Array(arguments.length - 1); 166 | if (arguments.length > 1) { 167 | for (var i = 1; i < arguments.length; i++) { 168 | args[i - 1] = arguments[i]; 169 | } 170 | } 171 | queue.push(new Item(fun, args)); 172 | if (queue.length === 1 && !draining) { 173 | setTimeout(drainQueue, 0); 174 | } 175 | }; 176 | 177 | // v8 likes predictible objects 178 | function Item(fun, array) { 179 | this.fun = fun; 180 | this.array = array; 181 | } 182 | Item.prototype.run = function () { 183 | this.fun.apply(null, this.array); 184 | }; 185 | process.title = 'browser'; 186 | process.browser = true; 187 | process.env = {}; 188 | process.argv = []; 189 | process.version = ''; // empty string to avoid regexp issues 190 | process.versions = {}; 191 | 192 | function noop() {} 193 | 194 | process.on = noop; 195 | process.addListener = noop; 196 | process.once = noop; 197 | process.off = noop; 198 | process.removeListener = noop; 199 | process.removeAllListeners = noop; 200 | process.emit = noop; 201 | 202 | process.binding = function (name) { 203 | throw new Error('process.binding is not supported'); 204 | }; 205 | 206 | process.cwd = function () { 207 | return '/'; 208 | }; 209 | process.chdir = function (dir) { 210 | throw new Error('process.chdir is not supported'); 211 | }; 212 | process.umask = function () { 213 | return 0; 214 | }; 215 | 216 | /***/ }, 217 | 218 | /***/ 161: 219 | /***/ function(module, exports) { 220 | 221 | /** 222 | * Created by narendrasisodiya on 06/08/15. 223 | */ 224 | "use strict"; 225 | 226 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 227 | 228 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 229 | 230 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 231 | 232 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 233 | 234 | var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; 235 | 236 | var MESSAGE_TYPE = { 237 | RETURN_MESSAGE: "returnMessage", 238 | DEPART_WITH_SENDBACK_ID: "departWithSendBackId", 239 | DEPART: "depart" 240 | }; 241 | 242 | function setUpGlobalMessagePass() { 243 | if (ENVIRONMENT_IS_WORKER === false && window._globalMessagePassForWorkerLessEnv_ === undefined) { 244 | //Define only once ! 245 | var local = {}; 246 | 247 | local.registerBL = function (callback) { 248 | local.BL = callback; 249 | }; 250 | 251 | local.registerUI = function (callback) { 252 | local.UI = callback; 253 | }; 254 | local.sendToBL = function (message) { 255 | local.BL(message); 256 | }; 257 | local.sendToUI = function (message) { 258 | local.UI(message); 259 | }; 260 | window._globalMessagePassForWorkerLessEnv_ = local; 261 | } 262 | } 263 | 264 | var FakeWorker = (function () { 265 | function FakeWorker(BLL) { 266 | _classCallCheck(this, FakeWorker); 267 | 268 | if (BLL === undefined) { 269 | throw "Send BLL Variable Either True of False"; 270 | } 271 | this.BLL = BLL; 272 | } 273 | 274 | _createClass(FakeWorker, [{ 275 | key: "addEventListener", 276 | value: function addEventListener(topic, callback) { 277 | if (this.BLL) { 278 | window._globalMessagePassForWorkerLessEnv_.registerBL(callback); 279 | } else { 280 | window._globalMessagePassForWorkerLessEnv_.registerUI(callback); 281 | } 282 | } 283 | }, { 284 | key: "postMessage", 285 | value: function postMessage(message) { 286 | if (this.BLL) { 287 | window._globalMessagePassForWorkerLessEnv_.sendToUI({ 288 | data: message 289 | }); 290 | } else { 291 | window._globalMessagePassForWorkerLessEnv_.sendToBL({ 292 | data: message 293 | }); 294 | } 295 | } 296 | }]); 297 | 298 | return FakeWorker; 299 | })(); 300 | 301 | var BaseAdapter = (function () { 302 | function BaseAdapter() { 303 | _classCallCheck(this, BaseAdapter); 304 | 305 | this.isBridgeReady = false; 306 | this._evtBus = {}; 307 | this._unsubObj = []; 308 | this._returnCallback = []; 309 | this.BLLayer = true; 310 | } 311 | 312 | _createClass(BaseAdapter, [{ 313 | key: "_processRawMessage", 314 | value: function _processRawMessage(message) { 315 | console.log("Message Received", message); 316 | 317 | if (message.type === MESSAGE_TYPE.RETURN_MESSAGE) { 318 | var c = this._returnCallback[message.sendBackId]; 319 | if (typeof c === "function") { 320 | c(message.payload); 321 | this._returnCallback[message.sendBackId] = null; 322 | } else { 323 | console.error("message contains sendBackID which do not have any corrosponding callback"); 324 | } 325 | } else { 326 | var path = message.path; 327 | 328 | //Some Message comes from URL Worker thread, we need to process it. message is raw message. payload is inside raw message. 329 | // User is only interested in payload. 330 | var f = this._evtBus[path]; 331 | var THAT = this; 332 | if (f !== undefined && f.length !== 0) { 333 | f.map(function (v, i) { 334 | v(message.payload, function (sendBackData) { 335 | console.log("send Back data is", sendBackData); 336 | THAT.worker.postMessage({ 337 | payload: sendBackData, 338 | type: MESSAGE_TYPE.RETURN_MESSAGE, 339 | sendBackId: message.sendBackId 340 | }); 341 | }); 342 | }); 343 | } 344 | } 345 | } 346 | }, { 347 | key: "on", 348 | value: function on(path, callback) { 349 | if (this._evtBus[path] === undefined) { 350 | this._evtBus[path] = []; 351 | } 352 | var index = this._evtBus[path].push(callback) - 1; 353 | var unSubIndex = this._unsubObj.push({ 354 | path: path, 355 | index: index 356 | }) - 1; 357 | 358 | return unSubIndex; 359 | } 360 | }, { 361 | key: "off", 362 | value: function off(unSubIndex) { 363 | try { 364 | var _unsubObj$unSubIndex = this._unsubObj[unSubIndex]; 365 | var path = _unsubObj$unSubIndex.path; 366 | var index = _unsubObj$unSubIndex.index; 367 | 368 | this._evtBus[path][index] = null; 369 | } catch (ex) {} 370 | } 371 | }, { 372 | key: "post", 373 | value: function post(path, payload, callback) { 374 | if (callback === undefined) { 375 | this.worker.postMessage({ 376 | path: path, 377 | payload: payload, 378 | type: MESSAGE_TYPE.DEPART 379 | }); 380 | } else { 381 | var id = this._registerSendBack(path, callback); 382 | this.worker.postMessage({ 383 | path: path, 384 | payload: payload, 385 | type: MESSAGE_TYPE.DEPART_WITH_SENDBACK_ID, 386 | sendBackId: id 387 | }); 388 | } 389 | } 390 | }, { 391 | key: "_registerSendBack", 392 | value: function _registerSendBack(path, callback) { 393 | //when a Raw Message comes with type : "return", we need to find its corresponding callback. 394 | var x = this._returnCallback.push(callback); 395 | return x - 1; 396 | } 397 | }]); 398 | 399 | return BaseAdapter; 400 | })(); 401 | 402 | var LocalAdapter = (function (_BaseAdapter) { 403 | _inherits(LocalAdapter, _BaseAdapter); 404 | 405 | function LocalAdapter(url) { 406 | var _this = this; 407 | 408 | _classCallCheck(this, LocalAdapter); 409 | 410 | _get(Object.getPrototypeOf(LocalAdapter.prototype), "constructor", this).call(this); 411 | 412 | if (url !== undefined) { 413 | this._loadScript(url); 414 | this.BLLayer = false; 415 | } 416 | 417 | if (window._globalMessagePassForWorkerLessEnv_ === undefined) { 418 | setUpGlobalMessagePass(); 419 | } 420 | this.worker = new FakeWorker(this.BLLayer); 421 | 422 | this.worker.addEventListener('message', function (e) { 423 | _this._processRawMessage(e.data); 424 | }, false); 425 | } 426 | 427 | _createClass(LocalAdapter, [{ 428 | key: "_loadScript", 429 | value: function _loadScript(url) { 430 | var _this2 = this; 431 | 432 | var script = document.createElement('script'); 433 | script.src = url; 434 | script.onload = function () { 435 | _this2._onScriptLoaded(); 436 | }; 437 | document.head.appendChild(script); 438 | } 439 | }, { 440 | key: "_onScriptLoaded", 441 | value: function _onScriptLoaded() { 442 | this.isBridgeReady = true; 443 | if (this._onReadyCallback !== undefined) { 444 | this._onReadyCallback(); 445 | this._onReadyCallback === undefined; 446 | } 447 | } 448 | }, { 449 | key: "onReady", 450 | value: function onReady(callback) { 451 | if (this.isBridgeReady === true) { 452 | callback(); 453 | } else { 454 | this._onReadyCallback = callback; 455 | } 456 | } 457 | }]); 458 | 459 | return LocalAdapter; 460 | })(BaseAdapter); 461 | 462 | var WorkerAdapter = (function (_BaseAdapter2) { 463 | _inherits(WorkerAdapter, _BaseAdapter2); 464 | 465 | function WorkerAdapter(url) { 466 | var _this3 = this; 467 | 468 | _classCallCheck(this, WorkerAdapter); 469 | 470 | _get(Object.getPrototypeOf(WorkerAdapter.prototype), "constructor", this).call(this); 471 | if (ENVIRONMENT_IS_WORKER === false) { 472 | this.BLLayer = false; 473 | this.worker = new Worker(url); 474 | } else { 475 | this.BLLayer = true; 476 | this.worker = self; 477 | } 478 | this.worker.addEventListener('message', function (e) { 479 | _this3._processRawMessage(e.data); 480 | }, false); 481 | } 482 | 483 | _createClass(WorkerAdapter, [{ 484 | key: "onReady", 485 | value: function onReady(callback) { 486 | callback(); //Immediatly execute callback - TODO 487 | } 488 | }]); 489 | 490 | return WorkerAdapter; 491 | })(BaseAdapter); 492 | 493 | var BLLayerLoader = { 494 | load: function load(config) { 495 | if (ENVIRONMENT_IS_WORKER === true) { 496 | throw "This method should not be called from Worker"; 497 | return; 498 | } 499 | var url = config.url; 500 | var method = config.method; 501 | 502 | if (method === "Worker") { 503 | return new WorkerAdapter(url); 504 | } 505 | if (method === "Local") { 506 | return new LocalAdapter(url); 507 | } 508 | }, 509 | getBLBridge: function getBLBridge() { 510 | if (ENVIRONMENT_IS_WORKER === true) { 511 | return new WorkerAdapter(); 512 | } else { 513 | return new LocalAdapter(); 514 | } 515 | } 516 | }; 517 | 518 | module.exports = BLLayerLoader; 519 | 520 | /***/ }, 521 | 522 | /***/ 163: 523 | /***/ function(module, exports) { 524 | 525 | 'use strict'; 526 | 527 | Object.defineProperty(exports, '__esModule', { 528 | value: true 529 | }); 530 | var SHOW_ALL = 'show_all'; 531 | exports.SHOW_ALL = SHOW_ALL; 532 | var SHOW_COMPLETED = 'show_completed'; 533 | exports.SHOW_COMPLETED = SHOW_COMPLETED; 534 | var SHOW_ACTIVE = 'show_active'; 535 | exports.SHOW_ACTIVE = SHOW_ACTIVE; 536 | 537 | /***/ }, 538 | 539 | /***/ 166: 540 | /***/ function(module, exports) { 541 | 542 | // Copyright Joyent, Inc. and other Node contributors. 543 | // 544 | // Permission is hereby granted, free of charge, to any person obtaining a 545 | // copy of this software and associated documentation files (the 546 | // "Software"), to deal in the Software without restriction, including 547 | // without limitation the rights to use, copy, modify, merge, publish, 548 | // distribute, sublicense, and/or sell copies of the Software, and to permit 549 | // persons to whom the Software is furnished to do so, subject to the 550 | // following conditions: 551 | // 552 | // The above copyright notice and this permission notice shall be included 553 | // in all copies or substantial portions of the Software. 554 | // 555 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 556 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 557 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 558 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 559 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 560 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 561 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 562 | 563 | 'use strict'; 564 | 565 | function EventEmitter() { 566 | this._events = this._events || {}; 567 | this._maxListeners = this._maxListeners || undefined; 568 | } 569 | module.exports = EventEmitter; 570 | 571 | // Backwards-compat with node 0.10.x 572 | EventEmitter.EventEmitter = EventEmitter; 573 | 574 | EventEmitter.prototype._events = undefined; 575 | EventEmitter.prototype._maxListeners = undefined; 576 | 577 | // By default EventEmitters will print a warning if more than 10 listeners are 578 | // added to it. This is a useful default which helps finding memory leaks. 579 | EventEmitter.defaultMaxListeners = 10; 580 | 581 | // Obviously not all Emitters should be limited to 10. This function allows 582 | // that to be increased. Set to zero for unlimited. 583 | EventEmitter.prototype.setMaxListeners = function (n) { 584 | if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); 585 | this._maxListeners = n; 586 | return this; 587 | }; 588 | 589 | EventEmitter.prototype.emit = function (type) { 590 | var er, handler, len, args, i, listeners; 591 | 592 | if (!this._events) this._events = {}; 593 | 594 | // If there is no 'error' event listener then throw. 595 | if (type === 'error') { 596 | if (!this._events.error || isObject(this._events.error) && !this._events.error.length) { 597 | er = arguments[1]; 598 | if (er instanceof Error) { 599 | throw er; // Unhandled 'error' event 600 | } 601 | throw TypeError('Uncaught, unspecified "error" event.'); 602 | } 603 | } 604 | 605 | handler = this._events[type]; 606 | 607 | if (isUndefined(handler)) return false; 608 | 609 | if (isFunction(handler)) { 610 | switch (arguments.length) { 611 | // fast cases 612 | case 1: 613 | handler.call(this); 614 | break; 615 | case 2: 616 | handler.call(this, arguments[1]); 617 | break; 618 | case 3: 619 | handler.call(this, arguments[1], arguments[2]); 620 | break; 621 | // slower 622 | default: 623 | args = Array.prototype.slice.call(arguments, 1); 624 | handler.apply(this, args); 625 | } 626 | } else if (isObject(handler)) { 627 | args = Array.prototype.slice.call(arguments, 1); 628 | listeners = handler.slice(); 629 | len = listeners.length; 630 | for (i = 0; i < len; i++) listeners[i].apply(this, args); 631 | } 632 | 633 | return true; 634 | }; 635 | 636 | EventEmitter.prototype.addListener = function (type, listener) { 637 | var m; 638 | 639 | if (!isFunction(listener)) throw TypeError('listener must be a function'); 640 | 641 | if (!this._events) this._events = {}; 642 | 643 | // To avoid recursion in the case that type === "newListener"! Before 644 | // adding it to the listeners, first emit "newListener". 645 | if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener); 646 | 647 | if (!this._events[type]) 648 | // Optimize the case of one listener. Don't need the extra array object. 649 | this._events[type] = listener;else if (isObject(this._events[type])) 650 | // If we've already got an array, just append. 651 | this._events[type].push(listener);else 652 | // Adding the second element, need to change to array. 653 | this._events[type] = [this._events[type], listener]; 654 | 655 | // Check for listener leak 656 | if (isObject(this._events[type]) && !this._events[type].warned) { 657 | if (!isUndefined(this._maxListeners)) { 658 | m = this._maxListeners; 659 | } else { 660 | m = EventEmitter.defaultMaxListeners; 661 | } 662 | 663 | if (m && m > 0 && this._events[type].length > m) { 664 | this._events[type].warned = true; 665 | console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); 666 | if (typeof console.trace === 'function') { 667 | // not supported in IE 10 668 | console.trace(); 669 | } 670 | } 671 | } 672 | 673 | return this; 674 | }; 675 | 676 | EventEmitter.prototype.on = EventEmitter.prototype.addListener; 677 | 678 | EventEmitter.prototype.once = function (type, listener) { 679 | if (!isFunction(listener)) throw TypeError('listener must be a function'); 680 | 681 | var fired = false; 682 | 683 | function g() { 684 | this.removeListener(type, g); 685 | 686 | if (!fired) { 687 | fired = true; 688 | listener.apply(this, arguments); 689 | } 690 | } 691 | 692 | g.listener = listener; 693 | this.on(type, g); 694 | 695 | return this; 696 | }; 697 | 698 | // emits a 'removeListener' event iff the listener was removed 699 | EventEmitter.prototype.removeListener = function (type, listener) { 700 | var list, position, length, i; 701 | 702 | if (!isFunction(listener)) throw TypeError('listener must be a function'); 703 | 704 | if (!this._events || !this._events[type]) return this; 705 | 706 | list = this._events[type]; 707 | length = list.length; 708 | position = -1; 709 | 710 | if (list === listener || isFunction(list.listener) && list.listener === listener) { 711 | delete this._events[type]; 712 | if (this._events.removeListener) this.emit('removeListener', type, listener); 713 | } else if (isObject(list)) { 714 | for (i = length; i-- > 0;) { 715 | if (list[i] === listener || list[i].listener && list[i].listener === listener) { 716 | position = i; 717 | break; 718 | } 719 | } 720 | 721 | if (position < 0) return this; 722 | 723 | if (list.length === 1) { 724 | list.length = 0; 725 | delete this._events[type]; 726 | } else { 727 | list.splice(position, 1); 728 | } 729 | 730 | if (this._events.removeListener) this.emit('removeListener', type, listener); 731 | } 732 | 733 | return this; 734 | }; 735 | 736 | EventEmitter.prototype.removeAllListeners = function (type) { 737 | var key, listeners; 738 | 739 | if (!this._events) return this; 740 | 741 | // not listening for removeListener, no need to emit 742 | if (!this._events.removeListener) { 743 | if (arguments.length === 0) this._events = {};else if (this._events[type]) delete this._events[type]; 744 | return this; 745 | } 746 | 747 | // emit removeListener for all listeners on all events 748 | if (arguments.length === 0) { 749 | for (key in this._events) { 750 | if (key === 'removeListener') continue; 751 | this.removeAllListeners(key); 752 | } 753 | this.removeAllListeners('removeListener'); 754 | this._events = {}; 755 | return this; 756 | } 757 | 758 | listeners = this._events[type]; 759 | 760 | if (isFunction(listeners)) { 761 | this.removeListener(type, listeners); 762 | } else if (listeners) { 763 | // LIFO order 764 | while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); 765 | } 766 | delete this._events[type]; 767 | 768 | return this; 769 | }; 770 | 771 | EventEmitter.prototype.listeners = function (type) { 772 | var ret; 773 | if (!this._events || !this._events[type]) ret = [];else if (isFunction(this._events[type])) ret = [this._events[type]];else ret = this._events[type].slice(); 774 | return ret; 775 | }; 776 | 777 | EventEmitter.prototype.listenerCount = function (type) { 778 | if (this._events) { 779 | var evlistener = this._events[type]; 780 | 781 | if (isFunction(evlistener)) return 1;else if (evlistener) return evlistener.length; 782 | } 783 | return 0; 784 | }; 785 | 786 | EventEmitter.listenerCount = function (emitter, type) { 787 | return emitter.listenerCount(type); 788 | }; 789 | 790 | function isFunction(arg) { 791 | return typeof arg === 'function'; 792 | } 793 | 794 | function isNumber(arg) { 795 | return typeof arg === 'number'; 796 | } 797 | 798 | function isObject(arg) { 799 | return typeof arg === 'object' && arg !== null; 800 | } 801 | 802 | function isUndefined(arg) { 803 | return arg === void 0; 804 | } 805 | 806 | /***/ }, 807 | 808 | /***/ 167: 809 | /***/ function(module, exports, __webpack_require__) { 810 | 811 | 'use strict'; 812 | 813 | var _actionToMethodsMapping; 814 | 815 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 816 | 817 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 818 | 819 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } 820 | 821 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 822 | 823 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 824 | 825 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 826 | 827 | var _constantsTodoFilters = __webpack_require__(163); 828 | 829 | var AppDispatcher = __webpack_require__(168); 830 | var TodoConstants = __webpack_require__(172); 831 | var BaseStore = __webpack_require__(174); 832 | 833 | var TodoStoreClass = (function (_BaseStore) { 834 | _inherits(TodoStoreClass, _BaseStore); 835 | 836 | function TodoStoreClass() { 837 | _classCallCheck(this, TodoStoreClass); 838 | 839 | _get(Object.getPrototypeOf(TodoStoreClass.prototype), 'constructor', this).call(this); 840 | if (this.state.todos.length !== 0) { 841 | this.counter = this.state.todos[this.state.todos.length - 1].id + 1; 842 | } else { 843 | this.counter = this.state.todos.length; 844 | } 845 | } 846 | 847 | _createClass(TodoStoreClass, [{ 848 | key: 'getInitialState', 849 | value: function getInitialState() { 850 | var defaultState = { 851 | todos: [], 852 | selectedFilter: _constantsTodoFilters.SHOW_ALL 853 | }; 854 | return defaultState; 855 | // try { 856 | // var state = JSON.parse(window.localStorage.getItem("todoStore")); 857 | // if (state !== null && state !== undefined) { 858 | // return state; 859 | // } else { 860 | // return defaultState; 861 | // } 862 | // } catch (ex) { 863 | // return defaultState; 864 | // } 865 | } 866 | }, { 867 | key: 'addTodo', 868 | value: function addTodo(text) { 869 | this.setState({ 870 | todos: [].concat(_toConsumableArray(this.state.todos), [{ 871 | task: text, 872 | done: false, 873 | id: this.counter 874 | }]) 875 | }); 876 | this.counter++; 877 | } 878 | }, { 879 | key: 'duringSetState', 880 | value: function duringSetState() { 881 | this.state.completed = this.getTotalCompleted(); 882 | this.state.uncompleted = this.state.todos.length - this.state.completed; 883 | //window.localStorage.setItem("todoStore", JSON.stringify(this.state)); 884 | } 885 | }, { 886 | key: 'markComplete', 887 | value: function markComplete(id) { 888 | this.setState({ 889 | todos: this.state.todos.map(function (v) { 890 | if (v.id === id) { 891 | v.done = true; 892 | } 893 | return v; 894 | }) 895 | }); 896 | } 897 | }, { 898 | key: 'remove', 899 | value: function remove(id) { 900 | this.setState({ 901 | todos: this.state.todos.filter(function (v) { 902 | return v.id !== id; 903 | }) 904 | }); 905 | } 906 | }, { 907 | key: 'removeAllCompleted', 908 | value: function removeAllCompleted() { 909 | this.setState({ 910 | todos: this.state.todos.filter(function (v) { 911 | return v.done === false; 912 | }) 913 | }); 914 | } 915 | }, { 916 | key: 'markAllComplete', 917 | value: function markAllComplete() { 918 | this.setState({ 919 | todos: this.state.todos.map(function (v) { 920 | v.done = true; 921 | return v; 922 | }) 923 | }); 924 | } 925 | }, { 926 | key: 'edit', 927 | value: function edit(id, task) { 928 | this.setState({ 929 | todos: this.state.todos.map(function (v) { 930 | if (v.id === id) { 931 | v.task = task; 932 | } 933 | return v; 934 | }) 935 | }); 936 | } 937 | }, { 938 | key: 'markAllUnComplete', 939 | value: function markAllUnComplete() { 940 | this.setState({ 941 | todos: this.state.todos.map(function (v) { 942 | v.done = false; 943 | return v; 944 | }) 945 | }); 946 | } 947 | }, { 948 | key: 'markUnComplete', 949 | value: function markUnComplete(id) { 950 | this.setState({ 951 | todos: this.state.todos.map(function (v) { 952 | if (v.id === id) { 953 | v.done = false; 954 | } 955 | return v; 956 | }) 957 | }); 958 | } 959 | }, { 960 | key: 'getTotalCompleted', 961 | value: function getTotalCompleted() { 962 | return this.state.todos.filter(function (v) { 963 | return v.done === true; 964 | }).length; 965 | } 966 | }, { 967 | key: 'onShow', 968 | value: function onShow(filter) { 969 | this.setState({ selectedFilter: filter, todos: this.state.todos }); 970 | } 971 | }]); 972 | 973 | return TodoStoreClass; 974 | })(BaseStore); 975 | 976 | var TodoStore = new TodoStoreClass(); 977 | var actionToMethodsMapping = (_actionToMethodsMapping = {}, _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_CREATE, "addTodo"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_REMOVE, "remove"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_MARK_COMPLETE, "markComplete"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_EDIT, "edit"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_MARK_UNCOMPLETE, "markUnComplete"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_MARK_ALL_COMPLETE, "markAllComplete"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_MARK_ALL_UNCOMPLETE, "markAllUnComplete"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_REMOVE_ALL_COMPLETED, "removeAllCompleted"), _defineProperty(_actionToMethodsMapping, TodoConstants.TODO_ON_SHOW, "onShow"), _actionToMethodsMapping); 978 | 979 | AppDispatcher.register(function (e) { 980 | var action = e.action; 981 | if (actionToMethodsMapping[action.actionType] !== undefined) { 982 | TodoStore[actionToMethodsMapping[action.actionType]].apply(TodoStore, action.args); 983 | } 984 | }); 985 | module.exports = TodoStore; 986 | 987 | /***/ }, 988 | 989 | /***/ 168: 990 | /***/ function(module, exports, __webpack_require__) { 991 | 992 | "use strict"; 993 | 994 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 995 | 996 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 997 | 998 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 999 | 1000 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1001 | 1002 | var Dispatcher = __webpack_require__(169).Dispatcher; 1003 | 1004 | var AppDispatcher = (function (_Dispatcher) { 1005 | _inherits(AppDispatcher, _Dispatcher); 1006 | 1007 | function AppDispatcher() { 1008 | _classCallCheck(this, AppDispatcher); 1009 | 1010 | _get(Object.getPrototypeOf(AppDispatcher.prototype), "constructor", this).call(this); 1011 | } 1012 | 1013 | _createClass(AppDispatcher, [{ 1014 | key: "handleViewAction", 1015 | value: function handleViewAction(action) { 1016 | //console.log(action); 1017 | this.dispatch({ 1018 | source: "VIEW_ACTION", 1019 | action: action 1020 | }); 1021 | } 1022 | }]); 1023 | 1024 | return AppDispatcher; 1025 | })(Dispatcher); 1026 | 1027 | module.exports = new AppDispatcher(); 1028 | 1029 | /***/ }, 1030 | 1031 | /***/ 169: 1032 | /***/ function(module, exports, __webpack_require__) { 1033 | 1034 | /** 1035 | * Copyright (c) 2014-2015, Facebook, Inc. 1036 | * All rights reserved. 1037 | * 1038 | * This source code is licensed under the BSD-style license found in the 1039 | * LICENSE file in the root directory of this source tree. An additional grant 1040 | * of patent rights can be found in the PATENTS file in the same directory. 1041 | */ 1042 | 1043 | 'use strict'; 1044 | 1045 | module.exports.Dispatcher = __webpack_require__(170); 1046 | 1047 | /***/ }, 1048 | 1049 | /***/ 170: 1050 | /***/ function(module, exports, __webpack_require__) { 1051 | 1052 | /* WEBPACK VAR INJECTION */(function(process) {/** 1053 | * Copyright (c) 2014-2015, Facebook, Inc. 1054 | * All rights reserved. 1055 | * 1056 | * This source code is licensed under the BSD-style license found in the 1057 | * LICENSE file in the root directory of this source tree. An additional grant 1058 | * of patent rights can be found in the PATENTS file in the same directory. 1059 | * 1060 | * @providesModule Dispatcher 1061 | * 1062 | * @preventMunge 1063 | */ 1064 | 1065 | 'use strict'; 1066 | 1067 | exports.__esModule = true; 1068 | 1069 | function _classCallCheck(instance, Constructor) { 1070 | if (!(instance instanceof Constructor)) { 1071 | throw new TypeError('Cannot call a class as a function'); 1072 | } 1073 | } 1074 | 1075 | var invariant = __webpack_require__(171); 1076 | 1077 | var _prefix = 'ID_'; 1078 | 1079 | /** 1080 | * Dispatcher is used to broadcast payloads to registered callbacks. This is 1081 | * different from generic pub-sub systems in two ways: 1082 | * 1083 | * 1) Callbacks are not subscribed to particular events. Every payload is 1084 | * dispatched to every registered callback. 1085 | * 2) Callbacks can be deferred in whole or part until other callbacks have 1086 | * been executed. 1087 | * 1088 | * For example, consider this hypothetical flight destination form, which 1089 | * selects a default city when a country is selected: 1090 | * 1091 | * var flightDispatcher = new Dispatcher(); 1092 | * 1093 | * // Keeps track of which country is selected 1094 | * var CountryStore = {country: null}; 1095 | * 1096 | * // Keeps track of which city is selected 1097 | * var CityStore = {city: null}; 1098 | * 1099 | * // Keeps track of the base flight price of the selected city 1100 | * var FlightPriceStore = {price: null} 1101 | * 1102 | * When a user changes the selected city, we dispatch the payload: 1103 | * 1104 | * flightDispatcher.dispatch({ 1105 | * actionType: 'city-update', 1106 | * selectedCity: 'paris' 1107 | * }); 1108 | * 1109 | * This payload is digested by `CityStore`: 1110 | * 1111 | * flightDispatcher.register(function(payload) { 1112 | * if (payload.actionType === 'city-update') { 1113 | * CityStore.city = payload.selectedCity; 1114 | * } 1115 | * }); 1116 | * 1117 | * When the user selects a country, we dispatch the payload: 1118 | * 1119 | * flightDispatcher.dispatch({ 1120 | * actionType: 'country-update', 1121 | * selectedCountry: 'australia' 1122 | * }); 1123 | * 1124 | * This payload is digested by both stores: 1125 | * 1126 | * CountryStore.dispatchToken = flightDispatcher.register(function(payload) { 1127 | * if (payload.actionType === 'country-update') { 1128 | * CountryStore.country = payload.selectedCountry; 1129 | * } 1130 | * }); 1131 | * 1132 | * When the callback to update `CountryStore` is registered, we save a reference 1133 | * to the returned token. Using this token with `waitFor()`, we can guarantee 1134 | * that `CountryStore` is updated before the callback that updates `CityStore` 1135 | * needs to query its data. 1136 | * 1137 | * CityStore.dispatchToken = flightDispatcher.register(function(payload) { 1138 | * if (payload.actionType === 'country-update') { 1139 | * // `CountryStore.country` may not be updated. 1140 | * flightDispatcher.waitFor([CountryStore.dispatchToken]); 1141 | * // `CountryStore.country` is now guaranteed to be updated. 1142 | * 1143 | * // Select the default city for the new country 1144 | * CityStore.city = getDefaultCityForCountry(CountryStore.country); 1145 | * } 1146 | * }); 1147 | * 1148 | * The usage of `waitFor()` can be chained, for example: 1149 | * 1150 | * FlightPriceStore.dispatchToken = 1151 | * flightDispatcher.register(function(payload) { 1152 | * switch (payload.actionType) { 1153 | * case 'country-update': 1154 | * case 'city-update': 1155 | * flightDispatcher.waitFor([CityStore.dispatchToken]); 1156 | * FlightPriceStore.price = 1157 | * getFlightPriceStore(CountryStore.country, CityStore.city); 1158 | * break; 1159 | * } 1160 | * }); 1161 | * 1162 | * The `country-update` payload will be guaranteed to invoke the stores' 1163 | * registered callbacks in order: `CountryStore`, `CityStore`, then 1164 | * `FlightPriceStore`. 1165 | */ 1166 | 1167 | var Dispatcher = (function () { 1168 | function Dispatcher() { 1169 | _classCallCheck(this, Dispatcher); 1170 | 1171 | this._callbacks = {}; 1172 | this._isDispatching = false; 1173 | this._isHandled = {}; 1174 | this._isPending = {}; 1175 | this._lastID = 1; 1176 | } 1177 | 1178 | /** 1179 | * Registers a callback to be invoked with every dispatched payload. Returns 1180 | * a token that can be used with `waitFor()`. 1181 | */ 1182 | 1183 | Dispatcher.prototype.register = function register(callback) { 1184 | var id = _prefix + this._lastID++; 1185 | this._callbacks[id] = callback; 1186 | return id; 1187 | }; 1188 | 1189 | /** 1190 | * Removes a callback based on its token. 1191 | */ 1192 | 1193 | Dispatcher.prototype.unregister = function unregister(id) { 1194 | !this._callbacks[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.unregister(...): `%s` does not map to a registered callback.', id) : invariant(false) : undefined; 1195 | delete this._callbacks[id]; 1196 | }; 1197 | 1198 | /** 1199 | * Waits for the callbacks specified to be invoked before continuing execution 1200 | * of the current callback. This method should only be used by a callback in 1201 | * response to a dispatched payload. 1202 | */ 1203 | 1204 | Dispatcher.prototype.waitFor = function waitFor(ids) { 1205 | !this._isDispatching ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): Must be invoked while dispatching.') : invariant(false) : undefined; 1206 | for (var ii = 0; ii < ids.length; ii++) { 1207 | var id = ids[ii]; 1208 | if (this._isPending[id]) { 1209 | !this._isHandled[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): Circular dependency detected while ' + 'waiting for `%s`.', id) : invariant(false) : undefined; 1210 | continue; 1211 | } 1212 | !this._callbacks[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): `%s` does not map to a registered callback.', id) : invariant(false) : undefined; 1213 | this._invokeCallback(id); 1214 | } 1215 | }; 1216 | 1217 | /** 1218 | * Dispatches a payload to all registered callbacks. 1219 | */ 1220 | 1221 | Dispatcher.prototype.dispatch = function dispatch(payload) { 1222 | !!this._isDispatching ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.') : invariant(false) : undefined; 1223 | this._startDispatching(payload); 1224 | try { 1225 | for (var id in this._callbacks) { 1226 | if (this._isPending[id]) { 1227 | continue; 1228 | } 1229 | this._invokeCallback(id); 1230 | } 1231 | } finally { 1232 | this._stopDispatching(); 1233 | } 1234 | }; 1235 | 1236 | /** 1237 | * Is this Dispatcher currently dispatching. 1238 | */ 1239 | 1240 | Dispatcher.prototype.isDispatching = function isDispatching() { 1241 | return this._isDispatching; 1242 | }; 1243 | 1244 | /** 1245 | * Call the callback stored with the given id. Also do some internal 1246 | * bookkeeping. 1247 | * 1248 | * @internal 1249 | */ 1250 | 1251 | Dispatcher.prototype._invokeCallback = function _invokeCallback(id) { 1252 | this._isPending[id] = true; 1253 | this._callbacks[id](this._pendingPayload); 1254 | this._isHandled[id] = true; 1255 | }; 1256 | 1257 | /** 1258 | * Set up bookkeeping needed when dispatching. 1259 | * 1260 | * @internal 1261 | */ 1262 | 1263 | Dispatcher.prototype._startDispatching = function _startDispatching(payload) { 1264 | for (var id in this._callbacks) { 1265 | this._isPending[id] = false; 1266 | this._isHandled[id] = false; 1267 | } 1268 | this._pendingPayload = payload; 1269 | this._isDispatching = true; 1270 | }; 1271 | 1272 | /** 1273 | * Clear bookkeeping used for dispatching. 1274 | * 1275 | * @internal 1276 | */ 1277 | 1278 | Dispatcher.prototype._stopDispatching = function _stopDispatching() { 1279 | delete this._pendingPayload; 1280 | this._isDispatching = false; 1281 | }; 1282 | 1283 | return Dispatcher; 1284 | })(); 1285 | 1286 | module.exports = Dispatcher; 1287 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3))) 1288 | 1289 | /***/ }, 1290 | 1291 | /***/ 171: 1292 | /***/ function(module, exports, __webpack_require__) { 1293 | 1294 | /* WEBPACK VAR INJECTION */(function(process) {/** 1295 | * Copyright 2013-2015, Facebook, Inc. 1296 | * All rights reserved. 1297 | * 1298 | * This source code is licensed under the BSD-style license found in the 1299 | * LICENSE file in the root directory of this source tree. An additional grant 1300 | * of patent rights can be found in the PATENTS file in the same directory. 1301 | * 1302 | * @providesModule invariant 1303 | */ 1304 | 1305 | "use strict"; 1306 | 1307 | /** 1308 | * Use invariant() to assert state which your program assumes to be true. 1309 | * 1310 | * Provide sprintf-style format (only %s is supported) and arguments 1311 | * to provide information about what broke and what you were 1312 | * expecting. 1313 | * 1314 | * The invariant message will be stripped in production, but the invariant 1315 | * will remain to ensure logic does not differ in production. 1316 | */ 1317 | 1318 | var invariant = function invariant(condition, format, a, b, c, d, e, f) { 1319 | if (process.env.NODE_ENV !== 'production') { 1320 | if (format === undefined) { 1321 | throw new Error('invariant requires an error message argument'); 1322 | } 1323 | } 1324 | 1325 | if (!condition) { 1326 | var error; 1327 | if (format === undefined) { 1328 | error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); 1329 | } else { 1330 | var args = [a, b, c, d, e, f]; 1331 | var argIndex = 0; 1332 | error = new Error('Invariant Violation: ' + format.replace(/%s/g, function () { 1333 | return args[argIndex++]; 1334 | })); 1335 | } 1336 | 1337 | error.framesToPop = 1; // we don't care about invariant's own frame 1338 | throw error; 1339 | } 1340 | }; 1341 | 1342 | module.exports = invariant; 1343 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3))) 1344 | 1345 | /***/ }, 1346 | 1347 | /***/ 172: 1348 | /***/ function(module, exports, __webpack_require__) { 1349 | 1350 | 'use strict'; 1351 | 1352 | var keymirror = __webpack_require__(173); 1353 | 1354 | var TodoConstants = keymirror({ 1355 | TODO_CREATE: null, 1356 | TODO_REMOVE: null, 1357 | TODO_EDIT: null, 1358 | TODO_MARK_COMPLETE: null, 1359 | TODO_MARK_UNCOMPLETE: null, 1360 | TODO_MARK_ALL_COMPLETE: null, 1361 | TODO_MARK_ALL_UNCOMPLETE: null, 1362 | TODO_REMOVE_ALL_COMPLETED: null, 1363 | TODO_ON_SHOW: null 1364 | }); 1365 | 1366 | module.exports = TodoConstants; 1367 | 1368 | /***/ }, 1369 | 1370 | /***/ 173: 1371 | /***/ function(module, exports) { 1372 | 1373 | /** 1374 | * Copyright 2013-2014 Facebook, Inc. 1375 | * 1376 | * Licensed under the Apache License, Version 2.0 (the "License"); 1377 | * you may not use this file except in compliance with the License. 1378 | * You may obtain a copy of the License at 1379 | * 1380 | * http://www.apache.org/licenses/LICENSE-2.0 1381 | * 1382 | * Unless required by applicable law or agreed to in writing, software 1383 | * distributed under the License is distributed on an "AS IS" BASIS, 1384 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1385 | * See the License for the specific language governing permissions and 1386 | * limitations under the License. 1387 | * 1388 | */ 1389 | 1390 | "use strict"; 1391 | 1392 | /** 1393 | * Constructs an enumeration with keys equal to their value. 1394 | * 1395 | * For example: 1396 | * 1397 | * var COLORS = keyMirror({blue: null, red: null}); 1398 | * var myColor = COLORS.blue; 1399 | * var isColorValid = !!COLORS[myColor]; 1400 | * 1401 | * The last line could not be performed if the values of the generated enum were 1402 | * not equal to their keys. 1403 | * 1404 | * Input: {key1: val1, key2: val2} 1405 | * Output: {key1: key1, key2: key2} 1406 | * 1407 | * @param {object} obj 1408 | * @return {object} 1409 | */ 1410 | var keyMirror = function keyMirror(obj) { 1411 | var ret = {}; 1412 | var key; 1413 | if (!(obj instanceof Object && !Array.isArray(obj))) { 1414 | throw new Error('keyMirror(...): Argument must be an object.'); 1415 | } 1416 | for (key in obj) { 1417 | if (!obj.hasOwnProperty(key)) { 1418 | continue; 1419 | } 1420 | ret[key] = key; 1421 | } 1422 | return ret; 1423 | }; 1424 | 1425 | module.exports = keyMirror; 1426 | 1427 | /***/ }, 1428 | 1429 | /***/ 174: 1430 | /***/ function(module, exports, __webpack_require__) { 1431 | 1432 | 'use strict'; 1433 | 1434 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 1435 | 1436 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 1437 | 1438 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 1439 | 1440 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1441 | 1442 | var EventEmitter = __webpack_require__(166).EventEmitter; 1443 | 1444 | var BaseStore = (function (_EventEmitter) { 1445 | _inherits(BaseStore, _EventEmitter); 1446 | 1447 | function BaseStore() { 1448 | _classCallCheck(this, BaseStore); 1449 | 1450 | _get(Object.getPrototypeOf(BaseStore.prototype), 'constructor', this).call(this); 1451 | this.setState(this.getInitialState()); 1452 | } 1453 | 1454 | _createClass(BaseStore, [{ 1455 | key: 'getState', 1456 | value: function getState() { 1457 | return this.state; 1458 | } 1459 | }, { 1460 | key: 'setState', 1461 | value: function setState(state) { 1462 | this.state = state; 1463 | this.duringSetState(); 1464 | this.emit('change'); 1465 | } 1466 | }, { 1467 | key: 'getInitialState', 1468 | value: function getInitialState() { 1469 | return {}; 1470 | } 1471 | }]); 1472 | 1473 | return BaseStore; 1474 | })(EventEmitter); 1475 | 1476 | module.exports = BaseStore; 1477 | 1478 | /***/ }, 1479 | 1480 | /***/ 175: 1481 | /***/ function(module, exports, __webpack_require__) { 1482 | 1483 | /** 1484 | * TodoActions 1485 | */ 1486 | 1487 | "use strict"; 1488 | 1489 | var AppDispatcher = __webpack_require__(168); 1490 | 1491 | var TodoConstants = __webpack_require__(172); 1492 | 1493 | var actionAlias = { 1494 | addTodo: TodoConstants.TODO_CREATE, 1495 | remove: TodoConstants.TODO_REMOVE, 1496 | markComplete: TodoConstants.TODO_MARK_COMPLETE, 1497 | markUnComplete: TodoConstants.TODO_MARK_UNCOMPLETE, 1498 | edit: TodoConstants.TODO_EDIT, 1499 | markAllComplete: TodoConstants.TODO_MARK_ALL_COMPLETE, 1500 | removeAllCompleted: TodoConstants.TODO_REMOVE_ALL_COMPLETED, 1501 | markAllUnComplete: TodoConstants.TODO_MARK_ALL_UNCOMPLETE, 1502 | onShow: TodoConstants.TODO_ON_SHOW 1503 | }; 1504 | 1505 | var TodoActions = {}; 1506 | Object.keys(actionAlias).map(function (key) { 1507 | TodoActions[key] = function () { 1508 | AppDispatcher.handleViewAction({ 1509 | actionType: actionAlias[key], 1510 | args: arguments 1511 | }); 1512 | }; 1513 | }); 1514 | 1515 | //window.TodoActions = TodoActions; 1516 | module.exports = TodoActions; 1517 | 1518 | /***/ } 1519 | 1520 | /******/ }); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flux inside Web Workers 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /js/constants/TodoFilters.js: -------------------------------------------------------------------------------- 1 | export const SHOW_ALL = 'show_all' 2 | export const SHOW_COMPLETED = 'show_completed' 3 | export const SHOW_ACTIVE = 'show_active' 4 | -------------------------------------------------------------------------------- /js/dom/TodoApp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by narendrasisodiya on 29/07/15. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | import bridge from './common/initBridge.js'; 7 | import classnames from 'classnames'; 8 | import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters'; 9 | 10 | const FILTER_TITLES = { 11 | [SHOW_ALL]: 'All', 12 | [SHOW_ACTIVE]: 'Active', 13 | [SHOW_COMPLETED]: 'Completed' 14 | } 15 | 16 | const TODO_FILTERS = { 17 | [SHOW_ALL]: () => true, 18 | [SHOW_ACTIVE]: todo => !todo.done, 19 | [SHOW_COMPLETED]: todo => todo.done 20 | } 21 | 22 | class TodoApp extends Component { 23 | constructor(props, context) { 24 | super(props, context); 25 | this.subfun = () => { 26 | this.setState(this.props.store.getState()); 27 | }; 28 | this.props.store.on('change', this.subfun); 29 | this.state = this.props.store.getState(); 30 | } 31 | 32 | componentWillUnmount() { 33 | this.props.store.removeListener('change', this.subfun); 34 | } 35 | handleBlur() { 36 | 37 | } 38 | 39 | handleChange() { 40 | 41 | } 42 | 43 | markComplete(e) { 44 | var url; 45 | if (e.currentTarget.checked) { 46 | url = "/actions/TodoActions/markComplete"; 47 | } else { 48 | url = "/actions/TodoActions/markUnComplete"; 49 | } 50 | bridge.post(url, parseInt(e.currentTarget.dataset.todoId, 10)); 51 | } 52 | 53 | toggleAll(e) { 54 | var url; 55 | if (e.currentTarget.checked) { 56 | url = "/actions/TodoActions/markAllComplete"; 57 | } else { 58 | url = "/actions/TodoActions/markAllUnComplete"; 59 | } 60 | bridge.post(url); 61 | } 62 | 63 | handleSubmit(e) { 64 | const text = e.currentTarget.value.trim(); 65 | if (e.which === 13 && text !== "") { 66 | bridge.post("/actions/TodoActions/addTodo", text); 67 | e.currentTarget.value = ""; 68 | } 69 | } 70 | 71 | handleEdit(e) { 72 | const text = e.currentTarget.value.trim(); 73 | if (e.which === 13) { 74 | var id = parseInt(e.currentTarget.dataset.todoId, 10); 75 | if (text === "") { 76 | bridge.post("/actions/TodoActions/remove", id); 77 | } else { 78 | bridge.post("/actions/TodoActions/edit", {id: id, text: text}); 79 | } 80 | } 81 | } 82 | 83 | handleRemove(e) { 84 | var id = parseInt(e.currentTarget.dataset.todoId, 10); 85 | bridge.post("/actions/TodoActions/remove", id); 86 | } 87 | 88 | clearCompleted(e) { 89 | bridge.post("/actions/TodoActions/removeAllCompleted"); 90 | } 91 | 92 | handleDoubleClick(e) { 93 | //editing flag 94 | } 95 | 96 | handelOnShow(filter) { 97 | bridge.post("/actions/TodoActions/onShow", filter); 98 | } 99 | 100 | renderFilterLink(filter, selectedFilter) { 101 | const title = FILTER_TITLES[filter] 102 | const { onShow } = this.props 103 | 104 | return ( 105 | 108 | {title} 109 | 110 | ) 111 | } 112 | 113 | render() { 114 | if (this.state === undefined || this.state === null) { 115 | return
Loading ...
; 116 | } 117 | 118 | const { todos, selectedFilter } = this.state; 119 | 120 | const filteredTodos = todos.filter(TODO_FILTERS[selectedFilter]) 121 | const completedCount = todos.reduce((count, todo) => 122 | todo.done ? count + 1 : count, 123 | 0 124 | ) 125 | 126 | return
127 |
128 |
129 |

todos

130 | 134 |
135 |
136 | 137 |
    138 | { 139 | filteredTodos.map((v, i)=> { 140 | return
  • 141 |
    142 | 144 | 145 | 146 |
    147 | 150 |
  • 151 | }) 152 | } 153 |
154 |
155 | { 156 | todos.length > 0 157 | ? 174 | : "" 175 | } 176 |
177 |
; 178 | } 179 | } 180 | 181 | export default TodoApp; -------------------------------------------------------------------------------- /js/dom/common/BusinessLayerLoader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by narendrasisodiya on 01/08/15. 3 | */ 4 | 5 | 6 | ///////////// ============ This FILE IS NOT USEFUL ============ 7 | //============ IT will be DELETED SOON ================ 8 | 9 | var EventEmitter = require('events').EventEmitter; 10 | 11 | class EvtBus extends EventEmitter { 12 | constructor(config) { 13 | super(); 14 | } 15 | } 16 | 17 | var globalEvtBusForWorkerLessEvt = new EvtBus(); 18 | window.globalEvtBusForWorkerLessEvt = globalEvtBusForWorkerLessEvt; 19 | 20 | var callbacks = []; 21 | var c = 0; 22 | 23 | function handelMessageFromWorker(message) { 24 | var cmd = message.cmd; 25 | if (cmd === "callbackUpdate") { 26 | var f = callbacks[message.callbackId]; 27 | if (typeof f === "function") { 28 | f(message.data); 29 | callbacks[message.callbackId] = null; 30 | } 31 | } 32 | }; 33 | 34 | var BusinessLayerLoader = { 35 | 36 | loadInWorkerThread: true, 37 | 38 | load: function (config) { 39 | this.url = config.url; 40 | if (config.loadInWorkerThread !== undefined && config.loadInWorkerThread !== null) { 41 | this.loadInWorkerThread = config.loadInWorkerThread; 42 | } 43 | 44 | if (this.loadInWorkerThread) { 45 | var worker = new Worker(this.url); 46 | worker.post = function (url, ...args) { 47 | worker.postMessage({cmd: url, args: args}); 48 | }; 49 | 50 | worker.get = function (url, callback) { 51 | callbacks[c] = callback; 52 | worker.postMessage({cmd: url, type: "callback", callbackId: c}); 53 | c = c + 1 54 | }; 55 | 56 | worker.onMessage = (callback) => { 57 | worker.addEventListener('message', function (e) { 58 | callback(e.data); 59 | }, false); 60 | }; 61 | worker.onMessage((message)=> { 62 | handelMessageFromWorker(message); 63 | }); 64 | worker.onReady = (callback) => { 65 | callback(); 66 | }; 67 | return worker; 68 | 69 | } else { 70 | var script = document.createElement('script'); 71 | script.src = this.url; 72 | script.onload = () => { 73 | //config.callback(); 74 | this.onReadyCallback(); 75 | }; 76 | document.head.appendChild(script); 77 | 78 | var worker = {}; 79 | worker.post = function (url, ...args) { 80 | globalEvtBusForWorkerLessEvt.emit("TO_WORKER_THREAD", {cmd: url, args: args}) 81 | }; 82 | worker.get = function (url, callback) { 83 | callbacks[c] = callback; 84 | globalEvtBusForWorkerLessEvt.emit("TO_WORKER_THREAD", {cmd: url, type: "callback", callbackId: c}); 85 | c = c + 1 86 | }; 87 | worker.onMessage = (callback) => { 88 | globalEvtBusForWorkerLessEvt.on("TO_UI_THREAD", (message) => { 89 | callback(message); 90 | }); 91 | }; 92 | worker.onMessage((message)=> { 93 | handelMessageFromWorker(message); 94 | }); 95 | worker.onReady = (callback) => { 96 | this.onReadyCallback = callback; 97 | }; 98 | return worker; 99 | } 100 | } 101 | }; 102 | 103 | 104 | module.exports = BusinessLayerLoader; -------------------------------------------------------------------------------- /js/dom/common/FakeStore.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by narendrasisodiya on 29/07/15. 3 | */ 4 | 5 | 6 | var EventEmitter = require('events').EventEmitter; 7 | 8 | class FakeStore extends EventEmitter { 9 | constructor(config) { 10 | super(); 11 | var bridge = config.bridge; 12 | 13 | this.unsubid = bridge.on(config.cmdOnStateUpdate, (payload, sendBack) => { 14 | this.setState(payload); 15 | }); 16 | 17 | bridge.post(config.cmdGetInitialState, {}, (data)=> { 18 | console.log("Received State from bridge"); 19 | this.setState(data); 20 | }); 21 | } 22 | 23 | destroy() { 24 | //TODO 25 | bridge.off(this.unsubid); 26 | } 27 | 28 | getState() { 29 | return this.state; 30 | } 31 | 32 | setState(state) { 33 | this.state = state; 34 | this.emit('change'); 35 | } 36 | } 37 | module.exports = FakeStore; -------------------------------------------------------------------------------- /js/dom/common/ForkMe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by narendrasisodiya on 30/07/15. 3 | */ 4 | 5 | import React, {Component} from 'react'; 6 | 7 | class ForkMe extends Component { 8 | render() { 9 | return Fork me on GitHub; 10 | } 11 | } 12 | export default ForkMe -------------------------------------------------------------------------------- /js/dom/common/StoreView.jsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | import JSONViewer from 'react-json-viewer'; 4 | 5 | 6 | class StoreView extends Component { 7 | constructor(props, context) { 8 | super(props, context); 9 | this.subfun = () => { 10 | this.setState(this.props.store.getState()); 11 | }; 12 | this.props.store.on('change', this.subfun); 13 | this.state = this.props.store.getState(); 14 | } 15 | 16 | componentWillUnmount() { 17 | this.props.store.removeListener('change', this.subfun); 18 | } 19 | downloadState() { 20 | var element = document.createElement('a'); 21 | element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(this.state))); 22 | element.setAttribute('download', "state.json"); 23 | element.style.display = 'none'; 24 | document.body.appendChild(element); 25 | element.click(); 26 | document.body.removeChild(element); 27 | } 28 | 29 | render() { 30 | if (this.state === null || this.state === undefined) { 31 | return
Loading...
32 | } 33 | return
34 |
35 | 36 |
37 | 38 |
; 39 | } 40 | } 41 | 42 | export default StoreView; -------------------------------------------------------------------------------- /js/dom/common/initBridge.js: -------------------------------------------------------------------------------- 1 | import BLLayerLoader from 'bl-layer-loader'; 2 | 3 | var bridge = BLLayerLoader.load({ 4 | url: './dist/worker.bundle.js', 5 | method: "Worker" 6 | }); 7 | export default bridge; -------------------------------------------------------------------------------- /js/dom/index.jsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import StoreView from './common/StoreView.jsx'; 3 | import TodoApp from './TodoApp.js'; 4 | import ForkMe from './common/ForkMe.js'; 5 | import FakeStore from './common/FakeStore'; 6 | import bridge from './common/initBridge.js'; 7 | 8 | 9 | window.bridge = bridge; 10 | 11 | bridge.onReady(() => { 12 | var fakeTodoStore = new FakeStore({ 13 | bridge: bridge, 14 | cmdOnStateUpdate: "/stores/TodoStore/updateState", 15 | cmdGetInitialState: "/stores/TodoStore/getInitialState" 16 | }); 17 | 18 | class MainApp extends Component { 19 | constructor() { 20 | super(); 21 | this.state = { 22 | showStoreView: false 23 | } 24 | } 25 | 26 | componentWillUnmount() { 27 | fakeTodoStore.destroy(); 28 | } 29 | 30 | onChange() { 31 | this.setState({showStoreView: !this.state.showStoreView}); 32 | } 33 | 34 | render() { 35 | return
36 | 37 | 38 |

Flux inside Web Workers

39 | 40 |
41 |

Open Console and copy paste following commands

42 |
43 | 					bridge.post("/actions/TodoActions/addTodo", "TodoAdded From Console");
44 | 				
45 |
46 | 					bridge.post("/actions/TodoActions/markComplete", 0);
47 | 				
48 |
49 |
50 | Show Store 51 | JSON View (DOMLess) 52 |
53 | { 54 | this.state.showStoreView ? : 55 | 56 | } 57 | 58 |
; 59 | } 60 | } 61 | 62 | React.render(, document.getElementById("content")); 63 | }); 64 | -------------------------------------------------------------------------------- /js/dom/todomvc-common/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | button { 8 | margin: 0; 9 | padding: 0; 10 | border: 0; 11 | background: none; 12 | font-size: 100%; 13 | vertical-align: baseline; 14 | font-family: inherit; 15 | font-weight: inherit; 16 | color: inherit; 17 | -webkit-appearance: none; 18 | appearance: none; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-font-smoothing: antialiased; 21 | font-smoothing: antialiased; 22 | } 23 | 24 | body { 25 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 26 | line-height: 1.4em; 27 | background: #f5f5f5; 28 | color: #4d4d4d; 29 | min-width: 230px; 30 | max-width: 550px; 31 | margin: 0 auto; 32 | -webkit-font-smoothing: antialiased; 33 | -moz-font-smoothing: antialiased; 34 | font-smoothing: antialiased; 35 | font-weight: 300; 36 | } 37 | 38 | button, 39 | input[type="checkbox"] { 40 | outline: none; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | } 46 | 47 | .todoapp { 48 | background: #fff; 49 | margin: 130px 0 40px 0; 50 | position: relative; 51 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 52 | 0 25px 50px 0 rgba(0, 0, 0, 0.1); 53 | } 54 | 55 | .todoapp input::-webkit-input-placeholder { 56 | font-style: italic; 57 | font-weight: 300; 58 | color: #e6e6e6; 59 | } 60 | 61 | .todoapp input::-moz-placeholder { 62 | font-style: italic; 63 | font-weight: 300; 64 | color: #e6e6e6; 65 | } 66 | 67 | .todoapp input::input-placeholder { 68 | font-style: italic; 69 | font-weight: 300; 70 | color: #e6e6e6; 71 | } 72 | 73 | .todoapp h1 { 74 | position: absolute; 75 | top: -155px; 76 | width: 100%; 77 | font-size: 100px; 78 | font-weight: 100; 79 | text-align: center; 80 | color: rgba(175, 47, 47, 0.15); 81 | -webkit-text-rendering: optimizeLegibility; 82 | -moz-text-rendering: optimizeLegibility; 83 | text-rendering: optimizeLegibility; 84 | } 85 | 86 | .new-todo, 87 | .edit { 88 | position: relative; 89 | margin: 0; 90 | width: 100%; 91 | font-size: 24px; 92 | font-family: inherit; 93 | font-weight: inherit; 94 | line-height: 1.4em; 95 | border: 0; 96 | outline: none; 97 | color: inherit; 98 | padding: 6px; 99 | border: 1px solid #999; 100 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 101 | box-sizing: border-box; 102 | -webkit-font-smoothing: antialiased; 103 | -moz-font-smoothing: antialiased; 104 | font-smoothing: antialiased; 105 | } 106 | 107 | .new-todo { 108 | padding: 16px 16px 16px 60px; 109 | border: none; 110 | background: rgba(0, 0, 0, 0.003); 111 | box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03); 112 | } 113 | 114 | .main { 115 | position: relative; 116 | z-index: 2; 117 | border-top: 1px solid #e6e6e6; 118 | } 119 | 120 | label[for='toggle-all'] { 121 | display: none; 122 | } 123 | 124 | .toggle-all { 125 | position: absolute; 126 | top: -55px; 127 | left: -12px; 128 | width: 60px; 129 | height: 34px; 130 | text-align: center; 131 | border: none; /* Mobile Safari */ 132 | } 133 | 134 | .toggle-all:before { 135 | content: '❯'; 136 | font-size: 22px; 137 | color: #e6e6e6; 138 | padding: 10px 27px 10px 27px; 139 | } 140 | 141 | .toggle-all:checked:before { 142 | color: #737373; 143 | } 144 | 145 | .todo-list { 146 | margin: 0; 147 | padding: 0; 148 | list-style: none; 149 | } 150 | 151 | .todo-list li { 152 | position: relative; 153 | font-size: 24px; 154 | border-bottom: 1px solid #ededed; 155 | } 156 | 157 | .todo-list li:last-child { 158 | border-bottom: none; 159 | } 160 | 161 | .todo-list li.editing { 162 | border-bottom: none; 163 | padding: 0; 164 | } 165 | 166 | .todo-list li.editing .edit { 167 | display: block; 168 | width: 506px; 169 | padding: 13px 17px 12px 17px; 170 | margin: 0 0 0 43px; 171 | } 172 | 173 | .todo-list li.editing .view { 174 | display: none; 175 | } 176 | 177 | .todo-list li .toggle { 178 | text-align: center; 179 | width: 40px; 180 | /* auto, since non-WebKit browsers doesn't support input styling */ 181 | height: auto; 182 | position: absolute; 183 | top: 0; 184 | bottom: 0; 185 | margin: auto 0; 186 | border: none; /* Mobile Safari */ 187 | -webkit-appearance: none; 188 | appearance: none; 189 | } 190 | 191 | .todo-list li .toggle:after { 192 | content: url('data:image/svg+xml;utf8,'); 193 | } 194 | 195 | .todo-list li .toggle:checked:after { 196 | content: url('data:image/svg+xml;utf8,'); 197 | } 198 | 199 | .todo-list li label { 200 | white-space: pre; 201 | word-break: break-word; 202 | padding: 15px 60px 15px 15px; 203 | margin-left: 45px; 204 | display: block; 205 | line-height: 1.2; 206 | transition: color 0.4s; 207 | } 208 | 209 | .todo-list li.completed label { 210 | color: #d9d9d9; 211 | text-decoration: line-through; 212 | } 213 | 214 | .todo-list li .destroy { 215 | display: none; 216 | position: absolute; 217 | top: 0; 218 | right: 10px; 219 | bottom: 0; 220 | width: 40px; 221 | height: 40px; 222 | margin: auto 0; 223 | font-size: 30px; 224 | color: #cc9a9a; 225 | margin-bottom: 11px; 226 | transition: color 0.2s ease-out; 227 | } 228 | 229 | .todo-list li .destroy:hover { 230 | color: #af5b5e; 231 | } 232 | 233 | .todo-list li .destroy:after { 234 | content: '×'; 235 | } 236 | 237 | .todo-list li:hover .destroy { 238 | display: block; 239 | } 240 | 241 | .todo-list li .edit { 242 | display: none; 243 | } 244 | 245 | .todo-list li.editing:last-child { 246 | margin-bottom: -1px; 247 | } 248 | 249 | .footer { 250 | color: #777; 251 | padding: 10px 15px; 252 | height: 20px; 253 | text-align: center; 254 | border-top: 1px solid #e6e6e6; 255 | } 256 | 257 | .footer:before { 258 | content: ''; 259 | position: absolute; 260 | right: 0; 261 | bottom: 0; 262 | left: 0; 263 | height: 50px; 264 | overflow: hidden; 265 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 266 | 0 8px 0 -3px #f6f6f6, 267 | 0 9px 1px -3px rgba(0, 0, 0, 0.2), 268 | 0 16px 0 -6px #f6f6f6, 269 | 0 17px 2px -6px rgba(0, 0, 0, 0.2); 270 | } 271 | 272 | .todo-count { 273 | float: left; 274 | text-align: left; 275 | } 276 | 277 | .todo-count strong { 278 | font-weight: 300; 279 | } 280 | 281 | .filters { 282 | margin: 0; 283 | padding: 0; 284 | list-style: none; 285 | position: absolute; 286 | right: 0; 287 | left: 0; 288 | } 289 | 290 | .filters li { 291 | display: inline; 292 | } 293 | 294 | .filters li a { 295 | color: inherit; 296 | margin: 3px; 297 | padding: 3px 7px; 298 | text-decoration: none; 299 | border: 1px solid transparent; 300 | border-radius: 3px; 301 | } 302 | 303 | .filters li a.selected, 304 | .filters li a:hover { 305 | border-color: rgba(175, 47, 47, 0.1); 306 | } 307 | 308 | .filters li a.selected { 309 | border-color: rgba(175, 47, 47, 0.2); 310 | } 311 | 312 | .clear-completed, 313 | html .clear-completed:active { 314 | float: right; 315 | position: relative; 316 | line-height: 20px; 317 | text-decoration: none; 318 | cursor: pointer; 319 | position: relative; 320 | } 321 | 322 | .clear-completed:hover { 323 | text-decoration: underline; 324 | } 325 | 326 | .info { 327 | margin: 65px auto 0; 328 | color: #bfbfbf; 329 | font-size: 10px; 330 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 331 | text-align: center; 332 | } 333 | 334 | .info p { 335 | line-height: 1; 336 | } 337 | 338 | .info a { 339 | color: inherit; 340 | text-decoration: none; 341 | font-weight: 400; 342 | } 343 | 344 | .info a:hover { 345 | text-decoration: underline; 346 | } 347 | 348 | /* 349 | Hack to remove background from Mobile Safari. 350 | Can't use it globally since it destroys checkboxes in Firefox 351 | */ 352 | @media screen and (-webkit-min-device-pixel-ratio: 0) { 353 | .toggle-all, 354 | .todo-list li .toggle { 355 | background: none; 356 | } 357 | 358 | .todo-list li .toggle { 359 | height: 40px; 360 | } 361 | 362 | .toggle-all { 363 | -webkit-transform: rotate(90deg); 364 | transform: rotate(90deg); 365 | -webkit-appearance: none; 366 | appearance: none; 367 | } 368 | } 369 | 370 | @media (max-width: 430px) { 371 | .footer { 372 | height: 50px; 373 | } 374 | 375 | .filters { 376 | bottom: 10px; 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /js/domless/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | class AppDispatcher extends Dispatcher { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | handleViewAction(action) { 9 | //console.log(action); 10 | this.dispatch({ 11 | source: "VIEW_ACTION", 12 | action: action 13 | }) 14 | } 15 | } 16 | 17 | module.exports = new AppDispatcher(); -------------------------------------------------------------------------------- /js/domless/BaseStore.js: -------------------------------------------------------------------------------- 1 | var EventEmitter = require('events').EventEmitter; 2 | 3 | class BaseStore extends EventEmitter { 4 | constructor() { 5 | super(); 6 | this.setState(this.getInitialState()); 7 | } 8 | 9 | getState() { 10 | return this.state; 11 | } 12 | 13 | setState(state) { 14 | this.state = state; 15 | this.duringSetState(); 16 | this.emit('change'); 17 | } 18 | 19 | getInitialState() { 20 | return {} 21 | } 22 | } 23 | module.exports = BaseStore; -------------------------------------------------------------------------------- /js/domless/TodoActions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TodoActions 3 | */ 4 | 5 | var AppDispatcher = require('./AppDispatcher'); 6 | 7 | 8 | var TodoConstants = require("./TodoConstants"); 9 | 10 | var actionAlias = { 11 | addTodo: TodoConstants.TODO_CREATE, 12 | remove: TodoConstants.TODO_REMOVE, 13 | markComplete: TodoConstants.TODO_MARK_COMPLETE, 14 | markUnComplete: TodoConstants.TODO_MARK_UNCOMPLETE, 15 | edit: TodoConstants.TODO_EDIT, 16 | markAllComplete: TodoConstants.TODO_MARK_ALL_COMPLETE, 17 | removeAllCompleted: TodoConstants.TODO_REMOVE_ALL_COMPLETED, 18 | markAllUnComplete: TodoConstants.TODO_MARK_ALL_UNCOMPLETE, 19 | onShow: TodoConstants.TODO_ON_SHOW 20 | }; 21 | 22 | var TodoActions = {}; 23 | Object.keys(actionAlias).map(function (key) { 24 | TodoActions[key] = function () { 25 | AppDispatcher.handleViewAction({ 26 | actionType: actionAlias[key], 27 | args: arguments 28 | }); 29 | } 30 | }); 31 | 32 | //window.TodoActions = TodoActions; 33 | module.exports = TodoActions; -------------------------------------------------------------------------------- /js/domless/TodoConstants.js: -------------------------------------------------------------------------------- 1 | var keymirror = require('keymirror'); 2 | 3 | var TodoConstants = keymirror({ 4 | TODO_CREATE: null, 5 | TODO_REMOVE: null, 6 | TODO_EDIT: null, 7 | TODO_MARK_COMPLETE: null, 8 | TODO_MARK_UNCOMPLETE: null, 9 | TODO_MARK_ALL_COMPLETE: null, 10 | TODO_MARK_ALL_UNCOMPLETE: null, 11 | TODO_REMOVE_ALL_COMPLETED: null, 12 | TODO_ON_SHOW: null 13 | }); 14 | 15 | module.exports = TodoConstants; -------------------------------------------------------------------------------- /js/domless/todoStore.js: -------------------------------------------------------------------------------- 1 | var AppDispatcher = require('./AppDispatcher'); 2 | var TodoConstants = require("./TodoConstants"); 3 | var BaseStore = require('./BaseStore'); 4 | import { SHOW_ALL } from '../constants/TodoFilters'; 5 | 6 | class TodoStoreClass extends BaseStore { 7 | constructor() { 8 | super(); 9 | if (this.state.todos.length !== 0) { 10 | this.counter = this.state.todos[this.state.todos.length - 1].id + 1; 11 | } else { 12 | this.counter = this.state.todos.length; 13 | } 14 | } 15 | 16 | getInitialState() { 17 | var defaultState = { 18 | todos: [], 19 | selectedFilter: SHOW_ALL 20 | }; 21 | return defaultState; 22 | // try { 23 | // var state = JSON.parse(window.localStorage.getItem("todoStore")); 24 | // if (state !== null && state !== undefined) { 25 | // return state; 26 | // } else { 27 | // return defaultState; 28 | // } 29 | // } catch (ex) { 30 | // return defaultState; 31 | // } 32 | } 33 | addTodo(text) { 34 | this.setState({ 35 | todos: [...this.state.todos, { 36 | task: text, 37 | done: false, 38 | id: this.counter 39 | }] 40 | }); 41 | this.counter++; 42 | } 43 | 44 | duringSetState() { 45 | this.state.completed = this.getTotalCompleted(); 46 | this.state.uncompleted = this.state.todos.length - this.state.completed; 47 | //window.localStorage.setItem("todoStore", JSON.stringify(this.state)); 48 | } 49 | 50 | markComplete(id) { 51 | this.setState({ 52 | todos: this.state.todos.map(function (v) { 53 | if (v.id === id) { 54 | v.done = true; 55 | } 56 | return v; 57 | }) 58 | }); 59 | } 60 | 61 | remove(id) { 62 | this.setState({ 63 | todos: this.state.todos.filter(function (v) { 64 | return v.id !== id; 65 | }) 66 | }); 67 | } 68 | 69 | removeAllCompleted() { 70 | this.setState({ 71 | todos: this.state.todos.filter(function (v) { 72 | return v.done === false; 73 | }) 74 | }); 75 | } 76 | 77 | markAllComplete() { 78 | this.setState({ 79 | todos: this.state.todos.map(function (v) { 80 | v.done = true; 81 | return v; 82 | }) 83 | }); 84 | } 85 | 86 | edit(id, task) { 87 | this.setState({ 88 | todos: this.state.todos.map(function (v) { 89 | if (v.id === id) { 90 | v.task = task; 91 | } 92 | return v; 93 | }) 94 | }); 95 | } 96 | 97 | markAllUnComplete() { 98 | this.setState({ 99 | todos: this.state.todos.map(function (v) { 100 | v.done = false; 101 | return v; 102 | }) 103 | }); 104 | } 105 | 106 | markUnComplete(id) { 107 | this.setState({ 108 | todos: this.state.todos.map(function (v) { 109 | if (v.id === id) { 110 | v.done = false; 111 | } 112 | return v; 113 | }) 114 | }); 115 | } 116 | 117 | getTotalCompleted() { 118 | return this.state.todos.filter(function (v) { 119 | return v.done === true; 120 | }).length; 121 | } 122 | 123 | onShow(filter){ 124 | this.setState({ selectedFilter: filter, todos: this.state.todos }); 125 | } 126 | } 127 | 128 | var TodoStore = new TodoStoreClass(); 129 | var actionToMethodsMapping = { 130 | [TodoConstants.TODO_CREATE]: "addTodo", 131 | [TodoConstants.TODO_REMOVE]: "remove", 132 | [TodoConstants.TODO_MARK_COMPLETE]: "markComplete", 133 | [TodoConstants.TODO_EDIT]: "edit", 134 | [TodoConstants.TODO_MARK_UNCOMPLETE]: "markUnComplete", 135 | [TodoConstants.TODO_MARK_ALL_COMPLETE]: "markAllComplete", 136 | [TodoConstants.TODO_MARK_ALL_UNCOMPLETE]: "markAllUnComplete", 137 | [TodoConstants.TODO_REMOVE_ALL_COMPLETED]: "removeAllCompleted", 138 | [TodoConstants.TODO_ON_SHOW]: "onShow", 139 | }; 140 | 141 | 142 | AppDispatcher.register(function (e) { 143 | var action = e.action; 144 | if (actionToMethodsMapping[action.actionType] !== undefined) { 145 | TodoStore[actionToMethodsMapping[action.actionType]].apply(TodoStore, action.args); 146 | } 147 | }); 148 | module.exports = TodoStore; -------------------------------------------------------------------------------- /js/domless/worker.js: -------------------------------------------------------------------------------- 1 | var todostore = require('./todoStore'); 2 | var TodoActions = require('./TodoActions'); 3 | import BLLayerLoader from 'bl-layer-loader' 4 | 5 | var bridge = BLLayerLoader.getBLBridge(); 6 | 7 | todostore.on('change', function () { 8 | bridge.post("/stores/TodoStore/updateState", todostore.getState()); 9 | }); 10 | 11 | bridge.on("/stores/TodoStore/getInitialState", function (payload, sendBack) { 12 | sendBack(todostore.getState()); 13 | }); 14 | 15 | //TODO , support : Syntax 16 | //bridge.on("/actions/TodoActions/:method", function (payload, sendBack, path) { 17 | // var method = path.params.method 18 | // path.url = "/actions/TodoActions/addTodo" 19 | // path.matchedUrl = "/actions/TodoActions/:method" 20 | // TodoActions[method].call(TodoActions, payload); 21 | //}); 22 | 23 | bridge.on("/actions/TodoActions/addTodo", function (payload, sendBack, path) { 24 | TodoActions.addTodo(payload); 25 | }); 26 | 27 | bridge.on("/actions/TodoActions/markComplete", function (payload, sendBack, path) { 28 | TodoActions.markComplete(payload); 29 | }); 30 | 31 | bridge.on("/actions/TodoActions/remove", function (payload, sendBack, path) { 32 | TodoActions.remove(payload); 33 | }); 34 | 35 | bridge.on("/actions/TodoActions/removeAllCompleted", function (payload, sendBack, path) { 36 | TodoActions.removeAllCompleted(); 37 | }); 38 | 39 | bridge.on("/actions/TodoActions/edit", function (payload, sendBack, path) { 40 | TodoActions.edit(payload.id, payload.text); 41 | }); 42 | 43 | 44 | bridge.on("/actions/TodoActions/markUnComplete", function (payload, sendBack, path) { 45 | TodoActions.markUnComplete(payload); 46 | }); 47 | 48 | bridge.on("/actions/TodoActions/markAllUnComplete", function (payload, sendBack, path) { 49 | TodoActions.markAllUnComplete(); 50 | }); 51 | 52 | bridge.on("/actions/TodoActions/markAllComplete", function (payload, sendBack, path) { 53 | TodoActions.markAllComplete(); 54 | }); 55 | 56 | bridge.on("/actions/TodoActions/onShow", function (payload, sendBack, path) { 57 | TodoActions.onShow(payload); 58 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-experiments", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nsisodiya/react-experiments.git" 12 | }, 13 | "author": "Narendra Sisodiya ", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/nsisodiya/react-experiments/issues" 17 | }, 18 | "dependencies": { 19 | "babel-loader": "^5.3.2", 20 | "bl-layer-loader": "^1.0.0", 21 | "flux": "^2.0.3", 22 | "grunt": "^0.4.5", 23 | "grunt-contrib-watch": "^0.6.1", 24 | "grunt-exec": "^0.4.6", 25 | "grunt-http-server": "^1.4.0", 26 | "keymirror": "^0.1.1", 27 | "react": "^0.13.3", 28 | "react-json-viewer": "^1.0.4", 29 | "classnames": "^2.2.0" 30 | }, 31 | "homepage": "https://github.com/nsisodiya/react-experiments#readme" 32 | } 33 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | table { 2 | padding: 0; 3 | } 4 | 5 | table tr { 6 | border-top: 1px solid #cccccc; 7 | background-color: white; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | 12 | /*table tr:nth-child(2n) { 13 | background-color: #f8f8f8; }*/ 14 | table tr th { 15 | font-weight: bold; 16 | border: 1px solid #cccccc; 17 | text-align: left; 18 | margin: 0; 19 | padding: 6px 13px; 20 | } 21 | 22 | table tr td { 23 | border: 1px solid #cccccc; 24 | text-align: left; 25 | margin: 0; 26 | padding: 6px 13px; 27 | } 28 | 29 | table tr th :first-child, table tr td :first-child { 30 | margin-top: 0; 31 | } 32 | 33 | table tr th :last-child, table tr td :last-child { 34 | margin-bottom: 0; 35 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | main: "./js/dom/index.jsx", 4 | worker: "./js/domless/worker.js" 5 | }, 6 | output: { 7 | path: "dist", 8 | filename: "[name].bundle.js" 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /.jsx?$/, loader: "babel-loader" } 13 | ] 14 | } 15 | }; --------------------------------------------------------------------------------