I encountered how painful traversing inline SVG can be when working on a recent project, simple DOM APIs such as adding, removing and toggling classes just aren’t there, or supported by tools such as jQuery (yes, I even tried jQuery).
Table of contents
Inline SVG is SVG in the DOM, rendered from its XML. Here’s a quick look at example inline SVG which would sit anywhere in the DOM:
svg element acts as a wrapper to the XML inside, whilst defining a few things such as height, width, namespace and version. You’ll notice I’ve added an
id attribute, with the value of
svg. Current DOM APIs make this seamlessly easy to target:
Problem: DOM stuff
But the problem begins when trying to do the ‘usual’ DOM stuff, adding a class, or removing a class. You’d think it would be pretty simple, but even using jQuery’s APIs don’t allow it to work either, so I wrote my own and I’m pretty pleased with its compactness. The trick is to set the attribute again, you can’t keep adding/removing classes using the .className method. The getAttribute method is what I’ve used to grab the class attribute’s value, and then the idea behind it is to grab that attribute, manipulate it and then set it back again.
Let’s say I have a function, I need to add a class to an SVG circle onclick:
… will give us:
I have to think as the ‘class’ attribute as totally made up and that className doesn’t exist. And manipulating this is where the magic happens.
Adding a class is simple, just set the attribute. Here I simply make a check using the hasClass API, and if it doesn’t exist I add it. There’s no point adding it again if it does exist. If it doesn’t exist, I set the attribute class with the current class value, plus my new class name, super simple.
Removing a class was the most fun, there’s also the issue of keeping spaces intact, for instances I had to work out how to remove a class and keep the appropriate spaces around that class name. You can see I create a new class here called removedClass, where I get the current value, then replace the passed in className using a dynamically created RegExp again. This RegExp has some coolness added to it, you’ll see I declare ‘g’ at the end of the RegExp declaration, this means global, and will replace all instances of the class, for example if it was declared more than once throughout the class value. I then make a safety check to ensure the class is there, and set the attribute back on the element.
|You’ll also see I used a second parameter as well in the replace method, which says ‘$2’. This is a nifty little trick, which refers to the capture group in the RegExp. Capture groups are denoted by circular brackets, my example at the end of the RegExp says _’(\s||$)’, this denotes a capture group, and then looks for whitespace after the className, OR it’s at the end of the string, which is what the _$ means. I can then remove the className and leave whatever was in the capture group, either a space or nothing, which keeps the class value tidy.|
Toggling from hereon is super simple, I’ll check if the element has the class, and based on that I’ll either add or remove the class using the above APIs.
Usage is simple, and simple API style: