123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- if (!dojo._hasResource["dijit.Menu"]) { // _hasResource checks added by build.
- // Do not use _hasResource directly in
- // your code.
- dojo._hasResource["dijit.Menu"] = true;
- dojo.provide("dijit.Menu");
- dojo.require("dijit._Widget");
- dojo.require("dijit._Container");
- dojo.require("dijit._Templated");
- dojo.declare("dijit.Menu", [dijit._Widget, dijit._Templated,
- dijit._KeyNavContainer], {
- constructor : function() {
- this._bindings = [];
- },
- templateString : '<table class="dijit dijitMenu dijitReset dijitMenuTable" waiRole="menu" dojoAttachEvent="onkeypress:_onKeyPress">'
- + '<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>'
- + '</table>',
- // targetNodeIds: String[]
- // Array of dom node ids of nodes to attach to.
- // Fill this with nodeIds upon widget creation and it becomes
- // context menu for those nodes.
- targetNodeIds : [],
- // contextMenuForWindow: Boolean
- // if true, right clicking anywhere on the window will cause
- // this context menu to open;
- // if false, must specify targetNodeIds
- contextMenuForWindow : false,
- // parentMenu: 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,
- // _contextMenuWithMouse: Boolean
- // used to record mouse and keyboard events to determine if a
- // context
- // menu is being opened with the keyboard or the mouse
- _contextMenuWithMouse : false,
- postCreate : function() {
- if (this.contextMenuForWindow) {
- this.bindDomNode(dojo.body());
- } else {
- dojo
- .forEach(this.targetNodeIds, this.bindDomNode,
- this);
- }
- this.connectKeyNavHandlers([dojo.keys.UP_ARROW],
- [dojo.keys.DOWN_ARROW]);
- },
- startup : function() {
- dojo.forEach(this.getChildren(), function(child) {
- child.startup();
- });
- this.startupKeyNavChildren();
- },
- onExecute : function() {
- // summary: attach point for notification about when a menu
- // item has been executed
- },
- onCancel : function(/* Boolean */closeAll) {
- // summary: attach point for notification about when the
- // user cancels the current menu
- },
- _moveToPopup : function(/* Event */evt) {
- if (this.focusedChild && this.focusedChild.popup
- && !this.focusedChild.disabled) {
- this.focusedChild._onClick(evt);
- }
- },
- _onKeyPress : function(/* Event */evt) {
- // summary
- // Handle keyboard based menu navigation.
- if (evt.ctrlKey || evt.altKey) {
- return;
- }
- switch (evt.keyCode) {
- case dojo.keys.RIGHT_ARROW :
- this._moveToPopup(evt);
- dojo.stopEvent(evt);
- break;
- case dojo.keys.LEFT_ARROW :
- if (this.parentMenu) {
- this.onCancel(false);
- } else {
- dojo.stopEvent(evt);
- }
- break;
- }
- },
- onItemHover : function(/* MenuItem */item) {
- this.focusChild(item);
- if (this.focusedChild.popup && !this.focusedChild.disabled
- && !this.hover_timer) {
- this.hover_timer = setTimeout(dojo.hitch(this,
- "_openPopup"), this.popupDelay);
- }
- },
- _onChildBlur : function(item) {
- // Close all popups that are open and descendants of this
- // menu
- dijit.popup.close(item.popup);
- item._blur();
- this._stopPopupTimer();
- },
- onItemUnhover : function(/* MenuItem */item) {
- },
- _stopPopupTimer : function() {
- if (this.hover_timer) {
- clearTimeout(this.hover_timer);
- this.hover_timer = null;
- }
- },
- _getTopMenu : function() {
- for (var top = this; top.parentMenu; top = top.parentMenu);
- return top;
- },
- onItemClick : function(/* Widget */item) {
- // summary: user defined function to handle clicks on an
- // item
- // summary: internal function for clicks
- if (item.disabled) {
- return false;
- }
- if (item.popup) {
- if (!this.is_open) {
- this._openPopup();
- }
- } 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();
- }
- },
- // thanks burstlib!
- _iframeContentWindow : function(
- /* HTMLIFrameElement */iframe_el) {
- // summary
- // returns the window reference of the passed iframe
- var win = dijit.getDocumentWindow(dijit.Menu
- ._iframeContentDocument(iframe_el))
- ||
- // Moz. TODO: is this available when defaultView
- // isn't?
- dijit.Menu._iframeContentDocument(iframe_el)['__parent__']
- || (iframe_el.name && document.frames[iframe_el.name])
- || null;
- return win; // Window
- },
- _iframeContentDocument : function(
- /* HTMLIFrameElement */iframe_el) {
- // summary
- // returns a reference to the document object inside
- // iframe_el
- var doc = iframe_el.contentDocument // W3
- || (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
- || (iframe_el.name
- && document.frames[iframe_el.name] && document.frames[iframe_el.name].document)
- || null;
- return doc; // HTMLDocument
- },
- bindDomNode : function(/* String|DomNode */node) {
- // summary: attach menu to given node
- node = dojo.byId(node);
- // TODO: this is to support context popups in Editor. Maybe
- // this shouldn't be in dijit.Menu
- var win = dijit.getDocumentWindow(node.ownerDocument);
- if (node.tagName.toLowerCase() == "iframe") {
- win = this._iframeContentWindow(node);
- node = dojo.withGlobal(win, dojo.body);
- }
- // to capture these events at the top level,
- // attach to document, not body
- var cn = (node == dojo.body() ? dojo.doc : node);
- node[this.id] = this._bindings.push([
- dojo.connect(cn, "oncontextmenu", this,
- "_openMyself"),
- dojo.connect(cn, "onkeydown", this, "_contextKey"),
- dojo.connect(cn, "onmousedown", this,
- "_contextMouse")]);
- },
- unBindDomNode : function(/* String|DomNode */nodeName) {
- // summary: detach menu from given node
- var node = dojo.byId(nodeName);
- var bid = node[this.id] - 1, b = this._bindings[bid];
- dojo.forEach(b, dojo.disconnect);
- delete this._bindings[bid];
- },
- _contextKey : function(e) {
- this._contextMenuWithMouse = false;
- if (e.keyCode == dojo.keys.F10) {
- dojo.stopEvent(e);
- if (e.shiftKey && e.type == "keydown") {
- // FF: copying the wrong property from e will cause
- // the system
- // context menu to appear in spite of stopEvent.
- // Don't know
- // exactly which properties cause this effect.
- var _e = {
- target : e.target,
- pageX : e.pageX,
- pageY : e.pageY
- };
- _e.preventDefault = _e.stopPropagation = function() {
- };
- // IE: without the delay, focus work in "open"
- // causes the system
- // context menu to appear in spite of stopEvent.
- window.setTimeout(dojo.hitch(this, function() {
- this._openMyself(_e);
- }), 1);
- }
- }
- },
- _contextMouse : function(e) {
- this._contextMenuWithMouse = true;
- },
- _openMyself : function(/* Event */e) {
- // summary:
- // Internal function for opening myself when the user
- // does a right-click or something similar
- dojo.stopEvent(e);
- // Get coordinates.
- // if we are opening the menu with the mouse or on safari
- // open
- // the menu at the mouse cursor
- // (Safari does not have a keyboard command to open the
- // context menu
- // and we don't currently have a reliable way to determine
- // _contextMenuWithMouse on Safari)
- var x, y;
- if (dojo.isSafari || this._contextMenuWithMouse) {
- x = e.pageX;
- y = e.pageY;
- } else {
- // otherwise open near e.target
- var coords = dojo.coords(e.target, true);
- x = coords.x + 10;
- y = coords.y + 10;
- }
- var self = this;
- var savedFocus = dijit.getFocus(this);
- function closeAndRestoreFocus() {
- // user has clicked on a menu or popup
- dijit.focus(savedFocus);
- dijit.popup.close(self);
- }
- dijit.popup.open({
- popup : this,
- x : x,
- y : y,
- onExecute : closeAndRestoreFocus,
- onCancel : closeAndRestoreFocus,
- orient : this.isLeftToRight() ? 'L' : 'R'
- });
- this.focus();
- this._onBlur = function() {
- // Usually the parent closes the child widget but if
- // this is a context
- // menu then there is no parent
- dijit.popup.close(this);
- // don't try to restore focus; user has clicked another
- // part of the screen
- // and set focus there
- }
- },
- onOpen : function(/* Event */e) {
- // summary
- // Open menu relative to the mouse
- this.isShowingNow = true;
- },
- onClose : function() {
- // summary: callback when this menu is closed
- this._stopPopupTimer();
- this.parentMenu = null;
- this.isShowingNow = false;
- this.currentPopup = null;
- if (this.focusedChild) {
- this._onChildBlur(this.focusedChild);
- this.focusedChild = null;
- }
- },
- _openPopup : function() {
- // summary: open the popup to the side of the current menu
- // item
- this._stopPopupTimer();
- var from_item = this.focusedChild;
- var popup = from_item.popup;
- if (popup.isShowingNow) {
- return;
- }
- popup.parentMenu = this;
- var self = this;
- dijit.popup.open({
- parent : this,
- popup : popup,
- around : from_item.arrowCell,
- orient : this.isLeftToRight() ? {
- 'TR' : 'TL',
- 'TL' : 'TR'
- } : {
- 'TL' : 'TR',
- 'TR' : 'TL'
- },
- onCancel : function() {
- // called when the child menu is canceled
- dijit.popup.close(popup);
- from_item.focus(); // put focus back on my
- // node
- self.currentPopup = null;
- }
- });
- this.currentPopup = popup;
- if (popup.focus) {
- popup.focus();
- }
- }
- });
- dojo.declare("dijit.MenuItem", [dijit._Widget, dijit._Templated,
- dijit._Contained], {
- // summary
- // A line item in a Menu2
- // Make 3 columns
- // icon, label, and expand arrow (BiDi-dependent) indicating
- // sub-menu
- templateString : '<tr class="dijitReset dijitMenuItem"'
- + 'dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">'
- + '<td class="dijitReset"><div class="dijitMenuItemIcon ${iconClass}" dojoAttachPoint="iconNode" ></div></td>'
- + '<td tabIndex="-1" class="dijitReset dijitMenuItemLabel" dojoAttachPoint="containerNode" waiRole="menuitem"></td>'
- + '<td class="dijitReset" dojoAttachPoint="arrowCell">'
- + '<div class="dijitMenuExpand" dojoAttachPoint="expand" style="display:none">'
- + '<span class="dijitInline dijitArrowNode dijitMenuExpandInner">+</span>'
- + '</div>' + '</td>' + '</tr>',
- // label: String
- // menu text
- label : '',
- // iconClass: String
- // class to apply to div in button to make it display an icon
- iconClass : "",
- // disabled: Boolean
- // if true, the menu item is disabled
- // if false, the menu item is enabled
- disabled : false,
- postCreate : function() {
- dojo.setSelectable(this.domNode, false);
- this.setDisabled(this.disabled);
- if (this.label) {
- this.containerNode.innerHTML = this.label;
- }
- },
- _onHover : function() {
- // summary: callback when mouse is moved onto menu item
- this.getParent().onItemHover(this);
- },
- _onUnhover : function() {
- // summary: callback when mouse is moved off of menu item
- // if we are unhovering the currently selected item
- // then unselect it
- this.getParent().onItemUnhover(this);
- },
- _onClick : function(evt) {
- this.getParent().onItemClick(this);
- dojo.stopEvent(evt);
- },
- onClick : function() {
- // summary
- // User defined function to handle clicks
- },
- focus : function() {
- dojo.addClass(this.domNode, 'dijitMenuItemHover');
- try {
- dijit.focus(this.containerNode);
- } catch (e) {
- // this throws on IE (at least) in some scenarios
- }
- },
- _blur : function() {
- dojo.removeClass(this.domNode, 'dijitMenuItemHover');
- },
- setDisabled : function(/* Boolean */value) {
- // summary: enable or disable this menu item
- this.disabled = value;
- dojo[value ? "addClass" : "removeClass"](this.domNode,
- 'dijitMenuItemDisabled');
- dijit.setWaiState(this.containerNode, 'disabled', value
- ? 'true'
- : 'false');
- }
- });
- dojo.declare("dijit.PopupMenuItem", dijit.MenuItem, {
- _fillContent : function() {
- // my inner HTML contains both the menu item text and a
- // popup widget, like
- // <div dojoType="dijit.PopupMenuItem">
- // <span>pick me</span>
- // <popup> ... </popup>
- // </div>
- // the first part holds the menu item text and the second
- // part is the popup
- if (this.srcNodeRef) {
- var nodes = dojo.query("*", this.srcNodeRef);
- dijit.PopupMenuItem.superclass._fillContent.call(this,
- nodes[0]);
- // save pointer to srcNode so we can grab the drop down
- // widget after it's instantiated
- this.dropDownContainer = this.srcNodeRef;
- }
- },
- startup : function() {
- // we didn't copy the dropdown widget from the
- // this.srcNodeRef, so it's in no-man's
- // land now. move it to document.body.
- if (!this.popup) {
- var node = dojo.query("[widgetId]",
- this.dropDownContainer)[0];
- this.popup = dijit.byNode(node);
- }
- dojo.body().appendChild(this.popup.domNode);
- this.popup.domNode.style.display = "none";
- dojo.addClass(this.expand, "dijitMenuExpandEnabled");
- dojo.style(this.expand, "display", "");
- dijit.setWaiState(this.containerNode, "haspopup", "true");
- }
- });
- dojo.declare("dijit.MenuSeparator", [dijit._Widget, dijit._Templated,
- dijit._Contained], {
- // summary
- // A line between two menu items
- templateString : '<tr class="dijitMenuSeparator"><td colspan=3>'
- + '<div class="dijitMenuSeparatorTop"></div>'
- + '<div class="dijitMenuSeparatorBottom"></div>'
- + '</td></tr>',
- postCreate : function() {
- dojo.setSelectable(this.domNode, false);
- },
- isFocusable : function() {
- // summary:
- // over ride to always return false
- return false;
- }
- });
- }
|