Přidávání a odebírání tříd z SVG elementů pomcí jQuery

Červen 18, 2015
Martin Pešout

Nedávno jsem se začal více zaměřovat na práci s SVG souborama a také na tvorbu SVG animací. Specializuju se převážně na UI a nepoužívám žádné složité Javascript frameworky. Dá se říct, že ke spokojenému životu front-end vývojáře si vystačím pouze s běžnou knihovnou jQuery. Před nedávnem jsem narazil na zajímavý problém. Potřeboval jsem po kliknutí přidat třídu do SVG elementu na stránce, abych mohl nechat proběhnout CSS3 animaci. Všechny knihovny jsem měl načtené. Nicméně po zavolání $('#js-svg-element').toggleClass('element--animated'); se nestalo vůbec nic.

Přiznám se, že jsem nad tím strávil dost času, než mně došlo, že bude zakopaný pes někde jinde. Stále jsem si myslel, že chyba musí být ukrytá v mém kódu. Nakonec jsem však našel vysvětelní. Manipulace s třídami v jQuery nefunguje na SVG elementech, protože jQuery k tomuto účelu používá vlastnost className. O konkrétní volání v jQuery se stará tato část kódu attributes/classes.js

cur = elem.nodeType === 1 && ( elem.className ?
    ( " " + elem.className + " " ).replace( rclass, " " ) :
    " "
);

Toto volání funguje na běžných HTML elementech. Avšak vlastnost className se na SVG elementu chová trochu jinak. Nevrací totiž běžný string, ale instanci SVGAnimatedString.

Autoři jQuery o tomto problému ví, nicméně mají tento problém umístěný na seznamu požadavků, které nechtějí řešit. Naštěstí existuje jednoduchý trik, s kterým se dá tento problém obejít:

jQuery .attr()

Asi nejjednodušším řešením je použití jQuery metody .attr():

/**
 * Místo volání metody .addClass('element--animated')
 */
$('#js-svg-element').attr('class', 'element--animated');

/**
 * Místo volání metody .removeClass('element--animated')
 */
$('#js-svg-element').attr('class', '');

Volání metody .attr() nahradí celý atribut class, takže pokud již máte na vybraném elementu nějakou třídu a nechcete o ní přijít, budete muset zápis trochu rozšířit:

/**
 * Místo volání metody .addClass('element--animated')
 */
var element = $('#js-svg-element');
var classes = element.attr('class');
element.attr('class', classes + ' element--animated');

classList

Druhým řešením, které jsem našel, je použít classList dostupný ve Web API Interface. classList je považován jako alternativa k běžnému volání, které vrací string tříd oddělených mezerami. Pro manipulaci s třídami nabízí tři metody: .add, .remove a .toggle.

// div je objekt, který ukazuje na element <div class="foo bar"></div>
div.classList.remove("foo");
div.classList.add("anotherclass");

// Pokud je třída visible dostupná, tak ji odebere.
// V opačném případě ji přidá.
div.classList.toggle("visible");

Bohužel Microsoft tuto možnost podporuje ve svých prohlížečích velice slabě. Pokud budeme chtít toto volání podporovat pro Internet Explorer 9, je třeba své stránky rozšířit o Javascrit Shim, který nám zajístí potřebnou dostupnost pro IE9 a Opera Mini.

Závěrem

Na první pohled je druhé řešení mnohem elegantnější a dovolí nám mnohem kratší zápis. Ale řekněme si na rovinu, že v dnešní době je stále nutné zajišťovat podporu pro prohlížeče Internet Explorer 9. Osobně zastávám názor, že přidávání dalších knihoven (jako Javascript Shim) do projektu mně za tu snahu nestojí. Snažím se totiž držet počet pluginů a závislostí na možném minimu. První řešení pomocí jQuery .attr() je za mě jasným vítězem.

Zdroje

Novinky ze světa front-endu

Pokud vás zajímají další novinky ze světa front-endu, můžete sledovat můj profil na Twitteru

Žádné komentáře

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Můžete používat následující HTML značky a atributy: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>