Использование .delegate в jQuery - PullRequest
1 голос
/ 11 апреля 2011

У меня есть функция, которая отлично работает при создании пользовательских подсказок, которые мне нужны для календаря событий. Проблема заключается в том, что когда пользователь щелкает в календаре на следующий месяц, создается новый набор ссылок, и 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 ]

2 голосов
/ 11 апреля 2011

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

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

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

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

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

Поэтому, когда вы используете delegate, вам нужно сообщить jQuery, какие элементы вы на самом деле ищете.Если вы ожидаете событие «mouseover», которое возникло в элементе 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>";

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

1 голос
/ 11 апреля 2011

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

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

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

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

...