Chosen 功能强大的 Select 下拉菜单美化插件
Chosen 是 Select 下拉框美化插件,它能让丑陋的、很长的 Select 选择框变的更好看、更方便。此外还可以搜索查找下拉选项。它可对列表进行分组,同时也可禁用某些选择项。
Chosen 插件依赖于 jQuery 库或 prototype,使用之前要先引入 jQuery 或 prototype。我使用的是 chosen1.5.1 版本的,要求 jQuery1.7,支持 IE8+(IE7 及以下版本会优雅降级)。
使用方法
引入 jQuery 插件和 Chosen 插件,对需要美化的下拉框执行 Chosen 函数 $(selector).chosen(options)
。可以把 selector 写成样式类,这样执行完 Chosen 函数后,只要加上样式类就可以了。
1、引入文件
<link href='chosen/1.5.1/chosen.min.css' rel='stylesheet'/>
<script src='jquery-1.9.0.js'></script>
<script src='chosen/1.5.1/chosen.jquery.js'></script>
2、编写下拉菜单
<select class='chosen' multiple>
<option value=""></option>
<option value="China">中国</option>
<option value="US">US</option>
<option value="England">英国</option>
<option value="Canada">加拿大</option>
<option value="Cube">古巴</option>
</select>
3、调用插件
$('.chosen').chosen({
search_contains:false,
enable_split_word_search: true
});
HTML 属性
可以通过在 源 <select>
上设置属性传递给 Chosen。
选项 | 描述 |
---|---|
data-placeholder | 占位符文字。注意: 该属性会覆盖 placeholder_text_multiple 或 placeholder_text_single 选项。 |
multiple | 有此属性的 select 会渲染成可以多选的 Chosen 选框 |
selected, disabled | 设置选中、禁止状态,Chosen 会读取这些属性 |
<select class='chosen' data-placeholder='请选择国家' multiple >
<option value=""></option>
<option value="China" selected>中国
<option value="Canada" disabled>加拿大</option>
</select>
可选参数
选项 | 默认值 | 描述 |
---|---|---|
allow_single_deselect | false | 设置为 true 时非必选的单选框会显示清除选中项图标(x号)。(非必须是指包括空选项,空选项的文本和值都为空) |
disable_search | false | 禁用搜索。设置为 true 时会隐藏单选框的搜索框 |
disable_search_threshold | 0 | 禁用搜索项的选项阈值。 选项数量少于这个阈值时隐藏搜索框 |
enable_split_word_search | true | 是否开启分词搜索,默认开启 |
inherit_select_classes | false | 是否继承 select 元素的 class,如果设为 true ,Chosen 将把 select 的 class 添加到容器上 |
max_selected_options | Infinity | 最多选择项数,达到最大限制时会触发 chosen:maxselected 事件 |
no_results_text | "No results match" | 没有搜索到匹配项时显示的文字 |
placeholder_text_multiple | "Select Some Options" | 多选框没有选中项时显示的占位文字 |
placeholder_text_single | "Select an Option" | 单选框没有选中项时显示的占位文字 |
search_contains | false | 模糊搜索。false 表示从第一个字符开始匹配,true表示只要选项包含搜索词即可 |
single_backstroke_delete | true | 多选框中使用一次退格键即可删除选中项目。为 true ,点击一次退格键即可删除。如果设为 false ,第一次按 delete/backspace 会高亮要删除的选中项目,再按delete/backspace会删除该选项 |
group_search | true | 选项组是否可搜索。false不可搜索,true 可搜索 |
width | Original select width. | Chosen 生成的选择框宽度,默认为和原 select 宽度保持一致。这个值会覆盖原select的宽度。如果执行chosen()函数时下拉框还是隐藏的,必须设置width,否则下拉框设置为可见时宽度为0。 |
display_disabled_options | true | 是否显示禁止选择的项目 |
display_selected_options | true | 多选框是否在下拉列表中显示已经选中的项。为false时下拉列表不显示选中选项,为true时下拉列表会显示选中选项,但会用特殊的样式标识。这个选项对单选框无效。 |
include_group_label_in_selected | false | 选中选项是否显示选项分组。false不显示,true显示。默认false。 |
max_shown_results | Infinity | 搜索结果最大显示数量。数量设置得小,可以提高速度。 |
case_sensitive_search | false | 搜索大小写敏感。为false大小写不敏感,为true大小写不敏感。chosen1.5.1还不支持。 |
hide_results_on_select | true | 搜索结果隐藏选中选项,只对多选框有效。为true表示隐藏,为false表示不隐藏。chosen1.5.1还不支持。 |
rtl | false | 文字方向是否改为从右向左。true表示文字方向从右向左,false表示从左向右。chosen1.5.1还不支持,但是可以给下拉框加上chosen-rtl。但是未来chosen会去掉这个样式类 |
监听事件
Chosen 会在源 <select>
元素上监听事件。
$('.chosen').on('change', function(e, params) {
do_something(e, params);
});
选项 | 描述 |
---|---|
change | Chosen 触发标准的 change 事件,同时会传递 selected or deselected 参数, 方便用户获取改变的选项 |
chosen:ready | Chosen 实例化完成时触发 |
chosen:maxselected | 超过 max_selected_options 设置时触发 |
chosen:showing_dropdown | Chosen 下拉选框打开完成时触发 |
chosen:hiding_dropdown | Chosen 下拉选框关闭完成时触发 |
chosen:no_results | 搜索没有匹配项时触发 |
注意:所有 Chosen 自定义事件都包含 Chosen 实例。Chosen 对象作为参数。
Chosen 触发的事件
通过在 源 <select> 元素上触发特定事件:
$('.chosen').trigger('chosen:updated');
选项 | 描述 |
---|---|
chosen:updated | 通过 JS 改变 select 元素选项时应该触发此事件,以更新 Chosen 生成的选框 |
chosen:activate | 相当于 HTML focus 事件 |
chosen:open | Chosen 并显示搜索结果 |
chosen:close | 关闭 Chosen 并隐藏搜索结果 |
Chosen 插件优化(通过传参)
Chosen 插件可以通过控制下拉框显示的最大数量来达到优化的目的。
$('.chosen').chosen({
max_shown_results: 1000, //下拉框最大显示选项数量
});
比如某项目的团队管理页面有 30 个下拉框(选择团队成员),每个下拉框有 1300 个选项。IE8 加载该页面需要耗时 45s,根本没法使用。看下设置下拉框最大显示数量。
浏览器 | 火狐 | 谷歌 | IE | |||
---|---|---|---|---|---|---|
优化后 | 效率提升 | 优化前 | 效率提升 | 优化前 | 效率提升 | |
1300 | 0.063 | 0.074 | 0.822 | |||
500 | 0.031 | 51.0% | 0.037 | 43.0% | 0.453 | 25.1% |
100 | 0.013 | 79.0% | 0.017 | 66.3% | 0.294 | 36.0% |
Chosen 插件优化(修改插件)
优化思路
Chosen 插件使用还是很方便,但是有多个下拉框且下拉框的数量比较多时就会比较慢,尤其是 IE 浏览器。上面虽然提到可以通过控制选项数量来提高效率,但这种方式并不适合所有场景。搜索结果有些不显示,用户直接拖动选择的时候会找不到目标选项。需要通过其他方式来优化
比如上面提到的某项目的团队管理页面有30个下拉框(选择团队成员),每个下拉框有 1300 个选项。IE8 加载该页面需要耗时 45s,根本没法使用。
Chosen 插件的实现原理其实是获取原下拉框的数据,构造一个新的 Chosen 下拉框。下拉框数据量多的时候,构造这个列表还是挺耗时的,IE8 将近 1s。之所以加载慢是因为 Chosen 插件在加载页面的时候就构造了所有的 Chosen 下拉框。
优化思路就是页面加载的时候 Chosen 下拉框不加载所有原下拉框的数据,而只获取选中项。等到用户第一次点击下拉框的时候再去获取完整的原下拉选项。把耗时分摊到第一次点击下拉框。这样提高用户体验:一个是因为用户并不会点击所有的下拉框,因此总耗时其实是减少的;另外页面加载时间耗时,用户根本不想等待,如果是分摊下去,耗时并不多,用户感受也不明显。
优化效果(以团队管理页面为例)
浏览器 | 优化前 | 优化后 | 效率提高 | ||||||
---|---|---|---|---|---|---|---|---|---|
页面加载 | 单个下拉框 | 总耗时 | 页面加载 | 单个下拉框 | 总耗时 | 页面加载 | 单个下拉框 | 总耗时 | |
火狐 | 0.683 | 0.063 | 2.573 | 0.473 | 0.473 | 2.633 | 30.75% | -14.29% | -2.33% |
谷歌 | 0.393 | 0.074 | 2.613 | 0.273 | 2.853 | 0.473 | 30.53% | -16.22% | -9.18% |
IE | 21.259 | 0.822 | 45.919 | 1.223 | 1.468 | 45.263 | 94.52% | -78.25% | 1.43% |
注意:
- 总耗时 = 页面加载 + 单个下拉框 * 下拉框总数
- 上表中的单个下拉框的耗时是指第一次点击下拉框的耗时,第一次以后点击下拉框,优化前和优化后耗时是一样的。所以上面的单个下拉框耗时和总耗时虽然是下降的,但是考虑用户并不会点击所有下拉框,总体上用户体验度是上升的。
优化的代码
执行 chosen() 函数会调用 set_up_html 函数,set_up_html() 函数会调用 results_build() 函数,用于构造下拉选项。
我们要给 results_build() 加上参数 only_selected_option,用于标识构造的下拉列表是否只包含选中选项,false 标识包含所有选项。
set_up_html() 调用 results_build() 时,参数 only_selected_option 设置为 true。
另外第一次点击下拉框时,要执行 results_build(),参数 only_selected_option 设置为 true。
Chosen.prototype.set_up_html = function() {
......
this.results_build(true); //only_selected_option参数设置为true
......
}
Chosen.prototype.register_observers = function() {
var _this = this;
this.container.bind('mousedown.chosen', function(evt) {
/*新增代码。第一次点击下拉框时构建完整的下拉框列表*/
if(_this.results_data.length < _this.form_field.options.length) {
_this.results_build(false);
}
_this.container_mousedown(evt); //原有代码
});
}
/*增加only_selected_option参数*/
Chosen.prototype.results_build = function(only_selected_option) {
......
this.results_data = SelectParser.select_to_array(this.form_field);
......
}
/*增加only_selected_option参数*/
SelectParser.select_to_array = function(select, only_selected_option) {
var child, parser, _i, _len, _ref, is_optgroup;
is_optgroup = select.children[0].nodeName.toUpperCase() == 'OPTGROUP'; //新增的变量
only_selected_option = !!only_selected_option; //默认false
parser = new SelectParser();
_ref = select.childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
/*如果是OPTGROUP,要先加到parser中,后面再对OPTGROUP中的选项做处理;如果当前选项是当前要获取的是全部选项或只获取选中选项*/
if(is_optgroup || (!only_selected_option || child.selected)) {
parser.add_node(child);
}
}
return parser.parsed;
}
相关链接
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论