/
ifIfnotWith.js
executable file
·45 lines (41 loc) · 2.21 KB
/
ifIfnotWith.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Makes a binding like with or if
function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
ko.bindingHandlers[bindingKey] = {
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var didDisplayOnLastUpdate,
savedNodes;
ko.computed(function() {
var dataValue = ko.utils.unwrapObservable(valueAccessor()),
shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
isFirstRender = !savedNodes,
needsRefresh = isFirstRender || isWith || (shouldDisplay !== didDisplayOnLastUpdate);
if (needsRefresh) {
// Save a copy of the inner nodes on the initial update, but only if we have dependencies.
if (isFirstRender && ko.computedContext.getDependenciesCount()) {
savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
}
if (shouldDisplay) {
if (!isFirstRender) {
ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(savedNodes));
}
ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
} else {
ko.virtualElements.emptyNode(element);
}
didDisplayOnLastUpdate = shouldDisplay;
}
}, null, { disposeWhenNodeIsRemoved: element });
return { 'controlsDescendantBindings': true };
}
};
ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
ko.virtualElements.allowedBindings[bindingKey] = true;
}
// Construct the actual binding handlers
makeWithIfBinding('if');
makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
makeWithIfBinding('with', true /* isWith */, false /* isNot */,
function(bindingContext, dataValue) {
return bindingContext['createChildContext'](dataValue);
}
);