diff --git a/README.md b/README.md index 3f6874db82..ce41353f76 100755 --- a/README.md +++ b/README.md @@ -127,7 +127,8 @@ List of Definitions * [KeyboardJS](https://github.com/RobertWHurst/KeyboardJS) (by [Vincent Bortone](https://github.com/vbortone/)) * [Knockback](http://kmalakoff.github.com/knockback/) (by [Marcel Binot](https://github.com/docgit)) * [Knockout.js](http://knockoutjs.com/) (by [Boris Yankov](https://github.com/borisyankov)) -* [Knockout.ES5](http://github.com/SteveSanderson/knockout-es5/‎) (by [Sebastián Galiano](https://github.com/sgaliano)) +* [Knockout.DeferredUpdates](https://github.com/mbest/knockout-deferred-updates) (by [Sebastián Galiano](https://github.com/sgaliano)) +* [Knockout.ES5](https://github.com/SteveSanderson/knockout-es5) (by [Sebastián Galiano](https://github.com/sgaliano)) * [Knockout.Mapping](https://github.com/SteveSanderson/knockout.mapping) (by [Boris Yankov](https://github.com/borisyankov)) * [Knockout.Postbox](https://github.com/rniemeyer/knockout-postbox) (by [Judah Gabriel](https://github.com/JudahGabriel)) * [Knockout.Validation](https://github.com/ericmbarnard/Knockout-Validation) (by [Dan Ludwig](https://github.com/danludwig)) @@ -175,7 +176,7 @@ List of Definitions * [Spin](http://fgnass.github.com/spin.js/) (by [Boris Yankov](https://github.com/borisyankov)) * [Store.js](https://github.com/marcuswestin/store.js/) (by [Vincent Bortone](https://github.com/vbortone)) * [Sugar](http://sugarjs.com/) (by [Josh Baldwin](https://github.com/jbaldwin/)) -* [Swiper](http://www.idangero.us/sliders/swiper/‎) (by [Sebastián Galiano](https://github.com/sgaliano)) +* [Swiper](http://www.idangero.us/sliders/swiper) (by [Sebastián Galiano](https://github.com/sgaliano)) * [SwipeView](http://cubiq.org/swipeview) (by [Boris Yankov](https://github.com/borisyankov)) * [Tags Manager](http://welldonethings.com/tags/manager) (by [Vincent Bortone](https://github.com/vbortone)) * [Teechart](http://www.steema.com) (by [Steema](http://www.steema.com)) diff --git a/knockout.deferred.updates/knockout.deferred.updates-tests.ts b/knockout.deferred.updates/knockout.deferred.updates-tests.ts new file mode 100644 index 0000000000..060ff3984a --- /dev/null +++ b/knockout.deferred.updates/knockout.deferred.updates-tests.ts @@ -0,0 +1,252 @@ +/// + +// Turn *off* deferred updates for computed observables and subscriptions +ko.computed.deferUpdates = false; + +var myComputed = ko.computed(() => { /* ... */ }); +// Turn *on* deferred updates for this computed observable +myComputed.deferUpdates = true; + +var myObservable = ko.observable(); +var mySubscription = myObservable.subscribe((value) => { /* ... */ }); +// Turn *on* deferred updates for this subscription +mySubscription.deferUpdates = true; + +// Turn *off* deferred updates for this computed observable +myComputed.extend({ deferred: false }); + + +// +// Examples +// + +function nestedComputedNoPlugin() { + var vm: any = { + a: ko.observable(0), + b: ko.observable(0), + c: ko.observable(0), + d: ko.observable(0), + e: ko.observable(0), + f: ko.observable(0) + }; + + var startTime = new Date().getTime(); + var updateArray = []; + + function firstUpdate() { + var updateList = document.getElementById('updates'); + while (updateList.firstChild) updateList.removeChild(updateList.firstChild); + } + + function pushUpdate(name, value, color) { + var li = document.createElement('li'); + li.appendChild(document.createTextNode(name + ' ' + value + '; ' + (new Date().getTime() - startTime) + ' ms')); + li.style.color = color; + document.getElementById('updates').appendChild(li); + } + + function lastUpdate() { + } + + var updateCounter = 0, plusminus = 1; + + vm.doUpdate = function () { + var u = updateCounter += plusminus; + startTime = new Date().getTime(); + vm.a(u); + vm.b(u); + vm.c(u); + vm.d(u); + vm.e(u); + vm.f(u); + plusminus = !u ? 1 : (u == 9) ? -1 : plusminus; + }; + + vm.setThrottle = function (value) { + vm.A.throttleEvaluation = value; + vm._B.throttleEvaluation = value; + vm.C.throttleEvaluation = value; + vm.D.throttleEvaluation = value; + vm.E.throttleEvaluation = value; + vm.F.throttleEvaluation = value; + }; + + vm.runNormal = function () { + ko.computed.deferUpdates = false; + vm.setThrottle(undefined); + vm.doUpdate(); + }; + + vm.runThrottle = function () { + ko.computed.deferUpdates = false; + vm.setThrottle(1); + vm.doUpdate(); + }; + + vm.A = ko.computed(function () { + var result = '' + vm.a(); + firstUpdate(); + pushUpdate('A', result, 'green'); + return result; + }, null, { deferEvaluation: true }); + + vm._B = ko.computed(function () { + var result = '' + vm.A() + vm.b(); + pushUpdate('B', result, 'darkturquoise'); + return result; + }, null, { deferEvaluation: true }); + + vm.C = ko.computed(function () { + var result = '' + vm._B() + vm.c(); + pushUpdate('C', result, 'royalblue'); + return result; + }, null, { deferEvaluation: true }); + + vm.D = ko.computed(function () { + var result = '' + vm.C() + vm.d(); + pushUpdate('D', result, 'indigo'); + return result; + }, null, { deferEvaluation: true }); + + vm.E = ko.computed(function () { + var result = '' + vm.D() + vm.e(); + pushUpdate('E', result, 'firebrick'); + return result; + }, null, { deferEvaluation: true }); + + vm.F = ko.computed(function () { + var f = vm.f(), result = '' + vm.E() + f; + pushUpdate('F', result, 'orangered'); + if (result === '' + f + f + f + f + f + f) lastUpdate(); + return result; + }, null, { deferEvaluation: true }); + + vm.A(); + vm._B(); + vm.C(); + vm.D(); + vm.E(); + vm.F(); + + ko.applyBindings(vm); +}; + +function nestedComputedPlugin() { + var vm: any = { + a: ko.observable(0), + b: ko.observable(0), + c: ko.observable(0), + d: ko.observable(0), + e: ko.observable(0), + f: ko.observable(0) + }; + + var startTime = new Date().getTime(); + var updateArray = []; + + function firstUpdate() { + var updateList = document.getElementById('updates'); + while (updateList.firstChild) + updateList.removeChild(updateList.firstChild); + } + + function pushUpdate(name, value, color) { + var li = document.createElement('li'); + li.appendChild(document.createTextNode(name + ' ' + value + '; ' + (new Date().getTime() - startTime) + ' ms')); + li.style.color = color; + document.getElementById('updates').appendChild(li); + } + + function lastUpdate() { + } + + var updateCounter = 0, plusminus = 1; + + vm.doUpdate = function () { + var u = updateCounter += plusminus; + startTime = new Date().getTime(); + vm.a(u); + vm.b(u); + vm.c(u); + vm.d(u); + vm.e(u); + vm.f(u); + plusminus = !u ? 1 : (u == 9) ? -1 : plusminus; + }; + + vm.setThrottle = function (value) { + vm.A.throttleEvaluation = value; + vm._B.throttleEvaluation = value; + vm.C.throttleEvaluation = value; + vm.D.throttleEvaluation = value; + vm.E.throttleEvaluation = value; + vm.F.throttleEvaluation = value; + }; + + vm.runNormal = function () { + ko.computed.deferUpdates = false; + vm.setThrottle(undefined); + vm.doUpdate(); + }; + + vm.runThrottle = function () { + ko.computed.deferUpdates = false; + vm.setThrottle(1); + vm.doUpdate(); + }; + + vm.runDefer = function () { + ko.computed.deferUpdates = true; + vm.setThrottle(undefined); + vm.doUpdate(); + }; + + vm.runWrappedDefer = ko.tasks.makeProcessedCallback(vm.runDefer); + + vm.A = ko.computed(function () { + var result = '' + vm.a(); + firstUpdate(); + pushUpdate('A', result, 'green'); + return result; + }, null, { deferEvaluation: true }); + + vm._B = ko.computed(function () { + var result = '' + vm.A() + vm.b(); + pushUpdate('B', result, 'darkturquoise'); + return result; + }, null, { deferEvaluation: true }); + + vm.C = ko.computed(function () { + var result = '' + vm._B() + vm.c(); + pushUpdate('C', result, 'royalblue'); + return result; + }, null, { deferEvaluation: true }); + + vm.D = ko.computed(function () { + var result = '' + vm.C() + vm.d(); + pushUpdate('D', result, 'indigo'); + return result; + }, null, { deferEvaluation: true }); + + vm.E = ko.computed(function () { + var result = '' + vm.D() + vm.e(); + pushUpdate('E', result, 'firebrick'); + return result; + }, null, { deferEvaluation: true }); + + vm.F = ko.computed(function () { + var f = vm.f(), result = '' + vm.E() + f; + pushUpdate('F', result, 'orangered'); + if (result === '' + f + f + f + f + f + f) lastUpdate(); + return result; + }, null, { deferEvaluation: true }); + + vm.A(); + vm._B(); + vm.C(); + vm.D(); + vm.E(); + vm.F(); + + ko.applyBindings(vm); +} diff --git a/knockout.deferred.updates/knockout.deferred.updates.d.ts b/knockout.deferred.updates/knockout.deferred.updates.d.ts new file mode 100644 index 0000000000..7822c7d95b --- /dev/null +++ b/knockout.deferred.updates/knockout.deferred.updates.d.ts @@ -0,0 +1,46 @@ +// Type definitions for Knockout Deferred Updates +// Project: https://github.com/mbest/knockout-deferred-updates +// Definitions by: Sebastián Galiano +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// + +interface KnockoutDeferredTasks { + processImmediate(evaluator: Function, object?: any, args?: Array): any; + processDelayed(evaluator: Function, distinct?: boolean, options?: Array): boolean; + makeProcessedCallback(evaluator: Function): void; +} + +// Knockout global +interface KnockoutStatic { + tasks: KnockoutDeferredTasks; + processAllDeferredBindingUpdates(): void; + processAllDeferredUpdates(): void; + evaluateAsynchronously(evaluator: Function, timeout?: any): number; + ignoreDependencies(callback: Function, callbackTarget: any, callbackArgs?: Array); +} + +// Observables +interface KnockoutSubscribableFunctions { + deferUpdates: boolean; +} + +// Computed +interface KnockoutComputedStatic { + deferUpdates: boolean; +} + +interface KnockoutComputedFunctions { + deferUpdates: boolean; +} + +// Utils +interface KnockoutUtils { + objectForEach(obj: any, action: Function): void; + objectMap(source: any, mapping: Function): any; +} + +// Deferred extender +interface KnockoutExtenders { + deferred(target: any, value: boolean): any; +} \ No newline at end of file diff --git a/knockout.es5/knockout.es5.d.ts b/knockout.es5/knockout.es5.d.ts index ffd1cffa01..c546e1bebb 100644 --- a/knockout.es5/knockout.es5.d.ts +++ b/knockout.es5/knockout.es5.d.ts @@ -9,6 +9,6 @@ interface KnockoutStatic { track(obj: any, propertyNames?: Array): any; defineProperty(obj: any, propertyName: string, evaluator: Function): any; defineProperty(obj: any, propertyName: string, options: { get: () => any; set?: (value: any) => void; }): any; - getObservable(obj: any, propertyName: string): KnockoutObservable; + getObservable(obj: any, propertyName: string): KnockoutObservable; valueHasMutated(obj: any, propertyName: string): void; } \ No newline at end of file