214 lines
7 KiB
JavaScript
214 lines
7 KiB
JavaScript
|
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;
|
||
|
var de = _document.documentElement;
|
||
|
var dew = de.clientWidth, deh = de.clientHeight;
|
||
|
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;
|
||
|
var dbw = _document.body.clientWidth;
|
||
|
if(dbw > dew){
|
||
|
minw = dew;
|
||
|
maxw = dbw;
|
||
|
}else{
|
||
|
maxw = dew;
|
||
|
minw = dbw;
|
||
|
}
|
||
|
var dbh = _document.body.clientHeight;
|
||
|
if(dbh > deh){
|
||
|
minh = deh;
|
||
|
maxh = dbh;
|
||
|
}else{
|
||
|
maxh = deh;
|
||
|
minh = dbh;
|
||
|
}
|
||
|
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 && de && deh){
|
||
|
w = dew;
|
||
|
h = deh;
|
||
|
}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, aroundNodeCorner, nodeCorner)
|
||
|
// 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 <div style="position: relative">,
|
||
|
// so reattach it to dojo.doc.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;
|
||
|
dojo.some(choices, function(choice){
|
||
|
var corner = choice.corner;
|
||
|
var pos = choice.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(node, choice.aroundCorner, corner);
|
||
|
}
|
||
|
|
||
|
// get node's size
|
||
|
var style = node.style;
|
||
|
var oldDisplay = style.display;
|
||
|
var oldVis = style.visibility;
|
||
|
style.visibility = "hidden";
|
||
|
style.display = "";
|
||
|
var mb = dojo.marginBox(node);
|
||
|
style.display = oldDisplay;
|
||
|
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: choice.aroundCorner,
|
||
|
x: startX,
|
||
|
y: startY,
|
||
|
w: width,
|
||
|
h: height,
|
||
|
overflow: overflow
|
||
|
};
|
||
|
}
|
||
|
return !overflow;
|
||
|
});
|
||
|
|
||
|
node.style.left = best.x + "px";
|
||
|
node.style.top = best.y + "px";
|
||
|
if(best.overflow && layoutNode){
|
||
|
layoutNode(node, best.aroundCorner, best.corner);
|
||
|
}
|
||
|
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, aroundNodeCorner, nodeCorner)
|
||
|
// 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);
|
||
|
}
|
||
|
|
||
|
}
|