2150 |
mathias |
1 |
if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dijit._base.popup"] = true;
|
|
|
3 |
dojo.provide("dijit._base.popup");
|
|
|
4 |
|
|
|
5 |
dojo.require("dijit._base.focus");
|
|
|
6 |
dojo.require("dijit._base.place");
|
|
|
7 |
dojo.require("dijit._base.window");
|
|
|
8 |
|
|
|
9 |
dijit.popup = new function(){
|
|
|
10 |
// summary:
|
|
|
11 |
// This class is used to show/hide widgets as popups.
|
|
|
12 |
//
|
|
|
13 |
|
|
|
14 |
var stack = [],
|
|
|
15 |
beginZIndex=1000,
|
|
|
16 |
idGen = 1;
|
|
|
17 |
|
|
|
18 |
this.open = function(/*Object*/ args){
|
|
|
19 |
// summary:
|
|
|
20 |
// Popup the widget at the specified position
|
|
|
21 |
//
|
|
|
22 |
// args: Object
|
|
|
23 |
// popup: Widget
|
|
|
24 |
// widget to display,
|
|
|
25 |
// parent: Widget
|
|
|
26 |
// the button etc. that is displaying this popup
|
|
|
27 |
// around: DomNode
|
|
|
28 |
// DOM node (typically a button); place popup relative to this node
|
|
|
29 |
// orient: Object
|
|
|
30 |
// structure specifying possible positions of popup relative to "around" node
|
|
|
31 |
// onCancel: Function
|
|
|
32 |
// callback when user has canceled the popup by
|
|
|
33 |
// 1. hitting ESC or
|
|
|
34 |
// 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
|
|
|
35 |
// ie: whenever popupWidget.onCancel() is called, args.onCancel is called
|
|
|
36 |
// onClose: Function
|
|
|
37 |
// callback whenever this popup is closed
|
|
|
38 |
// onExecute: Function
|
|
|
39 |
// callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
|
|
|
40 |
//
|
|
|
41 |
// examples:
|
|
|
42 |
// 1. opening at the mouse position
|
|
|
43 |
// dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
|
|
|
44 |
// 2. opening the widget as a dropdown
|
|
|
45 |
// dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...} });
|
|
|
46 |
//
|
|
|
47 |
// Note that whatever widget called dijit.popup.open() should also listen to it's own _onBlur callback
|
|
|
48 |
// (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
|
|
|
49 |
|
|
|
50 |
var widget = args.popup,
|
|
|
51 |
orient = args.orient || {'BL':'TL', 'TL':'BL'},
|
|
|
52 |
around = args.around,
|
|
|
53 |
id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+idGen++);
|
|
|
54 |
|
|
|
55 |
// make wrapper div to hold widget and possibly hold iframe behind it.
|
|
|
56 |
// we can't attach the iframe as a child of the widget.domNode because
|
|
|
57 |
// widget.domNode might be a <table>, <ul>, etc.
|
|
|
58 |
var wrapper = dojo.doc.createElement("div");
|
|
|
59 |
wrapper.id = id;
|
|
|
60 |
wrapper.className="dijitPopup";
|
|
|
61 |
wrapper.style.zIndex = beginZIndex + stack.length;
|
|
|
62 |
wrapper.style.visibility = "hidden";
|
|
|
63 |
if(args.parent){
|
|
|
64 |
wrapper.dijitPopupParent=args.parent.id;
|
|
|
65 |
}
|
|
|
66 |
dojo.body().appendChild(wrapper);
|
|
|
67 |
|
|
|
68 |
widget.domNode.style.display="";
|
|
|
69 |
wrapper.appendChild(widget.domNode);
|
|
|
70 |
|
|
|
71 |
var iframe = new dijit.BackgroundIframe(wrapper);
|
|
|
72 |
|
|
|
73 |
// position the wrapper node
|
|
|
74 |
var best = around ?
|
|
|
75 |
dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
|
|
|
76 |
dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR']);
|
|
|
77 |
|
|
|
78 |
wrapper.style.visibility = "visible";
|
|
|
79 |
// TODO: use effects to fade in wrapper
|
|
|
80 |
|
|
|
81 |
var handlers = [];
|
|
|
82 |
|
|
|
83 |
// Compute the closest ancestor popup that's *not* a child of another popup.
|
|
|
84 |
// Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
|
|
|
85 |
function getTopPopup(){
|
|
|
86 |
for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--);
|
|
|
87 |
return stack[pi];
|
|
|
88 |
}
|
|
|
89 |
|
|
|
90 |
// provide default escape and tab key handling
|
|
|
91 |
// (this will work for any widget, not just menu)
|
|
|
92 |
handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
|
|
|
93 |
if(evt.keyCode == dojo.keys.ESCAPE && args.onCancel){
|
|
|
94 |
args.onCancel();
|
|
|
95 |
}else if(evt.keyCode == dojo.keys.TAB){
|
|
|
96 |
dojo.stopEvent(evt);
|
|
|
97 |
var topPopup = getTopPopup();
|
|
|
98 |
if(topPopup && topPopup.onCancel){
|
|
|
99 |
topPopup.onCancel();
|
|
|
100 |
}
|
|
|
101 |
}
|
|
|
102 |
}));
|
|
|
103 |
|
|
|
104 |
// watch for cancel/execute events on the popup and notify the caller
|
|
|
105 |
// (for a menu, "execute" means clicking an item)
|
|
|
106 |
if(widget.onCancel){
|
|
|
107 |
handlers.push(dojo.connect(widget, "onCancel", null, args.onCancel));
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", null, function(){
|
|
|
111 |
var topPopup = getTopPopup();
|
|
|
112 |
if(topPopup && topPopup.onExecute){
|
|
|
113 |
topPopup.onExecute();
|
|
|
114 |
}
|
|
|
115 |
}));
|
|
|
116 |
|
|
|
117 |
stack.push({
|
|
|
118 |
wrapper: wrapper,
|
|
|
119 |
iframe: iframe,
|
|
|
120 |
widget: widget,
|
|
|
121 |
parent: args.parent,
|
|
|
122 |
onExecute: args.onExecute,
|
|
|
123 |
onCancel: args.onCancel,
|
|
|
124 |
onClose: args.onClose,
|
|
|
125 |
handlers: handlers
|
|
|
126 |
});
|
|
|
127 |
|
|
|
128 |
if(widget.onOpen){
|
|
|
129 |
widget.onOpen(best);
|
|
|
130 |
}
|
|
|
131 |
|
|
|
132 |
return best;
|
|
|
133 |
};
|
|
|
134 |
|
|
|
135 |
this.close = function(/*Widget*/ popup){
|
|
|
136 |
// summary:
|
|
|
137 |
// Close specified popup and any popups that it parented
|
|
|
138 |
while(dojo.some(stack, function(elem){return elem.widget == popup;})){
|
|
|
139 |
var top = stack.pop(),
|
|
|
140 |
wrapper = top.wrapper,
|
|
|
141 |
iframe = top.iframe,
|
|
|
142 |
widget = top.widget,
|
|
|
143 |
onClose = top.onClose;
|
|
|
144 |
|
|
|
145 |
if(widget.onClose){
|
|
|
146 |
widget.onClose();
|
|
|
147 |
}
|
|
|
148 |
dojo.forEach(top.handlers, dojo.disconnect);
|
|
|
149 |
|
|
|
150 |
// #2685: check if the widget still has a domNode so ContentPane can change its URL without getting an error
|
|
|
151 |
if(!widget||!widget.domNode){ return; }
|
|
|
152 |
dojo.style(widget.domNode, "display", "none");
|
|
|
153 |
dojo.body().appendChild(widget.domNode);
|
|
|
154 |
iframe.destroy();
|
|
|
155 |
dojo._destroyElement(wrapper);
|
|
|
156 |
|
|
|
157 |
if(onClose){
|
|
|
158 |
onClose();
|
|
|
159 |
}
|
|
|
160 |
}
|
|
|
161 |
};
|
|
|
162 |
}();
|
|
|
163 |
|
|
|
164 |
dijit._frames = new function(){
|
|
|
165 |
// summary: cache of iframes
|
|
|
166 |
var queue = [];
|
|
|
167 |
|
|
|
168 |
this.pop = function(){
|
|
|
169 |
var iframe;
|
|
|
170 |
if(queue.length){
|
|
|
171 |
iframe = queue.pop();
|
|
|
172 |
iframe.style.display="";
|
|
|
173 |
}else{
|
|
|
174 |
if(dojo.isIE){
|
|
|
175 |
var html="<iframe src='javascript:\"\"'"
|
|
|
176 |
+ " style='position: absolute; left: 0px; top: 0px;"
|
|
|
177 |
+ "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
|
|
|
178 |
iframe = dojo.doc.createElement(html);
|
|
|
179 |
}else{
|
|
|
180 |
var iframe = dojo.doc.createElement("iframe");
|
|
|
181 |
iframe.src = 'javascript:""';
|
|
|
182 |
iframe.className = "dijitBackgroundIframe";
|
|
|
183 |
}
|
|
|
184 |
iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
|
|
|
185 |
dojo.body().appendChild(iframe);
|
|
|
186 |
}
|
|
|
187 |
return iframe;
|
|
|
188 |
};
|
|
|
189 |
|
|
|
190 |
this.push = function(iframe){
|
|
|
191 |
iframe.style.display="";
|
|
|
192 |
if(dojo.isIE){
|
|
|
193 |
iframe.style.removeExpression("width");
|
|
|
194 |
iframe.style.removeExpression("height");
|
|
|
195 |
}
|
|
|
196 |
queue.push(iframe);
|
|
|
197 |
}
|
|
|
198 |
}();
|
|
|
199 |
|
|
|
200 |
// fill the queue
|
|
|
201 |
if(dojo.isIE && dojo.isIE < 7){
|
|
|
202 |
dojo.addOnLoad(function(){
|
|
|
203 |
var f = dijit._frames;
|
|
|
204 |
dojo.forEach([f.pop()], f.push);
|
|
|
205 |
});
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
|
|
|
209 |
dijit.BackgroundIframe = function(/* DomNode */node){
|
|
|
210 |
// summary:
|
|
|
211 |
// For IE z-index schenanigans. id attribute is required.
|
|
|
212 |
//
|
|
|
213 |
// description:
|
|
|
214 |
// new dijit.BackgroundIframe(node)
|
|
|
215 |
// Makes a background iframe as a child of node, that fills
|
|
|
216 |
// area (and position) of node
|
|
|
217 |
|
|
|
218 |
if(!node.id){ throw new Error("no id"); }
|
|
|
219 |
if((dojo.isIE && dojo.isIE < 7) || (dojo.isFF && dojo.isFF < 3 && dojo.hasClass(dojo.body(), "dijit_a11y"))){
|
|
|
220 |
var iframe = dijit._frames.pop();
|
|
|
221 |
node.appendChild(iframe);
|
|
|
222 |
if(dojo.isIE){
|
|
|
223 |
iframe.style.setExpression("width", "document.getElementById('" + node.id + "').offsetWidth");
|
|
|
224 |
iframe.style.setExpression("height", "document.getElementById('" + node.id + "').offsetHeight");
|
|
|
225 |
}
|
|
|
226 |
this.iframe = iframe;
|
|
|
227 |
}
|
|
|
228 |
};
|
|
|
229 |
|
|
|
230 |
dojo.extend(dijit.BackgroundIframe, {
|
|
|
231 |
destroy: function(){
|
|
|
232 |
// summary: destroy the iframe
|
|
|
233 |
if(this.iframe){
|
|
|
234 |
dijit._frames.push(this.iframe);
|
|
|
235 |
delete this.iframe;
|
|
|
236 |
}
|
|
|
237 |
}
|
|
|
238 |
});
|
|
|
239 |
|
|
|
240 |
}
|