Javascript代码
function log(str){
(′.log′).append(
(‘
}
(‘.parent′).focusin(function()log(‘divfocusin′);).focusout(function()log(‘divfocusout′);).focus(function()log(‘divfocus′);).blur(function()log(‘divblur′););
(‘input’)
.focusin(function(){log(‘input focusin’);})
.focusout(function(){log(‘input focusout’);})
.focus(function(){log(‘input focus’);})
.blur(function(){log(‘input blur’);});
执行结果
clipboard.png
从执行结果可以看到4个事件的执行顺序,同时也可以看到 focus/blur是不支持冒泡的,所以.parent 元素绑定的focus和blur事件回调并没有触发。
focusin 与 focusout的浏览器支持
几乎所有的浏览器都支持focus和blur事件,但对于focusin和focusout 就不是这样理想了。Firefox中不支持focusin和focusout事件;chrome和safari中只有通过addEventListener方式绑定事件才能正常使用,其他方式绑定都不行;
面对这样的浏览器支持似乎很头痛,庆幸的是jQuery对focusin和focusout做了兼容,使用 .focusin和 .focusout实现事件绑定,在所有浏览器中都支持;
focus和blur如何实现事件代理
事件代理简单来说就是将子元素事件绑定在祖先元素上,之所以能够这样做,得益于标准事件模型的捕获和冒泡。我们知道在标准事件模型中,一个事件的触发会经历三个阶段:捕获阶段+目标阶段+冒泡阶段,有了捕获和冒泡才能实现事件代理。由前面介绍可知,focus和blur不支持冒泡,但其支持捕获,但 IE 中事件模型没有捕获只有冒泡,所以在非IE浏览器中可以通过在捕获阶段进行事件绑定实现事件代理。那么针对IE浏览器怎么实现呢?通过支持冒泡的是focusin和focusout实现就可以了。代码示例如下:
html 代码
javascript 代码
function addColor(){
this.style.background=”red”;
}
var form = document.forms[‘form’];
if (form.addEventListener) { // 非 IE 浏览器
form.addEventListener(‘focus’, addColor, true);
}else{ // IE
form.onfocusin = addColor
}
哪些元素是focusable的
在本文的第一小节提到了一个 focusable 元素的概念,我觉得有必要在这里解释一下什么是focusable 元素。
默认情况下,只有部分html元素能获得鼠标焦点如input,很大一部分html元素是不能获得鼠标焦点的如div,这些能够获得鼠标焦点的元素就是focusable 元素。要想一个元素获得焦点,可以通过三种方式:
鼠标点击
tab 键
调用focus()方法
那么默认情况下,哪些元素是focusable 元素
window:当页面窗口从隐藏变成前置可见时,focus 事件就会触发
表单元素(form controllers):input/option/textarea/button
链接元素(links):a标签、area标签(必须要带 href 属性,包括 href 属性为空)
设置了 tabindex 属性(tabindex 值非-1)的元素
设置了contenteditable = “true”属性的元素
tabindex属性
默认情况下就能 focusable 的元素太少,如果想让一个 div 元素成为 focusable 的元素怎么做呢?很简单,设置 tabindex 属性即可!
tabindex 有2个作用:
使一个元素变成 focusable
只要在元素上设置了 tabindex 属性,不管此属性的值设为多少,此元素都将变成focusable元素。
定义多次按下 TAB 键时获得焦点的元素顺序
tabindex 属性的值可以正数、0、负数,当多次按下TAB键,首先是tabindex为正数的元素获得焦点,顺序是:tabindex=1、tabindex=2、tabindex=3、tabindex=…,最后是tabindex=0的元素获得焦点。注意:tabindex为负数的元素不能通过 TAB 键获得焦点,只能通过鼠标点击或者调用focus()方法才能获得焦点。示例代码如下:
- One
- Zero
- Two
- Minus one
- Minus two