靠谱的软件下载站
当前位置:  IEfans/IE专区/IE相关/从浏览器的focus blur说起

从浏览器的focus blur说起

IE相关 互联网 2010-04-28 阅读(3427)
“焦点事件”对于提高用户体验无疑有着至关重要的作用,但是使用的同时往往也会给我们带来一些困扰。浏览器加载的时候可能出现并非我们想要的效果。还有可能在IE浏览器下能够正常运行的时候,在别的浏览器下未必没有问题。先说个借助“焦点事件”解决一个弹出菜单问题的另类方案。以往我们对于弹出式菜单的关闭有以下几个方案: 1.当鼠标离开当前div时菜单即隐藏或者setTimeout隐藏如果鼠标及时的回到菜单上清除setTimeout的计时器。 2.注册document.onclick事件的同时禁止div的click事件冒泡,或者判断事件源是否是div或div的子节点。 3.当菜单div显示时,在div的前面插入一个mask层使其覆盖整个浏览器客户区.注册mask层的onclick隐藏div即可。 这些方法各有利弊方案1用户体验稍差,方案2一旦某元素禁止了click事件的冒泡则会失效而方案3显然用户体验稍微有点问题即mask层阻断了其他元素的所有事件这有时候是不能容忍的问题. 那么这里我们提出方案4借助div.onblur来弄...但是一些问题也随之而来... 首先因为div默认不支持focus(非ie)状态所以更谈不上blur了。(ie虽然默认支持但,默认仍然不支持blur) 一个非常有趣的方法是给div设置tabIndex一个自然数值(当然不要超过Math.max貌似和z-index最大值一样..没测试...偷懒一下)即可让所有主流浏览器的div具备focus和blur的能力.这样我们就可以给div.onblur=function(){this.style.display='none';}就ok啦! 但是事情远远没有完...一个问题是div一旦支持了focus那么当获取焦点后.除了opera浏览器以外其他主流浏览器都会出现outline,firefox和ie是虚线safari、chrome是他们特殊的发光效果的蓝色或黄色的outline...这显然是不能容忍的...幸运的是除了ie6ie7以外甚至是ie8我们都可以div{outline:none;}解决. 那么ie6和ie7要如何解决呢?答案是一个ie特有的属性---hidefocus="true"即我们只要divElement.hidefocus=true;搞定... 接下来是这个方案的致命缺点了.当用户按tab键时就有可能使div获取到焦点.(尤其是非ie浏览器即使element.style.display='none'也可以保持焦点.) 或丢失焦点这显然是我们不希望看到的.... 解决办法只有给document注册keydown了...(opera要注册keypress原因是opera的keydown不是持续性事件.和其他浏览器有些区别.)然后通过当前document.activeElement(webkit引擎貌似不支持...那么只好去给div前一个具备tabIndex的元素独立注册onfocus并使用一个变量保存其focus状态或者可以考虑所有浏览器统一这样做全部放弃使用document.activeElement)判断下一个是否会是我们的div那么就让div的下一个具备tabIndex的元素获取焦点就好了. 虽然看起来还不错但最终我们可能还要遍历当前页中所有表单元素肯能存在的tabIndex值.去自动判断div前一个具备tabIndex的元素是否存在并找到他..这样才能把此方案封装成控件.一个取巧的办法是我建议给divElement.tabIndex=Math.max;这样我们就不再需要考虑表单元素们是不是有tabIndex的值或者是否都是默认的0..而仅仅需要这样: var len,elem;  document.forms[0] && (len=document.forms[0].length)>0 && ( (elem=document.forms[0][len-1]).onfocus=function(e){... 维护this元素是否具备焦点的变量=ture;} );  elem.onblur=function(e){. 维护this元素是否具备焦点的变量=false;}; 然后别忘了判断如果keyCode==9的情况下我们的divElement是不是具备焦点如果是则禁止浏览器默认行为使tab更换焦点失败.保持住我们的焦点. 到了这里似乎我们解决了问题但是别忘了anchor元素等有些元素仍然可以通过tab键获取焦点.那么我们要还要处理所有的anchro标签么?显然这样不够好.另一个不错的思路是当我们的divElement.style.display=='block'时...我们再设置其tabIndex当'none'时删除掉该属性.这个是最好办法不是么? 各种方案有自己的有点和缺点..也许你会从中找到最适合自己需求的解决方案.或找到更完美的办法...ok就倒这里吧. 这是一个典型的借助focusblur解决问题的例子...暂时就到这里我们接着下个话题来说. 接着我们说一个focusblur的优化.这个方案是我的朋友wait和我提起的..我觉得很有价值借花献佛的拿出来说一下. 假如我当前页表单中有几十个textbox我想对他们做onfocus和onblur监听...然后做一些事情 这时候我们就是在没有必要吧这几十个都注册一下而仅仅给document注册就好...但问题在于focus和blur都是不冒泡的事件。没办法传到document上... 非ie的解决办法是document.addEventListener第三参数true.即不采用冒泡模式而改用捕获模式..即让事件流从document流回事件源...这样我们注册到document上的onfocus就可以监听到focus事件了... 而ie呢不支持捕获模式...但是ie支持两个特别的事件focusin focusout这两个事件对应focus和blur,但是他们是支持冒泡的....嘿嘿到了这里剩下的就只是函数内部判断事件源是否是我们期望的东西并写相应逻辑即可.是不是很好呢? 最后在大多数浏览器中一个有趣的现象是element.onblur(){这里是不能在此让自己this.focus()的....}原因在于当某个事件发生后导致了其他节点获取焦点的话在这之前就会发生element.blur然后才会发生otherElement.focus所以在element.blur发生时设置focus()并没有阻止导致otherElement获取焦点的事件...那么他仍然会在最后把焦点房到otherElement上....解决办法setTimeout...延迟处理... 焦点事件对于window对象也是很有意义的事情...比如我们现在需要dragAndDrop功能时当drag时我们切换窗口到别的程序并松开鼠标键时再回到网页..会发现之前的mouseup没有被捕捉然后会发现被拖拽层一直跟着鼠标跑...解决办法就是window.onblur=function(){obj.drop();} 接着有时候我们不希望ie中anchor元素被点时旁边出现讨厌的outline边框....如果你知道这个边框出现的原因同样是因为获取到焦点的话你一定就知道如何解决这个问题了。你也会明白为什么有些站点会使用a{outline:none;star:expression(this.onFocus=this.blur());}来解决这个问题了吧?其实就是强制anchor获取焦点后立刻blur()而已...

标签:IE相关浏览器focus blur

Copyright © 1998-2017 www.iefans.net All Rights Reserved 湘ICP备13012168号-17