Problem
I’m working with jQuery SVG. I can’t change the class of an object. Is anyone aware of my blunder?
The SVG:
<rect class="jimmy" id="p5" x="200" y="200" width="100" height="100" />
The version of jQuery that refuses to add the class:
$(".jimmy").click(function() {
$(this).addClass("clicked");
});
Because I can target the item and send an alert when it’s clicked, I know SVG and jQuery are compatible:
$(".jimmy").click(function() {
alert('Handler for .click() called.');
});
Asked by Don P
Solution #1
2016 update: please read the following two responses.
A class can’t be added to an SVG with JQuery (less than 3).
If you wish to rely on jQuery, use.attr() with SVG.
// Instead of .addClass("newclass")
$("#item").attr("class", "oldclass newclass");
// Instead of .removeClass("newclass")
$("#item").attr("class", "oldclass");
If you don’t want to rely on jQuery, you can:
var element = document.getElementById("item");
// Instead of .addClass("newclass")
element.setAttribute("class", "oldclass newclass");
// Instead of .removeClass("newclass")
element.setAttribute("class", "oldclass");
Answered by forresto
Solution #2
In the DOM API, there is a function called element.classList that works for both HTML and SVG components. There’s no need for the jQuery SVG plugin, or even jQuery itself.
$(".jimmy").click(function() {
this.classList.add("clicked");
});
Answered by Tomas Mikula
Solution #3
The following are some of the changes stated in the jQuery 3.0 revisions:
Upgrading to jQuery 3 is one answer to this problem. It’s fantastic:
Because jQuery versions before to 3.0 used the className property for these functions, the jQuery class manipulation functions do not work with SVG components.
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
For HTML elements, this works as expected, however for SVG elements, className functions differently. The className property of an SVG element is an instance of SVGAnimatedString, not a string.
If you run this code, your developer console should look something like this.
test div
SVGAnimatedString { baseVal="test svg", animVal="test svg"}
We’d get [object SVGAnimatedString] if we cast that SVGAnimatedString object to a string like jQuery does, which is where jQuery fails.
The jQuery SVG plugin works around this by adding SVG support to the relevant functions.
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
If an element is an SVG element, this function will use the baseVal property of the SVGAnimatedString object if it is available, rather than relying on the class attribute.
This bug is presently listed on jQuery’s Won’t Fix page. The pertinent sections are shown below.
Full SVG support, it appears, was judged outside the scope of the jQuery core and better suited for plugins.
Answered by Alexander O’Mara
Solution #4
If you have dynamic classes or aren’t sure what classes are already in use, I believe this way is the best option:
// addClass
$('path').attr('class', function(index, classNames) {
return classNames + ' class-name';
});
// removeClass
$('path').attr('class', function(index, classNames) {
return classNames.replace('class-name', '');
});
Answered by nav
Solution #5
Based on above answers I created the following API
/*
* .addClassSVG(className)
* Adds the specified class(es) to each of the set of matched SVG elements.
*/
$.fn.addClassSVG = function(className){
$(this).attr('class', function(index, existingClassNames) {
return ((existingClassNames !== undefined) ? (existingClassNames + ' ') : '') + className;
});
return this;
};
/*
* .removeClassSVG(className)
* Removes the specified class to each of the set of matched SVG elements.
*/
$.fn.removeClassSVG = function(className){
$(this).attr('class', function(index, existingClassNames) {
var re = new RegExp('\\b' + className + '\\b', 'g');
return existingClassNames.replace(re, '');
});
return this;
};
Answered by Sagar Gala
Post is based on https://stackoverflow.com/questions/8638621/jquery-svg-why-cant-i-addclass