fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2011-05-19 06:29 am

[dw-free] Contextual hover menu positioning not always accurate

[commit: http://hg.dwscoalition.org/dw-free/rev/a1a1c6af9228]

http://bugs.dwscoalition.org/show_bug.cgi?id=3684

Replace tooltip.js positioning logic with jquery.ui.position.js, to account
for the positioning not being accurate on some layouts. Also increase
z-index on contextual hover to overcome zindex in fluid measure.

Patch by [personal profile] fu.

Files modified:
  • cgi-bin/LJ/S2/EntryPage.pm
  • cgi-bin/ljlib.pl
  • htdocs/js/jquery.ajaxtip.js
  • htdocs/js/jquery.contextualhover.js
  • htdocs/js/tooltip.dynamic.js
  • htdocs/js/tooltip.dynamic.min.js
  • htdocs/js/tooltip.js
  • htdocs/js/tooltip.min.js
  • htdocs/stc/ajaxtip.css
  • htdocs/stc/contextualhover.css
--------------------------------------------------------------------------------
diff -r 1047502ac1c7 -r a1a1c6af9228 cgi-bin/LJ/S2/EntryPage.pm
--- a/cgi-bin/LJ/S2/EntryPage.pm	Thu May 19 00:38:30 2011 +0800
+++ b/cgi-bin/LJ/S2/EntryPage.pm	Thu May 19 14:28:57 2011 +0800
@@ -385,7 +385,7 @@
             js/jquery.ajaxtip.js
             js/jquery.commentmanage.js
             js/tooltip.js
-            js/tooltip.dynamic.js
+            js/jquery/jquery.ui.position.js
             stc/ajaxtip.css
             stc/popup-form.css
         ) );
diff -r 1047502ac1c7 -r a1a1c6af9228 cgi-bin/ljlib.pl
--- a/cgi-bin/ljlib.pl	Thu May 19 00:38:30 2011 +0800
+++ b/cgi-bin/ljlib.pl	Thu May 19 14:28:57 2011 +0800
@@ -1352,7 +1352,7 @@
 
                     js/jquery.ajaxtip.js
                     js/tooltip.js
-                    js/tooltip.dynamic.js
+                    js/jquery/jquery.ui.position.js
                     stc/ajaxtip.css
 
                     js/jquery.hoverIntent.js
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/jquery.ajaxtip.js
--- a/htdocs/js/jquery.ajaxtip.js	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/js/jquery.ajaxtip.js	Thu May 19 14:28:57 2011 +0800
@@ -29,7 +29,6 @@
                     widget: "ajaxstart"+ns+",ajaxresult"+ns,
                     tooltip: "mouseover,mouseleave"
                 },
-                position: "bottom center",
                 relative: true,
                 effect: "fade",
                 onBeforeShow: function(e) {
@@ -43,11 +42,11 @@
                         tip.empty().append($("<img />", { src: Site.imgprefix + "/ajax-loader.gif" }))
                             .addClass("ajaxresult")
                     }
+
+                    tip.css({position: "absolute", top: "", left: ""})
+                        .position({ my: "left top", at: "left bottom", of: self.element, collision: "fit"})
                 }
             },  self.options.tooltip));
-            if ( self.options.tooltip.dynamic )
-                self.element.dynamic({ classNames: "tip-top tip-right tip-bottom tip-left" });
-
     },
     _init: function() {
         if(this.options.content)
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/jquery.contextualhover.js
--- a/htdocs/js/jquery.contextualhover.js	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/js/jquery.contextualhover.js	Thu May 19 14:28:57 2011 +0800
@@ -79,7 +79,7 @@
             return;
         }
 
