Reputation: 1296
I'm trying to change the "xlink:href" attribute with a click event, and so far it is partially working. This is what I'm doing
HTML:
<a href="#" class="ui-btn ui-corner-all ui-shadow editIcon" data-iconpos="top" data-transition="none" style="text-align:center">
<svg class="icon icon-pencil">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-pencil"> </use>
</svg>
</a>
JS:
$('a.editIcon').on('click', function () {
if ($("a.editIcon svg").attr('class') == 'icon icon-pencil') {
$("a.editIcon svg").attr("class", "icon icon-floppy-disk");
$("a.editIcon svg use").attr("xlink:href", "#icon-floppy-disk");
} else {
myFunctionCall();
$("a.editIcon svg").attr("class", "icon icon-pencil");
$("a.editIcon svg use").attr("xlink:href", "#icon-pencil");
}
});
What is happening is that I'm able to change the class without any problems, but the "xlink:href" attribute doesn't change, instead, leaves the old one ("#icon-pencil"), and adds a new "href" attribute (href="#icon-floppy-disk"):
<svg class="icon icon-floppy-disk">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-pencil" href="#icon-floppy-disk"></use>
</svg>
What am I missing here? Thanks!
Upvotes: 3
Views: 10401
Reputation: 1237
I had this same question today and after searching around I found two solutions that worked. As suggested by @Dr.Molle and @prodigitalson in this question's comments, I was able to use:_HTMLNode_.setAttributeNS()
to fix my problem but I am not sure why this solution failed to work for you @cubanGuy.
After digging through SVG Spec, I learned that xlink:href
is deprecated in favor of using a non-namespaced href
attribute. The href
attribute (on SVG elements) is represented with a SVGAnimatedString object (used to reflect an animatable string attribute) which has two properties:
interface SVGAnimatedString {
attribute DOMString baseVal;
readonly attribute DOMString animVal;
};
This enables us to change the value of the href
attribute by setting _HTMLNode_.href.baseVal
which also changes the xlink:href
attribute because the baseVal setter does the following:
If the
href
attribute is not present, the SVGAnimatedString object is defined to additionally reflect the deprecatedxlink:href
attribute if the deprecated attribute is present. Then it sets that deprecated attribute to the specified value.
Since the namespaced attribute is deprecated I recommend that _HTMLNode_.href.baseVal
be used in favor of _HTMLNode_.setAttributeNS()
when supporting modern browsers. If you want to see them in action I created a snippet that demonstrates both methods working below:
var svgElement1 = document.getElementById("editIcon1");
svgElement1.onclick = function () {
var useElement = this.getElementsByTagName("use")[0];
if (this.className === 'icon icon-locked') {
this.className = "icon icon-unlocked";
useElement.href.baseVal = "#unlocked";
} else {
this.className = "icon icon-locked";
useElement.href.baseVal = "#locked";
}
}
var svgElement2 = document.getElementById("editIcon2");
svgElement2.onclick = function () {
var useElement = this.getElementsByTagName("use")[0];
if (this.className === 'icon icon-locked') {
this.className = "icon icon-unlocked";
useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#unlocked');
} else {
this.className = "icon icon-locked";
useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#locked');
}
}
<svg xmlns="http://www.w3.org/2000/svg" id="svg-icons">
<symbol viewBox="0 0 24 24" id="unlocked">
<path d="M18,9h-1V7c0-2.8-2.2-5-5-5S7,4.2,7,7h1.9c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H6c-1.1,0-2,0.9-2,2v9c0,1.1,0.9,2,2,2
h12c1.1,0,2-0.9,2-2v-9C20,9.9,19.1,9,18,9z"></path>
</symbol>
<symbol viewBox="0 0 24 24" id="locked">
<path d="M18,9h-1V7c0-2.8-2.2-5-5-5S7,4.2,7,7v2H6c-1.1,0-2,0.9-2,2v9c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-9C20,9.9,19.1,9,18,9z
M15.1,9H8.9V7c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1V9z"></path>
</symbol>
</svg>
<div>
<a href="#" id="editIcon1">this is test 1
<svg class="icon icon-locked">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#unlocked"> </use>
</svg>
</a>
</div>
<div>
<a href="#" id="editIcon2">this is test 2
<svg class="icon icon-locked">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#unlocked"></use>
</svg>
</a>
</div>
Here is a working JSFiddle: https://jsfiddle.net/ybtq9e03/
I hope this helps!
Upvotes: 6