source: Dev/trunk/src/client/dojo/dom-geometry.js @ 525

Last change on this file since 525 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 23.5 KB
Line 
1define(["./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/dom-style.getComputedStyle to get one. It is a better way, calling
53                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
82                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
112                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
147                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
181                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
230                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
337                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
371                //              dojo/dom-style.getComputedStyle 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/dom-style.getComputedStyle to get one. It is a better way, calling
564                //              dojo/dom-style.getComputedStyle 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/_base/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/_base/window.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});
Note: See TracBrowser for help on using the repository browser.