define([ "dojo/_base/declare", // declare "dojo/on", "dojo/window" // winUtils.scrollIntoView ], function(declare, on, winUtils){ // module: // dijit/form/_ListBase return declare("dijit.form._ListBase", null, { // summary: // Focus-less menu to handle UI events consistently. // Abstract methods that must be defined externally: // // - onSelect: item is active (mousedown but not yet mouseup, or keyboard arrow selected but no Enter) // - onDeselect: cancels onSelect // tags: // private // selected: DOMNode // currently selected node selected: null, _listConnect: function(/*String|Function*/ eventType, /*String*/ callbackFuncName){ // summary: // Connects 'containerNode' to specified method of this object // and automatically registers for 'disconnect' on widget destroy. // description: // Provide widget-specific analog to 'connect'. // The callback function is called with the normal event object, // but also a second parameter is passed that indicates which list item // actually received the event. // returns: // A handle that can be passed to `disconnect` in order to disconnect // before the widget is destroyed. // tags: // private var self = this; return self.own(on(self.containerNode, on.selector( function(eventTarget, selector, target){ return eventTarget.parentNode == target; }, eventType ), function(evt){ self[callbackFuncName](evt, this); } )); }, selectFirstNode: function(){ // summary: // Select the first displayed item in the list. var first = this.containerNode.firstChild; while(first && first.style.display == "none"){ first = first.nextSibling; } this._setSelectedAttr(first, true); }, selectLastNode: function(){ // summary: // Select the last displayed item in the list var last = this.containerNode.lastChild; while(last && last.style.display == "none"){ last = last.previousSibling; } this._setSelectedAttr(last, true); }, selectNextNode: function(){ // summary: // Select the item just below the current selection. // If nothing selected, select first node. var selectedNode = this.selected; if(!selectedNode){ this.selectFirstNode(); }else{ var next = selectedNode.nextSibling; while(next && next.style.display == "none"){ next = next.nextSibling; } if(!next){ this.selectFirstNode(); }else{ this._setSelectedAttr(next, true); } } }, selectPreviousNode: function(){ // summary: // Select the item just above the current selection. // If nothing selected, select last node (if // you select Previous and try to keep scrolling up the list). var selectedNode = this.selected; if(!selectedNode){ this.selectLastNode(); }else{ var prev = selectedNode.previousSibling; while(prev && prev.style.display == "none"){ prev = prev.previousSibling; } if(!prev){ this.selectLastNode(); }else{ this._setSelectedAttr(prev, true); } } }, _setSelectedAttr: function(/*DomNode*/ node, /*Boolean*/ scroll){ // summary: // Does the actual select. // node: // The option to select // scroll: // If necessary, scroll node into view. Set to false for mouse/touch to // avoid jumping problems on mobile/RTL, see https://bugs.dojotoolkit.org/ticket/17739. if(this.selected != node){ var selectedNode = this.selected; if(selectedNode){ this.onDeselect(selectedNode); } if(node){ if(scroll){ winUtils.scrollIntoView(node); } this.onSelect(node); } this._set("selected", node); }else if(node){ this.onSelect(node); } } }); });