Comparing version 0.5.2 to 0.6.0
@@ -8,3 +8,3 @@ import Graph from '../graph/Graph'; | ||
static disposeAll<T>(obj: T): void; | ||
static attachGraph(obj: any): Graph<any>; | ||
static attachGraph<T>(obj: T): Graph<T>; | ||
static createProperty<T, U extends keyof T>(obj: T, property: U, observable: IObservable<T[U]>): void; | ||
@@ -14,8 +14,9 @@ static attachObservable<T, U extends keyof T>(obj: T, property: U, observable: IObservable<T[U]>, readOnly?: boolean): void; | ||
static createComputed<T, U extends keyof T>(obj: T, property: U, definition: (n?: T[U]) => T[U], defer?: boolean, setter?: (n: T[U]) => any): void; | ||
static createObservableArray<T, U extends keyof T, V extends keyof T[U]>(obj: T, property: U, value?: T[U]): void; | ||
static createObservableHash<T, U extends keyof T, V extends keyof T[U]>(obj: T, property: U, value?: T[U]): void; | ||
static subscribe<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>, createDisposer?: boolean): () => void; | ||
static subscribeOnly<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>, createDisposer?: boolean): () => void; | ||
static unsubscribe<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>): void; | ||
static waitToEqual<T>(obj: any, property: string, testValue: T, timeout?: number): Promise<T>; | ||
static createObservableArray<T, U extends keyof T>(obj: T, property: U, value?: T[U]): void; | ||
static createObservableHash<T, U extends keyof T>(obj: T, property: U, value?: T[U]): void; | ||
static setAlwaysNotify<T, U extends keyof T>(obj: T, property: U, alwaysNotify: boolean): void; | ||
static subscribe<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>, createDisposer?: boolean): () => void; | ||
static subscribeOnly<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>, createDisposer?: boolean): () => void; | ||
static unsubscribe<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>): void; | ||
static waitToEqual<T, U extends keyof T>(obj: T, property: U, testValue: T[U], timeout?: number): Promise<T[U]>; | ||
static peek<T, U extends keyof T>(obj: T, property: U): T[U]; | ||
@@ -35,4 +36,3 @@ static peekDirty<T, U extends keyof T>(obj: T, property: U): T[U]; | ||
static Fragment: typeof Fragment; | ||
static proxyAvailable: boolean; | ||
static reflectAvailable: boolean; | ||
} |
@@ -5,3 +5,2 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Computed_1 = require("../graph/Computed"); | ||
const ObservableArrayLegacy_1 = require("../graph/ObservableArrayLegacy"); | ||
const ObservableArray_1 = require("../graph/ObservableArray"); | ||
@@ -70,3 +69,3 @@ const ObservableHash_1 = require("../graph/ObservableHash"); | ||
static createObservableArray(obj, property, value) { | ||
Cascade.attachObservable(obj, property, Cascade.proxyAvailable ? new ObservableArray_1.default(value) : new ObservableArrayLegacy_1.default(value)); | ||
Cascade.attachObservable(obj, property, new ObservableArray_1.default(value)); | ||
} | ||
@@ -76,7 +75,9 @@ static createObservableHash(obj, property, value) { | ||
} | ||
static setAlwaysNotify(obj, property, alwaysNotify) { | ||
let graph = this.attachGraph(obj); | ||
graph.setAlwaysNotify(property, alwaysNotify); | ||
} | ||
static subscribe(obj, property, subscriberFunction, createDisposer = false) { | ||
var graph = obj._graph; | ||
if (graph) { | ||
graph.subscribe(property, subscriberFunction); | ||
} | ||
let graph = this.attachGraph(obj); | ||
graph.subscribe(property, subscriberFunction); | ||
return createDisposer ? function () { | ||
@@ -87,6 +88,4 @@ graph.unsubscribe(property, subscriberFunction); | ||
static subscribeOnly(obj, property, subscriberFunction, createDisposer = false) { | ||
var graph = obj._graph; | ||
if (graph) { | ||
graph.subscribeOnly(property, subscriberFunction); | ||
} | ||
let graph = this.attachGraph(obj); | ||
graph.subscribeOnly(property, subscriberFunction); | ||
return createDisposer ? function () { | ||
@@ -97,3 +96,3 @@ graph.unsubscribe(property, subscriberFunction); | ||
static unsubscribe(obj, property, subscriberFunction) { | ||
var graph = obj._graph; | ||
var graph = obj['_graph']; | ||
if (graph) { | ||
@@ -104,32 +103,27 @@ graph.unsubscribe(property, subscriberFunction); | ||
static waitToEqual(obj, property, testValue, timeout) { | ||
var graph = obj._graph; | ||
if (graph) { | ||
return new Promise((resolve, reject) => { | ||
let resolved = false; | ||
let subscriberFunction = (value) => { | ||
if (value === testValue) { | ||
if (timerId) { | ||
window.clearTimeout(timerId); | ||
} | ||
if (!resolved) { | ||
resolved = true; | ||
window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
}); | ||
resolve(value); | ||
} | ||
let graph = this.attachGraph(obj); | ||
return new Promise((resolve, reject) => { | ||
let resolved = false; | ||
let subscriberFunction = (value) => { | ||
if (value === testValue) { | ||
if (timerId) { | ||
window.clearTimeout(timerId); | ||
} | ||
}; | ||
if (timeout) { | ||
var timerId = window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
reject(new Error('Timeout elapsed')); | ||
}, timeout); | ||
if (!resolved) { | ||
resolved = true; | ||
window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
}); | ||
resolve(value); | ||
} | ||
} | ||
graph.subscribeOnly(property, subscriberFunction); | ||
}); | ||
} | ||
else { | ||
return Promise.reject('Cannot subscribe to Object'); | ||
} | ||
}; | ||
if (timeout) { | ||
var timerId = window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
reject(new Error('Timeout elapsed')); | ||
}, timeout); | ||
} | ||
graph.subscribeOnly(property, subscriberFunction); | ||
}); | ||
} | ||
@@ -143,4 +137,4 @@ static peek(obj, property) { | ||
static track(obj, property) { | ||
let graph = obj['_graph']; | ||
let observable = (graph ? graph.observables[property] : undefined); | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property]; | ||
if (observable) { | ||
@@ -154,13 +148,8 @@ return observable.track(); | ||
static trackAll(obj) { | ||
let graph = obj['_graph']; | ||
if (graph) { | ||
return graph.trackAll(); | ||
} | ||
else { | ||
throw new Error('No observables attached to Object'); | ||
} | ||
let graph = this.attachGraph(obj); | ||
return graph.trackAll(); | ||
} | ||
static update(obj, property) { | ||
let graph = obj['_graph']; | ||
let observable = (graph ? graph.observables[property] : undefined); | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property]; | ||
if (observable && observable.update) { | ||
@@ -174,4 +163,4 @@ return observable.update(); | ||
static set(obj, property, value) { | ||
let graph = obj['_graph']; | ||
let observable = (graph ? graph.observables[property] : undefined); | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property]; | ||
if (observable) { | ||
@@ -185,4 +174,4 @@ return observable.setValue(value); | ||
static run(obj, property) { | ||
let graph = obj['_graph']; | ||
let observable = (graph ? graph.observables[property] : undefined); | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property]; | ||
if (observable) { | ||
@@ -201,12 +190,12 @@ if (observable.runOnly) { | ||
static getObservable(obj, property) { | ||
var graph = obj['_graph']; | ||
return (graph ? graph.observables[property] : undefined); | ||
let graph = this.attachGraph(obj); | ||
return graph.observables[property]; | ||
} | ||
static getSubscribers(obj, property) { | ||
var graph = obj['_graph']; | ||
return graph ? graph.getSubscribers(property) : undefined; | ||
let graph = this.attachGraph(obj); | ||
return graph.getSubscribers(property); | ||
} | ||
static getReferences(obj, property) { | ||
var graph = obj['_graph']; | ||
return graph ? graph.getReferences(property) : undefined; | ||
let graph = this.attachGraph(obj); | ||
return graph.getReferences(property); | ||
} | ||
@@ -249,5 +238,4 @@ static wrapContext(callback, thisArg) { | ||
Cascade.Fragment = Fragment_1.default; | ||
Cascade.proxyAvailable = typeof Proxy !== 'undefined'; | ||
Cascade.reflectAvailable = (typeof Reflect === 'object' && typeof Reflect.getMetadata === 'function'); | ||
exports.default = Cascade; | ||
//# sourceMappingURL=Cascade.js.map |
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Cascade_1 = require("./Cascade"); | ||
const Observable_1 = require("../graph/Observable"); | ||
const ObservableArrayLegacy_1 = require("../graph/ObservableArrayLegacy"); | ||
const ObservableArray_1 = require("../graph/ObservableArray"); | ||
@@ -21,3 +20,3 @@ const ObservableHash_1 = require("../graph/ObservableHash"); | ||
if (!obj._graph.observables[property]) { | ||
obj._graph.observables[property] = Cascade_1.default.proxyAvailable ? new ObservableArray_1.default(value) : new ObservableArrayLegacy_1.default(value); | ||
obj._graph.observables[property] = new ObservableArray_1.default(value); | ||
} | ||
@@ -32,3 +31,3 @@ else if (set) { | ||
if (!obj._graph.observables[property]) { | ||
obj._graph.observables[property] = Cascade_1.default.proxyAvailable ? new ObservableHash_1.default(value) : new Observable_1.default(value); | ||
obj._graph.observables[property] = new ObservableHash_1.default(value); | ||
} | ||
@@ -35,0 +34,0 @@ else if (set) { |
@@ -42,3 +42,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
let newValue = this.setter(value); | ||
if (this.value !== newValue) { | ||
if (this.value !== newValue || this.alwaysNotify) { | ||
var oldValue = this.value; | ||
@@ -84,3 +84,3 @@ this.value = newValue; | ||
this.dirty = false; | ||
if (this.value !== value) { | ||
if (this.value !== value || this.alwaysNotify) { | ||
await this.publish(this.value, value); | ||
@@ -87,0 +87,0 @@ } |
@@ -20,2 +20,3 @@ import { IObservable, ISubscriber, ISubscriberFunction } from './IObservable'; | ||
unsubscribe<U extends keyof T>(property: U, subscriber: ISubscriber | ISubscriberFunction<any>): void; | ||
setAlwaysNotify<U extends keyof T>(property: U, alwaysNotify: boolean): void; | ||
} |
@@ -76,4 +76,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
} | ||
setAlwaysNotify(property, alwaysNotify) { | ||
if (!this.observables[property]) { | ||
var value = this.parent[property]; | ||
} | ||
this.observables[property].alwaysNotify = alwaysNotify; | ||
} | ||
} | ||
exports.default = Graph; | ||
//# sourceMappingURL=Graph.js.map |
@@ -12,2 +12,3 @@ export interface ISubscriber { | ||
value: T; | ||
alwaysNotify: boolean; | ||
getValue(): T; | ||
@@ -14,0 +15,0 @@ peek(): T; |
@@ -10,2 +10,3 @@ import { IObservable, ISubscriber, ISubscriberFunction } from './IObservable'; | ||
subscribers: (ISubscriber | ISubscriberFunction<T>)[]; | ||
alwaysNotify: boolean; | ||
protected promise: Promise<void>; | ||
@@ -12,0 +13,0 @@ static id: number; |
@@ -29,3 +29,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
async setValue(value) { | ||
if (this.value !== value) { | ||
if (this.value !== value || this.alwaysNotify) { | ||
var oldValue = this.value; | ||
@@ -32,0 +32,0 @@ this.value = value; |
import Observable from './Observable'; | ||
import { IArray } from './IObservable'; | ||
export default class ObservableArray<T> extends Observable<IArray<T>> { | ||
private _innerValue; | ||
constructor(value?: Array<T>); | ||
wrapArray(value: Array<T>): ProxyArray<any>; | ||
wrapArray(value: Array<T>): ProxyArray<T>; | ||
setValue(value?: Array<T>): Promise<void>; | ||
@@ -10,3 +11,2 @@ } | ||
constructor(value?: Array<T>, containingObservable?: Observable<Array<T>>); | ||
set(index: number, value: T): void; | ||
} |
@@ -6,2 +6,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
super(); | ||
this._innerValue = value; | ||
this.value = this.wrapArray((value instanceof Array) ? value : []); | ||
@@ -15,3 +16,4 @@ } | ||
async setValue(value) { | ||
if (this.value !== value) { | ||
if (this._innerValue !== value || this.alwaysNotify) { | ||
this._innerValue = value; | ||
var oldValue = this.value; | ||
@@ -29,3 +31,2 @@ value = this.wrapArray((value instanceof Array) ? value : []); | ||
super(); | ||
value.set = ProxyArray.prototype.set; | ||
let inner = new Proxy(value, { | ||
@@ -35,3 +36,3 @@ set: (target, property, value, receiver) => { | ||
let oldValue = target[property]; | ||
if (oldValue !== value) { | ||
if (oldValue !== value || containingObservable.alwaysNotify) { | ||
result = (target[property] = value) === value; | ||
@@ -54,7 +55,4 @@ if (result && isFinite(Number(property)) || property === 'length') { | ||
} | ||
set(index, value) { | ||
this[index] = value; | ||
} | ||
} | ||
exports.ProxyArray = ProxyArray; | ||
//# sourceMappingURL=ObservableArray.js.map |
import Observable from './Observable'; | ||
import { IHash } from './IObservable'; | ||
export default class ObservableHash<T> extends Observable<IHash<T>> { | ||
private _innerValue; | ||
constructor(value?: IHash<T>); | ||
@@ -10,3 +11,3 @@ wrapHash(value: IHash<T>): ProxyHash<T>; | ||
[index: string]: T; | ||
constructor(value?: Array<T>, containingObservable?: Observable<IHash<T>>); | ||
constructor(value?: IHash<T>, containingObservable?: Observable<IHash<T>>); | ||
} |
@@ -6,2 +6,3 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
super(); | ||
this._innerValue = value; | ||
this.value = this.wrapHash((value instanceof Object) ? value : {}); | ||
@@ -15,3 +16,4 @@ } | ||
async setValue(value) { | ||
if (this.value !== value) { | ||
if (this._innerValue !== value || this.alwaysNotify) { | ||
this._innerValue = value; | ||
var oldValue = this.value; | ||
@@ -28,7 +30,7 @@ value = this.wrapHash((value instanceof Object) ? value : {}); | ||
constructor(value, containingObservable) { | ||
let inner = new Proxy((value instanceof Object) ? value : [], { | ||
let inner = new Proxy(value, { | ||
set: (target, property, value, receiver) => { | ||
let result = true; | ||
let oldValue = target[property]; | ||
if (oldValue !== value) { | ||
if (oldValue !== value || containingObservable.alwaysNotify) { | ||
result = (target[property] = value) === value; | ||
@@ -35,0 +37,0 @@ if (result) { |
@@ -6,3 +6,2 @@ import '../jsx/JSX'; | ||
export { default as Computed } from '../graph/Computed'; | ||
export { default as ObservableArrayLegacy } from '../graph/ObservableArrayLegacy'; | ||
export { default as ObservableArray } from '../graph/ObservableArray'; | ||
@@ -9,0 +8,0 @@ export { default as ObservableHash } from '../graph/ObservableHash'; |
@@ -7,4 +7,2 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Computed = Computed_1.default; | ||
var ObservableArrayLegacy_1 = require("../graph/ObservableArrayLegacy"); | ||
exports.ObservableArrayLegacy = ObservableArrayLegacy_1.default; | ||
var ObservableArray_1 = require("../graph/ObservableArray"); | ||
@@ -11,0 +9,0 @@ exports.ObservableArray = ObservableArray_1.default; |
{ | ||
"name": "cascade", | ||
"version": "0.5.2", | ||
"version": "0.6.0", | ||
"description": "A modern library for creating user interfaces.", | ||
@@ -35,3 +35,2 @@ "author": "Sean Johnson <sjohnson@sjohnsonaz.com>", | ||
"chai": "4.1.2", | ||
"es6-shim": "0.35.3", | ||
"jsdom": "11.11.0", | ||
@@ -38,0 +37,0 @@ "mocha": "5.2.0", |
/// <reference path="../../node_modules/@types/mocha/index.d.ts" /> | ||
import 'es6-shim'; | ||
import 'reflect-metadata'; | ||
let $IEVersion: number = (function () { | ||
let { userAgent } = window.navigator; | ||
let matches = userAgent.match(/MSIE ([0-9\.]*)/); | ||
if (matches) { | ||
return parseInt(matches[1]); | ||
} | ||
matches = userAgent.match(/Trident\/([0-9\.]*)/); | ||
if (matches) { | ||
return 11; | ||
} | ||
matches = userAgent.match(/Edge\/([0-9\.]*)/); | ||
if (matches) { | ||
return parseInt(matches[1]); | ||
} | ||
return 0; | ||
})(); | ||
window['$IEVersion'] = $IEVersion; | ||
import '../tests/Cascade.createObservable_Test'; | ||
@@ -61,5 +41,5 @@ import '../tests/Cascade.createObservableArray_Test'; | ||
import '../tests/Observable_Test'; | ||
import '../tests/Observable.alwaysNotify_Test'; | ||
import '../tests/ObservableArray_Decorator_Test'; | ||
import '../tests/ObservableArray_Test'; | ||
import '../tests/ObservableArrayLegacy_Test'; | ||
import '../tests/ObservableHash_Decorator_Test'; | ||
@@ -66,0 +46,0 @@ import '../tests/ObservableHash_Test'; |
@@ -1,4 +0,1 @@ | ||
// TODO: Remove Proxy check | ||
declare var Proxy: any; | ||
import Graph from '../graph/Graph'; | ||
@@ -8,3 +5,2 @@ import { IObservable, ISubscriber, ISubscriberFunction, IArray, IHash } from '../graph/IObservable'; | ||
import Computed from '../graph/Computed'; | ||
import ObservableArrayLegacy from '../graph/ObservableArrayLegacy'; | ||
import ObservableArray from '../graph/ObservableArray'; | ||
@@ -50,4 +46,4 @@ import ObservableHash from '../graph/ObservableHash'; | ||
*/ | ||
static attachGraph(obj: any) { | ||
if (!obj._graph) { | ||
static attachGraph<T>(obj: T) { | ||
if (!(obj as any)._graph) { | ||
Object.defineProperty(obj, '_graph', { | ||
@@ -60,3 +56,3 @@ configurable: true, | ||
} | ||
return obj._graph as Graph; | ||
return (obj as any)._graph as Graph<T>; | ||
} | ||
@@ -122,3 +118,2 @@ | ||
// TODO: Remove Proxy check | ||
/** | ||
@@ -130,4 +125,4 @@ * | ||
*/ | ||
static createObservableArray<T, U extends keyof T, V extends keyof T[U]>(obj: T, property: U, value?: T[U]) { | ||
Cascade.attachObservable<T, U>(obj, property, Cascade.proxyAvailable ? new ObservableArray<any>(value as any) : new ObservableArrayLegacy<any>(value as any) as any); | ||
static createObservableArray<T, U extends keyof T>(obj: T, property: U, value?: T[U]) { | ||
Cascade.attachObservable<T, U>(obj, property, new ObservableArray<any>(value as any) as any); | ||
} | ||
@@ -141,3 +136,3 @@ | ||
*/ | ||
static createObservableHash<T, U extends keyof T, V extends keyof T[U]>(obj: T, property: U, value?: T[U]) { | ||
static createObservableHash<T, U extends keyof T>(obj: T, property: U, value?: T[U]) { | ||
Cascade.attachObservable<T, U>(obj, property, new ObservableHash<T[U]>(value as any) as any); | ||
@@ -150,9 +145,18 @@ } | ||
* @param property | ||
* @param alwaysNotify | ||
*/ | ||
static setAlwaysNotify<T, U extends keyof T>(obj: T, property: U, alwaysNotify: boolean) { | ||
let graph = this.attachGraph(obj); | ||
graph.setAlwaysNotify(property, alwaysNotify); | ||
} | ||
/** | ||
* | ||
* @param obj | ||
* @param property | ||
* @param subscriberFunction | ||
*/ | ||
static subscribe<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>, createDisposer: boolean = false) { | ||
var graph: Graph = obj._graph; | ||
if (graph) { | ||
graph.subscribe(property, subscriberFunction); | ||
} | ||
static subscribe<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>, createDisposer: boolean = false) { | ||
let graph = this.attachGraph(obj); | ||
graph.subscribe(property, subscriberFunction); | ||
return createDisposer ? function () { | ||
@@ -169,7 +173,5 @@ graph.unsubscribe(property, subscriberFunction); | ||
*/ | ||
static subscribeOnly<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>, createDisposer: boolean = false) { | ||
var graph: Graph = obj._graph; | ||
if (graph) { | ||
graph.subscribeOnly(property, subscriberFunction); | ||
} | ||
static subscribeOnly<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>, createDisposer: boolean = false) { | ||
let graph = this.attachGraph(obj); | ||
graph.subscribeOnly(property, subscriberFunction); | ||
return createDisposer ? function () { | ||
@@ -180,4 +182,4 @@ graph.unsubscribe(property, subscriberFunction); | ||
static unsubscribe<T>(obj: any, property: string, subscriberFunction: ISubscriberFunction<T>) { | ||
var graph: Graph = obj._graph; | ||
static unsubscribe<T, U extends keyof T>(obj: T, property: U, subscriberFunction: ISubscriberFunction<T[U]>) { | ||
var graph: Graph<T> = obj['_graph']; | ||
if (graph) { | ||
@@ -188,32 +190,28 @@ graph.unsubscribe(property, subscriberFunction); | ||
static waitToEqual<T>(obj: any, property: string, testValue: T, timeout?: number) { | ||
var graph: Graph = obj._graph; | ||
if (graph) { | ||
return new Promise<T>((resolve, reject) => { | ||
let resolved = false; | ||
let subscriberFunction = (value: T) => { | ||
if (value === testValue) { | ||
if (timerId) { | ||
window.clearTimeout(timerId); | ||
} | ||
if (!resolved) { | ||
resolved = true; | ||
window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
}); | ||
resolve(value); | ||
} | ||
static waitToEqual<T, U extends keyof T>(obj: T, property: U, testValue: T[U], timeout?: number) { | ||
let graph = this.attachGraph(obj); | ||
return new Promise<T[U]>((resolve, reject) => { | ||
let resolved = false; | ||
let subscriberFunction = (value: T[U]) => { | ||
if (value === testValue) { | ||
if (timerId) { | ||
window.clearTimeout(timerId); | ||
} | ||
}; | ||
if (timeout) { | ||
var timerId = window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
reject(new Error('Timeout elapsed')); | ||
}, timeout); | ||
if (!resolved) { | ||
resolved = true; | ||
window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
}); | ||
resolve(value); | ||
} | ||
} | ||
graph.subscribeOnly(property, subscriberFunction); | ||
}); | ||
} else { | ||
return Promise.reject('Cannot subscribe to Object'); | ||
} | ||
}; | ||
if (timeout) { | ||
var timerId = window.setTimeout(() => { | ||
graph.unsubscribe(property, subscriberFunction); | ||
reject(new Error('Timeout elapsed')); | ||
}, timeout); | ||
} | ||
graph.subscribeOnly(property, subscriberFunction); | ||
}); | ||
} | ||
@@ -245,4 +243,4 @@ | ||
static track<T, U extends keyof T>(obj: T, property: U) { | ||
let graph: Graph<T> = obj['_graph']; | ||
let observable = (graph ? graph.observables[property as string] : undefined) as IObservable<T[U]>; | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property as string] as IObservable<T[U]>; | ||
if (observable) { | ||
@@ -260,8 +258,4 @@ return observable.track(); | ||
static trackAll<T>(obj: T) { | ||
let graph: Graph = obj['_graph']; | ||
if (graph) { | ||
return graph.trackAll(); | ||
} else { | ||
throw new Error('No observables attached to Object'); | ||
} | ||
let graph = this.attachGraph(obj); | ||
return graph.trackAll(); | ||
} | ||
@@ -275,4 +269,4 @@ | ||
static update<T, U extends keyof T>(obj: T, property: U) { | ||
let graph: Graph<T> = obj['_graph']; | ||
let observable = (graph ? graph.observables[property as string] : undefined) as Computed<T[U]>; | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property as string] as Computed<T[U]>; | ||
if (observable && observable.update) { | ||
@@ -286,4 +280,4 @@ return observable.update(); | ||
static set<T, U extends keyof T>(obj: T, property: U, value: T[U]) { | ||
let graph: Graph<T> = obj['_graph']; | ||
let observable = (graph ? graph.observables[property as string] : undefined) as IObservable<T[U]>; | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property as string] as IObservable<T[U]>; | ||
if (observable) { | ||
@@ -302,4 +296,4 @@ return observable.setValue(value); | ||
static run<T, U extends keyof T>(obj: T, property: U) { | ||
let graph: Graph<T> = obj['_graph']; | ||
let observable = (graph ? graph.observables[property as string] : undefined) as IObservable<T[U]>; | ||
let graph = this.attachGraph(obj); | ||
let observable = graph.observables[property as string] as IObservable<T[U]>; | ||
if (observable) { | ||
@@ -322,4 +316,4 @@ if ((observable as Computed<T[U]>).runOnly) { | ||
static getObservable<T, U extends keyof T>(obj: T, property: U) { | ||
var graph: Graph<T> = obj['_graph']; | ||
return (graph ? graph.observables[property as string] : undefined) as IObservable<T[U]>; | ||
let graph = this.attachGraph(obj); | ||
return graph.observables[property as string] as IObservable<T[U]>; | ||
} | ||
@@ -333,4 +327,4 @@ | ||
static getSubscribers<T, U extends keyof T>(obj: T, property: U) { | ||
var graph: Graph<T> = obj['_graph']; | ||
return graph ? graph.getSubscribers<U>(property) : undefined; | ||
let graph = this.attachGraph(obj); | ||
return graph.getSubscribers<U>(property); | ||
} | ||
@@ -344,4 +338,4 @@ | ||
static getReferences<T, U extends keyof T>(obj: T, property: U) { | ||
var graph: Graph<T> = obj['_graph']; | ||
return graph ? graph.getReferences(property) : undefined; | ||
let graph = this.attachGraph(obj); | ||
return graph.getReferences(property); | ||
} | ||
@@ -390,4 +384,3 @@ | ||
static proxyAvailable: boolean = typeof Proxy !== 'undefined'; | ||
static reflectAvailable: boolean = (typeof Reflect === 'object' && typeof Reflect.getMetadata === 'function'); | ||
} |
import Cascade from './Cascade'; | ||
import Observable from '../graph/Observable'; | ||
import ObservableArrayLegacy from '../graph/ObservableArrayLegacy'; | ||
import ObservableArray from '../graph/ObservableArray'; | ||
@@ -19,7 +18,6 @@ import ObservableHash from '../graph/ObservableHash'; | ||
// TODO: Remove Proxy check | ||
function createArrayIfNotExists<T>(obj: any, property: string, value?: Array<T>, set?: boolean): ObservableArray<T> { | ||
Cascade.attachGraph(obj); | ||
if (!obj._graph.observables[property]) { | ||
obj._graph.observables[property] = Cascade.proxyAvailable ? new ObservableArray<T>(value) : new ObservableArrayLegacy<T>(value); | ||
obj._graph.observables[property] = new ObservableArray<T>(value); | ||
} else if (set) { | ||
@@ -31,7 +29,6 @@ obj._graph.observables[property].setValue(value); | ||
// TODO: Remove Proxy check | ||
function createHashIfNotExists<T>(obj: any, property: string, value?: IHash<T>, set?: boolean): ObservableHash<T> { | ||
Cascade.attachGraph(obj); | ||
if (!obj._graph.observables[property]) { | ||
obj._graph.observables[property] = Cascade.proxyAvailable ? new ObservableHash<T>(value) : new Observable<IHash<T>>(value); | ||
obj._graph.observables[property] = new ObservableHash<T>(value); | ||
} else if (set) { | ||
@@ -38,0 +35,0 @@ obj._graph.observables[property].setValue(value); |
@@ -15,3 +15,2 @@ import { IObservable, ISubscriber } from './IObservable'; | ||
// TODO: Add alwaysNotify, alwaysUpdate, validation. | ||
constructor(definition: (n?: T) => T, defer: boolean = false, thisArg?: any, setter?: (n: T) => any) { | ||
@@ -38,2 +37,3 @@ super(undefined); | ||
} | ||
update() { | ||
@@ -43,2 +43,3 @@ this.dirty = true; | ||
} | ||
peek() { | ||
@@ -50,9 +51,11 @@ if (this.dirty) { | ||
} | ||
peekDirty() { | ||
return this.value; | ||
} | ||
setValue(value: T) { | ||
if (this.setter) { | ||
let newValue = this.setter(value); | ||
if (this.value !== newValue) { | ||
if (this.value !== newValue || this.alwaysNotify) { | ||
var oldValue = this.value; | ||
@@ -68,2 +71,3 @@ this.value = newValue; | ||
} | ||
notify() { | ||
@@ -80,2 +84,3 @@ if (!this.disposed) { | ||
} | ||
notifyDirty() { | ||
@@ -92,2 +97,3 @@ if (!this.dirty) { | ||
} | ||
async runUpdate() { | ||
@@ -98,3 +104,3 @@ if (!this.disposed && this.dirty) { | ||
this.dirty = false; | ||
if (this.value !== value) { | ||
if (this.value !== value || this.alwaysNotify) { | ||
await this.publish(this.value, value); | ||
@@ -105,2 +111,3 @@ } | ||
} | ||
runOnly() { | ||
@@ -111,2 +118,3 @@ this.value = this.runDefinition(this.definition); | ||
} | ||
runDefinition(definition: (n: T) => T) { | ||
@@ -113,0 +121,0 @@ //TODO: Reduce unsubscribe calls. |
@@ -133,2 +133,15 @@ import { IObservable, ISubscriber, ISubscriberFunction } from './IObservable'; | ||
} | ||
/** | ||
* | ||
* @param property | ||
* @param alwaysNotify | ||
*/ | ||
setAlwaysNotify<U extends keyof T>(property: U, alwaysNotify: boolean) { | ||
if (!this.observables[property as string]) { | ||
// Force value to update. | ||
var value = this.parent[property]; | ||
} | ||
this.observables[property as string].alwaysNotify = alwaysNotify; | ||
} | ||
} |
@@ -14,2 +14,3 @@ export interface ISubscriber { | ||
value: T; | ||
alwaysNotify: boolean; | ||
getValue(): T; | ||
@@ -16,0 +17,0 @@ peek(): T; |
@@ -17,2 +17,3 @@ import { IObservable, ISubscriber, ISubscriberFunction } from './IObservable'; | ||
subscribers: (ISubscriber | ISubscriberFunction<T>)[]; | ||
alwaysNotify: boolean; | ||
protected promise: Promise<void>; | ||
@@ -30,3 +31,2 @@ | ||
// TODO: Change this to push only unique | ||
getValue() { | ||
@@ -38,13 +38,17 @@ if (observableContext.context) { | ||
} | ||
peek() { | ||
return this.value; | ||
} | ||
peekDirty() { | ||
return this.value; | ||
} | ||
track() { | ||
return this.promise || Promise.resolve(); | ||
} | ||
async setValue(value: T) { | ||
if (this.value !== value) { | ||
if (this.value !== value || this.alwaysNotify) { | ||
var oldValue = this.value; | ||
@@ -56,2 +60,3 @@ this.value = value; | ||
} | ||
subscribeOnly(subscriber: ISubscriber | ISubscriberFunction<T>) { | ||
@@ -62,2 +67,3 @@ if (subscriber) { | ||
} | ||
subscribe(subscriber: ISubscriber | ISubscriberFunction<T>) { | ||
@@ -73,2 +79,3 @@ if (subscriber) { | ||
} | ||
unsubscribe(subscriber: ISubscriber | ISubscriberFunction<T>) { | ||
@@ -82,2 +89,3 @@ if (subscriber) { | ||
} | ||
async publish(value: T, oldValue?: T) { | ||
@@ -84,0 +92,0 @@ if (this.subscribers.length) { |
@@ -7,4 +7,7 @@ declare var Proxy: any; | ||
export default class ObservableArray<T> extends Observable<IArray<T>> { | ||
private _innerValue: Array<T>; | ||
constructor(value?: Array<T>) { | ||
super(); | ||
this._innerValue = value; | ||
this.value = this.wrapArray((value instanceof Array) ? value : []); | ||
@@ -23,3 +26,4 @@ } | ||
async setValue(value?: Array<T>) { | ||
if (this.value !== value) { | ||
if (this._innerValue !== value || this.alwaysNotify) { | ||
this._innerValue = value; | ||
var oldValue = this.value; | ||
@@ -37,3 +41,2 @@ value = this.wrapArray((value instanceof Array) ? value : []); | ||
super(); | ||
(value as IArray<T>).set = ProxyArray.prototype.set; | ||
let inner = new Proxy(value, { | ||
@@ -43,3 +46,3 @@ set: (target: Array<T>, property: string, value: T, receiver: ProxyArray<T>) => { | ||
let oldValue = target[property]; | ||
if (oldValue !== value) { | ||
if (oldValue !== value || containingObservable.alwaysNotify) { | ||
result = (target[property] = value) === value; | ||
@@ -62,7 +65,2 @@ if (result && isFinite(Number(property)) || property === 'length') { | ||
} | ||
// TODO: This is included to be compatible with ObservableArrayLegacy. | ||
set(index: number, value: T) { | ||
this[index] = value; | ||
} | ||
} |
@@ -7,4 +7,7 @@ declare var Proxy: any; | ||
export default class ObservableHash<T> extends Observable<IHash<T>> { | ||
private _innerValue: IHash<T>; | ||
constructor(value?: IHash<T>) { | ||
super(); | ||
this._innerValue = value; | ||
this.value = this.wrapHash((value instanceof Object) ? value : {}); | ||
@@ -16,4 +19,3 @@ } | ||
(value instanceof ProxyHash) ? | ||
// TODO: Fix this once es6 or above. | ||
(Object as any).assign({}, value) : | ||
Object.assign({}, value) : | ||
value, | ||
@@ -25,3 +27,4 @@ this | ||
async setValue(value?: IHash<T>) { | ||
if (this.value !== value) { | ||
if (this._innerValue !== value || this.alwaysNotify) { | ||
this._innerValue = value; | ||
var oldValue = this.value; | ||
@@ -39,8 +42,8 @@ value = this.wrapHash((value instanceof Object) ? value : {}); | ||
constructor(value?: Array<T>, containingObservable?: Observable<IHash<T>>) { | ||
let inner = new Proxy((value instanceof Object) ? value : [], { | ||
constructor(value?: IHash<T>, containingObservable?: Observable<IHash<T>>) { | ||
let inner = new Proxy(value, { | ||
set: (target: IHash<T>, property: string, value: T, receiver: ProxyHash<T>) => { | ||
let result = true; | ||
let oldValue = target[property]; | ||
if (oldValue !== value) { | ||
if (oldValue !== value || containingObservable.alwaysNotify) { | ||
result = (target[property] = value) === value; | ||
@@ -47,0 +50,0 @@ if (result) { |
@@ -8,3 +8,2 @@ import '../jsx/JSX'; | ||
export { default as Computed } from '../graph/Computed'; | ||
export { default as ObservableArrayLegacy } from '../graph/ObservableArrayLegacy'; | ||
export { default as ObservableArray } from '../graph/ObservableArray'; | ||
@@ -11,0 +10,0 @@ export { default as ObservableHash } from '../graph/ObservableHash'; |
@@ -6,9 +6,2 @@ import { expect } from 'chai'; | ||
describe('Cascade.createObservableHash', () => { | ||
before(function () { | ||
let $IEversion = window['$IEVersion']; | ||
let ie = 0 < $IEversion && $IEversion <= 11; | ||
if (ie) { | ||
this.skip(); | ||
} | ||
}); | ||
@@ -15,0 +8,0 @@ it('should initialize undefined to empty', () => { |
import { expect } from 'chai'; | ||
import Cascade, { Computed, observable, Observable } from '../scripts/modules/Cascade'; | ||
import Cascade, { Computed, observable, Observable, IObservable } from '../scripts/modules/Cascade'; | ||
@@ -20,2 +20,19 @@ describe('Computed', () => { | ||
}); | ||
it('should subscribe once per Observable', () => { | ||
var obs = new Observable(1); | ||
let readCount = 0; | ||
let referenceCount = 0; | ||
var value = new Computed(() => { | ||
obs.getValue(); | ||
let observableContext = window['$_cascade_observable_context']; | ||
let context: IObservable<any>[] = observableContext.context; | ||
let output = obs.getValue(); | ||
readCount = context.length; | ||
return output; | ||
}); | ||
referenceCount = value.references.length; | ||
expect(readCount).to.equal(2); | ||
expect(referenceCount).to.equal(1); | ||
}); | ||
}); | ||
@@ -22,0 +39,0 @@ |
@@ -7,7 +7,4 @@ import { expect } from 'chai'; | ||
// TODO: Remove Proxy check | ||
describe('ObservableArray', function () { | ||
it('should initialize to an emtpy Array', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray(); | ||
@@ -18,4 +15,2 @@ expect(value.getValue().length).to.equal(0); | ||
it('should initialize in the constructor to an Array', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray([1]); | ||
@@ -25,16 +20,13 @@ expect(value.getValue().length).to.equal(1); | ||
it('should notify subscribers on set method', function (done) { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
it('should notify subscribers on setter', function (done) { | ||
var value = new ObservableArray<number>(); | ||
value.subscribeOnly((currentValue) => { | ||
expect(currentValue.length).to.equal(1); | ||
expect(currentValue[0]).to.equal(0); | ||
done(); | ||
}); | ||
value.peek().set(0, 10); | ||
value.setValue([0]); | ||
}); | ||
it('should notify subscribers on setter', function (done) { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
it('should notify subscribers on index setter', function (done) { | ||
var value = new ObservableArray<number>(); | ||
@@ -48,5 +40,50 @@ value.subscribeOnly((currentValue) => { | ||
it('should not notify subscribers on identical setter', async () => { | ||
var value = new ObservableArray<number>(); | ||
let arrays = []; | ||
value.subscribeOnly((array) => { | ||
arrays.push(array); | ||
}); | ||
let array0 = [0]; | ||
let array1 = [1]; | ||
value.setValue(array0); | ||
await value.track(); | ||
value.setValue(array1); | ||
await value.track(); | ||
value.setValue(array1); | ||
await value.track(); | ||
expect(arrays.length).to.equal(2); | ||
expect(arrays[0][0]).to.equal(0); | ||
expect(arrays[1][0]).to.equal(1); | ||
}); | ||
it('should not notify subscribers on identical index setter', async () => { | ||
var value = new ObservableArray<number>(); | ||
let values = []; | ||
value.subscribeOnly((array) => { | ||
values.push(array[0]); | ||
}); | ||
value.peek()[0] = 0; | ||
await value.track(); | ||
value.peek()[0] = 1; | ||
await value.track(); | ||
value.peek()[0] = 1; | ||
await value.track(); | ||
expect(values.length).to.equal(2); | ||
expect(values[0]).to.equal(0); | ||
expect(values[1]).to.equal(1); | ||
}); | ||
it('should notify subscribers on setting length', function (done) { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray<number>([1]); | ||
@@ -60,6 +97,22 @@ value.subscribeOnly((currentValue) => { | ||
it('should not notify subscribers on identical index setter', async () => { | ||
var value = new ObservableArray<number>([1]); | ||
let values = []; | ||
value.subscribeOnly((array) => { | ||
values.push(array[0]); | ||
}); | ||
value.peek().length = 0; | ||
await value.track(); | ||
value.peek().length = 0; | ||
await value.track(); | ||
expect(values.length).to.equal(1); | ||
expect(values[0]).to.equal(undefined); | ||
}); | ||
// TODO: Figure out why done calls multiple times. | ||
it('should notify subscribers on push method', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray<number>(); | ||
@@ -73,4 +126,2 @@ value.subscribeOnly((currentValue) => { | ||
it('should notify subscribers on delete', function (done) { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray<number>([1]); | ||
@@ -85,4 +136,2 @@ value.subscribeOnly((currentValue) => { | ||
it('should not notify subscribers on delete length', async function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableArray<number>([1]); | ||
@@ -89,0 +138,0 @@ var count = 0; |
@@ -6,9 +6,2 @@ import { expect } from 'chai'; | ||
describe('ObservableHash @hash Decorator', () => { | ||
before(function () { | ||
let $IEversion = window['$IEVersion']; | ||
let ie = 0 < $IEversion && $IEversion <= 11; | ||
if (ie) { | ||
this.skip(); | ||
} | ||
}); | ||
@@ -15,0 +8,0 @@ it('should initialize to an emtpy Array', () => { |
@@ -5,7 +5,4 @@ import { expect } from 'chai'; | ||
// TODO: Remove Proxy check | ||
describe('ObservableHash', function () { | ||
it('should initialize to an emtpy Hash', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableHash(); | ||
@@ -15,5 +12,8 @@ expect(value.getValue()).instanceof(Object); | ||
it('should initialize in the constructor to an Array', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
it('should initialize non Object parameters in the constructor to an Object', function () { | ||
var value = new ObservableHash('test' as any); | ||
expect(value.getValue()).instanceof(Object); | ||
}); | ||
it('should initialize in the constructor to an Object', function () { | ||
var value = new ObservableHash({ | ||
@@ -25,8 +25,16 @@ property: 1 | ||
it('should notify subscribers on setter', function () { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
it('should notify subscribers on setter', function (done) { | ||
var value = new ObservableHash<number>(); | ||
value.subscribeOnly((currentValue) => { | ||
expect(currentValue['test']).to.equal(1); | ||
done(); | ||
}); | ||
value.setValue({ 'test': 1 }); | ||
}); | ||
it('should notify subscribers on property setter', function (done) { | ||
var value = new ObservableHash<number>(); | ||
value.subscribeOnly((currentValue) => { | ||
expect(currentValue['property']).to.equal(10); | ||
done(); | ||
}); | ||
@@ -36,5 +44,50 @@ value.peek()['property'] = 10; | ||
it('should not notify subscribers on identical setter', async () => { | ||
var value = new ObservableHash<number>(); | ||
let hashes = []; | ||
value.subscribeOnly((array) => { | ||
hashes.push(array); | ||
}); | ||
let hash0 = { 'test': 0 }; | ||
let hash1 = { 'test': 1 }; | ||
value.setValue(hash0); | ||
await value.track(); | ||
value.setValue(hash1); | ||
await value.track(); | ||
value.setValue(hash1); | ||
await value.track(); | ||
expect(hashes.length).to.equal(2); | ||
expect(hashes[0]['test']).to.equal(0); | ||
expect(hashes[1]['test']).to.equal(1); | ||
}); | ||
it('should not notify subscribers on identical index setter', async () => { | ||
var value = new ObservableHash<number>(); | ||
let values = []; | ||
value.subscribeOnly((hash) => { | ||
values.push(hash['test']); | ||
}); | ||
value.peek()['test'] = 0; | ||
await value.track(); | ||
value.peek()['test'] = 1; | ||
await value.track(); | ||
value.peek()['test'] = 1; | ||
await value.track(); | ||
expect(values.length).to.equal(2); | ||
expect(values[0]).to.equal(0); | ||
expect(values[1]).to.equal(1); | ||
}); | ||
it('should notify subscribers on delete', function (done) { | ||
if (!Cascade.proxyAvailable) this.skip(); | ||
var value = new ObservableHash<number>({ | ||
@@ -41,0 +94,0 @@ 'property': 10 |
@@ -49,2 +49,22 @@ import { expect } from 'chai'; | ||
}); | ||
it('should initialize an Observable', async () => { | ||
class State { | ||
@observable value: number; | ||
} | ||
let state = new State(); | ||
let values: number[] = []; | ||
Cascade.subscribe(state, 'value', (value) => { | ||
values.push(value); | ||
}); | ||
state.value = 1; | ||
await Cascade.track(state, 'value'); | ||
expect(values.length).to.equal(2); | ||
expect(values[0]).to.equal(undefined); | ||
expect(values[1]).to.equal(1); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12
397420
122
10536