dijit/_base/popup.js

  • Provides:

    • dijit
  • dijit.popup

    • type
      Object
    • summary
      This singleton is used to show/hide widgets as popups.
  • dijit.popup._stack

    • type
      dijit._Widget[
    • summary
      Stack of currently popped up widgets.
      (someone opened _stack[0], and then it opened _stack[1], etc.)
  • dijit.popup._beginZIndex

    • type
      Number
    • summary
      Z-index of the first popup.   (If first popup opens other
      popups they get a higher z-index.)
  • dijit.popup._idGen

    • summary
  • dijit.popup._createWrapper

    • type
      Function
    • parameters:
      • widget: (typeof Widget || DomNode)
    • source: [view]
        var wrapper = widget.declaredClass ? widget._popupWrapper : (widget.parentNode && dojo.hasClass(widget.parentNode, "dijitPopup")),
         node = widget.domNode || widget;


        if(!wrapper){
         // Create wrapper
      for when this widget [in the future] will be used as a popup.
         // This is done early because of IE bugs where creating/moving DOM nodes causes focus
         // to go wonky, see tests/robot/Toolbar.html to reproduce
         wrapper = dojo.create("div",{
          "class":"dijitPopup",
          style:{ display: "none"},
          role: "presentation"
         }, dojo.body());
         wrapper.appendChild(node);


         var s = node.style;
         s.display = "";
         s.visibility = "";
         s.position = "";
         s.top = "0px";


         if(widget.declaredClass){  // TODO: in 2.0 change signature to always take widget, then remove if()
          widget._popupWrapper = wrapper;
          dojo.connect(widget, "destroy", function(){
           dojo.destroy(wrapper);
           delete widget._popupWrapper;
          });
         }
        }

        
        return wrapper;
    • summary
      Initialization for widgets that will be used as popups.
      Puts widget inside a wrapper DIV (if not already in one),
      and returns pointer to that wrapper DIV.
  • dijit.popup.moveOffScreen

    • type
      Function
    • parameters:
      • widget: (typeof Widget || DomNode)
    • source: [view]
      define("dijit/_base/popup", ["dojo", "dijit", "dijit/_base/focus", "dijit/_base/place", "dijit/_base/window"], function(dojo, dijit) {




      dijit.popup.__OpenArgs = function(){
       // 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. (Specify this *or* "x" and "y" parameters.)
       // x: Integer
       //  Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // y: Integer
       //  Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // orient: Object|String
       //  When the around parameter is specified, orient should be an
       //  ordered list of tuples of the form (around-node-corner, popup-node-corner).
       //  dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
       //  until the popup appears fully within the viewport.
       //
       //  The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
       //   1. (BL, TL)
       //   2. (TL, BL)
       //  where BL means "bottom left" and "TL" means "top left".
       //  So by default, it first tries putting the popup below the around node, left-aligning them,
       //  and then tries to put it above the around node, still left-aligning them. Note that the
       //  default is horizontally reversed when in RTL mode.
       //
       //  When an (x,y) position is specified rather than an around node, orient is either
       //  "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
       //  specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
       //  fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
       //  and the top-right corner.
       // 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);
       //    i.e. 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)
       // padding: dijit.__Position
       //  adding a buffer around the opening position. This is only useful when around is not set.
       this.popup = popup;
       this.parent = parent;
       this.around = around;
       this.x = x;
       this.y = y;
       this.orient = orient;
       this.onCancel = onCancel;
       this.onClose = onClose;
       this.onExecute = onExecute;
       this.padding = padding;
      }




      dijit.popup = {
       // summary:
       //  This singleton is used to show/hide widgets as popups.


       // _stack: dijit._Widget[]
       //  Stack of currently popped up widgets.
       //  (someone opened _stack[0], and then it opened _stack[1], etc.)
       _stack: [],

       
       // _beginZIndex: Number
       //  Z-index of the first popup. (If first popup opens other
       //  popups they get a higher z-index.)
       _beginZIndex: 1000,


       _idGen: 1,


       _createWrapper: function(/*Widget || DomNode*/ widget){
        // summary:
        //  Initialization for widgets that will be used as popups.
        //  Puts widget inside a wrapper DIV (if not already in one),
        //  and returns pointer to that wrapper DIV.


        var wrapper = widget.declaredClass ? widget._popupWrapper : (widget.parentNode && dojo.hasClass(widget.parentNode, "dijitPopup")),
         node = widget.domNode || widget;


        if(!wrapper){
         // Create wrapper
      for when this widget [in the future] will be used as a popup.
         // This is done early because of IE bugs where creating/moving DOM nodes causes focus
         // to go wonky, see tests/robot/Toolbar.html to reproduce
         wrapper = dojo.create("div",{
          "class":"dijitPopup",
          style:{ display: "none"},
          role: "presentation"
         }, dojo.body());
         wrapper.appendChild(node);


         var s = node.style;
         s.display = "";
         s.visibility = "";
         s.position = "";
         s.top = "0px";


         if(widget.declaredClass){  // TODO: in 2.0 change signature to always take widget, then remove if()
          widget._popupWrapper = wrapper;
          dojo.connect(widget, "destroy", function(){
           dojo.destroy(wrapper);
           delete widget._popupWrapper;
          });
         }
        }

        
        return wrapper;
       },


       moveOffScreen: function(/*Widget || DomNode*/ widget){
        // summary:
        //  Moves the popup widget off-screen.
        //  Do not use this method to hide popups when not in use, because
        //  that will create an accessibility issue: the offscreen popup is
        //  still in the tabbing order.


        // Create wrapper if not already there
        var wrapper = this._createWrapper(widget);


        dojo.style(wrapper, {
         visibility: "hidden",
         top: "-9999px",  // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
         display: ""
        });
    • summary
  • dijit.popup.hide

    • type
      Function
    • parameters:
      • widget: (typeof dijit._Widget)
    • source: [view]
      define("dijit/_base/popup", ["dojo", "dijit", "dijit/_base/focus", "dijit/_base/place", "dijit/_base/window"], function(dojo, dijit) {




      dijit.popup.__OpenArgs = function(){
       // 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. (Specify this *or* "x" and "y" parameters.)
       // x: Integer
       //  Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // y: Integer
       //  Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // orient: Object|String
       //  When the around parameter is specified, orient should be an
       //  ordered list of tuples of the form (around-node-corner, popup-node-corner).
       //  dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
       //  until the popup appears fully within the viewport.
       //
       //  The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
       //   1. (BL, TL)
       //   2. (TL, BL)
       //  where BL means "bottom left" and "TL" means "top left".
       //  So by default, it first tries putting the popup below the around node, left-aligning them,
       //  and then tries to put it above the around node, still left-aligning them. Note that the
       //  default is horizontally reversed when in RTL mode.
       //
       //  When an (x,y) position is specified rather than an around node, orient is either
       //  "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
       //  specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
       //  fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
       //  and the top-right corner.
       // 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);
       //    i.e. 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)
       // padding: dijit.__Position
       //  adding a buffer around the opening position. This is only useful when around is not set.
       this.popup = popup;
       this.parent = parent;
       this.around = around;
       this.x = x;
       this.y = y;
       this.orient = orient;
       this.onCancel = onCancel;
       this.onClose = onClose;
       this.onExecute = onExecute;
       this.padding = padding;
      }




      dijit.popup = {
       // summary:
       //  This singleton is used to show/hide widgets as popups.


       // _stack: dijit._Widget[]
       //  Stack of currently popped up widgets.
       //  (someone opened _stack[0], and then it opened _stack[1], etc.)
       _stack: [],

       
       // _beginZIndex: Number
       //  Z-index of the first popup. (If first popup opens other
       //  popups they get a higher z-index.)
       _beginZIndex: 1000,


       _idGen: 1,


       _createWrapper: function(/*Widget || DomNode*/ widget){
        // summary:
        //  Initialization for widgets that will be used as popups.
        //  Puts widget inside a wrapper DIV (if not already in one),
        //  and returns pointer to that wrapper DIV.


        var wrapper = widget.declaredClass ? widget._popupWrapper : (widget.parentNode && dojo.hasClass(widget.parentNode, "dijitPopup")),
         node = widget.domNode || widget;


        if(!wrapper){
         // Create wrapper
      for when this widget [in the future] will be used as a popup.
         // This is done early because of IE bugs where creating/moving DOM nodes causes focus
         // to go wonky, see tests/robot/Toolbar.html to reproduce
         wrapper = dojo.create("div",{
          "class":"dijitPopup",
          style:{ display: "none"},
          role: "presentation"
         }, dojo.body());
         wrapper.appendChild(node);


         var s = node.style;
         s.display = "";
         s.visibility = "";
         s.position = "";
         s.top = "0px";


         if(widget.declaredClass){  // TODO: in 2.0 change signature to always take widget, then remove if()
          widget._popupWrapper = wrapper;
          dojo.connect(widget, "destroy", function(){
           dojo.destroy(wrapper);
           delete widget._popupWrapper;
          });
         }
        }

        
        return wrapper;
       },


       moveOffScreen: function(/*Widget || DomNode*/ widget){
        // summary:
        //  Moves the popup widget off-screen.
        //  Do not use this method to hide popups when not in use, because
        //  that will create an accessibility issue: the offscreen popup is
        //  still in the tabbing order.


        // Create wrapper if not already there
        var wrapper = this._createWrapper(widget);


        dojo.style(wrapper, {
         visibility: "hidden",
         top: "-9999px",  // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
         display: ""
        });
       },


       hide: function(/*dijit._Widget*/ widget){
        // summary:
        //  Hide this popup widget (until it is ready to be shown).
        //  Initialization for widgets that will be used as popups
        //
        //   Also puts widget inside a wrapper DIV (if not already in one)
        //
        //  If popup widget needs to layout it should
        //  do so when it is made visible, and popup._onShow() is called.


        // Create wrapper if not already there
        var wrapper = this._createWrapper(widget);


        dojo.style(wrapper, "display", "none");
    • summary
  • dijit.popup.getTopPopup

    • type
      Function
    • source: [view]
        var stack = this._stack;
        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];
    • summary
      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.
  • dijit.popup.open

    • type
      Function
    • parameters:
      • args: (typeof dijit.popup.__OpenArgs)
    • source: [view]
        var stack = this._stack,
         widget = args.popup,
         orient = args.orient || (
          (args.parent ? args.parent.isLeftToRight() : dojo._isBodyLtr()) ?
          {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
          {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'}
         ),
         around = args.around,
         id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);


        // If we are opening a new popup that isn't a child of a currently opened popup, then
        // close currently opened popup(s). This should happen automatically when the old popups
        // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
        while(stack.length && (!args.parent || !dojo.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
         dijit.popup.close(stack[stack.length-1].widget);
        }


        // Get pointer to popup wrapper, and create wrapper if it doesn't exist
        var wrapper = this._createWrapper(widget);




        dojo.attr(wrapper, {
         id: id,
         style: {
          zIndex: this._beginZIndex + stack.length
         },
         "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
         dijitPopupParent: args.parent ? args.parent.id : ""
        });


        if(dojo.isIE || dojo.isMoz){
         if(!widget.bgIframe){
          // setting widget.bgIframe triggers cleanup in _Widget.destroy()
          widget.bgIframe = new dijit.BackgroundIframe(wrapper);
         }
        }


        // position the wrapper node and make it visible
        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'], args.padding);


        wrapper.style.display = "";
        wrapper.style.visibility = "visible";
        widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown


        var handlers = [];


        // 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.charOrCode == dojo.keys.ESCAPE && args.onCancel){
          dojo.stopEvent(evt);
          args.onCancel();
         }else if(evt.charOrCode === dojo.keys.TAB){
          dojo.stopEvent(evt);
          var topPopup = this.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", args.onCancel));
        }


        handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", this, function(){
         var topPopup = this.getTopPopup();
         if(topPopup && topPopup.onExecute){
          topPopup.onExecute();
         }
        }));


        stack.push({
         widget: widget,
         parent: args.parent,
         onExecute: args.onExecute,
         onCancel: args.onCancel,
         onClose: args.onClose,
         handlers: handlers
        });


        if(widget.onOpen){
         // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
         widget.onOpen(best);
        }


        return best;
    • summary
      Popup the widget at the specified position
    • example
      opening at the mouse position
      
      		dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
    • example
      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 its own _onBlur callback
      (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  • dijit.popup.close

    • type
      Function
    • parameters:
      • popup: (typeof dijit._Widget)
    • source: [view]
        var stack = this._stack;


        // Basically work backwards from the top of the stack closing popups
        // until we hit the specified popup, but IIRC there was some issue where closing
        // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C]
        // closing C might close B indirectly and then the while() condition will run where stack==[A]...
        // so the while condition is constructed defensively.
        while((popup && dojo.some(stack, function(elem){return elem.widget == popup;})) ||
         (!popup && stack.length)){
         var top = stack.pop(),
          widget = top.widget,
          onClose = top.onClose;


         if(widget.onClose){
          // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
          widget.onClose();
         }
         dojo.forEach(top.handlers, dojo.disconnect);


         // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
         if(widget && widget.domNode){
          this.hide(widget);
         }


         if(onClose){
          onClose();
         }
        }
    • summary
      Close specified popup and any popups that it parented.
      If no popup is specified, closes all popups.
  • dijit.popup.__OpenArgs

    • type
      Function
    • source: [view]
      define("dijit/_base/popup", ["dojo", "dijit", "dijit/_base/focus", "dijit/_base/place", "dijit/_base/window"], function(dojo, dijit) {




      dijit.popup.__OpenArgs = function(){
       // 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. (Specify this *or* "x" and "y" parameters.)
       // x: Integer
       //  Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // y: Integer
       //  Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
       // orient: Object|String
       //  When the around parameter is specified, orient should be an
       //  ordered list of tuples of the form (around-node-corner, popup-node-corner).
       //  dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
       //  until the popup appears fully within the viewport.
       //
       //  The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
       //   1. (BL, TL)
       //   2. (TL, BL)
       //  where BL means "bottom left" and "TL" means "top left".
       //  So by default, it first tries putting the popup below the around node, left-aligning them,
       //  and then tries to put it above the around node, still left-aligning them. Note that the
       //  default is horizontally reversed when in RTL mode.
       //
       //  When an (x,y) position is specified rather than an around node, orient is either
       //  "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
       //  specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
       //  fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
       //  and the top-right corner.
       // 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);
       //    i.e. 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)
       // padding: dijit.__Position
       //  adding a buffer around the opening position. This is only useful when around is not set.
       this.popup = popup;
       this.parent = parent;
       this.around = around;
       this.x = x;
       this.y = y;
       this.orient = orient;
       this.onCancel = onCancel;
       this.onClose = onClose;
       this.onExecute = onExecute;
       this.padding = padding;
    • summary
  • dijit.popup.__OpenArgs.popup

    • type
      Widget
    • summary
      widget to display
  • dijit.popup.__OpenArgs.parent

    • type
      Widget
    • summary
      the button etc. that is displaying this popup
  • dijit.popup.__OpenArgs.around

    • type
      DomNode
    • summary
      DOM node (typically a button); place popup relative to this node.  (Specify this *or* "x" and "y" parameters.)
  • dijit.popup.__OpenArgs.x

    • type
      Integer
    • summary
      Absolute horizontal position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
  • dijit.popup.__OpenArgs.y

    • type
      Integer
    • summary
      Absolute vertical position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
  • dijit.popup.__OpenArgs.orient

    • type
      Object|String
    • summary
      When the around parameter is specified, orient should be an
      ordered list of tuples of the form (around-node-corner, popup-node-corner).
      dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
      until the popup appears fully within the viewport.
      
      The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
      1. (BL, TL)
      2. (TL, BL)
      where BL means "bottom left" and "TL" means "top left".
      So by default, it first tries putting the popup below the around node, left-aligning them,
      and then tries to put it above the around node, still left-aligning them.   Note that the
      default is horizontally reversed when in RTL mode.
      
      When an (x,y) position is specified rather than an around node, orient is either
      "R" or "L".  R (for right) means that it tries to put the popup to the right of the mouse,
      specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
      fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
      and the top-right corner.
  • dijit.popup.__OpenArgs.onCancel

    • type
      Function
    • summary
      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);
      i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
  • dijit.popup.__OpenArgs.onClose

    • type
      Function
    • summary
      callback whenever this popup is closed
  • dijit.popup.__OpenArgs.onExecute

    • type
      Function
    • summary
      callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
  • dijit.popup.__OpenArgs.padding

    • type
      dijit.__Position
    • summary
      adding a buffer around the opening position. This is only useful when around is not set.
  • dijit._frames

    • type
      Function
    • ?? initialized = 1 (debug: boolean) ??
    • source: [view]
       var queue = [];


       this.pop = function(){
        var iframe;
        if(queue.length){
         iframe = queue.pop();
         iframe.style.display="";
        }else{
         if(dojo.isIE < 9){
          var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"") || "javascript:\"\"";
          var html="