「jQuery」カテゴリーアーカイブ

jQueryゼロから / オートロード(スクロールすると次のページを自動読み込み)

画面下までスクロールすると次のページを読み込んでくれるヤツですね。
イロイロ見てると次のような考え方みたいす。

対象コンテンツの下端の位置座標が表示エリア(ウィンドウ下端)に近づいたら、続きを読み込みます。これを、ウィンドウをスクロールした時にチェック。

まず、コンテンツの下端の位置座標を求める。対象エリアの id 属性が target なら、以下。

1
var contentBottom = $('#target').offset().top + $('#target').height();

offset().top で対象がページの一番上からどの高さにあるかがわかるので、これに対象の高さ height() を足して求めます。

次に、今どの位置までウィンドウに表示されているか求める。

1
var displayBottom = $(window).scrollTop() + $(window).height();

スクロール位置 scrollTop() にウィンドウの高さ height() を足せば、どこまで表示されているかがわかります。

あとは、画面スクロール時に両者を比較して次のページを読み込むか判断します。まあ、あんまりギチギチにしても仕方ないので、10px(超適当っす)くらい余裕をもたせることにします。

1
2
3
4
5
$(window).scroll(function(){
    if (contentBottom - displayBottom < 10){
        // ページ読み込み
    }
});

スクロールされてから画像をあとで読み込むヤツも同じコトしてるのかもね。それはまた今度。
サンプル

2011.04.21追記
スクロールイベントに登録した処理が複数読み込まれないよう排他制御入れました。詳しくはサンプルみてね。

jQueryゼロから / スライドショー(複数の画像をフェードイン・フェードアウト表示)

ありがちな画像をフェードインで複数見せるヤツです。
画像をクリックするとリンク先に飛ぶようにします。
下記のようにリンク付き画像をまとめて指定することにします。

1
2
3
4
5
<div id="target">
    <a href="http://..."><img src="A.png" /></a>
    <a href="http://..."><img src="B.png" /></a>
    <a href="http://..."><img src="C.png" /></a>
</div>

ただ、画像を重ねた状態でのフェードイン・フェードアウトってリンクとか他のタグがあるとうまくいかないので、画像だけになるようにJavaScriptでいったん再構成します。再構成後のHTMLは最大でもフェードインとフェードアウトの画像が2枚ある感じ。
あ、ついでに #target ではこの2枚の画像が重なるように CSS で position: absolute; を指定しときます。

1
2
3
4
5
// #target img { position: absolute; } で画像が重なるように指定
<div id="target">
    <img src="..." /> <!-- フェードインする画像 -->
    <img src="..." /> <!-- フェードアウトする画像 -->
</div>

とりあえず、もとのHTMLの #target から <a> タグを取り出して、eachループ内で画像ファイル名とリンク先のURLを集めることにします。

1
2
3
4
5
6
$('#target').find('a').each(function(){
    // 画像とリンクを集めとく(ループ内でthisは<a>タグ)
    var image = $(this).find('img').attr('src');
    var link = $(this).attr('href');
   ...
});

さらにスライドショー表示用に、あらかじめ<img>タグにクリックでリンク先のURLを開くようにしときます(clickイベントを指定)。これを適当な配列に入れときます。

1
2
3
4
5
...
var slide = $('<img>').attr('src', image).click(function(){
    window.open(link);
});
slides[slides.length] = slide;

画像はHTMLで上から指定した順に3秒置きに表示することにします。
もともとあったタグは一度リセットしちゃいます。

1
2
3
4
5
6
var index = 0;
// リセットして1枚目の画像だけ表示
$('#target').html(slides[index].clone(true));
setInterval(function(){
// フェードイン・フェードアウト処理
}, 3000);

index は 0 〜 slides.length – 1 の範囲に収まるようにします。超えたら 0 にリセット。
slides に格納したデータは clone(true) で複製します。そうしないと、フェードイン・フェードアウトや削除したりで影響を受けてしまうので、オリジナルは加工しないようにします。
ちなみに clone(true) の様に引数に true があると、関連付けられたイベントも複製してくれます。これで、さっき追加したクリックイベントが引き継がれます。

