jQuery – メニューをスクロールに付随させてみる

最近国内のサイトでもちょくちょく目にするようになった「スクロールに付随するメニュー(「ユニクロ 特集/+J FINAL COLLECTION | MEN – ユニクロオンラインストア[store.uniqlo.com]」のページの少し下の方にあるメニュー一覧のような動きになるもの 2011年12月2日時点)」を実装してみます。

この実装はすごく簡単で、スクロール位置と固定する要素の位置を比べ、スタイルを書き換えるだけです。

jQuery メニューをスクロールに付随させてみるサンプル(headerFixedBoxを固定)
jQuery メニューをスクロールに付随させてみるサンプル(asideFixedBoxを固定)

サイドバーに固定要素を置く場合は、フッターにかぶってしまうことがあると思うので、それを回避するように条件を加えてみました。

$(function(){
floatBox("#headerFixedBox");
floatBox("#asideFixedBox", 1);

//ele=固定する要素、flag=サイドバーに固定する要素があり、フッターにかぶらないようにする場合に「1」を指定
function floatBox(ele, flag) {
	//固定する要素を取得
	var box = $(ele);
	//固定する要素の位置を取得
	var fixed_box_offset = box.offset();
	//固定する要素のサイズを取得
	var box_size = {"width": box.width(), "height":  box.height()};
	//フッター要素の位置を取得
	var footer_box_offset = $("#footer").offset();
	//スクロールイベントが発生したら実行
	$(window).scroll(function() {
		//スクロール位置を取得
		var scroll_val = $(this).scrollTop();
		//固定する要素の位置よりスクロール位置が大きくなれば...
		if(scroll_val > fixed_box_offset.top) {
			//固定する要素にtop:0が指定されていなければ...
			if(box.css("top") != 0) {
				//スタイルを追加
				box.css({
					"position": "fixed",
					"z-index": 999,
					"width": box_size.width,
					"height": box_size.height,
					"top": 0,
					"bottom": "auto"
				});
			}
			//フッターがあり、横メニューがかぶらないようにする場合は...
			if(flag == 1) {
				//フッターの位置よりスクロール位置が大きくなれば...
				if(scroll_val > (footer_box_offset.top - box_size.height)) {
					//スタイルを追加
					if(box.css("bottom") != 0) {
						box.css({
							"position": "absolute",
							"z-index": 999,
							"width": box_size.width,
							"height": box_size.height,
							"top": "auto",
							"bottom": 0
						});
					}
				}
			}
		//固定する要素の位置よりスクロール位置が小さければ...
		} else {
			//固定する要素のstyle属性を削除
			box.removeAttr("style");
		}
	});
}
});

あとは固定する要素の位置を取得するための、もととなる要素のCSSに「position: relative;」を指定します。

/*
#headerFixedBoxのもととなる要素
*/
#wrap {
	position: relative;
	margin: 0 auto;
	width: 900px;
}
/*
#asideFixedBoxのもととなる要素
*/
#aside {
	position: relative;
	float: right;
	width: 280px;
	min-height: 1600px;
	background: #111;
	color: #eee;
}

と、これでスクロールしてもついてくるメニューの完成です。

コピペですぐ使えるように関数化しているのですが、関数内にフッター要素のIDを直接していしている箇所があります。もし利用される場合は、関数内の「#footer」のところを、ご自身のサイトのフッターに割り当てているIDに変更してください。

	//フッター要素の位置を取得
	var footer_box_offset = $("ここを書き換え").offset();

今回はスクロールしてもついてくるメニューということで簡単なものをつくりましたが、これを元にして、ある一定箇所までスクロールしたら要素を表示させる、といったこともできます。

ソースをいじってテストできるようにJS Binにも置いておきました。いろいろ確認してみたい方はどーぞ。

JS Bin ソース確認用

GET送信時のURLのパラメータの値を取得する

「○○○.com?page=5&sort=desc」等のGET送信時のパラメータの値をJavascriptで取得する方法。

function getUrlParam(){
	var vars = [], param;
	if(param = location.search){
		var parray = param.replace('?','').split('&');
		for(var i=0; i<parray.length; i++){
			var n = parray[i].split('=');
			vars[n[0]] = n[1];
		}
	} else {
		return false;
	}
	return vars;
}
var prm = getUrlParam();
prm["page"]; //5
prm["sort"]; //desc

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