Skip to content

Commit

Permalink
Implement containerless text binding
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveSanderson committed Jun 15, 2012
1 parent de95292 commit 56dbc8a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
25 changes: 25 additions & 0 deletions spec/defaultBindingsBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@ describe('Binding: Text', {
ko.applyBindings(null, testNode);
var actualText = "textContent" in testNode.childNodes[0] ? testNode.childNodes[0].textContent : testNode.childNodes[0].innerText;
value_of(actualText).should_be("");
},

'Should work with virtual elements, adding a text node between the comments': function () {
var observable = ko.observable("Some text");
testNode.innerHTML = "xxx <!-- ko text: textProp --><!-- /ko -->";
ko.applyBindings({textProp: observable}, testNode);
value_of(testNode).should_contain_text("xxx Some text");
value_of(testNode).should_contain_html("xxx <!-- ko text: textprop -->some text<!-- /ko -->");

// update observable; should update text
observable("New text");
value_of(testNode).should_contain_text("xxx New text");
value_of(testNode).should_contain_html("xxx <!-- ko text: textprop -->new text<!-- /ko -->");

// clear observable; should remove text
observable(undefined);
value_of(testNode).should_contain_text("xxx ");
value_of(testNode).should_contain_html("xxx <!-- ko text: textprop --><!-- /ko -->");
},

'Should work with virtual elements, removing any existing stuff between the comments': function () {
testNode.innerHTML = "xxx <!--ko text: undefined-->some random thing<span> that won't be here later</span><!--/ko-->";
ko.applyBindings(null, testNode);
value_of(testNode).should_contain_text("xxx ");
value_of(testNode).should_contain_html("xxx <!--ko text: undefined--><!--/ko-->");
}
});

Expand Down
1 change: 1 addition & 0 deletions src/binding/defaultBindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ ko.bindingHandlers['text'] = {
ko.utils.setTextContent(element, valueAccessor());
}
};
ko.virtualElements.allowedBindings['text'] = true;

ko.bindingHandlers['html'] = {
'init': function() {
Expand Down
28 changes: 23 additions & 5 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,31 @@ ko.utils = new (function () {
if ((value === null) || (value === undefined))
value = "";

'innerText' in element ? element.innerText = value
: element.textContent = value;
if (element.nodeType == 8) {
// For virtual elements, we need there to be exactly one virtual child: a text node.
// If there are no virtual children, more than one, or if it's not a text node, we'll clear everything out first.
var innerTextNode = ko.virtualElements.firstChild(element);
if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
innerTextNode = document.createTextNode("");
ko.virtualElements.setDomNodeChildren(element, [innerTextNode]);
}
innerTextNode.data = value;
} else {
// Even though the above code path would technically work for regular elements too, the following is faster
'innerText' in element ? element.innerText = value
: element.textContent = value;
}

ko.utils.forceRefresh(element);
},

forceRefresh: function(node) {
// Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
if (ieVersion >= 9) {
// Believe it or not, this actually fixes an IE9 rendering bug
// (See https://github.com/SteveSanderson/knockout/issues/209)
element.style.display = element.style.display;
// For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
var elem = node.nodeType == 1 ? node : node.parentNode;
if (elem.style)
elem.style.display = elem.style.display;
}
},

Expand Down

0 comments on commit 56dbc8a

Please sign in to comment.