当前位置 : 主页 > 网页制作 > Dojo >

使用Dojo的FilteringSelect打造具有拼音检索功能的下拉菜单(上)

来源:互联网 收集:自由互联 发布时间:2021-06-15
感谢王牌海盗的投稿!本文首发于:http://cosbor.web-144.com/?p=38 ========= ========= ========= ========= ========= ========= ========= ========= ========= ====== 在我们国内开发应用系统的过程中往往会遇到这样

感谢王牌海盗的投稿!本文首发于:http://cosbor.web-144.com/?p=38 

=======================================================================================
在我们国内开发应用系统的过程中往往会遇到这样的需求:下拉菜单中的条目过多时,用户在筛选时往往非常费劲,希望能提供条目拼音简码的方式进行筛选,加快选择速度。而Dojo的FilteringSelect是个非常优秀的具有动态筛选及autoComplete的下拉菜单组件,我们尝试用它来实现一个具有拼音检索功能的下拉菜单。我们以一个三国人物选择的下拉菜单为例看看FilteringSelect的使用,注意demo使用的是dojo的1.8版本。

? FilteringSelect.html 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> < html > < head >      < title >下拉菜单</ title >       < link rel = "stylesheet" href = "static/js/dojo/dojo/resources/dojo.css" /> < link rel = "stylesheet" href = "static/js/dojo/dijit/themes/claro/claro.css" /> < script type = "text/javascript" src = "static/js/dojo/dojo/dojo.js" data-dojo-config = "async: true,parseOnLoad: true" ></ script >   < script type = "text/javascript" >      require([          'dijit/form/FilteringSelect',          'dojo/store/Memory',          'dojo/domReady!'      ],function(FilteringSelect,Memory){                          //下拉菜单的store,"py"字段存放每个条目的拼音简码            var selectStore = new Memory({                  data:[                      {name:'赵云',id:'1',py:'zy'},                          {name:'张飞',id:'2',py:'zf'},                          {name:'刘备',id:'3',py:'lb'},                          {name:'关羽',id:'4',py:'gy'},                          {name:'黄忠',id:'5',py:'hz'},                          {name:'魏延',id:'6',py:'wy'},                          {name:'周瑜',id:'7',py:'zy'},                          {name:'孙坚',id:'8',py:'sj'},                          {name:'曹操',id:'9',py:'cc'},                          {name:'夏侯敦',id:'10',py:'xhd'},                      ]            });                        //创建FilteringSelect            var testSelect = new FilteringSelect({                id: "testSelect",                name: "test",                value: "",                store: selectStore,                searchAttr: 'py',//指定输入文本框进行用来进行检索的字段                labelAttr: 'name',//指定下拉菜单中显示的字段                required:false,                autoComplete:false            },"testSelect");                }); </ script > </ head >   < body  class = "claro" > < div style = "text-align: center;width: 100%;padding-top: 100px;font-size:15px;" >          三国人物:< input id = "testSelect" /> </ div > </ body > </ html >

运行页面,在下拉菜单输入框中输入“zy”,发现下拉菜单已经可以根据输入的拼音简码进行过滤了,如下图:

这时,问题来了,你会发现当鼠标选定下拉菜单中条目,如选“周瑜”时,最终在输入框中呈现的并不是我们想要的中文名称“周瑜”而是该条目对应的py字段的值“zy”。这是因为FilteringSelect会以searchAttr属性中设置的字段作为最终显示结果。但这并不是我们想要的结果,我们希望显示的是中文的name字段。

经过翻看FilteringSelect的源码,发现可以对FilteringSelect进行一下小的改造来满足我们的要求。可以使用Dojo提供的自定义组件机制,通过继承FilteringSelect来创建一个满足我们需求的FilteringSelect组件。代码如下:

? customSelect 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 define([      "dojo/_base/declare" , // declare,      "dojo/dom-attr" , // domAttr.get      "dijit/form/FilteringSelect" ], function (declare, domAttr ,FilteringSelect){        return declare( "test.FilteringSelect" , [FilteringSelect], {                            displayValueAttr: null , //新增一个自定义属性,用于指定FilteringSelect的textbox中最终显示内容的属性字段                        // summary:              // 覆盖dijit.form._AutoCompleterMixin的同名方法,使FilteringSelect支持displayValueAttr指定textbox最终显示内容,而不是默认显示searchAttr指定的字段内容              _announceOption: function ( /*Node*/ node){                    if (!node){                      return ;                  }                  // pull the text value from the item attached to the DOM node                  var newValue;                  if (node == this .dropDown.nextButton ||                      node == this .dropDown.previousButton){                      newValue = node.innerHTML;                      this .item = undefined;                      this .value = '' ;                  } else {                      var item = this .dropDown.items[node.getAttribute( "item" )];                      var displayAttr = this .displayValueAttr!= null ? this .displayValueAttr: this .searchAttr; //此处判断是否配置了自定义属性displayValueAttr                                            newValue = ( this .store._oldAPI ?    // remove getValue() for 2.0 (old dojo.data API)                          this .store.getValue(item, displayAttr) : item[displayAttr]).toString(); //将this.searchAttr替换为displayAttr                        this .set( 'item' , item, false , newValue);                  }                  // get the text that the user manually entered (cut off autocompleted text)                  this .focusNode.value = this .focusNode.value.substring(0, this ._lastInput.length);                  // set up ARIA activedescendant                  this .focusNode.setAttribute( "aria-activedescendant" , domAttr.get(node, "id" ));                  // autocomplete the rest of the option to announce change                  this ._autoCompleteText(newValue);              },        }); });

将页面中引入FilteringSelect换成我们自定义的FilteringSelect,然后在创建FilteringSelect时的代码中加入自定义的displayValueAttr属性。

? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <script type= "text/javascript" >      require([          'test/FilteringSelect' ,          'dojo/store/Memory' ,          'dojo/domReady!'      ], function (FilteringSelect,Memory){                          //下拉菜单的store,"py"字段存放每个条目的拼音简码            var selectStore = new Memory({                  data:[                      {name: '赵云' ,id: '1' ,py: 'zy' },                          {name: '张飞' ,id: '2' ,py: 'zf' },                          {name: '刘备' ,id: '3' ,py: 'lb' },                          {name: '关羽' ,id: '4' ,py: 'gy' },                          {name: '黄忠' ,id: '5' ,py: 'hz' },                          {name: '魏延' ,id: '6' ,py: 'wy' },                          {name: '周瑜' ,id: '7' ,py: 'zy' },                          {name: '孙坚' ,id: '8' ,py: 'sj' },                          {name: '曹操' ,id: '9' ,py: 'cc' },                          {name: '夏侯敦' ,id: '10' ,py: 'xhd' },                      ]            });                        //创建FilteringSelect            var testSelect = new FilteringSelect({                id: "testSelect" ,                name: "test" ,                value: "" ,                store: selectStore,                searchAttr: 'py' , //指定输入文本框进行用来进行检索的字段                labelAttr: 'name' , //指定下拉菜单中显示的字段                displayValueAttr: 'name' , //指定选中下拉菜单后显示在输入框中的字段                required: false ,                autoComplete: false            }, "testSelect" );                }); </script>

再次访问本页面,可以看到在选择下拉菜单条目后,text输入框显示为name的中文了。

下篇预告:准备写一下服务端自动实现新增实体bean时,将相应name字段转为拼音简码后存储。大致过程是编写一个java注解,在model实体类中标注需要进行汉字转拼音的属性字段,利用spring的AOP功能,编写一个统一切面,在dao层对保存实体的save方法进行拦截,将标注的name字段转为拼音简码后注入bean的拼音简码字段,这样使业务编码人员无需再关注对实体name字段进行拼音简码的转换工作。

网友评论