From f0cfe83e3725f9a3928da97a6e3085e79cb25309 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 18 Mar 2013 10:26:24 +0400 Subject: upgrade dojo to 1.8.3 (refs #570) --- lib/dijit/_MenuBase.js.uncompressed.js | 429 +++++++++++++++++++++++++++++++++ 1 file changed, 429 insertions(+) create mode 100644 lib/dijit/_MenuBase.js.uncompressed.js (limited to 'lib/dijit/_MenuBase.js.uncompressed.js') diff --git a/lib/dijit/_MenuBase.js.uncompressed.js b/lib/dijit/_MenuBase.js.uncompressed.js new file mode 100644 index 000000000..4a0719e6a --- /dev/null +++ b/lib/dijit/_MenuBase.js.uncompressed.js @@ -0,0 +1,429 @@ +define("dijit/_MenuBase", [ + "dojo/_base/array", // array.indexOf + "dojo/_base/declare", // declare + "dojo/dom", // dom.isDescendant domClass.replace + "dojo/dom-attr", + "dojo/dom-class", // domClass.replace + "dojo/_base/lang", // lang.hitch + "dojo/mouse", // mouse.enter, mouse.leave + "dojo/on", + "dojo/window", + "./a11yclick", + "./popup", + "./registry", + "./_Widget", + "./_KeyNavContainer", + "./_TemplatedMixin" +], function(array, declare, dom, domAttr, domClass, lang, mouse, on, winUtils, + a11yclick, pm, registry, _Widget, _KeyNavContainer, _TemplatedMixin){ + + +// module: +// dijit/_MenuBase + +return declare("dijit._MenuBase", + [_Widget, _TemplatedMixin, _KeyNavContainer], +{ + // summary: + // Base class for Menu and MenuBar + + // parentMenu: [readonly] Widget + // pointer to menu that displayed me + parentMenu: null, + + // popupDelay: Integer + // number of milliseconds before hovering (without clicking) causes the popup to automatically open. + popupDelay: 500, + + // autoFocus: Boolean + // A toggle to control whether or not a Menu gets focused when opened as a drop down from a MenuBar + // or DropDownButton/ComboButton. Note though that it always get focused when opened via the keyboard. + autoFocus: false, + + childSelector: function(/*DOMNode*/ node){ + // summary: + // Selector (passed to on.selector()) used to identify MenuItem child widgets, but exclude inert children + // like MenuSeparator. If subclass overrides to a string (ex: "> *"), the subclass must require dojo/query. + // tags: + // protected + + var widget = registry.byNode(node); + return node.parentNode == this.containerNode && widget && widget.focus; + }, + + postCreate: function(){ + var self = this, + matches = typeof this.childSelector == "string" ? this.childSelector : lang.hitch(this, "childSelector"); + this.own( + on(this.containerNode, on.selector(matches, mouse.enter), function(){ + self.onItemHover(registry.byNode(this)); + }), + on(this.containerNode, on.selector(matches, mouse.leave), function(){ + self.onItemUnhover(registry.byNode(this)); + }), + on(this.containerNode, on.selector(matches, a11yclick), function(evt){ + self.onItemClick(registry.byNode(this), evt); + evt.stopPropagation(); + evt.preventDefault(); + }) + ); + this.inherited(arguments); + }, + + onExecute: function(){ + // summary: + // Attach point for notification about when a menu item has been executed. + // This is an internal mechanism used for Menus to signal to their parent to + // close them, because they are about to execute the onClick handler. In + // general developers should not attach to or override this method. + // tags: + // protected + }, + + onCancel: function(/*Boolean*/ /*===== closeAll =====*/){ + // summary: + // Attach point for notification about when the user cancels the current menu + // This is an internal mechanism used for Menus to signal to their parent to + // close them. In general developers should not attach to or override this method. + // tags: + // protected + }, + + _moveToPopup: function(/*Event*/ evt){ + // summary: + // This handles the right arrow key (left arrow key on RTL systems), + // which will either open a submenu, or move to the next item in the + // ancestor MenuBar + // tags: + // private + + if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){ + this.onItemClick(this.focusedChild, evt); + }else{ + var topMenu = this._getTopMenu(); + if(topMenu && topMenu._isMenuBar){ + topMenu.focusNext(); + } + } + }, + + _onPopupHover: function(/*Event*/ /*===== evt =====*/){ + // summary: + // This handler is called when the mouse moves over the popup. + // tags: + // private + + // if the mouse hovers over a menu popup that is in pending-close state, + // then stop the close operation. + // This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker) + if(this.currentPopup && this.currentPopup._pendingClose_timer){ + var parentMenu = this.currentPopup.parentMenu; + // highlight the parent menu item pointing to this popup + if(parentMenu.focusedChild){ + parentMenu.focusedChild._setSelected(false); + } + parentMenu.focusedChild = this.currentPopup.from_item; + parentMenu.focusedChild._setSelected(true); + // cancel the pending close + this._stopPendingCloseTimer(this.currentPopup); + } + }, + + onItemHover: function(/*MenuItem*/ item){ + // summary: + // Called when cursor is over a MenuItem. + // tags: + // protected + + // Don't do anything unless user has "activated" the menu by: + // 1) clicking it + // 2) opening it from a parent menu (which automatically focuses it) + if(this.isActive){ + this.focusChild(item); + if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){ + this.hover_timer = this.defer("_openPopup", this.popupDelay); + } + } + // if the user is mixing mouse and keyboard navigation, + // then the menu may not be active but a menu item has focus, + // but it's not the item that the mouse just hovered over. + // To avoid both keyboard and mouse selections, use the latest. + if(this.focusedChild){ + this.focusChild(item); + } + this._hoveredChild = item; + + item._set("hovering", true); + }, + + _onChildBlur: function(item){ + // summary: + // Called when a child MenuItem becomes inactive because focus + // has been removed from the MenuItem *and* it's descendant menus. + // tags: + // private + this._stopPopupTimer(); + item._setSelected(false); + // Close all popups that are open and descendants of this menu + var itemPopup = item.popup; + if(itemPopup){ + this._stopPendingCloseTimer(itemPopup); + itemPopup._pendingClose_timer = this.defer(function(){ + itemPopup._pendingClose_timer = null; + if(itemPopup.parentMenu){ + itemPopup.parentMenu.currentPopup = null; + } + pm.close(itemPopup); // this calls onClose + }, this.popupDelay); + } + }, + + onItemUnhover: function(/*MenuItem*/ item){ + // summary: + // Callback fires when mouse exits a MenuItem + // tags: + // protected + + if(this.isActive){ + this._stopPopupTimer(); + } + if(this._hoveredChild == item){ this._hoveredChild = null; } + + item._set("hovering", false); + }, + + _stopPopupTimer: function(){ + // summary: + // Cancels the popup timer because the user has stop hovering + // on the MenuItem, etc. + // tags: + // private + if(this.hover_timer){ + this.hover_timer = this.hover_timer.remove(); + } + }, + + _stopPendingCloseTimer: function(/*dijit/_WidgetBase*/ popup){ + // summary: + // Cancels the pending-close timer because the close has been preempted + // tags: + // private + if(popup._pendingClose_timer){ + popup._pendingClose_timer = popup._pendingClose_timer.remove(); + } + }, + + _stopFocusTimer: function(){ + // summary: + // Cancels the pending-focus timer because the menu was closed before focus occured + // tags: + // private + if(this._focus_timer){ + this._focus_timer = this._focus_timer.remove(); + } + }, + + _getTopMenu: function(){ + // summary: + // Returns the top menu in this chain of Menus + // tags: + // private + for(var top=this; top.parentMenu; top=top.parentMenu); + return top; + }, + + onItemClick: function(/*dijit/_WidgetBase*/ item, /*Event*/ evt){ + // summary: + // Handle clicks on an item. + // tags: + // private + + // this can't be done in _onFocus since the _onFocus events occurs asynchronously + if(typeof this.isShowingNow == 'undefined'){ // non-popup menu + this._markActive(); + } + + this.focusChild(item); + + if(item.disabled){ return false; } + + if(item.popup){ + this._openPopup(evt.type == "keypress"); + }else{ + // before calling user defined handler, close hierarchy of menus + // and restore focus to place it was when menu was opened + this.onExecute(); + + // user defined handler for click + item._onClick ? item._onClick(evt) : item.onClick(evt); + } + }, + + _openPopup: function(/*Boolean*/ focus){ + // summary: + // Open the popup to the side of/underneath the current menu item, and optionally focus first item + // tags: + // protected + + this._stopPopupTimer(); + var from_item = this.focusedChild; + if(!from_item){ return; } // the focused child lost focus since the timer was started + var popup = from_item.popup; + if(!popup.isShowingNow){ + if(this.currentPopup){ + this._stopPendingCloseTimer(this.currentPopup); + pm.close(this.currentPopup); + } + popup.parentMenu = this; + popup.from_item = from_item; // helps finding the parent item that should be focused for this popup + var self = this; + pm.open({ + parent: this, + popup: popup, + around: from_item.domNode, + orient: this._orient || ["after", "before"], + onCancel: function(){ // called when the child menu is canceled + // set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus + // which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro) + self.focusChild(from_item); // put focus back on my node + self._cleanUp(); // close the submenu (be sure this is done _after_ focus is moved) + from_item._setSelected(true); // oops, _cleanUp() deselected the item + self.focusedChild = from_item; // and unset focusedChild + }, + onExecute: lang.hitch(this, "_cleanUp") + }); + + this.currentPopup = popup; + // detect mouseovers to handle lazy mouse movements that temporarily focus other menu items + popup.connect(popup.domNode, "onmouseenter", lang.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close + } + + if(focus && popup.focus){ + // If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar), then focus the popup. + // If the cursor happens to collide with the popup, it will generate an onmouseover event + // even though the mouse wasn't moved. Use defer() to call popup.focus so that + // our focus() call overrides the onmouseover event, rather than vice-versa. (#8742) + popup._focus_timer = this.defer(lang.hitch(popup, function(){ + this._focus_timer = null; + this.focus(); + })); + } + }, + + _markActive: function(){ + // summary: + // Mark this menu's state as active. + // Called when this Menu gets focus from: + // + // 1. clicking it (mouse or via space/arrow key) + // 2. being opened by a parent menu. + // + // This is not called just from mouse hover. + // Focusing a menu via TAB does NOT automatically set isActive + // since TAB is a navigation operation and not a selection one. + // For Windows apps, pressing the ALT key focuses the menubar + // menus (similar to TAB navigation) but the menu is not active + // (ie no dropdown) until an item is clicked. + this.isActive = true; + domClass.replace(this.domNode, "dijitMenuActive", "dijitMenuPassive"); + }, + + onOpen: function(/*Event*/ /*===== e =====*/){ + // summary: + // Callback when this menu is opened. + // This is called by the popup manager as notification that the menu + // was opened. + // tags: + // private + + this.isShowingNow = true; + this._markActive(); + }, + + _markInactive: function(){ + // summary: + // Mark this menu's state as inactive. + this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here + domClass.replace(this.domNode, "dijitMenuPassive", "dijitMenuActive"); + }, + + onClose: function(){ + // summary: + // Callback when this menu is closed. + // This is called by the popup manager as notification that the menu + // was closed. + // tags: + // private + + this._stopFocusTimer(); + this._markInactive(); + this.isShowingNow = false; + this.parentMenu = null; + }, + + _closeChild: function(){ + // summary: + // Called when submenu is clicked or focus is lost. Close hierarchy of menus. + // tags: + // private + this._stopPopupTimer(); + + if(this.currentPopup){ + // If focus is on a descendant MenuItem then move focus to me, + // because IE doesn't like it when you display:none a node with focus, + // and also so keyboard users don't lose control. + // Likely, immediately after a user defined onClick handler will move focus somewhere + // else, like a Dialog. + if(array.indexOf(this._focusManager.activeStack, this.id) >= 0){ + domAttr.set(this.focusedChild.focusNode, "tabIndex", this.tabIndex); + this.focusedChild.focusNode.focus(); + } + // Close all popups that are open and descendants of this menu + pm.close(this.currentPopup); + this.currentPopup = null; + } + + if(this.focusedChild){ // unhighlight the focused item + this.focusedChild._setSelected(false); + this.onItemUnhover(this.focusedChild); + this.focusedChild = null; + } + }, + + _onItemFocus: function(/*MenuItem*/ item){ + // summary: + // Called when child of this Menu gets focus from: + // + // 1. clicking it + // 2. tabbing into it + // 3. being opened by a parent menu. + // + // This is not called just from mouse hover. + if(this._hoveredChild && this._hoveredChild != item){ + this.onItemUnhover(this._hoveredChild); // any previous mouse movement is trumped by focus selection + } + }, + + _onBlur: function(){ + // summary: + // Called when focus is moved away from this Menu and it's submenus. + // tags: + // protected + this._cleanUp(); + this.inherited(arguments); + }, + + _cleanUp: function(){ + // summary: + // Called when the user is done with this menu. Closes hierarchy of menus. + // tags: + // private + + this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close + if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose + this._markInactive(); + } + } +}); + +}); -- cgit v1.2.3