如何在事件代理中正确使用 focus 和 blur 事件

什么是事件代理(Event Delegation)?
如果不太了解的朋友,可详细阅读:《Event delegation in JavaScript》,这里不再累述。
首先让我们一起来回顾一些常识:

通常支持事件冒泡(Event Bubbling)的事件类型为鼠标事件和键盘事件,例如:mouseover, mouseout, click, keydown, keypress。
接口事件则通常不支持事件冒泡(Event Bubbling),例如:load, change, submit, focus, blur。

很明显:focus 和 blur 都属于不支持冒泡的接口事件。既然都不支持冒泡,那又如何实现事件代理呢?
可以换个角度,逆向思维,尝试事件捕获(Event Capturing,除了IE,现在流行的标准浏览器均支持)。
测试后会发现,如果你捕获 focus 或 blur 事件,目标元素的祖先元素均执行事件函数。至于为什么?或许是实现的一个 BUG。
el.addEventListener(‘focus’, focusHandler, t... 13 条评论 »

修复 jQuery 中 isFunction 方法的 BUG

jQuery 1.4 源码 449 行(core.js 431 行),判断是否为函数的方法如下(思路来源于 Douglas Crockford 的《The Miller Device》):
isFunction: function( obj ) {
return toString.call(obj) === “[object Function]“;
},
同时 jQuery 的作者也作了部分注释:
See test/unit/core.js for details concerning isFunction. Since version 1.3, DOM methods and functions like alert aren’t supported. They return false on IE (#2968).
即:此方法在 IE 下无法正确识别 DOM 方法和一些函数(例如 alert 方法等)。
为什么会这样呢?
详细看测试页面:http://www.planabc.net/demo/isfunction/
会发现在 IE [...]

... 8 条评论 »

如何将函数的实际参数转换成数组

实际参数在函数中我们可以使用 arguments 对象获得 (注:形参可通过 arguments.callee 获得),虽然 arguments 对象与数组形似,但仍不是真正意义上的数组。
值得庆幸的是,我们可以通过数组的 slice 方法将 arguments 对象转换成真正的数组:
var args = Array.prototype.slice.call(arguments, 0);
对于slice 方法,ECMAScript 262 中 15.4.4.10 Array.prototype.slice (start, end) 章节有备注:
The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a [...]

... 23 条评论 »

删除数组中重复项(uniq)

首先让我们看下 YUI 是如何处理的:
var toObject = function(a) {
var o = {};
for (var i = 0; i < a.length; i = i+1) {
o[a[i]] = true;
}
return o;
};

var keys = function(o) {
var a=[], i;
[...]

... 30 条评论 »

Firefox 的 Jetpack 扩展案例分析:Gmail 邮件提醒

Gtalk 软件的最下方有个很好又很实用的功能,就是 Gmail 邮件提醒功能。会定时更新你 Gmail 中未读新邮件的数量。

试想如果我们将此功能移植到 Firefox 上一定有趣!
第一步,在状态栏中显示图标和数据。
通过 《如何创建 Firefox 的 Jetpack 扩展》 这篇文章,我们可以轻易的创建:
jetpack.statusBar.append({
html: ‘<img src=”http://mail.google.com/mail/images/favicon.ico”/><span id=”count”></span>’, //Gmail邮件图标和未读新邮件数
width: 55, //状态栏上的宽度为55
onReady: function(widget) {
$(“#count”, widget).css({ //给未读新邮件数添加样式
[...]

... 12 条评论 »

如何创建 Firefox 的 Jetpack 扩展

Firefox 的 Jetpack 可以让我们很轻松地创建 Firefox 插件,仅通过已掌握的前端技能(HTML/CSS/JS),估计让人更兴奋的一点—— Jetpack 还集成了 jQuery 框架。
Adobe Air 也好,Web OS 也好, Jetpack 也好,至少让我们肯定一点,前端的价值将会在机遇中越来越大的被展现。
下面让我们一起来看看如何一步步创建你的第一个 Firefox 的 Jetpack 扩展:
第一步:安装 Jetpack 插件
Jetpack 插件地址:https://jetpack.mozillalabs.com/install.html
安装完成 Jetpack 插件后,你就可以通过在地址栏中输入 about:jetpack 来访问 Jetpack 本地界面了。

第二步:创建 planabc.js 文件。
planabc.js 的详细代码为:
jetpack.statusBar.append({
html: ‘<img src=”http://www.planabc.net/favicon.ico”/>’,
width: 16,
onReady: function(widget){
[...]

... 13 条评论 »

判断 iframe 是否加载完成的完美方法

一般来说,我们判断 iframe 是否加载完成其实与 判断 JavaScript 文件是否加载完成 采用的方法很类似:
var iframe = document.createElement(“iframe”);
iframe.src = “http://www.planabc.net”;

if (!/*@cc_on!@*/0) { //if not IE
iframe.onload = function(){
alert(“Local iframe is now loaded.”);
};
} else {
iframe.onreadystatechange = function(){
if [...]

... 24 条评论 »

YUI Compressor 组件压缩 JavaScript 的一些原理

YUI Compressor 压缩 JavaScript 的内容包括:

移除注释
移除额外的空格
细微优化
标识符替换(Identifier Replacement)

YUI Compressor 包括哪些细微优化呢?

object["property"] ,如果属性名是合法的 JavaScript 标识符(注:合法的 JavaScript 标识符——由一个字母开头,其后选择性地加上一个或者多个字母、数字或下划线)且不是保留字,将优化为: object.property
{“property”:123} ,如果属性名是合法的 JavaScript 标识符且不是保留字,将优化为 {property:123} (注:在对象字面量中,如果属性名是一个合法的 JavaScript 标识符且不是保留字,并不强制要求用引号引住属性名)。
‘abcd\’efgh’,将优化为 “abcd’efgh”。
“abcd” + “efgh”,如果是字符串相连接,将优化成 “abcdefgh”(注:所... 7 条评论 »

模拟兼容性的 addDOMLoadEvent 事件

由于 window.onload 事件需要在页面所有内容(包括图片等)加载完后,才执行,但往往我们更希望在 DOM 一加载完就执行脚本。其实在现在大部分主流浏览器上(Firefox 3+,Opera 9+,Safari 3+,Chrome 2+)都提供了这一事件方法:addDOMLoadEvent。
document.addEventListener(“DOMContentLoaded”, init, false);
那对于 IE 我们如何模拟 addDOMLoadEvent 事件呢?
Matthias Miller 最早提供了如下的解决方案:
// for Internet Explorer (using conditional comments)
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById(“__ie_onload”);
script.onreadystatechange = function() {
if (this.readyState == “complete”) {
init(); // call the onload handler
[...]

... 10 条评论 »

JavaScript 获取事件对象的一个注意点

平时我们获取事件对象一般写法如下:
function getEvent(event) {
return event || window.event // IE:window.event
}
如果没有参数,也可写成(非IE :事件对象会自动传递给对应的事件处理函数,且为第一个参数):
function getEvent() {
return arguments[0] || window.event // IE:window.event
}
这样的写法在除 Firefox(测试版本:3.0.12,下同) 外的浏览器上运行都不会有问题,但 Firefox 为什么例外呢?让我们这样一种情形:
<button id=”btn” onclick=”foo()”>按钮</button>

<script>
function foo(){
var e = getEvent();
alert(e);
}
</script>
运行结果在 Firefox 中是 undefined,为什么呢?
在 Firefox 中调用其实是这样的,先调用执行的是:
function onclick(event) {
foo();
}
然后... 18 条评论 »