概念:
除了常见的 focus,blur 事件,DOM Level 3 事件模块 还定义了 focusin ,focusout 以及 DOMFocusIn ,DOMFocusOut 四个事件。
规范:
blur :
在这个事件触发前,元素已经失去焦点,不冒泡,同步触发。target 指向当前失去焦点的元素。
DOMFocusIn :
在这个事件触发前,元素已经得到焦点,可冒泡,同步触发。target 指向当前得到焦点的元素。
DOMFocusOut :
在这个事件触发前,元素已经没有焦点,可冒泡,同步触发。target 指向当前失去焦点的元素。
focus:
在这个事件触发前,元素已经得到焦点,不冒泡,同步触发。target 指向当前得到焦点的元素。
focusin :
在当前元素获得焦点前以及相关元素失去焦点前触发,可冒泡,同步触发。target 指向当前将要获得焦点的元素,relatedTarget 指向失去焦点的元素
focusout :
在当前失去焦点前触发,可冒泡,同步触发。target 指向当前将要失去焦点的元素,relatedTarget 指向将要失去焦点的元素。
触发顺序:
假定有两个元素 1,2,先使得1 获得焦点再使得 2 获得焦点,那么事件的触发顺序以及触发源为
focusin -> 元素 1
元素 1 获得焦点
focus -> 元素 1
DOMFocusIn -> 元素 1
focusout -> 元素 1
focusin -> 元素 2
元素 1 失去焦点
blur -> 元素 1
DOMFocusOut ->元素 1
元素 2 获得焦点
focus -> 元素 2
DOMFocusIn -> 元素 2
兼容性测试:
测试代码:
- <div tabindex="-1" id='a1'>
- area 1
- </div>
- <div tabindex="-1" id='a2'>
- area 2
- </div>
<div tabindex="-1" id='a1'> area 1 </div> <div tabindex="-1" id='a2'> area 2 </div>
通过调用 focus()方法来进行焦点转移,(也可通过鼠标直接点击,但是就不能测试是否同步了)关于 div 的焦点可见这里 。
firefox 3.6.12
没有 focusin,focusout,DOMFocusIn,DOMFocusOut事件,focus,blur为同步触发
触发顺序为:
- a1 focus target:a1
- a1 focus relatedTarget:
- keydown : 49
- a1 blur target:a1
- a1 blur relatedTarget:
- a2 focus target:a2
- a2 focus relatedTarget:
- keydown : 50
a1 focus target:a1 a1 focus relatedTarget: keydown : 49 a1 blur target:a1 a1 blur relatedTarget: a2 focus target:a2 a2 focus relatedTarget: keydown : 50
chrome 9.0
全部事件都实现了,且都为同步触发,但是触发顺序和规范不一致,并且没有定义 relatedTarget 事件属性:
- a1 focus target:a1
- a1 focus relatedTarget:
- a1 focusin target:a1
- a1 focusin relatedTarget:
- a1 DOMFocusIn target:a1
- a1 DOMFocusIn relatedTarget:
- keydown : 49
- a1 blur target:a1
- a1 blur relatedTarget:
- a1 focusout target:a1
- a1 focusout relatedTarget:
- a1 DOMFocusOut target:a1
- a1 DOMFocusOut relatedTarget:
- a2 focus target:a2
- a2 focus relatedTarget:
- a2 focusin target:a2
- a2 focusin relatedTarget:
- a2 DOMFocusIn target:a2
- a2 DOMFocusIn relatedTarget:
- keydown : 50
a1 focus target:a1 a1 focus relatedTarget: a1 focusin target:a1 a1 focusin relatedTarget: a1 DOMFocusIn target:a1 a1 DOMFocusIn relatedTarget: keydown : 49 a1 blur target:a1 a1 blur relatedTarget: a1 focusout target:a1 a1 focusout relatedTarget: a1 DOMFocusOut target:a1 a1 DOMFocusOut relatedTarget: a2 focus target:a2 a2 focus relatedTarget: a2 focusin target:a2 a2 focusin relatedTarget: a2 DOMFocusIn target:a2 a2 DOMFocusIn relatedTarget: keydown : 50
只是将 focusxx DOMFocusXx 作为对应 focus,blur 的后面事件触发,没有使用意义。
ie
ie 支持 focusin ,focusout,并且同步触发顺序和规范一致,但是没有 target 以及 relatedTarget 事件属性。
对于 focus 以及 blur 为异步触发,同样没有 target 以及 relatedTarget 事件属性。
不支持 DOMFocusIn,DOMFocusOut。
触发顺序:
- a1 focusin target:null
- a1 focusin relatedTarget:
- keydown : 49
- a1 focus target:null
- a1 focus relatedTarget:
- a1 focusout target:null
- a1 focusout relatedTarget:
- a2 focusin target:null
- a2 focusin relatedTarget:
- keydown : 50
- a1 blur target:null
- a1 blur relatedTarget:
- a2 focus target:null
- a2 focus relatedTarget:
a1 focusin target:null a1 focusin relatedTarget: keydown : 49 a1 focus target:null a1 focus relatedTarget: a1 focusout target:null a1 focusout relatedTarget: a2 focusin target:null a2 focusin relatedTarget: keydown : 50 a1 blur target:null a1 blur relatedTarget: a2 focus target:null a2 focus relatedTarget:
updated : 2010-12-10
一点奇怪的问题:在 ie9 pp7 下,当点击按钮,聚焦页面iframe的body时,iframe body 的 focusin 事件也是异步的!
例如会出现序列
- before click
- after click
- body focusin
- body focus
before click after click body focusin body focus
而不是
- before click
- body focusin
- after click
- body focus
before click body focusin after click body focus
模拟 focusin/out
这次反过来了,在 focus 或 blur 前有事件触发并且支持子元素冒泡确实非常有用,可是目前 firefox 与 chrome 都不支持或者 触发 顺序不对,另一方面由于标准浏览器支持捕获capture,而捕获阶段恰恰在冒泡阶段前,虽然 focus/blur 不会冒泡,但是捕获阶段还是存在的,那么
handler1
- element.addEventListener("focus",function(){
- // handler 1
- },true);
element.addEventListener("focus",function(){ // handler 1 },true);
也就比 handler2
- element.addEventListener("focus",function(){
- // handler 2
- },false);
element.addEventListener("focus",function(){ // handler 2 },false);
先触发了,也就相当于 ie 下的
- element.attachEvent("onfocusin",function(){
- //handler1
- });
element.attachEvent("onfocusin",function(){ //handler1 });
并且由于捕获时子元素获得焦点也会通知父元素,那么也就达到了 ie 以及规范规定的冒泡效果,这也正是 kissy 事件模块 用来全平台兼容 focusin/out 的方法了。
应用:
通过监控 form 即可监控各个输入域,当失去焦点以及得到焦点时进行处理:
- <form id='f'>
- <input id='i'/>
- <input id='i2'/>
- </form>
- <script>
- KISSY.use("node",function(S,Node){
- Node.one("#f").on("focusin",function(ev){
- console.log("focusin : "+ev.target.attr("id"));
- });
- Node.one("#f").on("focusout",function(ev){
- console.log("focusout : "+ev.target.attr("id"));
- });
- });
- </script>
<form id='f'> <input id='i'/> <input id='i2'/> </form> <script> KISSY.use("node",function(S,Node){ Node.one("#f").on("focusin",function(ev){ console.log("focusin : "+ev.target.attr("id")); }); Node.one("#f").on("focusout",function(ev){ console.log("focusout : "+ev.target.attr("id")); }); }); </script>