jQuery – 目的の場所にさくっと要素を追加する

いろんなセレクタ指定方法+αを覚えて、目的の要素をさくっと取得する」で要素をさくっと選択できるようになったら、次は選択した要素を元に、さくっと新しく要素を追加する方法を覚えて見ましょう。

「新しく要素を追加する」というのはAjaxで外部データを読み込み、リスト一覧を表示させる場合などに頻繁に利用します。たとえばtwitterからデータを読み込んでサイドバーに表示する、といった場合です。

他にもホームページに新しい商品を追加して「NEW」という画像を表示することがあると思いますが、一ヶ月後には消したいという場合、直接HTMLに書き込んでいると、いちいち修正しないといけません。それをうまくJavascriptで追加するようにして上げれば、修正の必要がなくなります。

class名に日時を添えて、そのclass名につけられた日時と現在の日時と比べて処理をさせます。少しスクリプトは荒い例ですが、下記のような感じです。

<script>
$(function(){
	var now = new Date(); //現在の日時を取得
	var h1Class = $("h1").attr("class"); //h1のclassを取得
	var aDate = h1Class.replace("new","").split("-"); //取得したclassを整形
	var add_date = new Date(aDate[0], aDate[1], aDate[2]); //Dateオブジェクトに変換
	//もし現在が日時がclassで指定した日時より前なら画像を表示
	if(now < add_date) $("h1.new2011-12-21").append('<img src="new.gif">');
});
</script>
<!-- class名に画像の表示年月日を付ける -->
<h1 class="new2011-12-21">新色 ふかふか手編みマフラー</h1>

このように新しく要素を追加する方法を知っておくと、ちょっとしたスクリプトで手間を省く事ができます。

新しい要素を追加するといっても、対象の要素の前に追加、中に追加、包み込む、等いろいろなものが用意されています。ではではセレクタのとき同様、動作サンプル&簡易説明書きをチェックしてみてください。

jQuery DOM操作(Manipulation)系メソッド動作サンプル

[ DOM操作(Manipulation) ]

$(“div.box”).after(“<div>…</div>”)
CLASS名 box が指定されたdivタグの後に<div>…</div>を追加

$(“<div>…</div>”).insertAfter(“div.box”)
<div>…</div>をCLASS名 box が指定されたdivタグの後に追加

$(“div.box”).before(“<div>…</div>”)
CLASS名 box が指定されたdivタグの前に追加

$(“<div>…</div>”).insertBefore(“div.box”)
<div>…</div>をCLASS名 box が指定されたdivタグの前に追加

$(“div.box”).append(“<div>…</div>”)
CLASS名 box が指定されたdivタグの子要素の最後に<div>…</div>を追加

$(“<div>…</div>”).appendTo(“div.box”)
<div>…</div>をCLASS名 box が指定されたdivタグの子要素の最後に追加

$(“div.box”).prepend(“<div>…</div>”)
CLASS名 box が指定されたdivタグの子要素の最初に<div>…</div>を追加

$(“<div>…</div>”).prependTo(“div.box”)
<div>…</div>をCLASS名 box が指定されたdivタグの子要素の最初に追加

$(“div.box”).wrap(“<div>…</div>”)
CLASS名 box が指定されたdivタグを<div>…</div>をで包み込む
(複数ある場合は各それぞれを包み込む)

$(“div.box”).wrapAll(“<div>…</div>”)
CLASS名 box が指定されたdivタグすべてを<div>…</div>をで包み込む
(複数ある場合はすべてを一つに包み込む)

$(“div.box”).wrapInner(“<div>…</div>”)
CLASS名 box が指定されたdivタグの子要素を<div>…</div>をで包み込む

$(“div.box”).clone().appendTo(“div.boxA”)
「$(“div.box”).clone()」でCLASS名 box が指定されたdivタグを複製
「appendTo(“div.boxA”)」で複製したものを、CLASS名 boxA が指定されたdivタグの子要素の最後に追加

$(“div.box”).replaceWith(“<div>…</div>”)
CLASS名 box が指定されたdivタグを<div>…</div>に入れ替える

$(“div.box”).remove()
CLASS名 box が指定されたdivタグを削除(中身もすべて)

今回はManipulation系の中でも新しく要素を追加するものを抜粋して紹介しています。本家ドキュメントではカテゴリが細かく分けられていますが、新しく要素を追加するものはほぼ紹介できていると思います。その他のManipulation系メソッドも知りたい方は、ぜひ本家ドキュメントをのぞいて見て下さい。

