/** jQuery version: 1.8.3 Author: 小dee Date: 2014.11.8 */
接上一篇博客。
实现带缓存的仿亚马逊下拉面板
效果图:
图1 初始
图2 点击省份
图3 选择省份
图4 如果有第四级菜单
说明:该功能模块是固定前三极菜单,第四级菜单如果存在则动态加载 ( 不足:没有做到所有菜单完全动态加载 )。
图5
细节流程:
① 点击固定菜单时发生的动作:
■ 如果存在下拉面板,则下拉面板消失
■ 如果不存在下拉面板,则查看是否有缓存的下级菜单数据
■ 如果没有缓存数据,则通过 ajax 获取,同时缓存数据
■ 如果存在缓存数据,则直接读取缓存数据
■ 删除后级的菜单隐藏域信息、菜单数据以及菜单,同时后级菜单选择框的文字与样式还原成默认,删除动态加载的菜单选择框
② 点击固定菜单下单条数据时发生的动作:
■ 单条数据名称添加进相应选择框
■ 单条数据的 id 存入页面相应隐藏域
■ 对应的下拉面板消失
■ 请求下级菜单的数据
■ 把该数据追加至相应下拉面板中
■ 同时把该数据缓存在页面中
③ 点击最后一个固定菜单下单条数据时发生的动作:
■ 单条数据名称添加进城市选择框
■ 单条数据 id 存入页面隐藏域
■ 对应的下拉面板面板消失
■ 检测是否含有下级数据,如果有则追加动态菜单框
■ 请求动态菜单的数据
■ 把该数据追加至相应下拉面板中
■ 同时把该数据缓存在页面中
④ 点击动态加载的菜单下单条数据时发生的动作:
■ 单条数据名称添加进相应选择框
■ 单条数据的 id 存入页面相应隐藏域
■ 对应的下拉面板消失
addr.html 代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>仿亚马逊 - 动态添加的多级联动菜单</title> 6 <style> 7 body,html{ font-size:14px;} 8 form{ margin-top:20px; margin-left:20px;} 9 10 /* 选择框 */ 11 .con{ float:left; margin-right:10px; position:relative;} 12 .sel{ 13 14 padding:4px 23px 3px 5px; 15 border:1px solid #ccc; 16 background:url("images/dropdown_bg.gif") right 2px no-repeat; 17 } 18 .sel:hover{ 19 20 text-decoration:underline; 21 cursor:pointer; 22 } 23 24 /* 下拉面板 */ 25 .dropdiv{ 26 27 500px; 28 margin: 0; 29 border: solid 1px #cbe3f7; 30 padding: 7px 0 15px 15px; 31 background-color: #fff; 32 position:absolute; 33 34 font-size:12px; 35 } 36 /* 省市信息 */ 37 .span-new{ 38 39 display:inline-block; 40 110px; 41 padding-right:15px; 42 line-height:24px; 43 44 color:rgb(0, 75, 145); 45 cursor:pointer; 46 } 47 48 .span-new:hover{ text-decoration:underline; color:orange;} 49 50 /*结果*/ 51 #result{ margin:20px;} 52 53 .cls{ clear:both;} 54 </style> 55 <script src="../js/jquery-1.8.3.min.js"></script> 56 </head> 57 <body> 58 59 <form id="sel-form" action="addr.php" method="post"> 60 61 <div id="pcon" class="con"> 62 <div id="province" class="sel">请选择省</div> 63 </div> 64 65 <div id="ccon" class="con"> 66 <div id="city" class="sel">请选择城市</div> 67 </div> 68 69 <div id="acon" class="con"> 70 <div id="area" class="sel">请选择区县</div> 71 </div> 72 73 <div class="cls"></div> 74 <br> 75 <input type="submit" id="sub" value="提交"> 76 77 <!-- 隐藏域 --> 78 <input type="hidden" id="pid" name="pid"> 79 <input type="hidden" id="p" name="p"> 80 <input type="hidden" id="cid" name="cid"> 81 <input type="hidden" id="c" name="c"> 82 <input type="hidden" id="aid" name="aid"> 83 <input type="hidden" id="a" name="a"> 84 <input type="hidden" id="sid" name="sid"> 85 <input type="hidden" id="s" name="s"> 86 87 </form> 88 89 <!--缓存数据--> 90 <input type="hidden" id="pdata" name="pdata"> 91 92 <!-- 显示选择的结果 --> 93 <div id="result"> 94 省份:<{$pid}> - <{$p}><br> 95 城市:<{$cid}> - <{$c}><br> 96 区县:<{$aid}> - <{$a}><br> 97 <{if $sid && $s }> 98 街道:<{$sid}> - <{$s}> 99 <{/if}> 100 </div> 101 102 <script> 103 104 $(function(){ 105 106 //初始状态下只有第一级菜单显示可用(黑色字体),后级菜单显示不可用(灰色字体) 107 $(".sel:gt(0)").css("color","#ccc"); 108 109 //定义下拉面板 110 $dropdiv = $("<div class='dropdiv'></div"); 111 112 113 114 115 /******************* 116 * 点击第一级菜单 * 117 ********************/ 118 $("#province").click(function(){ 119 120 //可以封装函数 121 //删除后级 - 菜单单条信息 122 $("#citytab .span-new").remove(); 123 $("#areatab .span-new").remove(); 124 $("#streettab .span-new").remove(); 125 $("#citytab").remove(); 126 $("#areatab").remove(); 127 $("#streettab").remove(); 128 //删除后级 - 菜单信息 129 $("#city").text("请选择城市"); 130 $("#area").text("请选择区县"); 131 //清空后级对应的隐藏域 132 $("#cid").val(""); 133 $("#c").val(""); 134 $("#aid").val(""); 135 $("#a").val(""); 136 $("#sid").val(""); 137 $("#s").val(""); 138 //后级文字颜色 139 $("#city").css("color","#ccc"); 140 $("#area").css("color","#ccc"); 141 142 if( $("#provincetab").length == 0 ){ 143 144 //如果有省份缓存数据 145 if($("#pdata").val() == ""){ 146 147 //使用ajax获取省份信息 148 $.post("../sel2.php",{ 149 city:true 150 },function(data,textStatus){ 151 152 //接收json数据 153 var dataObj = eval("("+data+")"); //转换为json对象 154 155 //缓存数据 156 $("#pdata").val(data); 157 158 $.each(dataObj,function(idx,item){ 159 160 //给下拉面板加上ID 161 $dropdiv.attr("id","provincetab").css({"top":"25px","left":"0px"}); 162 $dropdiv.insertAfter($(".sel:eq(0)")); 163 164 //把获取到的数据追加至面板中 165 if( $("#provincetab .span-new").length < dataObj.length ){ 166 167 $span_new = $("<span class="span-new" id=""+item.provinceID+"">"+item.province+"</span>"); 168 $span_new.appendTo($("#provincetab")); 169 } 170 }) 171 172 }); 173 } 174 else{ 175 176 //取出缓存数据 177 var $bufferData = $("#pdata").val(); 178 var dataObj = eval("("+$bufferData+")"); 179 180 $.each(dataObj,function(idx,item){ 181 182 //给下拉面板加上ID 183 $dropdiv.attr("id","provincetab").css({"top":"25px","left":"0px"}); 184 $dropdiv.insertAfter($(".sel:eq(0)")); 185 186 //把获取到的数据追加至面板中 187 if( $("#provincetab .span-new").length < dataObj.length ){ 188 189 $span_new = $("<span class="span-new" id=""+item.provinceID+"">"+item.province+"</span>"); 190 $span_new.appendTo($("#provincetab")); 191 } 192 }) 193 } 194 195 }else{ 196 197 //当下拉面板已经存在时点击一级菜单,删除下拉面板 198 $("#provincetab").remove(); 199 } 200 201 //$("#province").click(function(){})结束 202 }); 203 204 205 206 207 /******************* 208 * 点击单条省份时 * 209 ********************/ 210 $("#provincetab .span-new").live("click",function(){ 211 212 //省份选择框 213 $("#province").text($(this).text()); 214 215 //隐藏域信息 216 $("#pid").val($(this).attr("id")); 217 $("#p").val($(this).text()); 218 219 $pid = $("#pid").val(); 220 221 //给$pid加上城市标识c,防止jQuery错误识别id 222 $pid4id = "c"+$pid; 223 224 //同时创建以该省id为id的input隐藏域id=c+pid,用作缓存城市数据 225 if($('#'+$pid4id).length == 0){ 226 227 $bufferCtiy = $("<input type='hidden' id='"+$pid4id+"'>"); 228 $bufferCtiy.insertAfter($("#pdata")); 229 230 } 231 232 //删除省菜单信息 233 $("#provincetab .span-new").remove(); 234 235 //后级 - 城市菜单弹出 236 //检查是否有缓存数据 237 if($("#"+$pid4id+"").val() == ""){ 238 239 $id = $(this).attr("id"); 240 $id4id = "c"+$id 241 242 //使用ajax获取省份信息 243 if( $("#citytab").length == 0 ){ 244 245 $.post("../sel2.php",{ 246 pid : $("#pid").val() 247 },function(data,textStatus){ 248 249 //接收json数据 250 var dataObj = eval("("+data+")"); //转换为json对象 251 252 //同时缓存对应省份的城市数据 253 $("#"+$id4id).val(data); 254 255 $.each(dataObj,function(idx,item){ 256 257 //给下拉面板加上ID 258 $dropdiv.attr("id","citytab").css({"top":"24px","left":"0px"}); 259 $("#citytab").appendTo($("#ccon")); 260 261 //后级菜单文字颜色 262 $("#city").css("color","#000"); 263 264 //把获取到的数据追加至面板中 265 if( $("#city .span-new").length < dataObj.length ){ 266 267 $span_new = $("<span class="span-new" id=""+item.cityID+"">"+item.city+"</span>"); 268 $span_new.appendTo($("#citytab")); 269 } 270 }); 271 }); 272 } 273 }else{ 274 275 //取出缓存数据 276 var $bufferData = $('#'+$pid4id).val(); 277 var dataObj = eval("("+$bufferData+")"); 278 279 //给下拉面板加上ID 280 $dropdiv.attr("id","citytab").css({"top":"24px","left":"0px"}); 281 $("#citytab").appendTo($("#ccon")); 282 283 //后级菜单文字颜色 284 $("#city").css("color","#000"); 285 286 $.each(dataObj,function(idx,item){ 287 288 //把获取到的数据追加至面板中 289 if( $("#city .span-new").length < dataObj.length ){ 290 291 $span_new = $("<span class="span-new" id=""+item.cityID+"">"+item.city+"</span>"); 292 $span_new.appendTo($("#citytab")); 293 } 294 }); 295 } 296 297 //$("#provincetab .span-new").live("click",function(){})结束 298 }); 299 300 301 302 303 /******************* 304 * 点击单条城市时 * 305 ********************/ 306 /****************************************** 307 * 7个动作: * 308 * * 309 * 1.城市名称添加进城市选择框 * 310 * 2.城市id存入页面隐藏域 * 311 * 3.城市面板消失 * 312 * 4.在dom中插入城市后级 - 区域下拉面板 * 313 * 5.请求城市后级 - 区县的数据 * 314 * 6.把该数据追加至区县面板中 * 315 * 7.同时把该数据缓存在页面中 * 316 * * 317 *******************************************/ 318 $("#citytab .span-new").live("click",function(){ 319 320 //1.城市名称添加进城市选择框 321 $("#city").text($(this).text()); 322 323 //2.城市id存入页面隐藏域 324 $("#cid").val($(this).attr("id")); 325 $("#c").val($(this).text()); 326 327 $cid = $("#cid").val(); 328 329 //3.城市面板消失 330 $("#citytab .span-new").remove(); 331 $("#citytab").remove(); 332 333 //4.在dom中插入城市后级 - 区域下拉面板 334 //给$cid加上城市标识c,防止jQuery错误识别id 335 $cid4id = "c"+$cid; 336 337 //同时创建以该城市id为id的input隐藏域id=c+cid,用作缓存区县数据 338 //创建隐藏域 339 if($('#'+$cid4id).length == 0){ 340 341 $bufferArea = $("<input type='hidden' id='"+$cid4id+"'>"); 342 $bufferArea.insertAfter($("#pdata")); 343 } 344 345 //检查是否有缓存数据 346 if($("#"+$cid4id+"").val() == ""){ 347 348 $id = $(this).attr("id"); 349 $id4id = "a"+$id; 350 351 //使用ajax获取省份信息 352 if( $("#areatab").length == 0 ){ 353 354 $.post("../sel2.php",{ 355 cid : $("#cid").val() 356 },function(data,textStatus){ 357 358 //接收json数据 359 var dataObj = eval("("+data+")"); //转换为json对象 360 361 //同时缓存对应城市的城市数据 362 $("#"+$cid4id).val(data); 363 364 $.each(dataObj,function(idx,item){ 365 366 //给下拉面板加上ID 367 $dropdiv.attr("id","areatab").css({"top":"24px","left":"0px"}); 368 $dropdiv.appendTo($("#acon")); 369 370 //后级菜单文字颜色 371 $("#area").css("color","#000"); 372 373 //把获取到的数据追加至面板中 374 if( $("#area .span-new").length < dataObj.length ){ 375 376 $span_new = $("<span class="span-new" id=""+item.areaID+"">"+item.area+"</span>"); 377 $span_new.appendTo($("#areatab")); 378 } 379 }); 380 }); 381 } 382 }else{ 383 384 //取出缓存数据 385 var $bufferData = $('#'+$cid4id).val(); 386 var dataObj = eval("("+$bufferData+")"); 387 388 //给下拉面板加上ID 389 $dropdiv.attr("id","areatab").css({"top":"24px","left":"0px"}); 390 $dropdiv.appendTo($("#acon")); 391 392 $.each(dataObj,function(idx,item){ 393 394 //把获取到的数据追加至面板中 395 if( $("#area .span-new").length < dataObj.length ){ 396 397 $span_new = $("<span class="span-new" id=""+item.areaID+"">"+item.area+"</span>"); 398 $span_new.appendTo($("#areatab")); 399 } 400 }); 401 } 402 403 }); 404 405 406 407 408 /************************** 409 * 点击二级菜单 - 城市时 * 410 ***************************/ 411 $("#city").click(function(){ 412 413 if($("#pid").val() != ""){ 414 415 //删除后级 - 菜单信息 416 $("#areatab .span-new").remove(); 417 $("#streettab .span-new").remove(); 418 $("#streettab").remove(); 419 $("#aid").val(""); 420 $("#a").val(""); 421 $("#sid").val(""); 422 $("#s").val(""); 423 $("#street").remove(); 424 //后级菜单文字颜色 425 $("#area").css("color","#ccc"); 426 $("#area").text("请选择区县"); 427 428 //当下拉面板不存在时 429 if( $("#citytab").length == 0 ){ 430 431 //根据表单中的省份id的隐藏域和表单外省份id=c+id的隐藏域的id进行对比,从页面缓存中读取数据 432 $pid = $("#pid").val(); 433 434 //存在缓存,直接从页面的隐藏域读取数据 435 //取出缓存数据 436 var $bufferData = $('#c'+$pid).val(); 437 438 var dataObj = eval("("+$bufferData+")"); 439 440 //给下拉面板加上ID 441 $dropdiv.attr("id","citytab").css({"top":"24px","left":"0px"}); 442 //注意:此处不能使用$("#citytab") 443 $dropdiv.appendTo($("#ccon")); 444 445 $.each(dataObj,function(idx,item){ 446 447 //把获取到的数据追加至面板中 448 if( $("#city .span-new").length < dataObj.length ){ 449 450 $span_new = $("<span class="span-new" id=""+item.cityID+"">"+item.city+"</span>"); 451 $span_new.appendTo($("#citytab")); 452 } 453 }); 454 455 }else{ 456 457 $("#citytab .span-new").remove(); 458 $("#citytab").remove(); 459 } 460 } 461 }); 462 463 464 465 /******************* 466 * 点击单条区域时 * 467 ********************/ 468 /****************************************** 469 * 7个动作: * 470 * * 471 * 1.区域名称添加进城市选择框 * 472 * 2.区域id存入页面隐藏域 * 473 * 3.区域面板消失 * 474 * 4.检测是否含有下级数据,如果有则追加 * 475 * 5.请求区县后级 - 街道的数据 * 476 * 6.把该数据追加至区县街道面板中 * 477 * 7.同时把该数据缓存在页面中 * 478 * * 479 *******************************************/ 480 $("#areatab .span-new").live("click",function(){ 481 482 //1.区域名称添加进城市选择框 483 $("#area").text($(this).text()); 484 $("#area").css("color","#000"); 485 486 //2.区域id存入页面隐藏域 487 $("#aid").val($(this).attr("id")); 488 $("#a").val($(this).text()); 489 490 $sid4id = "s"+$("#aid").val(); 491 //创建隐藏域 492 if($('#'+$sid4id).length == 0){ 493 494 $bufferArea = $("<input type='hidden' id='"+$sid4id+"'>"); 495 $bufferArea.insertAfter($("#pdata")); 496 } 497 498 //3.区域面板消失 499 $(this).siblings().remove(); 500 $(this).parent().remove(); 501 $(this).remove(); 502 503 //先检查是否有缓存 504 if($("#"+$sid4id).val() == ""){ 505 506 //4.如果没有缓存的话再检测是否含有下级数据,如果有则追加 507 $.post("../sel2.php",{ 508 aid : $("#aid").val() 509 },function(data,textStatus){ 510 511 //如果有返回值 512 if(data){ 513 514 //动态添加下一级菜单 515 $street = $("<div id="scon" class="con"><div id="street" class="sel">选择街道</div></div>"); 516 $street.insertAfter($("#acon")); 517 518 //接收json数据 519 var dataObj = eval("("+data+")"); //转换为json对象 520 521 //同时缓存对应城市的街道数据 522 $("#"+$sid4id).val(data); 523 524 $.each(dataObj,function(idx,item){ 525 526 //给下拉面板加上ID 527 $dropdiv.attr("id","streettab").css({"top":"24px","left":"0px"}); 528 $dropdiv.appendTo($("#scon")); 529 530 531 //把获取到的数据追加至面板中 532 if( $("#street .span-new").length < dataObj.length ){ 533 534 $span_new = $("<span class="span-new" id=""+item.streetID+"">"+item.street+"</span>"); 535 $span_new.appendTo($("#streettab")); 536 } 537 }); 538 } 539 }); 540 541 }else{ 542 543 //存在缓存,直接从页面的隐藏域读取数据 544 //取出缓存数据 545 var $bufferData = $("#"+$sid4id).val(); 546 547 var dataObj = eval("("+$bufferData+")"); 548 549 //动态添加下一级菜单 550 $street = $("<div id="scon" class="con"><div id="street" class="sel">选择街道</div></div>"); 551 $street.insertAfter($("#acon")); 552 553 //给下拉面板加上ID 554 $dropdiv.attr("id","streettab").css({"top":"24px","left":"0px"}); 555 $dropdiv.appendTo($("#scon")); 556 557 $.each(dataObj,function(idx,item){ 558 559 //把获取到的数据追加至面板中 560 if( $("#street .span-new").length < dataObj.length ){ 561 562 $span_new = $("<span class="span-new" id=""+item.streetID+"">"+item.street+"</span>"); 563 $span_new.appendTo($("#streettab")); 564 } 565 }); 566 567 } 568 569 }); 570 571 /************************** 572 * 点击三级菜单 - 区域时 * 573 ***************************/ 574 /****************************************************** 575 * 4个动作: * 576 * * 577 * 1.如果存在下拉面板,则下拉面板消失 * 578 * 2.如果不存在下拉面板,则查看是否有缓存数据 * 579 * 3.如果没有缓存数据,则通过ajax获取,同时缓存数据 * 580 * 4.如果存在缓存数据,则直接读取 * 581 * * 582 *******************************************************/ 583 $("#area").click(function(){ 584 585 if($("#cid").val() != ""){ 586 587 //删除后级 - 菜单信息 588 $("#streettab .span-new").remove(); 589 $("#streettab").remove(); 590 $("#sid").val(""); 591 $("#s").val(""); 592 $("#street").remove(); 593 594 //当下拉面板不存在时 595 if( $("#areatab").length == 0 ){ 596 597 //根据表单中的城市id的隐藏域和表单外省份id=a+id的隐藏域的id进行对比,从页面缓存中读取数据 598 $cid = $("#cid").val(); 599 600 //存在缓存,直接从页面的隐藏域读取数据 601 //取出缓存数据 602 var $bufferData = $('#c'+$cid).val(); 603 604 var dataObj = eval("("+$bufferData+")"); 605 606 //给下拉面板加上ID 607 $dropdiv.attr("id","areatab").css({"top":"24px","left":"0px"}); 608 //注意:此处不能使用$("#citytab") 609 $dropdiv.appendTo($("#acon")); 610 611 $.each(dataObj,function(idx,item){ 612 613 //把获取到的数据追加至面板中 614 if( $("#area .span-new").length < dataObj.length ){ 615 616 $span_new = $("<span class="span-new" id=""+item.areaID+"">"+item.area+"</span>"); 617 $span_new.appendTo($("#areatab")); 618 } 619 }); 620 621 }else{ 622 623 $("#areatab .span-new").remove(); 624 $("#areatab").remove(); 625 } 626 } 627 }); 628 629 630 631 632 /******************* 633 * 点击单条街道时 * 634 ********************/ 635 /****************************************** 636 * 3个动作: * 637 * * 638 * 1.街道名称添加进街道选择框 * 639 * 2.街道id存入页面隐藏域 * 640 * 3.街道面板消失 * 641 * * 642 *******************************************/ 643 $("#streettab .span-new").live("click",function(){ 644 645 //1.区域名称添加进城市选择框 646 $("#street").text($(this).text()); 647 $("#street").css("color","#000"); 648 649 //2.区域id存入页面隐藏域 650 $("#sid").val($(this).attr("id")); 651 $("#s").val($(this).text()); 652 653 //3.区域面板消失 654 $(this).siblings().remove(); 655 $(this).parent().remove(); 656 $(this).remove(); 657 }); 658 659 660 661 /******************* 662 * 点击街道菜单框时 * 663 ********************/ 664 $("#street").live("click",function(){ 665 666 if($("#aid").val() != ""){ 667 668 669 //当下拉面板不存在时 670 if( $("#streettab").length == 0 ){ 671 672 //根据表单中的区域id的隐藏域和表单外区域id=a+id的隐藏域的id进行对比,从页面缓存中读取数据 673 $aid = $("#aid").val(); 674 675 //存在缓存,直接从页面的隐藏域读取数据 676 //取出缓存数据 677 var $bufferData = $('#s'+$aid).val(); 678 679 var dataObj = eval("("+$bufferData+")"); 680 681 //给下拉面板加上ID 682 $dropdiv.attr("id","streettab").css({"top":"24px","left":"0px"}); 683 //注意:此处不能使用$("#citytab") 684 $dropdiv.appendTo($("#scon")); 685 686 $.each(dataObj,function(idx,item){ 687 688 //把获取到的数据追加至面板中 689 if( $("#street .span-new").length < dataObj.length ){ 690 691 $span_new = $("<span class="span-new" id=""+item.streetID+"">"+item.street+"</span>"); 692 $span_new.appendTo($("#streettab")); 693 } 694 }); 695 696 }else{ 697 698 $("#streettab .span-new").remove(); 699 $("#streettab").remove(); 700 } 701 } 702 }); 703 704 705 706 707 708 //如果有一栏为空或者不可用,不允许提交 709 $("#sub").click(function(){ 710 711 if($("#street").length == 0){ 712 713 if($("#pid").val() == "" || $("#p").val() == "" || $("#cid").val() == "" || $("#c").val() == "" || $("#aid").val() == "" || $("#a").val() == "" || $("#city").attr("disabled") === true || $("#area").attr("disabled") === true){ 714 715 alert("请完成选择"); 716 return false; 717 } 718 }else{ 719 720 if($("#pid").val() == "" || $("#p").val() == "" || $("#cid").val() == "" || $("#c").val() == "" || $("#aid").val() == "" || $("#a").val() == "" || $("#city").attr("disabled") === true || $("#area").attr("disabled") === true || $("#s").length == 0 || $("#s").val() == "" || $("#sid").length == 0 || $("#sid").val() == ""){ 721 722 alert("请完成选择"); 723 return false; 724 } 725 } 726 }); 727 728 729 //$(function(){})结束 730 }); 731 732 </script> 733 </body> 734 </html>
代码下载地址:https://github.com/dee0912/select_addr/tree/master/demo2
欢迎朋友们交流讨论。
如需转载,请在文章页面保留此说明并且给出原文链接。谢谢!