JQuery 初識及選擇器
cheet sheet cheet sheet 各版本 jQuery功能總覽
大概看這個表就可以了
簡介 jQuery 是一套 JavaScript 的 Library,它的核心程式並非包山包海,主要的功能還是在 DOM 文件的操作。
選擇器
初探
$( ) 工廠函數 , 這是JQuery的所有起點
$("div") 選取文件內所有的 <div> 元素
$("#body") 選取 id 為 body 的元素
$(".clsName") 選取 ClassName 為 clsName的所有元素
$("div#body") 選取所有的 Div 而且它的 id = body
$( "div.contents p" ) 選取所有的 Div 而且它的Class = contents 裡的 P元素
$( "div > p" ) 選取被div包住的下一層p
$( " div : has ( div ) " ) 選取至少有包住一個div的div
XPath選擇器
$ ( 'a [@title] ' ) 選擇所有超連結裡 有 title屬性的元素
$ ("div [ol] " ) div 元素裡 有一個 ol 元素
$ ( 'a [@href^="mailto:"] ' ) 取所有的電子郵件連結
$ ( 'a [@href=".pdf"] ' ) 所有 連結pdf的超連結元素
$ ( 'a [@href*="mysite.com"] ' ) 所有mysite.com頁面的連結
自訂選擇器
$ ( 'div.horizontal:eq(1)' ) 所有Div裡 className為 horizontal的第 2 個項目
$ ("div [ol] " ) div 元素裡 有一個 ol 元素
$ ( 'tr:odd ' ) :odd ,  tr 裡 所有 奇 數的元素
$ ( 'tr:even ' ) :even , tr 裡 所有 偶 數的元素
$ ( ' td :contains ("Henry") ' ) : contains("") , 所有 td 裡 包含 Henry 字元的 元素
$ ( ' tr : not([th]):even ' ) tr 裡 不是 th 的儲存格裡的偶數
所有的選擇器
$("*").css("","");
所有的元素 , 包含 head body....etc
$("*", document.body).css();
包含在body裡的所有的元素
 

以下整理常用的 Selector:

  • * 所有元素
  • E:nth-child(n) 傳回在所屬父元素下,排行第 n 的元素 E。(注意: 從 1 開始算,而非從 0)
  • E:first-child 傳回在所屬父元素下,排行第一的元素者(老大)
  • E:last-child 傳回在所屬父元素下,排行最後的元素者(老么)
  • E:only-child 傳回在所屬父元素下,是唯一子元素者(獨子)
  • E:empty 沒有任何子元素者(有文字也不算,例如 <span>TEXT</span> 就不合格)
  • E:enabled 未被停用的 UI 元素 E
  • E:disabled 被停用的 UI 元素 E
  • E:checked 被勾選的 UI 元素 E(適用於 Radio, Checkbox)
  • E:selected 被選取的 UI 元素 E(適用於 Select 下的 Option 元素)
  • E.myClassName CSS 類別設為 myClassName 的元素 E
  • E#myId id="myId" 的元素 E
  • E:not(s) 不符合 s 條件的元素 E,例如: $("span:not(:empty)") 即為找出有包含子元素的 span
  • E F 由包含在 E 底下的 F 元素 (不必直接為父子關係, 可為孫元素...)
  • E > F 找出父元素為 E 的 F 元素
  • E + F 找出緊接在 E 元素後方的 F 元素
  • E ~ F 找出緊接在 E 元素前方的 F 元素
  • E,F,G 取得 E、F、G 元素
  • E[foo] 有 foo 屬性 (Attribute) 的元素
  • E[foo=bar] 有 foo 屬性,且 foo 屬性值為 bar 的 E 元素
  • E[foo!=bar] 有 foo 屬性,且 foo 屬性值不等於 bar 的 E 元素
  • E[foo^=bar] 有 foo 屬性,且 foo 屬性值以 bar 開頭的 E 元素
  • E[foo$=bar] 有 foo 屬性,且 foo 屬性值以 bar 結尾的 E 元素
  • E[foo*=bar] 有 foo 屬性,且 foo 屬性值中包含 bar 字眼的 E 元素
  • E[foo=bar][baz=bop]  同時具備 foo 及 baz 屬性,且其值分別為 bar 及 bop 的 E 元素
  • :even 由選取結果中只挑出第雙數個
  • :odd 由選取結果中只挑出第單數個
  • :eq(N) and :nth(N) 由選取結果中取出第 N 個,由 0 起算
  • :gt(N) 由選取結果中只保留第 N 個以後者(不含 N)
  • :lt(N) 由選取結果中只保留第 N 個以前者(不含 N)
  • :first 選取結果中的第一個,等同於 :eq(0)
  • :last 選取結果中的最後一個
  • :parent 選取包含子元素者(文字內容也算,例如:<span>Text</span>)
  • :contains('test') 選取元素內的文字包含特定字串者
  • :visible 選取所有可見的元素(包含 CSS display=block 或 inline, visibility=visible 但不含<input type="hidden">)
  • :hidden 選取所有不可見的元素(包含 CSS display=none, visibility=hidden以及<inputtype="hidden">) 
  • :input 選取所有表單輸入元素(包含 input, select, textarea, button).
  • :text 選取所有 <input type="text">
  • :password 選取所有 <input type="password ">
  • :radio 選取所有 <input type="radio ">
  • :checkbox 選取所有 <input type="checkbox">
  • :submit 選取所有 <input type="submit">
  • :image 選取所有 <input type="image">
  • :reset 選取所有 <input type="reset">
  • :button 選取所有 <input type="button">
  • :file 選取所有 <input type="file">
  • $('#selected-plays > li').addClass('horizontal');
  • $('#selected-plays li:not(.horizontal)').addClass('sub-level');
  • $('a[@href^="mailto:"]').addClass('mailto');
  • $('a[@href$=".pdf"]').addClass('pdflink');
  • $('a[@href*="mysite.com"]').addClass('mysite');
  • $('th').parent().addClass('table-heading');
  • $('tr:not([th]):even').addClass('even');
  • $('tr:not([th]):odd').addClass('odd');
  • $('td:contains("Henry")').siblings().addClass('highlight');
  • $('div.character').contains('CELIA').find('a').empty().remove();
  • $('div.character').contains('CELIA').next().hide().end().append('<a href="#" class="expand">. . .</a>');
