htmlエスケープについて

こういうhtmlがあった時に、

<input type="text" name="txt" id="txt">
<span id="spn"></span>

txtの内容をspnに移動するには、

document.getElementById('spn').innerHTML = document.getElementById('txt').value;

とすればいける。
ただし、上記では不十分。innerHTMLに代入する場合はhtmlEscape処理が必要となる。というわけでこんな感じ。

document.getElementById('spn').innerHTML = htmlEscape(document.getElementById('txt').value);

htmlEscape関数は前のエントリで作ったこれが使えそう。

var htmlEscape = (function(){
  var map = {"<":"&lt;", ">":"&gt;", "&":"&amp;", "'":"&#39;", "\"":"&quot;", " ":"&nbsp;"};
  var replaceStr = function(s){ return map[s]; };
  return function(str) { return str.replace(/<|>|&|'|"|\s/g, replaceStr); };
})();

これをしないと例えばIEでtxtのところに「A&B」と入力して移動させると画面には「A」としか表示されない。「&」が実体参照の先頭文字という解釈をしているためにおこっている模様。ただし実体参照は「&」で始まって「;」で終わるはずだから「A&B」を実体参照として解釈するのは本来ならおかしいはずなんだけど。ちなみに「A&あ」だとそのまま表示されます。「&」のあとにマルチバイト文字がくるということは実体参照ではないのでそのまま表示するっていうロジックが走ってそう。バグなんちゃうか。firefoxだと「A&B」も「A&あ」もそのまま表示されます。
けど、こんなんを自作しなくてもjQueryを使ってこう書けば、内部でやってくれるから気にせず使える。

$('#spn').txt($('#txt').val());