Skip to content

Commit

Permalink
Export virtualElements; update bindingAttributeSyntax and templating …
Browse files Browse the repository at this point in the history
…to work with non-template virtual elements
  • Loading branch information
mbest committed Jan 20, 2012
1 parent 9cd4faa commit cb1043a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 23 deletions.
26 changes: 14 additions & 12 deletions src/binding/bindingAttributeSyntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
ko.bindingHandlers = {};

ko.bindingContext = function(dataItem, parentBindingContext) {
this['$data'] = dataItem;
if (parentBindingContext) {
// copy all properties from parent binding context
ko.utils.extend(this, parentBindingContext);
this['$parent'] = parentBindingContext['$data'];
this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
this['$parents'] = (this['$parents'] || []).slice(0);
this['$parents'].unshift(this['$parent']);
this['$root'] = parentBindingContext['$root'];
} else {
this['$parents'] = [];
this['$root'] = dataItem;
}
this['$data'] = dataItem;
}
ko.bindingContext.prototype['createChildContext'] = function (dataItem) {
return new ko.bindingContext(dataItem, this);
Expand All @@ -23,12 +24,12 @@
throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
}

function applyBindingsToDescendantsInternal (viewModel, elementVerified) {
var currentChild, nextInQueue = elementVerified.childNodes[0];
function applyBindingsToDescendantsInternal (viewModel, elementVerified, areRootNodesForBindingContext) {
var currentChild, nextInQueue = ko.virtualElements.firstChild(elementVerified);
while (currentChild = nextInQueue) {
// Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
nextInQueue = ko.virtualElements.nextSibling(currentChild);
applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, false);
applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, areRootNodesForBindingContext);
}
}

Expand All @@ -39,7 +40,7 @@
// (1) It's a root element for this binding context, as we will need to store the binding context on this node
// Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
// (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
var isElement = (nodeVerified.nodeType == 1);
var isElement = (nodeVerified.nodeType === 1);
if (isElement) // Workaround IE <= 8 HTML parsing weirdness
ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);

Expand All @@ -48,8 +49,8 @@
if (shouldApplyBindings)
shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, isRootNodeForBindingContext).shouldBindDescendants;

if (isElement && shouldBindDescendants)
applyBindingsToDescendantsInternal(viewModel, nodeVerified);
if (shouldBindDescendants)
applyBindingsToDescendantsInternal(viewModel, nodeVerified, (!isElement && isRootNodeForBindingContext));
}

function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, isRootNodeForBindingContext) {
Expand Down Expand Up @@ -147,9 +148,9 @@
return applyBindingsToNodeInternal(node, bindings, viewModel, true);
};

ko.applyBindingsToDescendants = function(viewModel, rootNode) {
if (rootNode.nodeType === 1)
applyBindingsToDescendantsInternal(viewModel, rootNode);
ko.applyBindingsToDescendants = function(viewModel, rootNode, areRootNodesForBindingContext) {
if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
applyBindingsToDescendantsInternal(viewModel, rootNode, areRootNodesForBindingContext);
};

ko.applyBindings = function (viewModel, rootNode) {
Expand Down Expand Up @@ -179,6 +180,7 @@
};

ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
ko.exportSymbol('bindingContext', ko.bindingContext);
ko.exportSymbol('applyBindings', ko.applyBindings);
ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
Expand Down
14 changes: 10 additions & 4 deletions src/templating/templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
}

function invokeForEachNodeOrCommentInParent(nodeArray, parent, action) {
for (var i = 0; node = nodeArray[i]; i++) {
if (node.parentNode !== parent) // Skip anything that has been removed during binding
continue;
if ((node.nodeType === 1) || (node.nodeType === 8))
if (!nodeArray.length)
return;
var node, nextInQueue = nodeArray[0],
endNode = ko.virtualElements.nextSibling(nodeArray[nodeArray.length-1]);
while ((node = nextInQueue) != endNode) {
nextInQueue = ko.virtualElements.nextSibling(node);
switch (node.nodeType) {
case 1: case 8:
action(node);
break;
}
}
}

Expand Down
28 changes: 21 additions & 7 deletions src/virtualElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,20 @@
}
},

firstChild: function(node) {
if (!isStartComment(node))
return node.firstChild;
if (!node.nextSibling || isEndComment(node.nextSibling))
return null;
return node.nextSibling;
},

nextSibling: function(node) {
if (!isStartComment(node)) {
if (node.nextSibling && isEndComment(node.nextSibling))
return undefined;
return node.nextSibling;
} else {
return getMatchingEndComment(node).nextSibling;
}
if (isStartComment(node))
node = getMatchingEndComment(node);
if (node.nextSibling && isEndComment(node.nextSibling))
return null;
return node.nextSibling;
},

virtualNodeBindingValue: function(node) {
Expand Down Expand Up @@ -175,3 +181,11 @@
}
};
})();
ko.exportSymbol('virtualElements', ko.virtualElements);
ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);
ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);
ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);

0 comments on commit cb1043a

Please sign in to comment.