選擇器回傳物件

由於 jQuery Selector 傳回的結果常是一群符合元素 jQuery 物件所組成的群組,還有有幾個取得群組特定元素的函數:

  • size()length 傳回群組的物件個數
  • eq(N) 取出群組中第 N 個 jQuery 物件
  • get() 傳回元素的陣列
  • get(N) 取出第 N 個元素
  • index(element 或 jQuery 物件) 用來找某元素在選取結果中的排名順序,例如網頁上有五個 <div>,<div id="dvX"> 名第三個,則 $("div").index(document.getElementById("dvX")) 可以得到 2 (由 0 起算,故第三個為 2),$("div").index($("#dvX")) 也可得到同樣結果。元素不在群組時傳回 -1。
【共用函數補充】
  • jQuery.browser 用以偵測瀏覽器版本,它是一個物件,會有 safari、opera、msie、mozila 及 version 五個屬性,前四個屬性依瀏覽器不同,只有一個屬性會傳回 true,其餘都傳回 false,而 version 則會傳回版號。
  • jQuery.support,由於使用 jQuery.browser 的做法意味著我們要寫死何種瀏覽器支援哪些功能,一旦瀏覽器改版或特性改變時就要修校,因此從 jQuery 1.3 起,jQuery 核心不再用 jQuery.browser 判斷決定不同的做法,而是一律由 jQuery.support.* 傳回 true/flase 判斷瀏覽器的支援度,目前可測試的瀏覽器特性包含了: boxModel、cssFloat、hrefNormalized、htmlSerialize、leadingWhitespace、noCloneEvent、objectAll、opacity、scriptEval、style、tbody。但基於向前相容,jQuery.browser 仍會持續存在。
  • jQuery.each(array, function() { ... }) ,將 array 的各元素逐一送給 callback 函數處理,函數中以 this 取得陣列元素內容。
  • jQuery.each(object, function(i, val) { ... }),逐一傳入物件各屬性的名稱 (i) 以及值 (val) 給 callback 函數處理。
    (註: each 中 return false 時,後續尚未處理到的其他陣列元素/物件屬性則略過不處理。)
  • jQuery.extend(obj1, obj2, obj3),將 obj2/3 的屬性合併到 obj1 中(若同名屬性存在則覆寫之),很常用於指定參數的預設值,例如:
    1. var finalSetting = { };      
    2. var  defaultSetting = { limit: 256, maxRows: 16, maxCols: 16 };      
    3. var  userOption = { maxRows: 10 };      
    4. //第一個參數物件會被修改,為了保持 defaultSetting 不被更動,放在第二個參數      
    5. $.extend(finalSetting, defaultSetting, userOption);      
    6. $.each(finalSetting, function (i, val) {       
    7.     alert(i + "->"  + val);      
    8. });  
  • jQuery.grep(array, function(v, i) { ... }); 將陣列元素 (v) 與其排序 (i) 傳給 callback,return true/false 決定該陣列元素留下或捨棄,可以用來過濾陣列。
  • jQuery.map(array, function(v, i) { ... }); 將陣列元素 (v) 處理過傳回,傳回值若為 null 則移除該元素,傳回值若為陣列則陣列中的元素都會被新增,最後得到一個處理過的新陣列。
  • jQuery.inArray(val, array); 檢查 val 有無存在於 array 中。
  • jQuery.merge(array1, array2); 合併兩個陣列,若要排除重覆元素則可用jQuery.unique(array)事後處理。
  • jQuery.isArray(obj)/jQuery.isFunction(obj) 判別是否為陣列/函數。
  • jQuery.trim(s); 去掉字串頭尾的空白
  • jQuery.param(array/object/jQuery) 將陣列 / 物件 / jQuery 物件序列化成一個字串,格式如: width=1680&height=1050。

 

