123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- 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 <table>, <ul>, 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 = "<iframe src='javascript:\"\"'"
- + " style='position: absolute; left: 0px; top: 0px;"
- + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
- iframe = dojo.doc.createElement(html);
- } else {
- var iframe = dojo.doc.createElement("iframe");
- iframe.src = 'javascript:""';
- iframe.className = "dijitBackgroundIframe";
- }
- iframe.tabIndex = -1; // Magic to prevent iframe from getting
- // focus on tab keypress - as style
- // didnt work.
- dojo.body().appendChild(iframe);
- }
- return iframe;
- };
- this.push = function(iframe) {
- iframe.style.display = "";
- if (dojo.isIE) {
- iframe.style.removeExpression("width");
- iframe.style.removeExpression("height");
- }
- queue.push(iframe);
- }
- }();
- // fill the queue
- if (dojo.isIE && dojo.isIE < 7) {
- dojo.addOnLoad(function() {
- var f = dijit._frames;
- dojo.forEach([f.pop()], f.push);
- });
- }
- dijit.BackgroundIframe = function(/* DomNode */node) {
- // summary:
- // For IE z-index schenanigans. id attribute is required.
- //
- // description:
- // new dijit.BackgroundIframe(node)
- // Makes a background iframe as a child of node, that fills
- // area (and position) of node
- if (!node.id) {
- throw new Error("no id");
- }
- if ((dojo.isIE && dojo.isIE < 7)
- || (dojo.isFF && dojo.isFF < 3 && dojo.hasClass(dojo.body(),
- "dijit_a11y"))) {
- var iframe = dijit._frames.pop();
- node.appendChild(iframe);
- if (dojo.isIE) {
- iframe.style.setExpression("width", "document.getElementById('"
- + node.id + "').offsetWidth");
- iframe.style.setExpression("height",
- "document.getElementById('" + node.id
- + "').offsetHeight");
- }
- this.iframe = iframe;
- }
- };
- dojo.extend(dijit.BackgroundIframe, {
- destroy : function() {
- // summary: destroy the iframe
- if (this.iframe) {
- dijit._frames.push(this.iframe);
- delete this.iframe;
- }
- }
- });
- }
|