Использование.delegate в jQuery

У меня есть функция, которая отлично работает при создании пользовательских подсказок, которые мне нужны для календаря событий. Проблема заключается в том, что когда пользователь щелкает, чтобы перейти к следующему месяцу в календаре, создается новый набор ссылок, и jQuery больше не выбирает эти ссылки.

Вот моя оригинальная функция:

jQuery(function(){
        var tip = jQuery("#tip");
        var myTitle = "";

        jQuery(".eventful-pre a, .eventful a").hover(function(e){

        toolTip = "<ul>";
           jQuery.each(jQuery(this).attr("title").split(","),function(ind, val){
               toolTip  = toolTip +"<li>"+val +"</li>";
            });
            toolTip = toolTip +"</ul>";

            tip.html(toolTip);
            myTitle = jQuery(this).attr("title");

            jQuery(this).attr("title", "");

            tip.css("top",(e.pageY+5)+"px")
                .css("left",(e.pageX+5)+"px")
                .fadeIn("slow");

        }, function() {
                jQuery("#tip").fadeOut("fast");

                jQuery(this).attr("title", myTitle);
        });

это работает так, как я этого хочу. Я думаю.delegate - это то, что я хочу использовать для захвата новых элементов, когда они появляются, но я, вероятно, делаю это неправильно, потому что это не работает.

jQuery("table").delegate("a.em-calnav", function(){
        in here I pasted my previous function.
    }

календарь можно посмотреть по адресу http://dev.adabible.org/about-ada/

Я, должно быть, неправильно делаю.delegate, а также должен быть лучший способ сделать что-то, чем снова вставлять мою функцию и делать это дважды в одном и том же скрипте.

Заранее спасибо, о мудрые!

2 ответа

Решение

JQuery-х delegate Метод фактически назначает прослушиватель событий. Ты использовал jQuery("table").delegate(...) Таким образом, вы сказали jQuery назначить прослушиватель событий для каждой таблицы на странице.

Итак, первый шаг - выяснить, какое событие вы хотите прослушать. Вы делаете всплывающие подсказки, поэтому в настоящее время вы используете "hover". В этом нет ничего плохого, за исключением того, что "hover" на самом деле представляет собой два события в одном: "mouseenter" и "mouseleave". Вы можете использовать "зависать" с delegate, но только если у вас есть одна функция для обработки событий "входа" и "выхода". Похоже, вы используете две разные функции: одну для создания / исчезновения в подсказке, а другую для ее уничтожения.

Вы могли бы использовать delegate дважды, один раз для "ввода" и один раз для "выхода", за исключением того, что (в соответствии с этим комментарием к jQuery) это поддерживается не во всех браузерах. ( QuirksMode имеет хороший набор таблиц совместимости, касающихся "ввода"/"отпуска", и объяснение того, почему они великолепны.)

Похоже, вам придется использовать "mouseover" и "mouseout", которые немного сложнее из-за того, как работает всплывающее окно событий. НО! Если вы используете всплывающие подсказки только на простых ссылках (например, a элементы, которые содержат текст и ничего больше, или одно изображение и ничего больше), все должно работать хорошо.

Следующий шаг требует знания пузыря событий, другой предмет, который QuirksMode объясняет очень хорошо. Когда вы наводите указатель мыши на элемент, возникает событие "наведение мыши". Если у этого элемента есть прослушиватель событий mouseover, то он выполняется. Событие затем перемещается к родителю элемента. Если у родителя есть прослушиватель событий mouseover, то он также выполняется. Это продолжается до тех пор, пока событие не пройдет через каждого родителя, вплоть до document,

Поэтому, когда вы используете delegate, вам нужно указать jQuery, какие элементы вы на самом деле ищете. Если вы ожидаете событие "наведения мыши", которое возникло на a элемент с классом "hover", тогда вы будете использовать что-то вроде этого:

jQuery(document).delegate('a.hover', 'mouseover', ...);

Обратите внимание, что первая часть может быть чем-нибудь, что содержит все ваши a.hover элементы. Все это будет работать примерно одинаково:

jQuery('body').delegate('a.hover', 'mouseover', ...);
jQuery(document).delegate('a.hover', 'mouseover', ...);
jQuery('div.some_container').delegate('a.hover', 'mouseover', ...);

Я привожу это потому, что в вашей текущей функции вы используете селектор ".eventful-pre a, .eventful a", Но потом, когда вы попытались делегировать, вы использовали "a.em-calnav", На какие из этих селекторов вы действительно хотите нацелиться? Если бы все ссылки, которые могли иметь всплывающие подсказки, также имели класс "em-calnav", то я бы согласился с этим просто потому, что вам не пришлось бы беспокоиться о потомках-селекторах. Но любой из них действителен.

Итак, что мы в итоге имеем что-то вроде этого:

jQuery(function () {
    var tip = jQuery("#tip");
    var myTitle = "";

    jQuery("table").delegate("YOUR_SELECTOR", "mouseover", function (e) {
        var toolTip = "<ul>";
        jQuery.each(jQuery(this).attr("title").split(","), function (ind, val) {
            toolTip = toolTip + "<li>" + val + "</li>";
        });
        toolTip = toolTip + "</ul>";

        tip.html(toolTip);
        myTitle = jQuery(this).attr("title");
        jQuery(this).attr("title", "");

        tip.css("top", (e.pageY + 5) + "px")
            .css("left", (e.pageX + 5) + "px")
            .fadeIn("slow");

    }).delegate("YOUR_SELECTOR", "mouseout", function () {
        jQuery("#tip").fadeOut("fast");
        jQuery(this).attr("title", myTitle);
    });
});

Ваша проблема заключалась в том, что при загрузке нового календаря ссылки больше не имели прослушивателей событий "зависания". Это решение здесь делегирует событие table, Но если в процессе создания нового календаря вы также создаете новую таблицу, то это решение на самом деле ничего не делает. Вы должны были бы делегировать события родителю таблицы, или что-то еще. По сути, вы делегируете элементы, которые в действительности не меняются в вашем JavaScript. (Вот почему document или же "body" так часто встречаются в делегировании событий.)

Кроме того, я не изменил сами функции; Я просто перенес их в подходящее место. Но есть некоторые вещи, которые вы могли бы сделать немного более эффективно. Самой большой проблемой, которую я видел, было то, как вы строите подсказку. Вместо звонка jQuery.each, вы могли бы сделать что-то вроде этого:

var toolTip = "<ul>";
myTitle = jQuery(this).attr("title");

toolTip += "<li>" + myTitle.split(",").join("</li><li>") + "</li></ul>";

Надеюсь, я смог помочь. Удачи.

Первое, что приходит на ум, - это то, что вы не указали событие для делегата.

Вы должны использовать это так:

jQuery("table").delegate("a.em-calnav", 'click', function(){
    in here I pasted my previous function.
}

Обратите внимание на добавленное click (должно быть любое событие, которое вы хотите делегировать).

Другие вопросы по тегам