最近在用dojo做一個項目的前臺。版本是1.2.3,期間使用到了FilteringSelect這個下拉菜單控件。這個控件的功能不錯,即可以像傳統的select標籤一樣下拉選擇,還可以讓用戶直接輸入進行逐字搜索匹配。不過,東西畢竟是老外做的,使用時還是到了一些水土不服的問題,這些問題在網上搜過,但都沒什麼結果。現在有些問題解決了,有些沒有很完美的解決。現在拿出來和大家一起分享和討論一下。
問題1:FilteringSelect和ComboBox控件中文顯示問題
發現FilteringSelect選定選項後,英文可以正常顯示在控件中間,但中文有明顯的上移,字體上面一小部分被遮蓋,下面有較大的空隙。我想應該是dojo的css樣式設定問題,於是找到了dijit\themes\dijit.css文件。其中有一段定義ComboBox文本框樣式的
.dijitTextBox INPUT, .dijitComboBox INPUT, .dijitSpinner INPUT { border-left: solid black 1px; display:inline; position:static !important; border:0 !important; margin:0 !important; vertical-align:top!important; visibility:visible !important; background-color:transparent !important; background-image:none !important; width:100% !important; }
其中vertical-align這項默認竟然是top,現改爲middle後,中文顯示正常。
問題2: 在FilteringSelect中輸入文字時,控件默認是按照從第一個字開始匹配的。現想對 可選項根據 輸入的字進行包含式模糊查詢的功能
之前查看了FilteringSelect的API,發現有個queryExpr的屬性,根據說明
dojo.data query expression pattern. ${0} will be substituted for the user text. * is used for wildcards. ${0}* means "starts with", *${0}* means "contains", ${0} means "is"
這個*${0}*應該就是我們想要的包含查詢了。於是將queryExpr=“ *${0}* ”屬性加入到 FilteringSelect得input標籤裏。但發現這樣聲明並不起作用,無奈之下,翻了下ComboBox.js的源碼,在其中發現了queryExpr屬性初始化的位置如下
// labelType: String //"html" or "text" labelType: "text", // queryExpr: String // dojo.data query expression pattern. // `${0}` will be substituted for the user text. // `*` is used for wildcards. // `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is" queryExpr: "${0}*" // ignoreCase: Boolean ignoreCase: true,
無奈下,在代碼中直接將queryExpr的初始值改爲 "*${0}*" ,問題解決。
問題3:在 FilteringSelect輸入中文後不像輸入英文或數字一樣自動進行搜索匹配,只能敲了空格再敲回退鍵的時候才觸發顯示提示選項
這個問題比較頭疼。繼續翻ComboBox的源碼,找到ComboBox文本框處理按鍵事件的函數,如下
_onKeyPress: function(/*Event*/ evt){ // summary: handles keyboard events var key = evt.charOrCode; //except for cutting/pasting case - ctrl + x/v if(evt.altKey || (evt.ctrlKey && (key != 'x' && key != 'v')) || evt.key == dojo.keys.SHIFT){ return; // throw out weird key combinations and spurious events } var doSearch = false; var pw = this._popupWidget; var dk = dojo.keys; if(this._isShowingNow){ pw.handleKey(key); } switch(key){ case dk.PAGE_DOWN: case dk.DOWN_ARROW: if(!this._isShowingNow||this._prev_key_esc){ this._arrowPressed(); doSearch=true; }else{ this._announceOption(pw.getHighlightedOption()); } dojo.stopEvent(evt); this._prev_key_backspace = false; this._prev_key_esc = false; break; case dk.PAGE_UP: case dk.UP_ARROW: if(this._isShowingNow){ this._announceOption(pw.getHighlightedOption()); } dojo.stopEvent(evt); this._prev_key_backspace = false; this._prev_key_esc = false; break; case dk.ENTER: // prevent submitting form if user presses enter. Also // prevent accepting the value if either Next or Previous // are selected var highlighted; if(this._isShowingNow && (highlighted = pw.getHighlightedOption()) ){ // only stop event on prev/next if(highlighted == pw.nextButton){ this._nextSearch(1); dojo.stopEvent(evt); break; }else if(highlighted == pw.previousButton){ this._nextSearch(-1); dojo.stopEvent(evt); break; } }else{ // Update 'value' (ex: KY) according to currently displayed text this._setDisplayedValueAttr(this.attr('displayedValue'), true); } // default case: // prevent submit, but allow event to bubble // 加入按下enter鍵後觸發搜索 doSearch = true; evt.preventDefault(); // fall through ........................................... } 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 visible setTimeout(dojo.hitch(this, "_startSearchFromInput"),1); } }
搜了下官網論壇,發現亞洲語言都會有這個問題,上面也沒有可借鑑的解決方案,這個問題直接原因應該是中文字都是通過輸入法軟件進行錄入的,控件文本框中無法捕捉到鍵盤的敲擊事件導致無法觸發search方法。
我目前一個變通方式就是在捕捉到enter事件後進行search,添加代碼如上。用戶在輸入文字後按enter鍵進行模糊查詢並顯示搜索後可選項。
最後一個問題不知道有沒有更好的解決方法,期待ing。