需求 : 热门城市、列表中的城市都需要在数据库中查询出来后构建列表,并按a-z排列,输入字母可以实现查询。
多城市选择器实现效果图:
实现:
1 后台根据登录用户获取列表中城市和热门城市的数据
@RequestMapping(value = "/getCity.do") 2 public void getCity(PrintWriter printWriter, HttpServletResponse response) 3 { 4 response.setContentType("text/html;charset=UTF-8"); 5 User user = this.getLoginUser(); 6 //查询出系统登陆人所有的所属区域名称 7 String allCity = getAllCityProperty(user.getId(), "areaName"); 8 String hotCity = getHotCity(allCity); 9 JSONObject json = new JSONObject(); 10 json.accumulate("hotCity",hotCity); 11 json.accumulate("allCity",allCity); 12 printWriter.print(json.toString()); 13 printWriter.flush(); 14 printWriter.close(); 15 }
2 前台打开界面的时候通过ajax获取城市和热门城市
1 window.onload=function(){ 2 var url = "/xxx/getCity.do"; 3 var params = {}; 4 $.getJSON(url,params,function(data){ 5 if(data.length==0) 6 { 7 $.messager.alert('提示',"未找到数据"); 8 }else{ 9 var hotString = data.hotCity; 10 var allString = data.allCity; 11 new Vcity.CitySelector({input:'city'},allString,hotString); 12 } 13 }); 14 }
3 citys.js 根据百度上的城市选择组件 新增热门城市和城市变量
/* * * ---------------------------------------- * * 城市选择组件 v1.0 * Author: zcx * ---------------------------------------- * * Date: 2016-05-17 * ---------------------------------------- * * */ /* * * 全局空间 Vcity * */ var Vcity = {}; /* * * 静态方法集 * @name _m * */ Vcity._m = { /* 选择元素 */ $:function (arg, context) { var tagAll, n, eles = [], i, sub = arg.substring(1); context = context || document; if (typeof arg == 'string') { switch (arg.charAt(0)) { case '#': return document.getElementById(sub); break; case '.': if (context.getElementsByClassName) return context.getElementsByClassName(sub); tagAll = Vcity._m.$('*', context); n = tagAll.length; for (i = 0; i < n; i++) { if (tagAll[i].className.indexOf(sub) > -1) eles.push(tagAll[i]); } return eles; break; default: return context.getElementsByTagName(arg); break; } } }, /* 绑定事件 */ on:function (node, type, handler) { node.addEventListener ? node.addEventListener(type, handler, false) : node.attachEvent('on' + type, handler); }, /* 获取事件 */ getEvent:function(event){ return event || window.event; }, /* 获取事件目标 */ getTarget:function(event){ return event.target || event.srcElement; }, /* 获取元素位置 */ getPos:function (node) { var scrollx = document.documentElement.scrollLeft || document.body.scrollLeft, scrollt = document.documentElement.scrollTop || document.body.scrollTop; var pos = node.getBoundingClientRect(); return {top:pos.top + scrollt, right:pos.right + scrollx, bottom:pos.bottom + scrollt, left:pos.left + scrollx } }, /* 添加样式名 */ addClass:function (c, node) { if(!node)return; node.className = Vcity._m.hasClass(c,node) ? node.className : node.className + ' ' + c ; }, /* 移除样式名 */ removeClass:function (c, node) { var reg = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"); if(!Vcity._m.hasClass(c,node))return; node.className = reg.test(node.className) ? node.className.replace(reg, '') : node.className; }, /* 是否含有CLASS */ hasClass:function (c, node) { if(!node || !node.className)return false; return node.className.indexOf(c)>-1; }, /* 阻止冒泡 */ stopPropagation:function (event) { event = event || window.event; event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; }, /* 去除两端空格 */ trim:function (str) { return str.replace(/^\s+|\s+$/g,''); } }; /* 正则表达式 筛选中文城市名、拼音、首字母 */ Vcity.regEx = /^([\u4E00-\u9FA5\uf900-\ufa2d]+)\|(\w+)\|(\w)\w*\|(\d+)$/i; Vcity.regExChiese = /([\u4E00-\u9FA5\uf900-\ufa2d]+)/; function adapterCity (citylist,hotStr) { if(!citylist){ return; } var citys = citylist; var match; var letter; var regEx = Vcity.regEx, reg2 = /^[a]$/i, reg3 = /^[b]$/i, reg4 = /^[c]$/i; reg5 = /^[d]$/i, reg6 = /^[e]$/i, reg7 = /^[f]$/i; reg8 = /^[g]$/i, reg9 = /^[h]$/i, reg10 = /^[i]$/i; reg11 = /^[j]$/i, reg12 = /^[k]$/i, reg13 = /^[l]$/i; reg14 = /^[m]$/i, reg15 = /^[n]$/i, reg16 = /^[o]$/i; reg17 = /^[p]$/i, reg18 = /^[q]$/i, reg19 = /^[r]$/i; reg20 = /^[s]$/i, reg21 = /^[t]$/i, reg22 = /^[u]$/i; reg23 = /^[v]$/i, reg24 = /^[w]$/i, reg25 = /^[x]$/i; reg26 = /^[y]$/i, reg27 = /^[z]$/i; //if (!Vcity.oCity) { Vcity.oCity = {hot:{},A:{},B:{},C:{},D:{},E:{},F:{},G:{},H:{}, I:{},J:{},K:{},L:{},M:{},N:{},O:{},P:{}, Q:{},R:{},S:{},T:{},U:{},V:{},W:{},X:{},Y:{},Z:{}}; //console.log(citys.length); for (var i = 0; i < citys.length; i++) { match = regEx.exec(citys[i]); letter = match[3].toUpperCase(); if (reg2.test(letter)) { if (!Vcity.oCity.A[letter]) Vcity.oCity.A[letter] = []; Vcity.oCity.A[letter].push(match[1]); } else if (reg3.test(letter)) { if (!Vcity.oCity.B[letter]) Vcity.oCity.B[letter] = []; Vcity.oCity.B[letter].push(match[1]); } else if (reg4.test(letter)) { if (!Vcity.oCity.C[letter]) Vcity.oCity.C[letter] = []; Vcity.oCity.C[letter].push(match[1]); }else if (reg5.test(letter)) { if (!Vcity.oCity.D[letter]) Vcity.oCity.D[letter] = []; Vcity.oCity.D[letter].push(match[1]); }else if (reg6.test(letter)) { if (!Vcity.oCity.E[letter]) Vcity.oCity.E[letter] = []; Vcity.oCity.E[letter].push(match[1]); }else if (reg7.test(letter)) { if (!Vcity.oCity.F[letter]) Vcity.oCity.F[letter] = []; Vcity.oCity.F[letter].push(match[1]); }else if (reg8.test(letter)) { if (!Vcity.oCity.G[letter]) Vcity.oCity.G[letter] = []; Vcity.oCity.G[letter].push(match[1]); }else if (reg9.test(letter)) { if (!Vcity.oCity.H[letter]) Vcity.oCity.H[letter] = []; Vcity.oCity.H[letter].push(match[1]); }else if (reg10.test(letter)) { if (!Vcity.oCity.I[letter]) Vcity.oCity.I[letter] = []; Vcity.oCity.I[letter].push(match[1]); }else if (reg11.test(letter)) { if (!Vcity.oCity.J[letter]) Vcity.oCity.J[letter] = []; Vcity.oCity.J[letter].push(match[1]); }else if (reg12.test(letter)) { if (!Vcity.oCity.K[letter]) Vcity.oCity.K[letter] = []; Vcity.oCity.K[letter].push(match[1]); }else if (reg13.test(letter)) { if (!Vcity.oCity.L[letter]) Vcity.oCity.L[letter] = []; Vcity.oCity.L[letter].push(match[1]); }else if (reg14.test(letter)) { if (!Vcity.oCity.M[letter]) Vcity.oCity.M[letter] = []; Vcity.oCity.M[letter].push(match[1]); }else if (reg15.test(letter)) { if (!Vcity.oCity.N[letter]) Vcity.oCity.N[letter] = []; Vcity.oCity.N[letter].push(match[1]); }else if (reg16.test(letter)) { if (!Vcity.oCity.O[letter]) Vcity.oCity.O[letter] = []; Vcity.oCity.O[letter].push(match[1]); }else if (reg17.test(letter)) { if (!Vcity.oCity.P[letter]) Vcity.oCity.P[letter] = []; Vcity.oCity.P[letter].push(match[1]); }else if (reg18.test(letter)) { if (!Vcity.oCity.Q[letter]) Vcity.oCity.Q[letter] = []; Vcity.oCity.Q[letter].push(match[1]); }else if (reg19.test(letter)) { if (!Vcity.oCity.R[letter]) Vcity.oCity.R[letter] = []; Vcity.oCity.R[letter].push(match[1]); }else if (reg20.test(letter)) { if (!Vcity.oCity.S[letter]) Vcity.oCity.S[letter] = []; Vcity.oCity.S[letter].push(match[1]); }else if (reg21.test(letter)) { if (!Vcity.oCity.T[letter]) Vcity.oCity.T[letter] = []; Vcity.oCity.T[letter].push(match[1]); }else if (reg22.test(letter)) { if (!Vcity.oCity.U[letter]) Vcity.oCity.U[letter] = []; Vcity.oCity.U[letter].push(match[1]); }else if (reg23.test(letter)) { if (!Vcity.oCity.V[letter]) Vcity.oCity.V[letter] = []; Vcity.oCity.V[letter].push(match[1]); }else if (reg24.test(letter)) { if (!Vcity.oCity.W[letter]) Vcity.oCity.W[letter] = []; Vcity.oCity.W[letter].push(match[1]); }else if (reg25.test(letter)) { if (!Vcity.oCity.X[letter]) Vcity.oCity.X[letter] = []; Vcity.oCity.X[letter].push(match[1]); }else if (reg26.test(letter)) { if (!Vcity.oCity.Y[letter]) Vcity.oCity.Y[letter] = []; Vcity.oCity.Y[letter].push(match[1]); }else if (reg27.test(letter)) { if (!Vcity.oCity.Z[letter]) Vcity.oCity.Z[letter] = []; Vcity.oCity.Z[letter].push(match[1]); } /* 热门城市 */ if(!Vcity.oCity.hot['hot']) Vcity.oCity.hot['hot'] = hotStr; } //} }; /* 城市HTML模板 */ /* 城市HTML模板 */ Vcity._template = [ '<p class="tip">热门城市(支持汉字/拼音)</p>', '<ul>', '<li class="on">热门城市</li>', '<li>A</li>', '<li>B</li>', '<li>C</li>', '<li>D</li>', '<li>E</li>', '<li>F</li>', '<li>G</li>', '<li>H</li>', '<li>I</li>', '<li>J</li>', '<li>K</li>', '<li>L</li>', '<li>M</li>', '<li>N</li>', '<li>O</li>', '<li>P</li>', '<li>Q</li>', '<li>R</li>', '<li>S</li>', '<li>T</li>', '<li>U</li>', '<li>V</li>', '<li>W</li>', '<li>x</li>', '<li>y</li>', '<li>Z</li>', '</ul>' ]; /* 城市HTML模板 */ /*Vcity._template = [ '<p class="tip">热门城市(支持汉字/拼音)</p>', '<ul>', '<li class="on">热门城市</li>', '<li>ABCDEFGH</li>', '<li>IJKLMNOP</li>', '<li>QRSTUVWXYZ</li>', '</ul>' ];*/ /* * * 城市控件构造函数 * @CitySelector * */ Vcity.CitySelector = function () { this.initialize.apply(this, arguments); }; Vcity.CitySelector.prototype = { constructor:Vcity.CitySelector, /* 初始化 */ initialize :function (options,istr,hotStr) { var input = options.input; this.input = Vcity._m.$('#'+ input); this.inputEvent(istr,hotStr); }, /* * * @createWarp * 创建城市BOX HTML 框架 * */ createWarp:function(cwstr,hotStr){ var inputPos = Vcity._m.getPos(this.input); var p = this.rootDiv = document.createElement('p'); var that = this; // 设置DIV阻止冒泡 Vcity._m.on(this.rootDiv,'click',function(event){ Vcity._m.stopPropagation(event); }); // 设置点击文档隐藏弹出的城市选择框 Vcity._m.on(document, 'click', function (event) { event = Vcity._m.getEvent(event); var target = Vcity._m.getTarget(event); if(target == that.input) return false; //console.log(target.className); if (that.cityBox)Vcity._m.addClass('hide', that.cityBox); if (that.ul)Vcity._m.addClass('hide', that.ul); if(that.myIframe)Vcity._m.addClass('hide',that.myIframe); }); p.className = 'citySelector'; p.style.position = 'absolute'; p.style.left = inputPos.left + 'px'; p.style.top = inputPos.bottom + 'px'; p.style.zIndex = 999999; // 判断是否IE6,如果是IE6需要添加iframe才能遮住SELECT框 var isIe = (document.all) ? true : false; var isIE6 = this.isIE6 = isIe && !window.XMLHttpRequest; if(isIE6){ var myIframe = this.myIframe = document.createElement('iframe'); myIframe.frameborder = '0'; myIframe.src = 'about:blank'; myIframe.style.position = 'absolute'; myIframe.style.zIndex = '-1'; this.rootDiv.appendChild(this.myIframe); } var childp = this.cityBox = document.createElement('p'); childp.className = 'cityBox'; childp.id = 'cityBox'; childp.innerHTML = Vcity._template.join(''); var hotCity = this.hotCity = document.createElement('p'); hotCity.className = 'hotCity'; childp.appendChild(hotCity); p.appendChild(childp); this.createHotCity(cwstr,hotStr); }, /* * * @createHotCity * TAB下面DIV:hot,a-h,i-p,q-z 分类HTML生成,DOM操作 * {HOT:{hot:[]},ABCDEFGH:{a:[1,2,3],b:[1,2,3]},IJKLMNOP:{},QRSTUVWXYZ:{}} **/ createHotCity:function(chstr,hotStr){ adapterCity (chstr,hotStr); var op,odl,odt,odd,odda=[],str,key,ckey,sortKey,regEx = Vcity.regEx, oCity = Vcity.oCity; for(key in oCity){ op = this[key] = document.createElement('p'); // 先设置全部隐藏hide op.className = key + ' ' + 'cityTab hide'; sortKey=[]; for(ckey in oCity[key]){ sortKey.push(ckey); // ckey按照ABCDEDG顺序排序 sortKey.sort(); } for(var j=0,k = sortKey.length;j<k;j++){ odl = document.createElement('dl'); odt = document.createElement('dt'); odd = document.createElement('dd'); odt.innerHTML = sortKey[j] == 'hot'?' ':sortKey[j]; odda = []; for(var i=0,n=oCity[key][sortKey[j]].length;i<n;i++){ str = '<a href="javascript:">' + oCity[key][sortKey[j]][i] + '</a>'; odda.push(str); } odd.innerHTML = odda.join(''); odl.appendChild(odt); odl.appendChild(odd); op.appendChild(odl); } // 移除热门城市的隐藏CSS Vcity._m.removeClass('hide',this.hot); this.hotCity.appendChild(op); } document.body.appendChild(this.rootDiv); /* IE6 */ this.changeIframe(); this.tabChange(); this.linkEvent(); }, /* * * tab按字母顺序切换 * @ tabChange * */ tabChange:function(){ var lis = Vcity._m.$('li',this.cityBox); var ps = Vcity._m.$('p',this.hotCity); var that = this; for(var i=0,n=lis.length;i<n;i++){ lis[i].index = i; lis[i].onclick = function(){ for(var j=0;j<n;j++){ Vcity._m.removeClass('on',lis[j]); Vcity._m.addClass('hide',ps[j]); } Vcity._m.addClass('on',this); Vcity._m.removeClass('hide',ps[this.index]); /* IE6 改变TAB的时候 改变Iframe 大小*/ that.changeIframe(); }; } }, /* * * 城市LINK事件 * @linkEvent * */ linkEvent:function(){ var links = Vcity._m.$('a',this.hotCity); var that = this; for(var i=0,n=links.length;i<n;i++){ links[i].onclick = function(){ that.input.value = this.innerHTML; Vcity._m.addClass('hide',that.cityBox); /* 点击城市名的时候隐藏myIframe */ Vcity._m.addClass('hide',that.myIframe); } } }, /* * * INPUT城市输入框事件 * @inputEvent * */ inputEvent:function(iestr,hotStr){ var that = this; Vcity._m.on(this.input,'click',function(event){ event = event || window.event; if(!that.cityBox){ that.createWarp(iestr,hotStr); }else if(!!that.cityBox && Vcity._m.hasClass('hide',that.cityBox)){ // slideul 不存在或者 slideul存在但是是隐藏的时候 两者不能共存 if(!that.ul || (that.ul && Vcity._m.hasClass('hide',that.ul))){ Vcity._m.removeClass('hide',that.cityBox); /* IE6 移除iframe 的hide 样式 */ //alert('click'); Vcity._m.removeClass('hide',that.myIframe); that.changeIframe(); } } }); Vcity._m.on(this.input,'focus',function(){ that.input.select(); if(that.input.value == '城市名') that.input.value = ''; }); Vcity._m.on(this.input,'blur',function(){ if(that.input.value == '') that.input.value = '城市名'; }); Vcity._m.on(this.input,'keyup',function(event){ event = event || window.event; var keycode = event.keyCode; Vcity._m.addClass('hide',that.cityBox); that.createUl(iestr); /* 移除iframe 的hide 样式 */ Vcity._m.removeClass('hide',that.myIframe); // 下拉菜单显示的时候捕捉按键事件 if(that.ul && !Vcity._m.hasClass('hide',that.ul) && !that.isEmpty){ that.KeyboardEvent(event,keycode); } }); }, /* * * 生成下拉选择列表 * @ createUl * */ createUl:function (iestr) { if(!iestr){ return; } //console.log('createUL'); var str; var value = Vcity._m.trim(this.input.value); // 当value不等于空的时候执行 if (value !== '') { var reg = new RegExp("^" + value + "|\\|" + value, 'gi'); var searchResult = []; /* * *【修改5】 * 这里原本是遍历Vcity.allCity,现在改用citylist * zcx 2016-5-17 */ for (var i = 0; i < iestr.length; i++) { if (reg.test(iestr[i])) { var match = Vcity.regEx.exec(iestr[i]); if (searchResult.length !== 0) { str = '<li><b class="cityname">' + match[1] + '</b><b class="cityspell">' + match[2] + '</b></li>'; } else { str = '<li class="on"><b class="cityname">' + match[1] + '</b><b class="cityspell">' + match[2] + '</b></li>'; } searchResult.push(str); } } this.isEmpty = false; // 如果搜索数据为空 if (searchResult.length == 0) { this.isEmpty = true; str = '<li class="empty">对不起,没有找到数据 "<em>' + value + '</em>"</li>'; searchResult.push(str); } // 如果slideul不存在则添加ul if (!this.ul) { var ul = this.ul = document.createElement('ul'); ul.className = 'cityslide'; this.rootDiv && this.rootDiv.appendChild(ul); // 记录按键次数,方向键 this.count = 0; } else if (this.ul && Vcity._m.hasClass('hide', this.ul)) { this.count = 0; Vcity._m.removeClass('hide', this.ul); } this.ul.innerHTML = searchResult.join(''); /* IE6 */ this.changeIframe(); // 绑定Li事件 this.liEvent(); }else{ Vcity._m.addClass('hide',this.ul); Vcity._m.removeClass('hide',this.cityBox); Vcity._m.removeClass('hide',this.myIframe); this.changeIframe(); } }, /* IE6的改变遮罩SELECT 的 IFRAME尺寸大小 */ changeIframe:function(){ if(!this.isIE6)return; this.myIframe.style.width = this.rootDiv.offsetWidth + 'px'; this.myIframe.style.height = this.rootDiv.offsetHeight + 'px'; }, /* * * 特定键盘事件,上、下、Enter键 * @ KeyboardEvent * */ KeyboardEvent:function(event,keycode){ var lis = Vcity._m.$('li',this.ul); var len = lis.length; switch(keycode){ case 40: //向下箭头↓ this.count++; if(this.count > len-1) this.count = 0; for(var i=0;i<len;i++){ Vcity._m.removeClass('on',lis[i]); } Vcity._m.addClass('on',lis[this.count]); break; case 38: //向上箭头↑ this.count--; if(this.count<0) this.count = len-1; for(i=0;i<len;i++){ Vcity._m.removeClass('on',lis[i]); } Vcity._m.addClass('on',lis[this.count]); break; case 13: // enter键 this.input.value = Vcity.regExChiese.exec(lis[this.count].innerHTML)[0]; Vcity._m.addClass('hide',this.ul); Vcity._m.addClass('hide',this.ul); /* IE6 */ Vcity._m.addClass('hide',this.myIframe); break; default: break; } }, /* * * 下拉列表的li事件 * @ liEvent * */ liEvent:function(){ var that = this; var lis = Vcity._m.$('li',this.ul); for(var i = 0,n = lis.length;i < n;i++){ Vcity._m.on(lis[i],'click',function(event){ event = Vcity._m.getEvent(event); var target = Vcity._m.getTarget(event); that.input.value = Vcity.regExChiese.exec(target.innerHTML)[0]; Vcity._m.addClass('hide',that.ul); /* IE6 下拉菜单点击事件 */ Vcity._m.addClass('hide',that.myIframe); }); Vcity._m.on(lis[i],'mouseover',function(event){ event = Vcity._m.getEvent(event); var target = Vcity._m.getTarget(event); Vcity._m.addClass('on',target); }); Vcity._m.on(lis[i],'mouseout',function(event){ event = Vcity._m.getEvent(event); var target = Vcity._m.getTarget(event); Vcity._m.removeClass('on',target); }) } } }
更多Multi-city selector implementation code请关注PHP中文网(m.sbmmt.com)其它文章!