innerHTMLのeventに関する罠
罠
innerHTMLの罠を紹介します。
addEventListenerにてtagにeventハンドラを追加している場合、
そのタグの中身をinnerHTMLを使って書き換えを行うと、eventが利用できなくなります。
sampleコード
<html> <script> var init = function() { var sample = document.getElementById( 'child_id' ); sample.addEventListener( 'mousedown', down, false ); } var down = function() { alert( 'mouse down' ); } var replaceHTML = function() { var parent = document.getElementById( 'parent_id' ); var tmp = parent.innerHTML; parent.innerHTML = tmp; } </script> <body onload="init();"> <div id="parent_id"> <div id="child_id">div sample</div> </div> <input type="button" value="push" onclick="replaceHTML();"> </body> </html>
sampleコードの中ではparent_id,child_idが入れ子の状態になっています。
parent_idのinnerHTMLに元々のhtmlをそのまま代入しているだけなのですが、
child_idのeventが失われてしまいます。innerHTMLの値を書き換える場合は注意が必要です。
回避策
必要な要素のみ書き換えを行うようにします。
上の場合ですと、child_idのinnerHTMLだけを書き換えます。
※Safariでは正常動作確認済みです。
<html> <script> var init = function() { var child = document.getElementById( 'child_id' ); child.addEventListener( 'mousedown', down, false ); } var down = function() { alert( 'mouse down' ); } var replaceHTML = function() { var child = document.getElementById( 'child_id' ); var tmp = child.innerHTML; child.innerHTML = tmp; } </script> <body onload="init();"> <div id="parent_id"> <div id="child_id">div sample</div> </div> <input type="button" value="push" onclick="replaceHTML();"> </body> </html>
その他
jQueryのhtml関数を利用しても同様にeventが失われる結果になります。
以下はjQueryを利用した場合のサンプルコードになります。
<html> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js" ></script> <script> var init = function() { var child = $( '#child_id' ); child.mousedown(function(){ alert( 'mouse down' ); }); } var replaceHTML = function() { //var parent = document.getElementById( 'parent_id' ); var parent = $( '#parent_id' ); var tmp = parent.html(); parent.html( tmp ); } </script> <body onload="init();"> <div id="parent_id"> <div id="child_id">div sample</div> </div> <input type="button" value="push" onclick="replaceHTML();"> </body> </html>
お願い
※firstChildなどを使ってDOM操作すれば以下の問題も解決出来ますね。
子nodeのidが取れれば上の解決策で対応できるのですが、子nodeのidが取れない場合どうすれば良いでしょうか。Eventが引き継げるコードさえかければ大丈夫なのですが、方法が見つかりません。どなたかご存じの方ご指摘いただけると助かります。