Delegation

因为工作的原因,不得不用YUI。以YUI 2为例吧,动态创建select元素,并绑定change事件。动态创建元素需要用delegate方法来绑定事件,一般的框架都提供了该方法。

selectWrap.delegate('change', function () {
    alert(this.get('value'));
};

Demo-YUI

但是在IE下无效。于是想起了框架之神jQuery,jQuery果然是无敌的,在IE毫无问题。

selectWrap.delegate('select', 'change', function(){
    alert($(this).val());
});

Demo-jQuery

Delegation

对于框架中的delegate方法一直没有研究过,意识中delegate就用于动态创建元素的绑定事件。其实delegation还有很多好处:

  1. Fewer functions to manage.
  2. Takes up less memory.
  3. Fewer ties between your code and the DOM.
  4. Don’t need to worry about removing event handlers when changing the DOM via innerHTML.

摘自《Event delegation in JavaScript》。

Delegation实现的原理这篇文章也有详细的介绍,主要基于事件中的冒泡模式,各个框架也都采用了这个模式。但是为什么change不行呢,主要就出在冒泡上。在W3C Event中,change事件是有冒泡模式的;但IE Event,change事件是没有冒泡模式的,所以IE下需要特殊处理。其实除了change,常用的focus, blur也都是没有冒泡模式的,而且在IE和非IE下都没有。

《Delegating the focus and blur events》中也提到了这个问题,它以focus为例。主要解决方法是,在非IE下,采用捕获模式;在IE下,使用了IE了私有事件onfocusin和onfocusout。

那么无敌的jQuery是怎么解决这些问题呢?看jQuery的源代码,你会发现实现delegate的兼容性,其实需要注意的坑很多。jQuery主要做了三方面的fix:

// IE submit delegation
// IE change delegation and checkbox/radio fix
...
jQuery.event.add( this, "beforeactivate._change", function( e ) {
	var elem = e.target;
	if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
		jQuery.event.add( elem, "change._change", function( event ) {
                if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
				jQuery.event.simulate( "change", this.parentNode, event, true );
			}
		});
		elem._change_attached = true;
	}
});
...
// Create "bubbling" focus and blur events

参考jquery-1.7.1.js,对于change事件,在IE下使用私有事件beforeactivate。

E.on(selectWrap, 'beforeactivate', function(e){
	var ele = E.getTarget(e);
	if(!ele._change_attached) {
		E.on(ele, 'change', function(e){
			alert(this.value);
		});
		ele._change_attached = true;
	}
});

Demo-YUI-fix

重点

当把本地Demo-YUI页面传到服务器时,在IE下居然生效了,囧~在本地测试的时候,通过虚拟机访问本机上测试页面,就是不行,测试过click事件等等都是可以的;但是把测试页面放在虚拟机下的目录,change事件就可以了。这是什么原因啊,不研究了,累人。看来误会YUI了,没有仔细读YUI的代码,YUI还是一样强大!变态的虚拟机。但是除了对YUI的误解,其他内容真实可信。

参考资料:

Event delegation in JavaScript

Delegating the focus and blur events

DHTML Events

Document Object Model Events

关于iframe

一. iframe获取父级页面对象

在iframe页面中,

window.parent: 获取父级页面的window对象。

window.frameElement: 获取父级页面对iframe对象的引用,就如在父级页面document.getElementById(iframeId)。其实每个window都有frameElement,当它不被作为iframe引用时,该属性就为null或者undefined。PS:之前没有发现这个用法,很有用。

二. 父级页面获取iframe对象

在父级页面中,

获取window对象:

document.getElementById(iframeId).contentWindow: 获取window对象,虽然不是标准方法,但是所有的浏览器都支持。

document.getElementById(iframeId).contentDocument.parentWindow: 获取window对象,但是没有浏览器支持parentWindow属性,只见《Iframes, onload, and document.domain》提过。

window.frames[iframeName/index]: 获取window对象。

其实很好玩,window.frames[iframeName/index].frameElement == document.getElementById(iframeId),

获取document对象:

