Tab layout, first commit with new third party packages
[openemr.git] / public / assets / knockout-3-4-0 / src / subscribables / subscribable.js
blob13ca674188cd0ad3e0f33f3269097f9a6d300ac0
2 ko.subscription = function (target, callback, disposeCallback) {
3     this._target = target;
4     this.callback = callback;
5     this.disposeCallback = disposeCallback;
6     this.isDisposed = false;
7     ko.exportProperty(this, 'dispose', this.dispose);
8 };
9 ko.subscription.prototype.dispose = function () {
10     this.isDisposed = true;
11     this.disposeCallback();
14 ko.subscribable = function () {
15     ko.utils.setPrototypeOfOrExtend(this, ko_subscribable_fn);
16     ko_subscribable_fn.init(this);
19 var defaultEvent = "change";
21 // Moved out of "limit" to avoid the extra closure
22 function limitNotifySubscribers(value, event) {
23     if (!event || event === defaultEvent) {
24         this._limitChange(value);
25     } else if (event === 'beforeChange') {
26         this._limitBeforeChange(value);
27     } else {
28         this._origNotifySubscribers(value, event);
29     }
32 var ko_subscribable_fn = {
33     init: function(instance) {
34         instance._subscriptions = {};
35         instance._versionNumber = 1;
36     },
38     subscribe: function (callback, callbackTarget, event) {
39         var self = this;
41         event = event || defaultEvent;
42         var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
44         var subscription = new ko.subscription(self, boundCallback, function () {
45             ko.utils.arrayRemoveItem(self._subscriptions[event], subscription);
46             if (self.afterSubscriptionRemove)
47                 self.afterSubscriptionRemove(event);
48         });
50         if (self.beforeSubscriptionAdd)
51             self.beforeSubscriptionAdd(event);
53         if (!self._subscriptions[event])
54             self._subscriptions[event] = [];
55         self._subscriptions[event].push(subscription);
57         return subscription;
58     },
60     "notifySubscribers": function (valueToNotify, event) {
61         event = event || defaultEvent;
62         if (event === defaultEvent) {
63             this.updateVersion();
64         }
65         if (this.hasSubscriptionsForEvent(event)) {
66             try {
67                 ko.dependencyDetection.begin(); // Begin suppressing dependency detection (by setting the top frame to undefined)
68                 for (var a = this._subscriptions[event].slice(0), i = 0, subscription; subscription = a[i]; ++i) {
69                     // In case a subscription was disposed during the arrayForEach cycle, check
70                     // for isDisposed on each subscription before invoking its callback
71                     if (!subscription.isDisposed)
72                         subscription.callback(valueToNotify);
73                 }
74             } finally {
75                 ko.dependencyDetection.end(); // End suppressing dependency detection
76             }
77         }
78     },
80     getVersion: function () {
81         return this._versionNumber;
82     },
84     hasChanged: function (versionToCheck) {
85         return this.getVersion() !== versionToCheck;
86     },
88     updateVersion: function () {
89         ++this._versionNumber;
90     },
92     limit: function(limitFunction) {
93         var self = this, selfIsObservable = ko.isObservable(self),
94             ignoreBeforeChange, previousValue, pendingValue, beforeChange = 'beforeChange';
96         if (!self._origNotifySubscribers) {
97             self._origNotifySubscribers = self["notifySubscribers"];
98             self["notifySubscribers"] = limitNotifySubscribers;
99         }
101         var finish = limitFunction(function() {
102             self._notificationIsPending = false;
104             // If an observable provided a reference to itself, access it to get the latest value.
105             // This allows computed observables to delay calculating their value until needed.
106             if (selfIsObservable && pendingValue === self) {
107                 pendingValue = self();
108             }
109             ignoreBeforeChange = false;
110             if (self.isDifferent(previousValue, pendingValue)) {
111                 self._origNotifySubscribers(previousValue = pendingValue);
112             }
113         });
115         self._limitChange = function(value) {
116             self._notificationIsPending = ignoreBeforeChange = true;
117             pendingValue = value;
118             finish();
119         };
120         self._limitBeforeChange = function(value) {
121             if (!ignoreBeforeChange) {
122                 previousValue = value;
123                 self._origNotifySubscribers(value, beforeChange);
124             }
125         };
126     },
128     hasSubscriptionsForEvent: function(event) {
129         return this._subscriptions[event] && this._subscriptions[event].length;
130     },
132     getSubscriptionsCount: function (event) {
133         if (event) {
134             return this._subscriptions[event] && this._subscriptions[event].length || 0;
135         } else {
136             var total = 0;
137             ko.utils.objectForEach(this._subscriptions, function(eventName, subscriptions) {
138                 if (eventName !== 'dirty')
139                     total += subscriptions.length;
140             });
141             return total;
142         }
143     },
145     isDifferent: function(oldValue, newValue) {
146         return !this['equalityComparer'] || !this['equalityComparer'](oldValue, newValue);
147     },
149     extend: applyExtenders
152 ko.exportProperty(ko_subscribable_fn, 'subscribe', ko_subscribable_fn.subscribe);
153 ko.exportProperty(ko_subscribable_fn, 'extend', ko_subscribable_fn.extend);
154 ko.exportProperty(ko_subscribable_fn, 'getSubscriptionsCount', ko_subscribable_fn.getSubscriptionsCount);
156 // For browsers that support proto assignment, we overwrite the prototype of each
157 // observable instance. Since observables are functions, we need Function.prototype
158 // to still be in the prototype chain.
159 if (ko.utils.canSetPrototype) {
160     ko.utils.setPrototypeOf(ko_subscribable_fn, Function.prototype);
163 ko.subscribable['fn'] = ko_subscribable_fn;
166 ko.isSubscribable = function (instance) {
167     return instance != null && typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
170 ko.exportSymbol('subscribable', ko.subscribable);
171 ko.exportSymbol('isSubscribable', ko.isSubscribable);