From 9e08f599bc286e3d497fc1f9ea6279863f487771 Mon Sep 17 00:00:00 2001 From: Patrick Heng Date: Mon, 13 Feb 2017 00:50:08 +0100 Subject: [PATCH] feat: add state class --- package.json | 5 ++ src/index.js | 154 ++++++++++++++++++++++++++++++++++++++++---------- test/index.js | 14 +++-- 3 files changed, 139 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index e04e0fe..16f0de3 100644 --- a/package.json +++ b/package.json @@ -67,5 +67,10 @@ "require": [ "babel-core/register" ] + }, + "dependencies": { + "ava": "^0.18.1", + "lodash.isequal": "^4.5.0", + "quark-signal": "^1.1.0" } } diff --git a/src/index.js b/src/index.js index 6330626..36d2e4e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,35 +1,129 @@ -/** - * Simple class - * - * @class - * - * @license {@link https://opensource.org/licenses/MIT|MIT} - * - * @author Patrick Heng - * @author Fabien Motte - * - * @example - * const simple = new Simple() - * simple.test() - */ -class Simple { - /** - * Creates an instance of Simple - * - * @constructor - */ +import Signal from 'quark-signal' +import isEquals from 'lodash.isequal' + +class State { + constructor () { - this.message = 'Hello world' + this._containers = {} } - /** - * Simple method - * - * @returns {string} - */ - test () { - return this.message + get (query) { + const { container, splittedQuery } = this._parseStateQuery(query) + + let value = container + + if (splittedQuery.length > 1) { + for (let i = 1, l = splittedQuery.length; i < l; i++) { + value = value[splittedQuery[i]] + + if (value === undefined || value === null) { + break + } + } + } + + return value } -} -export default Simple + set (query, value, forced = false) { + const { container, containerId, splittedQuery } = this._parseStateQuery(query) + + let target = this._containers + for (let i = 0, l = splittedQuery.length; i < l; i++) { + const p = splittedQuery[i] + const oldVal = target[p] + + if (typeof target[p] !== 'object') { + target[p] = {} + } + + if (i === splittedQuery.length - 1) { + if (typeof oldVal === 'undefined' || typeof value !== 'object' || value === null || forced) { + target[p] = value + } else { + target[p] = { + ...target, + ...value + } + } + } + + target = target[p] + + // Dispatch signal on change + let signalId = containerId + for (let j = 0; j < i; j++) { + signalId += `_${splittedQuery[i]}` + + console.log(signalId) + if (typeof container.signals[signalId] !== 'undefined') { + if (!isEquals(oldVal, target)) { + container.signals[signalId].dispatch(oldVal, target) + } + } + } + } + } + + onChange (query, callback) { + const { container, containerId, splittedQuery } = this._parseStateQuery(query) + + let signalId = containerId + + for (let i = 1, l = splittedQuery.length; i < l; i++) { + signalId += `_${splittedQuery[i]}` + } + + if (typeof container.signals[query] === 'undefined') { + container.signals[signalId] = new Signal() + } + + if (typeof callback !== 'function') { + throw new TypeError('Signal.onChange() : Second argument must be a Function') + } + + container.signals[signalId].add(callback) + } + + removeChangeCallback (query, callback) { + const { container } = this._parseStateQuery(query) + + if (typeof callback !== 'function') { + throw new TypeError('Signal.removeChangeCallback() : Second argument must be a Function') + } + + if (typeof container.signals[query] !== 'undefined') { + container.signals[query].remove(callback) + } + } + + initContainer (containerId, value) { + this._containers[containerId] = value + this._containers[containerId].signals = {} + } + + destroyContainer (containerId) { + if (typeof this._containers[containerId] !== 'undefined') { + for (let signalProp in this._containers[containerId].signals) { + this._containers[containerId].signals[signalProp].removeAll() + this._containers[containerId].signals[signalProp] = null + } + + this._containers[containerId] = null + delete this._containers[containerId] + } + } + + _parseStateQuery (query) { + const splittedQuery = query.split('.') + let objPathSegments = null + + return { + container: this._containers[splittedQuery[0]], + containerId: splittedQuery[0], + prop: splittedQuery[1], + splittedQuery + } + } +} +export default new State() diff --git a/test/index.js b/test/index.js index fcd68a6..286c830 100644 --- a/test/index.js +++ b/test/index.js @@ -1,11 +1,17 @@ import test from 'ava' -import Simple from '../src/index' +import States from '../src/index' test.beforeEach(t => { - t.context.simple = new Simple() + // t.context.simple = new Simple() }) -test('simple test', t => { - t.is(t.context.simple.test(), 'Hello world') +test('Set container', t => { + const initObj = { + message: 'hello world' + } + + States.initContainer('TEST', initObj) + + t.is(States.containers['TEST'], initObj) })