【事件處理】 IE 提供了 attachEvent()
Firefox 提供了 attchEventListener()

在 jQuery 中,我們要掛上事件函數,可以透過統一的寫法:

$(...).bind(type, data, function() { ... });

type 用來指名要掛載的事件名稱字串 (可以是 blur、focus, load、resize、scroll、unload、click、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter、mouseleave、change、select、submit、keydown、keypress、keyup、error 其中之一,多個事件名稱以空白相接則可將同一函數設在多個事件上)

blur元素失去焦點時
focus元素取得焦點時
load元素完成載入時
resize元素大小改變時
scroll 當捲軸捲動時
unload使用者關閉離開網頁時
click滑鼠點擊元素時
dblclick滑鼠連點二下元素時
mousedown按下滑鼠按鍵時
mouseup放開滑鼠按鍵時
mousemove介於 mouseover 跟 mouseout 間的滑鼠移動
mouseover滑鼠進入元素範圍時(滑鼠離開子元素但仍在其元素範圍內時也會觸發 mouseover)
mouseout滑鼠離開元素範圍時(在元素範圍內,滑鼠進入子元素範圍時也會觸發 mouseout)
mouseenter滑鼠進入元素範圍時
mouseleave滑鼠離開元素範圍時
change欄位內容改變時
select使用者選取元素中的文字時
submitHTML Form 送出時
keydown按下鍵盤按鍵時
keypress按下按鍵後放開按鍵前觸發
keyup放開鍵盤按鍵時

 

data 函數主要是用來傳遞額外的參數,這在多個事件共用函數時特別有用,例如:

  1. function sharedEvent(e) {      
  2.    alert("Data="  + e.data);      
  3. }      
  4. $("span").bind("click""SpanClick" , sharedEvent);      
  5. $("div").bind("click""DivClick", sharedEvent); 

 

 

卸除事件函數則可透過 unbind([type], [fn]),例如: unbind() 可卸除所有事件函數、unbind("click") 可以卸除所有的click事件函數、unbind("click", funcA) 則可只卸除 funcA。理論上,元素由 DOM 移除時應該要將其上所掛載的事件函數全部卸除以避免惱人的記憶體洩漏 (Memory Leak) 問題,所幸 jQuery 在這方面下了不少功夫,幾乎都能自動在 unload 時加上處理,除非有特殊的目的要卸除事件才要特別 unbind(),倒不需額外傷腦筋。

事件允許多重宣告,並會依宣告先後依序觸發,如果我們要由程式觸發事件,做法也很簡單,$(...).trigger(event, data); 即可(event 可以是事件名稱字串、jQuery.Event 物件、或是自訂物件,詳細說明可見 API 參考文件),或是比照宣告時,簡寫成 $(...).click();,差別只在於中間不傳入事件函數,例如:

 

【存取事件資訊】 在事件函數中,可以透過 this 存取觸發事件的元素物件,如果要取得滑鼠座標、按鍵內容等資訊,則在函數中接收 event 參數取得事件資訊物件。例如: mousedown 事件時,可以透過 pageX / pageY 取得相對於網頁的滑鼠座標,screenX / screenY 取得相對於螢幕的滑鼠座標、keydown 事件時,則可由 which 取得按鍵碼。以下為範例:
  1. $("#Inner").mousedown(function(evt) {      
  2.     alert("P:" + evt.pageX + ","  + evt.pageY);      
  3. });      
  4. $("input").keydown(function (evt) {      
  5.     alert(evt.which);      
  6. });  
除了元素的既有事件外,我們也可以自訂事件,方法是先 bind 到自訂的事件名稱上,之後再以 trigger 觸發,例如
  1. $("div").bind("beat"function(event, attacker, weapon) {       
  2.     alert("被" + attacker + "用" + weapon + "痛扁一頓!" ); });      
  3. //不傳入 event      
  4. $("div").trigger("beat", [ "Jeffrey""狼牙棒"  ]);      
  5. //傳入 event      
  6. var e = jQuery.Event("beat");  //jQuery 1.3+ 支援      
  7. $("div").trigger(e, [ "Darkthread""愛的小手" ]);  
