📄 combobox.js
字号:
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 appear var 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) }); dijit.setWaiState(this.comboNode, "expanded", "true"); }, _hideResultList: function(){ if(this._isShowingNow){ dijit.popup.close(this._popupWidget); this._arrowIdle(); this._isShowingNow=false; dijit.setWaiState(this.comboNode, "expanded", "false"); dijit.removeWaiState(this.focusNode,"activedescendant"); } }, _setBlurValue: function(){ // 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 value var newvalue=this.getDisplayedValue(); var pw = this._popupWidget; if(pw && ( newvalue == pw._messages["previousMessage"] || newvalue == pw._messages["nextMessage"] ) ){ this.setValue(this._lastValueReported, true); }else{ this.setDisplayedValue(newvalue); } }, _onBlur: function(){ // summary: called magically when focus has shifted away from this widget and it's dropdown this._hideResultList(); this._arrowIdle(); this.inherited(arguments); }, _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 // menu if(node == null){ return; } // pull the text value from the item attached to the DOM node var 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)); //set up ARIA activedescendant dijit.setWaiState(this.focusNode, "activedescendant", dojo.attr(node, "id")); // autocomplete the rest of the option to announce change this._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 TAB this.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 clicked if(this.disabled || this.readOnly){ 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 options this._startSearch(""); } }, _startSearchFromInput: function(){ this._startSearch(this.focusNode.value); }, _getQueryString: function(/*String*/ text){ return dojo.string.substitute(this.queryExpr, [text]); }, _startSearch: function(/*String*/ key){ if(!this._popupWidget){ var popupId = this.id + "_popup"; this._popupWidget = new dijit.form._ComboBoxMenu({ onChange: dojo.hitch(this, this._selectOption), id:popupId }); dijit.removeWaiState(this.focusNode,"activedescendant"); dijit.setWaiState(this.textbox,"owns",popupId); // associate popup with textbox } // create a new query to prevent accidentally querying for a hidden // value from FilteringSelect's keyField this.item = null; // #4872 var query = dojo.clone(this.query); // #5970 this._lastQuery = query[this.searchAttr] = this._getQueryString(key); // #5970: set _lastQuery, *then* start the timeout // otherwise, if the user types and the last query returns before the timeout, // _lastQuery won't be set and their input gets rewritten this.searchTimer=setTimeout(dojo.hitch(this, function(query, _this){ var dataObject = this.store.fetch({ queryOptions: { ignoreCase: this.ignoreCase, deep: true }, query: query, onComplete: dojo.hitch(this, "_openResultList"), onError: function(errText){ console.error('dijit.form.ComboBox: ' + errText); dojo.hitch(_this, "_hideResultList")(); }, start:0, count:this.pageSize }); var nextSearch = function(dataObject, direction){ dataObject.start += dataObject.count*direction; // #4091: // tell callback the direction of the paging so the screen // reader knows which menu option to shout dataObject.direction = direction; this.store.fetch(dataObject); } this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, dataObject); }, query, this), this.searchDelay); }, _getValueField:function(){ return this.searchAttr; }, /////////////// Event handlers ///////////////////// _arrowPressed: function(){ if(!this.disabled && !this.readOnly && this.hasDownArrow){ dojo.addClass(this.downArrowNode, "dijitArrowButtonActive"); } }, _arrowIdle: function(){ if(!this.disabled && !this.readOnly && this.hasDownArrow){ dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed"); } }, // FIXME: // this is public so we can't remove until 2.0, but the name // SHOULD be "compositionEnd" 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){ var srcNodeRef = this.srcNodeRef; // if user didn't specify store, then assume there are option tags this.store = new dijit.form._ComboBoxDataStore(srcNodeRef); // if there is no value set and there is an option list, set // the value to the first value to be consistent with native // Select // Firefox and Safari set value // IE6 and Opera set selectedIndex, which is automatically set // by the selected attribute of an option tag // IE6 does not set value, Opera sets value = selectedIndex if( !this.value || ( (typeof srcNodeRef.selectedIndex == "number") && srcNodeRef.selectedIndex.toString() === this.value) ){ var item = this.store.fetchSelectedItem(); if(item){ this.value = this.store.getValue(item, this._getValueField()); } } } }, _postCreate:function(){ //find any associated label element and add to combobox node. var label=dojo.query('label[for="'+this.id+'"]'); if(label.length){ label[0].id = (this.id+"_label"); var cn=this.comboNode; dijit.setWaiState(cn, "labelledby", label[0].id); dijit.setWaiState(cn, "disabled", this.disabled); } }, 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 }); }, reset:function(){ // summary: // Additionally reset the .item (to clean up). this.item = null; this.inherited(arguments); } });dojo.declare( "dijit.form._ComboBoxMenu", [dijit._Widget, dijit._Templated], { // summary: // Focus-less div based menu for internal use in ComboBox templateString: "<ul class='dijitMenu' dojoAttachEvent='onmousedown:_onMouseDown,onmouseup:_onMouseUp,onmouseover:_onMouseOver,onmouseout:_onMouseOut' tabIndex='-1' style='overflow:\"auto\";'>" +"<li class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton'></li>" +"<li class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton'></li>" +"</ul>", _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); }, // stubs onChange: function(/*Object*/ value){}, onPage: function(/*Number*/ direction){}, postCreate:function(){ // fill in template with i18n messages this.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 // FilteringSelect var labelObject = labelFunc(item); var menuitem = dojo.doc.createElement("li"); dijit.setWaiRole(menuitem, "option"); if(labelObject.html){ menuitem.innerHTML = labelObject.label; }else{ menuitem.appendChild( dojo.doc.createTextNode(labelObject.label) ); } // #3250: in blank options, assign a normal height if(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 . . ." button this.previousButton.style.display = (dataObject.start == 0) ? "none" : ""; dojo.attr(this.previousButton, "id", this.id + "_prev"); // create options using _createOption function defined by parent
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -