Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

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;
                }
        }
});

}