日々のコンピュータ情報の集積と整理

Dr.ウーパのコンピュータ備忘録

2015年2月19日木曜日

ソースコード解説:スタイル付きテキストを、コピーでブログに張り付け

イントロダクション

スタイルシートによってスタイルを適用した文字を、コピーによってブログに張り付けることのできるサービスのソースコードの解説を記載しました。

スタイル付きテキストを、コピーでブログに張り付けすることのできるサービスを作成しました!
http://upa-pc.blogspot.com/2015/02/css-copy-to-blog.html


そのままのソースコードは、以下のページで公開しています。

ソースコード:スタイル付きテキストを、コピーでブログに張り付け
http://upa-pc.blogspot.com/2015/02/src-css-copy-to-blog-v1.0.html


なお、これは初版(Version1.0)のものであり、今後修正が加わる可能性があります。

解説

iframe 

<iframe srcdoc='

スタイルシートの適用結果に、このサービスを運営するブログページのスタイルシートが影響を及ぼすのを防ぐために、iframe 内にサービスの画面を作成しています。


iframe タグの srcdoc 属性に、サービスの html と JavaScript をすべて記載しています。


なお、iframe タグの srcdoc 属性は、サポートしていないブラウザがあるので(Internet Explorer では、最新バージョン(11.0.9600.17501)でも表示させることができませんでした。)、別途その対策を後で行っています。

iframe タグの  srcdoc 属性をサポートしているブラウザ(対応ブラウザ)については、以下のページに詳しく記載されています。

iframe 要素 - HTML | MDN


入力部
<form onsubmit="return false;">
<b>表示するテキスト:</b><input type="text" id="input-text" style="width: 500px" /><br />
例)こんにちは!<br /><br />
<b>テキストのスタイルシート(CSS):</b><input type="text" id="input-css" style="width: 500px" /><br />
例)text-shadow: 4px 4px 7px rgba(150, 150, 150, 1);<br /><br />
</form>
<br />

表示するテキスト, テキストのスタイルシートの入力部です。

エンターキーが押されたときに、form タグ内のデータがサーバへ送信されないようにするために、onsubmit イベントにて、"return false;"しています。
(なお、このプログラムはサーバに入力データを送って処理を行うものではないので、この onsubmit イベントの "return false;" が無いと、ページがリロードされて入力したデータが消えてしまいます。)

2/3 Enterキーで送信されてしまうのを防ぐ [ホームページ作成] All About
http://allabout.co.jp/gm/gc/23972/2/


出力部

以下のテキストをコピーして、ブログの編集画面に貼り付けてください。<br />
<p>(上手くスタイルが適用されたテキストをコピーできない場合、コピー対象のテキストの上下の 1 行も含めてコピーしてみてください。)</p>
<div id="copy_target">
ここにデータが出力されます。
</div>

入力されたスタイルを適用したテキストのプレビューを表示させるための部分です。

入力部と同様に、エンターキーが押されたときに、form タグ内のデータがサーバへ送信されないようにするために、onsubmit イベントにて、"return false;"しています。


メイン処理部

<script type="text/javascript">
<!--
    (function () {

        var id_input_text = "input-text";        // 入力テキストを保持する要素の id
        var id_input_css = "input-css";        // 入力テキストを保持する要素の id
        var id_output = "copy_target";           // 出力値を保持する要素の id

        // 前回検査時の入力値
        var input_old_text = "";
        var input_old_css = "";


        // 定期的に入力を監視し、入力が変化していたら、出力する
        setInterval((function () {

            var input_text = document.getElementById(id_input_text).value;
            var input_css = document.getElementById(id_input_css).value;

            if (input_text != input_old_text ||
                input_css != input_old_css) {


                // データ出力
                var obj_output = document.createElement("div");

                // 余分なデータがコピーされないように十分な余白をとる
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createTextNode("--- ここから ---"));
                obj_output.appendChild(document.createElement("br"));

                var obj_output_text_with_css = document.createElement("span");
                obj_output_text_with_css.setAttribute("style", input_css);
                obj_output_text_with_css.appendChild(document.createTextNode(input_text));

                obj_output.appendChild(obj_output_text_with_css);

                // 余分なデータがコピーされないように十分な余白をとる
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createTextNode("--- ここまで ---"));
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createElement("br"));
                obj_output.appendChild(document.createElement("br"));


                // 画面へ出力
                var obj_output_target = document.getElementById(id_output);
                obj_output_target.innerHTML = "";
                obj_output_target.appendChild(obj_output);


                input_old_text = input_text;
                input_old_css = input_css;
            }

        }), 500);

    })();

