]> source.dussan.org Git - jquery-ui.git/commitdiff
Overhaul tooltip implementation. Avoid queuing and other problems by
authorjzaefferer <joern.zaefferer@gmail.com>
Wed, 13 Apr 2011 12:01:46 +0000 (14:01 +0200)
committerjzaefferer <joern.zaefferer@gmail.com>
Wed, 13 Apr 2011 12:01:46 +0000 (14:01 +0200)
creating the tooltip element on the fly, never reusing it.
Use aria-describedby attribute to find the associated tooltip again.
Allows customizing animations much easier (just replace fadeIn/fadeOut),
still open.
Updated demos and visual test to replace now-missing .widget() method.
Added tooltipClass for that.

demos/tooltip/custom-animation.html
demos/tooltip/index.html
demos/tooltip/tracking.html
tests/visual/tooltip/tooltip.html
ui/jquery.ui.tooltip.js

index a9d0df66e877be50c3bf05d075120beb8fff8607..a9745a06230c26099f9f99b7f93dfa47513dfbec 100644 (file)
        <link type="text/css" href="../demos.css" rel="stylesheet" />
        <script type="text/javascript">
        $(function() {
+               // TODO overhaul this with custom animation API
                $(".demo").tooltip({
                        open: function() {
-                               $(this).tooltip("widget").stop(false, true).hide().slideDown();
+                               $(".ui-tooltip").stop(false, true).hide().slideDown();
                        },
                        close: function() {
-                               $(this).tooltip("widget").stop(false, true).show().slideUp();
+                               $(".ui-tooltip").stop(false, false).show().slideUp(function() {
+                                       $(this).remove();
+                               });
                        }
                });
        });
index 6bc9c1e5c76c6a518d9de92a4b348e796c6717ff..3563350c5eb4a4e4ed1145893948dbe8db60cfc0 100644 (file)
@@ -14,6 +14,7 @@
                <li><a href="tracking.html">Track the mouse</a></li>
                <li><a href="custom-animation.html">Custom animation</a></li>
                <li><a href="delegation-mixbag.html">Delegation Mixbag</a></li>
+               <li><a href="lots.html">Lots</a></li>
        </ul>
 </div>
 
