123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- define(function() {
- 'use strict';
- var OBSERVABLES_PROPERTY = '__knockoutObservables';
- var SUBSCRIBABLE_PROPERTY = '__knockoutSubscribable';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- function track(obj, propertyNames) {
- if (!obj ) {
- throw new Error('When calling ko.track, you must pass an object as the first parameter.');
- }
- var ko = this,
- allObservablesForObject = getAllObservablesForObject(obj, true);
- propertyNames = propertyNames || Object.getOwnPropertyNames(obj);
- propertyNames.forEach(function(propertyName) {
-
- if (propertyName === OBSERVABLES_PROPERTY || propertyName === SUBSCRIBABLE_PROPERTY) {
- return;
- }
-
- if (propertyName in allObservablesForObject) {
- return;
- }
- var origValue = obj[propertyName],
- isArray = origValue instanceof Array,
- observable = ko.isObservable(origValue) ? origValue
- : isArray ? ko.observableArray(origValue)
- : ko.observable(origValue);
- Object.defineProperty(obj, propertyName, {
- configurable: true,
- enumerable: true,
- get: observable,
- set: ko.isWriteableObservable(observable) ? observable : undefined
- });
- allObservablesForObject[propertyName] = observable;
- if (isArray) {
- notifyWhenPresentOrFutureArrayValuesMutate(ko, observable);
- }
- });
- return obj;
- }
-
-
- function getAllObservablesForObject(obj, createIfNotDefined) {
- var result = obj[OBSERVABLES_PROPERTY];
- if (!result && createIfNotDefined) {
- result = {};
- Object.defineProperty(obj, OBSERVABLES_PROPERTY, {
- value : result
- });
- }
- return result;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- function defineComputedProperty(obj, propertyName, evaluatorOrOptions) {
- var ko = this,
- computedOptions = { owner: obj, deferEvaluation: true };
- if (typeof evaluatorOrOptions === 'function') {
- computedOptions.read = evaluatorOrOptions;
- } else {
- if ('value' in evaluatorOrOptions) {
- throw new Error('For ko.defineProperty, you must not specify a "value" for the property. You must provide a "get" function.');
- }
- if (typeof evaluatorOrOptions.get !== 'function') {
- throw new Error('For ko.defineProperty, the third parameter must be either an evaluator function, or an options object containing a function called "get".');
- }
- computedOptions.read = evaluatorOrOptions.get;
- computedOptions.write = evaluatorOrOptions.set;
- }
- obj[propertyName] = ko.computed(computedOptions);
- track.call(ko, obj, [propertyName]);
- return obj;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- function notifyWhenPresentOrFutureArrayValuesMutate(ko, observable) {
- var watchingArraySubscription = null;
- ko.computed(function () {
-
- if (watchingArraySubscription) {
- watchingArraySubscription.dispose();
- watchingArraySubscription = null;
- }
-
- var newArrayInstance = observable();
- if (newArrayInstance instanceof Array) {
- watchingArraySubscription = startWatchingArrayInstance(ko, observable, newArrayInstance);
- }
- });
- }
-
-
-
- function startWatchingArrayInstance(ko, observable, arrayInstance) {
- var subscribable = getSubscribableForArray(ko, arrayInstance);
- return subscribable.subscribe(observable);
- }
-
- function getSubscribableForArray(ko, arrayInstance) {
- var subscribable = arrayInstance[SUBSCRIBABLE_PROPERTY];
- if (!subscribable) {
- subscribable = new ko.subscribable();
- Object.defineProperty(arrayInstance, SUBSCRIBABLE_PROPERTY, {
- value : subscribable
- });
- var notificationPauseSignal = {};
- wrapStandardArrayMutators(arrayInstance, subscribable, notificationPauseSignal);
- addKnockoutArrayMutators(ko, arrayInstance, subscribable, notificationPauseSignal);
- }
- return subscribable;
- }
-
- function wrapStandardArrayMutators(arrayInstance, subscribable, notificationPauseSignal) {
- ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'].forEach(function(fnName) {
- var origMutator = arrayInstance[fnName];
- arrayInstance[fnName] = function() {
- var result = origMutator.apply(this, arguments);
- if (notificationPauseSignal.pause !== true) {
- subscribable.notifySubscribers(this);
- }
- return result;
- };
- });
- }
-
- function addKnockoutArrayMutators(ko, arrayInstance, subscribable, notificationPauseSignal) {
- ['remove', 'removeAll', 'destroy', 'destroyAll', 'replace'].forEach(function(fnName) {
-
- Object.defineProperty(arrayInstance, fnName, {
- enumerable: false,
- value: function() {
- var result;
-
-
-
-
- notificationPauseSignal.pause = true;
- try {
-
- result = ko.observableArray.fn[fnName].apply(ko.observableArray(arrayInstance), arguments);
- }
- finally {
- notificationPauseSignal.pause = false;
- }
- subscribable.notifySubscribers(arrayInstance);
- return result;
- }
- });
- });
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- function getObservable(obj, propertyName) {
- if (!obj ) {
- return null;
- }
- var allObservablesForObject = getAllObservablesForObject(obj, false);
- return (allObservablesForObject && allObservablesForObject[propertyName]) || null;
- }
-
-
- function valueHasMutated(obj, propertyName) {
- var observable = getObservable(obj, propertyName);
- if (observable) {
- observable.valueHasMutated();
- }
- }
-
- function attachToKo(ko) {
- ko.track = track;
- ko.getObservable = getObservable;
- ko.valueHasMutated = valueHasMutated;
- ko.defineProperty = defineComputedProperty;
- }
- return {
- attachToKo : attachToKo
- };
- });
|