jQuery の load() を使って同じサイト内の別のページの見出しを表示する方法に関するメモ。load() の基本的な使い方等についても再度メモ。
目次
$(ターゲット要素).load(url, parameters, callback)
$('#some_id').load('xyz.html', function(response, status, xhr) { 処理 }); //第2引数(parameters)を省略した場合
セレクタを指定するには、URLの後に、1個のスペースに続けてセレクタを記述。例えば、取得するデータにフィルタをかけて id=”side” の div 要素だけを #some_id に注入したい場合は、次のように記述。
$('#some_id').load('samples/sample1.html div#side');
取り合えず、別のページ(sample1.html)の見出しを抽出してみる。以下のページの div 要素(#content)内の見出し要素を抽出して表示。
見出しを抽出する別ページ(sample1.html)のHTML
<html lang="ja"> <head> ・・・中略・・・ </head> <body> <div id="header"> <h1>Web Desing Leaves</h1> </div> <div id="container"> <div id="content"> <h2>Web サイト作成入門</h2> <h3>Web について</h3> <h4>Web ページ</h4> <ul> <li>インターネット上に公開している文書(ファイル)・・・</li> </ul> <h4>Web サイト</h4> <p>Web サイトには複数の Web ページが含まれていて、各 Web ページは・・・</p> <h3>Web サイト作成に必要な知識</h3> <p>Web サイト作成に必要な知識(代表的なもの)には・・・。</p> <h3>Web ページを作成する方法</h3> <p>・・・</p> </div><!-- end of #content --> <div id="side"> <h2>Side Bar</h2> </div><!-- end of #side --> </div><!-- end of #container --> <div id="footer"> <p id="copy"><small>Copyright <span>©</span> Web Design Leaves. All Rights Reserved.</small></p> </div><!--end of #footer--> </body> </html>
読み込む側(test01.html)の HTML
<body> <div id="index"></div> </body>
jQuery では load() を使って sample1.html の #content 内の見出し要素(:header)を test01.html にロードして表示。
jQuery
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script> jQuery(function($){ $('#index').load('samples/sample1.html #content :header'); }); </script>
load() の外側で、 $(‘#index’) の HTML をコンソールに表示してみると、何も表示されない(空文字列)。
jQuery(function($){ $('#index').load('samples/sample1.html #content :header'); console.log($('#index').html()); //コンソールに出力 });
コンソールには GET リクエストと(空文字列)と表示されているが、test01.html には抽出(取得)した見出しが表示されている。
この時表示されている test01.html の HTML を見てみると、以下のようになっていて、div 要素(#content)内に抽出した見出し要素が注入されている。
コールバック関数を使って応答テキスト(取得したデータ)をコンソールに表示してみる。
jQuery(function($){ $('#index').load('samples/sample1.html #content :header', function(response) { console.log(response); //コールバックで応答テキストをコンソールに出力 }); });
以下のように sample1.html の HTML 全てが出力される。
load() の第1引数の URL に jQuery のセレクタを指定して、取得する要素をフィルタしても、コールバック関数に渡されるパラメータ「response:応答テキスト」は常に GET でリクエストされた HTML 全体になっている。
それでは、以下のようにコールバック関数でターゲットの HTML をコンソールに出力すると。。。
jQuery(function($){ $('#index').load('samples/sample1.html #content :header', function() { console.log($(this).html()); //console.log($('#index').html()); でも同じ }); });
以下のように、見出し要素が表示される。
このことから(?)、ターゲットの要素へ注入する要素に何らかの操作するには、コールバック関数で処理する必要があるらしい。
別のページの見出しをそのまま見出しとして表示するのではなく、リスト(ul li 要素)として表示してみる。
jQuery(function($){ $('#index').load('samples/sample1.html #content', function() { //変数に必要な要素を記憶させてこの関数の中で処理する var index$ = $(this).find(':header'); //var index$ = $('#index').find(':header'); こちらでも同じ $('#index').html(''); //$(this).html('');でも同じ var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = 1; i <= 5 ; i++) { elem = 'h' + i; if($(this).is(elem)){ // $(this)は index$ の中の各要素(h要素) li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $('#index').append(ul$); //$(this).append(ul$);でも同じ }); });
表示される HTML
<div id="index"> <ul id="index_list"> <li class="h2_class">Web サイト作成入門</li> <li class="h3_class">Web について</li> <li class="h4_class">Web ページ</li> <li class="h4_class">Web サイト</li> <li class="h3_class">Web サイト作成に必要な知識</li> <li class="h3_class">Web ページを作成する方法</li> </ul> </div>
複数のページから見出しを抽出する場合、いちいち同じ記述を繰り返すのは面倒なので、関数にしておく場合の例。
function list_hx(target, url, start, end){ $(target).load(url, function() { var index$ = $(this).find(':header'); $(target).html(''); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = start; i <= end ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(target).append(ul$); }); } list_hx('#index', 'samples/sample1.html #content :header', 1, 5);
引数に $.extend を使う場合の例(あまり実用的ではないかも)。
関連ページ: $.extend を利用したパラメータ(引数)の整理
function list_hx(my_options){ var settings = $.extend({ target : '#index', //リストを表示する要素(必須:デフォルトはダミー) url: 'index.html', //URL(必須:デフォルトはダミー) filter : '', //取得するデータにフィルタをかける要素等 ul_id: 'index_list', //リスト(ul 要素)の id start : 1, //h1~h6 のどの要素を対象とするか(小さい方の数値を指定) end : 6, //h1~h6 のどの要素を対象とするか(大きい方の数値を指定) }, my_options || {}); $(settings.target).load(settings.url + '' + settings.filter, function() { var index$ = $(this).find(':header'); $(settings.target).html(''); var ul$ = $('<ul id="' + settings.ul_id + '"></ul>'); var elem, li; index$.each(function() { for(var i = settings.start; i <= settings.end ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(settings.target).append(ul$); }); } list_hx({url: 'samples/sample1.html', target:'#index', start:1, end:5});
表示する対象のページが多い場合は、以下のように引数に配列を渡した方がいいかもしれない。
function list_hx(targets, urls){ var length = targets.length; for(var i=0; i<length; i++){ $(targets[i]).load(urls[i], function() { var index$ = $(this).find(':header'); $(this).html(''); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var j = 1; j <= 5 ; j++) { elem = 'h' + j; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(this).append(ul$); }); } } var targets = ['#index1', '#index2']; var urls = ['samples/sample1.html #content :header', 'samples/sample2.html #content :header']; list_hx(targets, urls);
前述の配列を使った例などで、読み込む対象のページに変更があると毎回 jQuery も変更しなければならないので、読み込む側の HTML を工夫してみる。
以下のようにターゲット要素にクラス属性(list_h)を付与して、その内側に、読み込む対象のページのリンクを記述しておく。
HTML
<div class="list_h"><a href="samples/sample1.html"></a></div> <div class="list_h"><a href="samples/sample2.html"></a></div>
jQuery
jQuery(function($){ //引数にクラス名などのターゲット要素を指定 function list_hx(targets) { var targets$ = $(targets); var urls = []; targets$.each(function() { urls.push($(this).find('a').attr('href') + ' #content'); }); //for 文ではなく、each() を利用する場合 targets$.each(function(index) { $(this).load(urls[index], function() { var index$ = $(this).find(':header'); $(this).html(''); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = 1; i <= 5 ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(this).append(ul$); }); }); //for 文を使う場合の例 /*for(var i = 0; i < targets.length; i++) { targets$.eq(i).load(urls[i], function() { //targets$ はラップ集合なので eq() を利用 var index$ = $(this).find(':header'); $(this).html(''); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var j = 1; j <= 5 ; j++) { elem = 'h' + j; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(this).append(ul$); }); }*/ } list_hx('.list_h'); });
もし読み込む対象のページごとに絞り込む要素が異なる場合は、HTML5 の独自データ属性を使用する方法も考えられる。
HTML
<div class="list_h"><a href="samples/sample1.html" data-filter ="#content"></a></div> <div class="list_h"><a href="samples/sample2.html" data-filter ="#side"></a></div>
jQuery
jQuery(function($){ function list_hx(targets) { var targets$ = $(targets); var urls = []; targets$.each(function() { urls.push($(this).find('a').attr('href') + ' ' + $(this).find('a').data('filter')); }); targets$.each(function(index) { $(this).load(urls[index], function() { var index$ = $(this).find(':header'); $(this).html(''); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = 1; i <= 5 ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(this).append(ul$); }); }); } list_hx('.list_h'); });
コールバックでターゲットを操作するのではなく、応答テキスト(response)を使って別のページの見出しを表示してみる例。(この場合、load() ではなく、$.get() を使うほうが自然かも)
応答テキスト(response)は、load() の 第1パラメータ(URL)に、フィルタのための要素を指定しても常に読み込む HTML の全文を取得しているので、対象の範囲を絞るには、応答テキストを正規表現で絞り込む(フィルタする)必要がある。
function list_hx(target, url) { $(target).load(url, function(response) { response = response.replace(/<div id="side">[\s\S]*<\/html>/, ""); var hx = /<(h\d).?>(.+)<\/h\d>/g; var result_hx; $(this).html(''); var h_type_array = new Array(); var hx_array = new Array(); while((result_hx = hx.exec(response)) != null){ h_type_array.push(result_hx[1]); hx_array.push(result_hx[2]); } var my_html = '<ul>'; for(var i = 0; i < hx_array.length; i++){ my_html += '<li class="' + h_type_array[i] + '_class" >' + hx_array[i] + '</li>\n'; } $(this).html(my_html + '</ul>' ); }); } list_hx('#index','samples/sample1.html' );
関連ページ:ajax を使って更新を自動的に行う
HTML (load_01.html)
<body> <div class="list_index"> <h3><a href="samples/sample1.html">HTML</a></h3> <p><a href="samples/sample1.html" class="show_list">索引を表示</a></p> <div class="index_target"></div> </div> <div class="list_index"> <h3><a href="samples/sample2.html">CSS</a></h3> <p><a href="samples/sample2.html" class="show_list">索引を表示</a></p> <div class="index_target"></div> </div>
jQuery
jQuery(function($){ $(document).on('click', 'a.show_list', function() { var this$ = $(this); var url = this$.attr('href') + ' #content :header'; var target = this$.closest('.list_index').find('div.index_target'); target.load(url, function() { var index$ = $(this).find(':header'); $(this).html('').hide(); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = 1; i <= 5 ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); this$.hide(); $(this).append(ul$).fadeIn(); }); return false; }); });
CSS
ul { list-style-type: none; } .h2_class { font-weight: bold; } .h3_class { padding-left: 1em; } .h4_class { padding-left: 2em; }
サンプル1と同じ HTML の構造だが以下が異なる。
jQuery
jQuery(function($){ $(document).on('click', 'a.show_list', function() { var this$ = $(this); var text_display = "索引を表示"; var text_hide = "索引を隠す"; var url = this$.attr('href') + ' #content :header'; var target = this$.closest('.list_index').find('div.index_target'); if(!target.hasClass('loaded')){ target.load(url, function() { var index$ = $(this).find(':header'); $(this).html('').hide(); var ul$ = $('<ul id="index_list"></ul>'); var elem, li; index$.each(function() { for(var i = 1; i <= 5 ; i++) { elem = 'h' + i; if($(this).is(elem)){ li = '<li class="' + elem + '_class">' + $(this).text() + '</li>'; ul$.append(li); } } }); $(this).append(ul$).fadeIn().addClass('loaded').addClass('displayed'); this$.text(text_hide); }); }else{ if(target.hasClass('displayed')) { target.removeClass('displayed'); target.fadeOut(); this$.text(text_display); }else{ target.addClass('displayed'); target.fadeIn(); this$.text(text_hide); } } return false; }); });