if (!dojo._hasResource["dijit._base.place"]) { // _hasResource checks added by // build. Do not use // _hasResource directly in your // code. dojo._hasResource["dijit._base.place"] = true; dojo.provide("dijit._base.place"); // ported from dojo.html.util dijit.getViewport = function() { // summary // Returns the dimensions and scroll position of the viewable area of a // browser window var _window = dojo.global; var _document = dojo.doc; // get viewport size var w = 0, h = 0; if (dojo.isMozilla) { // mozilla // _window.innerHeight includes the height taken by the scroll bar // clientHeight is ideal but has DTD issues: // #4539: FF reverses the roles of body.clientHeight/Width and // documentElement.clientHeight/Width based on the DTD! // check DTD to see whether body or documentElement returns the // viewport dimensions using this algorithm: var minw, minh, maxw, maxh; if (_document.body.clientWidth > _document.documentElement.clientWidth) { minw = _document.documentElement.clientWidth; maxw = _document.body.clientWidth; } else { maxw = _document.documentElement.clientWidth; minw = _document.body.clientWidth; } if (_document.body.clientHeight > _document.documentElement.clientHeight) { minh = _document.documentElement.clientHeight; maxh = _document.body.clientHeight; } else { maxh = _document.documentElement.clientHeight; minh = _document.body.clientHeight; } w = (maxw > _window.innerWidth) ? minw : maxw; h = (maxh > _window.innerHeight) ? minh : maxh; } else if (!dojo.isOpera && _window.innerWidth) { // in opera9, dojo.body().clientWidth should be used, instead // of window.innerWidth/document.documentElement.clientWidth // so we have to check whether it is opera w = _window.innerWidth; h = _window.innerHeight; } else if (dojo.isIE && _document.documentElement && _document.documentElement.clientHeight) { w = _document.documentElement.clientWidth; h = _document.documentElement.clientHeight; } else if (dojo.body().clientWidth) { // IE5, Opera w = dojo.body().clientWidth; h = dojo.body().clientHeight; } // get scroll position var scroll = dojo._docScroll(); return { w : w, h : h, l : scroll.x, t : scroll.y }; // object }; dijit.placeOnScreen = function( /* DomNode */node, /* Object */pos, /* Object */corners, /* boolean? */tryOnly) { // summary: // Keeps 'node' in the visible area of the screen while trying to // place closest to pos.x, pos.y. The input coordinates are // expected to be the desired document position. // // Set which corner(s) you want to bind to, such as // // placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"]) // // The desired x/y will be treated as the topleft(TL)/topright(TR) or // BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is // tested // and if a perfect match is found, it will be used. Otherwise, it goes // through // all of the specified corners, and choose the most appropriate one. // // NOTE: node is assumed to be absolutely or relatively positioned. var choices = dojo.map(corners, function(corner) { return { corner : corner, pos : pos }; }); return dijit._place(node, choices); } dijit._place = function(/* DomNode */node, /* Array */choices, /* Function */ layoutNode) { // summary: // Given a list of spots to put node, put it at the first spot where it // fits, // of if it doesn't fit anywhere then the place with the least overflow // choices: Array // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} } // Above example says to put the top-left corner of the node at (10,20) // layoutNode: Function(node, orient) // for things like tooltip, they are displayed differently (and have // different dimensions) // based on their orientation relative to the parent. This adjusts the // popup based on orientation. // get {x: 10, y: 10, w: 100, h:100} type obj representing position of // viewport over document var view = dijit.getViewport(); // This won't work if the node is inside a
, // so reattach it to document.body. (Otherwise, the positioning will be // wrong // and also it might get cutoff) if (!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body") { dojo.body().appendChild(node); } var best = null; for (var i = 0; i < choices.length; i++) { var corner = choices[i].corner; var pos = choices[i].pos; // configure node to be displayed in given position relative to // button // (need to do this in order to get an accurate size for the node, // because // a tooltips size changes based on position, due to triangle) if (layoutNode) { layoutNode(corner); } // get node's size var oldDisplay = node.style.display; var oldVis = node.style.visibility; node.style.visibility = "hidden"; node.style.display = ""; var mb = dojo.marginBox(node); node.style.display = oldDisplay; node.style.visibility = oldVis; // coordinates and size of node with specified corner placed at pos, // and clipped by viewport var startX = (corner.charAt(1) == 'L' ? pos.x : Math.max(view.l, pos.x - mb.w)), startY = (corner.charAt(0) == 'T' ? pos.y : Math.max(view.t, pos.y - mb.h)), endX = (corner.charAt(1) == 'L' ? Math.min(view.l + view.w, startX + mb.w) : pos.x), endY = (corner.charAt(0) == 'T' ? Math.min(view.t + view.h, startY + mb.h) : pos.y), width = endX - startX, height = endY - startY, overflow = (mb.w - width) + (mb.h - height); if (best == null || overflow < best.overflow) { best = { corner : corner, aroundCorner : choices[i].aroundCorner, x : startX, y : startY, w : width, h : height, overflow : overflow }; } if (overflow == 0) { break; } } node.style.left = best.x + "px"; node.style.top = best.y + "px"; return best; } dijit.placeOnScreenAroundElement = function( /* DomNode */node, /* DomNode */aroundNode, /* Object */aroundCorners, /* Function */layoutNode) { // summary // Like placeOnScreen, except it accepts aroundNode instead of x,y // and attempts to place node around it. Uses margin box dimensions. // // aroundCorners // specify Which corner of aroundNode should be // used to place the node => which corner(s) of node to use (see the // corners parameter in dijit.placeOnScreen) // e.g. {'TL': 'BL', 'BL': 'TL'} // // layoutNode: Function(node, orient) // for things like tooltip, they are displayed differently (and have // different dimensions) // based on their orientation relative to the parent. This adjusts the // popup based on orientation. // get coordinates of aroundNode aroundNode = dojo.byId(aroundNode); var oldDisplay = aroundNode.style.display; aroundNode.style.display = ""; // #3172: use the slightly tighter border box instead of marginBox var aroundNodeW = aroundNode.offsetWidth; // mb.w; var aroundNodeH = aroundNode.offsetHeight; // mb.h; var aroundNodePos = dojo.coords(aroundNode, true); aroundNode.style.display = oldDisplay; // Generate list of possible positions for node var choices = []; for (var nodeCorner in aroundCorners) { choices.push({ aroundCorner : nodeCorner, corner : aroundCorners[nodeCorner], pos : { x : aroundNodePos.x + (nodeCorner.charAt(1) == 'L' ? 0 : aroundNodeW), y : aroundNodePos.y + (nodeCorner.charAt(0) == 'T' ? 0 : aroundNodeH) } }); } return dijit._place(node, choices, layoutNode); } }