/* 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"); dojo.declare( "dojo.widget.MenuBase", null, function(){ // summary // Base class for PopupMenu and MenuBar this.eventNames = { open: "" }; }, { isContainer: true, isMenu: true, // eventNaming: String // if "default" event names are based on widget id, otherwise user must define // TODO: write real documentation about the events eventNaming: "default", templateCssPath: dojo.uri.moduleUri("dojo.widget", "templates/Menu2.css"), // submenuDelay: Integer // number of milliseconds before hovering (without clicking) causes the submenu to automatically open submenuDelay: 500, initialize: function(args, frag) { if (this.eventNaming == "default") { for (var eventName in this.eventNames) { this.eventNames[eventName] = this.widgetId+"/"+eventName; } } }, _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.parentMenu){ //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.closeSubmenu(); 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: case evt.KEY_TAB: this.close(true); 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 }, closeSubmenu: function(force){ // summary: close the currently displayed submenu if (this.currentSubmenu == null){ return; } this.currentSubmenu.close(force); this.currentSubmenu = null; this.currentSubmenuTrigger.is_open = false; this.currentSubmenuTrigger._closedSubmenu(force); this.currentSubmenuTrigger = null; } }); dojo.widget.defineWidget( "dojo.widget.PopupMenu2", [dojo.widget.HtmlWidget, dojo.widget.PopupContainerBase, dojo.widget.MenuBase], function(){ // 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. this.targetNodeIds = []; }, { // 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. templateString: '
' , // submenuOverlap: 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, // 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, 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