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;
});
});