1
2
3
4
5
6
7
8
9
10
11
12
13
// setInterval のループ内
$('#target > img').fadeOut('slow', function(){
    $(this).remove(); // 表示中の画像はフェードアウトして削除
});

index++;
if (index >= slides.length){
    index = 0;
}

// 次の画像を複製してフェードイン
var image = slides[index].clone(true);
$('#target').prepend(image.fadeIn('slow'));

先にフェードアウトさせる方が、表示中の画像が1つなので jQuery で指定しやすいです。($(‘#target > img’) で指定)
IEなど透過ができないブラウザもありますが(jQuery で $.support.opacity で判定できます)画像だけならfadeIn / fadeOut で対応できるので特に判定は入れません。

任意の画像を表示するインターフェイスを用意したり、スライドアニメーションを停止したりなどの機能もあるとそれっぽいですが、とりあえず基本部分だけ。
サンプル

2011.11.03追記
よくあるナビもつけてみた
ナビ付きスライドショー

JavaScriptでWindowを操作

あんまりjQueryとか関係なく普通のJavaScriptですが、仕事でウィンドウの操作する必要があり調査も兼ねて。

画面サイズを取得
ウィンドウ開く前に画面のサイズがわかってた方がイイよね。

1
2
var screenWidth = screen.availWidth;
var screenHeight = screen.availHeight;

screen.width, screen.height でも問題ないけど、JavaScript でウィンドウ動かしたりするのでコチラで。

ウィンドウサイズの取得
ウィンドウのサイズを調べます。

1
2
var windowWidth = window.outerWidth;
var windowHeight = window.outerHeight;

IEでは outerWidth, outerHeight が使えないので innerWidth, innerHeight を使う。さらにバージョンでも違うみたいなので、jQueryで取得しても良いかも。

1
2
var windowWidth = $(window).width();
var windowHeight = $(window).height();

ウィンドウサイズは環境やブラウザによって違うのであまりアテにならない。JavaScriptでは指定するだけにとどめた方が良いかも。

ウィンドウを開く
定番過ぎますが一応。

1
var popup = window.open(location, name, option);

あとで操作できるように、適当な変数に保持します。引数の説明は下記。
location: URLの指定
name: window名
option: 下記の項目を key=value,key=value,… とカンマ区切りで指定

  • width: 横幅(innerWidth)
  • height: 縦幅(innerHeight)
  • left: ウィンドウ左端の位置(X座標)
  • top: ウィンドウ上端の位置(Y座標)
  • location: ロケーションバーの有無(yes / no)
  • menubar: メニューバーの有無(yes / no}
  • toolbar: ツールバーの有無(yes / no)
  • scrollbars: スクロールバーの有無(yes / no)
  • status: ステータスバーの有無(yes / no)
  • resizable: サイズ変更の可否(yes / no)

オプション指定しても、その通りにならないこともまああるよね。

ウィンドウを閉じる
開いたので閉じます。保持してた変数で指定。

1
popup.close();

ウィンドウの移動
座標の指定と、差分の指定ができます。座標指定はウィンドウの左上です。

1
2
popup.moveTo(x, y); // 座標指定
popup.moveBy(dx, dy); // 差分の指定

あ、自分自身は window.moveTo で移動します。例は、ポップアップの移動です。

ウィンドウサイズの指定
ウィンドウのサイズを指定します。サイズはウィンドウの左上を基点に変更されます。

1
popup.resizeTo(width, height);

ウィンドウの拡大縮小みたいなイメージの動作にしたければ、resizeTo と moveTo を併用するとよいかも。ウィンドウの中心が指定座標になるように、ウィンドウサイズの半分だけ位置を調整するとか。

これだけあれば、ウィンドウ自体のアニメーションぽいことは出来そうかな。
サンプル

jQueryゼロから / scale(画像を拡大縮小する)

scaleって意外にも無いんだけどね…
chrome / safari (あと多分IE) だと CSS で zoom プロパティで出来るみたい。

2011.07.17追記
CSS3のtransform使う場合はこちらを参照

1
2
3
img.zoom {
    zoom: 1.8;
}

だけどなるべくクロスブラウザで、と思ったので width / height で何とかならんかなと試してみた。

1
$('#target').css({ width: 58, height: 58 });

jQueryのcssでプロパティを直接いじるのだが、width, height は 180% とか指定できないのね。
なので、直接画像サイズを指定しました。(画像サイズ 32px × 1.8 ≒ 58px)

んで、結局何がやりたかったのかというと、オンマウスでぷるんと出来んかなと。
width / height をいじると画像の左上を原点として拡大するので、同時にtop / left もいじることに。
位置調整用に<span>とか何かしらのタグで囲いつつ、position: relative にしておいてください。

1
2
3
4
5
6
7
8
9
10
11
var option = { duration: 'fast', easing: 'easeOutElastic' };
$('#target').hover(function(){
  $(this).animate({ top: -13, left: -13 }, option)
         .find('img').animate({ width: 58, height: 58 }, option);
}, function(){
  $(this).stop(true, true)
         .css({ top: 0, left: 0 })
         .find('img')
         .stop(true, true)
         .css({ width: 32, height: 32 });
});

ユーザが素早い動き出来る場合は stop は必須ですね。(stopについてはこちらのサンプルにある追記部分を参照下さいませ)
じゃないと、アニメーションとリセットのタイミングがずれて、マウスを外したのに大きいままになっちゃったり。

それからアニメーションは jQuery デフォルトだと swing か linear しかないので、下記のアニメーション用プラグイン使いました。
jQuery Easing Plugin
jQuery Easing – jQuery 日本語リファレンス (動きの確認はこちらが参考になります)

あとは細かい数字を補足しておくと、animate に渡している width / height の 58px は、元画像 32px を約1.8倍したものですね。(1.8倍の根拠は無いです。最初の zoom で適当に 1.8 としたので…)
んで、top / left の -13px は画像の拡大が画像左上を基準にしてるので、画像の中心で拡大しているように見せかけるためです。
拡大前後の差から (58 – 32) / 2 = 13 なので、上方向、左方向に位置をずらしてます。
このとき動きがおかしくならないよう、拡大と移動の両方のアニメーションに同じ動きを指定するようにしてます。(変数 option で同じものを指定)
mouseleave は単に元の位置 (0, 0) と元のサイズ (32, 32) に戻してるだけです。
この辺は、デザインによっていろいろ変わるので調整するといいと思います。

サンプル

2011.07.17追記
CSS3のtransformを使用する場合は下記参照
Transform / 回転・拡大縮小

jQueryゼロから / hover (オンマウスでアニメーション)

mouseover / mouseout でもできるけど hover ( mouseenter / mouseleave) の方が便利なので。
例えば、ある要素にマウスが乗っかったらアニメーションしたい時に、その要素の上にボタンとかアイコンとかがあると、mouseover / mouseout イベントが発生して思うように動作しなかったりするので、その時は hover 使いましょ、と。
まあ、基本なんだろうけど細かい動作の違いを知っておくと助かる場面も。
※知らずにやって驚いただけなんだが…

1
2
3
4
5
$('#target').hover(function(event){
    // mouseover時の処理
}, function(event){
    // mouseout時の処理
});

サンプル
2011.01.29追記
hoverと組み合わせてstop使うと便利なので、サンプルに補足しました。

javascriptでfeedを読み込む

よそのサイトのfeedをjavascriptだけで取り込もうとすると、制限あってできないのよね。テストサイトなんだけどxmlだけは本番の拝借したいとかでひかかったり。
んで、これまでphp経由してやりくりしてたんだが、それGoogleのAPIにあるのね。
Google Feed API – Google Code

まずは、APIキー取得します。
Sign-up for an API Key – Google Loader – Google Code

このAPIのキー使って読み込みます。
いつもは直リンしてるjQueryも今回はgoogle.loadで読み込んでみます。

1
2
3
4
5
6
<script type="text/javascript" src="https://www.google.com/jsapi?key=【取得したAPIキー】"></script>
<script type="text/javascript">
google.load('feeds', '1');
google.load('jquery', '1.4.4');
google.setOnLoadCallback(/* ここに読み込み後の処理を書く */);
</script>

使い方も簡単で、feedのURIと表示数を指定するだけ。

1
2
3
var feed = new google.feeds.Feed('feedのURIを指定する');
feed.setNumEntries(10); // 省略可、省略時は4件
feed.load(/* feed読み込み後の処理 */);

あ、でも、jQueryもgoogle.loadで読み込んでるから、google.setOnLoadCallback以降じゃないと使えんので注意かな。jQueryは直接読んだほうが書きやすいかも。

1
2
3
4
5
6
7
google.setOnLoadCallback(function(){
    jQuery(function($){
        var feed = new google.feeds.Feed(feedUri);
        feed.setNumEntries(10);
        feed.load(feedDraw);
    });
});

あとは取得したfeedによってHTMLに出力するなり加工するなりすれば大丈夫。上の例ならfeedDrawって関数で処理するイメージです。(jQueryのonLoad後にしてるのは、feedDrawで出力時にDOMが生成されていて欲しいから。jsの記述自体をHTMLの最後の方に持ってくる、というのも手ですが)
サンプル(GoogleNewsのfeedを読み込んで表示)

jQueryの書き方

2011.08.16 もう少しまとめた → 続・jQueryの書き方

jQueryのプラグインが便利なのでイロイロ使っていると変数が衝突したり、prototype.js(最近は全然使わないなあ…)と同時に読むとコンフリクトしたりとかあるので、最低でも自分で書いたトコだけでも回避できると心配事がひとつ減っていいよね。
という事であちこち参考にしつつ、今現在使っている書き方を。

1
2
3
(function($){
// ここでは $ は jQuery として使える
})(jQuery);

だいたいこの記述を<head>タグ内に書くか、または<head>タグから<script>タグで読み込むので、onload後に処理をするために次のようにする事が多いかな。

1
2
3
4
5
(function($){
  $(function(){
    // onload後の処理はここに書く
  });
})(jQuery);

以前は $ を使わず全部 jQuery(‘#id’).click… のように書いてたけど、そんな事みんなせんのね…

2011.01.07 追記
コメントで下記のような書き方教えてもらいました。
こっちの方が見た目スッキリしていてカッコイイですね。

1
2
3
jQuery(function($){
  // onload後の処理はここに書く
});

jQueryゼロから / Tab Interface (処理を組み合わせる)

タブインターフェイスはプラグインごろごろ転がっているので、実際に使うのはそちらがいいと思うけど、jQueryの基本的な処理の組み合わせの練習で。
タブクリックに加えて、マウスオーバー入れたい場合もあって、調整する場合もあるし。

まずは適当にHTMLを決めちゃいます。タブとタブの中身の id 属性に統一ルールをつけるくらいかな。
あとは、タブの中身は最初は非表示にすることにします。

1
2
3
4
5
6
7
<span id="tab1" class="tab">タブ1</span>
<span id="tab2" class="tab">タブ2</span>
<span id="tab3" class="tab">タブ3</span>
<br style="clear: left;" />
<div id="target-tab1" class="target" style="display: none;">タブ1の内容</div>
<div id="target-tab2" class="target" style="display: none;">タブ2の内容</div>
<div id="target-tab3" class="target" style="display: none;">タブ3の内容</div>

jQueryでタブにロールオーバーやクリックのアクションを指定します。大まかに下記のような流れにします。

1
2
3
4
5
6
7
$('span.tab').mouseover(function(){
// マウスオーバー処理
}).mouseout(function(){
// マウスアウト処理
}).click(function(){
// クリック処理
});

タブの挙動は背景画像を入れ替えて対応することにします。
jQueryではマウスオーバーなどのイベントから対象となるDOMを拾ってこれるので、これを利用します。
※大体は this で間に合う事も多いですが

1
2
3
4
$('span.tab').mouseover(function(e){
  var target = e.currentTarget;
  $(target).css('background-image', 'url("tab_mouseover.png")');
});

マウスアウトもだいたい同じ。やってることは show / hide の時とほとんど同じ。
タブクリックで中身を展開します。展開には slideUp / slideDown を使います。今回は展開する対象が複数あるので、今どれが開いているかを変数 current で管理することにします。クリックされた状況に合わせて処理を分岐します。

1
2
3
4
5
6
7
8
9
10
11
12
13
$('span.tab').click(function(e){
  var target = e.currentTarget;
  if (current == target.id) {
    // 開いているタブをクリックした場合は閉じる
    current = false; // すべて閉じている
  } else if (current) {
    // 他のタブが開いている場合は、閉じてから対象のタブを開く
    current = target.id; // クリックしたタブが開いている
  } else {
    // タブが全てとじている場合は、対象のタブを開く
    current = target.id;
  }
});

タブを閉じるアニメーションが完了してから開く様な処理は jQuery で次のように指定します。

1
2
3
$('#target-' + current).slideUp('fast', function(){
  $('#target-' + target.id).slideDown('slow');
});

こんな感じでアニメーション(今回はslideUp)の引数に関数を渡すと、処理が完了してから実行してくれます。
サンプル

jQueryゼロから / SlideScroll (指定の要素を横スクロール)

スクロールと言ってもウィンドウではなく、ページの要素の一部をスクロールさせます。
まずは下記のような構成のHTMLを用意します。

1
2
3
<div id="scroll">
    <div id="layer"></div>
</div>

指定の枠(div#scroll)の中を要素(div#layer)が横スクロールする事にします。
内容は面倒なので下記のJavaScriptで自動生成させます。

1
2
3
4
5
for (var i = 0; i < 100; i++) {
    $('#layer').append('<span style="float: left;"><img src="space.gif" width="10px" height="100px" /></span>n');
}
$('#layer').find('span:odd').css('background-color', '#000000');
$('#layer').find('span:even').css('background-color', '#FFFFFF');

CSSで外枠からはみ出た部分は非表示にしつつ、スクロールする部分はposition: absoluteに。

1
2
3
4
5
6
7
8
9
10
11
12
13
<style type="text/css">
#scroll {
    width: 300px;
    height: 100px;
    overflow: hidden;
    position: relative;
}
#layer {
    width: 1000px;
    height: 100px;
    position: absolute;
}
</style>

あとは表示位置を少しずつずらせばスクロール出来ます。
setTimeoutの 1000 / 30 は秒30フレームで更新させたいので、1000ミリ秒を30で割り算してます。

1
2
3
4
5
6
7
8
9
10
11
$(function(){
    var x = 0;
    setTimeout(function(){
        $('#layer').css({ left: x });
        x--;
        if (x < -1000) {
            x = 0;
        }
        setTimeout(arguments.callee, 1000 / 30);
    }, 0);
});

サンプル

2011.01.28 追記
実際に無限ルーブさせるには、スクロール部分の両端が綺麗につながるようにします。上記サンプルでは単に座標リセットしてますが、単純な繰り返しパターンじゃない場合は、左端と同じ要素をのりしろ的に右端に追加したほうがいいです。(※意味不明だな…サンプルにも追記したので参照くださいな)

jQueryゼロから / BlackOut (Lightboxの背景のような効果)

2011.07.07追記: ウィンドウサイズ変えてもズレないようにこちらに修正
jQueryゼロから / BlackOutふたたび

Lightbox的な背景が暗くなるアレです。
背景用に適当に<div id=”layer”>とか用意しておいて、下記のようなCSS設定します。
注意するのはz-indexくらい?

1
2
3
4
5
6
7
8
9
10
11
12
<style type="text/css">
#layer {
    position: absolute;
    z-index: 100000;
    background: #000000;
    top: 0px;
    left: 0px;
    filter: alpha(opacity=0);
    opacity: 0.0;
    display: none;
}
</style>

クリックでこの<div>をウィンドウサイズにしてから、フェードインさせます。
とりあえず、トリガは<a class=”blackout”>にしておきます。

1
2
3
4
5
6
7
8
$('a.blackout').click(function(){
    var width  = $(document).width();
    var height = $(document).height();
    $('#layer').width(width)
               .height(height)
               .show()
               .fadeTo('slow', 0.8);
});

クリック後にWindowサイズを取得すれば、ページ読み込み後にWindowサイズを変えても問題ないです。ただ、Blackoutした状態でWindowサイズ変えると恥ずかしい感じになります…(2011.07.07 修正してます)
レイヤーをクリックすると閉じるようにしときます。

1
2
3
4
5
$('#layer').click(function(){
    $(this).fadeTo('fast', 0, function(){
        $(this).hide();
    });
});

サンプル