はじめに
youtubeプレーヤーページを作成していると、いつもこの問題に悩まされます。
再生リストの動画のタイトルには、ダブルクォテーションやシングルクォテーションを含むタイトルが結構あります。
再生リストを表示する場合と、もう少し難解な、input要素などのテキスト入力フィールドに動画のタイトルをセットする場合は、中々、思い通りにはセットできません。
ダブルクォテーションやシングルクォテーションの途中で表示が途切れてしまいます。
まだ、続きが残っていますが、表示はされません。デバッガーで表示してみると、データ自体は存在していますが、表示できません。
今回は、これらの不具合の原因を追究してみました。
サンプル画面
この画面に赤い矢印が2か所あります。
これは、タブルクォテーションの例です。
現象は
左側の矢印が示しているのは、再生リストのトップの動画のタイトルです。この部分のhtmlテータは以下の通りです。
<li class="ameba ui-sortable-handle" name="1" style="padding:1%;clear:both;">
1.<a class="thumb" href="#"><img class="my_list"src="https://i.ytimg.com/vi/CEL_ZyPxNzM/default.jpg"></a><span
class="plist_title" style="font-weight: bold; font-size: 1.3em; color: blue;">
前野曜子 ”そして今は(NOW)”</span><span style="zoom:2;" class="mark">😊</span></li>
右側
<div id="apop" style="display: block; border: 3px solid blue; font-weight: bold; font-size:
1.3em; padding: 5px; z-index: 999999; width: 700px; height: 300px; background-color:
lightgreen; position: fixed; top: 222px; left: 834px;" class="ui-draggable ui-draggable-
handle">タイトルクリック<br><input style="width:600px;" type="text" id="select" value="前野曜
子 ”そして今は(NOW)”"><br><button id="apop_cancel">キャンセル</button><button id="apop_hover">ホバーオフします。</button></div>
原因は
一番の問題は、下記のコードの
tt = e.target.textContent.replace(/"/g,'"'); //
の部分でした。この対策をしていなかったために、かなり、時間を無駄にしました。
ここで、お気づきかも知れませんが、" と表示されている箇所は、実は、\" となっています。このQiitaページでも、"の表示には&の前に(エスケープ文字)を入れています。
このQiitaのページ自体もHTMLのため、制御文字(&など)を表示するには、逆スラッシュでエスケープが必要です。
tt = e.target.textContent.replace(/"/g,'\\\"');
ここでは、敢えて、制御コードを見るために、''の中を\\\"としています。
こうすると表示できます。(&の前に\を3つ入れています。一つは\をエスケープするためともう一つは&をエスケープするためです。)これは、Qiitqの編集画面でなければ、逆スラッシュを見ることができません。表示画面では、逆スラッシュを解釈後のため、見ることはできません。
もう一か所の
mess = `タイトルクリック<br><input style=\"width:600px;\" type=\"text\" id=\"select\" value=\"`+tt+`\"></input>`;
ここに関しては、属性のエスケープをあれこれ試行錯誤はしていたのですが、根本の問題は、tt変数のエスケープがうまく行かなかったことです。
//リストのタイトルをクリックするとイベントが発火します。
switch (e.target.className) {
//タイトルをクリック時のインデックスを取得
case "plist_title":
//ここの問題は、tt
//このエスケープは重要
tt = e.target.textContent.replace(/"/g,'"'); // <== ここが問題だった。
//ここでもエスケープが必要 ``で囲む。さらに、属性の囲い込みをエスケープする。/"
//""で囲むとエラーになる。
mess = `タイトルクリック<br><input style=\"width:600px;\" type=\"text\" id=\"select\" value=\"`+tt+`\"></input>`;
alertY(mess,3000);
break;
//この関数は、パラメータのmsgを表示するだけです。
window.alertY = async function (msg, n) {
if (apop_top === undefined) {
apop_top = "222px";
apop_left = "834px";
}
$("#apop").css({"top": apop_top, "left": apop_left, "display": "block"});
//ここで、パラメータのmsgを埋め込んでいます。
let html = msg + "<br><button id='apop_cancel'>キャンセル</buton><button id='apop_hover'>ホバーオフします。</buton>";
await $("#apop").html(html);
$("#apop").draggable({
drag: function (event, ui) {
//■ ドラッグ中に実行したい処理
apop_top = ui.position.top;
apop_left = ui.position.left;
}
});
};
/***
動作結果
上記の対策をすることで、タイトルクリックのポップアップの要素に、"または'を表示することができました。
テスト実行
このページで、リストの先頭のタイトルをクリックすると、タイトルクリックのポップアップが表示されます。
あとがき
htmlページ関連の文字列のエスケープには、いつも悩まされています。
試行錯誤をしながら、解決策を探しています。
"とか、逆スラッシュの使い方(\"、\'など)は、テストしながら確認しています。