【事件物件】

jQuery.Event

1. 事件函數中除了用 this 可以存取被觸發的元素外,還有幾個相關屬性: target 適用於由 Bubble 引發事件時,指向真正觸發事件的元素,用一個例子較易說明: 有一個 <div id="d"><span id="s">TEXT</span></div>,當 span 被 click 時,會進一步也觸發 div 的 click 事件,因此若寫成

  1. $("div").click(function(e) {       
  2.     alert($(this).attr("id" ));       
  3.     alert($(e.target).attr("id" ));       
  4. });  

就會分別得到 "d" 與 "s"。屬性 currentTarget 原則上就等同於 this。relatedTarget 用於父子元素間 mouseover 與 mouseout 事件切換時偵察之用,稍候會再另做討論。

 

 

2. IE 原本不支援 pageX / pageY,jQuery 補上了。

3. result 可用於同一事件的多個事件函數間傳遞資料,例如:

  1. $("div").click(function() { return "First Event Handler's Result"; });      
  2. $("div").click(function (e) {       
  3.     alert(e.result);      
  4. }).click();  

 

 

4. 某些事件函數中,可以控制阻止作業繼續進行,例如:<a> 的 onclick 事件可以阻止連向該連結、<form> 的 onsubmit 可以拒絕將表單送出。在做法上各家瀏覽器有所不同,jQuery 則統一可透過 event.preventDefault() 達成取消的目的。例如: $("a").click(function(e) { e.preventDefault(); }); 將會阻止瀏覽器轉接超連結。

5. 借用第一點中提到的 Bubble 原理,span 被點選時,除了span 的 click 事件被觸發,span 的父元素 div 也會被觸發 click 事件,就像氣泡一樣一路浮上去。如果我們希望 span click 事件觸發後就結束,不要再觸發其父元素的 click 事件,可以使用 event.stopPropagation() 達到目標。如下例,將 e.stopPropagation(); 前方的註解移除,就只會看到 alert SPAN:

  1. $("div").click(function(e) { alert("DIV"); });      
  2. $("span").click(function (e) {       
  3.     alert("SPAN" );       
  4.      //e.stopPropagation();       
  5. });  

 

6. event.stopImmediatePropagation() 類似 event.stopPropagation() 的概念,但停止觸發的對象除了父元素外,還包含同一元素針對該事件多重宣告的其他函數

 

【好用的 mouseenter、mouseleave】

先前在談 relatedTarget 時提到它跟 mouseover / mouseout 有關,如果不了解 mouseover、mouseout 有什麼缺點,就不會知道 mouseenter / mouseleave 好在哪裡。

基本的概念是,當滑鼠滑入元素範圍時,會先觸發 mouseover、接著在元素上游移時會觸發 mousemove、等移出元素時會觸發 mouseout,邏輯看來很清楚,應該沒有什麼問題。當元素中包有子元素時,這一切就變了調,滑鼠在父元素中移動時,當其進入子元素的範圍,會觸發父元素的 mouseout,才觸發子元素的 mouseover。換句話說,雖然子元素也被包含在父元素中,但進到子元素領空時,瀏覽器的認知是這也算離開父元素的範圍(雖然我們較傾向認定子元素也是父元素的一部分),這在處理邏輯上會造成一些困擾。光用描述的有點抽象,因此我們用一個實例來展示它有多機車:

強化型事件裝卸功能】 除了標準的 bind 之外,有時我們會需要一次性的事件處理邏輯,傳統做法是在事件函數中將自己 unbind。jQuery 則有另一個 one() 可以省去我們自己 unbind 的功夫,在事件觸發後就會自動卸除。

另外,針對 mouseover、mouseout 時要分別呼叫對應的事件函數,jQuery 提供了 hover(overFunc、outFunc) 的一次宣告法,可以再省點工。


而如果是第一次點選執行 fn1,第二次點選 fn2,第三次 fn3 的情境,jQuery 則有 toggle(fn1、fn2、fn3、...) 的簡便宣告方式。

另外,使用 $("...").bind(...) 的寫法,只會作用在 bind(...) 執行當下已存在的元素上,若事後又有符合該 Selector 的元素新增,並不會自動掛上該事件,需要額外的程式邏輯再處理一次。

 

jQuery 1.3 起有個 live()與die(),跟 bind() / unbind() 的目標相同,但是可以做到未來符合 Selector 的元素一旦出現,就會自動掛上事件的功能。請看以下示範:

 

在這個區域裡按右鋌是沒用的
                                    $(document).ready(function () {
                                        $('.notContentmenu').bind("contextmenu", function () {
                                            return false;
                                        });
                                    });