document.getElementById(iframeId).contentDocument: 获取document对象,且是W3C的标注方法,但是IE6、7不支持。

document.getElementById(iframeId).contentWindow.document: 获取document对象。

window.frames[iframeName/index].document: 获取document对象。

三. 跨域的限制

对于不同域之间的访问,浏览器都是做了限制,《About Cross-Frame Scripting and Security》。在iframe中,只能设置父级页面的location.href属性,但是不能读取,其他属性则都不能访问。

  • window.location.href 可写不可读;
  • window.location除href之外的属性 禁止;
  • document.location.href 可写不可读;
  • document.location除href之外的属性 禁止;

如何突破跨域的限制,是另一个话题。

四. iframe的load事件

根据《Iframes, onload, and document.domain》文章所提,主要有两种方法。

方法一

在iframe的window.onload中触发父级页面定义的方法。这个方法的缺点就是要在iframe页面中增加代码,优点也是显而易见的。这是作者逆向思维的产物。

方法二

var iframe = document.createElement("iframe");
iframe.src = "simpleinner.htm";
if (iframe.attachEvent){
    iframe.attachEvent("onload", function(){
        alert("Local iframe is now loaded.");
    });
} else {
    iframe.onload = function(){
        alert("Local iframe is now loaded.");
    };
}
document.body.appendChild(iframe);

《判断 iframe 是否加载完成的完美方法》中也提到方法二是很完美的,但文中提到“ 因为 readystatechange 事件相对于 load 事件有一些潜在的问题”,一直不明白readystatechange存在什么问题。

在另一篇文章中看到两篇引用。OnReadyStateChange and OnLoad Events Not Fired for an IFrame 和 document.readyState Not in Sync with Download in IFrame。大体是讲iframe不一定触发OnReadyStateChange 和 OnLoad事件,以及readystate与iframe的实际状态并不同步。我想大概是这个原因吧。

主要参考:

