Объединение Raphael и jQuery для обеспечения совместимости с браузером

Обнаружив, что IE не обрабатывает javascript onmouseout, я решил использовать jQuery, чтобы обеспечить совместимость кросс-браузера автоматически. Я делаю область, определенную путём svg, загорается, когда мышь нависает над ней, и я адаптировал код, представленный на веб-сайте Рафаэля, из примера Австралия.

В этом коде каждое состояние Австралии определяется путем Рафаэля, например Tasmania:

 aus.tas = R.path("...").attr(attr);

Этот путь ('st') затем передается функции:

st[0].onmouseover = function () {
    ...
};

В отличие от того, что я ожидал бы, код st[0].onmouseover, а не просто st.onmouseover. Таким образом, путь должен быть массивом, а st[0], что бы это ни было, - это то, что зависает.

Чтобы заменить onmouseover эквивалентом jQuery (который я считаю .mouseout()), мне нужно назначить класс st[0], чтобы я мог ссылаться на него с помощью jQuery. Мой вопрос: как мне это сделать? Если код был st.onmouseover, это было бы просто, но почему путь (st) - массив? Что такое st[0]? И как, черт возьми, я добираюсь до него?

Ответ 1

Примечание. Это демо было сделано со старой версией Рафаэля. Теперь у Raphael есть свои собственные обработчики событий, в том числе .mouseover() и .hover().


Короче:

Просто оберните объект DOM, чтобы сделать из него объект jQuery, или используйте Raphael, встроенный в пользовательские обработчики событий:

$(st[0]).mouseover( ... );            // This uses the jQuery .mouseover() method

Или, возможно, более удобный и поддерживаемый IE:

$(st[0]).hover( ... );                //     This uses the jQuery .hover() method

Или, используя Рафаэль, встроенный в метод обработчика событий:

st.mouseover( ... );                 // This uses the Raphael .mouseover() method
st.hover( ... );                     //     This uses the Raphael .hover() method

Долгое время:

Вы можете получить ссылку на объект DOM для работы с node или [0], так как RaphaelObject[0] всегда является ссылкой на элемент DOM:

aus.tas = R.path("...").attr(attr);

// aus.tas is a Raphael object
// aus.tas[0] is aus.tas.node is the reference to the DOM Object

$(aus.tas[0]).mouseover(function() {          // Could have also use aus.tas.node
    ...
});

// Raphael now has custom event handlers
aus.tas.mouseover(function() {
    ...
});
aus.tas.hover(function() {
    ...
}, function() {
    ...
});

Итак, с вами функция:

(function (st, state) {
      // st is a Raphael Object
      // st[0] is st.node is the reference to the DOM Object

      // This is now using jQuery for mouseover!
    $(st[0]).mouseover(function() {
        ...
    });
    ...
})(aus[state], state);

Кроме того, я бы предложил заглянуть в функцию jQuery .hover(), которая отлично справляется с IE:

(function (st, state) {
      // This is now using jQuery not Raphael for hover!
    $(st[0]).hover(function() {
        ... // the mouseenter function
    }, function() {
        ... // the mouseleave function
    });
    ...
})(aus[state], state);

Как упрощенная демонстрация, вот как привязать mouseenter и mouseout с помощью .hover() к элементу Рафаэля (проверенному в IE 8):

​$(function() {
    var elie, paper = Raphael("canvas", 500, 500); 

      // Create Raphael element
    elie = paper.rect(0,0,100,100).attr("fill","#000");

      // Get reference to DOM object using .node and bind
      //     mouseover and mouseout to it:
    $(elie[0]).hover(function() {
        elie.attr("fill","#FFF");
    },function() {
        elie.attr("fill","#000");    
    });
});​

Попробуйте это с помощью jsFiddle

Кроме того, метод Raphael .hover(), похоже, работает и в IE.

Ответ 2

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

$(st[0]).mouseout(function() {
  alert("That mouse is outta here!");
};

Вы видите синтаксис массива, потому что, как правило, библиотеки Javascript поддерживают ссылку на исходный элемент (по сути, просто "обертывая" его и добавляя функциональность). Объяснение псевдокода...

st == Raphael element
st[0] == DOM element

Ответ 3

Если вы просто скопируете код, используемый демоверсией в Австралии, вы столкнетесь с проблемой IE, независимо от того, какой обработчик (наведение, наведение мыши и т.д.) вы используете.

После того, как я немного наткнулся на него, кажется, что функция st.toFront() в функции ввода/вывода отменяет событие "мыши" в IE. Удалите эти строки из кода примера, и все должно быть в порядке.

Ответ 4

Это немного обмана javascript, st передается. Посмотрите на JS-код в примере australia.

(function (st, state) {
                    .. some code referring to st[0] in here .. 
                })(aus[state], state);

Итак, st [0] в этом коде ссылается на путь DOM node из aus [state].

Попробуйте сами, используя этот простой пример в консоли Firebug:

(function(a,b) {alert(a); })("hello", "b");

HTH

Ответ 5

В моем случае, фактическая проблема заключалась в вызове .toFront для каждого freakin millisecond, потому что .hover(fooFunction, outFunction) вызывает fooFunction с каждым сдвигом курсора мыши. На самом деле, имя вполне предполагает, что это вызов наведения, а не центр мыши:)

Итак, трюк заключается в том, чтобы убедиться, что ваш fooFunction или его содержимое выполняется только один раз (onmouseenter). Даже в IE это отлично работает для меня, без доступа к каким-либо узлам DOM или к доступу к другим материалам, которые я не хочу касаться:

var MouseEventHelper = {
    hover: function (el, funcIn, funcOut) {
        var entered = false;

        el.hover(
            function (e) {
                if (entered) {
                    return;
                }

                funcIn(e);
                entered = true;
            },
            function (e) {
                funcOut(e);
                entered = false;
            }
        );
    }
}

Затем замените ваши зависающие вызовы следующим образом:

var el = paper.rect(...);
MouseEventHelper.hover(
    el, 
    function (e) { 
        // do whatever you want!
        el.toFront();
    }
    function (e) { }
);