Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/rampion/knockout into ram…
Browse files Browse the repository at this point in the history
…pion-master
  • Loading branch information
mbest committed Sep 29, 2017
2 parents bd13741 + 0b575f8 commit cee294c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
20 changes: 19 additions & 1 deletion spec/defaultBindings/attrBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ describe('Binding: Attr', function() {
expect(testNode.childNodes[0].getAttribute("second-attribute")).toEqual("true");
});

it('Should be able to set namespaced attribute values', function() {
var model = { myValue: "first value" };
testNode.innerHTML = [
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">',
'<g>',
'<a data-bind="attr: { \'xlink:href\': myValue }">',
'<text>foo</text>',
'</a>',
'</g>',
'</svg>'
].join('');

ko.applyBindings(model, testNode);
var anchor = testNode.childNodes[0]/*svg*/.childNodes[0]/*g*/.childNodes[0]/*a*/;
expect( anchor.getAttributeNode('xlink:href').value ).toEqual( 'first value' );
expect( anchor.getAttributeNode('xlink:href').namespaceURI ).toEqual( 'http://www.w3.org/1999/xlink' );
});

it('Should be able to set \"name\" attribute, even on IE6-7', function() {
var myValue = ko.observable("myName");
testNode.innerHTML = "<input data-bind='attr: { name: myValue }' />";
Expand Down Expand Up @@ -62,4 +80,4 @@ describe('Binding: Attr', function() {
expect(testNode.childNodes[0].className).toEqual("");
expect(testNode.childNodes[0].getAttribute("class")).toEqual(null);
});
});
});
13 changes: 11 additions & 2 deletions src/binding/defaultBindings/attr.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ ko.bindingHandlers['attr'] = {
ko.utils.objectForEach(value, function(attrName, attrValue) {
attrValue = ko.utils.unwrapObservable(attrValue);

// Find the namespace of this attribute, if any.
// Defaulting to `null` should be ok, as
//
// element.setAttributeNS( null, name, value ) ~ element.setAttribute( name, value )
// element.removetAttributeNS( null, name ) ~ element.removeAttribute( name )
//
var prefixLen = attrName.indexOf(':');
var namespace = prefixLen < 0 ? null : element.lookupNamespaceURI( attrName.substr(0, prefixLen) );

// To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
// when someProp is a "no value"-like value (strictly null, false, or undefined)
// (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
if (toRemove)
element.removeAttribute(attrName);
element.removeAttributeNS(namespace, attrName);

// In IE <= 7 and IE8 Quirks Mode, you have to use the JavaScript property name instead of the
// HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
Expand All @@ -23,7 +32,7 @@ ko.bindingHandlers['attr'] = {
else
element[attrName] = attrValue;
} else if (!toRemove) {
element.setAttribute(attrName, attrValue.toString());
element.setAttributeNS(namespace, attrName, attrValue.toString());
}

// Treat "name" specially - although you can think of it as an attribute, it also needs
Expand Down

0 comments on commit cee294c

Please sign in to comment.