/
ifIfnotWith.js
executable file
·46 lines (41 loc) · 2.24 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
46
// Makes a binding like with or if
function makeWithIfBinding(bindingKey, isWith, isNot) {
ko.bindingHandlers[bindingKey] = {
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var savedNodes;
var ifCondition = !isWith && ko.computed(function() {
return !isNot !== !ko.utils.unwrapObservable(valueAccessor());
}, null, { disposeWhenNodeIsRemoved: element });
ko.computed(function() {
var rawWithValue = isWith && ko.utils.unwrapObservable(valueAccessor()),
shouldDisplay = isWith ? !!rawWithValue : ifCondition(),
isFirstRender = !savedNodes;
// 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(
isWith ?
bindingContext['createChildContext'](typeof rawWithValue == "function" ? rawWithValue : valueAccessor) :
ifCondition.isActive() ?
bindingContext['extend'](function() { ifCondition(); return null; }) :
bindingContext,
element);
} else {
ko.virtualElements.emptyNode(element);
}
}, 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 */);