在网页中,下拉框的样式最难美化,默认样式巨丑,好在现在已经有各种框架实现了下拉框的样式美化,主要思路都是通过JS代码将下拉框元素用更容易设置样式的div进行替换,再将对应选项及事件进行关联。
最近一项目需要修改很久以前的页面,用户需求又需要美化下拉框样式,又不能引入第三方的框架,只好自己动手写了一个JS插件,实现下拉框的样式美化。
1、插件效果
页面包含两个下拉框,一个3个选项,一个多个选项,一个选项内容较短,一个较长,页面代码如下:
<form>
<div class="div-form">
<div class="div-form-row">
<span class="form-title">selected: </span>
<div class="form-input">
<select name="s1" onchange="selectChange('1','2')">
<option value="1">1111</option>
<option value="2" selected>2222</option>
<option value="3">3333</option>
</select>
</div>
</div>
<div class="div-form-row">
<span class="form-title">select time zone: </span>
<div class="form-input">
<select name="s2">
<option value="1">(GMT-12:00) International Date Line West</option>
<option value="2">(GMT-11:00) Midway Island, Samoa</option>
<option value="3">(GMT-10:00) Hawaii</option>
<option value="4">(GMT-09:00) Alaska</option>
<option value="5">(GMT-08:00) Pacific Time, Tijuana</option>
<option value="6">(GMT-07:00) Arizona, Mazatlan</option>
<option value="7">(GMT-07:00-1) Chihuahua, La Paz</option>
<option value="8">(GMT-07:00-2) Mountain Time</option>
<option value="9">(GMT-06:00) Central America</option>
<option value="10">(GMT-06:00-1) Central Time</option>
<option value="11" selected>(GMT-06:00-2) Guadalajara, Mexico City, Monterrey</option>
<option value="12">(GMT-06:00-3) Saskatchewan</option>
<option value="13">(GMT-05:00) Bogota, Lima, Quito</option>
<option value="14">(GMT-05:00-1) Eastern Time</option>
<option value="15">(GMT-05:00-2) Indiana</option>
<option value="16">(GMT-04:00) Atlantic Time</option>
<option value="17">(GMT-04:00-1) Caracas, La Paz</option>
<option value="18">(GMT-04:00-2) Santiago</option>
<option value="19">(GMT-03:30) Newfoundland</option>
</select>
</div>
</div>
</div>
</form>
<script src="select.js"></script>
<link rel="stylesheet" href="select.css">
主要变化是整个下拉框使用边框包裹,下拉框展开和收起状态右侧箭头方向改变,选项列表设置了最高高度,超过高度出现滚动条,选中的选项自定背景色展示。
2、实现步骤
win.addListener(win, 'load', function () {
renderSelects();
});
win.renderSelects = function (className) {
var selectList;
if (typeof className != "string" || className.trim().length == 0) {
selectList = document.querySelectorAll('select');
} else {
selectList = document.getElementsByClassName(className);
}
for (var i = 0; i < selectList.length; i++) {
renderOneSelect(selectList[i]);
}
}
此方法主要将页面中的下拉框通过选择器选取出来,再循坏调用单个的渲染方法进行渲染。此方法可以传入下拉框的样式类名,传入后选择器匹配的下拉框才会进行自定义样式渲染,未传入参数时页面内全部的下拉框都会进行渲染。
再看单个下拉框的渲染 renderOneSelect(el),这里的el是单个的下拉框元素。先添加一个临时的段落元素pTemp,然后用此段落元素,与下拉框进行替换,占住下拉框原来的位子,等待div构造的下拉框结构拼接好后再将pTemp替换掉:
renderOneSelect(el){
var pTemp = document.createElement("p");
el.replaceWith(pTemp);
var divSelect = document.createElement("div"); //div构造的下拉框结构
// ... 一系列构造过程
pTemp.replaceWith(divSelect); //用构造好的div替换掉 pTemp
}
整个下拉框用div.div-select包裹,原有下拉框select元素放到div.div-select内,其后添加div.div-options,div.div-options内部包含了两个div,第一个div.div-selected,用于展示下拉框当前选中的选项,第二个用于展示所有的下拉框选项,单个选项用div.div-option展示,当前选中的选项添加 option-selected 样式,与其他选项区别展示。选项的内容使用span元素包裹展示,用于控制长度,超过长度出现省略号,添加title,当鼠标悬停时展示完整的选项内容。
div.div-select添加click事件处理,点击时进行选项列表的展开和收起操作:
selectClick = function (el) {
if (el.hasClass("select-open")) {
el.removeClass("select-open")
} else {
el.addClass("select-open");
}
}
div.div-select添加blur事件处理,失去焦点时收起选项列表:
selectBlur = function (el) {
if (el.hasClass("select-open")) {
el.removeClass("select-open")
}
}
div.div-option添加click事件处理,点击时选中该选项,同步设置原有select选项的选中状态,设置原有select的selectIndex,调用原有select的onchange方法:
optionClick = function (el) {
var _value = el.get("value");
var select = el.parentElement.parentElement.parentElement.children[0];
var originIndex = select.selectedIndex;
var optionLength = select.children.length;
for (var i = 0; i < optionLength; i++) {
if (select.children[i].get("value") == _value) {
select.children[i].set("selected", "");
} else {
select.children[i].remove("selected");
}
}
var selected = el.parentElement.parentElement.children[0];
selected.innerHTML = el.innerHTML;
var newIndex = 0;
for (var i = 0; i < el.parentElement.children.length; i++) {
var tempEl = el.parentElement.children[i];
tempEl.removeClass("option-selected");
if (tempEl.get("value") == _value && tempEl.innerHTML == el.innerHTML) {
newIndex = i;
}
}
el.addClass("option-selected");
//设置下拉框 selectedIndex 并触发onchange事件
if (originIndex != newIndex) {
select.selectedIndex = newIndex;
eval(select.get("onchange"));
}
3、其他问题
实际项目中,个别页面个别select的选中状态是通过js设置selectedIndex指定的,渲染代码不能通过option的selected参数获取选中状态,就不能正确的渲染选中状态,此时需要在下拉框完成渲染后,调用一个根据selectedIndex渲染选中状态的方法:
HTMLElement.prototype.renderSelected = function () {
var ele = this;
if (this.nodeName == "SELECT") {
var index = ele.selectedIndex;
var divOptions = ele.parentElement.children[1];
if (!!divOptions && divOptions.nodeName == "DIV" && divOptions.hasClass("div-options") && index >= 0) {
divOptions.children[0].innerHTML = divOptions.children[1].children[index].innerHTML;
divOptions.children[1].children[index].addClass("option-selected");
}
}
};
还有的页面,下拉框的选项列表是通过异步方法动态获取的,在页面onload方法中执行渲染时,选项列表还是空的,渲染完成后可能选项列表才获取到,这种情况就只能手动的在异步方法完成后调用渲染方法。
代码下载:https://download.csdn.net/download/evanyanglibo/87490754
原文地址:https://blog.csdn.net/evanyanglibo/article/details/129194656
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_16439.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!