-
Notifications
You must be signed in to change notification settings - Fork 0
/
ko.splitBindingProvider.js
87 lines (73 loc) · 3.34 KB
/
ko.splitBindingProvider.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(function ($) {
// Prevent multiple loading
if (ko.splitBindingProvider != undefined) return;
// Sanity check (should be obvious)
if (!ko) throw new Error('Knockout JS must be loaded');
// Custom binding provider ctor declaration
//
// A custom binding provider must provide two functions:
// --> 'nodeHasBindings(node)'
// --> 'getBindings(node, bindingContext)'
ko.splitBindingProvider = function () {
var sbp = this;
// Split attributes begin with this (e.g. 'data-bind-text')
sbp.splitBindingAttributePrefix = "data-bind-";
// Leverages the default instance of the ko binding provider
sbp.defaultBindingProvider = ko.bindingProvider.instance;
// Internal : determines if the attribute is a split binding.
// .lastIndexOf() is supposed to be moderately fast
sbp.attributeIsSplitBinding = function (attributeName) {
return attributeName.lastIndexOf(sbp.splitBindingAttributePrefix, 0) === 0;
};
// Iterate through attributes, searching for "data-bind-*" names
sbp.checkNodeForSplitDataBindAttributes = function (attributes) {
for (var i = 0; i < attributes.length; i++) {
if (sbp.attributeIsSplitBinding(attributes[i].nodeName)) return true;
}
return false; // no data-bind-* to be found
};
// Called by ko to find nodes that must be data bound
sbp.nodeHasBindingsInternal = function (node) {
switch (node.nodeType) {
case 1: // Element node
// Check if we have a standard KO "data-bind" attribute - use that first
if (sbp.defaultBindingProvider.nodeHasBindings(node)) return true;
// Otherwise look for data-bind-* attributes
return sbp.checkNodeForSplitDataBindAttributes(node.attributes);
case 8: // Comment node - handled the default way
return sbp.defaultBindingProvider.nodeHasBindings(node);
default: return false;
}
};
// Debugging : just print comparison
sbp.nodeHasBindings = function(node) {
var hasBindingsInternal = sbp.nodeHasBindingsInternal(node);
var hasBindings = sbp.defaultBindingProvider.nodeHasBindings(node);
console.log('hasBindings -->', 'ko', hasBindings, 'sbp', hasBindingsInternal);
//return hasBindings; // default for now
return sbp.nodeHasBindingsInternal(node);
};
// This fxn returns a bindings object representing that active bindings for a given node
sbp.getBindings = function (node, bindingContext) {
var originalBindings = sbp.defaultBindingProvider.getBindings(node, bindingContext);
console.log('og:', originalBindings);
// Check if we should use "old-school" KO data-bind attribute mechanism
if (sbp.defaultBindingProvider.nodeHasBindings(node)) {
//return sbp.defaultBindingProvider.getBindings(node, bindingContext);
return originalBindings;
}
// Get split data-bind attributes
var bindingsString = "";
for (var i = 0; i < node.attributes.length; i++) {
if (sbp.attributeIsSplitBinding(node.attributes[i].nodeName)) {
if (i > 0) bindingsString += ',';
bindingsString +=
node.attributes[i].nodeName.substring(sbp.splitBindingAttributePrefix.length) + ':' + node.attributes[i].nodeValue;
}
}
// BIG PROBLEMO : Binding cache is undefined...
// If the bindings were legitimate, leverage the ko binding providers parse bindings string method
return bindingsString ? sbp.defaultBindingProvider.parseBindingsString(bindingsString, bindingContext) : null;
};
};
})(jQuery);