//-->
</script>


今回の JavaScript のプログラムのメインです。

入力のテキストボックスを監視し、入力データが変化していたら、プレビュー用の html を生成し、出力のテキストボックスへデータを出力しています。

監視間隔は、setInterval で指定している 500 ms ごとです。
入力のテキストボックスに入力されたテキストが変化するごとにイベントが発生すれば、そのイベントにこの処理を書くのが良さそうですが、どうやら JavaScript ではそのようなイベントが無さそう(テキストボックスの onchage イベントは、データが入力される毎ではなく、フォーカスを失った時に発生する)なので、タイマによる定期的な入力データの変更チェックを行うことにしました。

テキストボックスのonchangeイベントを信用するべからず - 熱燗ロックのブログ
http://d.hatena.ne.jp/atsukanrock/20100427/1272358711


なお、ページ内の他の JavaScript コードと干渉しないように、コード全体を (function () {})(); で囲んでいます。


プレビュー用のスタイルシートによって装飾されたテキストは、その上下に十分な数の改行(<br />) を生成することで、余分なデータまでコピーされることを防いでいます。

特に、プレビュー用のデータを出力するために、出力用のターゲットのタグを特定するために id を設定しているので、その部分をコピーされなくなかったために、このように大量の改行をその内側に生成しています。
(タグに設定した id までコピーされてしまうと、コピー先のブログ内などに余分な id のデータが含まれてしまうため。)


プレビュー用のスタイルシートによって装飾されたテキストの上下に、"--- ここから ---" と "--- ここまで ---" を出力しているのは、その上下の1行を含めてコピーを出来るようにするためです。

"--- ここから ---" と "--- ここまで ---" がなく、ただの改行しかない空行の場合、Windows の Chrome で試してみたところ、プレビューの上下1行をうまく範囲選択することが出来ず、<div id="copy_target"> の先頭からの選択しかできませんでした。

そのため、"--- ここから ---" と "--- ここまで ---" という文字を出力することで、プレビューの上下1行を選択できるようにしています。


なぜ、プレビューの上下1行の選択が必要なのかというと、プレビュー用のスタイルシートによって装飾されたテキストをコピーした場合に、適用したスタイルによってはその上下の1行も含めてコピーしないと、スタイルシートがコピーされないものがありました。(text-shadowなど)


' width="100%" height="600px" id="iframe-copy_css">
</iframe>


iframe の srcdoc 非対応ブラウザ用処理

<script type="text/javascript">
<!--
    // iframe の srcdoc 非対応ブラウザ用
    // javascript で iframe の中身を作成する
    (function () {
        var iframe = document.getElementById("iframe-copy_css");

        // iframe の中身が無ければ、作成する
        if (iframe.contentWindow.document.body) {
            if (iframe.contentWindow.document.body.innerHTML != "") {
                return;
            }
        }

        iframe.contentWindow.document.open();
        iframe.contentWindow.document.write("<html><head></head><body>" + iframe.getAttribute("srcdoc") + "</body></html>");
        iframe.contentWindow.document.close();
    })();
//-->
</script>


iframe タグの srcdoc 属性をサポートしていないブラウザのために、JavaScript によって iframe の中身を動的に作成しています。

iframe タグの srcdoc 属性をサポートしているブラウザであれば、iframe の中身(iframe.contentWindow.document.body や iframe.contentWindow.document.body.innerHTML)があるはずですから、それらがあればこの処理は実行されません。

document.write を使用して、iframe タグの srcdoc 属性に設定されているデータを html 文書に必要なタグで囲んで出力しています。


この処理によって、iframe タグの srcdoc 属性をサポートしていない Internet Explorer 9(9.0.8112.16421) , Internet Explorer 11(11.0.9600.17501) にて、このプログラムが動くようになったことを確認しました。



以上が、このプログラムの全てです。






関連記事

関連記事を読み込み中...

同じラベルの記事を読み込み中...