Javascriptのテンプレートエンジンについてはこちらでまとめられています。
http://tanarky.blogspot.com/2009/11/javascript-template-engines.html
jTemplatesの本家ページ
http://jtemplates.tpython.com/
試しにYahooのAPIを叩いてみます。
サンプルのソースコードは以下の通り
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script> <script type="text/javascript" src="http://jtemplates.tpython.com/jTemplates/jquery-jtemplates.js"></script> <div id="test_result"></div> <script type="text/javascript"> jQuery(function(){ var appid = jQuery.ajax({ url: "http://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch", data: { "appid": "cPvQ.eCxg67GFHywsAFH2KW2bVkOlYSz_pBz9.V3sOefgLF09GM8gJw8PJHRqII-", "query": "amp", "hits": 5 }, dataType: "jsonp", cache: false, error: function(data, status) { alert(status); }, success: function(data, status) { jQuery("#test_result").setTemplate("<table id=\"dataTable\" border=\"1\">" + "{#foreach $T as item begin=2 count=5}" + "<tr><td><a href={$T.item.Url}>{$T.item.Name}</a></td>" + "<td><img src={$T.item.Image.Small} /></td></tr>" + "{#/for}" + "</table>"); jQuery("#test_result").processTemplate(data.ResultSet[0].Result); } }); }); </script>
これを実際に実行するとこんな感じになります。
でもこれだと&がそのまま残ってしまってしまってます。
おかしいなーと思ってjTemplatesのソースを見てみたら、案の定HTMLエンティティを変換している部分がありました
/** * Replace chars &, >, <, ", ' with html entities. * To disable function set settings: filter_data=false, filter_params=false * @param {string} string * @return {string} * @static * @memberOf TemplateUtils */ TemplateUtils.escapeHTML = function(txt) { return txt.replace(/&/g,'&').replace(/>/g,'>').replace(/</g,'<').replace(/"/g,'"').replace(/'/g,''\ ');
ソースをたどっていくと、どうやらsetTemplateするときにオプションで設定できることが分かりました。
/** * Create new template from string s. * @name Template * @class A template or multitemplate. * @param {string} s A template string (like: "Text: {$T.txt}."). * @param {array} [includes] Array of included templates. * @param {object} [settings] Settings. * @config {boolean} [disallow_functions] Do not allow use function in data (default: true). * @config {boolean} [filter_data] Enable filter data using escapeHTML (default: true). * @config {boolean} [filter_params] Enable filter parameters using escapeHTML (default: false). * @config {boolean} [runnable_functions] Automatically run function (from data) inside {} [default: false]. * @config {boolean} [clone_data] Clone input data [default: true] * @config {boolean} [clone_params] Clone input parameters [default: true] * @config {Function} [f_cloneData] Function using to data cloning * @config {Function} [f_escapeString] Function using to escape strings * @augments BaseNode */ var Template = function(s, includes, settings) {(※setはTemplateのラッパーメソッド)
というわけで、setTemplateの第二引数にundefined, 第三引数に{filter_data : false}を与えてやるとうまくエンティティが文字として表示されました。
要するに、jTemplateに渡されるデータの中にHTMLエンティティが含まれているとjTemplateが気を利かしてエンコードしてくれるけど、すでにエンコード済みのデータを渡すと二重にエンコードすることになって、結果として&amp;みたいなことになってしまいます。
jTemplatesはエンコードするかどうかのオプションを引数で渡すことができるので、渡すデータによって使い分ける必要がありそうです。
hoge
返信削除