enyo / opentip

Opentip is an open source javascript tooltip based on the protoype framework.
http://www.opentip.org
1.25k stars 401 forks source link

Avoid disappearing when mouse is in Tooltip #89

Open daald opened 10 years ago

daald commented 10 years ago

If a tooltip contains a link, The only way to make it clickable is to set hideDelay to a high value. Otherwise, the tip disappears before the cursor reaches the link. If the user doesn't want to click, it is annoying to wait for the tooltip to disappear.

In my case 1 second is not enough for the link but too much for the tooltip itself.

Please have a look at demo 16 (Element as tooltip) at http://www.nickstakenburg.com/projects/prototip/ which shows what I like to see.

How about implementing this feature in OpenTip?

circunspecter commented 10 years ago

Through the API you can interact with the tooltip. For example:

var myTooltip = new Opentip('#myElement');

myTooltip.tooltipElement.on({
    mouseenter: function()
    {
        myTooltip._abortHiding();
    },
    mouseleave: function()
    {
        myTooltip.prepareToHide();
    }
});

You can also include the click event and call the hide() method.

Regards!

daald commented 10 years ago

Thanks. I will try this as soon I have time again

daald commented 10 years ago

I just tried it with the current 2.4.6 version but I get:

TypeError: myOpentip.tooltipElement is undefined
    myOpentip.tooltipElement.on({

Is there any documentation about tooltipElement?

My test code:

    // Install tooptip
    var myOpentip = new Opentip(el, '', {
        ajax: tipurl,
        hideDelay: 1,
        fixed: true,
        removeElementsOnHide: true,
    });

    myOpentip.tooltipElement.on({
        mouseenter: function() {
            alert('x');
            //myOpentip._abortHiding();
        },
        mouseleave: function() {
            alert('y');
            //myOpentip.prepareToHide();
        }
    });
circunspecter commented 10 years ago

Sorry, the example was to show the idea, but certainly there are cases where it does not work.

Anyway, "tooltipElement" is the DOM element(s) generated by Opentip and appended to body. In your case, Opentip generates this element (tooltip) on "mouseover", so "tooltipElement" does not exist until that time, hence the error.

One solution is to associate events to future elements:

$(document.body).on({
    mouseenter: function() {
        myOpentip._abortHiding();
    },
    mouseleave: function() {
        myOpentip.prepareToHide();
    }
}, '.opentip-container');

I've taken a quick look at the code and does not seem to accept any callback fot ~ aftershow, which would be interesting in this case; there may be something I have not seen, of course. However, another option would be override the "show" method to contemplate your requirements:

(function($){
    var opentipExtensions = {
        oldShow: Opentip.prototype.show,
        show: function(event) {
            var self = this;

            this.oldShow(event);

            this.tooltipElement.on({
                mouseenter: function() {
                    self._abortHiding();
                },
                mouseleave: function() {
                    self.prepareToHide();
                }
            });
        } 
    };
    $.extend(Opentip.prototype, opentipExtensions);
})(jQuery);

From: http://stackoverflow.com/a/7257359/1375362

Here are a couple of options. Maybe you can find some other more appropriate.

PS: I don't know other documentation than www.opentip.org.

circunspecter commented 10 years ago

I have realized that I forgot to note that in the first example you can also avoid storing the instance in a variable, allowing you to create multiple tooltips without being, probably, a hassle; I'm not sure if your case requires multiple instances simultaneously.

That said, it would be enough to use the collection of tips offered by Opentip: Opentip.tips.

An example would be:

var myOpentip;

$('.tooltip').each(function(){
    new Opentip($(this), '', {
        ajax: tipurl,
        hideDelay: 1,
        fixed: true,
        removeElementsOnHide: true,
    });
});

$(document.body).on({
    mouseenter: function() {
        var opentipId = parseInt($(this).attr('id').split('-')[1], 10);
        myOpentip = $.grep(Opentip.tips, function(tip){
            return tip.id === opentipId;
        })[0];

        myOpentip._abortHiding();
    },
    mouseleave: function() {
        myOpentip.prepareToHide();
    }
}, '.opentip-container');

Regards.