本文转自:http://www.soulteary.com/2013/05/10/jquery-city-select.html
完成地址:http://thecdn.sinaapp.com/page/demo/jq-select/
GITHUB地址:https://github.com/soulteary/jquery-city-select
首先建立基础HTML结构:
1
|
html
:
5
>
div
#warp>((select#province>option[value="载入中"])+(select#city>option[value="载入中"]))
|
预览地址:http://thecdn.sinaapp.com/page/demo/jq-select/step-1.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!doctype html>
<html
lang
=
"en"
>
<head>
<meta
charset
=
"UTF-8"
>
<title>
省市下拉联动插件 @soulteary
</title>
</head>
<body>
<div
id
=
"warp"
>
<select
id
=
"province"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
<select
id
=
"city"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
</div>
</body>
</html>
|
添加简单的样式。
地址:http://thecdn.sinaapp.com/page/demo/jq-select/step-2.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
|
<!doctype html>
<html
lang
=
"en"
>
<head>
<meta
charset
=
"UTF-8"
>
<title>
省市下拉联动插件 @soulteary
</title>
<style>
#warp
{
width
:
230px
;
height
:
80px
;
position
:
absolute
;
top
:
50%
;
left
:
50%
;
margin-left
:
-200px
;
margin-top
:
-130px
;
box-shadow
:
1px
1px
#3A393A
;
border
:
1px
solid
#222
;
font-size
:
13px
;
line-height
:
13px
;
}
#province
{
margin
:
30px
0
0
30px
;
float
:
left
;
}
#city
{
float
:
right
;
margin
:
30px
30px
0
0
;
}
</style>
</head>
<body>
<div
id
=
"warp"
>
<select
id
=
"province"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
<select
id
=
"city"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
</div>
</body>
</html>
|
接着来写JS实现。
首先我们要进行数据定义,就是这个省市联动的数据是如何的关系。
有许多的省份,那么省份是包含在一个数组中的,然后每个省份中的城市包含在这些省份中,所以获得包含关系。
定义结构如下:(为了简单的开发,我随意写的数据,真实上线用自己定义的数据来替换即可)
1
2
3
4
5
6
7
8
9
10
11
12
|
[
{
'name'
:
'北京市'
,
id
:
100000
,
children
:
[
{
'name'
:
'海淀区'
,
id
:
100003
}
,
{
'name'
:
'西城区'
,
id
:
100002
}
,
{
'name'
:
'东城区'
,
id
:
100001
}
]
}
,
{
'name'
:
'天津市'
,
id
:
300000
,
children
:
[
{
'name'
:
'北辰区'
,
id
:
300003
}
,
{
'name'
:
'红桥区'
,
id
:
300002
}
,
{
'name'
:
'河西区'
,
id
:
300001
}
]
}
]
;
|
简单的思考后,插件接受的参数为不定长,1~2个,为什么这么说呢。
场景A:数据要输出到一个下拉框中,即省份和城市输出一起。
场景B:数据分别初始化到两个下拉列表中。
那么设计插件框架如下:
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
|
;
(
function
(
$
)
{
$
.
fn
.
extend
(
{
"citylist"
:
function
(
params
)
{
params
=
$
.
extend
(
{
param
:
'this is a param'
}
,
params
)
;
var
target
=
$
(
this
)
;
if
(
!
target
.
length
)
{
return
this
;
}
else
if
(
target
.
length
==
1
)
{
}
else
{
}
console
.
log
(
'PLUGN LOADED!:'
,
target
,
params
)
;
return
this
;
}
}
)
;
}
)
(
jQuery
,
'SOULTEARY.COM'
)
;
//USEAGE:
$
(
'#province'
)
.
citylist
(
)
;
$
(
'#province , #city'
)
.
citylist
(
)
;
|
接着来写实现代码:
地址:http://thecdn.sinaapp.com/page/demo/jq-select/step-3.html
首先是将省市数据初始化到两个不同的列表中的功能的实现,即:$('#province , #city').citylist();
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
<script
type
=
"text/javascript"
>
//插件基础代码
;
(
function
(
$
)
{
$
.
fn
.
extend
(
{
"citylist"
:
function
(
params
)
{
params
=
$
.
extend
(
{
param
:
'this is a param'
}
,
params
)
;
var
target
=
$
(
this
)
;
if
(
!
target
.
length
)
{
return
this
;
}
else
if
(
target
.
length
==
1
)
{
}
else
{
var
province
=
target
.
eq
(
0
)
;
var
city
=
target
.
eq
(
1
)
;
var
html
=
[
]
,
oItem
;
for
(
var
item
in
params
.
data
)
{
oItem
=
params
.
data
[
item
]
;
console
.
log
(
oItem
)
html
.
push
(
'<option data-extra="'
+
oItem
[
'id'
]
+
'">'
+
oItem
[
'name'
]
+
'</option>'
)
;
}
html
=
html
.
join
(
''
)
;
province
.
find
(
'option'
)
.
remove
(
)
;
province
.
append
(
html
)
;
var
provinces
=
province
.
find
(
'option'
)
;
province
.
on
(
'change'
,
function
(
)
{
var
curSelect
=
$
(
this
)
.
val
(
)
;
provinces
.
each
(
function
(
k
,
v
)
{
if
(
$
(
v
)
.
val
(
)
==
curSelect
)
{
return
(
function
(
v
)
{
var
extra
=
$
(
v
)
.
attr
(
'data-extra'
)
;
var
html
=
[
]
,
oItem
;
for
(
var
item
in
params
.
data
)
{
oItem
=
params
.
data
[
item
]
;
if
(
oItem
[
'id'
]
==
extra
&&
oItem
.
children
)
{
oItem
=
oItem
.
children
;
for
(
var
sItem
in
oItem
)
{
html
.
push
(
'<option data-extra="'
+
oItem
[
sItem
]
[
'id'
]
+
'">'
+
oItem
[
sItem
]
[
'name'
]
+
'</option>'
)
;
}
break
;
}
}
html
=
html
.
join
(
''
)
;
city
.
find
(
'option'
)
.
remove
(
)
;
city
.
append
(
html
)
;
}
(
v
)
)
;
}
}
)
}
)
.
trigger
(
'change'
)
;
}
return
this
;
}
}
)
;
}
)
(
jQuery
,
'SOULTEARY.COM'
)
;
//插件调用代码
;
$
(
function
(
)
{
var
data
=
[
{
'name'
:
'北京市'
,
id
:
100000
,
children
:
[
{
'name'
:
'海淀区'
,
id
:
100003
}
,
{
'name'
:
'西城区'
,
id
:
100002
}
,
{
'name'
:
'东城区'
,
id
:
100001
}
]
}
,
{
'name'
:
'天津市'
,
id
:
300000
,
children
:
[
{
'name'
:
'北辰区'
,
id
:
100003
}
,
{
'name'
:
'红桥区'
,
id
:
100002
}
,
{
'name'
:
'河西区'
,
id
:
100001
}
]
}
]
;
$
(
'#province, #city'
)
.
citylist
(
{
data
:
data
}
)
;
}
)
;
</script>
|
接着我们继续写单独SELECT BOX的功能。
首先修改HTML结构,添加一个元素作为合并输出数据的容器。可以这么做:
1
2
3
4
5
|
<div
id
=
"warp2"
>
<select
id
=
"all"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
</div>
|
当然,为了有较好的心情去写实现代码,我们需要把CSS也写一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#warp2
{
width
:
230px
;
height
:
80px
;
position
:
absolute
;
top
:
50%
;
left
:
50%
;
margin-left
:
-200px
;
margin-top
:
0
;
box-shadow
:
1px
1px
#3A393A
;
border
:
1px
solid
#222
;
font-size
:
13px
;
line-height
:
13px
;
}
#all
{
margin
:
30px
;
}
|
接着开始写实现代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var
all
=
target
;
var
data
=
params
.
data
;
var
html
=
[
]
;
for
(
var
oo
in
data
)
{
html
.
push
(
'<option data-extra="'
+
data
[
oo
]
[
'id'
]
+
'">'
+
data
[
oo
]
[
'name'
]
+
'</option>'
)
;
for
(
var
xx
in
data
[
oo
]
.
children
)
{
html
.
push
(
'<option data-extra="'
+
data
[
oo
]
.
children
[
xx
]
[
'id'
]
+
'">'
+
data
[
oo
]
.
children
[
xx
]
[
'name'
]
+
'</option>'
)
;
}
}
html
=
html
.
join
(
''
)
;
all
.
find
(
'option'
)
.
remove
(
)
;
all
.
append
(
html
)
;
|
完整实现代码:
地址:http://thecdn.sinaapp.com/page/demo/jq-select/step-4.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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
<!doctype html>
<html
lang
=
"en"
>
<head>
<meta
charset
=
"UTF-8"
>
<title>
省市下拉联动插件 @soulteary
</title>
<style>
#warp
{
width
:
230px
;
height
:
80px
;
position
:
absolute
;
top
:
50%
;
left
:
50%
;
margin-left
:
-200px
;
margin-top
:
-130px
;
box-shadow
:
1px
1px
#3A393A
;
border
:
1px
solid
#222
;
font-size
:
13px
;
line-height
:
13px
;
}
#province
{
margin
:
30px
0
0
30px
;
float
:
left
;
}
#city
{
float
:
right
;
margin
:
30px
30px
0
0
;
}
#warp2
{
width
:
230px
;
height
:
80px
;
position
:
absolute
;
top
:
50%
;
left
:
50%
;
margin-left
:
-200px
;
margin-top
:
0
;
box-shadow
:
1px
1px
#3A393A
;
border
:
1px
solid
#222
;
font-size
:
13px
;
line-height
:
13px
;
}
#all
{
margin
:
30px
;
}
</style>
<script src="jquery-packed.ver.1.js"></script>
</head>
<body>
<div
id
=
"warp"
>
<select
id
=
"province"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
<select
id
=
"city"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
</div>
<div
id
=
"warp2"
>
<select
id
=
"all"
>
<option
value
=
"载入中"
>
载入中
</option>
</select>
</div>
<script type="text/javascript">
/* SOULTEARY.COM
_____ ____ __ ____ _______________ ______ __
/ ___// __ \/ / / / / /_ __/ ____/ | / __ \ \/ /
\__ \/ / / / / / / / / / / __/ / /| | / /_/ /\ /
___/ / /_/ / /_/ / /___/ / / /___/ ___ |/ _, _/ / /
/____/\____/\____/_____/_/ /_____/_/ |_/_/ |_| /_/ */
;
(
function
(
$
)
{
$
.
fn
.
extend
(
{
"citylist"
:
function
(
params
)
{
params
=
$
.
extend
(
{
id
:
'id'
,
//数据的ID名称
name
:
'name'
,
//数据的VALUE名称
children
:
'children'
,
//数据子元素的KEY的名称
metaTag
:
'data-extra'
,
//将数据元素的ID存放到HTML元素的标签中
idVal
:
false
,
//使用ID做OPTION的VALUE
data
:
false
,
//默认数据
selected
:
false
//选中的元素eg: 14 / [14:1401]
}
,
params
)
;
var
target
=
$
(
this
)
;
var
hasSelected
=
' selected="selected"'
;
var
html
=
[
]
;
if
(
!
target
.
length
)
{
return
this
;
}
else
if
(
target
.
length
==
1
)
{
var
all
=
target
;
var
data
=
params
.
data
;
for
(
var
oo
in
data
)
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
data
[
oo
]
[
params
.
id
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
==
data
[
oo
]
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
data
[
oo
]
[
params
.
name
]
+
'</option>'
)
;
for
(
var
xx
in
data
[
oo
]
[
params
.
children
]
)
{
if
(
params
.
idVal
)
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
id
]
+
'" value="'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
name
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
==
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
name
]
+
'</option>'
)
;
}
else
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
id
]
+
'" value="'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
id
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
==
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
data
[
oo
]
[
params
.
children
]
[
xx
]
[
params
.
name
]
+
'</option>'
)
;
}
}
}
html
=
html
.
join
(
''
)
;
all
.
find
(
'option'
)
.
remove
(
)
;
all
.
append
(
html
)
;
}
else
if
(
target
.
length
==
2
)
{
var
province
=
target
.
eq
(
0
)
;
var
city
=
target
.
eq
(
1
)
;
var
html
=
[
]
,
oItem
;
for
(
var
item
in
params
.
data
)
{
oItem
=
params
.
data
[
item
]
;
if
(
params
.
idVal
)
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
oItem
[
params
.
id
]
+
'" value="'
+
oItem
[
params
.
id
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
[
0
]
==
oItem
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
oItem
[
params
.
name
]
+
'</option>'
)
;
}
else
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
oItem
[
params
.
id
]
+
'" value="'
+
oItem
[
params
.
name
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
[
0
]
==
oItem
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
oItem
[
params
.
name
]
+
'</option>'
)
;
}
}
html
=
html
.
join
(
''
)
;
province
.
find
(
'option'
)
.
remove
(
)
;
province
.
append
(
html
)
;
var
provinces
=
province
.
find
(
'option'
)
;
province
.
on
(
'change'
,
function
(
)
{
var
curSelect
=
$
(
this
)
.
val
(
)
;
provinces
.
each
(
function
(
k
,
v
)
{
if
(
$
(
v
)
.
val
(
)
==
curSelect
)
{
return
(
function
(
v
)
{
var
extra
=
$
(
v
)
.
attr
(
params
.
metaTag
)
;
var
html
=
[
]
,
oItem
;
for
(
var
item
in
params
.
data
)
{
oItem
=
params
.
data
[
item
]
;
if
(
oItem
[
params
.
id
]
==
extra
&&
oItem
[
params
.
children
]
)
{
oItem
=
oItem
[
params
.
children
]
;
for
(
var
sItem
in
oItem
)
{
if
(
params
.
idVal
)
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
oItem
[
sItem
]
[
params
.
id
]
+
'" value="'
+
oItem
[
sItem
]
[
params
.
id
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
[
1
]
==
oItem
[
sItem
]
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
oItem
[
sItem
]
[
params
.
name
]
+
'</option>'
)
;
}
else
{
html
.
push
(
'<option '
+
params
.
metaTag
+
'="'
+
oItem
[
sItem
]
[
params
.
id
]
+
'" value="'
+
oItem
[
sItem
]
[
params
.
name
]
+
'"'
+
(
(
params
.
selected
&&
(
params
.
selected
[
1
]
==
oItem
[
sItem
]
[
params
.
id
]
)
)
?
hasSelected
:
''
)
+
'>'
+
oItem
[
sItem
]
[
params
.
name
]
+
'</option>'
)
;
}
}
break
;
}
}
html
=
html
.
join
(
''
)
;
city
.
find
(
'option'
)
.
remove
(
)
;
city
.
append
(
html
)
;
}
(
v
)
)
;
}
}
)
}
)
.
trigger
(
'change'
)
;
}
return
this
;
}
}
)
;
}
)
(
jQuery
,
'SOULTEARY.COM'
)
;
//插件调用代码
;
$
(
function
(
)
{
var
data
=
[
{
'name'
:
'北京市'
,
id
:
100000
,
children
:
[
{
'name'
:
'海淀区'
,
id
:
100003
}
,
{
'name'
:
'西城区'
,
id
:
100002
}
,
{
'name'
:
'东城区'
,
id
:
100001
}
]
}
,
{
'name'
:
'天津市'
,
id
:
300000
,
children
:
[
{
'name'
:
'北辰区'
,
id
:
100003
}
,
{
'name'
:
'红桥区'
,
id
:
100002
}
,
{
'name'
:
'河西区'
,
id
:
100001
}
]
}
]
;
$
(
'#province, #city'
)
.
citylist
(
{
data
:
data
,
id
:
'id'
,
children
:
'citys'
,
name
:
'name'
,
metaTag
:
'name'
}
)
;
$
(
'#all'
)
.
citylist
(
{
data
:
data
,
id
:
'id'
,
children
:
'citys'
,
name
:
'name'
,
metaTag
:
'name'
}
)
;
$
(
'#pre-province, #pre-city'
)
.
citylist
(
{
data
:
data
,
id
:
'id'
,
children
:
'citys'
,
name
:
'name'
,
metaTag
:
'name'
,
selected
:
[
14
,
1401
]
}
)
;
$
(
'#pre-all'
)
.
citylist
(
{
data
:
data
,
id
:
'id'
,
children
:
'citys'
,
name
:
'name'
,
metaTag
:
'name'
,
idVal
:
true
,
selected
:
1401
}
)
;
}
)
;
</script>
</body>
</html>
|
最后,把CSS,JS独立出页面即可。
当然,这里多添加了一个小功能,如果使用者定义的数据不是id,name,children这样的键,或者不想使用DATA-EXTRA来保存数据,那么一样可以使用这个小插件。
完成地址:http://thecdn.sinaapp.com/page/demo/jq-select/
GITHUB地址:https://github.com/soulteary/jquery-city-select