Manipulation – jQuery API

jQuery – いろんなセレクタ指定方法+αを覚えて、目的の要素をさくっと取得する

ずいぶん以前にセレクタについて書いたのですが、今回はセレクタの種類を抜粋して、記述例と説明書きにまとめてました。「セレクタとは?」という方は、まず下記記事を読んでみて下さい。

jQueryを使ってみよう。(基本編 セレクタ1)

+αというのはトラバース(走査)系のメソッドです。「この要素を抜き出したい!」と思ったときにセレクタだけでは抜き出しにくい場合があります。そういうときにトラバース(走査)系のメソッドを使うと、簡単にできたりするので覚えておくと便利なものです。

「こういう書き方をすると、こういう要素が選択される」という例で説明を添えていますが、数が多いので説明書きは、ほんとうに添えた程度です。説明だけではわかりにくいと思うので動作サンプルを用意しました。動作サンプルを眺めながら、ちらっと説明書きをチェックしてもらえれば「なるほど!」となるはず。。。ご利用ください。

jQuery セレクタ&トラバース動作サンプル

[ セレクタ ]

$(“body”)
bodyタグの要素を選択

$(“#id1”)
ID名 id1 の要素を選択

$(“.class1”)
CLASS名 class1 の要素を選択

$(“.class1 .class2”)
CLASS名 class1 の要素の中にあるCLASS名 class2 の要素を選択

$(“.class3, .class4”)
CLASS名 class3、もしくはCLASS名 class4 の要素を選択

$(“.class5”, “#id1”)
ID名 id1 の要素の中にあるCLASS名 class5 の要素を選択

$(“.class6.class7”)
CLASS名 class6 と class7 2つ持つ要素を選択

$(“a[href]”)
aタグのhref属性がある要素を選択

$(“a[href = ‘#pagetop’]”)
aタグのhref属性の値が「#pagetop」の要素を選択

$(“a[href != ‘#pagetop’]”)
aタグのhref属性の値が「#pagetop」でない要素を選択

$(“a[href ^= ‘#link’]”)
aタグのhref属性の値が「#link」から始まる要素を選択

$(“a[href $= ‘bottom’]”)
aタグのhref属性の値が「bottom」で終わる要素を選択

$(“a[href *= ‘page’]”)
aタグのhref属性の値に「page」が含まれている要素を選択

$(“ul li:first”)
すべてのulタグ内をあわせたliタグの中の最初の要素を選択

$(“ul li:first-child”)
各ulタグ内にあるそれぞれのliタグの最初の要素を選択

$(“ul li:last”)
すべてのulタグ内をあわせたliタグの中の最後の要素を選択

$(“ul li:last-child”)
各ulタグ内にあるそれぞれのliタグの最後の要素を選択

$(‘li:not(“.class6”)’)
liタグでCLASS名 class6 が指定されていない要素を選択

[ トラバース ]

要素については先祖、親子、兄弟という階層が存在します。

<div>
	<ul>
		<li>兄</li>
		<li>この要素から見て....ul要素は親、div要素は先祖</li>
		<li>弟</li>
	</u/>
	ul要素からみるとli要素は子、div要素は親ということになります。
</div>

以下説明に子要素や兄要素等の言葉がでてきますが、簡単に説明すると上記のような感じなのでイメージできれば簡単です。

$(“#id1”).find(“.class7”)
ID名 id1 の要素の中にあるCLASS名 class7 の要素を選択

$(“ul”).children(“.class6”)
ulタグ の子要素にある CLASS名 class6 の要素を選択

$(“li.class6”).parent()
CLASS名 class6 があるliタグを持つ親要素を選択

$(“li.class6”).parent(“#id1”)
CLASS名 class6 があるliタグを持つ親要素でID名 id1 の要素を選択

$(“li.class6”).next()
CLASS名 class6 があるliタグに隣接する弟要素を選択

$(“li.class6”).next(“.class7”)
CLASS名 class6 があるliタグに隣接する弟要素の中でCLASS名 class7 の要素であれば選択
(それ以外であれば選択しない)

$(“li.class7”).prev()
CLASS名 class7 があるliタグに隣接する兄要素を選択

$(“li.class7”).next(“.class6”)
CLASS名 class7 があるliタグに隣接する兄要素の中でCLASS名 class6 の要素であれば選択
(それ以外であれば選択しない)

$(“a[href ^= ‘#link’]”).closest(“li”)
aタグのhref属性の値が「#link」から始まる要素の最も近いliタグ(親要素)を選択

$(“li”).slice(“3,12”)
すべてのliタグをあわせた0から数えて3個目から12個目までの間の要素を選択

$(“li”).find(“a”).css({color: ‘white’}).end()
liタグ内にあるaタグにスタイルを追加した後、直前の要素を選択

$(“li”).not(“li.class6”)
すべてのliタグでCLASS名 class6 が指定されていない要素を選択

$(“a[href *= ‘middle’]”).first()
aタグのhref属性の値に「middle」が含まれている一番最初にある要素を選択

$(“a[href *= ‘middle’]”).last()
aタグのhref属性の値に「middle」が含まれている一番最後にある要素を選択

$(“p”).siblings()
pタグの兄弟要素を選択

$(“p”).siblings(“p”)
pタグの兄弟要素の中でpタグの要素を選択

この他にもCSS2、3系のセレクタ、フォーム関連のセレクタ等、まだまだたくさんあります。もっと詳しく動作内容を知りたい場合は、jQuery本家ドキュメント「Selectors – jQuery API」「Traversing – jQuery API」で確認してみてください。

jQueryプラグインを使わずに自前カルーセルパネルを関数化

jQueryプラグインを使わずに自前カルーセルパネルを導入してみる」で作成したものを使い回しができるよう関数化してみました。

プラグインを使わずにカルーセルパネル(関数化)

プラグインにすると少しカスタマイズの難易度が上がる気がする、もっと機能がついたものたくさん配布されているのでこれを使う理由があまりない、「自前で」と銘打ってる、ということで関数にしました。

あくまでも「ちょっとJavascriptを触って勉強がてらカスタマイズに挑戦して導入もできるように」ということが目的です。ですので、前記事「jQueryプラグインを使わずに自前カルーセルパネルを導入してみる」のjavascriptと比べつつ眺めてもらえればと思います。

さて、関数化するにあたり使い回しができるようにすために「横型、縦型、両方利用できる」「複数設置可能にする」ということを考慮し、単純に引数で判定することにしました。

「引数」というのは、簡単にいうと「関数に渡す値」のことで、『関数名(引数1,引数2,…)』という形で利用します。

carouselPanel("#carouselwrap", "left", 1);

今回作成したものは上記のように、この引数に指定された値を元にJavascriptの処理を振り分けています。で、できあがったものは下記。

/* Copyright (c) 2011 detelu (http://www.detelu.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * carouselPanel.js
 * Version: 2011-11-18
*/
//id=ターゲットになる要素のid名、posmove=横に動かしたい場合はleft,縦はtop、limove=スライドさせるliの数を引数として設定
function carouselPanel(id,posmove,limove) {
	var carousel_size,ul_size,ul_w_size,ul_h_size,li_move_top,li_move_left;
	//ターゲットになる要素を変数 tgt に代入
	var tgt = $(id);
	//tgtの要素の中に戻る、進むボタンを追加
	tgt.append('<div class="prev hide"></div><div class="next show"></div>');
	//tgtの要素の中からulタグ要素を抜き出し変数 tgt_ul に代入
	var tgt_ul = tgt.find("ul");
	//tgtの要素の中からliタグ要素を抜き出し変数 tgt_li に代入
	var tgt_li = tgt.find("li");
	var li_move = limove;
	var li_w_size = tgt_li.outerWidth();
	var li_h_size = tgt_li.outerHeight();
	var li_num = tgt_li.size();
	//引数 posmove に left が指定されていたら 横に動かすのに必要な値を変数に代入していく
	if(posmove == "left") {
		carousel_size = tgt.width();
		ul_w_size = li_w_size*li_num;
		ul_h_size = li_h_size;
		ul_size = ul_w_size;
		li_move_top = 0;
		li_move_left = li_w_size*li_move;
	//引数 posmove に top が指定されていたら 縦に動かすのに必要な値を変数に代入していく
	}else if(posmove == "top") {
		carousel_size = tgt.height();
		ul_w_size = li_w_size;
		ul_h_size = li_h_size*li_num;
		ul_size = ul_h_size;
		li_move_top = li_h_size*li_move;
		li_move_left = 0;
	}
	tgt_ul.css({position: 'absolute',top: '0',left: '0', width: ul_w_size+'px', height: ul_h_size+'px'});
	var tgt_prev = tgt.find("div.prev");
	var tgt_next = tgt.find("div.next");
	tgt_prev.click(function(){
		//クリックされた要素(ここではclass名 prevの要素)にclass名 hideが指定されていなければ以下を実行
		if(!$(this).hasClass('hide')){
				tgt.find('ul:not(:animated)').animate(
				{top:'+='+li_move_top, left:'+='+li_move_left},
				600,
				function(){
					var ul_pos = boxPosition(tgt_ul, posmove);
					//tgt_next に代入されている要素のclass hide を取り除き、class show を追加
					tgt_next.removeClass("hide").addClass("show");
					if(ul_pos === 0) {
						tgt_prev.removeClass("show").addClass("hide");
					}
				}
			);
		}
	});
	//クリックされた要素(ここではclass名 nextの要素)にclass名 hideが指定されていなければ以下を実行 以下略
	tgt_next.click(function(){
		if(!$(this).hasClass('hide')) {
			tgt.find('ul:not(:animated)').animate(
				{top:'-='+li_move_top, left:'-='+li_move_left},
				600,
				function(){
					var ul_pos = boxPosition(tgt_ul,posmove);
					tgt_prev.removeClass("hide").addClass("show");
					if(carousel_size >= (ul_size + ul_pos)) {
						tgt_next.removeClass("show").addClass("hide");
					}
				}
			);
		}
	});
	function boxPosition(ele,pos) {
		var position = ele.position();
		return position[pos];
	}
}

と、このように書き直してみました。少しだけ補足。

var tgt = $(id);

ここでjQueryを利用して引数 id に指定された要素を取得し、変数に代入しています。変数に代入しているのは、$(id)で抜き出した要素を何度か利用するためです。

たとえばjQueryは$(“#abc”)という記述があるたびに、HTMLの中で「id=abc」が指定された要素を探して抜き出す、という処理を行います。もし$(“#abc”)という記述が10個あれば、その度に「id=abc」が指定された要素を探して抜き出すという処理をさせることになるのです。

この「探して抜き出す」という処理を何度も行わせないために、一度抜き出したものを変数に代入しておいて、以降は変数に代入されている要素を利用するようにしています。処理速度を上げるための一個のポイントなので、覚えておくと損はないです。

ちょっとした記述の違いで処理速度が大幅にかわることもあります。記事は古いですが下記「てっく煮ブログ」さんがとても参考にります。あと英語ですがもっと詳しく知りたい方は「jQuery Proven Performance Tips And Tricks (Slides)」は必見の内容です。英語はちょっと…、という方はgoogle先生に聞いてみて下さい。

jQuery を高速に使う CSS セレクタの書き方 – てっく煮ブログ
jQuery Proven Performance Tips And Tricks (Slides)
jquery 高速 – Google 検索

var tgt_ul = tgt.find("ul");

ここでも同じように要素を代入しているのですが、jQueryのfindメソッドを利用して要素を抜き出しています。ここでは変数 tgt に代入されている要素の中の ul を抜き出し、変数 tgt_ul に代入しています。

.find() – jQuery API
find([expr]) – jQuery API 1.4.4 日本語リファレンス – StackTrace

※本家ドキュメントは日本語がないので、バージョン違いですが日本語リファレンスを掲載しているサイト「StackTrace」さんのリンクを張らせて頂いてますが、バージョンが違うと挙動が異なることもあり、jQuery本家のドキュメントと比べながら利用しましょう。

ドキュメントについては、下記もおすすめです。こちらも古いのですが、逆引きになっているので、jQueryでどんなことができるのかをざっくり確認しながら利用できます。

jQuery逆引きリファレンス - @IT

最後にこの関数を利用方法を。jQueryと関数を記述したファイルを読み込んで、下記のように指定します。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="carouselPanel.js"></script>
<script>
$(function(){
	//carouselPanel("カルーセルパネルのid名", "left(左右に動かす) or top(上下に動かす)", 戻る、進むでスライドさせるliの数);
	carouselPanel("#carouselwrap", "left", 1);
});
</script>

HTML、CSSについては「jQueryプラグインを使わずに自前カルーセルパネルを導入してみる」で作成したものとあまり変わりませんが、HTMLのid属性はページ内で同じものを複数記述するのは規則違反になるので、複数設置可能できるよう prev, next, carouselの id指定をclass指定に変更しています。ファイル一式ダウンロードできるようにしたので、そちらのぞいてください。

カルーセルパネル関数 – ファイル一式ダウンロード

もしそのまま利用したい方はご自由にお使いください。もちろん改変もご自由にどーぞ。