JavaScript實(shí)現(xiàn)城市選擇控件的效果
在淘寶旅行上看到的城市選擇效果,感覺(jué)還不錯(cuò),就自己的理解重新實(shí)現(xiàn)一遍,先看效果(有人說(shuō)IE9下面有BUG,LZ用的是落后的XP,居然裝不上IE9,去公司在搞搞好了),然后再細(xì)說(shuō)實(shí)現(xiàn)原理,支持鼠標(biāo)上下鍵選擇城市,支持直接輸入城市名稱(chēng),拼音首字母,全拼,支持IE6遮蓋SELECT,壓縮后12K。

實(shí)現(xiàn)的步驟:
一、先用一定的格式羅列出控件所需要的城市以及拼音等,我這里是按照如下格式羅列成一個(gè)數(shù)組, 如果需要增加城市,直接增加在數(shù)組里面即可:
城市我是一個(gè)一個(gè)手打的。。。
['北京|beijing|bj','上海|shanghai|sh', '重慶|chongqing|cq']
二、因?yàn)榭丶某鞘蟹纸M按好幾類(lèi)劃分,比如:按首字母HOT 、ABCDEFH 、 IJKLMNOP 、 QRSTUVWXYZ 四組劃分,
而劃分了四組后又按照了首字母劃分,所以我用正則表達(dá)式和循環(huán)把數(shù)組重新格式化為一個(gè)分組對(duì)象,熱門(mén)城市取前16條。
對(duì)象格式如下:
{HOT:{hot:[]},ABCDEFGH:{a:[1,2,3],b:[1,2,3]},IJKLMNOP:{i:[1.2.3],j:[1,2,3]},QRSTUVWXYZ:{}}
所用代碼如下:
/* *
* 格式化城市數(shù)組為對(duì)象oCity,按照a-h,i-p,q-z,hot熱門(mén)城市分組:
* {HOT:{hot:[]},ABCDEFGH:{a:[1,2,3],b:[1,2,3]},IJKLMNOP:{i:[1.2.3],j:[1,2,3]},QRSTUVWXYZ:{}}
* */
(function () {
var citys = Vcity.allCity, match, letter,
regEx = Vcity.regEx,
reg2 = /^[a-h]$/i, reg3 = /^[i-p]$/i, reg4 = /^[q-z]$/i;
if (!Vcity.oCity) {
Vcity.oCity = {hot:{},ABCDEFGH:{}, IJKLMNOP:{}, QRSTUVWXYZ:{}};
//console.log(citys.length);
for (var i = 0, n = citys.length; i < n; i++) {
match = regEx.exec(citys[i]);
letter = match[3].toUpperCase();
if (reg2.test(letter)) {
if (!Vcity.oCity.ABCDEFGH[letter]) Vcity.oCity.ABCDEFGH[letter] = [];
Vcity.oCity.ABCDEFGH[letter].push(match[1]);
} else if (reg3.test(letter)) {
if (!Vcity.oCity.IJKLMNOP[letter]) Vcity.oCity.IJKLMNOP[letter] = [];
Vcity.oCity.IJKLMNOP[letter].push(match[1]);
} else if (reg4.test(letter)) {
if (!Vcity.oCity.QRSTUVWXYZ[letter]) Vcity.oCity.QRSTUVWXYZ[letter] = [];
Vcity.oCity.QRSTUVWXYZ[letter].push(match[1]);
}
/* 熱門(mén)城市 前16條 */
if(i<16){
if(!Vcity.oCity.hot['hot']) Vcity.oCity.hot['hot'] = [];
Vcity.oCity.hot['hot'].push(match[1]);
}
}
}
})();
三、然后先照著淘寶旅行里面的樣子弄出HTML與CSS;這里略過(guò)。
四、然后開(kāi)始建立CitySelector構(gòu)造函數(shù),根據(jù)城市對(duì)象,構(gòu)建生成DOM對(duì)象,在按照相應(yīng)的事件觸發(fā)。在生成相應(yīng)的按照A\B\C\D……分組的時(shí)候遇到一個(gè)
關(guān)于排序的問(wèn)題,我的對(duì)象格式是這樣的ABCDEFGH:{a:[1,2,3],b:[1,2,3],c:[1,2,3]},里面的小數(shù)組要按照字母的順序排序,但是我用for……in循環(huán)生成
出來(lái)是亂的,咨詢(xún)了群里的高人后,處理方法如下:這里單獨(dú)把KEY拿出來(lái)組成一個(gè)數(shù)組,然后排序后,在根據(jù)數(shù)組的值作為KEY值,來(lái)讀取對(duì)象!
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="#">' + oCity[key][sortKey[j]][i] + '</a>';
odda.push(str);
}
五、鼠標(biāo)上下鍵移動(dòng)選擇城市的處理方法:在城市彈出后記錄一個(gè)this.count = 0;然后再獲取上下鍵的按鍵事件中分別對(duì)count值加一或者減一,
當(dāng)然count的最大值不能大于篩選出來(lái)的城市數(shù)組的長(zhǎng)度,超過(guò)長(zhǎng)度后歸0,小于0后賦值最大值,然后把this.count的值,來(lái)作為數(shù)組的標(biāo)獲取相應(yīng)的城市項(xiàng):
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;
}
六、IE中對(duì)SELECT的遮擋也是一個(gè)增加代碼的地方,因?yàn)槌鞘袕棾隹虻拇笮∈亲兓?,然后下拉的城市列也是根?jù)篩選出來(lái)的值而變化,所以得每操作一個(gè)變化的地方的時(shí)候就重新給iframe設(shè)置長(zhǎng)度和寬度,苦逼的處理方法啊,所以就多了這樣一個(gè)方法,然后在改變尺寸的時(shí)候,應(yīng)用一下就可以了。
/* 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';
}
7、彈出框的取消問(wèn)題,這個(gè)問(wèn)題最開(kāi)始我是設(shè)置document的click事件關(guān)閉層,然后再?gòu)棾龅膶由献柚筩lick事件的冒泡,但是這樣兩個(gè)層有同時(shí)出現(xiàn)的可能,
// 設(shè)置點(diǎn)擊文檔隱藏彈出的城市選擇框
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);
});
8、輸入框輸入拼音或者文字或者拼音首字母篩選城市,這個(gè)就是直接用正則表達(dá)式在最開(kāi)始的數(shù)組里面篩選數(shù)據(jù)即可:
var reg = new RegExp("^" + value + "|\\|" + value, 'gi');
var searchResult = [];
for (var i = 0, n = Vcity.allCity.length; i < n; i++) {
if (reg.test(Vcity.allCity[i])) {
var match = Vcity.regEx.exec(Vcity.allCity[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);
}
}
然后總的JS代碼如下:
/* *
* ---------------------------------------- *
* 城市選擇組件 v1.0
* Author: VVG
* QQ: 83816819
* Mail: mysheller@163.com
* http://www.cnblogs.com/NNUF/
* ---------------------------------------- *
* Date: 2012-07-10
* ---------------------------------------- *
* */
/* *
* 全局空間 Vcity
* */
var Vcity = {};
/* *
* 靜態(tài)方法集
* @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;
},
/* 獲取事件目標(biāo) */
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,'');
}
};
/* 所有城市數(shù)據(jù),可以按照格式自行添加(北京|beijing|bj),前16條為熱門(mén)城市 */
Vcity.allCity = ['北京|beijing|bj','上海|shanghai|sh', '重慶|chongqing|cq', '深圳|shenzhen|sz', '廣州|guangzhou|gz', '杭州|hangzhou|hz',
'南京|nanjing|nj', '蘇州|shuzhou|sz', '天津|tianjin|tj', '成都|chengdu|cd', '南昌|nanchang|nc', '三亞|sanya|sy','青島|qingdao|qd',
'廈門(mén)|xiamen|xm', '西安|xian|xa','長(zhǎng)沙|changsha|cs','合肥|hefei|hf','西藏|xizang|xz', '內(nèi)蒙古|neimenggu|nmg', '安慶|anqing|aq', '阿泰勒|ataile|atl', '安康|ankang|ak',
'阿克蘇|akesu|aks', '包頭|baotou|bt', '北海|beihai|bh', '百色|baise|bs','保山|baoshan|bs', '長(zhǎng)治|changzhi|cz', '長(zhǎng)春|changchun|cc', '常州|changzhou|cz', '昌都|changdu|cd',
'朝陽(yáng)|chaoyang|cy', '常德|changde|cd', '長(zhǎng)白山|changbaishan|cbs', '赤峰|chifeng|cf', '大同|datong|dt', '大連|dalian|dl', '達(dá)縣|daxian|dx', '東營(yíng)|dongying|dy', '大慶|daqing|dq', '丹東|dandong|dd',
'大理|dali|dl', '敦煌|dunhuang|dh', '鄂爾多斯|eerduosi|eeds', '恩施|enshi|es', '福州|fuzhou|fz', '阜陽(yáng)|fuyang|fy', '貴陽(yáng)|guiyang|gy',
'桂林|guilin|gl', '廣元|guangyuan|gy', '格爾木|geermu|gem', '呼和浩特|huhehaote|hhht', '哈密|hami|hm',
'黑河|heihe|hh', '海拉爾|hailaer|hle', '哈爾濱|haerbin|heb', '??趞haikou|hk', '黃山|huangshan|hs', '邯鄲|handan|hd',
'漢中|hanzhong|hz', '和田|hetian|ht', '晉江|jinjiang|jj', '錦州|jinzhou|jz', '景德鎮(zhèn)|jingdezhen|jdz',
'嘉峪關(guān)|jiayuguan|jyg', '井岡山|jinggangshan|jgs', '濟(jì)寧|jining|jn', '九江|jiujiang|jj', '佳木斯|jiamusi|jms', '濟(jì)南|jinan|jn',
'喀什|kashi|ks', '昆明|kunming|km', '康定|kangding|kd', '克拉瑪依|kelamayi|klmy', '庫(kù)爾勒|kuerle|kel', '庫(kù)車(chē)|kuche|kc', '蘭州|lanzhou|lz',
'洛陽(yáng)|luoyang|ly', '麗江|lijiang|lj', '林芝|linzhi|lz', '柳州|liuzhou|lz', '瀘州|luzhou|lz', '連云港|lianyungang|lyg', '黎平|liping|lp',
'連成|liancheng|lc', '拉薩|lasa|ls', '臨滄|lincang|lc', '臨沂|linyi|ly', '芒市|mangshi|ms', '牡丹江|mudanjiang|mdj', '滿(mǎn)洲里|manzhouli|mzl', '綿陽(yáng)|mianyang|my',
'梅縣|meixian|mx', '漠河|mohe|mh', '南充|nanchong|nc', '南寧|nanning|nn', '南陽(yáng)|nanyang|ny', '南通|nantong|nt', '那拉提|nalati|nlt',
'寧波|ningbo|nb', '攀枝花|panzhihua|pzh', '衢州|quzhou|qz', '秦皇島|qinhuangdao|qhd', '慶陽(yáng)|qingyang|qy', '齊齊哈爾|qiqihaer|qqhe',
'石家莊|shijiazhuang|sjz', '沈陽(yáng)|shenyang|sy', '思茅|simao|sm', '銅仁|tongren|tr', '塔城|tacheng|tc', '騰沖|tengchong|tc', '臺(tái)州|taizhou|tz',
'通遼|tongliao|tl', '太原|taiyuan|ty', '威海|weihai|wh', '梧州|wuzhou|wz', '文山|wenshan|ws', '無(wú)錫|wuxi|wx', '濰坊|weifang|wf', '武夷山|wuyishan|wys', '烏蘭浩特|wulanhaote|wlht',
'溫州|wenzhou|wz', '烏魯木齊|wulumuqi|wlmq', '萬(wàn)州|wanzhou|wz', '烏海|wuhai|wh', '興義|xingyi|xy', '西昌|xichang|xc', '襄樊|xiangfan|xf',
'西寧|xining|xn', '錫林浩特|xilinhaote|xlht', '西雙版納|xishuangbanna|xsbn', '徐州|xuzhou|xz', '義烏|yiwu|yw', '永州|yongzhou|yz', '榆林|yulin|yl', '延安|yanan|ya', '運(yùn)城|yuncheng|yc',
'煙臺(tái)|yantai|yt', '銀川|yinchuan|yc', '宜昌|yichang|yc', '宜賓|yibin|yb', '鹽城|yancheng|yc', '延吉|yanji|yj', '玉樹(shù)|yushu|ys', '伊寧|yining|yn', '珠海|zhuhai|zh', '昭通|zhaotong|zt',
'張家界|zhangjiajie|zjj', '舟山|zhoushan|zs', '鄭州|zhengzhou|zz', '中衛(wèi)|zhongwei|zw', '芷江|zhijiang|zj', '湛江|zhanjiang|zj'];
/* 正則表達(dá)式 篩選中文城市名、拼音、首字母 */
Vcity.regEx = /^([\u4E00-\u9FA5\uf900-\ufa2d]+)\|(\w+)\|(\w)\w*$/i;
Vcity.regExChiese = /([\u4E00-\u9FA5\uf900-\ufa2d]+)/;
/* *
* 格式化城市數(shù)組為對(duì)象oCity,按照a-h,i-p,q-z,hot熱門(mén)城市分組:
* {HOT:{hot:[]},ABCDEFGH:{a:[1,2,3],b:[1,2,3]},IJKLMNOP:{i:[1.2.3],j:[1,2,3]},QRSTUVWXYZ:{}}
* */
(function () {
var citys = Vcity.allCity, match, letter,
regEx = Vcity.regEx,
reg2 = /^[a-h]$/i, reg3 = /^[i-p]$/i, reg4 = /^[q-z]$/i;
if (!Vcity.oCity) {
Vcity.oCity = {hot:{},ABCDEFGH:{}, IJKLMNOP:{}, QRSTUVWXYZ:{}};
//console.log(citys.length);
for (var i = 0, n = citys.length; i < n; i++) {
match = regEx.exec(citys[i]);
letter = match[3].toUpperCase();
if (reg2.test(letter)) {
if (!Vcity.oCity.ABCDEFGH[letter]) Vcity.oCity.ABCDEFGH[letter] = [];
Vcity.oCity.ABCDEFGH[letter].push(match[1]);
} else if (reg3.test(letter)) {
if (!Vcity.oCity.IJKLMNOP[letter]) Vcity.oCity.IJKLMNOP[letter] = [];
Vcity.oCity.IJKLMNOP[letter].push(match[1]);
} else if (reg4.test(letter)) {
if (!Vcity.oCity.QRSTUVWXYZ[letter]) Vcity.oCity.QRSTUVWXYZ[letter] = [];
Vcity.oCity.QRSTUVWXYZ[letter].push(match[1]);
}
/* 熱門(mén)城市 前16條 */
if(i<16){
if(!Vcity.oCity.hot['hot']) Vcity.oCity.hot['hot'] = [];
Vcity.oCity.hot['hot'].push(match[1]);
}
}
}
})();
/* 城市HTML模板 */
Vcity._template = [
'<p class="tip">熱門(mén)城市(支持漢字/拼音)</p>',
'<ul>',
'<li class="on">熱門(mén)城市</li>',
'<li>ABCDEFGH</li>',
'<li>IJKLMNOP</li>',
'<li>QRSTUVWXYZ</li>',
'</ul>'
];
/* *
* 城市控件構(gòu)造函數(shù)
* @CitySelector
* */
Vcity.CitySelector = function () {
this.initialize.apply(this, arguments);
};
Vcity.CitySelector.prototype = {
constructor:Vcity.CitySelector,
/* 初始化 */
initialize :function (options) {
var input = options.input;
this.input = Vcity._m.$('#'+ input);
this.inputEvent();
},
/* *
* @createWarp
* 創(chuàng)建城市BOX HTML 框架
* */
createWarp:function(){
var inputPos = Vcity._m.getPos(this.input);
var div = this.rootDiv = document.createElement('div');
var that = this;
// 設(shè)置DIV阻止冒泡
Vcity._m.on(this.rootDiv,'click',function(event){
Vcity._m.stopPropagation(event);
});
// 設(shè)置點(diǎn)擊文檔隱藏彈出的城市選擇框
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);
});
div.className = 'citySelector';
div.style.position = 'absolute';
div.style.left = inputPos.left + 'px';
div.style.top = inputPos.bottom + 'px';
div.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 childdiv = this.cityBox = document.createElement('div');
childdiv.className = 'cityBox';
childdiv.id = 'cityBox';
childdiv.innerHTML = Vcity._template.join('');
var hotCity = this.hotCity = document.createElement('div');
hotCity.className = 'hotCity';
childdiv.appendChild(hotCity);
div.appendChild(childdiv);
this.createHotCity();
},
/* *
* @createHotCity
* TAB下面DIV:hot,a-h,i-p,q-z 分類(lèi)HTML生成,DOM操作
* {HOT:{hot:[]},ABCDEFGH:{a:[1,2,3],b:[1,2,3]},IJKLMNOP:{},QRSTUVWXYZ:{}}
**/
createHotCity:function(){
var odiv,odl,odt,odd,odda=[],str,key,ckey,sortKey,regEx = Vcity.regEx,
oCity = Vcity.oCity;
for(key in oCity){
odiv = this[key] = document.createElement('div');
// 先設(shè)置全部隱藏hide
odiv.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);
odiv.appendChild(odl);
}
// 移除熱門(mén)城市的隱藏CSS
Vcity._m.removeClass('hide',this.hot);
this.hotCity.appendChild(odiv);
}
document.body.appendChild(this.rootDiv);
/* IE6 */
this.changeIframe();
this.tabChange();
this.linkEvent();
},
/* *
* tab按字母順序切換
* @ tabChange
* */
tabChange:function(){
var lis = Vcity._m.$('li',this.cityBox);
var divs = Vcity._m.$('div',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',divs[j]);
}
Vcity._m.addClass('on',this);
Vcity._m.removeClass('hide',divs[this.index]);
/* IE6 改變TAB的時(shí)候 改變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);
/* 點(diǎn)擊城市名的時(shí)候隱藏myIframe */
Vcity._m.addClass('hide',that.myIframe);
}
}
},
/* *
* INPUT城市輸入框事件
* @inputEvent
* */
inputEvent:function(){
var that = this;
Vcity._m.on(this.input,'click',function(event){
event = event || window.event;
if(!that.cityBox){
that.createWarp();
}else if(!!that.cityBox && Vcity._m.hasClass('hide',that.cityBox)){
// slideul 不存在或者 slideul存在但是是隱藏的時(shí)候 兩者不能共存
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();
/* 移除iframe 的hide 樣式 */
Vcity._m.removeClass('hide',that.myIframe);
// 下拉菜單顯示的時(shí)候捕捉按鍵事件
if(that.ul && !Vcity._m.hasClass('hide',that.ul) && !that.isEmpty){
that.KeyboardEvent(event,keycode);
}
});
},
/* *
* 生成下拉選擇列表
* @ createUl
* */
createUl:function () {
//console.log('createUL');
var str;
var value = Vcity._m.trim(this.input.value);
// 當(dāng)value不等于空的時(shí)候執(zhí)行
if (value !== '') {
var reg = new RegExp("^" + value + "|\\|" + value, 'gi');
var searchResult = [];
for (var i = 0, n = Vcity.allCity.length; i < n; i++) {
if (reg.test(Vcity.allCity[i])) {
var match = Vcity.regEx.exec(Vcity.allCity[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;
// 如果搜索數(shù)據(jù)為空
if (searchResult.length == 0) {
this.isEmpty = true;
str = '<li class="empty">對(duì)不起,沒(méi)有找到數(shù)據(jù) "<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);
// 記錄按鍵次數(shù),方向鍵
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';
},
/* *
* 特定鍵盤(pán)事件,上、下、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 下拉菜單點(diǎn)擊事件 */
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);
})
}
}
};
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java Web開(kāi)發(fā)之訪問(wèn)路徑問(wèn)題分析
這篇文章主要介紹了Java Web開(kāi)發(fā)之訪問(wèn)路徑問(wèn)題,較為詳細(xì)的分析了java web開(kāi)發(fā)過(guò)程中常見(jiàn)的絕對(duì)路徑與相對(duì)路徑使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
詳解Spring Hibernate連接oracle數(shù)據(jù)庫(kù)的配置
這篇文章主要介紹了詳解Spring Hibernate連接oracle數(shù)據(jù)庫(kù)的配置的相關(guān)資料,需要的朋友可以參考下2017-06-06
基于jsp:included的使用與jsp:param亂碼的解決方法
本篇文章是對(duì)jsp:included的使用與jsp:param亂碼的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
JSP使用JDBC連接MYSQL數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了JSP使用JDBC連接MYSQL數(shù)據(jù)庫(kù)的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了JDBC的下載,注冊(cè)及具體使用技巧,需要的朋友可以參考下2015-12-12

