почему setAttribute работает, когда атрибут jQuery не работает

Я пытаюсь динамически вращать градиент в SVG в зависимости от положения мыши, и все работает нормально, кроме этой одной строки. Проблема в том, что я не могу заставить работать метод jQuery attr. setAttribute отлично подходит для замены rotate(#,#,#) внутри атрибута gradientTransform, а attr — нет. Часть, с которой у меня действительно возникли проблемы, заключается в том, что я могу изменить другие атрибуты с помощью attr (как в третьем примере в скрипке).

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

этот работает

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

этот не

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

это бросает меня .. почему это работает?

mainLogoFill.attr('x1', '100');

person sam    schedule 28.03.2014    source источник


Ответы (2)


jQuery использует toLowerCase с именами атрибутов, поэтому он заканчивается как gradienttransform, а не gradientTransform, который является новым атрибутом и не совпадает с тем, который у вас уже есть, отсюда и проблемы.

Метод attr() начинается так

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) {

Вместо этого можно использовать setAttribute.

person adeneo    schedule 28.03.2014

Хотя SVG основан на XML (и, таким образом, использует имена атрибутов с учетом регистра), обнаружение jQuery на этом этапе дает сбой и преобразует имена атрибутов в нижний регистр.

Если вам не нравится использовать .setAttribute() везде, альтернативой является исправление jQuery, переопределяющее то, как он определяет режим XML:

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

Приведенный выше код дополнительно проверяет, есть ли в пространстве имен текущего элемента термин "html"; пространство имен для SVG — "http://www.w3.org/2000/svg", поэтому jQuery не изменит регистр имен ваших свойств.

Демо

person Ja͢ck    schedule 28.03.2014
comment
Хотя на самом деле это метод isHTMLDoc. ;-) Но не зазнавайся, IE считает, что обычный HTML-документ — это XHTML (w3.org/ 1999/xhtml), который чувствителен к регистру и требует тега атрибута HTML и имен в нижнем регистре, но возвращает значения для имен тегов HTML в верхнем регистре. Такова жизнь. :-/ - person RobG; 28.03.2014
comment
@RobG Разве это не больше похоже на метод не HTML-документа? :) - person Ja͢ck; 28.03.2014
comment
- ошибся, да. Я думал, что ему нужен метод isHTMLDoc, но это не то, что получилось. :-( - person RobG; 28.03.2014