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 of the title
attribute in a stylish way when you do a hover
on any html element. When you do a hover, however, by standard the browser renders the title
in its own box. I would like to supress that. So what I've thought of is to move the contents of the title
attribute to a custom (HTML5) data-title
attribute the first time the page is loaded, and then my tooltip function will work with data-title
.
The problem is that later on I might add / remove / change the HTML dynamically, so I need to 'rebind' those elements - change those title attrs again. It would be nice if there was an event listener that would listen for such changes for me and rebind the elements automatically.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With