Is it possible and how can I listen for changes through the entire DOM tree with jQuery?
My specific issue: I have a \'tooltip\' function that displays the contents
You need to look at this here: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents
My best guess is that you want to listen to DOM mutation events. You can do that by DOM mutation event as any normal javascript event such as a mouse click.
Refer to this : W3 MutationEvent
Example:
$("element-root").bind("DOMSubtreeModified", "CustomHandler");
[edited in reply to research by member Tony]
So, without additional code, this is a bit of a blind shot, but it seems to me there are two things to think about here: 1. the default browser tooltip behaviour; 2. a potentially updated DOM and the ability for your custom tooltips to continue functioning.
Regarding #1: when you bind your custom event to the element, you can use This doesn't work properly. So, the workaround to keep using the "title" attribute is to grab the value, push it into the data object (the event.preventDefault()
so that the tooltips don't appear.$.data()
function), and then null the title with an empty string (removeAttr is inconsistent). Then on mouseleave, you grab the value out of the data object and push it back into the title. This idea comes from here: How to disable tooltip in the browser with jQuery?
Regarding #2: instead of re-binding on DOM change, you just need to bind once to a listener element that is never expected to be destroyed. Usually this is a container element of some sort, but it can even be document
(approximating .live()
which is now deprecated) if you really need an all-encompassing container. Here's a sample that uses some fake markup of my own devising:
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);
});
My unrealistic markup (just for this example) is here:
<div class="section">
<a href="#" title="foo">Hover this foo!</a>
<div id="notatooltip"></div>
</div>
And a fiddle is here: http://jsfiddle.net/GVDqn/ Or with some sanity checks: http://jsfiddle.net/GVDqn/1/
There's probably a more optimal way to do this (I honestly didn't research if you could bind two separate functions for two separate events with one selector) but it'll do the trick.
You shouldn't need to re-bind based on DOM change, the delegated listener will automatically handle it. And you should be able to prevent default tooltip functionality just by preventing it.
As noted by Greg Pettit, you should be using the on() function on the element.
What this does is allows you to bind a selector to an event, then jQuery will add this event handler when the objects returned by the selector are available.
If you wanted a function to fire on a mouse over event and you wanted it to fire on all elements with the class of *field_title* you would do this:
$('.field_title').bind('mouseenter', function() { doSomething(); });
This will trigger on the over mouse over event on any objects that have the class of *field_title* and execute the function doSomething().
Hope that makes sense :)