You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
576 lines
22 KiB
576 lines
22 KiB
define(["./sniff", "./_base/window","./dom", "./dom-style"], |
|
function(has, win, dom, style){ |
|
// module: |
|
// dojo/dom-geometry |
|
|
|
// the result object |
|
var geom = { |
|
// summary: |
|
// This module defines the core dojo DOM geometry API. |
|
}; |
|
|
|
// Box functions will assume this model. |
|
// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode. |
|
// Can be set to change behavior of box setters. |
|
|
|
// can be either: |
|
// "border-box" |
|
// "content-box" (default) |
|
geom.boxModel = "content-box"; |
|
|
|
// We punt per-node box mode testing completely. |
|
// If anybody cares, we can provide an additional (optional) unit |
|
// that overrides existing code to include per-node box sensitivity. |
|
|
|
// Opera documentation claims that Opera 9 uses border-box in BackCompat mode. |
|
// but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box. |
|
// IIRC, earlier versions of Opera did in fact use border-box. |
|
// Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault. |
|
|
|
if(has("ie") /*|| has("opera")*/){ |
|
// client code may have to adjust if compatMode varies across iframes |
|
geom.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box"; |
|
} |
|
|
|
geom.getPadExtents = function getPadExtents(/*DomNode*/ node, /*Object*/ computedStyle){ |
|
// summary: |
|
// Returns object with special values specifically useful for node |
|
// fitting. |
|
// description: |
|
// Returns an object with `w`, `h`, `l`, `t` properties: |
|
// | l/t/r/b = left/top/right/bottom padding (respectively) |
|
// | w = the total of the left and right padding |
|
// | h = the total of the top and bottom padding |
|
// If 'node' has position, l/t forms the origin for child nodes. |
|
// The w/h are used for calculating boxes. |
|
// Normally application code will not need to invoke this |
|
// directly, and will use the ...box... functions instead. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue, |
|
l = px(node, s.paddingLeft), t = px(node, s.paddingTop), r = px(node, s.paddingRight), b = px(node, s.paddingBottom); |
|
return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; |
|
}; |
|
|
|
var none = "none"; |
|
|
|
geom.getBorderExtents = function getBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){ |
|
// summary: |
|
// returns an object with properties useful for noting the border |
|
// dimensions. |
|
// description: |
|
// - l/t/r/b = the sum of left/top/right/bottom border (respectively) |
|
// - w = the sum of the left and right border |
|
// - h = the sum of the top and bottom border |
|
// |
|
// The w/h are used for calculating boxes. |
|
// Normally application code will not need to invoke this |
|
// directly, and will use the ...box... functions instead. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var px = style.toPixelValue, s = computedStyle || style.getComputedStyle(node), |
|
l = s.borderLeftStyle != none ? px(node, s.borderLeftWidth) : 0, |
|
t = s.borderTopStyle != none ? px(node, s.borderTopWidth) : 0, |
|
r = s.borderRightStyle != none ? px(node, s.borderRightWidth) : 0, |
|
b = s.borderBottomStyle != none ? px(node, s.borderBottomWidth) : 0; |
|
return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; |
|
}; |
|
|
|
geom.getPadBorderExtents = function getPadBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){ |
|
// summary: |
|
// Returns object with properties useful for box fitting with |
|
// regards to padding. |
|
// description: |
|
// - l/t/r/b = the sum of left/top/right/bottom padding and left/top/right/bottom border (respectively) |
|
// - w = the sum of the left and right padding and border |
|
// - h = the sum of the top and bottom padding and border |
|
// |
|
// The w/h are used for calculating boxes. |
|
// Normally application code will not need to invoke this |
|
// directly, and will use the ...box... functions instead. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), |
|
p = geom.getPadExtents(node, s), |
|
b = geom.getBorderExtents(node, s); |
|
return { |
|
l: p.l + b.l, |
|
t: p.t + b.t, |
|
r: p.r + b.r, |
|
b: p.b + b.b, |
|
w: p.w + b.w, |
|
h: p.h + b.h |
|
}; |
|
}; |
|
|
|
geom.getMarginExtents = function getMarginExtents(node, computedStyle){ |
|
// summary: |
|
// returns object with properties useful for box fitting with |
|
// regards to box margins (i.e., the outer-box). |
|
// |
|
// - l/t = marginLeft, marginTop, respectively |
|
// - w = total width, margin inclusive |
|
// - h = total height, margin inclusive |
|
// |
|
// The w/h are used for calculating boxes. |
|
// Normally application code will not need to invoke this |
|
// directly, and will use the ...box... functions instead. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue, |
|
l = px(node, s.marginLeft), t = px(node, s.marginTop), r = px(node, s.marginRight), b = px(node, s.marginBottom); |
|
return {l: l, t: t, r: r, b: b, w: l + r, h: t + b}; |
|
}; |
|
|
|
// Box getters work in any box context because offsetWidth/clientWidth |
|
// are invariant wrt box context |
|
// |
|
// They do *not* work for display: inline objects that have padding styles |
|
// because the user agent ignores padding (it's bogus styling in any case) |
|
// |
|
// Be careful with IMGs because they are inline or block depending on |
|
// browser and browser mode. |
|
|
|
// Although it would be easier to read, there are not separate versions of |
|
// _getMarginBox for each browser because: |
|
// 1. the branching is not expensive |
|
// 2. factoring the shared code wastes cycles (function call overhead) |
|
// 3. duplicating the shared code wastes bytes |
|
|
|
geom.getMarginBox = function getMarginBox(/*DomNode*/ node, /*Object*/ computedStyle){ |
|
// summary: |
|
// returns an object that encodes the width, height, left and top |
|
// positions of the node's margin box. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), me = geom.getMarginExtents(node, s), |
|
l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode, px = style.toPixelValue, pcs; |
|
|
|
if((has("ie") == 8 && !has("quirks"))){ |
|
// IE 8 offsetLeft/Top includes the parent's border |
|
if(p){ |
|
pcs = style.getComputedStyle(p); |
|
l -= pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0; |
|
t -= pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0; |
|
} |
|
} |
|
return {l: l, t: t, w: node.offsetWidth + me.w, h: node.offsetHeight + me.h}; |
|
}; |
|
|
|
geom.getContentBox = function getContentBox(node, computedStyle){ |
|
// summary: |
|
// Returns an object that encodes the width, height, left and top |
|
// positions of the node's content box, irrespective of the |
|
// current box model. |
|
// node: DOMNode |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
// clientWidth/Height are important since the automatically account for scrollbars |
|
// fallback to offsetWidth/Height for special cases (see #3378) |
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), w = node.clientWidth, h, |
|
pe = geom.getPadExtents(node, s), be = geom.getBorderExtents(node, s), l = node.offsetLeft + pe.l + be.l, |
|
t = node.offsetTop + pe.t + be.t; |
|
if(!w){ |
|
w = node.offsetWidth - be.w; |
|
h = node.offsetHeight - be.h; |
|
}else{ |
|
h = node.clientHeight; |
|
} |
|
|
|
if((has("ie") == 8 && !has("quirks"))){ |
|
// IE 8 offsetLeft/Top includes the parent's border |
|
var p = node.parentNode, px = style.toPixelValue, pcs; |
|
if(p){ |
|
pcs = style.getComputedStyle(p); |
|
l -= pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0; |
|
t -= pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0; |
|
} |
|
} |
|
|
|
return {l: l, t: t, w: w - pe.w, h: h - pe.h}; |
|
}; |
|
|
|
// Box setters depend on box context because interpretation of width/height styles |
|
// vary wrt box context. |
|
// |
|
// The value of boxModel is used to determine box context. |
|
// boxModel can be set directly to change behavior. |
|
// |
|
// Beware of display: inline objects that have padding styles |
|
// because the user agent ignores padding (it's a bogus setup anyway) |
|
// |
|
// Be careful with IMGs because they are inline or block depending on |
|
// browser and browser mode. |
|
// |
|
// Elements other than DIV may have special quirks, like built-in |
|
// margins or padding, or values not detectable via computedStyle. |
|
// In particular, margins on TABLE do not seems to appear |
|
// at all in computedStyle on Mozilla. |
|
|
|
function setBox(/*DomNode*/ node, /*Number?*/ l, /*Number?*/ t, /*Number?*/ w, /*Number?*/ h, /*String?*/ u){ |
|
// summary: |
|
// sets width/height/left/top in the current (native) box-model |
|
// dimensions. Uses the unit passed in u. |
|
// node: |
|
// DOM Node reference. Id string not supported for performance |
|
// reasons. |
|
// l: |
|
// left offset from parent. |
|
// t: |
|
// top offset from parent. |
|
// w: |
|
// width in current box model. |
|
// h: |
|
// width in current box model. |
|
// u: |
|
// unit measure to use for other measures. Defaults to "px". |
|
u = u || "px"; |
|
var s = node.style; |
|
if(!isNaN(l)){ |
|
s.left = l + u; |
|
} |
|
if(!isNaN(t)){ |
|
s.top = t + u; |
|
} |
|
if(w >= 0){ |
|
s.width = w + u; |
|
} |
|
if(h >= 0){ |
|
s.height = h + u; |
|
} |
|
} |
|
|
|
function isButtonTag(/*DomNode*/ node){ |
|
// summary: |
|
// True if the node is BUTTON or INPUT.type="button". |
|
return node.tagName.toLowerCase() == "button" || |
|
node.tagName.toLowerCase() == "input" && (node.getAttribute("type") || "").toLowerCase() == "button"; // boolean |
|
} |
|
|
|
function usesBorderBox(/*DomNode*/ node){ |
|
// summary: |
|
// True if the node uses border-box layout. |
|
|
|
// We could test the computed style of node to see if a particular box |
|
// has been specified, but there are details and we choose not to bother. |
|
|
|
// TABLE and BUTTON (and INPUT type=button) are always border-box by default. |
|
// If you have assigned a different box to either one via CSS then |
|
// box functions will break. |
|
|
|
return geom.boxModel == "border-box" || node.tagName.toLowerCase() == "table" || isButtonTag(node); // boolean |
|
} |
|
|
|
function getBoundingClientRect(/*DomNode*/ node) { |
|
// summary: |
|
// Gets the bounding client rectangle for a dom node. |
|
// node: DOMNode |
|
|
|
// This will return the result of node.getBoundingClientRect if node is in the dom, and |
|
// {x:0, y:0, width:0, height:0, top:0, right:0, bottom:0, left:0} if it throws an error or the node is not on the dom |
|
// This will handle when IE throws an error or Edge returns an empty object when node is not on the dom |
|
|
|
var retEmpty = { x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 }, |
|
ret; |
|
|
|
try { |
|
ret = node.getBoundingClientRect(); |
|
} catch (e) { |
|
// IE throws an Unspecified Error if the node is not in the dom. Handle this by returning an object with 0 values |
|
return retEmpty; |
|
} |
|
|
|
// Edge returns an empty object if the node is not in the dom. Handle this by returning an object with 0 values |
|
if (typeof ret.left === "undefined") { return retEmpty; } |
|
|
|
return ret; |
|
} |
|
|
|
geom.setContentSize = function setContentSize(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){ |
|
// summary: |
|
// Sets the size of the node's contents, irrespective of margins, |
|
// padding, or borders. |
|
// node: DOMNode |
|
// box: Object |
|
// hash with optional "w", and "h" properties for "width", and "height" |
|
// respectively. All specified properties should have numeric values in whole pixels. |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var w = box.w, h = box.h; |
|
if(usesBorderBox(node)){ |
|
var pb = geom.getPadBorderExtents(node, computedStyle); |
|
if(w >= 0){ |
|
w += pb.w; |
|
} |
|
if(h >= 0){ |
|
h += pb.h; |
|
} |
|
} |
|
setBox(node, NaN, NaN, w, h); |
|
}; |
|
|
|
var nilExtents = {l: 0, t: 0, w: 0, h: 0}; |
|
|
|
geom.setMarginBox = function setMarginBox(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){ |
|
// summary: |
|
// sets the size of the node's margin box and placement |
|
// (left/top), irrespective of box model. Think of it as a |
|
// passthrough to setBox that handles box-model vagaries for |
|
// you. |
|
// node: DOMNode |
|
// box: Object |
|
// hash with optional "l", "t", "w", and "h" properties for "left", "right", "width", and "height" |
|
// respectively. All specified properties should have numeric values in whole pixels. |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var s = computedStyle || style.getComputedStyle(node), w = box.w, h = box.h, |
|
// Some elements have special padding, margin, and box-model settings. |
|
// To use box functions you may need to set padding, margin explicitly. |
|
// Controlling box-model is harder, in a pinch you might set dojo/dom-geometry.boxModel. |
|
pb = usesBorderBox(node) ? nilExtents : geom.getPadBorderExtents(node, s), |
|
mb = geom.getMarginExtents(node, s); |
|
if(has("webkit")){ |
|
// on Safari (3.1.2), button nodes with no explicit size have a default margin |
|
// setting an explicit size eliminates the margin. |
|
// We have to swizzle the width to get correct margin reading. |
|
if(isButtonTag(node)){ |
|
var ns = node.style; |
|
if(w >= 0 && !ns.width){ |
|
ns.width = "4px"; |
|
} |
|
if(h >= 0 && !ns.height){ |
|
ns.height = "4px"; |
|
} |
|
} |
|
} |
|
if(w >= 0){ |
|
w = Math.max(w - pb.w - mb.w, 0); |
|
} |
|
if(h >= 0){ |
|
h = Math.max(h - pb.h - mb.h, 0); |
|
} |
|
setBox(node, box.l, box.t, w, h); |
|
}; |
|
|
|
// ============================= |
|
// Positioning |
|
// ============================= |
|
|
|
geom.isBodyLtr = function isBodyLtr(/*Document?*/ doc){ |
|
// summary: |
|
// Returns true if the current language is left-to-right, and false otherwise. |
|
// doc: Document? |
|
// Optional document to query. If unspecified, use win.doc. |
|
// returns: Boolean |
|
|
|
doc = doc || win.doc; |
|
return (win.body(doc).dir || doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean |
|
}; |
|
|
|
geom.docScroll = function docScroll(/*Document?*/ doc){ |
|
// summary: |
|
// Returns an object with {node, x, y} with corresponding offsets. |
|
// doc: Document? |
|
// Optional document to query. If unspecified, use win.doc. |
|
// returns: Object |
|
|
|
doc = doc || win.doc; |
|
var node = doc.parentWindow || doc.defaultView; // use UI window, not dojo.global window. TODO: use dojo/window::get() except for circular dependency problem |
|
return "pageXOffset" in node ? {x: node.pageXOffset, y: node.pageYOffset } : |
|
(node = has("quirks") ? win.body(doc) : doc.documentElement) && |
|
{x: geom.fixIeBiDiScrollLeft(node.scrollLeft || 0, doc), y: node.scrollTop || 0 }; |
|
}; |
|
|
|
geom.getIeDocumentElementOffset = function(/*Document?*/ doc){ |
|
// summary: |
|
// Deprecated method previously used for IE6-IE7. Now, just returns `{x:0, y:0}`. |
|
return { |
|
x: 0, |
|
y: 0 |
|
}; |
|
}; |
|
|
|
geom.fixIeBiDiScrollLeft = function fixIeBiDiScrollLeft(/*Integer*/ scrollLeft, /*Document?*/ doc){ |
|
// summary: |
|
// In RTL direction, scrollLeft should be a negative value, but IE |
|
// returns a positive one. All codes using documentElement.scrollLeft |
|
// must call this function to fix this error, otherwise the position |
|
// will offset to right when there is a horizontal scrollbar. |
|
// scrollLeft: Number |
|
// doc: Document? |
|
// Optional document to query. If unspecified, use win.doc. |
|
// returns: Number |
|
|
|
// In RTL direction, scrollLeft should be a negative value, but IE |
|
// returns a positive one. All codes using documentElement.scrollLeft |
|
// must call this function to fix this error, otherwise the position |
|
// will offset to right when there is a horizontal scrollbar. |
|
|
|
doc = doc || win.doc; |
|
var ie = has("ie"); |
|
if(ie && !geom.isBodyLtr(doc)){ |
|
var qk = has("quirks"), |
|
de = qk ? win.body(doc) : doc.documentElement, |
|
pwin = win.global; // TODO: use winUtils.get(doc) after resolving circular dependency b/w dom-geometry.js and dojo/window.js |
|
if(ie == 6 && !qk && pwin.frameElement && de.scrollHeight > de.clientHeight){ |
|
scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels |
|
} |
|
return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer |
|
} |
|
return scrollLeft; // Integer |
|
}; |
|
|
|
geom.position = function(/*DomNode*/ node, /*Boolean?*/ includeScroll){ |
|
// summary: |
|
// Gets the position and size of the passed element relative to |
|
// the viewport (if includeScroll==false), or relative to the |
|
// document root (if includeScroll==true). |
|
// |
|
// description: |
|
// Returns an object of the form: |
|
// `{ x: 100, y: 300, w: 20, h: 15 }`. |
|
// If includeScroll==true, the x and y values will include any |
|
// document offsets that may affect the position relative to the |
|
// viewport. |
|
// Uses the border-box model (inclusive of border and padding but |
|
// not margin). Does not act as a setter. |
|
// node: DOMNode|String |
|
// includeScroll: Boolean? |
|
// returns: Object |
|
|
|
node = dom.byId(node); |
|
var db = win.body(node.ownerDocument), |
|
ret= getBoundingClientRect(node); |
|
ret = {x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top}; |
|
|
|
if(has("ie") < 9){ |
|
// fixes the position in IE, quirks mode |
|
ret.x -= (has("quirks") ? db.clientLeft + db.offsetLeft : 0); |
|
ret.y -= (has("quirks") ? db.clientTop + db.offsetTop : 0); |
|
} |
|
|
|
// account for document scrolling |
|
// if offsetParent is used, ret value already includes scroll position |
|
// so we may have to actually remove that value if !includeScroll |
|
if(includeScroll){ |
|
var scroll = geom.docScroll(node.ownerDocument); |
|
ret.x += scroll.x; |
|
ret.y += scroll.y; |
|
} |
|
|
|
return ret; // Object |
|
}; |
|
|
|
// random "private" functions wildly used throughout the toolkit |
|
|
|
geom.getMarginSize = function getMarginSize(/*DomNode*/ node, /*Object*/ computedStyle){ |
|
// summary: |
|
// returns an object that encodes the width and height of |
|
// the node's margin box |
|
// node: DOMNode|String |
|
// computedStyle: Object? |
|
// This parameter accepts computed styles object. |
|
// If this parameter is omitted, the functions will call |
|
// dojo/dom-style.getComputedStyle to get one. It is a better way, calling |
|
// dojo/dom-style.getComputedStyle once, and then pass the reference to this |
|
// computedStyle parameter. Wherever possible, reuse the returned |
|
// object of dojo/dom-style.getComputedStyle(). |
|
|
|
node = dom.byId(node); |
|
var me = geom.getMarginExtents(node, computedStyle || style.getComputedStyle(node)); |
|
var size = getBoundingClientRect(node); |
|
return { |
|
w: (size.right - size.left) + me.w, |
|
h: (size.bottom - size.top) + me.h |
|
}; |
|
}; |
|
|
|
geom.normalizeEvent = function(event){ |
|
// summary: |
|
// Normalizes the geometry of a DOM event, normalizing the pageX, pageY, |
|
// offsetX, offsetY, layerX, and layerX properties |
|
// event: Object |
|
if(!("layerX" in event)){ |
|
event.layerX = event.offsetX; |
|
event.layerY = event.offsetY; |
|
} |
|
|
|
if(!("pageX" in event)){ |
|
// FIXME: scroll position query is duped from dojo/_base/html to |
|
// avoid dependency on that entire module. Now that HTML is in |
|
// Base, we should convert back to something similar there. |
|
var se = event.target; |
|
var doc = (se && se.ownerDocument) || document; |
|
// DO NOT replace the following to use dojo/_base/window.body(), in IE, document.documentElement should be used |
|
// here rather than document.body |
|
var docBody = has("quirks") ? doc.body : doc.documentElement; |
|
event.pageX = event.clientX + geom.fixIeBiDiScrollLeft(docBody.scrollLeft || 0, doc); |
|
event.pageY = event.clientY + (docBody.scrollTop || 0); |
|
} |
|
}; |
|
|
|
// TODO: evaluate separate getters/setters for position and sizes? |
|
|
|
return geom; |
|
});
|
|
|