6a7d20a77e012d4b074d24afa9670daeb043a256
[jquery.git] / src / dimensions / dimensions.js
1 /** \r
2  * This plugin overrides jQuery's height() and width() functions and\r
3  * adds more handy stuff for cross-browser compatibility.\r
4  */\r
5 \r
6 /**\r
7  * Returns the css height value for the first matched element.\r
8  * If used on document, returns the document's height (innerHeight)\r
9  * If used on window, returns the viewport's (window) height\r
10  *\r
11  * @example $("#testdiv").height()\r
12  * @result "200px"\r
13  *\r
14  * @example $(document).height();\r
15  * @result 800\r
16  *\r
17  * @example $(window).height();\r
18  * @result 400\r
19  * \r
20  * @name height\r
21  * @type Object\r
22  * @cat Dimensions\r
23  */\r
24 jQuery.fn.height = function() {\r
25         if ( this.get(0) == window )\r
26                 return self.innerHeight ||\r
27                         jQuery.boxModel && document.documentElement.clientHeight ||\r
28                         document.body.clientHeight;\r
29         \r
30         if ( this.get(0) == document )\r
31                 return Math.max( document.body.scrollHeight, document.body.offsetHeight );\r
32         \r
33         return this.css("height");\r
34 };\r
35 \r
36 /**\r
37  * Returns the css width value for the first matched element.\r
38  * If used on document, returns the document's width (innerWidth)\r
39  * If used on window, returns the viewport's (window) width\r
40  *\r
41  * @example $("#testdiv").width()\r
42  * @result "200px"\r
43  *\r
44  * @example $(document).width();\r
45  * @result 800\r
46  *\r
47  * @example $(window).width();\r
48  * @result 400\r
49  * \r
50  * @name width\r
51  * @type Object\r
52  * @cat Dimensions\r
53  */\r
54 jQuery.fn.width = function() {\r
55         if ( this.get(0) == window )\r
56                 return self.innerWidth ||\r
57                         jQuery.boxModel && document.documentElement.clientWidth ||\r
58                         document.body.clientWidth;\r
59         \r
60         if ( this.get(0) == document )\r
61                 return Math.max( document.body.scrollWidth, document.body.offsetWidth );\r
62         \r
63         return this.css("width");\r
64 };\r
65 \r
66 /**\r
67  * Returns the inner height value (without border) for the first matched element.\r
68  * If used on document, returns the document's height (innerHeight)\r
69  * If used on window, returns the viewport's (window) height\r
70  *\r
71  * @example $("#testdiv").innerHeight()\r
72  * @result 800\r
73  * \r
74  * @name innerHeight\r
75  * @type Number\r
76  * @cat Dimensions\r
77  */\r
78 jQuery.fn.innerHeight = function() {\r
79         return this.get(0) == window || this.get(0) == document ?\r
80                 this.height() :\r
81                 this.get(0).offsetHeight - parseInt(this.css("borderTop") || 0) - parseInt(this.css("borderBottom") || 0);\r
82 };\r
83 \r
84 /**\r
85  * Returns the inner width value (without border) for the first matched element.\r
86  * If used on document, returns the document's Width (innerWidth)\r
87  * If used on window, returns the viewport's (window) width\r
88  *\r
89  * @example $("#testdiv").innerWidth()\r
90  * @result 1000\r
91  * \r
92  * @name innerWidth\r
93  * @type Number\r
94  * @cat Dimensions\r
95  */\r
96 jQuery.fn.innerWidth = function() {\r
97         return this.get(0) == window || this.get(0) == document ?\r
98                 this.width() :\r
99                 this.get(0).offsetWidth - parseInt(this.css("borderLeft") || 0) - parseInt(this.css("borderRight") || 0);\r
100 };\r
101 \r
102 /**\r
103  * Returns the outer height value (including border) for the first matched element.\r
104  * Cannot be used on document or window.\r
105  *\r
106  * @example $("#testdiv").outerHeight()\r
107  * @result 1000\r
108  * \r
109  * @name outerHeight\r
110  * @type Number\r
111  * @cat Dimensions\r
112  */\r
113 jQuery.fn.outerHeight = function() {\r
114         return this.get(0) == window || this.get(0) == document ?\r
115                 this.height() :\r
116                 this.get(0).offsetHeight;       \r
117 };\r
118 \r
119 /**\r
120  * Returns the outer width value (including border) for the first matched element.\r
121  * Cannot be used on document or window.\r
122  *\r
123  * @example $("#testdiv").outerWidth()\r
124  * @result 1000\r
125  * \r
126  * @name outerWidth\r
127  * @type Number\r
128  * @cat Dimensions\r
129  */\r
130 jQuery.fn.outerWidth = function() {\r
131         return this.get(0) == window || this.get(0) == document ?\r
132                 this.width() :\r
133                 this.get(0).offsetWidth;        \r
134 };\r
135 \r
136 /**\r
137  * Returns how many pixels the user has scrolled to the right (scrollLeft).\r
138  * Works on containers with overflow: auto and window/document.\r
139  *\r
140  * @example $("#testdiv").scrollLeft()\r
141  * @result 100\r
142  * \r
143  * @name scrollLeft\r
144  * @type Number\r
145  * @cat Dimensions\r
146  */\r
147 jQuery.fn.scrollLeft = function() {\r
148         if ( this.get(0) == window || this.get(0) == document )\r
149                 return self.pageXOffset ||\r
150                         jQuery.boxModel && document.documentElement.scrollLeft ||\r
151                         document.body.scrollLeft;\r
152         \r
153         return this.get(0).scrollLeft;\r
154 };\r
155 \r
156 /**\r
157  * Returns how many pixels the user has scrolled to the bottom (scrollTop).\r
158  * Works on containers with overflow: auto and window/document.\r
159  *\r
160  * @example $("#testdiv").scrollTop()\r
161  * @result 100\r
162  * \r
163  * @name scrollTop\r
164  * @type Number\r
165  * @cat Dimensions\r
166  */\r
167 jQuery.fn.scrollTop = function() {\r
168         if ( this.get(0) == window || this.get(0) == document )\r
169                 return self.pageYOffset ||\r
170                         jQuery.boxModel && document.documentElement.scrollTop ||\r
171                         document.body.scrollTop;\r
172 \r
173         return this.get(0).scrollTop;\r
174 };\r
175 \r
176 /**\r
177  * This returns an object with top, left, width, height, borderLeft,\r
178  * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, \r
179  * pageXOffset, pageYOffset.\r
180  *\r
181  * The top and left values include the scroll offsets but the\r
182  * scrollLeft and scrollTop properties of the returned object\r
183  * are the combined scroll offets of the parent elements \r
184  * (not including the window scroll offsets). This is not the\r
185  * same as the element's scrollTop and scrollLeft.\r
186  * \r
187  * For accurate readings make sure to use pixel values.\r
188  *\r
189  * @name offset \r
190  * @type Object\r
191  * @cat Dimensions\r
192  * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)\r
193  */\r
194 /**\r
195  * This returns an object with top, left, width, height, borderLeft,\r
196  * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, \r
197  * pageXOffset, pageYOffset.\r
198  *\r
199  * The top and left values include the scroll offsets but the\r
200  * scrollLeft and scrollTop properties of the returned object\r
201  * are the combined scroll offets of the parent elements \r
202  * (not including the window scroll offsets). This is not the\r
203  * same as the element's scrollTop and scrollLeft.\r
204  * \r
205  * For accurate readings make sure to use pixel values.\r
206  *\r
207  * @name offset \r
208  * @type Object\r
209  * @param String refElement This is an expression. The offset returned will be relative to the first matched element.\r
210  * @cat Dimensions\r
211  * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)\r
212  */\r
213 /**\r
214  * This returns an object with top, left, width, height, borderLeft,\r
215  * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, \r
216  * pageXOffset, pageYOffset.\r
217  *\r
218  * The top and left values include the scroll offsets but the\r
219  * scrollLeft and scrollTop properties of the returned object\r
220  * are the combined scroll offets of the parent elements \r
221  * (not including the window scroll offsets). This is not the\r
222  * same as the element's scrollTop and scrollLeft.\r
223  * \r
224  * For accurate readings make sure to use pixel values.\r
225  *\r
226  * @name offset \r
227  * @type Object\r
228  * @param jQuery refElement The offset returned will be relative to the first matched element.\r
229  * @cat Dimensions\r
230  * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)\r
231  */\r
232 /**\r
233  * This returns an object with top, left, width, height, borderLeft,\r
234  * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, \r
235  * pageXOffset, pageYOffset.\r
236  *\r
237  * The top and left values include the scroll offsets but the\r
238  * scrollLeft and scrollTop properties of the returned object\r
239  * are the combined scroll offets of the parent elements \r
240  * (not including the window scroll offsets). This is not the\r
241  * same as the element's scrollTop and scrollLeft.\r
242  * \r
243  * For accurate readings make sure to use pixel values.\r
244  *\r
245  * @name offset \r
246  * @type Object\r
247  * @param HTMLElement refElement The offset returned will be relative to this element.\r
248  * @cat Dimensions\r
249  * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)\r
250  */\r
251 jQuery.fn.offset = function(refElem) {\r
252         if (!this[0]) throw 'jQuery.fn.offset requires an element.';\r
253         \r
254         refElem = (refElem) ? jQuery(refElem)[0] : null;\r
255         var x = 0, y = 0, elm = this[0], parent = this[0], pos = null, borders = [0,0], isElm = true, sl = 0, st = 0;\r
256         do {\r
257                 if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {\r
258                         // Safari and IE don't add margin for static and relative\r
259                         if ((jQuery.browser.safari || jQuery.browser.msie) && pos != 'absolute') {\r
260                                 x += parseInt(jQuery.css(parent, 'marginLeft')) || 0;\r
261                                 y += parseInt(jQuery.css(parent, 'marginTop'))  || 0;\r
262                         }\r
263                         break;\r
264                 }\r
265                 \r
266                 pos    = jQuery.css(parent, 'position');\r
267                 border = [parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0,\r
268                                                         parseInt(jQuery.css(parent, 'borderTopWidth'))  || 0];\r
269                 sl = parent.scrollLeft;\r
270                 st = parent.scrollTop;\r
271                 \r
272                 x += (parent.offsetLeft || 0) + border[0] - sl;\r
273                 y += (parent.offsetTop  || 0) + border[1] - st;\r
274                 \r
275                 // Safari and Opera include the border already for parents with position = absolute|relative\r
276                 if ((jQuery.browser.safari || jQuery.browser.opera) && !isElm && (pos == 'absolute' || pos == 'relative')) {\r
277                         x -= border[0];\r
278                         y -= border[1];\r
279                 }\r
280                 \r
281                 parent = parent.offsetParent;\r
282                 isElm  = false;\r
283         } while(parent);\r
284         \r
285         if (refElem) {\r
286                 var offset = jQuery(refElem).offset();\r
287                 x  = x  - offset.left;\r
288                 y  = y  - offset.top;\r
289                 sl = sl - offset.scrollLeft;\r
290                 st = st - offset.scrollTop;\r
291         }\r
292         \r
293         return {\r
294                 top:  y,\r
295                 left: x,\r
296                 width:  elm.offsetWidth,\r
297                 height: elm.offsetHeight,\r
298                 borderTop:  parseInt(jQuery.css(elm, 'borderTopWidth'))  || 0,\r
299                 borderLeft: parseInt(jQuery.css(elm, 'borderLeftWidth')) || 0,\r
300                 marginTop:  parseInt(jQuery.css(elm, 'marginTopWidth'))  || 0,\r
301                 marginLeft: parseInt(jQuery.css(elm, 'marginLeftWidth')) || 0,\r
302                 scrollTop:  st,\r
303                 scrollLeft: sl,\r
304                 pageYOffset: window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop  || 0,\r
305                 pageXOffset: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0\r
306         };\r
307 };