stevie-mayhew/silverstripe-svg

base tag & multiple IDs

Opened this issue · 2 comments

lerni commented

I've included the same SVG multiple times on one Page and set a ID for it per instance to change styles. Say the SVG looked something like this:

    <radialGradient id="SVGID_1_" cx="36" cy="46" r="50" gradientUnits="userSpaceOnUse">
        <stop  offset="0" style="stop-color:#5EE9FF"/>
        <stop  offset="1" style="stop-color:#009DDF"/>
    </radialGradient>
    <polygon opacity="0.6" fill="url(#SVGID_1_)" points="0,0 72,0 72,92 0,92    "/>

Since I could not make the above SVG work with classes (ur(.class)) I had multiple instances of the same ID in the document. In the HTML header I also had a base-tag and this caused the following problem:
http://stackoverflow.com/questions/18259032/using-base-tag-on-a-page-that-contains-svg-marker-elements-fails-to-render-marke

I hacked around with something like this:

    // this is to prefix all ID's with $this-ID to make multiple includes of the same file work without having multiple ID's with the same name
    foreach ($out->getElementsByTagName('*') as $element ) {
        if ($element->hasAttribute('id')) {
            $originID = $element->getAttribute('id');
            $element->setAttribute('id', $this->id .'-'.$originID);
        }
    }
    // here we fetch all fill:url(#...) also prefixing and workaround if base-tag is set in HTML
    foreach ($out->getElementsByTagName('*') as $element ) {
        if ($element->hasAttribute('fill')) {
            $originFill = $element->getAttribute('fill');
            $URLprefix = Controller::curr()->Link();
            if (startsWith($originFill, 'url')) {
                $newVal = str_replace('url(#','url('. $URLprefix .'#'. $this->id . '-' . substr($originFill,5,0), $originFill);
                $element->setAttribute('fill', $newVal);
            }
        }
    }
...
function startsWith($haystack, $needle) {
    // search backwards starting from haystack length characters from the end
    return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
}

I don't know if this issues should be prevented some other how. What are your thoughts?

Hmm, I'm not sure if we can effectively deal with this issue.

We actually started removing all of the SVG reference and including all of the SVG information in each source due to this issue - previous to using this module and inlining the source we we're dumping the entire SVG bundle into the HTML and then using an xlink and a "CurrentURL" function to link them like the following:

public function CurrentURL()
{
    if(strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') > 0){
        return $_SERVER['REQUEST_URI'];
    }
    return false;
}
<svg width="34" height="34"><use xlink:href="{$CurrentURL}#shape-contact-drop-close"></use></svg>

This was because of the issue with relative path which happens with the base_url tag set as well.

I'm not sure if its something which should be dealing with at the module level or not as its an issue with implementations by browser vendors - but I'm happy to include something like this in the module which you can "turn on" as it will obviously make life easier until we reach a point where SVG works in browser more effectively.

lerni commented

thanks for your answer! I see how you work with it. I think the issue with multiple ID's is something the module could somehow deal with, since it leads to all sort of oddities, but I don't see a nice way doing it. So it all is probable more about me, trying to understand this SVG thing :)