JavaScript おれおれ Advent Calendar 2011 – 22日目

DBで得た情報をHTML形式で出力するだけならサーバー側でやればいいんですが、JSだけで使いたい場合ってありますよね。ないかな。あるでしょ。あるはず。

そういうデータはテキストにしてAjax/XHRで取得するとか、JavaScriptの変数に代入するとかして出力するとかあるんですが、前者だと通信のコストがかかるし、後者はエスケープとか考慮しなくちゃいけなくてなんとも剣呑です。

echo '<script type="text/javascript">';
echo "var myData = $formatted_data;";
echo '</script>';

というわけでテキストはテキストのまま埋め込んでしまいます。

これスクリプトじゃないよって主張する

こんな感じで。

<script id="mydata" type="text/x-mydata">
26,23,43,55,82,75,82,98,83,85
79,31,38,16,85,85,20,41,90,61
36,52,66,61,43,4,10,40,30,49
...
</script>

(何のデータだこれ……。)

script要素のtype属性をtext/javascriptとかじゃないものにするのがミソです。これならブラウザーがスクリプトとして自動で実行したりはしません。

で、要素の内容を取得して解析してやればいいです。script要素の内容は要素のオブジェクトの .textプロパティに格納されています。

var el = document.getElementById('mydata');
var myData = parseMyData(el.text);

function parseMyData(text) {
  // TODO : CSVなりJSONなりを解析して返す。
  //        jQuery.parseJSON()とか。
}

内容のエスケープ

内容には</が含まれないようにする必要があります。それ以外は、改行があろうがタグ<>があろうがお構いなしです。

スクリプトデータやスタイルデータが要素の内容である場合 (SCRIPT要素かSTYLE要素)、 データは当該要素の開始タグの直後から始まり、最初のETAGO【終了タグ開始区切り子】「</」に続けて名前開始文字([a-zA-Z])があるところで終わる。末尾と判断される組み合わせ【ETAGOと名前開始文字】が当該要素の終了タグではない場合があり得ることに注意されたい。 従って著者は、「</」を各スクリプト言語あるいはスタイルシート言語固有のエスケープ機構によってエスケープすべきである。

エスケープを全く行わなくて良いわけではないのですが、例えばデータをJavaScriptに格納するコードを直接出力するよりはだいぶ簡単だと思います。

HTMLの仕様的に大丈夫なの?

HTML5

まずHTML5では大丈夫っぽいです。

script 要素は、ウェブ制作者がドキュメントに動的なスクリプトやデータブロックを含めることができるようにします。この要素は、ユーザーに対するコンテンツを表しません。

データ・ブロックを入れるために使う場合(スクリプトとは対照的ですが)、そのデータはインラインで組み込まなければいけません。そして、type 属性を使ってデータのフォーマットを指定しなければいけません。この場合、src 属性を指定してはいけません。そして、script 要素のコンテンツは、採用フォーマットに定義された要件に適合しなければいけません。

ここでいう「インラインで組み込み」とはsrcを使わずに要素のコンテンツに記述するって事です。

type属性の値は妥当な MIME タイプとの事なので、CSVならtext/csv、JSONならapplication/json、独自形式ならtext/x-なんちゃらにしとくと良いのかもしれません。

HTML 4.01

HTML 4.01の方はちょっと記述が見つからなかったんですが、多分大丈夫だと思います。とりあえず動きはします。

スクリプトはスクリプトエンジンによって評価される。スクリプトエンジンはユーザエージェントにとって既知でなければならない。

該当するエンジンがない場合にどうするかの記述が見つかりませんでした。無視されてるみたいですが。。。