stevenbenner / jquery-powertip

:speech_balloon: A jQuery plugin that creates hover tooltips.
https://stevenbenner.github.io/jquery-powertip/
MIT License
821 stars 137 forks source link

Add a « live mode » #33

Open GuillaumeAmat opened 12 years ago

GuillaumeAmat commented 12 years ago

If I launch PowerTip with the ".my_class" selector, I should want to have tooltips on existing element with the class "my_class" AND on element added with Ajax later.

stevenbenner commented 12 years ago

This could be a useful addition. But I'm not sure of what the API should look like. $(selector).powerTip() doesn't really make sense in live mode, so it probably belongs in the $.powerTip namespace.

I'll investigate. Do you use any other jQuery plugins with a live mode that you like? I'd like to see how other people are implementing this.

GuillaumeAmat commented 12 years ago

I used to work with https://github.com/vicb/tipsy-swift, but your library is, IMHO, far better and polish. This live mode is the only thing I regret from TipSwift...

Thanks for your investigation and your good work !

stevenbenner commented 12 years ago

Okay, I see. That project accepts a live option, then uses that to choose between using jQuery's bind() or live() methods when hooking its events up.

I don't think that is the most expressive or efficient way to do it, and the jQuery team would seem to agree since live() was deprecated in 1.7. If I were to build this right now I would try to replicate how the new on() method behaves for event delegation.

Example of what I'm thinking:

$.powerTip(document, '.tips', options);

Or, possibly:

$(document).powerTip(options, '.tips');

If you (or anyone reading this) have any suggestions for the best way to do this please let me know.

GuillaumeAmat commented 12 years ago

I was thinking of the on() event delegation too, but not in that way.

In my opinion, the user perspective must not reflect the technicals tricks. The PowerTip method must be the same and the live mode is sort of an option to switch on and off.

But under the hood, it means that you can grab the selector which was used during the call (I don't know if it's possible). Next, you test the boolean for the live mode and trigger the on() method on the document element if it's true (like your examples).

Am I wrong anywhere ? It's just a suggestion anyway and again, I don't know if jQuery lets you get the used selectors.

puzrin commented 12 years ago

IMHO, this option is too specific to generalise. It will need tons of data-* attributes -> can bloat API. It's not a big problem to make custom initializer, if you have such advanced requirements.

GuillaumeAmat commented 12 years ago

I don't think it's too specific, it can be used on every site which have tooltips. Since one powertip call with one event listener is better than dozens calls and event listeners.

Why it will need more data-* than the actual state ?

puzrin commented 12 years ago

AFAIK, in actual state popover don't have stable data-* API. And if you like to use single event listener, you'll need ability to override any defaults for each specific popover.

Anyway, you can see working example, that does ~ what you are speaking about https://github.com/nodeca/nodeca.users/blob/master/client/common/init/usercard_popover.js#L38 . Feel free to use any part of code as you wish.

GuillaumeAmat commented 12 years ago

Thanks for sharing ;)

stevenbenner commented 12 years ago

There would be some tricky parts to implement this request, such as how to deal with the title attribute. Title attributes need to have their content copied to the data attribute and then removed because we don't want the browser to show the built in title tooltip over the PowerTip tooltip.

Right now that work is done when powerTip() is run, but if we're listening for events bubbling through the document on elements that may or may not exist when the plugin is run then that will be a challenge.

But I won't really know what problems will crop up until I dig deeper. Investigating this is still on my to-do list, but (like all requests) it may get rejected as impossible or to hacky to implement.

I'll let you know when I have more info.

nrabinowitz commented 12 years ago

One way to approach this is by implementing the "manual" option discussed on #26, which basically just suppresses the event attachment. I'm currently using this in my fork for delegated events, lazy-loading the powerTip, like this:

var mouseenterHandler = comp.mouseover = function() {
        var $this = $(this);
        // attach if necessary
        if (!$this.data('powertip')) {
            $this.data('powertip', "My Content");
            $this.powerTip({
                manual: true,
                // other options
            });
        }
        $this.data('displayController').show();
    },
    mouseleaveHandler = function() {
        var controller = $(this).data('displayController');
        if (controller) controller.hide();
    };

$('.parent-element')
    .on('mouseenter', '.child-element', mouseenterHandler)
    .on('mouseleave', '.child-element', mouseleaveHandler);

I will try to submit a pull request for the "manual" option shortly - in its simplest implementation, it's just an if statement around the event listeners.

GuillaumeAmat commented 12 years ago

Awesome! Thank you very much ;)

seabasss commented 10 years ago

Hey great plugin!

I'm having problem with dynamically loaded content though. How can I use this live? Is there a solution? Thanks!

seabasss commented 10 years ago

I tried nrabinowitz's solution but it only works the first time I hover an object, then it stops.

stevenbenner commented 10 years ago

@seabasss Would it be possible to see the code you're using? Right now the only way to hook PowerTip to elements that may or may not exist is the use the event delegation approach.

seabasss commented 10 years ago

Hi, thanks for answering!

I used the exact code as above. What I tried to do was opening a fancybox (like lightbox) and it fetches data with ajax and none of the titles in the fetched data worked with the powertip.

I placed another powertip code on the page that I'm fetching with ajax and it works, but it would be wonderful to only use one code in my javascript file for all titles, existing and added later. It works like that with the standard jquery tooltip, but that hasn't the hoverintent like powertip which is why I switched.

I just found out about the data("powertip", "value") so that's great to be able to update them. I can't get it to work for the ajax content without loading the actual .powertip() script again though.

Fancybox also have some thumbnails that I want tooltip on, but I couldn't figure out how to use powertip on that so I'm using jquery tooltip for that right now. (=loading a tooltip script 3 times)

This is my Thumbnail script. Can it be translated into powertip? (is there a code tag on this forum? It renders some of my code as html below)

... .attr( 'title', thumbTitle ) .addClass( 'tooltip' ) .tooltip({ show: 250, hide: 25, content: function () { return $(this).prop('title'); } });

stevenbenner commented 10 years ago

I'll have to review the live-mode workaround code, but I don't have time tonight, hopefully I'll have a chance this weekend.

For now I did notice that FancyBox does have event callbacks, so it is possible to hook PowerTip to elements that were generated by FancyBox after it has rendered them, for example:

$(".fancybox").fancybox({
    afterLoad: function(current, previous) {
        $('.tooltip').powerTip();
    }
});

This is my Thumbnail script. Can it be translated into powertip?

PowerTip doesn't have a custom content function at the moment so you would have to use the data attributes with a function to compute the return, for example:

$('.tooltip').data('powertip', function() {
    return $(this).prop('title');
});
$('.tooltip').powerTip();
Itguts commented 5 years ago

for long string tooltip, it is crossing the screen and displaying the truncated tooltip. Is there any provision for multiline tooltip?