summaryrefslogtreecommitdiff
path: root/includes/js/dijit/_base/popup.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dijit/_base/popup.js')
-rw-r--r--includes/js/dijit/_base/popup.js269
1 files changed, 269 insertions, 0 deletions
diff --git a/includes/js/dijit/_base/popup.js b/includes/js/dijit/_base/popup.js
new file mode 100644
index 0000000..6cb4dfc
--- /dev/null
+++ b/includes/js/dijit/_base/popup.js
@@ -0,0 +1,269 @@
+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.prepare = function(/*DomNode*/ node){
+ // summary:
+ // Prepares a node to be used as a popup
+ //
+ // description:
+ // Attaches node to dojo.doc.body, and
+ // positions it off screen, but not display:none, so that
+ // the widget doesn't appear in the page flow and/or cause a blank
+ // area at the bottom of the viewport (making scrollbar longer), but
+ // initialization of contained widgets works correctly
+
+ dojo.body().appendChild(node);
+ var s = node.style;
+ if(s.display == "none"){
+ s.display="";
+ }
+ s.visibility = "hidden"; // not needed for hiding, but used as flag that node is off-screen
+ s.position = "absolute";
+ s.top = "-9999px";
+ };
+
+ 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");
+ dijit.setWaiRole(wrapper, "presentation");
+ 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);
+
+ var s = widget.domNode.style;
+ s.display = "";
+ s.visibility = "";
+ s.position = "";
+ 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.
+ var getTopPopup = function(){
+ for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
+ /* do nothing, just trying to get right value for 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){
+ dojo.stopEvent(evt);
+ 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; }
+
+ this.prepare(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{
+ 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", dojo._scopeName + ".doc.getElementById('" + node.id + "').offsetWidth");
+ iframe.style.setExpression("height", dojo._scopeName + ".doc.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;
+ }
+ }
+});
+
+}