特定のページに記述してある情報を他のページでも使用している場合に、元のページの情報を更新すると他のページの情報も自動的に更新されるようにする方法のメモ。
例えば、スケジュールが記述されている「schedule.html」のサマリーをトップページなどにも表示する場合、内容を更新するにはそれぞれのページを更新しなければならない。
これを jQuery の load() を利用して「schedule.html」を更新すると自動的に他のページも更新されるようにしてみる。
schedule.html 抜粋
・・・省略・・・ <table id="schedule"> <tr> <th>DATE</th> <th>VENUE / LOCATION</th> </tr> <tr> <td class="date">1/3 (Thurs)</td> <td class="info"><span class="venue">Cleopatra's Needle</span> ....</td> </tr> <tr> <td class="date">1/6 (Sun)</td> <td class="info"><span class="venue">Small's</span>....</td> </tr> ・・・省略・・・ <td class="date">1/19 (Wed)</td> <td class="info"><span class="venue">St. Peter's Church</span>....</td> </tr> </table> ・・・省略・・・
上記の schedule.html の「table id=”schedule”」の概要を他のページにも表示する。
index.html 抜粋
<h2>スケジュール</h2> <div id="live_summary"> <!--この部分に概要を表示する--> </div><!--end of #live_summary-->
追加情報
以下の方法では、load() を使っているのに、コールバック関数の中で、応答テキストの response を使って無駄な処理をしています。効率の悪い例として残しておきますが、こちらのコードの方を参考にしてください。
jQuery
jQuery(function($){ $('#live_summary').load('en/schedule.html #schedule', function( response, status, xhr ) { var date = /<td class="date">(.+)<\/td>/g; var venue = /<span class="venue">(.+)<\/span>/g; var result_date; var result_venue; $(this).html(''); var date_array = new Array(); var venue_array = new Array(); while((result_date = date.exec(response)) != null){ date_array.push(result_date[1]); } while((result_venue = venue.exec(response)) != null){ venue_array.push(result_venue[1]); } var my_html = ''; for(var i = 0; i < date_array.length; i++){ my_html += '<dl><dt>' + date_array[i] + "</dt>\n" + '<dd>' + venue_array[i] + "</dd>\n" + '</dl>'; } $(this).html(my_html); }); });
もし、schedule.html にユーザーのためにコメントアウトを使って以下のような使用法が記述してあると、この部分の td 要素も対象になってしまい不要な部分が出力されてしまう。
<!-- 行を追加する場合は以下をコピーして使用してください。 <tr> <td class="date">日付 (曜日)</td> <td class="info"><span class="venue">場所</span><br>住所等</td> </tr> --> <table id="schedule"> <tr> <th>DATE</th> <th>VENUE / LOCATION</th> </tr> <tr> <td class="date">1/3 (Thurs)</td> <td class="info"><span class="venue">Cleopatra's Needle</span> ....</td> </tr>
そのような場合は、replace() を使って HTML のコメントアウト部分を削除する。
text.replace(/<!--([^-]|-[^-]|--[^>])*-->/g, "");
ロードしたデータから全てのコメントアウトを削除する場合の例
jQuery
jQuery(function($){ $('#live_summary').load('en/schedule.html #schedule', function( response, status, xhr ) { var date = /<td class="date">(.+)<\/td>/g; var venue = /<span class="venue">(.+)<\/span>/g; var result_date; var result_venue; $(this).html(''); var date_array = new Array(); var venue_array = new Array(); //コメントアウト部分を削除 response = response.replace(/<!--([^-]|-[^-]|--[^>])*-->/g, ""); while((result_date = date.exec(response)) != null){ date_array.push(result_date[1]); } while((result_venue = venue.exec(response)) != null){ venue_array.push(result_venue[1]); } var my_html = ''; for(var i = 0; i < date_array.length; i++){ my_html += '<dl><dt>' + date_array[i] + "</dt>\n" + '<dd>' + venue_array[i] + "</dd>\n" + '</dl>'; } $(this).html(my_html); }); });
せっかく load() を使っているのだから、コールバック関数の中で $(this) を使用すれば、フィルタした要素(この例の場合は、id が schedule の table 要素)を操作できる。
jQuery
jQuery(function($){ $('#live_summary').load('en/schedule.html #schedule', function() { var table$ = $(this); var date$ = table$.find('td.date'); var venue$ = table$.find('td.info span.venue'); var html = ""; for(var i = 0; i < date$.length; i ++) { html += "<dl><dt>" + date$.eq(i).text() + "</dt>\n<dd>" + venue$.eq(i).text() + "</dd></dl>"; } $(this).html(html); }); });
コールバック関数は、マッチした要素に取得したデータが挿入された後に呼び出されるので、$(this) にはすでに、table 要素 <table id="schedule">~</table> の jQuery オブジェクトが入っています。それをまず変数(table$)に格納します。
そして find() を使って、 <td class=”date”> と <span class=”venue”> の要素を抽出して、それらを変数(date$, venue$)に格納します。
変数 html は、 live_summary という id 名の div 要素に挿入する HTML で、まず空文字列で初期化しておきます。
for 文を使って、要素の数だけ繰り返し処理を行います。繰り返しの数は、date$.length または、venue$.length で取得できます。
繰り返し処理の中では、date$ 及び venue$ から eq() と text() を使ってそれぞれの要素のテキストを取得して、それを dt 及び dd 要素の内容として html に追加しています。
繰り返し処理が終了したら、全ての要素の内容を html に代入できているので、それを $(this) つまり、$(‘#live_summary’) の HTML に設定します。
関連ページ:「jQuery の load()」
load(url, parameters, callback)
セレクタを指定するには、URLの後に、1個のスペースに続けてセレクタを書く。例えば、応答要素(取得するデータ)にフィルタをかけて div インスタンスだけを注入したい場合は、次のように書く。
$('.injectMe').load('en/schedule.html div');
RegExp.exec() メソッド:
汎用のパターンマッチング。exec()は文字列を引数にとる RegExp のメソッド
RegExp がグローバルな正規表現の場合
var pattern = /Java/g; var text = "JavaScript is more fun than Java!"; var result; while((result = pattern.exec(text)) != null){ console.log("Matched '" + result[0] + "'" + " at position " + result.index + "; next search begins at " + pattern.lastIndex); }
console.log() の出力
Matched ‘Java’ at position 0; next search begins at 4
Matched ‘Java’ at position 28; next search begins at 32
問題なく表示されるが、コンソールを見ると以下のようなエラーが出ていた。
GET http://localhost/images/header_page.jpg 404 (Not Found) jquery-1.10.1.js:6590
問題なく表示されるので、無視してもいいような気がするが取りあえずエラーが出ないようにしてみた。
load() でセレクタを指定するには URLの後に 1個のスペースに続けてセレクタを書くが、調べて見ると実際には指定したページの HTML 全てが最初にロードされその後セレクタでフィルタされているみたい。
このため、ロードしたページの画像へのパスが異なった階層として読み込まれているようなので、$.ajaxSetup() の dataFilter を使って以下を追加したところ、エラーが消えた。但し、以下の方法はこのサンプル特有な方法なので汎用的ではない。
load() は内部的には $.ajax() を使っているようなので、 $.ajaxSetup() で Ajax リクエストのデフォルト設定を変更。(Ajax リクエストのデフォルト設定の変更はそのサイトの環境により判断する必要があると思うので注意が必要)
function return_img_path_depth() { var src = $('#header_img img').attr('src'); var result = src.match(/(\.\.\/)/g); if(result != null) { return result.length; }else{ return 0; } } $.ajaxSetup({ dataFilter: function (response) { var parent_path = ''; var path_depth_count = return_img_path_depth(); for(var i = 0; i < path_depth_count ; i++){ parent_path += '../'; } return response.replace(/<img src="(..\/)*images/g, '<img src="' + parent_path + 'images'); }, //変更がすぐに反映されるよう「false」に設定 cache: false });
文字列で regexp にマッチするサブストリングを探し、replacement でそれらを置換する(文字列に対して検索と置換を行う)。
文字 | 置換 |
---|---|
$1,$2, … $9 | regexp で最初から9番目までのカッコ付きサブ表現のテキスト |
$+ | regexp で最後にマッチしたカッコ付きサブ表現 |
$ | regexp にマッチしたサブストリング |
$` | マッチした文字列の左側のテキスト |
$’ | マッチしたテキストの右側の文字列 |
\\$ | 文字としてのドル記号 |
「Davis, Miles」という名前を「Miles Davis」という形式に置換するには、以下のようにする。
name.replace(/(\w+)\s*,\s*(\w+)/, "$2 $1");