-        trigger.ajaxtip({ namespace: "contextualpopup", tooltip: {position: "bottom left",dynamic:false} })
+        trigger.ajaxtip({ namespace: "contextualpopup"})
             .ajaxtip( "load", {
                 endpoint: "ctxpopup",
                 formmethod: "GET",
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/tooltip.dynamic.js
--- a/htdocs/js/tooltip.dynamic.js	Thu May 19 00:38:30 2011 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/**
- * @license 
- * jQuery Tools 1.2.5 / Tooltip Dynamic Positioning
- * 
- * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
- * 
- * http://flowplayer.org/tools/tooltip/dynamic.html
- *
- * Since: July 2009
- * Date:    Wed Sep 22 06:02:10 2010 +0000 
- */
-(function($) { 
-
-	// version number
-	var t = $.tools.tooltip;
-	
-	t.dynamic = {
-		conf: {
-			classNames: "top right bottom left"
-		}
-	};
-		
-	/* 
-	 * See if element is on the viewport. Returns an boolean array specifying which
-	 * edges are hidden. Edges are in following order:
-	 * 
-	 * [top, right, bottom, left]
-	 * 
-	 * For example following return value means that top and right edges are hidden
-	 * 
-	 * [true, true, false, false]
-	 * 
-	 */
-	function getCropping(el) {
-		
-		var w = $(window); 
-		var right = w.width() + w.scrollLeft();
-		var bottom = w.height() + w.scrollTop();		
-		
-		return [
-			el.offset().top <= w.scrollTop(), 						// top
-			right <= el.offset().left + el.width(),				// right
-			bottom <= el.offset().top + el.height(),			// bottom
-			w.scrollLeft() >= el.offset().left 					// left
-		]; 
-	}
-	
-	/*
-		Returns true if all edges of an element are on viewport. false if not
-		
-		@param crop the cropping array returned by getCropping function
-	 */
-	function isVisible(crop) {
-		var i = crop.length;
-		while (i--) {
-			if (crop[i]) { return false; }	
-		}
-		return true;
-	}
-	
-	// dynamic plugin
-	$.fn.dynamic = function(conf) {
-		
-		if (typeof conf == 'number') { conf = {speed: conf}; }
-		
-		conf = $.extend({}, t.dynamic.conf, conf);
-		
-		var cls = conf.classNames.split(/\s/), orig;	
-			
-		this.each(function() {		
-				
-			var api = $(this).tooltip().onBeforeShow(function(e, pos) {				
-
-				// get nessessary variables
-				var tip = this.getTip(), tipConf = this.getConf();  
-
-				/*
-					We store the original configuration and use it to restore back to the original state.
-				*/					
-				if (!orig) {
-					orig = [
-						tipConf.position[0], 
-						tipConf.position[1], 
-						tipConf.offset[0], 
-						tipConf.offset[1], 
-						$.extend({}, tipConf)
-					];
-				}
-				
-				/*
-					display tip in it's default position and by setting visibility to hidden.
-					this way we can check whether it will be on the viewport
-				*/
-				$.extend(tipConf, orig[4]);
-				tipConf.position = [orig[0], orig[1]];
-				tipConf.offset = [orig[2], orig[3]];
-
-				tip.css({
-					visibility: 'hidden',
-					position: 'absolute',
-					top: pos.top,
-					left: pos.left 
-				}).show(); 
-				
-				// now let's see for hidden edges
-				var crop = getCropping(tip);		
-								
-				// possibly alter the configuration
-				if (!isVisible(crop)) {
-					
-					// change the position and add class
-					if (crop[2]) { $.extend(tipConf, conf.top);		tipConf.position[0] = 'top'; 		tip.addClass(cls[0]); }
-					if (crop[3]) { $.extend(tipConf, conf.right);	tipConf.position[1] = 'right'; 	tip.addClass(cls[1]); }					
-					if (crop[0]) { $.extend(tipConf, conf.bottom); 	tipConf.position[0] = 'bottom';	tip.addClass(cls[2]); } 
-					if (crop[1]) { $.extend(tipConf, conf.left);		tipConf.position[1] = 'left'; 	tip.addClass(cls[3]); }					
-					
-					// vertical offset
-					if (crop[0] || crop[2]) { tipConf.offset[0] *= -1; }
-					
-					// horizontal offset
-					if (crop[1] || crop[3]) { tipConf.offset[1] *= -1; }
-				}  
-				
-				tip.css({visibility: 'visible'}).hide();
-		
-			});
-			
-			// restore positioning as soon as possible
-			api.onBeforeShow(function() {
-				var c = this.getConf(), tip = this.getTip();		 
-				setTimeout(function() { 
-					c.position = [orig[0], orig[1]];
-					c.offset = [orig[2], orig[3]];
-				}, 0);
-			});
-			
-			// remove custom class names and restore original effect
-			api.onHide(function() {
-				var tip = this.getTip(); 
-				tip.removeClass(conf.classNames);
-			});
-				
-			ret = api;
-			
-		});
-		
-		return conf.api ? ret : this;
-	};	
-	
-}) (jQuery);
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/tooltip.dynamic.min.js
--- a/htdocs/js/tooltip.dynamic.min.js	Thu May 19 00:38:30 2011 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-/*
- 
- jQuery Tools 1.2.5 / Tooltip Dynamic Positioning
-
- NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
-
- http://flowplayer.org/tools/tooltip/dynamic.html
-
- Since: July 2009
- Date:    Wed Sep 22 06:02:10 2010 +0000 
-*/
-(function(g){function j(a){var c=g(window),d=c.width()+c.scrollLeft(),h=c.height()+c.scrollTop();return[a.offset().top<=c.scrollTop(),d<=a.offset().left+a.width(),h<=a.offset().top+a.height(),c.scrollLeft()>=a.offset().left]}function k(a){for(var c=a.length;c--;)if(a[c])return false;return true}var i=g.tools.tooltip;i.dynamic={conf:{classNames:"top right bottom left"}};g.fn.dynamic=function(a){if(typeof a=="number")a={speed:a};a=g.extend({},i.dynamic.conf,a);var c=a.classNames.split(/\s/),d;this.each(function(){var h=
-g(this).tooltip().onBeforeShow(function(e,f){e=this.getTip();var b=this.getConf();d||(d=[b.position[0],b.position[1],b.offset[0],b.offset[1],g.extend({},b)]);g.extend(b,d[4]);b.position=[d[0],d[1]];b.offset=[d[2],d[3]];e.css({visibility:"hidden",position:"absolute",top:f.top,left:f.left}).show();f=j(e);if(!k(f)){if(f[2]){g.extend(b,a.top);b.position[0]="top";e.addClass(c[0])}if(f[3]){g.extend(b,a.right);b.position[1]="right";e.addClass(c[1])}if(f[0]){g.extend(b,a.bottom);b.position[0]="bottom";e.addClass(c[2])}if(f[1]){g.extend(b,
-a.left);b.position[1]="left";e.addClass(c[3])}if(f[0]||f[2])b.offset[0]*=-1;if(f[1]||f[3])b.offset[1]*=-1}e.css({visibility:"visible"}).hide()});h.onBeforeShow(function(){var e=this.getConf();this.getTip();setTimeout(function(){e.position=[d[0],d[1]];e.offset=[d[2],d[3]]},0)});h.onHide(function(){var e=this.getTip();e.removeClass(a.classNames)});ret=h});return a.api?ret:this}})(jQuery);
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/tooltip.js
--- a/htdocs/js/tooltip.js	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/js/tooltip.js	Thu May 19 14:28:57 2011 +0800
@@ -79,7 +79,7 @@
 		
 	/* calculate tip position relative to the trigger */  	
 	function getPosition(trigger, tip, conf) {	
-
+        return {};
 		
 		// get origin top/left position 
 		var top = conf.relative ? trigger.position().top : trigger.offset().top, 
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/js/tooltip.min.js
--- a/htdocs/js/tooltip.min.js	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/js/tooltip.min.js	Thu May 19 14:28:57 2011 +0800
@@ -9,7 +9,7 @@
  Since: November 2008
  Date:    Wed Sep 22 06:02:10 2010 +0000 
 */
-(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,d=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];d+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))h-=f(window).scrollTop();var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")d-=a/2;if(i=="left")d-=a;return{top:h,left:d}}function u(a,b){var c=this,h=a.add(c),d,i=0,j=
+(function(f){function p(a,b,c){return {};var h=c.relative?a.position().top:a.offset().top,d=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];d+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))h-=f(window).scrollTop();var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")d-=a/2;if(i=="left")d-=a;return{top:h,left:d}}function u(a,b){var c=this,h=a.add(c),d,i=0,j=
 0,m=a.attr("title"),q=a.attr("data-tooltip"),r=o[b.effect],l,s=a.is(":input"),v=s&&a.is(":checkbox, :radio, select, :button, :submit"),t=a.attr("type"),k=b.events[t]||b.events[s?v?"widget":"input":"def"];if(!r)throw'Nonexistent effect "'+b.effect+'"';k=k.split(/,\s*/);if(k.length!=2)throw"Tooltip: bad events configuration for "+t;a.bind(k[0],function(e){clearTimeout(i);if(b.predelay)j=setTimeout(function(){c.show(e)},b.predelay);else c.show(e)}).bind(k[1],function(e){clearTimeout(j);if(b.delay)i=
 setTimeout(function(){c.hide(e)},b.delay);else c.hide(e)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c,{show:function(e){if(!d){if(q)d=f(q);else if(b.tip)d=f(b.tip).eq(0);else if(m)d=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide().append(m);else{d=a.next();d.length||(d=a.parent().next())}if(!d.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;d.stop(true,true);var g=p(a,d,b);b.tip&&d.html(a.data("title"));e=e||f.Event();e.type="onBeforeShow";
 h.trigger(e,[g]);if(e.isDefaultPrevented())return c;g=p(a,d,b);d.css({position:"absolute",top:g.top,left:g.left});l=true;r[0].call(c,function(){e.type="onShow";l="full";h.trigger(e)});g=b.events.tooltip.split(/,\s*/);if(!d.data("__set")){d.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&d.bind(g[1],function(n){n.relatedTarget!=a[0]&&a.trigger(k[1].split(" ")[0])});d.data("__set",true)}return c},hide:function(e){if(!d||!c.isShown())return c;
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/stc/ajaxtip.css
--- a/htdocs/stc/ajaxtip.css	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/stc/ajaxtip.css	Thu May 19 14:28:57 2011 +0800
@@ -1,6 +1,6 @@
 .ajaxtooltip {
     padding: .2em .5em;
-    z-index: 99;
+    z-index: 999;
     text-align: left;
     color: #000;
     background: #fff;
diff -r 1047502ac1c7 -r a1a1c6af9228 htdocs/stc/contextualhover.css
--- a/htdocs/stc/contextualhover.css	Thu May 19 00:38:30 2011 +0800
+++ b/htdocs/stc/contextualhover.css	Thu May 19 14:28:57 2011 +0800
@@ -3,7 +3,7 @@
     margin: 5px 0 0 20px;
     font: normal 11px "Arial", "Verdana", sans-serif !important;
     text-align: left;
-    z-index: 99;
+    z-index: 999;
     }
 
 * html div.ContextualPopup {
--------------------------------------------------------------------------------