From 135ca5e53f69322235a9bf000d28a864ff01bfea Mon Sep 17 00:00:00 2001 From: herrmanno Date: Thu, 10 Sep 2015 09:41:11 +0200 Subject: [PATCH] Added observe-js definition --- observe-js/observe-js-test.ts | 111 +++++++++++++++ observe-js/observe-js.d.ts | 250 ++++++++++++++++++++++++++++++++++ 2 files changed, 361 insertions(+) create mode 100644 observe-js/observe-js-test.ts create mode 100644 observe-js/observe-js.d.ts diff --git a/observe-js/observe-js-test.ts b/observe-js/observe-js-test.ts new file mode 100644 index 000000000..37ad0216c --- /dev/null +++ b/observe-js/observe-js-test.ts @@ -0,0 +1,111 @@ +/// + +module observejs { + + function Test_PathObserver() { + var obj = { foo: { bar: 'baz' } }; + var defaultValue = 42; + var observer = new PathObserver(obj, 'foo.bar', defaultValue); + observer.open(function(newValue, oldValue) { + // respond to obj.foo.bar having changed value. + }); + } + + + function Test_ArrayObserver() { + var arr = [0, 1, 2, 4]; + var observer = new ArrayObserver(arr); + observer.open(function(splices) { + // respond to changes to the elements of arr. + splices.forEach(function(splice) { + splice.index; // the index position that the change occurred. + splice.removed; // an array of values representing the sequence of removed elements + splice.addedCount; // the number of elements which were inserted. + }); + }); + } + + function Test_ObejctObserver() { + var myObj = { id: 1, foo: 'bar' }; + var observer = new ObjectObserver(myObj); + observer.open(function(added, removed, changed, getOldValueFn) { + // respond to changes to the obj. + Object.keys(added).forEach(function(property) { + property; // a property which has been been added to obj + added[property]; // its value + }); + Object.keys(removed).forEach(function(property) { + property; // a property which has been been removed from obj + getOldValueFn(property); // its old value + }); + Object.keys(changed).forEach(function(property) { + property; // a property on obj which has changed value. + changed[property]; // its value + getOldValueFn(property); // its old value + }); + }); + } + + function Test_CompounObserver() { + var obj = { + a: 1, + b: 2, + }; + + var otherObj = { c: 3 }; + + var observer = new CompoundObserver(); + observer.addPath(obj, 'a'); + observer.addObserver(new PathObserver(obj, 'b')); + observer.addPath(otherObj, 'c'); + var logTemplate = 'The %sth value before & after:'; + observer.open(function(newValues, oldValues) { + // Use for-in to iterate which values have changed. + for (var i in oldValues) { + console.log(logTemplate, i, oldValues[i], newValues[i]); + } + }); + } + + function Test_ObserverTransform_1() { + var obj = { value: 10 }; + var observer = new PathObserver(obj, 'value'); + function getValue(value:any) { return value * 2 }; + function setValue(value:any) { return value / 2 }; + + var transform = new ObserverTransform(observer, getValue, setValue); + + // returns 20. + transform.open(function(newValue, oldValue) { + console.log('new: ' + newValue + ', old: ' + oldValue); + }); + + obj.value = 20; + transform.deliver(); // 'new: 40, old: 20' + transform.setValue(4); // obj.value === 2; + } + + function Test_ObserverTransform_2() { + var obj = { a: 1, b: 2, c: 3 }; + var observer = new CompoundObserver(); + observer.addPath(obj, 'a'); + observer.addPath(obj, 'b'); + observer.addPath(obj, 'c'); + var transform = new ObserverTransform(observer, function(values) { + var value = 0; + for (var i = 0; i < values.length; i++) + value += values[i] + return value; + }); + + // returns 6. + transform.open(function(newValue, oldValue) { + console.log('new: ' + newValue + ', old: ' + oldValue); + }); + + obj.a = 2; + obj.c = 10; + transform.deliver(); // 'new: 14, old: 6' + } + +} \ No newline at end of file diff --git a/observe-js/observe-js.d.ts b/observe-js/observe-js.d.ts new file mode 100644 index 000000000..abd2caa00 --- /dev/null +++ b/observe-js/observe-js.d.ts @@ -0,0 +1,250 @@ +// Type definitions for observe-js v0.5.5 +// Project: https://github.com/Polymer/observe-js +// Definitions by: Oliver Herrmann +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module observejs { + + /*---------------------- + Observable + ----------------------*/ + + interface Observable { + /** + * Begins observation. + * @param onChange the function that gets invoked if a change is detected + * @param the target of observation + */ + open(onChange:(newValue:any, oldValue:any)=>any, receiver?:any):void + + /** + * Report any changes now (does nothing if there are no changes to report). + */ + deliver(): void + + /** + * If there are changes to report, ignore them. Returns the current value of the observation. + */ + discardChanges():void + + /** + * Ends observation. Frees resources and drops references to observed objects. + */ + close():void + } + + + /*---------------------- + PathObserver + ----------------------*/ + + interface PathObserver_static { + /** + * Constructor + * @param receiver the target for observation + * @param path specifies the paht to observe. If path === '' the receiver itself gets observed. + * @param defaultValue the defaultValue + */ + new(receiver:any, path:string, defaultValue?:any): PathObserver_instance + } + + interface PathObserver_instance extends Observable { + /** + * sets the observed value without notifying about the change. + * @param value the value to set + */ + setValue(value:any): void + } + + /** + * Observes a "value-at-a-path" from a given object: + */ + var PathObserver: PathObserver_static + + + /*---------------------- + ArrayObserver + ----------------------*/ + + interface splice { + + /** + * the index position that the change occured + */ + index:number + + /** + * an array of values representing the sequence of removed elements + */ + removed: Array + + /** + * the number of element which were inserted + */ + addedCount:number + } + + interface ArrayObserver_static { + + /** + * Constructor + * @param receiver the target for observation + */ + new(receiver:Array): ArrayObserver_instance + + /** + * transforms a copy of an old state of an array into a copy of its current state. + * @param previous array of old state + * @param current array of current state + * @param splices splices to apply + */ + applySplices(previous:Array, current:Array, splices:Array):void + } + + interface ArrayObserver_instance extends Observable { + open(onChange:(splices:Array)=>any):void + } + + /** + * ArrayObserver observes the index-positions of an Array and reports changes as the minimal set of "splices" which would have had the same effect. + */ + var ArrayObserver: ArrayObserver_static + + + /*---------------------- + ObjectObserver + ----------------------*/ + + interface Properties { + [key:string]:any + } + + interface ObjectObserver_static { + + /** + * Constructor + * @param receiver the target for observation + */ + new(receiver:any): ObjectObserver_instance + } + + interface ObjectObserver_instance extends Observable { + open(onChange:(added:Properties, removed:Properties, changed:Properties, getOldValueFn:(property:string)=>any)=>any):void + } + + /** + * Observes the set of own-properties of an object and their values + */ + var ObjectObserver: ObjectObserver_static + + + /*---------------------- + CompounObserver + ----------------------*/ + + interface CompoundObserver_static { + + /** + * Constructor + */ + new(): CompoundObserver_instance + } + + interface CompoundObserver_instance extends Observable { + open(onChange:(newValues:Array, oldValue:Array)=>any):void + + /** + * Adds the receivers property at the specified path to the list of observables. + * @param receiver the target for observation + * @param path specifies the paht to observe. If path === '' the receiver itself gets observed. + */ + addPath(receiver:any, path:string):void + + /** + * Adds an Observer to the list of observables. + */ + addObserver(observer:Observable):void + + } + + /** + * CompoundObserver allows simultaneous observation of multiple paths and/or Observables. + */ + var CompoundObserver: CompoundObserver_static + + + + /*---------------------- + ObserverTransform + ----------------------*/ + + interface ObserverTransform_static { + + /** + * Constructor + * @param observer the observer to transform + * @param getValue function that proxys getting a value + * @param setValue function that proxys setting a value + */ + new(observer:Observable, getValue:(value:any)=>any, setValue:(value:any)=>any): ObserverTransform_instance + + /** + * Constructor + * @param observer the observer to transform + * @param valueFn function that gets invoked with all observed values. May return a single new value. + */ + new(observer:Observable, valueFn:(values:Array)=>any): ObserverTransform_instance + } + + interface ObserverTransform_instance extends Observable { + /** + * sets the observed value without notifying about the change. + * @param value the value to set + */ + setValue(value:any): void + } + + /** + * CompoundObserver allows simultaneous observation of multiple paths and/or Observables. + */ + var ObserverTransform: ObserverTransform_static + + + /*---------------------- + Path + ----------------------*/ + + interface Path { + + /** + * Returns the current value of the path from the provided object. If eval() is available, + * a compiled getter will be used for better performance. Like PathObserver above, undefined + * is returned unless you provide an overriding defaultValue. + */ + getValueFrom(object:any, defaultValue:any): any + + /** + * Attempts to set the value of the path from the provided object. Returns true IFF the path + * was reachable and set. + */ + getValueFrom(object:any, newValue:any): any + } +} + +declare module "observejs" { + var PathObserver: typeof observejs.PathObserver; + var ArrayObserver: typeof observejs.ArrayObserver; + var ObjectObserver: typeof observejs.ObjectObserver; + var CompoundObserver: typeof observejs.CompoundObserver; + var ObserverTransform: typeof observejs.ObserverTransform; + var Path: observejs.Path; + + export { + PathObserver, + ArrayObserver, + ObjectObserver, + CompoundObserver, + ObserverTransform, + Path + }; +} \ No newline at end of file