要实现一个这样的交互,可以归纳下功能点:
- 浮层的显示/隐藏
- 商业区/行政区/地铁线tab切换
- 地铁线点击显示地铁站点
- 选择地标返回内容到文本框内
浮层的显示/隐藏
浮层的显示和隐藏我们通过input的focus和blur事件来做控制,这里要注意的是在显示的时候需要进行定位,通过input相对于浏览器窗口左上角的偏移加上滚动条高度(宽度)就能对浮层进行绝对定位。
var input1 = document.getElementById('input1'); var inputFocus = function(){ var rect = this.getBoundingClientRect(); //获取文本框input相对于浏览器窗口左上角的偏移 var top = rect.top + (document.documentElement.scrollTop || document.body.scrollTop), left = rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft); var style = document.getElementById('popArea').style; style.left = left + 'px'; style.top = top + this.offsetHeight + 'px'; //input相对文档的高度 + 文本框自身高度 style.display = 'block'; } var inputBlur = function(e){ document.getElementById('popArea').style.display = 'none'; } addEvent(input1, 'focus', inputFocus); //绑定focus事件 addEvent(input1, 'blur', inputBlur); //绑定blur事件 |
商业区/行政区/地铁线tab切换
实现tab一般为两种方法:给每个tab分别绑定事件或者对所有tab共同的父元素绑定一个事件(子项会动态变化或者子项过多时使用此方法),如果tab项不多时可以循环遍历来改变样式和display,反之可以使用全局变量来存放当前选中项。这里使用了前者。
var popArea = document.getElementById('popArea'); var tabs = popArea.getElementsByTagName('li'), subs = popArea.getElementsByTagName('dd'); var handlerTab = function(){ for(var i=0,l=tabs.length;i<l;i++){ if(this == tabs[i]){ //this为当前触发事件的element tabs[i].className = 'hot_selected2'; subs[i].style.display = ''; }else{ tabs[i].className = ''; subs[i].style.display = 'none'; } } } for(var i=0,l=tabs.length;i<l;i++){ addEvent(tabs[i], 'mousedown', handlerTab); //为什么用mousedown而不是click? } |
地铁线点击显示地铁站点 & 选择地标返回内容到文本框内
这两个功能都是在点击浮层时触发,并且由于浮层内容多、经常变化的特点,我们就应该选择给浮层添加事件而不是每个内容绑事件,然后根据事件源来执行相应的代码,一劳永逸。
addEvent(popArea, 'mousedown', function(e){ //为什么用mousedown而不是click? e = e || window.event; var el = e.target || e.srcElement; if (el.tagName.toLowerCase() == 'a') { switch(el.className){ //用class判断来源 /* * 地铁线点击显示地铁站点 * 这边可以视为选项卡的一种类型,即选项卡子项很多,对应显示内容不是模块之间的显示隐藏,而是获取新的HTML替换 * 选项卡选项发生改变时,通过之前记录的ID来获取element,还原该element的样式,然后记录当前子项ID并改变其样式 * 生成HTML有两种方法:一是拼写html字符串通过innerHTML一次性赋值;二是createElement节点再通过appendChild添加。从效率上说innerHTML效率更高,而拼写字符串也有多种方法,可以使用数组的join方法连接和使用"+"连接,join方法效率更高。 */ case "metro": var station = document.getElementById('metroStation'); var metroId = station.getAttribute('metroId'); if(metroId){ document.getElementById(metroId).className = 'metro'; //还原前选项卡样式 } el.className = 'metro current'; station.setAttribute('metroId', el.id); //记录当前选项卡ID var res = ['<a href="javascript:;" data="'+ el.getAttribute('metrodata') +'" title="'+ el.innerHTML +'">全部</a>']; var kw = '('+el.innerHTML+')'; var reg = new RegExp('@[^\\|]*\\|(([^\\|]*)'+ kw.replace(/([\.\\\/\+\*\?\[\]\{\}\(\)\^\$\|])/g,"\\$1") +'[^\\|]*)\\|(S\\d+)\\|[^@]*', "gi"); //通过正则来获取匹配的内容并拼写html POSITION = POSITION.replace(reg, function (_, name, label, id) { res.push('<a href="javascript:;" data="'+ _ +'" title="'+ name +'">'+ label +'</a>'); return ''; }); if(res.length){ station.innerHTML = res.join(''); station.style.display = ''; }else{ station.innerHTML = ''; station.style.display = 'none'; } break; case "metro current": break; default: //选择地标返回内容到文本框内 if(currentInput){ currentInput.value = el.getAttribute('data').split('|')[1]; } return; //直接结束事件,作用是为了触发input的blur事件 } } if(!-[1,]){ el.setCapture(); //解决IE下任然触发blur事件的bug capture = el; } e.preventDefault ? e.stopPropagation() : e.cancelBubble = true; e.preventDefault ? e.preventDefault() : e.returnValue = false; //阻止input触发blur事件 }); if(!-[1,]){ addEvent(popArea, 'mouseup', function(){ //释放鼠标捕获 if(capture && capture.releaseCapture){ capture.releaseCapture(); capture = null; } }) } |
一次鼠标点击会触发的事件有mousedown、click、mouseup,双击还有dblclick,为什么这里使用了mousedown而不是click或者其他的类型?原因是执行顺序。
(function(){ var input = document.getElementById('input'), container = document.getElementById('container'), popArea = document.getElementById('popArea'); var consoleType = function(e){ e = e || window.event; container.innerHTML += e.type + '<br/>'; } addEvent(input, 'blur', consoleType); addEvent(popArea, 'mousedown', consoleType); addEvent(popArea, 'click', consoleType); addEvent(popArea, 'mouseup', consoleType); })() |
这段代码的返回结果是mousedown、blur、mouseup、click,当我们点击浮层的同时不希望input失去焦点,只有在blur触发之前通过preventDefault()来阻止,符合条件的只有mousedown,这就是为什么我们使用mousedown而不使用click的原因。
这个在标准浏览器下是可以的,但是在IE下,这个似乎不行,我们会发现,在IE下,当我们点击这个浮层的时候,input还是失去了焦点,浮层还是隐藏了。为了解决IE下面的问题,我们需要用到IE的setCapture。其作用:http://baike.baidu.com.cn/view/1080215.htm
Demo:http://unicac.sinaapp.com/jquery/ctrip_tab/demo_tab.html