thd/web/js/jquery-tooltip/lib/jquery.dimensions.js
changeset 35 94a1dc255022
equal deleted inserted replaced
34:56befcb22751 35:94a1dc255022
       
     1 /* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
       
     2  * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
       
     3  * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
       
     4  *
       
     5  * $LastChangedDate: 2007-06-22 04:38:37 +0200 (Fr, 22 Jun 2007) $
       
     6  * $Rev: 2141 $
       
     7  *
       
     8  * Version: 1.0b2
       
     9  */
       
    10 
       
    11 (function($){
       
    12 
       
    13 // store a copy of the core height and width methods
       
    14 var height = $.fn.height,
       
    15     width  = $.fn.width;
       
    16 
       
    17 $.fn.extend({
       
    18 	/**
       
    19 	 * If used on document, returns the document's height (innerHeight)
       
    20 	 * If used on window, returns the viewport's (window) height
       
    21 	 * See core docs on height() to see what happens when used on an element.
       
    22 	 *
       
    23 	 * @example $("#testdiv").height()
       
    24 	 * @result 200
       
    25 	 *
       
    26 	 * @example $(document).height()
       
    27 	 * @result 800
       
    28 	 *
       
    29 	 * @example $(window).height()
       
    30 	 * @result 400
       
    31 	 *
       
    32 	 * @name height
       
    33 	 * @type Object
       
    34 	 * @cat Plugins/Dimensions
       
    35 	 */
       
    36 	height: function() {
       
    37 		if ( this[0] == window )
       
    38 			return self.innerHeight ||
       
    39 				$.boxModel && document.documentElement.clientHeight || 
       
    40 				document.body.clientHeight;
       
    41 		
       
    42 		if ( this[0] == document )
       
    43 			return Math.max( document.body.scrollHeight, document.body.offsetHeight );
       
    44 		
       
    45 		return height.apply(this, arguments);
       
    46 	},
       
    47 	
       
    48 	/**
       
    49 	 * If used on document, returns the document's width (innerWidth)
       
    50 	 * If used on window, returns the viewport's (window) width
       
    51 	 * See core docs on height() to see what happens when used on an element.
       
    52 	 *
       
    53 	 * @example $("#testdiv").width()
       
    54 	 * @result 200
       
    55 	 *
       
    56 	 * @example $(document).width()
       
    57 	 * @result 800
       
    58 	 *
       
    59 	 * @example $(window).width()
       
    60 	 * @result 400
       
    61 	 *
       
    62 	 * @name width
       
    63 	 * @type Object
       
    64 	 * @cat Plugins/Dimensions
       
    65 	 */
       
    66 	width: function() {
       
    67 		if ( this[0] == window )
       
    68 			return self.innerWidth ||
       
    69 				$.boxModel && document.documentElement.clientWidth ||
       
    70 				document.body.clientWidth;
       
    71 
       
    72 		if ( this[0] == document )
       
    73 			return Math.max( document.body.scrollWidth, document.body.offsetWidth );
       
    74 
       
    75 		return width.apply(this, arguments);
       
    76 	},
       
    77 	
       
    78 	/**
       
    79 	 * Returns the inner height value (without border) for the first matched element.
       
    80 	 * If used on document, returns the document's height (innerHeight)
       
    81 	 * If used on window, returns the viewport's (window) height
       
    82 	 *
       
    83 	 * @example $("#testdiv").innerHeight()
       
    84 	 * @result 800
       
    85 	 *
       
    86 	 * @name innerHeight
       
    87 	 * @type Number
       
    88 	 * @cat Plugins/Dimensions
       
    89 	 */
       
    90 	innerHeight: function() {
       
    91 		return this[0] == window || this[0] == document ?
       
    92 			this.height() :
       
    93 			this.is(':visible') ?
       
    94 				this[0].offsetHeight - num(this, 'borderTopWidth') - num(this, 'borderBottomWidth') :
       
    95 				this.height() + num(this, 'paddingTop') + num(this, 'paddingBottom');
       
    96 	},
       
    97 	
       
    98 	/**
       
    99 	 * Returns the inner width value (without border) for the first matched element.
       
   100 	 * If used on document, returns the document's Width (innerWidth)
       
   101 	 * If used on window, returns the viewport's (window) width
       
   102 	 *
       
   103 	 * @example $("#testdiv").innerWidth()
       
   104 	 * @result 1000
       
   105 	 *
       
   106 	 * @name innerWidth
       
   107 	 * @type Number
       
   108 	 * @cat Plugins/Dimensions
       
   109 	 */
       
   110 	innerWidth: function() {
       
   111 		return this[0] == window || this[0] == document ?
       
   112 			this.width() :
       
   113 			this.is(':visible') ?
       
   114 				this[0].offsetWidth - num(this, 'borderLeftWidth') - num(this, 'borderRightWidth') :
       
   115 				this.width() + num(this, 'paddingLeft') + num(this, 'paddingRight');
       
   116 	},
       
   117 	
       
   118 	/**
       
   119 	 * Returns the outer height value (including border) for the first matched element.
       
   120 	 * Cannot be used on document or window.
       
   121 	 *
       
   122 	 * @example $("#testdiv").outerHeight()
       
   123 	 * @result 1000
       
   124 	 *
       
   125 	 * @name outerHeight
       
   126 	 * @type Number
       
   127 	 * @cat Plugins/Dimensions
       
   128 	 */
       
   129 	outerHeight: function() {
       
   130 		return this[0] == window || this[0] == document ?
       
   131 			this.height() :
       
   132 			this.is(':visible') ?
       
   133 				this[0].offsetHeight :
       
   134 				this.height() + num(this,'borderTopWidth') + num(this, 'borderBottomWidth') + num(this, 'paddingTop') + num(this, 'paddingBottom');
       
   135 	},
       
   136 	
       
   137 	/**
       
   138 	 * Returns the outer width value (including border) for the first matched element.
       
   139 	 * Cannot be used on document or window.
       
   140 	 *
       
   141 	 * @example $("#testdiv").outerHeight()
       
   142 	 * @result 1000
       
   143 	 *
       
   144 	 * @name outerHeight
       
   145 	 * @type Number
       
   146 	 * @cat Plugins/Dimensions
       
   147 	 */
       
   148 	outerWidth: function() {
       
   149 		return this[0] == window || this[0] == document ?
       
   150 			this.width() :
       
   151 			this.is(':visible') ?
       
   152 				this[0].offsetWidth :
       
   153 				this.width() + num(this, 'borderLeftWidth') + num(this, 'borderRightWidth') + num(this, 'paddingLeft') + num(this, 'paddingRight');
       
   154 	},
       
   155 	
       
   156 	/**
       
   157 	 * Returns how many pixels the user has scrolled to the right (scrollLeft).
       
   158 	 * Works on containers with overflow: auto and window/document.
       
   159 	 *
       
   160 	 * @example $("#testdiv").scrollLeft()
       
   161 	 * @result 100
       
   162 	 *
       
   163 	 * @name scrollLeft
       
   164 	 * @type Number
       
   165 	 * @cat Plugins/Dimensions
       
   166 	 */
       
   167 	/**
       
   168 	 * Sets the scrollLeft property and continues the chain.
       
   169 	 * Works on containers with overflow: auto and window/document.
       
   170 	 *
       
   171 	 * @example $("#testdiv").scrollLeft(10).scrollLeft()
       
   172 	 * @result 10
       
   173 	 *
       
   174 	 * @name scrollLeft
       
   175 	 * @param Number value A positive number representing the desired scrollLeft.
       
   176 	 * @type jQuery
       
   177 	 * @cat Plugins/Dimensions
       
   178 	 */
       
   179 	scrollLeft: function(val) {
       
   180 		if ( val != undefined )
       
   181 			// set the scroll left
       
   182 			return this.each(function() {
       
   183 				if (this == window || this == document)
       
   184 					window.scrollTo( val, $(window).scrollTop() );
       
   185 				else
       
   186 					this.scrollLeft = val;
       
   187 			});
       
   188 		
       
   189 		// return the scroll left offest in pixels
       
   190 		if ( this[0] == window || this[0] == document )
       
   191 			return self.pageXOffset ||
       
   192 				$.boxModel && document.documentElement.scrollLeft ||
       
   193 				document.body.scrollLeft;
       
   194 				
       
   195 		return this[0].scrollLeft;
       
   196 	},
       
   197 	
       
   198 	/**
       
   199 	 * Returns how many pixels the user has scrolled to the bottom (scrollTop).
       
   200 	 * Works on containers with overflow: auto and window/document.
       
   201 	 *
       
   202 	 * @example $("#testdiv").scrollTop()
       
   203 	 * @result 100
       
   204 	 *
       
   205 	 * @name scrollTop
       
   206 	 * @type Number
       
   207 	 * @cat Plugins/Dimensions
       
   208 	 */
       
   209 	/**
       
   210 	 * Sets the scrollTop property and continues the chain.
       
   211 	 * Works on containers with overflow: auto and window/document.
       
   212 	 *
       
   213 	 * @example $("#testdiv").scrollTop(10).scrollTop()
       
   214 	 * @result 10
       
   215 	 *
       
   216 	 * @name scrollTop
       
   217 	 * @param Number value A positive number representing the desired scrollTop.
       
   218 	 * @type jQuery
       
   219 	 * @cat Plugins/Dimensions
       
   220 	 */
       
   221 	scrollTop: function(val) {
       
   222 		if ( val != undefined )
       
   223 			// set the scroll top
       
   224 			return this.each(function() {
       
   225 				if (this == window || this == document)
       
   226 					window.scrollTo( $(window).scrollLeft(), val );
       
   227 				else
       
   228 					this.scrollTop = val;
       
   229 			});
       
   230 		
       
   231 		// return the scroll top offset in pixels
       
   232 		if ( this[0] == window || this[0] == document )
       
   233 			return self.pageYOffset ||
       
   234 				$.boxModel && document.documentElement.scrollTop ||
       
   235 				document.body.scrollTop;
       
   236 
       
   237 		return this[0].scrollTop;
       
   238 	},
       
   239 	
       
   240 	/** 
       
   241 	 * Returns the top and left positioned offset in pixels.
       
   242 	 * The positioned offset is the offset between a positioned
       
   243 	 * parent and the element itself.
       
   244 	 *
       
   245 	 * @example $("#testdiv").position()
       
   246 	 * @result { top: 100, left: 100 }
       
   247 	 * 
       
   248 	 * @name position
       
   249 	 * @param Map options Optional settings to configure the way the offset is calculated.
       
   250 	 * @option Boolean margin Should the margin of the element be included in the calculations? False by default.
       
   251 	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
       
   252 	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
       
   253 	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
       
   254 	 *                            chain will not be broken and the result will be assigned to this object.
       
   255 	 * @type Object
       
   256 	 * @cat Plugins/Dimensions
       
   257 	 */
       
   258 	position: function(options, returnObject) {
       
   259 		var elem = this[0], parent = elem.parentNode, op = elem.offsetParent,
       
   260 		    options = $.extend({ margin: false, border: false, padding: false, scroll: false }, options || {}),
       
   261 			x = elem.offsetLeft,
       
   262 			y = elem.offsetTop, 
       
   263 			sl = elem.scrollLeft, 
       
   264 			st = elem.scrollTop;
       
   265 			
       
   266 		// Mozilla and IE do not add the border
       
   267 		if ($.browser.mozilla || $.browser.msie) {
       
   268 			// add borders to offset
       
   269 			x += num(elem, 'borderLeftWidth');
       
   270 			y += num(elem, 'borderTopWidth');
       
   271 		}
       
   272 
       
   273 		if ($.browser.mozilla) {
       
   274 			do {
       
   275 				// Mozilla does not add the border for a parent that has overflow set to anything but visible
       
   276 				if ($.browser.mozilla && parent != elem && $.css(parent, 'overflow') != 'visible') {
       
   277 					x += num(parent, 'borderLeftWidth');
       
   278 					y += num(parent, 'borderTopWidth');
       
   279 				}
       
   280 
       
   281 				if (parent == op) break; // break if we are already at the offestParent
       
   282 			} while ((parent = parent.parentNode) && (parent.tagName.toLowerCase() != 'body' || parent.tagName.toLowerCase() != 'html'));
       
   283 		}
       
   284 		
       
   285 		var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
       
   286 		
       
   287 		if (returnObject) { $.extend(returnObject, returnValue); return this; }
       
   288 		else              { return returnValue; }
       
   289 	},
       
   290 	
       
   291 	/**
       
   292 	 * Returns the location of the element in pixels from the top left corner of the viewport.
       
   293 	 *
       
   294 	 * For accurate readings make sure to use pixel values for margins, borders and padding.
       
   295 	 * 
       
   296 	 * Known issues:
       
   297 	 *  - Issue: A div positioned relative or static without any content before it and its parent will report an offsetTop of 0 in Safari
       
   298 	 *    Workaround: Place content before the relative div ... and set height and width to 0 and overflow to hidden
       
   299 	 *
       
   300 	 * @example $("#testdiv").offset()
       
   301 	 * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
       
   302 	 *
       
   303 	 * @example $("#testdiv").offset({ scroll: false })
       
   304 	 * @result { top: 90, left: 90 }
       
   305 	 *
       
   306 	 * @example var offset = {}
       
   307 	 * $("#testdiv").offset({ scroll: false }, offset)
       
   308 	 * @result offset = { top: 90, left: 90 }
       
   309 	 *
       
   310 	 * @name offset
       
   311 	 * @param Map options Optional settings to configure the way the offset is calculated.
       
   312 	 * @option Boolean margin Should the margin of the element be included in the calculations? True by default.
       
   313 	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
       
   314 	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
       
   315 	 * @option Boolean scroll Should the scroll offsets of the parent elements be included in the calculations? True by default.
       
   316 	 *                        When true it adds the totla scroll offets of all parents to the total offset and also adds two properties
       
   317 	 *                        to the returned object, scrollTop and scrollLeft. 
       
   318 	 * @options Boolean lite Will use offsetLite instead of offset when set to true. False by default.
       
   319 	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
       
   320 	 *                            chain will not be broken and the result will be assigned to this object.
       
   321 	 * @type Object
       
   322 	 * @cat Plugins/Dimensions
       
   323 	 */
       
   324 	offset: function(options, returnObject) {
       
   325 		var x = 0, y = 0, sl = 0, st = 0,
       
   326 		    elem = this[0], parent = this[0], op, parPos, elemPos = $.css(elem, 'position'),
       
   327 		    mo = $.browser.mozilla, ie = $.browser.msie, sf = $.browser.safari, oa = $.browser.opera,
       
   328 		    absparent = false, relparent = false, 
       
   329 		    options = $.extend({ margin: true, border: false, padding: false, scroll: true, lite: false }, options || {});
       
   330 		
       
   331 		// Use offsetLite if lite option is true
       
   332 		if (options.lite) return this.offsetLite(options, returnObject);
       
   333 		
       
   334 		if (elem.tagName.toLowerCase() == 'body') {
       
   335 			// Safari is the only one to get offsetLeft and offsetTop properties of the body "correct"
       
   336 			// Except they all mess up when the body is positioned absolute or relative
       
   337 			x = elem.offsetLeft;
       
   338 			y = elem.offsetTop;
       
   339 			// Mozilla ignores margin and subtracts border from body element
       
   340 			if (mo) {
       
   341 				x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2);
       
   342 				y += num(elem, 'marginTop')  + (num(elem, 'borderTopWidth') *2);
       
   343 			} else
       
   344 			// Opera ignores margin
       
   345 			if (oa) {
       
   346 				x += num(elem, 'marginLeft');
       
   347 				y += num(elem, 'marginTop');
       
   348 			} else
       
   349 			// IE does not add the border in Standards Mode
       
   350 			if (ie && jQuery.boxModel) {
       
   351 				x += num(elem, 'borderLeftWidth');
       
   352 				y += num(elem, 'borderTopWidth');
       
   353 			}
       
   354 		} else {
       
   355 			do {
       
   356 				parPos = $.css(parent, 'position');
       
   357 			
       
   358 				x += parent.offsetLeft;
       
   359 				y += parent.offsetTop;
       
   360 
       
   361 				// Mozilla and IE do not add the border
       
   362 				if (mo || ie) {
       
   363 					// add borders to offset
       
   364 					x += num(parent, 'borderLeftWidth');
       
   365 					y += num(parent, 'borderTopWidth');
       
   366 
       
   367 					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
       
   368 					if (mo && parPos == 'absolute') absparent = true;
       
   369 					// IE does not include the border on the body if an element is position static and without an absolute or relative parent
       
   370 					if (ie && parPos == 'relative') relparent = true;
       
   371 				}
       
   372 
       
   373 				op = parent.offsetParent;
       
   374 				if (options.scroll || mo) {
       
   375 					do {
       
   376 						if (options.scroll) {
       
   377 							// get scroll offsets
       
   378 							sl += parent.scrollLeft;
       
   379 							st += parent.scrollTop;
       
   380 						}
       
   381 				
       
   382 						// Mozilla does not add the border for a parent that has overflow set to anything but visible
       
   383 						if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
       
   384 							x += num(parent, 'borderLeftWidth');
       
   385 							y += num(parent, 'borderTopWidth');
       
   386 						}
       
   387 				
       
   388 						parent = parent.parentNode;
       
   389 					} while (parent != op);
       
   390 				}
       
   391 				parent = op;
       
   392 
       
   393 				if (parent.tagName.toLowerCase() == 'body' || parent.tagName.toLowerCase() == 'html') {
       
   394 					// Safari and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
       
   395 					if ((sf || (ie && $.boxModel)) && elemPos != 'absolute' && elemPos != 'fixed') {
       
   396 						x += num(parent, 'marginLeft');
       
   397 						y += num(parent, 'marginTop');
       
   398 					}
       
   399 					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
       
   400 					// IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
       
   401 					if ( (mo && !absparent && elemPos != 'fixed') || 
       
   402 					     (ie && elemPos == 'static' && !relparent) ) {
       
   403 						x += num(parent, 'borderLeftWidth');
       
   404 						y += num(parent, 'borderTopWidth');
       
   405 					}
       
   406 					break; // Exit the loop
       
   407 				}
       
   408 			} while (parent);
       
   409 		}
       
   410 
       
   411 		var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
       
   412 
       
   413 		if (returnObject) { $.extend(returnObject, returnValue); return this; }
       
   414 		else              { return returnValue; }
       
   415 	},
       
   416 	
       
   417 	/**
       
   418 	 * Returns the location of the element in pixels from the top left corner of the viewport.
       
   419 	 * This method is much faster than offset but not as accurate. This method can be invoked
       
   420 	 * by setting the lite option to true in the offset method.
       
   421 	 *
       
   422 	 * @name offsetLite
       
   423 	 * @param Map options Optional settings to configure the way the offset is calculated.
       
   424 	 * @option Boolean margin Should the margin of the element be included in the calculations? True by default.
       
   425 	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
       
   426 	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
       
   427 	 * @option Boolean scroll Should the scroll offsets of the parent elements be included in the calculations? True by default.
       
   428 	 *                        When true it adds the totla scroll offets of all parents to the total offset and also adds two properties
       
   429 	 *                        to the returned object, scrollTop and scrollLeft. 
       
   430 	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
       
   431 	 *                            chain will not be broken and the result will be assigned to this object.
       
   432 	 * @type Object
       
   433 	 * @cat Plugins/Dimensions
       
   434 	 */
       
   435 	offsetLite: function(options, returnObject) {
       
   436 		var x = 0, y = 0, sl = 0, st = 0, parent = this[0], op, 
       
   437 		    options = $.extend({ margin: true, border: false, padding: false, scroll: true }, options || {});
       
   438 				
       
   439 		do {
       
   440 			x += parent.offsetLeft;
       
   441 			y += parent.offsetTop;
       
   442 
       
   443 			op = parent.offsetParent;
       
   444 			if (options.scroll) {
       
   445 				// get scroll offsets
       
   446 				do {
       
   447 					sl += parent.scrollLeft;
       
   448 					st += parent.scrollTop;
       
   449 					parent = parent.parentNode;
       
   450 				} while(parent != op);
       
   451 			}
       
   452 			parent = op;
       
   453 		} while (parent && parent.tagName.toLowerCase() != 'body' && parent.tagName.toLowerCase() != 'html');
       
   454 
       
   455 		var returnValue = handleOffsetReturn(this[0], options, x, y, sl, st);
       
   456 
       
   457 		if (returnObject) { $.extend(returnObject, returnValue); return this; }
       
   458 		else              { return returnValue; }
       
   459 	}
       
   460 });
       
   461 
       
   462 /**
       
   463  * Handles converting a CSS Style into an Integer.
       
   464  * @private
       
   465  */
       
   466 var num = function(el, prop) {
       
   467 	return parseInt($.css(el.jquery?el[0]:el,prop))||0;
       
   468 };
       
   469 
       
   470 /**
       
   471  * Handles the return value of the offset and offsetLite methods.
       
   472  * @private
       
   473  */
       
   474 var handleOffsetReturn = function(elem, options, x, y, sl, st) {
       
   475 	if ( !options.margin ) {
       
   476 		x -= num(elem, 'marginLeft');
       
   477 		y -= num(elem, 'marginTop');
       
   478 	}
       
   479 
       
   480 	// Safari and Opera do not add the border for the element
       
   481 	if ( options.border && ($.browser.safari || $.browser.opera) ) {
       
   482 		x += num(elem, 'borderLeftWidth');
       
   483 		y += num(elem, 'borderTopWidth');
       
   484 	} else if ( !options.border && !($.browser.safari || $.browser.opera) ) {
       
   485 		x -= num(elem, 'borderLeftWidth');
       
   486 		y -= num(elem, 'borderTopWidth');
       
   487 	}
       
   488 
       
   489 	if ( options.padding ) {
       
   490 		x += num(elem, 'paddingLeft');
       
   491 		y += num(elem, 'paddingTop');
       
   492 	}
       
   493 	
       
   494 	// do not include scroll offset on the element
       
   495 	if ( options.scroll ) {
       
   496 		sl -= elem.scrollLeft;
       
   497 		st -= elem.scrollTop;
       
   498 	}
       
   499 
       
   500 	return options.scroll ? { top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl }
       
   501 	                      : { top: y, left: x };
       
   502 };
       
   503 
       
   504 })(jQuery);