基于jQuery打造智能的人员选择输入框
UPDATE:修正了在FireFox下显示的问题,重新copy CSS即可
写完这个名字忽然觉得有点标题党的嫌疑,但是又不知道什么样的名字比较合适,那就暂且这样吧。
今天要讲的东西比较简单,其中会用到另外的一个jQuery控件,是一个人员选择输入框。那到底是个什么东西呢?
那好还是先来看最后的效果,有个直接的了解。
是不是和时下流行的SNS网站的选择人员控件很像?对比一下,哈哈是的,其实目的是差不多的。
其实还有很多这样应用,如邮件系统中发件人,在输入时的自动补全,它是一个类似于Autocomplete的功能,但是又要比Autocomplete多那么一些功能的插件
基于这个情况,我所编写的这个控件时基于一个Autocomplete控件的,它就是jQuery.autocomplete,它的官方网址是:http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/
大家可以通过访问以下来获取它的使用方法,资料和demo还是比较详细,我这边就不重复写了。所以我们还是直接开始扩展的部分
第一我们还是先确定HTML
从html上分析autocomplete和选人控件的所查的就是
容器我们用Div就可以了,小方块也比较简单 ,来看一下,最外层是div包裹,然后是嵌套一个a标签(为了方便以后做hover效果),在a标签中是一个span放置文字,
input[type=hidden]来防止这个节点的数据,img就似乎删除按钮的载体,那控件的载体又是什么呢?其实从设计来说可以是个input的,但是我更偏向于div,在实例化的时候往div中动态添加一个input来附加autocomplete的属性,如果反过来在input外包裹容器的话,在一些特殊情况下定位会是问题。
那html既然已经定义好了,接着就是CSS了,这个css其实很简单,就是容器的边框还有就是item的样子而已,来看下代码
1 2 3 4 5 6 7 8 9 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 | .bbit-usbox { border : solid 1px #3C7FB1 ; margin : 20px ; padding : 2px ; display : block ; background-color : #f3fefe ; } .bbit-usbox .bbit-usbox-item { width : auto ; margin-left : 4px ; margin-top : 2px ; background-color : #e0e5ee ; border : solid 1px #ccd5e4 ; float : left ; white-space : nowrap ; } .bbit-usbox .bbit-usbox-item a { color : #000 ; text-decoration : none ; padding-left : 2px ; } .bbit-usbox .bbit-usbox-item a span { } .bbit-usbox .bbit-usbox-del { background : url ( "images/usbox/del.gif" ) no-repeat 50% 80% ; width : 10px ; height : 5px ; cursor : pointer ; border : none ; vertical-align : middle ; margin-left : 2px ; } .bbit-usbox-boxc { margin-left : 4px ; clear : left ; } .bbit-usbox-box { } .bbit-usbox-boxc input { background-color : #f3fefe ; width : 100% ; height : 17px ; display : block ; border : none ; } |

第二 开始编写Javascript
还是老规矩,先来个完整代码,非常简单只有不到70行代码
1 2 3 4 5 6 7 8 9 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 55 56 57 58 59 60 61 62 63 64 65 66 67 | ; ( function ($) { if (!$.Autocompleter) { alert( "请先引用jquery.autocomplete.js" ); return ; } $.fn.usbox = function (o) { var def = { urlOrData: "ResponseAutoComplete.ashx" , width: "90%" , //宽度 addItem: false , removeItem: false , clickItem: function () { }, completeOp: {} }; $.extend(def, o); var co = $.extend({ scroll: false , formatItem: function (row, i, max) { return row[0] + "[" + row[1] + "]" ; } }, def.completeOp); var temp = "<div class='bbit-usbox-item'><a href='javascript:void(0);'><span>${text}</span><input type='hidden' value='${value}'/><img src='../Themes/Shared/images/s.gif' alt='点击删除' class='bbit-usbox-del'/></a></div>" ; return this .each( function (e) { var me = $( this ); var id = me.attr( "id" ); if (id == null || id == "" ) { id = "usbox_" + new Date().getTime(); } var inc = $( "<div class='bbit-usbox-boxc'/>" ); var input = $( "<input type='text' id='" + id + "_inbox' class='bbit-usbox-box' />" ).appendTo(inc); me.addClass( "bbit-usbox" ).width(def.width).append(inc); input.autocomplete(def.urlOrData, co).result( function (event, data, formatted) { $( this ).val( "" ); additem( this , data); }); me.bind( "addboxitem" , function (e,data) { additem(input,data); }); function additem(inc, data) { var tp = $(temp.replace(/\$\{([\w]+)\}/g, function (s1, s2) { if (s2 == "text" ) { return data[0]; } else if (s2 == "value" ) { return data.join( "|" ); } else { return s1; } })); tp.click(def.clickItem).find( "img.bbit-usbox-del" ).click(removeitem); $(inc).parent().before(tp); if (def.addItem) { def.addItem(data); } } function removeitem() { var p = $( this ).prev() var v = p.val(); var arr = v.split( "|" ); if (def.removeItem) { def.removeItem(arr); } $( this ).parent().parent().remove(); } return me; }); }; $.fn.addboxitem = function (op) { $( this ).trigger( "addboxitem" , [op]); }; })(jQuery) |
接着我们来一步一步来分析我的实现,开始还是编写jQuery控件的“模板”,关于为什么要这么写,请参考这篇的说明
1 2 3 4 5 6 7 8 | ; ( function ($) { if (!$.Autocompleter) { alert( "请先引用jquery.autocomplete.js" ); return ; } $.fn.usbox = function (o) { } })(jQuery) |
1 2 3 4 5 6 7 8 | var def = { urlOrData: false , //必须!请求数据的url和或者直接是数据,格式参考autocomplete的说明 width: "90%" , //宽度 addItem: false , //当从下拉选项中选择一个人员后触发的函数 removeItem: false , //当从已选择的人员删除一个人时触发的函数 clickItem: function () { }, //点击人员小方块时触发的时间 completeOp: {} //autocomplete的参数,格式参考它自身的说明 }; |
参数也是比较简单,添加和移除的两个函数比较重要,在demo中会讲到,autocomplete的参数因为太多,大家只有自己参考一下官方的说明, 默认不管也可以,因为我会给大家默认来一下.
1 2 3 4 5 | $.extend(def, o); //这才是默认的Complete的参数 var co = $.extend({ scroll: false , formatItem: function (row, i, max) { return row[0] + "[" + row[1] + "]" ; } }, def.completeOp); //定义小方块的模板,其中s.gif是个空图片,位置可根据实际情况进行调整 var temp = "${text}" ; |
formatItem函数是下拉中显示的格式 ,接着是生成HTML,注册事件,详细的步骤我已经注释到代码中了如下所示
1 2 3 4 5 6 7 8 9 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 | return this .each( function (e) { var me = $( this ); var id = me.attr( "id" ); //获取唯一的ID if (id == null || id == "" ) { id = "usbox_" + new Date().getTime(); } //input的容器 var inc = $( "<div class='bbit-usbox-boxc'/>" ); //生成一个input用于附加autocomplete控件 var input = $( "<input type='text' id='" + id + "_inbox' class='bbit-usbox-box' />" ).appendTo(inc); //设置样式,并把input添加到对象中 me.addClass( "bbit-usbox" ).width(def.width).append(inc); //给input注册autocomplete功能,并设置回调函数 input.autocomplete(def.urlOrData, co).result( function (event, data, formatted) { $( this ).val( "" ); //选择人员了则把输入框自己清空 additem( this , data); //生成小方块 }); //注册一个自定义的事件,事件名addboxitem me.bind( "addboxitem" , function (e,data) { additem(input,data); }); function additem(inc, data) { //小方块的模板替换成正确的值 var tp = $(temp.replace(/\$\{([\w]+)\}/g, function (s1, s2) { if (s2 == "text" ) { return data[0]; //返回的第一个值是displayname } else if (s2 == "value" ) { return data.join( "|" ); //其他全部放到input[type=hidden]中 } else { return s1; } })); //触发小放开的click事件,并且在内部查找删除按钮,注册点击事件,jQuery的链式哦 tp.click(def.clickItem).find( "img.bbit-usbox-del" ).click(removeitem); //把小方块放到input之前! $(inc).parent().before(tp); if (def.addItem) { //如果additem存在则触发 def.addItem(data); } } //移除的方法 function removeitem() { var p = $( this ).prev() //获取input[type=hidden],this指向delete img var v = p.val(); var arr = v.split( "|" ); //拼成一个数组 if (def.removeItem) { //触发移除函数 def.removeItem(arr); } //小方块移除本身 $( this ).parent().parent().remove(); // } return me; }); |
最后是公开一个函数来方便外面调用additem,如我有一个弹出界面可以一次选择n个人回来,那么就可以调用这个函数了
1 2 3 | $.fn.addboxitem = function (op) { $( this ).trigger( "addboxitem" , [op]); //想到我在之前注册的自定义事件了吗? }; |
1 2 3 4 5 6 7 8 9 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 | $(document).ready( function () { $( "#usbox" ).usbox({ width: 430, urlOrData: "<%=Url.Action(" QueryComplete ")%>" , addItem: function (data) { var t = $( "#hdtext" ).val(); var v = $( "#hdvalue" ).val(); var t1 = t != "" ? t.split( "," ) : []; var v1 = v != "" ? v.split( "," ) : []; t1.push(data[0]); v1.push(data[2]); $( "#hdtext" ).val(t1.join( "," )); $( "#hdvalue" ).val(v1.join( "," )); }, removeItem: function (data) { var t = $( "#hdtext" ).val(); var v = $( "#hdvalue" ).val(); var t1 = t.split( "," ); var v1 = v.split( "," ); var index = -1; for ( var i = v1.length - 1; i >= 0; i--) { if (data[2] == v1[i]) { index = i; break ; } } if (index > -1) { t1.splice(index, 1); v1.splice(index, 1); $( "#hdtext" ).val(t1.join( "," )); $( "#hdvalue" ).val(v1.join( "," )); } } }); var tempdata = [ "假正经哥哥" , "xuanye" , "001" ]; $( "#usbox" ).addboxitem(tempdata); }); |
HTML代码
1 2 3 4 5 | < div id="usbox" class="bbit-usbox"> </ div > < input id="hdtext" type="text"/> < input id="hdvalue" type="text"/> 输入框在实际项目中可能是隐藏域,默认我加上了假正经哥哥 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public ContentResult QueryComplete( string q, int limit) { string ret = "" ; if (q != "" && limit >0) { //根据关键字搜索数据库或缓存,这个就比较简单不深入了 List<Person> list=_respository.QueryCompletePerson(q, limit); if (list != null ) { StringBuilder sb = new StringBuilder(); foreach (Person person in list) { //以|分割的数据格式,可以是多个,这里是三个。当然也可以吧ID作为特殊的 sb.AppendLine(person.FullName + "|" + person.PY+ "|" +person.ID); } ret = sb.ToString(); } } return Content(ret); } |
本示例的地址是:http://jscs.cloudapp.net/ControlsSample/usbox
另外抱怨一下:部署到window azure 真的是有点麻烦哟。。搞了几次
最后 你的支持就是我继续写作的动力!
本文地址:http://www.cnblogs.com/xuanye/archive/2009/10/28/1591733.html
转载请保留!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?