2012年1月12日木曜日

Blogger で JavaScript(4) - script type="text/html" を iframe へ変換

(2012.02.06)更新

  • .createElement() した div を .inertBefore() しないで、直接 div.innerHTML = "<iframe ..." して iframe を DOM Tree へ .insertBefore()
    ※ IE6 だとうまくいかなかったような気がするけれど無視。
  • title 属性を json 形式で iframe の属性に展開するようにコードを追加
    title="'id':'test', 'style':'display:block;width:100%;'" と書けば
    <iframe id="test" style="display:block;width:100%;" のように .setAttribute() される
  • iframe コンテンツの height を iframe の height に設定することでスクロールバーが出ないようにコードを追加
JavaScript Source
<script>
  (function () {
    var nodes = document.getElementsByTagName("script");
    for (var i=0; i<nodes.length; i++) {
      var script = nodes.item(i);
      if (script.getAttribute("type") == "text/html") {
        // iframe = document.createElement("iframe");
        // IE7,IE8 do not implement disabling frameborder by CSS
        var div = document.createElement("div");
        div.innerHTML = '<iframe frameborder="0"></iframe>';
        var iframe = div.firstChild;
        if (!iframe)
          return;

        var json = script.getAttribute("title");
        if (json) {
          //var obj = JSON.parse(json); // not implemented by IE7
          var obj = eval("("+ json +")"); // execute eval securely,because json is written by me
          var attrs = ["id","class","title","style"];
          for (var i=0; i<attrs.length; i++) {
            var value = obj[attrs[i]];
            if (value)
              iframe.setAttribute(attrs[i],value);
          }
        }

        script.parentNode.insertBefore(iframe, script);
        var win = iframe.contentWindow;
        if (!win)
          return;
        var doc = win.document;
        if(!doc)
          return;
        //win.onload = function () { // implemented on Firefox
        iframe.onload = function () { // implemented on Firefox, Webkit, IE
          var html = doc.documentElement;
          if (!html)
            return;
          iframe.height = html.scrollHeight;
        };

        doc.open();
        doc.write(script.innerHTML);
        doc.close();
      }
    }
  })();
</script>

(2012.01.17)更新

  • Global 変数を使わないように関数化
  • return で深くなったブロック階層を解消
JavaScript Source
<script>
  (function () {
    var nodes = document.getElementsByTagName("script");
    for (var i=0; i<nodes.length; i++) {
      var script = nodes.item(i);
      if (script.getAttribute("type") == "text/html") {
        // iframe = document.createElement("iframe");
        // IE7,IE8 do not implement disabling frameborder by CSS
        var div = document.createElement("div");
        script.parentNode.insertBefore(div, script);
        div.innerHTML = '<iframe frameborder="0"></iframe>';
        var iframe = div.firstChild;
        if (!iframe)
          return;
        script.parentNode.replaceChild(iframe, div);
        var doc = iframe.contentDocument || iframe.contentWindow.document;
        if(!doc)
          return;
        doc.open();
        doc.write(script.innerHTML);
        doc.close();
      }
    }
  })();
</script>

(2012.01.12)

JavaScript Source
<script type="text/javascript">
    var nodes = document.getElementsByTagName("script");
    for (var i=0; i<nodes.length; i++) {
      var script = nodes.item(i);
      if (script.getAttribute("type") == "text/html") {
        var div = document.createElement("div");
        script.parentNode.insertBefore(div, script);
        div.innerHTML = '<iframe frameborder="0"></iframe>'; // for IE7,IE8
        var iframe = div.firstChild;
        if (iframe) {
          script.parentNode.replaceChild(iframe, div);
          var doc = iframe.contentDocument || iframe.contentWindow.document;
          if (doc) {
            doc.open();
            doc.write(script.innerHTML);
            doc.close();
          }
        }
      }
    }
</script>
HTML Source
<script type="text/html">
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <title>script の内容を iframe へ</title>
  <style>
    html, body { border:0; }
    body { font-family:tahoma,meiryo,sans-serif; }
  </style>
</head>
<body>
  <h1>script の内容を iframe へ</h1>
</body>
</html>
</script><!-- type="text/html" -->
Result

確認

OS
Windows XP Professional Service Pack 3
Web Brower
Internet Explorer 8
Firefox 9.0.1

Blogger で JavaScript(3) - <![CDATA[ の代わりに script type="text/plain"

タグやソースコードの中の <, &, > をエスケープするのは大変だし、HTMLソースの見通しが悪くなるので、JavaScript で何とかしてみる。

JavaScript Source
<script type='text/javascript'>
  var nodes = document.getElementsByTagName('script');
  for (var i=0; i<nodes.length; i++) {
    var script = nodes.item(i);
    if (script.getAttribute("type") == "text/plain") {
      var text= document.createTextNode(script.innerHTML);
      script.parentNode.insertBefore(text, script);
    }
  }
</script>
HTML Source
<pre><script type="text/plain">普通のテキスト
<p>タグもそのまま</p>
<!-- コメントもそのまま --></script></pre>
Result
普通のテキスト
<p>タグもそのまま</p>
<!-- コメントもそのまま -->