Tooltips stop working after an ajax call

Go To StackoverFlow.com

3

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.

enter image description here

2012-04-03 20:55
by Catfish


6

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');
    });
});
2012-04-03 21:01
by Selvakumar Arumugam
Assuming he is using 1.7+, this would be my guess - Matthew Blancarte 2012-04-03 21:03
@MatthewBlancarte True, Added Note mentioning that it is for jQuery 1.7. Thanks - Selvakumar Arumugam 2012-04-03 21:05
jQuery 1.7.x is included since PrimeFaces 3.2. So if OP is using 3.2 or newer, s/he should be all set - BalusC 2012-04-03 21:10
I'm using primefaces 3.0.1 so i must not be using 1.7. Your code seems to work for the most part (using delegate instead of on). The only issue now is that I'm seeing multiple tooltips - Catfish 2012-04-03 21:18
@Catfish mm interesting, are u seeing different tooltips when you hover on 1 of those item - Selvakumar Arumugam 2012-04-03 21:26
I've edited my question with a screenshot - Catfish 2012-04-03 21:35
I changed it from hover to mouseover/mouseout. Works like a charm - Catfish 2012-04-03 21:42
@Catfish I forgot to convert the mouseleave function where you were removing the tooltip. Try to use .delegate on mouseleave like above and it should work well - Selvakumar Arumugam 2012-04-03 21:42


1

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
});
2012-04-03 21:01
by Sander Bruggeman


0

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?

2012-04-03 21:00
by Rob Stevenson-Leggett


0

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.

2012-04-03 21:02
by Khôi