Personal tools
You are here: Home ブログ uchida IE + closure library + cloneNode
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Categories
JavaScript
Go
Ada
Delphi
junk
 
Document Actions

IE + closure library + cloneNode

http://code.google.com/p/closure-library/source/detail?r=43
これまでgoog/demos/css以下にあったcssがgoog/cssに昇格したようです。
デモ用のcssをいちいちコピーするのが面倒だったので助かります。

さて、IEだとcloneNode時にイベントや独自に追加したプロパティも一緒にコピーされてしまいます。
このせいでclosure libraryのイベントで厄介な問題につまづきました。
備忘録兼腹いせとしてここに記録しておきます。

<html>
<head>
<script type="text/javascript" src="../closure-library-read-only/closure/goog/base.js"></script>
<script>
goog.require('goog.events');
goog.require('goog.dom');
goog.require('goog.events.EventType');
goog.require('goog.events.EventHandler');
</script>
</head>
<body>
<div id="hoge">hoge</div>
<script>
var onMouseDown = function(e) {
var target = e.target || e.srcElement;
alert(target.id);
};
var onMouseDownEx = function(e) {
var target = e.target || e.srcElement;
alert(target.id + ' Ex');
};

goog.events.listen(goog.dom.getElement('hoge'), goog.events.EventType.MOUSEDOWN, onMouseDown, false);
// goog.dom.getElement('hoge').attachEvent('onmousedown', onMouseDown);

// "hoge" をコピーして "fuga" を作る
var clone = goog.dom.getElement('hoge').cloneNode(true);
clone.id = 'fuga';
clone.innerHTML = 'fuga';
document.body.appendChild(clone);

// IEだとイベントもコピーされているため外す
goog.events.unlisten(clone, goog.events.EventType.MOUSEDOWN, onMouseDown, false);
// clone.detachEvent('onmousedown', onMouseDown);

// 別のイベントをつける
goog.events.listen(goog.dom.getElement('fuga'), goog.events.EventType.MOUSEDOWN, onMouseDownEx, false);
// goog.dom.getElement('fuga').attachEvent('onmousedown', onMouseDownEx);
</script>
</body>
</html>

id="hoge"のdiv要素をcloneNodeして別のイベントをlistenしています。
これでIEでもFireFoxでも"hoge"を押下したら「hoge」が、"div"を押下したら「fuga Ex」が表示されるように見えます。
しかしIEでは"hoge"を押下しても何も表示されません。

理由はgoog.events.listen/unlistenの中で使っているgoog.getHashCodeにあります。
http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/base.js

/**
* Adds a hash code field to an object. The hash code is unique for the
* given object.
* @param {Object} obj The object to get the hash code for.
* @return {number} The hash code for the object.
*/
goog.getHashCode = function(obj) {
// In IE, DOM nodes do not extend Object so they do not have this method.
// we need to check hasOwnProperty because the proto might have this set.

// TODO: There is a proposal to add hashcode as a global function to JS2
// we should keep track of this process so we can use that whenever
// it starts to show up in the real world.
if (obj.hasOwnProperty && obj.hasOwnProperty(goog.HASH_CODE_PROPERTY_)) {
return obj[goog.HASH_CODE_PROPERTY_];
}
if (!obj[goog.HASH_CODE_PROPERTY_]) {
obj[goog.HASH_CODE_PROPERTY_] = ++goog.hashCodeCounter_;
}
return obj[goog.HASH_CODE_PROPERTY_];
};
こいつは見ての通り与えられたオブジェクトにプロパティを追加し、そこにユニークなハッシュコード(という名の連番)をセットしてます。
goog.events.listen/unlistenではこのハッシュコードでunlistenするイベントハンドラを取得したり、同じ全くイベントを監視しないようにしたりしています。
IEだとcloneNode時にこのハッシュコードもコピーしてしまうため、イベント管理まわりで思ったように動かないことがあります。

IEがタコなのか、closure libraryがまずいのか、cloneNodeが黒魔術なのか。
怖いなあ、これ。

Category(s)
JavaScript
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/uchida/ie-closure-library-clonenode/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.