]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/dom-geometry.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dojo / dom-geometry.js.uncompressed.js
1 define("dojo/dom-geometry", ["./sniff", "./_base/window","./dom", "./dom-style"],
2 function(has, win, dom, style){
3 // module:
4 // dojo/dom-geometry
5
6 // the result object
7 var geom = {
8 // summary:
9 // This module defines the core dojo DOM geometry API.
10 };
11
12 // Box functions will assume this model.
13 // On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
14 // Can be set to change behavior of box setters.
15
16 // can be either:
17 // "border-box"
18 // "content-box" (default)
19 geom.boxModel = "content-box";
20
21 // We punt per-node box mode testing completely.
22 // If anybody cares, we can provide an additional (optional) unit
23 // that overrides existing code to include per-node box sensitivity.
24
25 // Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
26 // but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
27 // IIRC, earlier versions of Opera did in fact use border-box.
28 // Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
29
30 if(has("ie") /*|| has("opera")*/){
31 // client code may have to adjust if compatMode varies across iframes
32 geom.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box";
33 }
34
35 geom.getPadExtents = function getPadExtents(/*DomNode*/ node, /*Object*/ computedStyle){
36 // summary:
37 // Returns object with special values specifically useful for node
38 // fitting.
39 // description:
40 // Returns an object with `w`, `h`, `l`, `t` properties:
41 // | l/t/r/b = left/top/right/bottom padding (respectively)
42 // | w = the total of the left and right padding
43 // | h = the total of the top and bottom padding
44 // If 'node' has position, l/t forms the origin for child nodes.
45 // The w/h are used for calculating boxes.
46 // Normally application code will not need to invoke this
47 // directly, and will use the ...box... functions instead.
48 // node: DOMNode
49 // computedStyle: Object?
50 // This parameter accepts computed styles object.
51 // If this parameter is omitted, the functions will call
52 // dojo.getComputedStyle to get one. It is a better way, calling
53 // dojo.computedStyle once, and then pass the reference to this
54 // computedStyle parameter. Wherever possible, reuse the returned
55 // object of dojo/dom-style.getComputedStyle().
56
57 node = dom.byId(node);
58 var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue,
59 l = px(node, s.paddingLeft), t = px(node, s.paddingTop), r = px(node, s.paddingRight), b = px(node, s.paddingBottom);
60 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
61 };
62
63 var none = "none";
64
65 geom.getBorderExtents = function getBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){
66 // summary:
67 // returns an object with properties useful for noting the border
68 // dimensions.
69 // description:
70 // - l/t/r/b = the sum of left/top/right/bottom border (respectively)
71 // - w = the sum of the left and right border
72 // - h = the sum of the top and bottom border
73 //
74 // The w/h are used for calculating boxes.
75 // Normally application code will not need to invoke this
76 // directly, and will use the ...box... functions instead.
77 // node: DOMNode
78 // computedStyle: Object?
79 // This parameter accepts computed styles object.
80 // If this parameter is omitted, the functions will call
81 // dojo.getComputedStyle to get one. It is a better way, calling
82 // dojo.computedStyle once, and then pass the reference to this
83 // computedStyle parameter. Wherever possible, reuse the returned
84 // object of dojo/dom-style.getComputedStyle().
85
86 node = dom.byId(node);
87 var px = style.toPixelValue, s = computedStyle || style.getComputedStyle(node),
88 l = s.borderLeftStyle != none ? px(node, s.borderLeftWidth) : 0,
89 t = s.borderTopStyle != none ? px(node, s.borderTopWidth) : 0,
90 r = s.borderRightStyle != none ? px(node, s.borderRightWidth) : 0,
91 b = s.borderBottomStyle != none ? px(node, s.borderBottomWidth) : 0;
92 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
93 };
94
95 geom.getPadBorderExtents = function getPadBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){
96 // summary:
97 // Returns object with properties useful for box fitting with
98 // regards to padding.
99 // description:
100 // - l/t/r/b = the sum of left/top/right/bottom padding and left/top/right/bottom border (respectively)
101 // - w = the sum of the left and right padding and border
102 // - h = the sum of the top and bottom padding and border
103 //
104 // The w/h are used for calculating boxes.
105 // Normally application code will not need to invoke this
106 // directly, and will use the ...box... functions instead.
107 // node: DOMNode
108 // computedStyle: Object?
109 // This parameter accepts computed styles object.
110 // If this parameter is omitted, the functions will call
111 // dojo.getComputedStyle to get one. It is a better way, calling
112 // dojo.computedStyle once, and then pass the reference to this
113 // computedStyle parameter. Wherever possible, reuse the returned
114 // object of dojo/dom-style.getComputedStyle().
115
116 node = dom.byId(node);
117 var s = computedStyle || style.getComputedStyle(node),
118 p = geom.getPadExtents(node, s),
119 b = geom.getBorderExtents(node, s);
120 return {
121 l: p.l + b.l,
122 t: p.t + b.t,
123 r: p.r + b.r,
124 b: p.b + b.b,
125 w: p.w + b.w,
126 h: p.h + b.h
127 };
128 };
129
130 geom.getMarginExtents = function getMarginExtents(node, computedStyle){
131 // summary:
132 // returns object with properties useful for box fitting with
133 // regards to box margins (i.e., the outer-box).
134 //
135 // - l/t = marginLeft, marginTop, respectively
136 // - w = total width, margin inclusive
137 // - h = total height, margin inclusive
138 //
139 // The w/h are used for calculating boxes.
140 // Normally application code will not need to invoke this
141 // directly, and will use the ...box... functions instead.
142 // node: DOMNode
143 // computedStyle: Object?
144 // This parameter accepts computed styles object.
145 // If this parameter is omitted, the functions will call
146 // dojo.getComputedStyle to get one. It is a better way, calling
147 // dojo.computedStyle once, and then pass the reference to this
148 // computedStyle parameter. Wherever possible, reuse the returned
149 // object of dojo/dom-style.getComputedStyle().
150
151 node = dom.byId(node);
152 var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue,
153 l = px(node, s.marginLeft), t = px(node, s.marginTop), r = px(node, s.marginRight), b = px(node, s.marginBottom);
154 return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
155 };
156
157 // Box getters work in any box context because offsetWidth/clientWidth
158 // are invariant wrt box context
159 //
160 // They do *not* work for display: inline objects that have padding styles
161 // because the user agent ignores padding (it's bogus styling in any case)
162 //
163 // Be careful with IMGs because they are inline or block depending on
164 // browser and browser mode.
165
166 // Although it would be easier to read, there are not separate versions of
167 // _getMarginBox for each browser because:
168 // 1. the branching is not expensive
169 // 2. factoring the shared code wastes cycles (function call overhead)
170 // 3. duplicating the shared code wastes bytes
171
172 geom.getMarginBox = function getMarginBox(/*DomNode*/ node, /*Object*/ computedStyle){
173 // summary:
174 // returns an object that encodes the width, height, left and top
175 // positions of the node's margin box.
176 // node: DOMNode
177 // computedStyle: Object?
178 // This parameter accepts computed styles object.
179 // If this parameter is omitted, the functions will call
180 // dojo.getComputedStyle to get one. It is a better way, calling
181 // dojo.computedStyle once, and then pass the reference to this
182 // computedStyle parameter. Wherever possible, reuse the returned
183 // object of dojo/dom-style.getComputedStyle().
184
185 node = dom.byId(node);
186 var s = computedStyle || style.getComputedStyle(node), me = geom.getMarginExtents(node, s),
187 l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode, px = style.toPixelValue, pcs;
188 if(has("mozilla")){
189 // Mozilla:
190 // If offsetParent has a computed overflow != visible, the offsetLeft is decreased
191 // by the parent's border.
192 // We don't want to compute the parent's style, so instead we examine node's
193 // computed left/top which is more stable.
194 var sl = parseFloat(s.left), st = parseFloat(s.top);
195 if(!isNaN(sl) && !isNaN(st)){
196 l = sl;
197 t = st;
198 }else{
199 // If child's computed left/top are not parseable as a number (e.g. "auto"), we
200 // have no choice but to examine the parent's computed style.
201 if(p && p.style){
202 pcs = style.getComputedStyle(p);
203 if(pcs.overflow != "visible"){
204 l += pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0;
205 t += pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0;
206 }
207 }
208 }
209 }else if(has("opera") || (has("ie") == 8 && !has("quirks"))){
210 // On Opera and IE 8, offsetLeft/Top includes the parent's border
211 if(p){
212 pcs = style.getComputedStyle(p);
213 l -= pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0;
214 t -= pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0;
215 }
216 }
217 return {l: l, t: t, w: node.offsetWidth + me.w, h: node.offsetHeight + me.h};
218 };
219
220 geom.getContentBox = function getContentBox(node, computedStyle){
221 // summary:
222 // Returns an object that encodes the width, height, left and top
223 // positions of the node's content box, irrespective of the
224 // current box model.
225 // node: DOMNode
226 // computedStyle: Object?
227 // This parameter accepts computed styles object.
228 // If this parameter is omitted, the functions will call
229 // dojo.getComputedStyle to get one. It is a better way, calling
230 // dojo.computedStyle once, and then pass the reference to this
231 // computedStyle parameter. Wherever possible, reuse the returned
232 // object of dojo/dom-style.getComputedStyle().
233
234 // clientWidth/Height are important since the automatically account for scrollbars
235 // fallback to offsetWidth/Height for special cases (see #3378)
236 node = dom.byId(node);
237 var s = computedStyle || style.getComputedStyle(node), w = node.clientWidth, h,
238 pe = geom.getPadExtents(node, s), be = geom.getBorderExtents(node, s);
239 if(!w){
240 w = node.offsetWidth;
241 h = node.offsetHeight;
242 }else{
243 h = node.clientHeight;
244 be.w = be.h = 0;
245 }
246 // On Opera, offsetLeft includes the parent's border
247 if(has("opera")){
248 pe.l += be.l;
249 pe.t += be.t;
250 }
251 return {l: pe.l, t: pe.t, w: w - pe.w - be.w, h: h - pe.h - be.h};
252 };
253
254 // Box setters depend on box context because interpretation of width/height styles
255 // vary wrt box context.
256 //
257 // The value of boxModel is used to determine box context.
258 // boxModel can be set directly to change behavior.
259 //
260 // Beware of display: inline objects that have padding styles
261 // because the user agent ignores padding (it's a bogus setup anyway)
262 //
263 // Be careful with IMGs because they are inline or block depending on
264 // browser and browser mode.
265 //
266 // Elements other than DIV may have special quirks, like built-in
267 // margins or padding, or values not detectable via computedStyle.
268 // In particular, margins on TABLE do not seems to appear
269 // at all in computedStyle on Mozilla.
270
271 function setBox(/*DomNode*/ node, /*Number?*/ l, /*Number?*/ t, /*Number?*/ w, /*Number?*/ h, /*String?*/ u){
272 // summary:
273 // sets width/height/left/top in the current (native) box-model
274 // dimensions. Uses the unit passed in u.
275 // node:
276 // DOM Node reference. Id string not supported for performance
277 // reasons.
278 // l:
279 // left offset from parent.
280 // t:
281 // top offset from parent.
282 // w:
283 // width in current box model.
284 // h:
285 // width in current box model.
286 // u:
287 // unit measure to use for other measures. Defaults to "px".
288 u = u || "px";
289 var s = node.style;
290 if(!isNaN(l)){
291 s.left = l + u;
292 }
293 if(!isNaN(t)){
294 s.top = t + u;
295 }
296 if(w >= 0){
297 s.width = w + u;
298 }
299 if(h >= 0){
300 s.height = h + u;
301 }
302 }
303
304 function isButtonTag(/*DomNode*/ node){
305 // summary:
306 // True if the node is BUTTON or INPUT.type="button".
307 return node.tagName.toLowerCase() == "button" ||
308 node.tagName.toLowerCase() == "input" && (node.getAttribute("type") || "").toLowerCase() == "button"; // boolean
309 }
310
311 function usesBorderBox(/*DomNode*/ node){
312 // summary:
313 // True if the node uses border-box layout.
314
315 // We could test the computed style of node to see if a particular box
316 // has been specified, but there are details and we choose not to bother.
317
318 // TABLE and BUTTON (and INPUT type=button) are always border-box by default.
319 // If you have assigned a different box to either one via CSS then
320 // box functions will break.
321
322 return geom.boxModel == "border-box" || node.tagName.toLowerCase() == "table" || isButtonTag(node); // boolean
323 }
324
325 geom.setContentSize = function setContentSize(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
326 // summary:
327 // Sets the size of the node's contents, irrespective of margins,
328 // padding, or borders.
329 // node: DOMNode
330 // box: Object
331 // hash with optional "w", and "h" properties for "width", and "height"
332 // respectively. All specified properties should have numeric values in whole pixels.
333 // computedStyle: Object?
334 // This parameter accepts computed styles object.
335 // If this parameter is omitted, the functions will call
336 // dojo.getComputedStyle to get one. It is a better way, calling
337 // dojo.computedStyle once, and then pass the reference to this
338 // computedStyle parameter. Wherever possible, reuse the returned
339 // object of dojo/dom-style.getComputedStyle().
340
341 node = dom.byId(node);
342 var w = box.w, h = box.h;
343 if(usesBorderBox(node)){
344 var pb = geom.getPadBorderExtents(node, computedStyle);
345 if(w >= 0){
346 w += pb.w;
347 }
348 if(h >= 0){
349 h += pb.h;
350 }
351 }
352 setBox(node, NaN, NaN, w, h);
353 };
354
355 var nilExtents = {l: 0, t: 0, w: 0, h: 0};
356
357 geom.setMarginBox = function setMarginBox(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
358 // summary:
359 // sets the size of the node's margin box and placement
360 // (left/top), irrespective of box model. Think of it as a
361 // passthrough to setBox that handles box-model vagaries for
362 // you.
363 // node: DOMNode
364 // box: Object
365 // hash with optional "l", "t", "w", and "h" properties for "left", "right", "width", and "height"
366 // respectively. All specified properties should have numeric values in whole pixels.
367 // computedStyle: Object?
368 // This parameter accepts computed styles object.
369 // If this parameter is omitted, the functions will call
370 // dojo.getComputedStyle to get one. It is a better way, calling
371 // dojo.computedStyle once, and then pass the reference to this
372 // computedStyle parameter. Wherever possible, reuse the returned
373 // object of dojo/dom-style.getComputedStyle().
374
375 node = dom.byId(node);
376 var s = computedStyle || style.getComputedStyle(node), w = box.w, h = box.h,
377 // Some elements have special padding, margin, and box-model settings.
378 // To use box functions you may need to set padding, margin explicitly.
379 // Controlling box-model is harder, in a pinch you might set dojo/dom-geometry.boxModel.
380 pb = usesBorderBox(node) ? nilExtents : geom.getPadBorderExtents(node, s),
381 mb = geom.getMarginExtents(node, s);
382 if(has("webkit")){
383 // on Safari (3.1.2), button nodes with no explicit size have a default margin
384 // setting an explicit size eliminates the margin.
385 // We have to swizzle the width to get correct margin reading.
386 if(isButtonTag(node)){
387 var ns = node.style;
388 if(w >= 0 && !ns.width){
389 ns.width = "4px";
390 }
391 if(h >= 0 && !ns.height){
392 ns.height = "4px";
393 }
394 }
395 }
396 if(w >= 0){
397 w = Math.max(w - pb.w - mb.w, 0);
398 }
399 if(h >= 0){
400 h = Math.max(h - pb.h - mb.h, 0);
401 }
402 setBox(node, box.l, box.t, w, h);
403 };
404
405 // =============================
406 // Positioning
407 // =============================
408
409 geom.isBodyLtr = function isBodyLtr(/*Document?*/ doc){
410 // summary:
411 // Returns true if the current language is left-to-right, and false otherwise.
412 // doc: Document?
413 // Optional document to query. If unspecified, use win.doc.
414 // returns: Boolean
415
416 doc = doc || win.doc;
417 return (win.body(doc).dir || doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
418 };
419
420 geom.docScroll = function docScroll(/*Document?*/ doc){
421 // summary:
422 // Returns an object with {node, x, y} with corresponding offsets.
423 // doc: Document?
424 // Optional document to query. If unspecified, use win.doc.
425 // returns: Object
426
427 doc = doc || win.doc;
428 var node = win.doc.parentWindow || win.doc.defaultView; // use UI window, not dojo.global window. TODO: use dojo/window::get() except for circular dependency problem
429 return "pageXOffset" in node ? {x: node.pageXOffset, y: node.pageYOffset } :
430 (node = has("quirks") ? win.body(doc) : doc.documentElement) &&
431 {x: geom.fixIeBiDiScrollLeft(node.scrollLeft || 0, doc), y: node.scrollTop || 0 };
432 };
433
434 if(has("ie")){
435 geom.getIeDocumentElementOffset = function getIeDocumentElementOffset(/*Document?*/ doc){
436 // summary:
437 // returns the offset in x and y from the document body to the
438 // visual edge of the page for IE
439 // doc: Document?
440 // Optional document to query. If unspecified, use win.doc.
441 // description:
442 // The following values in IE contain an offset:
443 // | event.clientX
444 // | event.clientY
445 // | node.getBoundingClientRect().left
446 // | node.getBoundingClientRect().top
447 // But other position related values do not contain this offset,
448 // such as node.offsetLeft, node.offsetTop, node.style.left and
449 // node.style.top. The offset is always (2, 2) in LTR direction.
450 // When the body is in RTL direction, the offset counts the width
451 // of left scroll bar's width. This function computes the actual
452 // offset.
453
454 //NOTE: assumes we're being called in an IE browser
455
456 doc = doc || win.doc;
457 var de = doc.documentElement; // only deal with HTML element here, position() handles body/quirks
458
459 if(has("ie") < 8){
460 var r = de.getBoundingClientRect(), // works well for IE6+
461 l = r.left, t = r.top;
462 if(has("ie") < 7){
463 l += de.clientLeft; // scrollbar size in strict/RTL, or,
464 t += de.clientTop; // HTML border size in strict
465 }
466 return {
467 x: l < 0 ? 0 : l, // FRAME element border size can lead to inaccurate negative values
468 y: t < 0 ? 0 : t
469 };
470 }else{
471 return {
472 x: 0,
473 y: 0
474 };
475 }
476 };
477 }
478
479 geom.fixIeBiDiScrollLeft = function fixIeBiDiScrollLeft(/*Integer*/ scrollLeft, /*Document?*/ doc){
480 // summary:
481 // In RTL direction, scrollLeft should be a negative value, but IE
482 // returns a positive one. All codes using documentElement.scrollLeft
483 // must call this function to fix this error, otherwise the position
484 // will offset to right when there is a horizontal scrollbar.
485 // scrollLeft: Number
486 // doc: Document?
487 // Optional document to query. If unspecified, use win.doc.
488 // returns: Number
489
490 // In RTL direction, scrollLeft should be a negative value, but IE
491 // returns a positive one. All codes using documentElement.scrollLeft
492 // must call this function to fix this error, otherwise the position
493 // will offset to right when there is a horizontal scrollbar.
494
495 doc = doc || win.doc;
496 var ie = has("ie");
497 if(ie && !geom.isBodyLtr(doc)){
498 var qk = has("quirks"),
499 de = qk ? win.body(doc) : doc.documentElement,
500 pwin = win.global; // TODO: use winUtils.get(doc) after resolving circular dependency b/w dom-geometry.js and dojo/window.js
501 if(ie == 6 && !qk && pwin.frameElement && de.scrollHeight > de.clientHeight){
502 scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels
503 }
504 return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer
505 }
506 return scrollLeft; // Integer
507 };
508
509 geom.position = function(/*DomNode*/ node, /*Boolean?*/ includeScroll){
510 // summary:
511 // Gets the position and size of the passed element relative to
512 // the viewport (if includeScroll==false), or relative to the
513 // document root (if includeScroll==true).
514 //
515 // description:
516 // Returns an object of the form:
517 // `{ x: 100, y: 300, w: 20, h: 15 }`.
518 // If includeScroll==true, the x and y values will include any
519 // document offsets that may affect the position relative to the
520 // viewport.
521 // Uses the border-box model (inclusive of border and padding but
522 // not margin). Does not act as a setter.
523 // node: DOMNode|String
524 // includeScroll: Boolean?
525 // returns: Object
526
527 node = dom.byId(node);
528 var db = win.body(node.ownerDocument),
529 ret = node.getBoundingClientRect();
530 ret = {x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top};
531
532 if(has("ie") < 9){
533 // On IE<9 there's a 2px offset that we need to adjust for, see dojo.getIeDocumentElementOffset()
534 var offset = geom.getIeDocumentElementOffset(node.ownerDocument);
535
536 // fixes the position in IE, quirks mode
537 ret.x -= offset.x + (has("quirks") ? db.clientLeft + db.offsetLeft : 0);
538 ret.y -= offset.y + (has("quirks") ? db.clientTop + db.offsetTop : 0);
539 }
540
541 // account for document scrolling
542 // if offsetParent is used, ret value already includes scroll position
543 // so we may have to actually remove that value if !includeScroll
544 if(includeScroll){
545 var scroll = geom.docScroll(node.ownerDocument);
546 ret.x += scroll.x;
547 ret.y += scroll.y;
548 }
549
550 return ret; // Object
551 };
552
553 // random "private" functions wildly used throughout the toolkit
554
555 geom.getMarginSize = function getMarginSize(/*DomNode*/ node, /*Object*/ computedStyle){
556 // summary:
557 // returns an object that encodes the width and height of
558 // the node's margin box
559 // node: DOMNode|String
560 // computedStyle: Object?
561 // This parameter accepts computed styles object.
562 // If this parameter is omitted, the functions will call
563 // dojo.getComputedStyle to get one. It is a better way, calling
564 // dojo.computedStyle once, and then pass the reference to this
565 // computedStyle parameter. Wherever possible, reuse the returned
566 // object of dojo/dom-style.getComputedStyle().
567
568 node = dom.byId(node);
569 var me = geom.getMarginExtents(node, computedStyle || style.getComputedStyle(node));
570 var size = node.getBoundingClientRect();
571 return {
572 w: (size.right - size.left) + me.w,
573 h: (size.bottom - size.top) + me.h
574 };
575 };
576
577 geom.normalizeEvent = function(event){
578 // summary:
579 // Normalizes the geometry of a DOM event, normalizing the pageX, pageY,
580 // offsetX, offsetY, layerX, and layerX properties
581 // event: Object
582 if(!("layerX" in event)){
583 event.layerX = event.offsetX;
584 event.layerY = event.offsetY;
585 }
586 if(!has("dom-addeventlistener")){
587 // old IE version
588 // FIXME: scroll position query is duped from dojo.html to
589 // avoid dependency on that entire module. Now that HTML is in
590 // Base, we should convert back to something similar there.
591 var se = event.target;
592 var doc = (se && se.ownerDocument) || document;
593 // DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
594 // here rather than document.body
595 var docBody = has("quirks") ? doc.body : doc.documentElement;
596 var offset = geom.getIeDocumentElementOffset(doc);
597 event.pageX = event.clientX + geom.fixIeBiDiScrollLeft(docBody.scrollLeft || 0, doc) - offset.x;
598 event.pageY = event.clientY + (docBody.scrollTop || 0) - offset.y;
599 }
600 };
601
602 // TODO: evaluate separate getters/setters for position and sizes?
603
604 return geom;
605 });