Iframes, onload, and document.domain
【翻译】Iframes, onload, and document.domain

    明朝那些人

    第一次较为完整阅读一部有关历史的书《明朝那些事儿》,除了愧于自己历史知识的贫乏,也受到了不少震撼教育,认识了很多奇特的人。

    最后还是没有看完结局,实在不忍。已经知道这个朝代的结局是毁灭,终不忍看着它一点点被毁灭,女生毕竟还是感性的。看完后也想留下什么,虽然不是评论,因为我还远远不够格,只是记录一些比较奇特的人、比较深刻的语句,用于回味。

    以下段落全部摘自《明朝那些事儿》

    于谦

    北京保卫战——这场战争真正向我们讲述的并不是王侯将相的丰功伟绩,而是一个关于勇气和决心的故事,是一个在绝境下始终坚持信念的传奇。

    无论在多么绝望的情况下,也不要放弃希望,坚持下去,就一定能够创造奇迹。

    于谦用他的行为为我们证明了这一真理。

    王守仁——知行合一

    四方英杰,各有异同,议论纷纷,多言何益——王守仁一生的注解

    前进的潮流是无法阻挡的,正如同王守仁的光芒,纵然历经千年,饱经风雨,却终将光耀于天下万物之间。

    无善无恶心之体,有善有恶意之动,知善知恶是良知,为善去恶是格物——心学四诀

    鸟,吾知其能飞;鱼,吾知其能游;兽,吾知其能走。走者可以为罔,游者可以为纶,飞者可以为矰。至于龙吾不能知,其乘风云而上天。——《史记·老子韩非例传》

    杨一清

    即使全天下的人都误解了你,我也理解你的言行,明了你的用心,我知道,你一直在屈辱中等待着。

    无论何时何地,在最终胜负显现之前,绝不能押上所有的筹码——洛克菲勒。

    历史一次又一次地告诉了我们这样一个真理:正义合公道或许会迟到,却绝不会旷课。

    徐阶

    有时候,天堂到地狱只有一步之遥。

    可是人生最痛苦的地方就在于,明明已经无法忍受,却还要忍受下去。

    胸怀天下,舍生取义的绝对道德确实是存在的,可惜的这玩意太高级,付出的代价太高,从古自今,除了个别先进分子外,大多数人都不愿意消费。

    利益,只有充足的利益,才有驱动人们的魔力,这就是这个世界的真实面目,极其的残酷,却异常的真实。

    在这个残酷的现实面前,徐阶终于明白了知行合一的真意,无论有多么伟大正真的理想,要实现它,还必须懂得两个字——变通。只有变通,只有切合实际的行动,才能适应这个变化万千的世界。

    贪官奸,清官要比贪官更奸——九品芝麻官。

    戚继光

    万众一心兮群山可撼,惟忠与义兮气冲斗牛。主将亲我兮胜如父母,干犯军法兮身不自由。号令明兮赏罚信,赴水火兮敢迟留!上报天子兮下救黔首,杀尽倭奴兮觅个封侯。

    海瑞——奇怪的人

    海纳百川,有容乃大。壁立千仞,无欲则刚。

    海瑞确实没有什么欲望,他唯一的工作动力就是工作,在他看来,自己既然拿朝廷的工钱,就要给朝廷干活,升官发财与他毫无关系。

    你是个好人,却并无用处——《围城》。

    张居正——伟人

    人天生,并将永远,是自私的动物——《国富论》。

    试问有谁愿意为了一个素不相识的人去拼搏、奋斗,付出自己的一切努力、心血乃至生命?

    他们甘愿牺牲自己的一切,只是为了别人的利益。这个特殊的群体,我们通常称之为伟人。

    只有当你知道,他是一个正常人,有正常的欲望,有自己的小算盘,有过犹豫和挣扎,有过贪污和污点,你才能明白,那个不顾一切,顶着压力坚持改革的张居正,到底有多么伟大。

    所有的英雄,都是平凡的人。千回百转,千锤百炼,矢志不渝,如此而已。

    他是一个天才,生于纷繁复杂之乱世,身负绝学,以一介草民闯荡二十余年,终成大器。

    他敢于改革,敢于创新,不惧风险,不怕威胁,是一个伟大的改革家,他也有缺点,他独断专行,待人不善,生活奢侈,表里不一,是个道德并不高尚的人。

    一句话,他不是好人,也不是坏人,而是一个复杂的人。

    十年前,当我即将踏入大学校园时,在一个极为特殊的场合,有一个人对我说过这样一番话:

    你还很年轻,将来你会遇到很多人,经历很多事,得到很多,也会失去很多,但无论如何,有两样东西,你绝不能丢弃,一个叫良心,另一个叫理想。

    我记得,当时我碍于形势,连连点头,虽然我并不知道这句话的真实含义。

    一晃十年过去了,如他所言,我得到了很多,也失去了很多,所幸,这两样东西我还带着,虽然不多,总算还有。

    当然,我并不因此感到自豪,因为这并非是我的意志有多坚强,或是人格有多高尚,唯一的原因在于,我遇到的人还不够坏,经历的事情还不够多,吃的苦头还不够大。

    他用他的人生告诉我们,良知和理想是不会消失的,不因富贵而逝去,不因权势而凋亡。

    不是好人,不是坏人,他是一个有理想,有良心的人。

    杨涟——纯粹的人。

    纯粹的人,是这个世界上最可怕的人,他们的一生,往往只有一个目标,为了达到这个目标,他们可以不择手段,不顾一切,他们无法被收买,无法被威逼,他们不要钱,不要女色,甚至不要权势和名声。

    在他们的世界里,只有一个目标,以及坚定的决心和意志。

    摘抄完毕。

    这个朝代出现太多奇特的人,刘基、徐达、蓝玉、解缙、常遇春、郑和、袁崇焕、郑成功、杨廷和、李东阳、陶行知、李时珍、徐霞客、徐光启、吴承恩、唐伯虎 ⋯⋯这是一个光辉耀眼的朝代,但是历史总是惊人的相似。最近网上有一篇文章《200多年前一个英国人就看透了中国》里提到,“中国的历史从本质上看是没有 历史的,它只是君主覆灭的一再重复而已,任何进步都不可能从中产生。千百年来在广阔的土地上重复庄严的毁灭,而又在本质上毫无变化”。虽然结论太绝对化, 但是又不无道理。历史只是单调重复着,历史中相同的错误和杯具也总是重复上演,只有历史中的人能够给我们带来些许惊喜。让我们记住这些人吧。

    2010年总结

    又到了写总结的时候了。看了20082009的总结,觉得时间过的很快,也发现自己身上的一些变化。看来记录变化还是很有必要的。2010年又发生了什么了?

    工作

    年初开始打算换工作,但是过程并不顺利。最有把握的一次面试被拒之后让我很郁闷,觉得这就是世界末日,对自己也没有信心,一度想放弃杭州的面试(因为觉得机会渺茫,又要长途跋涉,结果早上到了杭州,晚上就回广州了)⋯⋯但现在明白了最痛苦的时候就是转折的开始。我还是离开广州,到了杭州。

    离开一座城市,就会想念这座城市的种种的好。广州给很多人的印象是乱,空气质量不适合人类居住。但我却觉得这座城市很好,交通便利、生活设施齐全、最重要的是冬天里它也是一座很温暖的城市。

    杭州给很多人的印象是天堂,适合人类居住。但是我却还没适应这座城市。也有些人对这座城市没有认同感,但依然选择留下,很无奈。我希望我能找到这座城市的美好的地方。

    新的生活,新的工作开始了。后面没有给我太多思考的时间,开始了一段比较忙碌、多变的工作生活(价值观里的拥抱变化,应该是点到频率最高的)。到目前为止我适应了,也有一定的成效。但是也开始迷茫,接下来的目标呢?

    阅读

    前一段开始看《明朝那些事》。很少看历书的我,有很多触动,原来自己知道的这么少。我从来没有如此强烈的感觉到阅读的重要性。每当有这种强烈醒悟的时候,我都会觉得自己白活了。自己生活的轨迹正在以蜗牛的速度慢慢前行。醒悟慢总比没醒悟的好。2011年开始竭尽所能的疯狂阅读吧,在阅读中找到迷茫的出口。

    生活

    生活的目标依然还是健康,希望2011年能学习一项体育项目,不求达到运动员的水平,只希望达到普通人的水平。目前为止还没跨出第一步,汗。2011年还给自己许下一个愿望,2012年就要到了,希望自己的生活能够稳定,不确定的事能够确定。

    2011年的关键词:阅读、运动、英语、JS。

    PS:总结还是主要以工作为主,希望以后有所转变。总结中又有展望,结构有点乱~文笔有待提高。

    null&undefine

    又是几个月没有更新博客,都长满野草了,惰性是种可怕的习惯~从简单做起,更新一篇小文。

    Javascript数据类型有number, string, boolean, funtion, object, array, null, undefined, Date, RegExp, Error。 其中比较让人迷惑的是null和undefined。

    null是一个对象,但又不同于一般对象,它无法调用toString()。

    当null用于布尔环境,它转换成false,当它用于一个数字环境,它转换为0, 当它用于一个字符串环境,它转换成“null”。

    undefined的数据类型还是undefined。一个定义未赋值的变量,一个已存在对象的未定义的属性的值都为undefined。

    var x;
    var y={};
    alert(x); //undefined
    alert(y.name); //undefined
    alert(z); //z is not defined

    其中调用未定义的z将会抛出异常,因为未定义的变量,仅仅是可写,但不可读可能被你忽略的 JavaScript 代码陷阱也有提到这一点。js这些细节很有趣,但也让人抓狂。

    当undefined用于布尔环境,它转换成false,当它用于一个数字环境,它转换为NaN, 当它用于一个字符串环境,它转换成“undefined”。

    null和undefined在布尔环境下都是false, 说明它们在某种意义上是相等,但是并不全等。

    alert(typeof null === 'object'); //true
    alert(typeof undefined === 'undefined'); //true
    alert(null==undefined); //true
    alert(null===undefined); //false

    BTW: null, undefined, false,  0,  空字符串, NaN在布尔环境中均为false。