if (!dojo._hasResource["dijit._base.popup"]) { // _hasResource checks added by
// build. Do not use
// _hasResource directly in your
// code.
dojo._hasResource["dijit._base.popup"] = true;
dojo.provide("dijit._base.popup");
dojo.require("dijit._base.focus");
dojo.require("dijit._base.place");
dojo.require("dijit._base.window");
dijit.popup = new function() {
// summary:
// This class is used to show/hide widgets as popups.
//
var stack = [], beginZIndex = 1000, idGen = 1;
this.open = function(/* Object */args) {
// summary:
// Popup the widget at the specified position
//
// args: Object
// popup: Widget
// widget to display,
// parent: Widget
// the button etc. that is displaying this popup
// around: DomNode
// DOM node (typically a button); place popup relative to this node
// orient: Object
// structure specifying possible positions of popup relative to
// "around" node
// onCancel: Function
// callback when user has canceled the popup by
// 1. hitting ESC or
// 2. by using the popup widget's proprietary cancel mechanism (like
// a cancel button in a dialog);
// ie: whenever popupWidget.onCancel() is called, args.onCancel is
// called
// onClose: Function
// callback whenever this popup is closed
// onExecute: Function
// callback when user "executed" on the popup/sub-popup by selecting
// a menu choice, etc. (top menu only)
//
// examples:
// 1. opening at the mouse position
// dijit.popup.open({popup: menuWidget, x: evt.pageX, y:
// evt.pageY});
// 2. opening the widget as a dropdown
// dijit.popup.open({parent: this, popup: menuWidget, around:
// this.domNode, onClose: function(){...} });
//
// Note that whatever widget called dijit.popup.open() should also
// listen to it's own _onBlur callback
// (fired from _base/focus.js) to know that focus has moved
// somewhere else and thus the popup should be closed.
var widget = args.popup, orient = args.orient || {
'BL' : 'TL',
'TL' : 'BL'
}, around = args.around, id = (args.around && args.around.id)
? (args.around.id + "_dropdown")
: ("popup_" + idGen++);
// make wrapper div to hold widget and possibly hold iframe behind
// it.
// we can't attach the iframe as a child of the widget.domNode
// because
// widget.domNode might be a
, , etc.
var wrapper = dojo.doc.createElement("div");
wrapper.id = id;
wrapper.className = "dijitPopup";
wrapper.style.zIndex = beginZIndex + stack.length;
wrapper.style.visibility = "hidden";
if (args.parent) {
wrapper.dijitPopupParent = args.parent.id;
}
dojo.body().appendChild(wrapper);
widget.domNode.style.display = "";
wrapper.appendChild(widget.domNode);
var iframe = new dijit.BackgroundIframe(wrapper);
// position the wrapper node
var best = around ? dijit.placeOnScreenAroundElement(wrapper,
around, orient, widget.orient ? dojo
.hitch(widget, "orient") : null) : dijit
.placeOnScreen(wrapper, args, orient == 'R' ? ['TR', 'BR',
'TL', 'BL'] : ['TL', 'BL', 'TR', 'BR']);
wrapper.style.visibility = "visible";
// TODO: use effects to fade in wrapper
var handlers = [];
// Compute the closest ancestor popup that's *not* a child of
// another popup.
// Ex: For a TooltipDialog with a button that spawns a tree of
// menus, find the popup of the button.
function getTopPopup() {
for (var pi = stack.length - 1; pi > 0
&& stack[pi].parent === stack[pi - 1].widget; pi--);
return stack[pi];
}
// provide default escape and tab key handling
// (this will work for any widget, not just menu)
handlers.push(dojo.connect(wrapper, "onkeypress", this, function(
evt) {
if (evt.keyCode == dojo.keys.ESCAPE && args.onCancel) {
args.onCancel();
} else if (evt.keyCode == dojo.keys.TAB) {
dojo.stopEvent(evt);
var topPopup = getTopPopup();
if (topPopup && topPopup.onCancel) {
topPopup.onCancel();
}
}
}));
// watch for cancel/execute events on the popup and notify the
// caller
// (for a menu, "execute" means clicking an item)
if (widget.onCancel) {
handlers.push(dojo.connect(widget, "onCancel", null,
args.onCancel));
}
handlers.push(dojo.connect(widget, widget.onExecute
? "onExecute"
: "onChange", null, function() {
var topPopup = getTopPopup();
if (topPopup && topPopup.onExecute) {
topPopup.onExecute();
}
}));
stack.push({
wrapper : wrapper,
iframe : iframe,
widget : widget,
parent : args.parent,
onExecute : args.onExecute,
onCancel : args.onCancel,
onClose : args.onClose,
handlers : handlers
});
if (widget.onOpen) {
widget.onOpen(best);
}
return best;
};
this.close = function(/* Widget */popup) {
// summary:
// Close specified popup and any popups that it parented
while (dojo.some(stack, function(elem) {
return elem.widget == popup;
})) {
var top = stack.pop(), wrapper = top.wrapper, iframe = top.iframe, widget = top.widget, onClose = top.onClose;
if (widget.onClose) {
widget.onClose();
}
dojo.forEach(top.handlers, dojo.disconnect);
// #2685: check if the widget still has a domNode so ContentPane
// can change its URL without getting an error
if (!widget || !widget.domNode) {
return;
}
dojo.style(widget.domNode, "display", "none");
dojo.body().appendChild(widget.domNode);
iframe.destroy();
dojo._destroyElement(wrapper);
if (onClose) {
onClose();
}
}
};
}();
dijit._frames = new function() {
// summary: cache of iframes
var queue = [];
this.pop = function() {
var iframe;
if (queue.length) {
iframe = queue.pop();
iframe.style.display = "";
} else {
if (dojo.isIE) {
var html = "