2150 |
mathias |
1 |
if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dijit._base.place"] = true;
|
|
|
3 |
dojo.provide("dijit._base.place");
|
|
|
4 |
|
|
|
5 |
// ported from dojo.html.util
|
|
|
6 |
|
|
|
7 |
dijit.getViewport = function(){
|
|
|
8 |
// summary
|
|
|
9 |
// Returns the dimensions and scroll position of the viewable area of a browser window
|
|
|
10 |
|
|
|
11 |
var _window = dojo.global;
|
|
|
12 |
var _document = dojo.doc;
|
|
|
13 |
|
|
|
14 |
// get viewport size
|
|
|
15 |
var w = 0, h = 0;
|
|
|
16 |
if(dojo.isMozilla){
|
|
|
17 |
// mozilla
|
|
|
18 |
// _window.innerHeight includes the height taken by the scroll bar
|
|
|
19 |
// clientHeight is ideal but has DTD issues:
|
|
|
20 |
// #4539: FF reverses the roles of body.clientHeight/Width and documentElement.clientHeight/Width based on the DTD!
|
|
|
21 |
// check DTD to see whether body or documentElement returns the viewport dimensions using this algorithm:
|
|
|
22 |
var minw, minh, maxw, maxh;
|
|
|
23 |
if(_document.body.clientWidth>_document.documentElement.clientWidth){
|
|
|
24 |
minw = _document.documentElement.clientWidth;
|
|
|
25 |
maxw = _document.body.clientWidth;
|
|
|
26 |
}else{
|
|
|
27 |
maxw = _document.documentElement.clientWidth;
|
|
|
28 |
minw = _document.body.clientWidth;
|
|
|
29 |
}
|
|
|
30 |
if(_document.body.clientHeight>_document.documentElement.clientHeight){
|
|
|
31 |
minh = _document.documentElement.clientHeight;
|
|
|
32 |
maxh = _document.body.clientHeight;
|
|
|
33 |
}else{
|
|
|
34 |
maxh = _document.documentElement.clientHeight;
|
|
|
35 |
minh = _document.body.clientHeight;
|
|
|
36 |
}
|
|
|
37 |
w = (maxw > _window.innerWidth) ? minw : maxw;
|
|
|
38 |
h = (maxh > _window.innerHeight) ? minh : maxh;
|
|
|
39 |
}else if(!dojo.isOpera && _window.innerWidth){
|
|
|
40 |
//in opera9, dojo.body().clientWidth should be used, instead
|
|
|
41 |
//of window.innerWidth/document.documentElement.clientWidth
|
|
|
42 |
//so we have to check whether it is opera
|
|
|
43 |
w = _window.innerWidth;
|
|
|
44 |
h = _window.innerHeight;
|
|
|
45 |
}else if(dojo.isIE && _document.documentElement && _document.documentElement.clientHeight){
|
|
|
46 |
w = _document.documentElement.clientWidth;
|
|
|
47 |
h = _document.documentElement.clientHeight;
|
|
|
48 |
}else if(dojo.body().clientWidth){
|
|
|
49 |
// IE5, Opera
|
|
|
50 |
w = dojo.body().clientWidth;
|
|
|
51 |
h = dojo.body().clientHeight;
|
|
|
52 |
}
|
|
|
53 |
|
|
|
54 |
// get scroll position
|
|
|
55 |
var scroll = dojo._docScroll();
|
|
|
56 |
|
|
|
57 |
return { w: w, h: h, l: scroll.x, t: scroll.y }; // object
|
|
|
58 |
};
|
|
|
59 |
|
|
|
60 |
dijit.placeOnScreen = function(
|
|
|
61 |
/* DomNode */ node,
|
|
|
62 |
/* Object */ pos,
|
|
|
63 |
/* Object */ corners,
|
|
|
64 |
/* boolean? */ tryOnly){
|
|
|
65 |
// summary:
|
|
|
66 |
// Keeps 'node' in the visible area of the screen while trying to
|
|
|
67 |
// place closest to pos.x, pos.y. The input coordinates are
|
|
|
68 |
// expected to be the desired document position.
|
|
|
69 |
//
|
|
|
70 |
// Set which corner(s) you want to bind to, such as
|
|
|
71 |
//
|
|
|
72 |
// placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
|
|
|
73 |
//
|
|
|
74 |
// The desired x/y will be treated as the topleft(TL)/topright(TR) or
|
|
|
75 |
// BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is tested
|
|
|
76 |
// and if a perfect match is found, it will be used. Otherwise, it goes through
|
|
|
77 |
// all of the specified corners, and choose the most appropriate one.
|
|
|
78 |
//
|
|
|
79 |
// NOTE: node is assumed to be absolutely or relatively positioned.
|
|
|
80 |
|
|
|
81 |
var choices = dojo.map(corners, function(corner){ return { corner: corner, pos: pos }; });
|
|
|
82 |
|
|
|
83 |
return dijit._place(node, choices);
|
|
|
84 |
}
|
|
|
85 |
|
|
|
86 |
dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
|
|
|
87 |
// summary:
|
|
|
88 |
// Given a list of spots to put node, put it at the first spot where it fits,
|
|
|
89 |
// of if it doesn't fit anywhere then the place with the least overflow
|
|
|
90 |
// choices: Array
|
|
|
91 |
// Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
|
|
|
92 |
// Above example says to put the top-left corner of the node at (10,20)
|
|
|
93 |
// layoutNode: Function(node, orient)
|
|
|
94 |
// for things like tooltip, they are displayed differently (and have different dimensions)
|
|
|
95 |
// based on their orientation relative to the parent. This adjusts the popup based on orientation.
|
|
|
96 |
|
|
|
97 |
// get {x: 10, y: 10, w: 100, h:100} type obj representing position of
|
|
|
98 |
// viewport over document
|
|
|
99 |
var view = dijit.getViewport();
|
|
|
100 |
|
|
|
101 |
// This won't work if the node is inside a <div style="position: relative">,
|
|
|
102 |
// so reattach it to document.body. (Otherwise, the positioning will be wrong
|
|
|
103 |
// and also it might get cutoff)
|
|
|
104 |
if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
|
|
|
105 |
dojo.body().appendChild(node);
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
var best=null;
|
|
|
109 |
for(var i=0; i<choices.length; i++){
|
|
|
110 |
var corner = choices[i].corner;
|
|
|
111 |
var pos = choices[i].pos;
|
|
|
112 |
|
|
|
113 |
// configure node to be displayed in given position relative to button
|
|
|
114 |
// (need to do this in order to get an accurate size for the node, because
|
|
|
115 |
// a tooltips size changes based on position, due to triangle)
|
|
|
116 |
if(layoutNode){
|
|
|
117 |
layoutNode(corner);
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
// get node's size
|
|
|
121 |
var oldDisplay = node.style.display;
|
|
|
122 |
var oldVis = node.style.visibility;
|
|
|
123 |
node.style.visibility = "hidden";
|
|
|
124 |
node.style.display = "";
|
|
|
125 |
var mb = dojo.marginBox(node);
|
|
|
126 |
node.style.display = oldDisplay;
|
|
|
127 |
node.style.visibility = oldVis;
|
|
|
128 |
|
|
|
129 |
// coordinates and size of node with specified corner placed at pos,
|
|
|
130 |
// and clipped by viewport
|
|
|
131 |
var startX = (corner.charAt(1)=='L' ? pos.x : Math.max(view.l, pos.x - mb.w)),
|
|
|
132 |
startY = (corner.charAt(0)=='T' ? pos.y : Math.max(view.t, pos.y - mb.h)),
|
|
|
133 |
endX = (corner.charAt(1)=='L' ? Math.min(view.l+view.w, startX+mb.w) : pos.x),
|
|
|
134 |
endY = (corner.charAt(0)=='T' ? Math.min(view.t+view.h, startY+mb.h) : pos.y),
|
|
|
135 |
width = endX-startX,
|
|
|
136 |
height = endY-startY,
|
|
|
137 |
overflow = (mb.w-width) + (mb.h-height);
|
|
|
138 |
|
|
|
139 |
if(best==null || overflow<best.overflow){
|
|
|
140 |
best = {
|
|
|
141 |
corner: corner,
|
|
|
142 |
aroundCorner: choices[i].aroundCorner,
|
|
|
143 |
x: startX,
|
|
|
144 |
y: startY,
|
|
|
145 |
w: width,
|
|
|
146 |
h: height,
|
|
|
147 |
overflow: overflow
|
|
|
148 |
};
|
|
|
149 |
}
|
|
|
150 |
if(overflow==0){
|
|
|
151 |
break;
|
|
|
152 |
}
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
node.style.left = best.x + "px";
|
|
|
156 |
node.style.top = best.y + "px";
|
|
|
157 |
return best;
|
|
|
158 |
}
|
|
|
159 |
|
|
|
160 |
dijit.placeOnScreenAroundElement = function(
|
|
|
161 |
/* DomNode */ node,
|
|
|
162 |
/* DomNode */ aroundNode,
|
|
|
163 |
/* Object */ aroundCorners,
|
|
|
164 |
/* Function */ layoutNode){
|
|
|
165 |
|
|
|
166 |
// summary
|
|
|
167 |
// Like placeOnScreen, except it accepts aroundNode instead of x,y
|
|
|
168 |
// and attempts to place node around it. Uses margin box dimensions.
|
|
|
169 |
//
|
|
|
170 |
// aroundCorners
|
|
|
171 |
// specify Which corner of aroundNode should be
|
|
|
172 |
// used to place the node => which corner(s) of node to use (see the
|
|
|
173 |
// corners parameter in dijit.placeOnScreen)
|
|
|
174 |
// e.g. {'TL': 'BL', 'BL': 'TL'}
|
|
|
175 |
//
|
|
|
176 |
// layoutNode: Function(node, orient)
|
|
|
177 |
// for things like tooltip, they are displayed differently (and have different dimensions)
|
|
|
178 |
// based on their orientation relative to the parent. This adjusts the popup based on orientation.
|
|
|
179 |
|
|
|
180 |
|
|
|
181 |
// get coordinates of aroundNode
|
|
|
182 |
aroundNode = dojo.byId(aroundNode);
|
|
|
183 |
var oldDisplay = aroundNode.style.display;
|
|
|
184 |
aroundNode.style.display="";
|
|
|
185 |
// #3172: use the slightly tighter border box instead of marginBox
|
|
|
186 |
var aroundNodeW = aroundNode.offsetWidth; //mb.w;
|
|
|
187 |
var aroundNodeH = aroundNode.offsetHeight; //mb.h;
|
|
|
188 |
var aroundNodePos = dojo.coords(aroundNode, true);
|
|
|
189 |
aroundNode.style.display=oldDisplay;
|
|
|
190 |
|
|
|
191 |
// Generate list of possible positions for node
|
|
|
192 |
var choices = [];
|
|
|
193 |
for(var nodeCorner in aroundCorners){
|
|
|
194 |
choices.push( {
|
|
|
195 |
aroundCorner: nodeCorner,
|
|
|
196 |
corner: aroundCorners[nodeCorner],
|
|
|
197 |
pos: {
|
|
|
198 |
x: aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW),
|
|
|
199 |
y: aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH)
|
|
|
200 |
}
|
|
|
201 |
});
|
|
|
202 |
}
|
|
|
203 |
|
|
|
204 |
return dijit._place(node, choices, layoutNode);
|
|
|
205 |
}
|
|
|
206 |
|
|
|
207 |
}
|