イントロダクション
「コンマ(,)区切りの文字列の要素を、括弧[]でそれぞれ囲むサービスを作りました」で公開したプログラムを、実際に Blogger のページに張り付けて運用してみたところ、一部でうまく動作していないことが分かりました。どうも、全角のダブルクォーテーション(“”)が入力データに入っていると、ちゃんと変換してくれないようです。
Blogger のページに張り付ける前に、パソコンのローカルの html ファイルでテストした時には同じ条件で正常に動作していました。
何故かと思い、Blogger のページのソースコードを見ていたら原因が分かりました。
そのときの、Blogger のページのソースコードを以下に貼り付けます。
なお、元のソースコードは、以下のページにあります。
プログラムソース:コンマ(,)区切りの文字列の要素を、括弧[]でそれぞれ囲む - ver1.0
http://upa-pc.blogspot.com/2015/02/Src-Comma-Separated-Words-to-Square-Bracket-Separated-v1.0.html
Blogger のサーバから出力された、ページのソースコード
<form onsubmit="return false;">
<strong>(ダブルクォーテーション(")で囲まれた)コンマ(,)区切りの文字列 :</strong><br />
<input id="input-text" style="width: 700px;" type="text" /><br />
<input checked="checked" id="auto-focus-move" type="checkbox" />自動的に結果を選択する<br />
例)“Dr.ウーパ , コンピュータ備忘録 , Blog”
</form>
<form onsubmit="return false;">
<strong>括弧[]でそれぞれの要素を囲んだ結果:</strong><br />
<input id="output-text" onfocus="this.select();" style="width: 700px;" type="text" />
</form>
<br />
<script type="text/javascript">
//<でそれぞれ囲んだ文字列に変換する
var output_text = changeInputText(input_text);
document.getElementById(id_output).value = output_text;
if (document.getElementById("auto-focus-move").checked) {
document.getElementById(id_output).select();
}
input_old_text = input_text;
}
}), 500);
/*
入力されたダブルクォーテーション(")で囲まれたコンマ(,)区切りの文字列を、
括弧[](角括弧、大括弧、ブラケット)でそれぞれ囲んだ結果を返す
*/
function changeInputText(input_text) {
return "[" +
input_text.replace(/["“”]/g, "")
.replace(/\s*[,,]\s*/g, "][") +
"]";
}
var debug_flag = false;
if (debug_flag) {
/* テスト用 */
(function () {
var error_count = 0;
(function () {
var input = "“Dr.ウーパ,コンピュータ備忘録 , Blog”";
var output = changeInputText(input);
var error = output != "[Dr.ウーパ][コンピュータ備忘録][Blog]";
if (error) error_count++;
console.log("input," + input + ",output," + output + ",error," + error);
})();
(function () {
var input = "\"Dr.ウーパ , コンピュータ備忘録,Blog\"";
var output = changeInputText(input);
var error = output != "[Dr.ウーパ][コンピュータ備忘録][Blog]";
if (error) error_count++;
console.log("input," + input + ",output," + output + ",error," + error);
})();
(function () {
var input = "Dr ウーパ コンピュータ 備忘録 , Bl og";
var output = changeInputText(input);
var error = output != "[Dr ウーパ コンピュータ 備忘録][Bl og]";
if (error) error_count++;
console.log("input," + input + ",output," + output + ",error," + error);
})();
console.log("error_count," + error_count);
if (error_count > 0) {
console.log("Test NG");
} else {
console.log("Test OK");
}
})();
}
})();
//-->
//]]>
</script>
お分かりいただけたでしょうか?
なんと、Blogger のページ中に記載した JavaScript コードの、一部の全角文字がエスケープ処理されています。Blogger のページ中に記載した JavaScript コードの、一部の全角文字がエスケープ処理されている
例えば、次の正規表現による置換の部分を見てみましょう。return "[" +
input_text.replace(/["“”]/g, "")
.replace(/\s*[,,]\s*/g, "][") +
"]";
もともとのソースコードでは、以下のようになっていました。
return "[" +
input_text.replace(/["“”]/g, "")
.replace(/\s*[,,]\s*/g, "][") +
"]";
以下のような変換が行われていることが分かります。
“” の部分が、“”
, の部分が、,
全角のダブルクォーテーションや、全角のコンマがエスケープ処理されています。
これでは、JavaScript コードが期待通りに動くはずがありません。
このようなエスケープされた表現が html ファイルのソースコード中にあった場合には、html として表現されている部分では、アンエスケープ(“ が “ として見える・取得できる)されたデータを見たり・得たりすることができます。
しかし、JavaScript コード中にそのような表現があった場合には、html 中の文字とは解釈が異なるため、アンエスケープされません
なお、このデータの変換は、Blogger のサーバからページが配信されるときに行われていると考えられます。
なぜなら、ページを編集するときに表示した HTML や、保存したページを再編集した時の HTML では、このようなエスケープ処理された表現になっていなかったからです。
従って、Blogger の内部的にはエスケープ処理される前のデータを持っていますが、実際にBlogger のサーバから閲覧者へデータが配信されるまでの間でこのようなエスケープ処理が行われていることになります。
このような変換を止めるような設定なども見当たらなかったため、このような変換が行われる前提で、正常に動作するようにコードを書き換える必要があります。
どう対処するべきか?
JavaScript 中の文字列リテラルが自動的にエスケープされてしまうのであれば、それらの文字列リテラルを利用する前に、エスケープされた文字をアンエスケープする処理を挟んでやればいいことになります。この文字のアンエスケープをやるには、いくつかの方法があります。
例えば、element オブジェクトを生成し、その innerHTML にアンエスケープされた文字列データを設定すれば、そのテキストデータ(textContent || innerText) を取得すれば、アンエスケープされたデータが取得できるでしょう。
または、html 中に JavaScript で利用する(エスケープされてしまう)文字列を記載しておき、それを JavaScript で取得すれば、アンエスケープされた文字列を取得できます。
今回は、後者の方法で実装することにしました。
次のように、input タグの隠しデータとして、JavaScript で利用するデータを埋め込んでおきます。
<input type="hidden" id="reg-exp-double-quotes-list" value=""“”" />
<input type="hidden" id="reg-exp-comma-list" value=",," />
そして、そのデータを JavaScript 中で要素から取得します。
// ダブルクォーテーション(") 認識用データ
var double_quotes_array = document.getElementById("reg-exp-double-quotes-list").value.split("");
var double_quotes_str = double_quotes_array.join("");
// コンマ(,)認識用データ
var comma_array = document.getElementById("reg-exp-comma-list").value.split("");
var comma_str = comma_array.join("");
そして、そのデータを実際に使いたかった部分で使用します。
return "[" +
input_text.replace(new RegExp("[" + double_quotes_str + "]", "g"), "")
.replace(new RegExp("\\s*[" + comma_str + "]\\s*", "g"), "][") +
"]";
なお、正規表現の部分では、元々使用していた /pattern/flags という形式では、正規表現のパターン部分に変数の値を使うことができなかったため、new RegExp("pattern" [, "flags"]) の形式に書き直しました。
RegExp - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp
それらの修正を行った、コンマ(,)区切りの文字列の要素を、括弧[]でそれぞれ囲むサービスのソースコードを以下のページに記載しました。
コメントを投稿 (ここをクリックしてコメント投稿フォームを表示)
コメント投稿機能について