I'm using this jQuery snippet to create tooltips on some JSF primefaces elements in an html table.
$(document).ready(function() {
$('.ui-icon-pencil, .ui-icon-check, .ui-icon-close, .ui-icon-trash').hover(function(e) { // this is the hover in function
// Since the elements have multiple classes, this function gets the one that starts with ui-icon-<something>
var icon = $(this).attr('class').match(/ui-icon-(?:pencil|check|close|trash)/)[0];
var title = null;
if(icon == 'ui-icon-pencil') {
title = 'Edit';
} else if(icon == 'ui-icon-check') {
title = 'Save';
} else if(icon == 'ui-icon-close') {
title = 'Cancel';
} else if(icon == 'ui-icon-trash') {
title = 'Delete';
}
$('body').append('<p class="tooltip">'+title+'</p>');
$('.tooltip').css('top', (e.pageY-50) + 'px').css('left', (e.pageX-10) + 'px').fadeIn('fast');
}, function() { // this is the hover out function
$('.tooltip').remove();
});
// this handles the tooltip moving when the mouse moves
$('.ui-icon-pencil').mousemove(function(e) {
$('.tooltip').css('top', (e.pageY-50) + 'px').css('left', (e.pageX-10) + 'px');
});
});
This works great except that if you either modify/add/delete a row in the table via jsf ajax magic, the tooltips stop working.
How can i keep the tooltips working after modifying/adding/deleting a row in the table?
I'm think i should be using jquery's live function to keep the tooltips working, but i'm not sure how i would use them in this circumstance.
Most likely the handlers are lost when you modify the table row (via jsf ajax magic). Try using .on
like below and let us know the results,
Note: Below is for jQuery version 1.7. Use .live or .delegate
if you using older version of jQuery.
$(document).ready(function() {
$(document).on('mouseenter', '.ui-icon-pencil, .ui-icon-check, .ui-icon-close, .ui-icon-trash', function(e) { // this is the hover in function
// Since the elements have multiple classes, this function gets the one that starts with ui-icon-<something>
var icon = $(this).attr('class').match(/ui-icon-(?:pencil|check|close|trash)/)[0];
var title = null;
if(icon == 'ui-icon-pencil') {
title = 'Edit';
} else if(icon == 'ui-icon-check') {
title = 'Save';
} else if(icon == 'ui-icon-close') {
title = 'Cancel';
} else if(icon == 'ui-icon-trash') {
title = 'Delete';
}
$('body').append('<p class="tooltip">'+title+'</p>');
$('.tooltip').css('top', (e.pageY-50) + 'px').css('left', (e.pageX-10) + 'px').fadeIn('fast');
});
$(document).on('mouseleave', '.ui-icon-pencil, .ui-icon-check, .ui-icon-close, .ui-icon-trash', function() { // this is the hover out function
$('.tooltip').remove();
});
// this handles the tooltip moving when the mouse moves
$(document).on('mousemove', '.ui-icon-pencil', function(e) {
$('.tooltip').css('top', (e.pageY-50) + 'px').css('left', (e.pageX-10) + 'px');
});
});
Are you adding/removing elements with one of the classes that should show a tooltip on hover after you've done the ajax-call (changing the DOM)?
Eventlisteners are by default bound to the elements that are in the DOM at that moment. You indeed shoud use live, or even better: delegate.
I will post an answer that bounds the eventlistener to the body, but if you have, for instance a deeper nested wrapper-element that will contain al the child-elements that should have the tooltip, then you should bind the eventlistener to that.
$("body").delegate('.ui-icon-pencil, .ui-icon-check, .ui-icon-close, .ui-icon-trash', 'click', function(event){
// Just do the things you would do in a normal .hover-event that is binded to these classes
});
Warning: I don't know JSF
You would need to rebind the mousemove event to the loaded content.
JSF will probably offer a callback to achieve this. This link looks promising: http://javaserverfaces.java.net/nonav/docs/2.0/jsdocs/symbols/jsf.ajax.html#.addOnEvent
Apparently Primefaces has an oncomplete attribute for this purpose:
<p:commandButton value="Cancel" actionListener="#{progressBean.cancel}" oncomplete="pbAjax.cancel();startButton2.enable();" />
Maybe that will help you?
The hover events aren't bound to the new elements added by an ajax call. You will have to manually add the hover function to those newly added elements.
I don't really advocate it, but it will probably work when you run the code you posted above after every ajax call. Just be aware that you will probably have bound the event twice on some elements, which will sometimes produce some strange bugs.