[Javascript] jQuery SVG, ¿por qué no puedo agregarClass?


Answers

Hay element.classList en la API DOM que funciona para elementos HTML y SVG. No es necesario el complemento jQuery SVG o incluso jQuery.

$(".jimmy").click(function() {
    this.classList.add("clicked");
});
Question

Estoy usando jQuery SVG. No puedo agregar o eliminar una clase a un objeto. Alguien sabe mi error?

El SVG:

<rect class="jimmy" id="p5" x="200" y="200" width="100" height="100" />

El jQuery que no agregará la clase:

$(".jimmy").click(function() {
    $(this).addClass("clicked");
});

Sé que SVG y jQuery funcionan bien juntos porque puedo apuntar al objeto y disparar una alerta cuando se hace clic:

$(".jimmy").click(function() {
    alert('Handler for .click() called.');
});



Una solución podría ser agregarClass a un contenedor del elemento svg:

$('.svg-container').addClass('svg-red');
.svg-red svg circle{
    fill: #ED3F32;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="svg-container">
  <svg height="40" width="40">
      <circle cx="20" cy="20" r="20"/>
  </svg>
</div>




Si tiene clases dinámicas o no sabe qué clases podrían aplicarse ya, creo que este método es el mejor:

// addClass
$('path').attr('class', function(index, classNames) {
    return classNames + ' class-name';
});

// removeClass
$('path').attr('class', function(index, classNames) {
    return classNames.replace('class-name', '');
});



jQuery 2.2 es compatible con la manipulación de clase SVG

La publicación jQuery 2.2 y 1.12 publicada incluye la siguiente cita:

Si bien jQuery es una biblioteca HTML, acordamos que el soporte de clase para los elementos SVG podría ser útil. Los usuarios ahora podrán llamar a los métodos .addClass () , .removeClass () , .toggleClass () y .hasClass () en SVG. jQuery ahora cambia el atributo de clase en lugar de la propiedad className . Esto también hace que los métodos de clase sean utilizables en documentos XML generales. Tenga en cuenta que muchas otras cosas no funcionarán con SVG, y aún recomendamos usar una biblioteca dedicada a SVG si necesita algo más allá de la manipulación de clases.

Ejemplo usando jQuery 2.2.0

Prueba:

  • .addClass ()
  • .removeClass ()
  • .hasClass ()

Si hace clic en ese cuadrado pequeño, cambiará su color porque el atributo de class se agrega / elimina.

$("#x").click(function() {
    if ( $(this).hasClass("clicked") ) {
        $(this).removeClass("clicked");
    } else {
        $(this).addClass("clicked");
    }
});
.clicked {
    fill: red !important;  
}
<html>

<head>
    <script src="https://code.jquery.com/jquery-2.2.0.js"></script>
</head>

<body>
    <svg width="80" height="80">
        <rect id="x" width="80" height="80" style="fill:rgb(0,0,255)" />
    </svg>
</body>

</html>




Aquí está mi código poco elegante pero funcional que trata los siguientes problemas (sin dependencias):

  • classList no existe en elementos <svg> en IE
  • className no representa el atributo de class en elementos <svg> en IE
  • Las getAttribute() y setAttribute() rotas del viejo IE

Utiliza classList siempre que sea posible.

Código:

var classNameContainsClass = function(fullClassName, className) {
    return !!fullClassName &&
           new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(fullClassName);
};

var hasClass = function(el, className) {
    if (el.nodeType !== 1) {
        return false;
    }
    if (typeof el.classList == "object") {
        return (el.nodeType == 1) && el.classList.contains(className);
    } else {
        var classNameSupported = (typeof el.className == "string");
        var elClass = classNameSupported ? el.className : el.getAttribute("class");
        return classNameContainsClass(elClass, className);
    }
};

var addClass = function(el, className) {
    if (el.nodeType !== 1) {
        return;
    }
    if (typeof el.classList == "object") {
        el.classList.add(className);
    } else {
        var classNameSupported = (typeof el.className == "string");
        var elClass = classNameSupported ?
            el.className : el.getAttribute("class");
        if (elClass) {
            if (!classNameContainsClass(elClass, className)) {
                elClass += " " + className;
            }
        } else {
            elClass = className;
        }
        if (classNameSupported) {
            el.className = elClass;
        } else {
            el.setAttribute("class", elClass);
        }
    }
};

var removeClass = (function() {
    function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) {
        return (whiteSpaceBefore && whiteSpaceAfter) ? " " : "";
    }

    return function(el, className) {
        if (el.nodeType !== 1) {
            return;
        }
        if (typeof el.classList == "object") {
            el.classList.remove(className);
        } else {
            var classNameSupported = (typeof el.className == "string");
            var elClass = classNameSupported ?
                el.className : el.getAttribute("class");
            elClass = elClass.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer);
            if (classNameSupported) {
                el.className = elClass;
            } else {
                el.setAttribute("class", elClass);
            }
        }
    }; //added semicolon here
})();

Ejemplo de uso:

var el = document.getElementById("someId");
if (hasClass(el, "someClass")) {
    removeClass(el, "someClass");
}
addClass(el, "someOtherClass");



Escribí esto en mi proyecto, y funciona ... probablemente;)

$.fn.addSvgClass = function(className) {

    var attr
    this.each(function() {
        attr = $(this).attr('class')
        if(attr.indexOf(className) < 0) {
            $(this).attr('class', attr+' '+className+ ' ')
        }
    })
};    

$.fn.removeSvgClass = function(className) {

    var attr
    this.each(function() {
        attr = $(this).attr('class')
        attr = attr.replace(className , ' ')
        $(this).attr('class' , attr)
    })
};    

ejemplos

$('path').addSvgClass('fillWithOrange')
$('path').removeSvgClass('fillWithOrange')






Links