Skip to content

Commit

Permalink
3.0.6
Browse files Browse the repository at this point in the history
  • Loading branch information
phillipskevin committed Jan 18, 2017
1 parent 87256c0 commit cc93d9d
Show file tree
Hide file tree
Showing 2 changed files with 1,438 additions and 0 deletions.
288 changes: 288 additions & 0 deletions dist/amd/can-observation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
/*can-observation@3.0.5#can-observation*/
define(function (require, exports, module) {
require('can-event');
var canEvent = require('can-event');
var canBatch = require('can-event/batch');
var assign = require('can-util/js/assign');
var namespace = require('can-namespace');
var remaining = {
updates: 0,
notifications: 0
};
function Observation(func, context, compute) {
this.newObserved = {};
this.oldObserved = null;
this.func = func;
this.context = context;
this.compute = compute.updater ? compute : { updater: compute };
this.onDependencyChange = this.onDependencyChange.bind(this);
this.childDepths = {};
this.ignore = 0;
this.needsUpdate = false;
}
var observationStack = [];
assign(Observation.prototype, {
get: function () {
if (this.bound) {
canEvent.flush();
if (remaining.updates) {
Observation.updateChildrenAndSelf(this);
}
return this.value;
} else {
return this.func.call(this.context);
}
},
getPrimaryDepth: function () {
return this.compute._primaryDepth || 0;
},
addEdge: function (objEv) {
objEv.obj.addEventListener(objEv.event, this.onDependencyChange);
if (objEv.obj.observation) {
this.depth = null;
}
},
removeEdge: function (objEv) {
objEv.obj.removeEventListener(objEv.event, this.onDependencyChange);
if (objEv.obj.observation) {
this.depth = null;
}
},
dependencyChange: function (ev) {
if (this.bound) {
if (ev.batchNum !== this.batchNum) {
Observation.registerUpdate(this, ev.batchNum);
this.batchNum = ev.batchNum;
}
}
},
onDependencyChange: function (ev, newVal, oldVal) {
this.dependencyChange(ev, newVal, oldVal);
},
update: function (batchNum) {
if (this.needsUpdate) {
remaining.updates--;
}
this.needsUpdate = false;
if (this.bound) {
var oldValue = this.value;
this.oldValue = null;
this.start();
if (oldValue !== this.value) {
this.compute.updater(this.value, oldValue, batchNum);
return true;
}
}
},
getValueAndBind: function () {
console.warn('can-observation: call start instead of getValueAndBind');
return this.start();
},
start: function () {
this.bound = true;
this.oldObserved = this.newObserved || {};
this.ignore = 0;
this.newObserved = {};
observationStack.push(this);
this.value = this.func.call(this.context);
observationStack.pop();
this.updateBindings();
},
updateBindings: function () {
var newObserved = this.newObserved, oldObserved = this.oldObserved, name, obEv;
for (name in newObserved) {
obEv = newObserved[name];
if (!oldObserved[name]) {
this.addEdge(obEv);
} else {
oldObserved[name] = null;
}
}
for (name in oldObserved) {
obEv = oldObserved[name];
if (obEv) {
this.removeEdge(obEv);
}
}
},
teardown: function () {
console.warn('can-observation: call stop instead of teardown');
return this.stop();
},
stop: function () {
this.bound = false;
for (var name in this.newObserved) {
var ob = this.newObserved[name];
this.removeEdge(ob);
}
this.newObserved = {};
}
});
var updateOrder = [], curPrimaryDepth = Infinity, maxPrimaryDepth = 0, currentBatchNum, isUpdating = false;
var updateUpdateOrder = function (observation) {
var primaryDepth = observation.getPrimaryDepth();
if (primaryDepth < curPrimaryDepth) {
curPrimaryDepth = primaryDepth;
}
if (primaryDepth > maxPrimaryDepth) {
maxPrimaryDepth = primaryDepth;
}
var primary = updateOrder[primaryDepth] || (updateOrder[primaryDepth] = []);
return primary;
};
Observation.registerUpdate = function (observation, batchNum) {
if (observation.needsUpdate) {
return;
}
remaining.updates++;
observation.needsUpdate = true;
var objs = updateUpdateOrder(observation);
objs.push(observation);
};
var afterCallbacks = [];
Observation.updateAndNotify = function (ev, batchNum) {
currentBatchNum = batchNum;
if (isUpdating) {
return;
}
isUpdating = true;
while (true) {
if (curPrimaryDepth <= maxPrimaryDepth) {
var primary = updateOrder[curPrimaryDepth];
var lastUpdate = primary && primary.pop();
if (lastUpdate) {
lastUpdate.update(currentBatchNum);
} else {
curPrimaryDepth++;
}
} else {
updateOrder = [];
curPrimaryDepth = Infinity;
maxPrimaryDepth = 0;
isUpdating = false;
var afterCB = afterCallbacks;
afterCallbacks = [];
afterCB.forEach(function (cb) {
cb();
});
return;
}
}
};
canEvent.addEventListener.call(canBatch, 'batchEnd', Observation.updateAndNotify);
Observation.afterUpdateAndNotify = function (callback) {
canBatch.after(function () {
if (isUpdating) {
afterCallbacks.push(callback);
} else {
callback();
}
});
};
Observation.updateChildrenAndSelf = function (observation) {
if (observation.needsUpdate) {
return Observation.unregisterAndUpdate(observation);
}
var childHasChanged;
for (var prop in observation.newObserved) {
if (observation.newObserved[prop].obj.observation) {
if (Observation.updateChildrenAndSelf(observation.newObserved[prop].obj.observation)) {
childHasChanged = true;
}
}
}
if (childHasChanged) {
return observation.update(currentBatchNum);
}
};
Observation.unregisterAndUpdate = function (observation) {
var primaryDepth = observation.getPrimaryDepth();
var primary = updateOrder[primaryDepth];
if (primary) {
var index = primary.indexOf(observation);
if (index !== -1) {
primary.splice(index, 1);
}
}
return observation.update(currentBatchNum);
};
Observation.add = function (obj, event) {
var top = observationStack[observationStack.length - 1];
if (top && !top.ignore) {
var evStr = event + '', name = obj._cid + '|' + evStr;
if (top.traps) {
top.traps.push({
obj: obj,
event: evStr,
name: name
});
} else {
top.newObserved[name] = {
obj: obj,
event: evStr
};
}
}
};
Observation.addAll = function (observes) {
var top = observationStack[observationStack.length - 1];
if (top) {
if (top.traps) {
top.traps.push.apply(top.traps, observes);
} else {
for (var i = 0, len = observes.length; i < len; i++) {
var trap = observes[i], name = trap.name;
if (!top.newObserved[name]) {
top.newObserved[name] = trap;
}
}
}
}
};
Observation.ignore = function (fn) {
return function () {
if (observationStack.length) {
var top = observationStack[observationStack.length - 1];
top.ignore++;
var res = fn.apply(this, arguments);
top.ignore--;
return res;
} else {
return fn.apply(this, arguments);
}
};
};
Observation.trap = function () {
if (observationStack.length) {
var top = observationStack[observationStack.length - 1];
var oldTraps = top.traps;
var traps = top.traps = [];
return function () {
top.traps = oldTraps;
return traps;
};
} else {
return function () {
return [];
};
}
};
Observation.trapsCount = function () {
if (observationStack.length) {
var top = observationStack[observationStack.length - 1];
return top.traps.length;
} else {
return 0;
}
};
Observation.isRecording = function () {
var len = observationStack.length;
var last = len && observationStack[len - 1];
return last && last.ignore === 0 && last;
};
if (namespace.Observation) {
throw new Error('You can\'t have two versions of can-observation, check your dependencies');
} else {
module.exports = namespace.Observation = Observation;
}
});
Loading

0 comments on commit cc93d9d

Please sign in to comment.