📄 combobox.js
字号:
// ComboBox (or FilteringSelect) class // #2309: // iterate over cache nondestructively dojo.forEach(results, function(item, i){ var menuitem = this._createOption(item, labelFunc); menuitem.className = "dijitMenuItem"; dojo.attr(menuitem, "id", this.id + i); this.domNode.insertBefore(menuitem, this.nextButton); }, this); // display "Next . . ." button this.nextButton.style.display = (dataObject.count == results.length) ? "" : "none"; dojo.attr(this.nextButton,"id", this.id + "_next") }, clearResultList: function(){ // keep the previous and next buttons of course while(this.domNode.childNodes.length>2){ this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]); } }, // these functions are called in showResultList getItems: 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 div while(!tgt.item){ // recurse to the top tgt = 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 div while(!tgt.item){ // recurse to the top tgt = 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 highlight if(this._highlighted_option != node){ this._blurOptionNode(); this._highlighted_option = node; dojo.addClass(this._highlighted_option, "dijitMenuItemHover"); } }, _blurOptionNode:function(){ // summary: // removes highlight on highlighted option if(this._highlighted_option){ dojo.removeClass(this._highlighted_option, "dijitMenuItemHover"); this._highlighted_option = null; } }, _highlightNextOption:function(){ // summary: // Highlight the item just below the current selection. // If nothing selected, highlight first option // 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. var fc = this.domNode.firstChild; if(!this.getHighlightedOption()){ this._focusOptionNode(fc.style.display=="none" ? fc.nextSibling : fc); }else{ var ns = this._highlighted_option.nextSibling; if(ns && ns.style.display!="none"){ this._focusOptionNode(ns); } } // scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover dijit.scrollIntoView(this._highlighted_option); }, highlightFirstOption:function(){ // summary: // Highlight the first real item in the list (not Previous Choices). this._focusOptionNode(this.domNode.firstChild.nextSibling); dijit.scrollIntoView(this._highlighted_option); }, highlightLastOption:function(){ // summary: // Highlight the last real item in the list (not More Choices). this._focusOptionNode(this.domNode.lastChild.previousSibling); dijit.scrollIntoView(this._highlighted_option); }, _highlightPrevOption:function(){ // summary: // Highlight the item just above the current selection. // If nothing selected, highlight last option (if // you select Previous and try to keep scrolling up the list) var lc = this.domNode.lastChild; if(!this.getHighlightedOption()){ this._focusOptionNode(lc.style.display == "none" ? lc.previousSibling : lc); }else{ var ps = this._highlighted_option.previousSibling; if(ps && ps.style.display != "none"){ this._focusOptionNode(ps); } } dijit.scrollIntoView(this._highlighted_option); }, _page:function(/*Boolean*/ up){ var scrollamount = 0; var oldscroll = this.domNode.scrollTop; var height = dojo.style(this.domNode, "height"); // if no item is highlighted, highlight the first option if(!this.getHighlightedOption()){ this._highlightNextOption(); } while(scrollamount<height){ if(up){ // stop at option 1 if(!this.getHighlightedOption().previousSibling || this._highlighted_option.previousSibling.style.display == "none"){ break; } this._highlightPrevOption(); }else{ // stop at last option if(!this.getHighlightedOption().nextSibling || this._highlighted_option.nextSibling.style.display == "none"){ break; } this._highlightNextOption(); } // going backwards var 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. var ho = this._highlighted_option; return (ho && ho.parentNode) ? ho : 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], { // summary: // Auto-completing text box, and base class for dijit.form.FilteringSelect. // // description: // 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 dijit.formComboBoxMixin) will inherit from dijit.form._FormWidget and thus the `this` // reference will also "be a" _FormWidget. postMixInProperties: function(){ // this.inherited(arguments); // ?? dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments); dijit.form.ValidationTextBox.prototype.postMixInProperties.apply(this, arguments); }, postCreate: function(){ dijit.form.ComboBoxMixin.prototype._postCreate.apply(this, arguments); dijit.form.ValidationTextBox.prototype.postCreate.apply(this, arguments); }, setAttribute: function(/*String*/ attr, /*anything*/ value){ dijit.form.ValidationTextBox.prototype.setAttribute.apply(this, arguments); dijit.form.ComboBoxMixin.prototype._setAttribute.apply(this, arguments); } });dojo.declare("dijit.form._ComboBoxDataStore", null, { // summary: // Inefficient but small data store specialized for inlined ComboBox data // // description: // Provides a store for inlined data like: // // | <select> // | <option value="AL">Alabama</option> // | ... // // Actually. just implements the subset of dojo.data.Read/Notification // needed for ComboBox and FilteringSelect to work. // // Note that an item is just a pointer to the <option> DomNode. constructor: function( /*DomNode*/ root){ this.root = root;/* // TODO: this was added in #3858 but unclear why/if it's needed; doesn't seem to be. // If it is needed then can we just hide the select itself instead? dojo.query("> option", root).forEach(function(node){ node.style.display="none"; });*/ }, getValue: function( /* item */ item, /* attribute-name-string */ attribute, /* value? */ defaultValue){ return (attribute == "value") ? item.value : (item.innerText || item.textContent || ''); }, isItemLoaded: function(/* anything */ something) { return true; }, fetch: function(/* Object */ args){ // summary: // Given a query and set of defined options, such as a start and count of items to return, // this method executes the query and makes the results available as data items. // Refer to dojo.data.api.Read.fetch() more details. // // description: // Given a query like // // | { // | query: {name: "Cal*"}, // | start: 30, // | count: 20, // | ignoreCase: true, // | onComplete: function(/* item[] */ items, /* Object */ args){...} // | } // // will call `onComplete()` with the results of the query (and the argument to this method) // convert query to regex (ex: convert "first\last*" to /^first\\last.*$/i) and get matching vals var query = "^" + args.query.name .replace(/([\\\|\(\)\[\{\^\$\+\?\.\<\>])/g, "\\$1") .replace("*", ".*") + "$", matcher = new RegExp(query, args.queryOptions.ignoreCase ? "i" : ""), items = dojo.query("> option", this.root).filter(function(option){ return (option.innerText || option.textContent || '').match(matcher); } ); var start = args.start || 0, end = ("count" in args && args.count != Infinity) ? (start + args.count) : items.length ; args.onComplete(items.slice(start, end), args); return args; // Object // TODO: I don't need to return the length? }, close: function(/*dojo.data.api.Request || args || null */ request){ return; }, getLabel: function(/* item */ item){ return item.innerHTML; }, getIdentity: function(/* item */ item){ return dojo.attr(item, "value"); }, fetchItemByIdentity: function(/* Object */ args){ // summary: // Given the identity of an item, this method returns the item that has // that identity through the onItem callback. // Refer to dojo.data.api.Identity.fetchItemByIdentity() for more details. // // description: // Given arguments like: // // | {identity: "CA", onItem: function(item){...} // // Call `onItem()` with the DOM node `<option value="CA">California</option>` var item = dojo.query("option[value='" + args.identity + "']", this.root)[0]; args.onItem(item); }, fetchSelectedItem: function(){ // summary: // Get the option marked as selected, like `<option selected>`. // Not part of dojo.data API. var root = this.root, si = root.selectedIndex; return dojo.query("> option:nth-child(" + (si != -1 ? si+1 : 1) + ")", root)[0]; // dojo.data.Item }});}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -