JavaScript封装一个实用的select控件
最近一直把精力放在项目上面,导致忽略的一些底层的东西。以前就一直觉得原有的select控件很丑,正好周末有时间,试着做了一个简单封装,实现了它的基本功能。我总结了一下,大概分为三个部分:
1、对显示样式的处理
2、对点击和hover事件的处理
3、change事件发送请求的处理
我们先看jsp的展示代码:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style>
.hide{display:none}
.mySelect{position:relative;}
.ms_div{height:33px;line-height:33px;width:220px;display:inline-block;border:1px solid #ddd;
border-right:0;cursor:pointer;border-radius:3px;}
ms_op{display:block;line-height:33px;margin-bottom:1px;}
.ms_div .ms_label:before,.ms_div ms_op:before{content:" "}
ms_op:hover{color:rgb(1%,60%,80%)}
.ms_btn{position:absolute;width:20px;height:100%;display:block;top:0px;right:0px;
text-align:center;color:#fff;z-index:3;line-height:35px;background: rgb(10%,65%,85%);}
.ms_op_div{position:absolute;top:34px;left:0;width:100%;z-index:4;}
.ms_op_con{max-height:400px;overflow-y:auto;border-bottom:1px solid #ddd;background:#fff;
border-right:1px solid #eee;padding-bottom:5px;font-weight:nomal;color:#666;border-left:1px solid #ddd;}
.showDiv{padding-top:30px}
</style>
<script type="text/javascript" src="<c:url value='/res/js/jquery.js'/>"></script>
<script>
$.fn.extend({
changeClass:function(flag,removeFlag,class1,class2) {
if(removeFlag) return this.removeClass(class1).removeClass(class2);
return this.addClass(flag?class1:class2).removeClass(flag?class2:class1);
},
addOrRemoveClass:function(flag,className){
if(flag) return this.addClass(className);
return this.removeClass(className);
},
switchClass:function(className){
if(this.hasClass(className)) return this.removeClass(className);
return this.addClass(className);
},
switchClass2:function(class1,class2){
if(this.hasClass(class1)) return this.removeClass(class1).addClass(class2);
return this.removeClass(class2).addClass(class1);
},
replaceClass:function(class1,class2){
return this.removeClass(class2).addClass(class1);
}
});
</script>
<script type="text/javascript" src="<c:url value='/res/js/MySelect.js'/>"></script>
</head>
<div class="selectDiv"></div>
<div class="showDiv"></div>
<script>
$(function(){
var $showDiv = $(".showDiv");
var orgTypeMap={"j":"集团","b":"银行","a":"合作方","m":"商户","":"--请选择机构类型--"};
var changeHandler = function(id,value){
//回调函数,这里可以拿到当前选中的option的id和value
var url = "";
var param = {};
param.id = id;
$.post("<c:url value='/sys/selectQueryData'/>",param,function(data){
//把后台发送的数据显示到页面
if(!data.success=="success") alert("请求数据出错");
$showDiv.html(data.msg);
},"json")
}
//new一个MySelect对象,执行createByData和change方法,这两个方法是必须在这里执行的
new MySelect($(".selectDiv"),"id","").createByData(orgTypeMap).change(changeHandler); })
</script>
<body> </body>
</html>
引入MySelect.js文件,不要忘了在之前先要引入jquery.js,因为这个使用了jquery的方法。上面我对$做了几个方法的扩展,其中用到了switchClass方法,这样要比单独写一个文件方便的多。
MySelect.js的代码如下:
function MySelect($selectDiv,fildName,defaultValue){
this.defaultValue = defaultValue;
this.$selectDiv = $selectDiv.addClass("mySelect");
this.$selectBtn = $("<span class='ms_btn'>▼</span>");
this.$optionsDiv=$("<div class='ms_op_div hide'></div>");
this.$optionConDiv=$("<div class='ms_op_con'></div>").appendTo(this.$optionsDiv);
this.$selectLabel=$("<span class='ms_label'></span>");
this.$hiddenInput=$("<input type='hidden' name='"+fildName+"' value='"+this.defaultValue+"'></input>");
this.changeHandler=$.noop;
this.init();
}
//将回调函数changeHandler赋值给MySelect的函数
MySelect.prototype.change = function(changeHandler){
this.changeHandler = changeHandler;
return this;
}
//初始化select,我在里面定义了一个hover事件
MySelect.prototype.init = function(){
if(!this.$selectDiv||this.$selectDiv.length==0){
alert("初始化容器失败!");
return;
}
this.$selectDiv.addClass("ms_div").append(this.$selectLabel).append(this.$hiddenInput);
var ch=null;
var self = this;
this.$optionsDiv.hover(function(e){
e.stopPropagation();
if(ch!=null) clearTimeout(ch);
},function(e){
e.stopPropagation();
var t=this;
ch=setTimeout(function(){
$(t).addClass("hide");
},500);
});
return this;
}
//根据用户提供的map对象创建select的option数据
MySelect.prototype.createByData=function(data){
var cn="";
for(var key in data){
var value=data[key];
this.addOption(key,value,cn);
}
this.fill();
return this;
}
//设置默认显示的option,把数据填充到已经创建好的$optionConDiv里面
MySelect.prototype.addOption=function(key,value,cn){
if(key==this.defaultValue){
cn="ms_op_cur";
this.$selectLabel.html(value);
}
$("<ms_op value='"+key+"'>"+value+"</ms_op>").addClass(cn).appendTo(this.$optionConDiv);
}
//设置选中的option
MySelect.prototype.setCurValue = function(key,value){
this.$selectLabel.html(value);
this.$hiddenInput.val(key);
}
//定义select的点击事件,如果nodeName是option,就执行setCurValue和回调函数
MySelect.prototype.click=function(e){
var t=e.target;
var n=t.nodeName;
this.$optionsDiv.switchClass("hide");
if (n == 'MS_OP') {
if($(t).hasClass("ms_op_cur")) return;
$(t).addClass("ms_op_cur").siblings(".ms_op_cur").removeClass("ms_op_cur");
this.setCurValue(t.getAttribute("value"), t.textContent);
this.changeHandler(t.getAttribute("value"),t.textContent);
}
}
//fill函数是在select对象调用createByData时候执行的,这里使用了事件代理完成了对$selectDiv的click事件操作
MySelect.prototype.fill=function(){
this.$selectDiv.append(this.$selectBtn).append(this.$optionsDiv);
this.$selectDiv.click($.proxy(this.click,this));
}
根据上面代码,页面初步的展示如图:
下一步,我们需要编写后台代码来响应change事件的请求:
package cn.wangze.servlet; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class MySelectServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
String id = request.getParameter("id");
if("j".equals(id)){
out.println("这里返回集团的数据....");
}
if("b".equals(id)){
out.println("这里返回银行的数据....");
}
if("a".equals(id)){
out.println("这里返回合作方的数据....");
}
if("m".equals(id)){
out.println("这里返回商户的数据....");
}
}
}
根据前台传的id不同,做出不同的回应。实际应用中肯定会复杂很多,我这里只是简单的演示一下。
代码部分就是上面展示的这些,我们看一下最后完成的效果:
因为"--请选择机构类型--"对应的id我们没有设置,后台也没有处理,所以response没有返回值,其他设置过的返回数据都是正常了。
我觉得封装这些小控件非常考验js的基础掌握能力,对个人的技术水平有一定程度的锻炼,我们现在做项目都是找到好用的插件随手拿来就用,但是里面底层的只是估计很难讲清楚。很多人都是知道怎么用。但是不知道为什么这么用,自己封装就不同了,第一可以更灵活的使用它,第二哪里出了问题不会一脸懵,第三可根据业务作出扩展或者修改。
当然,这些都是在时间富裕的前提下说的,如果每天工作的事情都做不完,哪里还有时间自己造轮子,所以业余时间的的分配很能够考验一个人的职业水平。
说的再多,不如自己动手操作,毕竟实践出真知嘛。
JavaScript封装一个实用的select控件的更多相关文章
- 自己动手用Javascript写一个无刷新分页控件
.NET技术交流群:337901356 ,欢迎您的加入! 对 于一个用户体验好的网站来说,无刷新技术是很重要的,无刷新,顾名思义,就是局部刷新数据,有用过Asp.net Web Form技术开发网页的 ...
- Selenium webdriver 之select 控件封装,解决onchange问题
使用webdriver的时候,select 控件经常会绑定onchange 事件,在selenium2.09 之前click 方法对onchange 事件有bug,2.09 以后修复了,但是根据经验也 ...
- Jquery 操作Html 控件 CheckBox、Radio、Select 控件 【转】http://www.cnblogs.com/lxblog/archive/2013/01/09/2853056.html
Jquery 操作Html 控件 CheckBox.Radio.Select 控件 在使用 Javascript 编写前台脚本的时候,经常会操作 Html 控件,比如 checkbox.radio ...
- Jquery 操作Html 控件 CheckBox、Radio、Select 控件
在使用 Javascript 编写前台脚本的时候,经常会操作 Html 控件,比如 checkbox.radio.select,用 Jquery 库操作其他会方便很多,下面用Jq对这些控件的操作进行一 ...
- 模拟select控件,css模拟下拉
<!DOCTYPE html > <head> <meta http-equiv="Content-Type" content="t ...
- SELECT控件操作的JS代码示例
SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...
- HTML的select控件美化
HTML的select控件美化 CSS: .div-select { border: solid 1px #999; height: 40px; line-height: 40px; cursor: ...
- IE6下div层被select控件遮住的问题解决方法
Select在IE6下是处于最顶层的,因此想要遮住它,设置zIndex属性是不行的,就需要一个优先级更高的元素,就是iframe,当把iframe嵌套在弹出div层中后,把iframe设置为不可见,但 ...
- js+CSS实现模拟华丽的select控件下拉菜单效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
随机推荐
- 浅谈Nginx负载均衡原理与实现
1.Nginx能做什么? Nginx可以两件事: -- HTTP请求 经过官方测试Nginx可以承受5万的并发量.可用来做静态资源的图片服务器 --负载均衡,如下解释什么是负载均衡. 2.负载均衡 ...
- Verilog HDL的程序结构及其描述
这篇博文是写给要入门Verilog HDL及其初学者的,也算是我对Verilog HDL学习的一个总结,主要是Verilog HDL的程序结构及其描述,如果有错,欢迎评论指出. 一.Verilog ...
- Java 程序员技能导图 1.0
做Java开发已经一年,并非科班出身,在毕业工作三年后毅然决然辞职,参加培训机构从零开始.在这期间迷茫.失望.绝望时常伴我左右,但是在不断自我提高与努力中渐渐看到一些小小的成果使我不断坚信自己的选择并 ...
- github 或者gitlab 设置添加SSH
克隆项目二种方式: 1. 使用https url克隆, 复制https url 然后到 git clone https-url 2.使用 SSH url 克隆却需要在克隆之前先配置和添加好 SSH ...
- 定时任务FluentScheduler 学习笔记 .net
第一步添加引用 GitHub源码地址 与详细用法 https://github.com/fluentscheduler/FluentScheduler 下面开始简单的实现 /// <summar ...
- WordPress中函数钩子hook的作用及基本用法
WordPress 的插件机制实际上只的就是这个 Hook 了,它中文被翻译成钩子,允许你参与 WordPress 核心的运行,是一个非常棒的东西,下面我们来详细了解一下它.钩子分类 钩子分为两种,一 ...
- python-桶排序
桶排序 通排序非常浪费空间, 比如需要排序的范围在0~2000之间, 需要排序的数是[3,9,4,2000], 同样需要2001个空间 注意: 通排序不能排序小数 以下为从小到大代码实现 #!/usr ...
- Jersey实现Restful服务
jersey 是基于Java的一个轻量级RESTful风格的Web Services框架.以下我基于IDEA实现Restful完整Demo. 1.创建maven-web工程,后面就是正常的maven工 ...
- 一篇关于Python装饰器的博文
这是一篇关于python装饰器的博文 在学习python的过程中处处受阻,之前的学习中Python的装饰器学习了好几遍也没能真正的弄懂.这一次抓住视频猛啃了一波,就连python大佬讲解装饰器起来也需 ...
- iOS设置状态栏样式
iOS设置状态栏样式可以使用两种方式. 方式一: 直接在需要改变默认状态栏样式的控制器中实现一个方法(其他任何事情都不用做): // 返回状态栏的样式 - (UIStatusBarStyle)pref ...