📄 menu2.js
字号:
/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml*/dojo.provide("dojo.widget.Menu2");dojo.require("dojo.widget.PopupContainer");// summary// provides a menu that can be used as a context menu (typically shown by right-click),// or as the drop down on a DropDownButton, ComboButton, etc.dojo.widget.defineWidget( "dojo.widget.PopupMenu2", dojo.widget.PopupContainer, function(){ this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it becomes context menu for those nodes this.eventNames = { open: "" }; },{ snarfChildDomOutput: true, // String // if "default" event names are based on widget id, otherwise user must define // TODO: write real documentation about the events eventNaming: "default", templateString: '<table class="dojoPopupMenu2" border=0 cellspacing=0 cellpadding=0 style="display: none;"><tbody dojoAttachPoint="containerNode"></tbody></table>', templateCssPath: dojo.uri.dojoUri("src/widget/templates/Menu2.css"), templateCssString: "", // Integer // number of milliseconds before hovering (without clicking) causes the submenu to automatically open submenuDelay: 500, // Integer // a submenu usually appears to the right, but slightly overlapping, it's parent menu; // this controls the number of pixels the two menus overlap. submenuOverlap: 5, // Boolean // if true, right clicking anywhere on the window will cause this context menu to open; // if false, must specify targetNodeIds contextMenuForWindow: false, // Array // Array of dom node ids of nodes to attach to targetNodeIds: [], initialize: function(args, frag) { if (this.eventNaming == "default") { for (var eventName in this.eventNames) { this.eventNames[eventName] = this.widgetId+"/"+eventName; } } }, postCreate: function(){ if (this.contextMenuForWindow){ var doc = dojo.body(); this.bindDomNode(doc); } else if ( this.targetNodeIds.length > 0 ){ dojo.lang.forEach(this.targetNodeIds, this.bindDomNode, this); } this._subscribeSubitemsOnOpen(); }, _subscribeSubitemsOnOpen: function() { var subItems = this.getChildrenOfType(dojo.widget.MenuItem2); for(var i=0; i<subItems.length; i++) { dojo.event.topic.subscribe(this.eventNames.open, subItems[i], "menuOpen") } }, getTopOpenEvent: function() { // summary: get event that initially caused current chain of menus to open var menu = this; while (menu.parentPopup){ menu = menu.parentPopup; } return menu.openEvent; // Event }, bindDomNode: function(/*String|DomNode*/ node){ // summary: attach menu to given node node = dojo.byId(node); var win = dojo.html.getElementWindow(node); if(dojo.html.isTag(node,'iframe') == 'iframe'){ win = dojo.html.iframeContentWindow(node); node = dojo.withGlobal(win, dojo.body); } // fixes node so that it supports oncontextmenu if not natively supported, Konqueror, Opera more? dojo.widget.Menu2.OperaAndKonqFixer.fixNode(node); dojo.event.kwConnect({ srcObj: node, srcFunc: "oncontextmenu", targetObj: this, targetFunc: "onOpen", once: true }); //normal connect does not work if document.designMode is on in FF, use addListener instead if(dojo.render.html.moz && win.document.designMode.toLowerCase() == 'on'){ dojo.event.browser.addListener(node, "contextmenu", dojo.lang.hitch(this, "onOpen")); } dojo.widget.PopupManager.registerWin(win); }, unBindDomNode: function(/*String|DomNode*/ nodeName){ // summary: detach menu from given node var node = dojo.byId(nodeName); dojo.event.kwDisconnect({ srcObj: node, srcFunc: "oncontextmenu", targetObj: this, targetFunc: "onOpen", once: true }); // cleans a fixed node, konqueror and opera dojo.widget.Menu2.OperaAndKonqFixer.cleanNode(node); }, _moveToNext: function(/*Event*/ evt){ this._highlightOption(1); return true; //do not pass to parent menu }, _moveToPrevious: function(/*Event*/ evt){ this._highlightOption(-1); return true; //do not pass to parent menu }, _moveToParentMenu: function(/*Event*/ evt){ if(this._highlighted_option && this.parentPopup){ //only process event in the focused menu //and its immediate parentPopup to support //MenuBar2 if(evt._menu2UpKeyProcessed){ return true; //do not pass to parent menu }else{ this._highlighted_option.onUnhover(); this.closeSubpopup(); evt._menu2UpKeyProcessed = true; } } return false; }, _moveToChildMenu: function(/*Event*/ evt){ if(this._highlighted_option && this._highlighted_option.submenuId){ this._highlighted_option._onClick(true); return true; //do not pass to parent menu } return false; }, _selectCurrentItem: function(/*Event*/ evt){ if(this._highlighted_option){ this._highlighted_option._onClick(); return true; } return false; }, processKey: function(/*Event*/ evt){ // summary // callback to process key strokes // return true to stop the event being processed by the // parent popupmenu if(evt.ctrlKey || evt.altKey || !evt.key){ return false; } var rval = false; switch(evt.key){ case evt.KEY_DOWN_ARROW: rval = this._moveToNext(evt); break; case evt.KEY_UP_ARROW: rval = this._moveToPrevious(evt); break; case evt.KEY_RIGHT_ARROW: rval = this._moveToChildMenu(evt); break; case evt.KEY_LEFT_ARROW: rval = this._moveToParentMenu(evt); break; case " ": //fall through case evt.KEY_ENTER: if(rval = this._selectCurrentItem(evt)){ break; } //fall through case evt.KEY_ESCAPE: dojo.widget.PopupManager.currentMenu.close(); rval = true; break; } return rval; }, _findValidItem: function(dir, curItem){ if(curItem){ curItem = dir>0 ? curItem.getNextSibling() : curItem.getPreviousSibling(); } for(var i=0; i < this.children.length; ++i){ if(!curItem){ curItem = dir>0 ? this.children[0] : this.children[this.children.length-1]; } //find next/previous visible menu item, not including separators if(curItem.onHover && curItem.isShowing()){ return curItem; } curItem = dir>0 ? curItem.getNextSibling() : curItem.getPreviousSibling(); } }, _highlightOption: function(dir){ var item; // || !this._highlighted_option.parentNode if((!this._highlighted_option)){ item = this._findValidItem(dir); }else{ item = this._findValidItem(dir, this._highlighted_option); } if(item){ if(this._highlighted_option) { this._highlighted_option.onUnhover(); } item.onHover(); dojo.html.scrollIntoView(item.domNode); // navigate into the item table and select the first caption tag try { var node = dojo.html.getElementsByClass("dojoMenuItem2Label", item.domNode)[0]; node.focus(); } catch(e) { } } }, onItemClick: function(/*Widget*/ item) { // summary: user defined function to handle clicks on an item }, close: function(/*Boolean*/ force){ // summary: close the menu if(this.animationInProgress){ dojo.widget.PopupMenu2.superclass.close.apply(this, arguments); return; } if(this._highlighted_option){ this._highlighted_option.onUnhover(); } dojo.widget.PopupMenu2.superclass.close.apply(this, arguments); }, closeSubpopup: function(force){ // summary: close the currently displayed submenu if (this.currentSubpopup == null){ return; } this.currentSubpopup.close(force); this.currentSubpopup = null; this.currentSubmenuTrigger.is_open = false; this.currentSubmenuTrigger._closedSubmenu(force); this.currentSubmenuTrigger = null; }, _openSubmenu: function(submenu, from_item){ // summary: open the menu to the right of the current menu item var fromPos = dojo.html.getAbsolutePosition(from_item.domNode, true); var our_w = dojo.html.getMarginBox(this.domNode).width; var x = fromPos.x + our_w - this.submenuOverlap; var y = fromPos.y; //the following is set in open, so we do not need it //this.currentSubpopup = submenu; submenu.open(x, y, this, from_item.domNode); this.currentSubmenuTrigger = from_item; this.currentSubmenuTrigger.is_open = true; }, onOpen: function(/*Event*/ e){ // summary: callback when menu is opened this.openEvent = e; if(e["target"]){ this.openedForWindow = dojo.html.getElementWindow(e.target); }else{ this.openedForWindow = null; } var x = e.pageX, y = e.pageY; var win = dojo.html.getElementWindow(e.target); var iframe = win._frameElement || win.frameElement; if(iframe){ var cood = dojo.html.abs(iframe, true); x += cood.x - dojo.withGlobal(win, dojo.html.getScroll).left; y += cood.y - dojo.withGlobal(win, dojo.html.getScroll).top; } this.open(x, y, null, [x, y]); e.preventDefault(); e.stopPropagation(); }});// summary// A line item in a Menu2dojo.widget.defineWidget( "dojo.widget.MenuItem2", dojo.widget.HtmlWidget, function(){ this.eventNames = { engage: "" }; },{ // Make 4 columns // icon, label, accelerator-key, and right-arrow indicating sub-menu templateString: '<tr class="dojoMenuItem2" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick: _onClick; onKey:onKey;">' +'<td><div class="${this.iconClass}" style="${this.iconStyle}"></div></td>' +'<td tabIndex="-1" class="dojoMenuItem2Label">${this.caption}</td>' +'<td class="dojoMenuItem2Accel">${this.accelKey}</td>' +'<td><div class="dojoMenuItem2Submenu" style="display:${this.arrowDisplay};"></div></td>' +'</tr>', // // internal settings // is_hovering: false, hover_timer: null, is_open: false, topPosition: 0, // // options // // String // text of the menu item caption: 'Untitled', // String // accelerator key (not supported yet!) accelKey: '', // String // path to icon to display to the left of the menu text iconSrc: '', // String // CSS class name to use for menu item (if CSS class specifies a background image then iconSrc is not necessary) iconClass: 'dojoMenuItem2Icon', // String // widget ID of Menu2 widget to open when this menu item is clicked submenuId: '', // Boolean // if true, this menu item cannot be selected disabled: false, // String // event names for announcing when menu item is clicked. // if "default", then use the default name, based on the widget ID eventNaming: "default",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -