jQuery 3 no tiene este problema
Uno de los cambios enumerados en las revisiones de jQuery 3.0 es:
agregar manipulación de clase SVG ( # 2199 , 20aaed3 )
Una solución para este problema sería actualizar a jQuery 3. Funciona muy bien:
var flip = true;
setInterval(function() {
// Could use toggleClass, but demonstrating addClass.
if (flip) {
$('svg circle').addClass('green');
}
else {
$('svg circle').removeClass('green');
}
flip = !flip;
}, 1000);
svg circle {
fill: red;
stroke: black;
stroke-width: 5;
}
svg circle.green {
fill: green;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<svg>
<circle cx="50" cy="50" r="25" />
</svg>
El problema:
La razón por la cual las funciones de manipulación de clase jQuery no funcionan con los elementos SVG es porque las versiones jQuery anteriores a la 3.0 usan className
propiedad para estas funciones.
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
Esto se comporta como se espera para los elementos HTML, pero para los elementos SVG className
es un poco diferente. Para un elemento SVG, className
no es una cadena, sino una instancia deSVGAnimatedString
.
Considere el siguiente código:
var test_div = document.getElementById('test-div');
var test_svg = document.getElementById('test-svg');
console.log(test_div.className);
console.log(test_svg.className);
#test-div {
width: 200px;
height: 50px;
background: blue;
}
<div class="test div" id="test-div"></div>
<svg width="200" height="50" viewBox="0 0 200 50">
<rect width="200" height="50" fill="green" class="test svg" id="test-svg" />
</svg>
Si ejecuta este código, verá algo como lo siguiente en su consola de desarrollador.
test div
SVGAnimatedString { baseVal="test svg", animVal="test svg"}
Si tuviéramos que convertir ese SVGAnimatedString
objeto en una cadena como lo hace jQuery, tendríamos[object SVGAnimatedString]
, que es donde falla jQuery.
Cómo maneja esto el complemento jQuery SVG:
El complemento jQuery SVG soluciona este problema parcheando las funciones relevantes para agregar soporte SVG.
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
Esta función detectará si un elemento es un elemento SVG y, si lo es, utilizará la baseVal
propiedad del SVGAnimatedString
objeto si está disponible, antes de recurrir al class
atributo.
La postura histórica de jQuery sobre el tema:
jQuery actualmente enumera este problema en su página No se solucionará . Aquí están las partes relevantes.
SVG / VML o errores de elementos de espacio de nombres
jQuery es principalmente una biblioteca para el DOM HTML, por lo que la mayoría de los problemas relacionados con documentos SVG / VML o elementos con espacios de nombres están fuera de alcance. Intentamos abordar los problemas que "se filtran" a los documentos HTML, como los eventos que salen de SVG.
Evidentemente, jQuery consideró el soporte SVG completo fuera del alcance del núcleo jQuery, y mejor adaptado para complementos.