This project is archived and is in readonly mode.

#580 open
Xandros

Tips.js : timer not cleared if element detached or removed

Reported by Xandros | June 27th, 2011 @ 11:16 AM

In the case that a Tips instance is attached to some element which is removed from the DOM, if the removal occurs when the mouse is over the removed attached element, a tip is still displayed after the element is removed.

http://jsfiddle.net/istrasoft/nA3Fw/

This can cause other issues later on in IE when trying to retrieve offsets of the element which is not there any more and calling getBoundingClientRect.

A fix would be that when Tips.hide is called, or Tips.detach is called and the element which timer is running is contained in the detached elements, the timer should be cleared.

Also, when the currently shown tip is associated with an element that is being detached, the tip should be hidden.

Thanks !

Comments and changes to this ticket

  • oelmekki

    oelmekki June 28th, 2011 @ 11:59 AM

    Hello,

    I've made the show function to test if trigger element is still in DOM. (patch attached)

    Also, when the currently shown tip is associated with an element that is being detached, the tip should be hidden.

    Afaik, there's no cross-browser event fired when an element is detached, so I suppose it's your responsibility to detach the tooltip when you are removing the trigger element, using Tips#detach(). (patch will prevent tooltip to be shown if trigger element doesn't exist anymore when the show start, though).

  • Xandros

    Xandros June 28th, 2011 @ 12:43 PM

    ok thanks for the patch, I thought it was just easier to properly clear the timer instead ?

    Also, there is no event thats right, but it may be useful to save the element who's tip is currently being shown in the Tips instance (one may use it for other purposes also, as now there is no way to retrieve it) and then check for it when detach is called.

  • oelmekki

    oelmekki June 28th, 2011 @ 01:09 PM

    I thought it was just easier to properly clear the timer instead ?

    Well, clearing the timer isn't a problem. The problem is when we do it, since there are no special event on deletion :) It's ok to me to just test in the timer callback function, because the timeout won't be set anymore then, since it's set on the mouseenter event of the trigger element.

    Btw, I've realized I put the condition in the wrong place, it should be inside the timer callback. Re-attached.

    it may be useful to save the element who's tip is currently being shown in the Tips instance (one may use it for other purposes also, as now there is no way to retrieve it) and then check for it when detach is called

    Agreed, one shouldn't have to pass all elements again. Don't hesitate to fork the repos on github and make pull requests.

  • Xandros

    Xandros June 28th, 2011 @ 01:46 PM

    wow that's a bit tricky to fork/pull and stuff, sorry, i saw aaron's video on Vimeo and well, it's tricky ! :D
    That's why I included a possible change to fix this issue in the fiddle ...

  • Xandros

    Xandros July 5th, 2011 @ 03:16 PM

    Actually, just checking element.parentNode to see if element is in DOM may be insufficient. Here is a better solution IMO (I had a case where element.parentNode was pointing to an element yet this parent was not in the DOM itself).

    
        elementEnter: function(event, element){
            event.stop(); // EFF: temporary
            clearTimeout(this.timer);
            this.timer = (function(){
                this.container.empty();
    
                if(!document.body.contains(element)) { // fix
                  this.hide();                         
                  return;
                }
    
                ['title', 'text'].each(function(value){
                    var content = element.retrieve('tip:' + value);
                    var div = this['_' + value + 'Element'] = new Element('div', {
                            'class': 'tip-' + value
                        }).inject(this.container);
                    if (content) this.fill(div, content);
                }, this);
                this.show(element);
                this.position((this.options.fixed) ? {page: element.getPosition()} : event);
            }).delay(this.options.showDelay, this);
        },
    
  • fakedarren

    fakedarren July 16th, 2011 @ 03:09 PM

    • State changed from “new” to “open”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

The MooTools Extensions

Attachments

Pages