Ch.2 Creating the wrapped element set

第二章會詳細介紹$()的兩個常用的功能: selectors 跟 創建新的DOM elements

2.1 Selecting elements for manipulation

在操作任何動作前 都必須要先會取得自己需要操作的elements
這邊有提供一個可以下載來練習selectors的Selectors Lab網頁
可以在原文版的首頁下載得到
(找到一個名字為Source code的連結下載)

2.1.1 Using basic CSS selectors

一開始先講解幾個基本的css selectors
這可以咕狗研究一下
而jQuery就是在$()裡使用selectors

//這個就是取得<p>中有class=specialClass的<a>
$("p a.specialClass")
2.1.2 Using child, container, and attribute selectors

而當需要取得更精細更複雜的selectors 時
就可以用到jQuery內建的功能

首先以child selectors來說
大意就是說 如果要取得特定的elements
ul.mylist > li > a 可以比 ul.mylist li a取得更精確的elements
有包含 > 的是指有上下層關係(也就是parents跟child的關係) li一定在ul下面一層 而a一定在li下面一層
沒有 > 的就是指所有包在裡面的都算在內 不管隔了幾層

而attribute selectors就是
可以對各tag的屬性再做篩選 挑出所需要的elements

//所有<a>中 屬性href的開頭為http://的<a>
a[href^=http://]
//所以這邊使用 ^ 來代表字的開頭的意思 跟正規表達式的一樣

以下是幾個用法

//取得所有 type=text的<input>
input[type=text]

//取得所有 title的開頭為my的<div>
div[title^=my]

//取得所有 href的結尾為.pdf的<a> (這也與正規表達式的 $ 一樣)
a[href$=.pdf]

//取得所有 href的值中有包含jquery.com字串的<a>
a[href*=jquery.com]

而container selector指的是有包含所指定的selector

//取得 含有<a>的<li>
li:has(a)

//但是要注意這個只能夠使用一層 如果是下面這樣
foo:not(bar:has(baz))
//或是
foo:not(bar:has(baz:eq(2)))
//都是無法使用的

然後書中有附一張簡表 說明各用法
也可以在官網的documentation中找得到

2.1.3 Selecting by position

jQuery也可以依據elements間的位置關係取得所需要的elements

//取得 第一個<a>
a:first

//取得 所有奇數的<p> (也就是第1,3,5,7 ...個的<p>)
p:odd
//當然也可以取得偶數的
p:even

//取得 <li>中最後一個child element (也就是<li>下一層中 最後一個element)
li:last-child

這邊也有附一個簡表 詳情請看官網的documentation

而這邊有一點要注意的是
使用:nth-child(n)的時候 這個n是從1開始算起 (1-based)
而其他的如 :eq(n) 或是 :gt(n) 這些是從0開始算起 (0-based)
所以使用:nth-child(2)會等於使用:eq(1)

2.1.4 Using custom jQuery selectors

這小節主要是介紹除了css中可以使用的selectors之外
jQuery自己內建的filter selectors
(filter就是過濾器、過濾、篩選的意思)
這邊也有附一個簡表 詳情請看官網的documentation

這些filter selectors大部分都是跟form有關的
下面舉幾個例子

//取得正在作特效(animations and effects)的elements
:animated

//取得checkbox (這裡就等於input[type=checkbox])
:checkbox

//取得內容有child elements(只有文字也算)的elements (也就是還有下一層)
:parent

//這些selectors也可以連著用
:checkbox:checked:enabled

如果想要選擇與selectors的規則相反的filter
可以使用:not

//取得不是checkbox的input
input:not(:checkbox)

:not這個filter selector中 只能放filter

//例如下面這樣是不行的
div :not(p:hidden)

//而這樣是ok的
div p:not(:hidden)
2.2 Generating new HTML

建立新的html elements
這裡還有提到一個簡略的方法
如果是要建立一個空的element

//這個的用法
$("<div>")
//會與下面這兩個一樣
$("<div></div>")
$("<div/>")
2.3 Managing the wrapped element set

操作取得的elements
這邊提供了另一個Selectors Lab可以練習
可以在原文版的首頁下載得到
(找到一個名字為Source code的連結下載)

2.3.1 Determining the size of the wrapped set
size()

取得selector所會操作的elements個數 使用size()

$('a').size()

例如取得頁面上有幾個連結(也就是<a>)

2.3.2 Obtaining elements from the wrapped set
get()

因為jQuery可以把一個取得的elements當作一個array來使用
所以如果要取得特定的element 可以依照他的index獲得
例如要取得第一個element

//可以使用
$('img[alt]')[0]
//而如果要用method來取得的話 可以使用get()
$('img[alt]').get(0)

如果沒有填入index值的話 則會返回一個含有所有的elements的array

index()

而要取得某一個element在 一個selector中取得的elements 裡的index
(也就是排序的位置 第一個就是0 第二個就是1)
可以使用index()

//取得 bid=findMe的<img> 在所有<img>中的index
var n = $('img').index($('img#findMe')[0]);

如果要取得index的element不在這些elements裡 則會返回-1

2.3.3 Slicing and dicing the wrapped element set
add()

在已經取得的elements之外 再取得另外的elements一起作操作

//對含有alt屬性的<img>操作
$('img[alt]')
//除了含有alt的<img>之外 再加上含有title的<img> 再一起對這些符合條件的elements操作
$('img[alt]').add('img[title]')
//當然在這個例子中 如果使用下面這樣也是可以
$('img[alt],img[title]')
//但是如果要先對含有alt的<img>操作 再對這兩種elements操作
//就必須要用到add()了
//
//在add()裡也可以加入新建立的html elements(像是2.2講的那樣)
$('p').add('<div>Hi there!</div>')
not()

可以加入特定的elements 同樣的也是可以減少
這邊使用的not() 有點類似前面講的:not
而這個not()的使用的方法就跟add()一樣

//取得有title屬性 但是title值不包含puppy這個字串的<img>
$('img[title]').not('[title*=puppy]')
filter()

除了add()跟not()之外
如果需要更多條件來挑出需要的elements
可以使用filter()

//取得所有innerHTML為數字的<td>
$('td').filter(function(){return this.innerHTML.match(/^d+$/)})

filter()跟not()的用法有點類似
但是條件剛好是相反的

//這裡是指篩選出title值含有dog字串的
$('img').addClass('seeThrough').filter('[title*=dog]').addClass('thickBorder')
//但如果是not() 就是把title值含有dog字串的拿掉
$('img').addClass('seeThrough').not('[title*=dog]').addClass('thickBorder')

add()、not()、filter()三種method可以很靈活的增減所需要的elements

slice(begin,end)

取得elements中特定的index的element(例如index為2~5的elements)
slice()有兩個參數 型態都是數字 皆由0開始算(zero-based)
第1個參數begin 為開始取得的index值 如果為負數就是由尾巴開始取值
第2個參數end 就是要取到第幾個為止 如果省略的話就是取到最後(這個參數所指的該index不會被取得 只會到前一個)

//取得頁面上前4個elements
$('*').slice(0,4);
//取得頁面上除了前4個elements之外的elements 也就是從第5個element開始取得 到最後1個
$('*').slice(4);
2.3.4 Getting wrapped sets using relationships

這邊有一個簡表列出其他可以篩選出elements的methods
詳情請看官網的documentation
這些methods返回的都是新的一組elements 不會影響到原本的elements
下面舉幾個例子

//取得該elements所有的child elements
children()
//取得該elements的下一個同一層的element
next()
//取得該elements之後所有同一層的elements
nextAll()
//取得該elements的所有同一層不重複的elements
siblings()

這些methods除了contents()之外 其他的都可以再在裡面用字串來篩選出elements

2.3.5 Even more ways to use a wrapped set
find()

對一組已經篩選出的elements作另一個selectors的篩選

//取得在<p>中的<span>
$("p").find("span")

雖然上面這個例子跟$(‘p span’)的用法一樣
但是如果需要在chains中使用 就必須用到find()

contains()
//取得在<p>中有包含'Lorem ipsum'這個字串的elements
$('p').contains('Lorem ipsum')

對一組已經篩選出的elements作字串的篩選

is()

對一組已經篩選出的elements作另一個selectors的查找 是否有包含此selectors

//檢查頁面上是否有至少一個<img>
var hasImage = $('*').is('img');

返回值是個boolean
如果有找到就是返回true 反之則是false

2.3.6 Managing jQuery chains

這小節會說明2個在chain中變換可以操作的elements的method

end()

在一個chain中如果先變換了操作的elements
但是在後面又要操作原本的elements
就要使用到end()
(clone()在ch3會講 這是一個複製elements的method)

$('img').clone().appendTo('#somewhere').end().addClass('beenCloned');

先對所有的<img>作複製
再把這些複製的elements加到id=somewhere的element中
而因為要再對原本的elements(所有<img>)加上class=beenCloned
所以加上end()後再加上addClass(‘beenCloned’)
如果沒有end() 而直接加addClass(‘beenCloned’)
那就是會加到複製的elements上 而不是原本的elements

andSelf()

在一個chain中如果先變換了操作的elements
但是在後面又要對原本的elements一起操作
就要使用到andSelf()

$("div").find("p").andSelf().addClass("border");

如果沒有加上andSelf() 就是只有<div>中的<p>會加上class=border
如果加上了 就是 <div> 跟 <div>中的<p> 都會加上class=border