Подтвердить что ты не робот

JQuery: Как прослушивать изменения DOM?

Возможно ли это и как я могу слушать изменения во всем дереве DOM с помощью jQuery?

Моя конкретная проблема: у меня есть функция "tooltip", которая стильно отображает атрибут title, когда вы делаете hover для любого элемента html. Однако, когда вы делаете зависание, по стандарту браузер отображает title в своем собственном окне. Я хотел бы это подавить. Так что я думал о том, чтобы перенести содержимое атрибута title в пользовательский (HTML5) data-title атрибут при первой загрузке страницы, а затем моя функция подсказки будет работать с data-title.

Проблема в том, что позже я мог бы добавлять/удалять/изменять HTML динамически, поэтому мне нужно "переподтвердить" эти элементы - снова измените эти атрибуты title. Было бы неплохо, если бы слушатель событий прослушал такие изменения для меня и автоматически перезаписывал элементы.

4b9b3361

Ответ 1

Мое лучшее предположение заключается в том, что вы хотите слушать события мутации DOM. Вы можете сделать это с помощью события мутации DOM как любое нормальное событие javascript, например щелчок мышью.

Обратитесь к этому: W3 MutationEvent

Пример:

$("element-root").bind("DOMSubtreeModified", "CustomHandler");

Ответ 2

[отредактировано в ответ на исследование члена Тони]

Итак, без дополнительного кода это немного слепой, но мне кажется, что здесь есть две вещи: 1. поведение всплывающей подсказки браузера по умолчанию; 2. потенциально обновленный DOM и возможность для ваших пользовательских всплывающих подсказок продолжать работу.

Относительно # 1: , когда вы привязываете свое настраиваемое событие к элементу, вы можете использовать event.preventDefault(), чтобы всплывающие подсказки не отображались. Это не работает должным образом. Таким образом, обходным путем для продолжения использования атрибута "title" является захват значения, вставка его в объект данных (функция $.data()), а затем нулевое название с пустой строкой (removeAttr несовместимо). Затем на mouseleave вы извлекаете значение из объекта данных и вставляете его обратно в заголовок. Эта идея приходит отсюда: Как отключить всплывающую подсказку в браузере с помощью jQuery?

Относительно # 2: вместо повторной привязки к изменению DOM вам просто нужно привязать один раз к элементу прослушивателя, который никогда не должен быть уничтожен. Обычно это элемент контейнера какого-то типа, но он может даже быть document (приближается .live(), который теперь устарел), если вам действительно нужен контейнер, содержащий все объекты. Здесь образец, который использует некоторую поддельную разметку моего собственного проекта:

var container = $('.section');

container.on('mouseenter', 'a', function() {
    var $this = $(this);
    var theTitle = $this.attr('title');
    $this.attr('title', '');
    $('#notatooltip').html(theTitle);   
    $.data(this, 'title', theTitle);
});

container.on('mouseleave', 'a', function() {
    $('#notatooltip').html('');
    var $this = $(this);
    var storedTitle = $.data(this, 'title');
    $this.attr('title', storedTitle);
});

Моя нереалистичная разметка (только для этого примера) находится здесь:

<div class="section">
  <a href="#" title="foo">Hover this foo!</a>
  <div id="notatooltip"></div>
</div>

И скрипка здесь: http://jsfiddle.net/GVDqn/ Или с некоторыми проверками здравомыслия: http://jsfiddle.net/GVDqn/1/

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

Вам не нужно повторно связываться на основе изменения DOM, делегированный прослушиватель автоматически обрабатывает его. И вы должны быть в состоянии предотвратить функциональность всплывающей подсказки по умолчанию, просто предотвратив ее.

Ответ 4

Как отмечено Грегом Петтитом, вы должны использовать функцию on() для элемента.

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

Если вы хотите, чтобы функция срабатывала над мышью над событием, и вы хотели, чтобы она запускала все элементы с классом * field_title *, вы бы сделали следующее:

$('.field_title').bind('mouseenter', function() { doSomething(); });

Это вызовет событие over mouse over для любых объектов класса * field_title * и выполнит функцию doSomething().

Надеюсь, что это имеет смысл:)