Question

I'm trying to dynamically rotate a gradient in an SVG based on mouse position and it's all working fine except this one line. The trouble is I can't seem to get the jQuery attr method to work. setAttribute works fine to replace rotate(#,#,#) inside of the attribute gradientTransform but attr doesn't. The part that I'm really having trouble with is that I can change other attributes with attr (as in the third example in the fiddle).

http://jsfiddle.net/samt/8yUNL/

this one works

mainLogoFill[0].setAttribute('gradientTransform', 'rotate(45,100,100)');

this one doesn't

mainLogoFill.attr('gradientTransform', 'rotate(90,100,100)');

this one throws me.. why does it work?

mainLogoFill.attr('x1', '100');
Was it helpful?

Solution

jQuery uses toLowerCase with attribute names, so it ends up as gradienttransform not gradientTransform, which is a new attribute and not the same as the one you already have, hence the issues.

The attr() method starts like this

function (elem, name, value) {
    var hooks, ret, nType = elem.nodeType;

    // don't get/set attributes on text, comment and attribute nodes
    if (!elem || nType === 3 || nType === 8 || nType === 2) {
        return;
    }

    // Fallback to prop when attributes are not supported
    if (typeof elem.getAttribute === core_strundefined) {
        return jQuery.prop(elem, name, value);
    }

    // All attributes are lowercase
    // Grab necessary hook if one is defined
    if (nType !== 1 || !jQuery.isXMLDoc(elem)) {
        name = name.toLowerCase(); // this is the line where the name is lowercased
        hooks = jQuery.attrHooks[name] || (jQuery.expr.match.bool.test(name) ? boolHook : nodeHook);
    }

    if (value !== undefined) {

The way around this is to use setAttribute instead.

OTHER TIPS

Although SVG is based on XML (and thus uses case sensitive attribute names), jQuery's detection fails at this point and transforms attribute names to lower case.

If you don't like using .setAttribute() everywhere, an alternative is to patch jQuery by overriding how it determines XML mode:

jQuery.isXMLDoc = function(elem)
{
    return (elem.ownerDocument || elem).documentElement.nodeName !== "HTML" || 
        (elem.namespaceURI).indexOf('html') == -1;
}

The above code additionally checks if the namespace of the current element has the term "html" in it; the namespace for SVG is "http://www.w3.org/2000/svg", so jQuery will not alter the case of your property names.

Demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top