[IE6|IE7|IE8]cloneNodeで複製したエレメントのidをjQueryから参照出来ない時のTips

2011
05.23
このエントリーをはてなブックマークに追加

皆さんこんにちわ、なんだか冷えますね。

 

さて、皆大好き IE ブラザーズのお茶目な仕様で少々ハマりましたので仕様解説と解決策の TIPS です。

実は基本的な事かもしれませんが、仕様を理解しておくのに越した事は無いでしょう。

リッチコンテンツ制作時にちょこちょこ問題になる可能性が高いので、便利な関数も作ってみました。改良して使ってもらえればよろしいかと思います。

 

出くわした状況

メニューをスライドしたい時に数がギリギリなので、一番端の要素を予め逆側に複製しておいてスライドした後に複製したエレメントを消去しようとした。

 

症状

IE だけスライドした後に複製元となったエレメントが動き出して、思い通りの動きをしなかった。

 

元ソース

■html

1
2
3
4
5
<ul id="listBox">
    <li id="list1">hoge</li>
    <li id="list2">moge</li>
    <li id="list3">foo</li>
</ul>

■javascript

1
2
3
4
5
6
7
var content = document.getElementById('listBox');
var clone = document.getElementById('list1').cloneNode(true);
clone.id = 'temp';
clone.style.position = 'absolute';
clone.style.left = '600px';
content.appendChild(clone);
$('#temp').animate({left: 400});

 

cloneNode して、id を書き換えて親要素に appendChild して動かそうとした訳です。

IE 以外のブラウザはこれで問題無く動きます、IE 以外は。

IE だけは #temp を呼ぶと複製元である #list1 を参照して、そちらを動かそうとします。ちなみにリスナを仕掛けたり、setTimeout でぐるぐる回してフラグを監視して、存在確認をした後に命令しても一切を無視して複製元を動かします。
更に jQuery から attr を使って id を変えても駄目です、凄い頑固ちゃんです。

 

早速原因を追求していくと、どうにも困った事になっていました。

 

IE は同一プロセス内で cloneNode(複製)されたエレメントは、別プロセスから呼ばれない限り複製元の id を参照する。

 

え、なんで!?と言う仕様ですよね、cloneNode(複製)したプロセスとは別にボタンを用意して、適当に命令を書いた関数を呼び出すと思い通りの動きをします。

もしかしたらちょっと違うのかもしれませんが、大体こんな感じの挙動になる筈です。

 

 

非常に気持ち悪いです。

 

 

ともあれ fix していきましょう、要は cloneNode(複製)したエレメントの挙動がおかしいのならば新規でエレメントを生成して、複製元のエレメントもしくは複製したばかりのエレメントから欲しい情報を新規エレメントに移してから appnedChild すれば良いのです。

 

改良版ソース

■javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
var content = document.getElementById('listBox');
var clone = document.getElementById('list1').cloneNode(true);
var elm = document.createElement('li');
content.appendChild(getCloneNode(clone, elm, 'temp'));
$('#temp').animate({left: 400});

function getCloneNode(clone, elm, id) {
    elm.id = id;
    elm.style.position = 'absolute';
    elm.style.left = '600px';
    elm.innerHTML = colne.innerHTML;
    return elm;
}

 

 

こうやると意図した動きになるはずです、なんだか回りくどいけど。

これは複製したエレメントから新規エレメントに要素を移していますが、多分複製せずに直接突っ込んでも上手く行きそうですね。別処理との兼ね合いで content を外で作ってますが、全部関数内でやっちゃった方が綺麗にかけそうですね。

 

そこはお好みで。

 

なんか悔しかったから複製してやっただけですし。

 

それではまた。

 

Tags: , , , ,

Your Reply