原创|其它|编辑:郝浩|2009-10-29 10:09:55.000|阅读 995 次
概述:写完这个名字忽然觉得有点标题党的嫌疑,但是又不知道什么样的名字比较合适,那就暂且这样吧。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
写完这个名字忽然觉得有点标题党的嫌疑,但是又不知道什么样的名字比较合适,那就暂且这样吧。
今天要讲的东西比较简单,其中会用到另外的一个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的样子而已,来看下代码
01.
.bbit-usbox
02.
{
03.
border: solid 1px #3C7FB1;
04.
margin:20px;
05.
padding:2px;
06.
display:block;
07.
background-color:#f3fefe;
08.
}
09.
.bbit-usbox .bbit-usbox-item
10.
{
11.
width:auto;
12.
margin-left:4px;
13.
margin-top:2px;
14.
background-color:#e0e5ee;
15.
border: solid 1px #ccd5e4;
16.
float:left;
17.
white-space : nowrap;
18.
}
19.
.bbit-usbox .bbit-usbox-item a
20.
{
21.
color:#000;
22.
text-decoration:none;
23.
padding-left:2px;
24.
}
25.
.bbit-usbox .bbit-usbox-item a span
26.
{
27.
}
28.
.bbit-usbox .bbit-usbox-del
29.
{
30.
background:url("images/usbox/del.gif") no-repeat 50% 80%;
31.
width:10px;
32.
height:5px;
33.
cursor:pointer;
34.
border:none;
35.
vertical-align:middle;
36.
margin-left:2px;
37.
}
38.
.bbit-usbox-boxc
39.
{
40.
margin-left:4px;
41.
}
42.
.bbit-usbox-box
43.
{
44.
}
45.
.bbit-usbox input
46.
{
47.
background-color:#f3fefe;
48.
width:100%;
49.
height:17px;
50.
display:block;
51.
border:none;
52.
}
第二 开始编写Javascript
还是老规矩,先来个完整代码,非常简单只有不到70行代码
01.
; (
function
($) {
02.
if
(!$.Autocompleter) {
03.
alert(
"请先引用jquery.autocomplete.js"
);
04.
return
;
05.
}
06.
$.fn.usbox =
function
(o) {
07.
var
def = {
08.
urlOrData:
"ResponseAutoComplete.ashx"
,
09.
width:
"90%"
,
//宽度
10.
addItem:
false
,
11.
removeItem:
false
,
12.
clickItem:
function
() { },
13.
completeOp: {}
14.
};
15.
$.extend(def, o);
16.
var
co = $.extend({ scroll:
false
, formatItem:
function
(row, i, max) {
return
row[0] +
"["
+ row[1] +
"]"
; } }, def.completeOp);
17.
18.
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>"
;
19.
20.
return
this
.each(
function
(e) {
21.
var
me = $(
this
);
22.
var
id = me.attr(
"id"
);
23.
if
(id ==
null
|| id ==
""
) {
24.
id =
"usbox_"
+
new
Date().getTime();
25.
}
26.
var
inc = $(
"<div class='bbit-usbox-boxc'/>"
);
27.
var
input = $(
"<input type='text' id='"
+ id +
"_inbox' class='bbit-usbox-box' />"
).appendTo(inc);
28.
me.addClass(
"bbit-usbox"
).width(def.width).append(inc);
29.
input.autocomplete(def.urlOrData, co).result(
function
(event, data, formatted) {
30.
$(
this
).val(
""
);
31.
additem(
this
, data);
32.
});
33.
me.bind(
"addboxitem"
,
function
(e,data) { additem(input,data); });
34.
function
additem(inc, data) {
35.
var
tp = $(temp.replace(/\$\{([\w]+)\}/g,
function
(s1, s2) {
36.
if
(s2 ==
"text"
) {
37.
return
data[0];
38.
}
39.
else
if
(s2 ==
"value"
) {
40.
return
data.join(
"|"
);
41.
}
42.
else
{
43.
return
s1;
44.
}
45.
}));
46.
tp.click(def.clickItem).find(
"img.bbit-usbox-del"
).click(removeitem);
47.
$(inc).parent().before(tp);
48.
if
(def.addItem) {
49.
def.addItem(data);
50.
}
51.
}
52.
function
removeitem() {
53.
var
p = $(
this
).prev()
54.
var
v = p.val();
55.
var
arr = v.split(
"|"
);
56.
if
(def.removeItem) {
57.
def.removeItem(arr);
58.
}
59.
$(
this
).parent().parent().remove();
60.
}
61.
return
me;
62.
});
63.
};
64.
$.fn.addboxitem =
function
(op) {
65.
$(
this
).trigger(
"addboxitem"
, [op]);
66.
};
67.
})(jQuery)
接着我们来一步一步来分析我的实现,开始还是编写jQuery控件的“模板”,关于为什么要这么写,请参考这篇的说明
1.
; (
function
($) {
2.
if
(!$.Autocompleter) {
3.
alert(
"请先引用jquery.autocomplete.js"
);
4.
return
;
5.
}
6.
$.fn.usbox =
function
(o) {
7.
}
8.
})(jQuery)
这次加了一个判断,因为我们这个控件是依赖于autocomplete的,如果你看了前两篇,那么就一定知道接着就是编写默认参数
1.
var
def = {
2.
urlOrData:
false
,
//必须!请求数据的url和或者直接是数据,格式参考autocomplete的说明
3.
width:
"90%"
,
//宽度
4.
addItem:
false
,
//当从下拉选项中选择一个人员后触发的函数
5.
removeItem:
false
,
//当从已选择的人员删除一个人时触发的函数
6.
clickItem:
function
() { },
//点击人员小方块时触发的时间
7.
completeOp: {}
//autocomplete的参数,格式参考它自身的说明
8.
};
参数也是比较简单,添加和移除的两个函数比较重要,在demo中会讲到,autocomplete的参数因为太多,大家只有自己参考一下官方的说明, 默认不管也可以,因为我会给大家默认来一下.
1.
2.
$.extend(def, o);
3.
//这才是默认的Complete的参数
4.
var
co = $.extend({ scroll:
false
, formatItem:
function
(row, i, max) {
return
row[0] +
"["
+ row[1] +
"]"
; } }, def.completeOp);
5.
//定义小方块的模板,其中s.gif是个空图片,位置可根据实际情况进行调整
6.
var
temp =
"<DIV class=bbit-usbox-item><A href="
javascript:void(0);
"><SPAN>${text}</SPAN><INPUT value=${value} type=hidden><IMG class=bbit-usbox-del alt=点击删除 src="
../Themes/Shared/images/s.gif
"></A></DIV>"
;
formatItem函数是下拉中显示的格式 ,接着是生成HTML,注册事件,详细的步骤我已经注释到代码中了如下所示
01.
02.
return
this
.each(
function
(e) {
03.
var
me = $(
this
);
04.
var
id = me.attr(
"id"
);
05.
//获取唯一的ID
06.
if
(id ==
null
|| id ==
""
) {
07.
id =
"usbox_"
+
new
Date().getTime();
08.
}
09.
//input的容器
10.
var
inc = $(
"<div class='bbit-usbox-boxc'/>"
);
11.
//生成一个input用于附加autocomplete控件
12.
var
input = $(
"<input type='text' id='"
+ id +
"_inbox' class='bbit-usbox-box' />"
).appendTo(inc);
13.
//设置样式,并把input添加到对象中
14.
me.addClass(
"bbit-usbox"
).width(def.width).append(inc);
15.
//给input注册autocomplete功能,并设置回调函数
16.
input.autocomplete(def.urlOrData, co).result(
function
(event, data, formatted) {
17.
$(
this
).val(
""
);
//选择人员了则把输入框自己清空
18.
additem(
this
, data);
//生成小方块
19.
});
20.
//注册一个自定义的事件,事件名addboxitem
21.
me.bind(
"addboxitem"
,
function
(e,data) { additem(input,data); });
22.
function
additem(inc, data) {
23.
//小方块的模板替换成正确的值
24.
var
tp = $(temp.replace(/\$\{([\w]+)\}/g,
function
(s1, s2) {
25.
if
(s2 ==
"text"
) {
26.
return
data[0];
//返回的第一个值是displayname
27.
}
28.
else
if
(s2 ==
"value"
) {
29.
return
data.join(
"|"
);
//其他全部放到input[type=hidden]中
30.
}
31.
else
{
32.
return
s1;
33.
}
34.
}));
35.
//触发小放开的click事件,并且在内部查找删除按钮,注册点击事件,jQuery的链式哦
36.
tp.click(def.clickItem).find(
"img.bbit-usbox-del"
).click(removeitem);
37.
//把小方块放到input之前!
38.
$(inc).parent().before(tp);
39.
if
(def.addItem) {
//如果additem存在则触发
40.
def.addItem(data);
41.
}
42.
}
43.
//移除的方法
44.
function
removeitem() {
45.
var
p = $(
this
).prev()
//获取input[type=hidden],this指向delete img
46.
var
v = p.val();
47.
var
arr = v.split(
"|"
);
//拼成一个数组
48.
if
(def.removeItem) {
//触发移除函数
49.
def.removeItem(arr);
50.
}
51.
//小方块移除本身
52.
$(
this
).parent().parent().remove();
//
53.
}
54.
return
me;
55.
});
最后是公开一个函数来方便外面调用additem,如我有一个弹出界面可以一次选择n个人回来,那么就可以调用这个函数了
1.
2.
$.fn.addboxitem =
function
(op) {
3.
$(
this
).trigger(
"addboxitem"
, [op]);
//想到我在之前注册的自定义事件了吗?
4.
};
至此我们的控件其实已经分析完成了,但是为了让大家更好的理解这个控件,我把对应的服务器端代码也顺便写写因为Demo是Asp.NET MVC的,那么就以asp.net mvc 为例来讲吧 先来看看Demo的调用代码,urlOrData是个Action,additem和removeitem分别处理将选中的人员添加到指定的隐藏域或从中删除,以便表单提交。
01.
02.
$(document).ready(
function
() {
03.
$(
"#usbox"
).usbox({
04.
width: 430,
05.
urlOrData:
"<%=Url.Action("
QueryComplete
")%>"
,
06.
addItem:
function
(data) {
07.
var
t = $(
"#hdtext"
).val();
08.
var
v = $(
"#hdvalue"
).val();
09.
var
t1 = t !=
""
? t.split(
","
) : [];
10.
var
v1 = v !=
""
? v.split(
","
) : [];
11.
t1.push(data[0]);
12.
v1.push(data[2]);
13.
$(
"#hdtext"
).val(t1.join(
","
));
14.
$(
"#hdvalue"
).val(v1.join(
","
));
15.
},
16.
removeItem:
function
(data) {
17.
var
t = $(
"#hdtext"
).val();
18.
var
v = $(
"#hdvalue"
).val();
19.
var
t1 = t.split(
","
);
20.
var
v1 = v.split(
","
);
21.
var
index = -1;
22.
for
(
var
i = v1.length - 1; i >= 0; i--) {
23.
if
(data[2] == v1[i]) {
24.
index = i;
25.
break
;
26.
}
27.
}
28.
if
(index > -1) {
29.
t1.splice(index, 1);
30.
v1.splice(index, 1);
31.
$(
"#hdtext"
).val(t1.join(
","
));
32.
$(
"#hdvalue"
).val(v1.join(
","
));
33.
}
34.
35.
}
36.
});
37.
var
tempdata = [
"假正经哥哥"
,
"xuanye"
,
"001"
];
38.
$(
"#usbox"
).addboxitem(tempdata);
39.
});
HTML代码
1.
<
div
id
=
"usbox"
class
=
"bbit-usbox"
>
2.
</
div
>
3.
<
input
id
=
"hdtext"
type
=
"text"
/>
4.
<
input
id
=
"hdvalue"
type
=
"text"
/>
5.
输入框在实际项目中可能是隐藏域,默认我加上了假正经哥哥
再来看看Action的代码,默认接受两个参数,一个是q,即input中的输入框,一个是限制条数(默认是10,可通过修改complete的参数来改变)
01.
02.
public
ContentResult QueryComplete(
string
q,
int
limit)
03.
{
04.
string
ret =
""
;
05.
if
(q !=
""
&& limit >0)
06.
{
07.
//根据关键字搜索数据库或缓存,这个就比较简单不深入了
08.
List<Person> list=_respository.QueryCompletePerson(q, limit);
09.
if
(list !=
null
)
10.
{
11.
StringBuilder sb =
new
StringBuilder();
12.
foreach
(Person person
in
list)
13.
{
14.
//以|分割的数据格式,可以是多个,这里是三个。当然也可以吧ID作为特殊的
15.
sb.AppendLine(person.FullName +
"|"
+ person.PY+
"|"
+person.ID);
16.
}
17.
ret = sb.ToString();
18.
}
19.
}
20.
return
Content(ret);
21.
}
本示例的地址是:http://jscs.cloudapp.net/ControlsSample/usbox
另外抱怨一下:部署到window azure 真的是有点麻烦哟。。搞了几次
最后 你的支持就是我继续写作的动力!
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:博客园