感谢王牌海盗的投稿!本文首发于:http://cosbor.web-144.com/?p=38
=======================================================================================
在我们国内开发应用系统的过程中往往会遇到这样的需求:下拉菜单中的条目过多时,用户在筛选时往往非常费劲,希望能提供条目拼音简码的方式进行筛选,加快选择速度。而Dojo的FilteringSelect是个非常优秀的具有动态筛选及autoComplete的下拉菜单组件,我们尝试用它来实现一个具有拼音检索功能的下拉菜单。我们以一个三国人物选择的下拉菜单为例看看FilteringSelect的使用,注意demo使用的是dojo的1.8版本。
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组件。代码如下:
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字段进行拼音简码的转换工作。