index e3bb19e7463d959d17a7aa621169997a623cb688..dd5dc9d92021b21ff911a4031773fedfab922a2c 100644 (file)
        $(function() {
                $(".demo").tooltip({
                        open: function() {
-                               var tooltip = $(this).tooltip("widget");
-                               $(document).mousemove(function(event) {
-                                       tooltip.position({
-                                               my: "left center",
-                                               at: "right center",
-                                               offset: "25 25",
+                               var tooltip = $( ".ui-tooltip" );
+                               $(document).mousemove(function( event ) {
+                                       tooltip.position( {
+                                               my: "left+25 center",
+                                               at: "right+25 center",
                                                of: event
                                        });
                                })
@@ -26,7 +25,7 @@
                                .mousemove();
                        },
                        close: function() {
-                               $(document).unbind("mousemove");
+                               $(document).unbind( "mousemove" );
                        }
                });
        });
index 538b43804fbf96eebc28ddaca9723148ae4d9d7d..70c850b60678e4348969e2a430716b3019b91493 100644 (file)
@@ -10,7 +10,9 @@
        <script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script>
        <script type="text/javascript" src="../../../ui/jquery.ui.button.js"></script>
        <script type="text/javascript" src="../../../ui/jquery.ui.tooltip.js"></script>
+       <!--
        <script type="text/javascript" src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
+       -->
        <script type="text/javascript">
        $(function() {
                $.fn.themeswitcher && $('<div/>').css({
                        right: 10,
                        top: 10
                }).appendTo(document.body).themeswitcher();
-               
+
                function enable() {
                        // default
                        $("#context1, form, #childish").tooltip();
                        
                        // custom class, replaces ui-widget-content
-                       $("#context2").tooltip().each(function() {
-                               $(this).tooltip("widget").addClass("ui-widget-header");
-                       })
-                       $("#right1").tooltip().tooltip("widget").addClass("ui-state-error");
+                       $("#context2").tooltip({
+                               tooltipClass: "ui-widget-header"
+                       });
+                       $("#right1").tooltip({
+                               tooltipClass: "ui-state-error"
+                       });
                        
                        // synchronous content
                        $("#footnotes").tooltip({
-                               items: "[href^=#]",
+                               items: "[href^='#']",
                                content: function() {
                                        return $($(this).attr("href")).html();
                                }
                        
                        // custom position
                        $("#right2").tooltip({
+                               tooltipClass: "ui-state-highlight",
                                position: {
                                        my: "center top",
                                        at: "center bottom",
                                        offset: "0 10"
                                }
-                       }).tooltip("widget").addClass("ui-state-highlight");
+                       });
                        
                        $("#button1").button();
                        $("#button2").button({
                enable();
                
                $("#disable").toggle(function() {
-                       $("*").tooltip("disable");
+                       $(":ui-tooltip").tooltip("disable");
                }, function() {
-                       $("*").tooltip("enable");
+                       $(":ui-tooltip").tooltip("enable");
                });
                $("#toggle").toggle(function() {
-                       $("*").tooltip("destroy");
+                       $(":ui-tooltip").tooltip("destroy");
                }, function() {
                        enable();
                });
index 9b4d52bd1821f8d224f1eef91660e018662fa5fe..534b3c94780b1440c07dce6617da28fcdbb59d4d 100644 (file)
@@ -18,9 +18,10 @@ var increments = 0;
 
 $.widget("ui.tooltip", {
        options: {
+               tooltipClass: null,
                items: "[title]",
                content: function() {
-                       return $(this).attr("title");
+                       return $( this ).attr( "title" );
                },
                position: {
                        my: "left center",
@@ -29,25 +30,10 @@ $.widget("ui.tooltip", {
                }
        },
        _create: function() {
-               var self = this;
-               this.tooltip = $("<div></div>")
-                       .attr("id", "ui-tooltip-" + increments++)
-                       .attr("role", "tooltip")
-                       .attr("aria-hidden", "true")
-                       .addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content")
-                       .appendTo(document.body)
-                       .hide();
-               this.tooltipContent = $("<div></div>")
-                       .addClass("ui-tooltip-content")
-                       .appendTo(this.tooltip);
-               this.opacity = this.tooltip.css("opacity");
-               this.element
-                       .bind("focus.tooltip mouseover.tooltip", function(event) {
-                               self.open( event );
-                       })
-                       .bind("blur.tooltip mouseout.tooltip", function(event) {
-                               self.close( event );
-                       });
+               this._bind( {
+                       mouseover: "open",
+                       focusin: "open"
+               });
        },
        
        enable: function() {
@@ -55,34 +41,28 @@ $.widget("ui.tooltip", {
        },
        
        disable: function() {
+               // only set option, disable element style changes
                this.options.disabled = true;
        },
        
-       _destroy: function() {
-               this.tooltip.remove();
-       },
-       
-       widget: function() {
-               return this.element.pushStack(this.tooltip.get());
-       },
-       
        open: function(event) {
                var target = $(event && event.target || this.element).closest(this.options.items);
                if ( !target.length ) {
                        return;
                }
-               // already visible? possible when both focus and mouseover events occur
-               if (this.current && this.current[0] == target[0])
-                       return;
                var self = this;
-               this.current = target;
-               this.currentTitle = target.attr("title");
+               if ( !target.data("tooltip-title") ) {
+                       target.data("tooltip-title", target.attr("title"));
+               }
                var content = this.options.content.call(target[0], function(response) {
                        // IE may instantly serve a cached response, need to give it a chance to finish with _open before that
                        setTimeout(function() {
-                               // ignore async responses that come in after the tooltip is already hidden
-                               if (self.current == target)
+                               // when undefined, it got removeAttr, then ignore (ajax response)
+                               // intially its an empty string, so not undefined
+                               // TODO is there a better approach to enable ajax tooltips to have two updates?
+                               if (target.attr( "aria-describedby" ) !== undefined) {
                                        self._open(event, target, response);
+                               }
                        }, 13);
                });
                if (content) {
@@ -90,48 +70,74 @@ $.widget("ui.tooltip", {
                }
        },
        
-       _open: function(event, target, content) {
-               if (!content)
+       _open: function( event, target, content ) {
+               if ( !content )
                        return;
-               
+
                target.attr("title", "");
-               
-               if (this.options.disabled)
+
+               if ( this.options.disabled )
                        return;
-                       
-               this.tooltipContent.html(content);
-               this.tooltip.css({
-                       top: 0,
-                       left: 0
-               }).show().position( $.extend({
+
+               // ajaxy tooltip can update an existing one
+               var tooltip = this._find( target );
+               if (!tooltip.length) {
+                       tooltip = this._tooltip();
+                       target.attr( "aria-describedby", tooltip.attr( "id" ) );
+               }
+               tooltip.find(".ui-tooltip-content").html( content );
+               tooltip.position( $.extend({
                        of: target
-               }, this.options.position )).hide();
-               
-               this.tooltip.attr("aria-hidden", "false");
-               target.attr("aria-describedby", this.tooltip.attr("id"));
+               }, this.options.position ) ).hide();
+
 
-               this.tooltip.stop(false, true).fadeIn();
+               tooltip.fadeIn();
 
                this._trigger( "open", event );
+
+               this._bind( target, {
+                       mouseleave: "close",
+                       blur: "close"
+               });
        },
        
-       close: function(event) {
-               if (!this.current)
-                       return;
-               
-               var current = this.current;
-               this.current = null;
-               current.attr("title", this.currentTitle);
+       close: function( event ) {
+               var target = $( event && event.currentTarget || this.element );
+               target.attr( "title", target.data( "tooltip-title" ) );
                
-               if (this.options.disabled)
+               if ( this.options.disabled )
                        return;
+
+               var tooltip = this._find( target );
+               target.removeAttr( "aria-describedby" );
                
-               current.removeAttr("aria-describedby");
-               this.tooltip.attr("aria-hidden", "true");
+               tooltip.fadeOut( function() {
+                       $( this ).remove();
+               });
                
-               this.tooltip.stop(false, true).fadeOut();
+               target.unbind( "mouseleave.tooltip blur.tooltip" );
                
                this._trigger( "close", event );
+       },
+
+       _tooltip: function() {
+               var tooltip = $( "<div></div>" )
+                       .attr( "id", "ui-tooltip-" + increments++ )
+                       .attr( "role", "tooltip" )
+                       .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content" );
+               if (this.options.tooltipClass) {
+                       tooltip.addClass(this.options.tooltipClass);
+               }
+               $( "<div></div>" )
+                       .addClass( "ui-tooltip-content" )
+                       .appendTo( tooltip );
+               tooltip.appendTo( document.body );
+               return tooltip;
+       },
+
+       _find: function( target ) {
+               var id = target.attr( "aria-describedby" );
+               return id ? $( document.getElementById( id ) ) : $();
        }
 });