2011年9月12日月曜日

[JavaScript] [jQuery] jQuery.find() と jQuery.children() で子(子孫)要素を取得する

jQuery を使って、jQueryオブジェクトの子要素、子孫要素をまとめて取得する場合、.find().children()メソッドを使います。このエントリでは、以下のネストした<ul id="nav"> について、li要素を取得しながら、2つのメソッドの違いを確認してみます。
(以下すべてのコードでは、jquery-1.6.2.js を使用して動作を確認しました。)
<ul id="nav">
<li class="toplevel">sport
<ul>
<li>soccer</li>
<li>bascketball</li>
</ul>
</li>
<li class="toplevel">technorogy
<ul>
<li>windows</li>
<li>Mac</li>
</ul>
</li>
</ul>

.find()は子孫要素を、.children()は直接の子要素を


.find()は、jQueryオブジェクトのすべての子孫要素に対して、引数で渡したセレクタ式にマッチする要素を取得します。

var lis = $("ul#nav").find('li');
console.log(lis.length); // 6 (#nav 以下のすべてのli要素が取得された)

これは,単純に$()にセレクタを渡した場合や、$()に引数を2つ渡した場合と同じです。

var lis = $('ul#nav li');

var nav = $('ul#nav');
lis = $('li', nav);

また、jQuery バージョン1.6 からは,jQueryオブジェクト,DOM elementでもfilterできるようになりました。

var toplevel = $("li.toplevel");

var nav = $('ul#nav');
var lis = nav.find(toplevel);
alert(lis.length); //2 (class="toplevel" のli が取得された。)

.children()は直接の子要素に対して、セレクタに一致する要素を取得します。

var lis = $("ul#nav").children('li');
console.log(lis.length); // 2 (#nav の直接の子要素のli要素が取得された)

これは,単純に$()にセレクタを渡した場合や、$()に引数を2つ渡した場合()と同じです。

var lis = $('ul#nav > li');

var nav = $('ul#nav');
lis = $('> li', nav);

まとめ


  • .find()はすべての子孫要素に対して、引数で渡したセレクタに一致する要素を取得する。
  • .children()は直接の子要素に対して、引数で渡したセレクタに一致する要素を取得する。
  • .find()には、jQueryオブジェクトやDOM element を渡すことができる。

※推奨されない記法


$()に2つの引数(selector, jQuery object)渡して、直接の子要素を取得する場合、">" で子要素を指定できますが、jQuery のドキュメントを見ると、この書き方は推奨されない(将来のリリースではサポートされない)ようです。(http://api.jquery.com/child-selector/)

var nav = $("ul#nav");
var lis = $("> li", nav); // 推奨されない記法

上のコードは、.children()を使って以下のように書き換えられます。

var lis = ("ul#nav").children('li');

2011年9月7日水曜日

[JavaScript] [jQuery] jQuery.extend()でオブジェクトをマージ(ミックスイン)する

オブジェクトのマージ(ミックスイン)


$.extend()に2つ以上の引数を渡すと、2つ目以降の引数で渡されたオブジェクトを、最初の引数で渡されたオブジェクトにマージすることができます。

以下のコードでは、hogeオブジェクト に fooオブジェクトをマージしています。

(以下すべてのコードでは、jquery-1.6.2.js を使用しました。)

var hoge = {name: "hoge", width: "100px" };
var foo  = {width: "200px", height: "100px"};

hoge = $.extend(hoge, foo);

console.log(hoge.name);   // hoge
console.log(hoge.width);  // 200px  <- foo.widthの値で上書きされた
console.log(hoge.height); // 100px <- foo.heightが追加された

$.extend()に引数が1つしか渡されない場合は、引数のオブジェクトは、$(=jQuery)オブジェクトにマージされます。

var hoge = {name: "hoge", width: "100px" };
$.extend(hoge);
console.log($.width); //100px

ネストしたオブジェクトをマージしたい場合は、最初の引数にtrue を渡せばokです。

var hoge = { pos: { top: "0", left: "0" } };
var foo  = { pos: { top: "100" } };

//------------------------------------------------------------------------
//true を指定しない場合
hoge = $.extend(hoge, foo);

console.log(hoge.pos.top);  // 100
console.log(hoge.pos.left); //undefined <- hoge.posはfoo.posに置き換わった

//------------------------------------------------------------------------
//true を指定した場合
hoge = $.extend(hoge, foo);

console.log(hoge.position.top);  // 100
console.log(hoge.position.left); // 0  <- hoge.position はfoo.posとマージされた

何が便利なのか?


例えば、ユーザーが上書きできるデフォルト値を持つ関数を作りたい場合、以下のように、$.extend()でoptionsオブジェクトをparamsとマージすれば、ユーザーが指定したオプション値をデフォルトのオプション値をミックスしたオブジェクトが出来上がります。

以降の処理では、optinsオブジェクトからすべてのオプションにアクセスできます。

function foo(params){

var options = {
top : 20,
left: 100
}

options = $.extend(options, params);
//---略---
}

まとめ


柔軟なオプション指定が可能な関数、jQueryプラグインを開発したいときは、$.extend()でデフォルト値とユーザー指定値をマージする!