Blame | Last modification | View Log | RSS feed
if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.ComboBox"] = true;dojo.provide("dijit.form.ComboBox");dojo.require("dojo.data.ItemFileReadStore");dojo.require("dijit.form.ValidationTextBox");dojo.requireLocalization("dijit.form", "ComboBox", null, "ko,zh,ja,zh-tw,ru,it,hu,ROOT,fr,pt,pl,es,de,cs");dojo.declare("dijit.form.ComboBoxMixin",null,{// summary:// Auto-completing text box, and base class for FilteringSelect widget.//// The drop down box's values are populated from an class called// a data provider, which returns a list of values based on the characters// that the user has typed into the input box.//// Some of the options to the ComboBox are actually arguments to the data// provider.//// You can assume that all the form widgets (and thus anything that mixes// in ComboBoxMixin) will inherit from _FormWidget and thus the "this"// reference will also "be a" _FormWidget.// item: Object// This is the item returned by the dojo.data.store implementation that// provides the data for this cobobox, it's the currently selected item.item: null,// pageSize: Integer// Argument to data provider.// Specifies number of search results per page (before hitting "next" button)pageSize: Infinity,// store: Object// Reference to data provider object used by this ComboBoxstore: null,// query: Object// A query that can be passed to 'store' to initially filter the items,// before doing further filtering based on searchAttr and the key.query: {},// autoComplete: Boolean// If you type in a partial string, and then tab out of the <input> box,// automatically copy the first entry displayed in the drop down list to// the <input> fieldautoComplete: true,// searchDelay: Integer// Delay in milliseconds between when user types something and we start// searching based on that valuesearchDelay: 100,// searchAttr: String// Searches pattern match against this fieldsearchAttr: "name",// ignoreCase: Boolean// Set true if the ComboBox should ignore case when matching possible itemsignoreCase: true,// hasDownArrow: Boolean// Set this textbox to have a down arrow button.// Defaults to true.hasDownArrow:true,// _hasFocus: Boolean// Represents focus state of the textbox// TODO: get rid of this; it's unnecessary (but currently referenced in FilteringSelect)_hasFocus:false,templateString:"<table class=\"dijit dijitReset dijitInlineTable dijitLeft\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\" dojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class='dijitReset dijitStretch dijitInputField' width=\"100%\"\n\t\t\t><input type=\"text\" autocomplete=\"off\" name=\"${name}\"\n\t\t\tdojoAttachEvent=\"onkeypress, onkeyup, onfocus, compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"combobox\"\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div\n\t\t\t><div class='dijitValidationIconText'>Χ</div\n\t\t></td\n\t\t><td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton' width=\"0%\"\n\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\tdojoAttachEvent=\"onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t><div class=\"dijitDownArrowButtonInner\" waiRole=\"presentation\"\n\t\t\t\t><div class=\"dijitDownArrowButtonChar\">▼</div\n\t\t\t></div\n\t\t></td\t\n\t></tr\n></table>\n",baseClass:"dijitComboBox",_lastDisplayedValue: "",getValue:function(){// don't get the textbox value but rather the previously set hidden valuereturn dijit.form.TextBox.superclass.getValue.apply(this, arguments);},setDisplayedValue:function(/*String*/ value){this._lastDisplayedValue = value;this.setValue(value, true);},_getCaretPos: function(/*DomNode*/ element){// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22if(typeof(element.selectionStart)=="number"){// FIXME: this is totally borked on Moz < 1.3. Any recourse?return element.selectionStart;}else if(dojo.isIE){// in the case of a mouse click in a popup being handled,// then the document.selection is not the textarea, but the popup// var r = document.selection.createRange();// hack to get IE 6 to play nice. What a POS browser.var tr = document.selection.createRange().duplicate();var ntr = element.createTextRange();tr.move("character",0);ntr.move("character",0);try{// If control doesnt have focus, you get an exception.// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).// There appears to be no workaround for this - googled for quite a while.ntr.setEndPoint("EndToEnd", tr);return String(ntr.text).replace(/\r/g,"").length;}catch(e){return 0; // If focus has shifted, 0 is fine for caret pos.}}},_setCaretPos: function(/*DomNode*/ element, /*Number*/ location){location = parseInt(location);this._setSelectedRange(element, location, location);},_setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){if(!end){end = element.value.length;} // NOTE: Strange - should be able to put caret at start of text?// Mozilla// parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130if(element.setSelectionRange){dijit.focus(element);element.setSelectionRange(start, end);}else if(element.createTextRange){ // IEvar range = element.createTextRange();with(range){collapse(true);moveEnd('character', end);moveStart('character', start);select();}}else{ //otherwise try the event-creation hack (our own invention)// do we need these?element.value = element.value;element.blur();dijit.focus(element);// figure out how far back to govar dist = parseInt(element.value.length)-end;var tchar = String.fromCharCode(37);var tcc = tchar.charCodeAt(0);for(var x = 0; x < dist; x++){var te = document.createEvent("KeyEvents");te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);element.dispatchEvent(te);}}},onkeypress: function(/*Event*/ evt){// summary: handles keyboard events//except for pasting case - ctrl + v(118)if(evt.altKey || (evt.ctrlKey && evt.charCode != 118)){return;}var doSearch = false;this.item = null; // #4872if(this._isShowingNow){this._popupWidget.handleKey(evt);}switch(evt.keyCode){case dojo.keys.PAGE_DOWN:case dojo.keys.DOWN_ARROW:if(!this._isShowingNow||this._prev_key_esc){this._arrowPressed();doSearch=true;}else{this._announceOption(this._popupWidget.getHighlightedOption());}dojo.stopEvent(evt);this._prev_key_backspace = false;this._prev_key_esc = false;break;case dojo.keys.PAGE_UP:case dojo.keys.UP_ARROW:if(this._isShowingNow){this._announceOption(this._popupWidget.getHighlightedOption());}dojo.stopEvent(evt);this._prev_key_backspace = false;this._prev_key_esc = false;break;case dojo.keys.ENTER:// prevent submitting form if user presses enter// also prevent accepting the value if either Next or Previous are selectedvar highlighted;if(this._isShowingNow&&(highlighted=this._popupWidget.getHighlightedOption())){// only stop event on prev/nextif(highlighted==this._popupWidget.nextButton){this._nextSearch(1);dojo.stopEvent(evt);break;}else if(highlighted==this._popupWidget.previousButton){this._nextSearch(-1);dojo.stopEvent(evt);break;}}else{this.setDisplayedValue(this.getDisplayedValue());}// default case:// prevent submit, but allow event to bubbleevt.preventDefault();// fall throughcase dojo.keys.TAB:var newvalue=this.getDisplayedValue();// #4617: if the user had More Choices selected fall into the _onBlur handlerif(this._popupWidget &&(newvalue == this._popupWidget._messages["previousMessage"] ||newvalue == this._popupWidget._messages["nextMessage"])){break;}if(this._isShowingNow){this._prev_key_backspace = false;this._prev_key_esc = false;if(this._popupWidget.getHighlightedOption()){this._popupWidget.setValue({target:this._popupWidget.getHighlightedOption()}, true);}this._hideResultList();}break;case dojo.keys.SPACE:this._prev_key_backspace = false;this._prev_key_esc = false;if(this._isShowingNow && this._popupWidget.getHighlightedOption()){dojo.stopEvent(evt);this._selectOption();this._hideResultList();}else{doSearch = true;}break;case dojo.keys.ESCAPE:this._prev_key_backspace = false;this._prev_key_esc = true;this._hideResultList();if(this._lastDisplayedValue != this.getDisplayedValue()){this.setDisplayedValue(this._lastDisplayedValue);dojo.stopEvent(evt);}else{this.setValue(this.getValue(), false);}break;case dojo.keys.DELETE:case dojo.keys.BACKSPACE:this._prev_key_esc = false;this._prev_key_backspace = true;doSearch = true;break;case dojo.keys.RIGHT_ARROW: // fall throughcase dojo.keys.LEFT_ARROW: // fall throughthis._prev_key_backspace = false;this._prev_key_esc = false;break;default:// non char keys (F1-F12 etc..) shouldn't open listthis._prev_key_backspace = false;this._prev_key_esc = false;if(dojo.isIE || evt.charCode != 0){doSearch=true;}}if(this.searchTimer){clearTimeout(this.searchTimer);}if(doSearch){// need to wait a tad before start search so that the event bubbles through DOM and we have value visiblethis.searchTimer = setTimeout(dojo.hitch(this, this._startSearchFromInput), this.searchDelay);}},_autoCompleteText: function(/*String*/ text){// summary:// Fill in the textbox with the first item from the drop down list, and// highlight the characters that were auto-completed. For example, if user// typed "CA" and the drop down list appeared, the textbox would be changed to// "California" and "ifornia" would be highlighted.// IE7: clear selection so next highlight works all the timethis._setSelectedRange(this.focusNode, this.focusNode.value.length, this.focusNode.value.length);// does text autoComplete the value in the textbox?// #3744: escape regexp so the user's input isn't treated as a regular expression.// Example: If the user typed "(" then the regexp would throw "unterminated parenthetical."// Also see #2558 for the autocompletion bug this regular expression fixes.if(new RegExp("^"+escape(this.focusNode.value), this.ignoreCase ? "i" : "").test(escape(text))){var cpos = this._getCaretPos(this.focusNode);// only try to extend if we added the last character at the end of the inputif((cpos+1) > this.focusNode.value.length){// only add to input node as we would overwrite Capitalisation of chars// actually, that is okthis.focusNode.value = text;//.substr(cpos);// visually highlight the autocompleted charactersthis._setSelectedRange(this.focusNode, cpos, this.focusNode.value.length);dijit.setWaiState(this.focusNode, "valuenow", text);}}else{// text does not autoComplete; replace the whole value and highlightthis.focusNode.value = text;this._setSelectedRange(this.focusNode, 0, this.focusNode.value.length);dijit.setWaiState(this.focusNode, "valuenow", text);}},_openResultList: function(/*Object*/ results, /*Object*/ dataObject){if(this.disabled || dataObject.query[this.searchAttr] != this._lastQuery){return;}this._popupWidget.clearResultList();if(!results.length){this._hideResultList();return;}// Fill in the textbox with the first item from the drop down list, and// highlight the characters that were auto-completed. For example, if user// typed "CA" and the drop down list appeared, the textbox would be changed to// "California" and "ifornia" would be highlighted.var zerothvalue=new String(this.store.getValue(results[0], this.searchAttr));if(zerothvalue && this.autoComplete && !this._prev_key_backspace &&// when the user clicks the arrow button to show the full list,// startSearch looks for "*".// it does not make sense to autocomplete// if they are just previewing the options available.(dataObject.query[this.searchAttr] != "*")){this._autoCompleteText(zerothvalue);// announce the autocompleted valuedijit.setWaiState(this.focusNode || this.domNode, "valuenow", zerothvalue);}this._popupWidget.createOptions(results, dataObject, dojo.hitch(this, this._getMenuLabelFromItem));// show our list (only if we have content, else nothing)this._showResultList();// #4091: tell the screen reader that the paging callback finished by shouting the next choiceif(dataObject.direction){if(dataObject.direction==1){this._popupWidget.highlightFirstOption();}else if(dataObject.direction==-1){this._popupWidget.highlightLastOption();}this._announceOption(this._popupWidget.getHighlightedOption());}},_showResultList: function(){this._hideResultList();var items = this._popupWidget.getItems(),visibleCount = Math.min(items.length,this.maxListLength);this._arrowPressed();// hide the tooltipthis._displayMessage("");// Position the list and if it's too big to fit on the screen then// size it to the maximum possible height// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time// TODO: want to redo this, see http://trac.dojotoolkit.org/ticket/3272, http://trac.dojotoolkit.org/ticket/4108with(this._popupWidget.domNode.style){// natural size of the list has changed, so erase old width/height settings,// which were hardcoded in a previous call to this function (via dojo.marginBox() call)width="";height="";}var best=this.open();// #3212: only set auto scroll bars if necessary// prevents issues with scroll bars appearing when they shouldn't when node is made wider (fractional pixels cause this)var popupbox=dojo.marginBox(this._popupWidget.domNode);this._popupWidget.domNode.style.overflow=((best.h==popupbox.h)&&(best.w==popupbox.w))?"hidden":"auto";// #4134: borrow TextArea scrollbar test so content isn't covered by scrollbar and horizontal scrollbar doesn't appearvar newwidth=best.w;if(best.h<this._popupWidget.domNode.scrollHeight){newwidth+=16;}dojo.marginBox(this._popupWidget.domNode, {h:best.h,w:Math.max(newwidth,this.domNode.offsetWidth)});},_hideResultList: function(){if(this._isShowingNow){dijit.popup.close(this._popupWidget);this._arrowIdle();this._isShowingNow=false;}},_onBlur: function(){// summary: called magically when focus has shifted away from this widget and it's dropdownthis._hasFocus=false;this._hasBeenBlurred = true;this._hideResultList();this._arrowIdle();// if the user clicks away from the textbox OR tabs away, set the value to the textbox value// #4617: if value is now more choices or previous choices, revert the valuevar newvalue=this.getDisplayedValue();if(this._popupWidget&&(newvalue==this._popupWidget._messages["previousMessage"]||newvalue==this._popupWidget._messages["nextMessage"])){this.setValue(this._lastValueReported, true);}else{this.setDisplayedValue(newvalue);}},onfocus:function(/*Event*/ evt){this._hasFocus=true;// update styling to reflect that we are focusedthis._onMouse(evt);},_announceOption: function(/*Node*/ node){// summary:// a11y code that puts the highlighted option in the textbox// This way screen readers will know what is happening in the menuif(node==null){return;}// pull the text value from the item attached to the DOM nodevar newValue;if(node==this._popupWidget.nextButton||node==this._popupWidget.previousButton){newValue=node.innerHTML;}else{newValue=this.store.getValue(node.item, this.searchAttr);}// get the text that the user manually entered (cut off autocompleted text)this.focusNode.value=this.focusNode.value.substring(0, this._getCaretPos(this.focusNode));// autocomplete the rest of the option to announce changethis._autoCompleteText(newValue);},_selectOption: function(/*Event*/ evt){var tgt = null;if(!evt){evt ={ target: this._popupWidget.getHighlightedOption()};}// what if nothing is highlighted yet?if(!evt.target){// handle autocompletion where the the user has hit ENTER or TABthis.setDisplayedValue(this.getDisplayedValue());return;// otherwise the user has accepted the autocompleted value}else{tgt = evt.target;}if(!evt.noHide){this._hideResultList();this._setCaretPos(this.focusNode, this.store.getValue(tgt.item, this.searchAttr).length);}this._doSelect(tgt);},_doSelect: function(tgt){this.item = tgt.item;this.setValue(this.store.getValue(tgt.item, this.searchAttr), true);},_onArrowMouseDown: function(evt){// summary: callback when arrow is clickedif(this.disabled){return;}dojo.stopEvent(evt);this.focus();if(this._isShowingNow){this._hideResultList();}else{// forces full population of results, if they click// on the arrow it means they want to see more optionsthis._startSearch("");}},_startSearchFromInput: function(){this._startSearch(this.focusNode.value);},_startSearch: function(/*String*/ key){if(!this._popupWidget){this._popupWidget = new dijit.form._ComboBoxMenu({onChange: dojo.hitch(this, this._selectOption)});}// create a new query to prevent accidentally querying for a hidden value from FilteringSelect's keyFieldvar query=this.query;this._lastQuery=query[this.searchAttr]=key+"*";var dataObject=this.store.fetch({queryOptions:{ignoreCase:this.ignoreCase, deep:true}, query: query, onComplete:dojo.hitch(this, "_openResultList"), start:0, count:this.pageSize});function nextSearch(dataObject, direction){dataObject.start+=dataObject.count*direction;// #4091: tell callback the direction of the paging so the screen reader knows which menu option to shoutdataObject.direction=direction;dataObject.store.fetch(dataObject);}this._nextSearch=this._popupWidget.onPage=dojo.hitch(this, nextSearch, dataObject);},_getValueField:function(){return this.searchAttr;},/////////////// Event handlers /////////////////////_arrowPressed: function(){if(!this.disabled&&this.hasDownArrow){dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");}},_arrowIdle: function(){if(!this.disabled&&this.hasDownArrow){dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");}},compositionend: function(/*Event*/ evt){// summary: When inputting characters using an input method, such as Asian// languages, it will generate this event instead of onKeyDown event// Note: this event is only triggered in FF (not in IE)this.onkeypress({charCode:-1});},//////////// INITIALIZATION METHODS ///////////////////////////////////////constructor: function(){this.query={};},postMixInProperties: function(){if(!this.hasDownArrow){this.baseClass = "dijitTextBox";}if(!this.store){// if user didn't specify store, then assume there are option tagsvar items = this.srcNodeRef ? dojo.query("> option", this.srcNodeRef).map(function(node){node.style.display="none";return { value: node.getAttribute("value"), name: String(node.innerHTML) };}) : {};this.store = new dojo.data.ItemFileReadStore({data: {identifier:this._getValueField(), items:items}});// if there is no value set and there is an option list,// set the value to the first value to be consistent with native Selectif(items && items.length && !this.value){// For <select>, IE does not let you set the value attribute of the srcNodeRef (and thus dojo.mixin does not copy it).// IE does understand selectedIndex though, which is automatically set by the selected attribute of an option tagthis.value = items[this.srcNodeRef.selectedIndex != -1 ? this.srcNodeRef.selectedIndex : 0][this._getValueField()];}}},uninitialize:function(){if(this._popupWidget){this._hideResultList();this._popupWidget.destroy()};},_getMenuLabelFromItem:function(/*Item*/ item){return {html:false, label:this.store.getValue(item, this.searchAttr)};},open:function(){this._isShowingNow=true;return dijit.popup.open({popup: this._popupWidget,around: this.domNode,parent: this});}});dojo.declare("dijit.form._ComboBoxMenu",[dijit._Widget, dijit._Templated],{// summary:// Focus-less div based menu for internal use in ComboBoxtemplateString:"<div class='dijitMenu' dojoAttachEvent='onmousedown,onmouseup,onmouseover,onmouseout' tabIndex='-1' style='overflow:\"auto\";'>"+"<div class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton'></div>"+"<div class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton'></div>"+"</div>",_messages:null,postMixInProperties:function(){this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);this.inherited("postMixInProperties", arguments);},setValue:function(/*Object*/ value){this.value=value;this.onChange(value);},onChange:function(/*Object*/ value){},onPage:function(/*Number*/ direction){},postCreate:function(){// fill in template with i18n messagesthis.previousButton.innerHTML=this._messages["previousMessage"];this.nextButton.innerHTML=this._messages["nextMessage"];this.inherited("postCreate", arguments);},onClose:function(){this._blurOptionNode();},_createOption:function(/*Object*/ item, labelFunc){// summary: creates an option to appear on the popup menu// subclassed by FilteringSelectvar labelObject=labelFunc(item);var menuitem = document.createElement("div");if(labelObject.html){menuitem.innerHTML=labelObject.label;}else{menuitem.appendChild(document.createTextNode(labelObject.label));}// #3250: in blank options, assign a normal heightif(menuitem.innerHTML==""){menuitem.innerHTML=" "}menuitem.item=item;return menuitem;},createOptions:function(results, dataObject, labelFunc){//this._dataObject=dataObject;//this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);// display "Previous . . ." buttonthis.previousButton.style.display=dataObject.start==0?"none":"";// create options using _createOption function defined by parent ComboBox (or FilteringSelect) class// #2309: iterate over cache nondestructivelyvar _this=this;dojo.forEach(results, function(item){var menuitem=_this._createOption(item, labelFunc);menuitem.className = "dijitMenuItem";_this.domNode.insertBefore(menuitem, _this.nextButton);});// display "Next . . ." buttonthis.nextButton.style.display=dataObject.count==results.length?"":"none";},clearResultList:function(){// keep the previous and next buttons of coursewhile(this.domNode.childNodes.length>2){this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);}},// these functions are called in showResultListgetItems:function(){return this.domNode.childNodes;},getListLength:function(){return this.domNode.childNodes.length-2;},onmousedown:function(/*Event*/ evt){dojo.stopEvent(evt);},onmouseup:function(/*Event*/ evt){if(evt.target === this.domNode){return;}else if(evt.target==this.previousButton){this.onPage(-1);}else if(evt.target==this.nextButton){this.onPage(1);}else{var tgt=evt.target;// while the clicked node is inside the divwhile(!tgt.item){// recurse to the toptgt=tgt.parentNode;}this.setValue({target:tgt}, true);}},onmouseover:function(/*Event*/ evt){if(evt.target === this.domNode){ return; }var tgt=evt.target;if(!(tgt==this.previousButton||tgt==this.nextButton)){// while the clicked node is inside the divwhile(!tgt.item){// recurse to the toptgt=tgt.parentNode;}}this._focusOptionNode(tgt);},onmouseout:function(/*Event*/ evt){if(evt.target === this.domNode){ return; }this._blurOptionNode();},_focusOptionNode:function(/*DomNode*/ node){// summary:// does the actual highlightif(this._highlighted_option != node){this._blurOptionNode();this._highlighted_option = node;dojo.addClass(this._highlighted_option, "dijitMenuItemHover");}},_blurOptionNode:function(){// summary:// removes highlight on highlighted optionif(this._highlighted_option){dojo.removeClass(this._highlighted_option, "dijitMenuItemHover");this._highlighted_option = null;}},_highlightNextOption:function(){// because each press of a button clears the menu,// the highlighted option sometimes becomes detached from the menu!// test to see if the option has a parent to see if this is the case.if(!this.getHighlightedOption()){this._focusOptionNode(this.domNode.firstChild.style.display=="none"?this.domNode.firstChild.nextSibling:this.domNode.firstChild);}else if(this._highlighted_option.nextSibling&&this._highlighted_option.nextSibling.style.display!="none"){this._focusOptionNode(this._highlighted_option.nextSibling);}// scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseoverdijit.scrollIntoView(this._highlighted_option);},highlightFirstOption:function(){// highlight the non-Previous choices optionthis._focusOptionNode(this.domNode.firstChild.nextSibling);dijit.scrollIntoView(this._highlighted_option);},highlightLastOption:function(){// highlight the noon-More choices optionthis._focusOptionNode(this.domNode.lastChild.previousSibling);dijit.scrollIntoView(this._highlighted_option);},_highlightPrevOption:function(){// if nothing selected, highlight last option// makes sense if you select Previous and try to keep scrolling up the listif(!this.getHighlightedOption()){this._focusOptionNode(this.domNode.lastChild.style.display=="none"?this.domNode.lastChild.previousSibling:this.domNode.lastChild);}else if(this._highlighted_option.previousSibling&&this._highlighted_option.previousSibling.style.display!="none"){this._focusOptionNode(this._highlighted_option.previousSibling);}dijit.scrollIntoView(this._highlighted_option);},_page:function(/*Boolean*/ up){var scrollamount=0;var oldscroll=this.domNode.scrollTop;var height=parseInt(dojo.getComputedStyle(this.domNode).height);// if no item is highlighted, highlight the first optionif(!this.getHighlightedOption()){this._highlightNextOption();}while(scrollamount<height){if(up){// stop at option 1if(!this.getHighlightedOption().previousSibling||this._highlighted_option.previousSibling.style.display=="none"){break;}this._highlightPrevOption();}else{// stop at last optionif(!this.getHighlightedOption().nextSibling||this._highlighted_option.nextSibling.style.display=="none"){break;}this._highlightNextOption();}// going backwardsvar newscroll=this.domNode.scrollTop;scrollamount+=(newscroll-oldscroll)*(up ? -1:1);oldscroll=newscroll;}},pageUp:function(){this._page(true);},pageDown:function(){this._page(false);},getHighlightedOption:function(){// summary:// Returns the highlighted option.return this._highlighted_option&&this._highlighted_option.parentNode ? this._highlighted_option : null;},handleKey:function(evt){switch(evt.keyCode){case dojo.keys.DOWN_ARROW:this._highlightNextOption();break;case dojo.keys.PAGE_DOWN:this.pageDown();break;case dojo.keys.UP_ARROW:this._highlightPrevOption();break;case dojo.keys.PAGE_UP:this.pageUp();break;}}});dojo.declare("dijit.form.ComboBox",[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],{postMixInProperties: function(){dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);dijit.form.ValidationTextBox.prototype.postMixInProperties.apply(this, arguments);}});}