JavaScript 與 jQuery

第 7 章    jQuery 進階

(1) CSS選擇器格式

∗ ­jQuery 利用 CSS 選擇器 (Selector) 格式選擇元素,再加上額外的選擇模式

▸ 基本選擇器

選擇器選擇對象範例
* 所有元素 $('*')
<tagName> 所有名為 <tagName> 的元素 $('h1')
#<idName> id<idName> 的元素 $('#myId')
.<className> CSS 類別為 <className> 的元素 $('.myClass')
<selector1>, <selector2>, ... 以逗點分隔:符合多個選擇器其中之一的元素 $('h1, #myId')

▸ 階層選擇

選擇器選擇對象範例
<ancestor> <descendant>符合階層關係的元素$('li a') → a
<parent> > <child>符合親子關係的元素$('li>a') → a
<previous> + <next>符合同階層相鄰關係的後者元素$('div+p') → p
<previous> ~ <sibling>符合同階層相鄰關係的後者所有元素$('ul~li') → 所有 li

▸ 基本過濾器

過濾器過濾對象範例
:not(<selector>) 除此以外的其他元素 $('div:not("#main")')
:first 第一個元素 $('li:first')
:last 最後一個元素 $('li:last')
:odd 奇數元素 $('li:odd')
:even 偶數元素 $('li:even')
:eq(<index>) 索引值等於 <index> 的元素 $('li:eq(3)')
:gt(<index>) 索引值大於 <index> 的所有元素 $('li:gt(3)')
:lt(index) 索引值小於 <index> 的所有元素 $('li:lt(3)')
:header 所有 <h1> ~ <h6> 的元素 $(':header')
:animated 所有動畫元素 $(':animated')
:focus 目前聚焦的元素 $(':focus')

▸ 內容過濾器

過濾器過濾對象範例
:contains('<text>') 文字內容包含 text 的元素 $(':contains("Hello")')
:empty空元素 (沒有孩子)$(':empty')
:parent非空元素 (有孩子)$(':parent')
:has(<selector>)內容包含某個元素$('div:has("p")')

▸ 可見過濾器

過濾器過濾對象範例
:hidden隱藏的元素$(':hidden')
:visible可見的元素$(':visible')
✶ 註:
# :visible 不會選到 display: none, height/width: 0,ancestor 是隱藏
# :visible 會選到 visibility: hiddenopacity: 0 (這些都佔有空間)

▸ 孩子過濾器

過濾器過濾對象範例
:nth-child(<index>)<index> 個孩子 (從 1 開始)$('li:nth-child(2)')
:first-child第一個孩子$('p:first-child')
:last-child最後一個孩子$('p:last-child')
:only-child唯一的孩子$('p:only-child')

▸ 屬性過濾器

過濾器過濾對象範例
[<attr>] 有該屬性的元素 $('[href]')
[<attr>='<value>'] 有該屬性值的元素 $('[href="a.html"]')
[<attr>!='<value>'] 有該屬性但沒有該屬性值的元素 $('[href!="a.html"]')
[<attr>^='<value>'] 有該屬性且以該值開頭的元素 $('[href^="f"]')
[<attr>$='<value>'] 有該屬性且以該值結尾的元素 $('[href$="t"]')
[<attr>*='<value>'] 有該屬性且屬性值包含此字串的元素 $('[class|="first"]')
→ class="first-one
[<attr>|='<value>'] 有該屬性值或以該值開頭再跟隨一個短橫線的元素 $('[class|="first"]'))
→ class="first-one
[<attr>~='<value>'] 在多個屬性值中存在該屬性值 $('[class~="first"]'))
→ class="first second
[<attr1>='<value>'] [<attr2>='<value>'] 符合所有選擇器的元素 $('[class="first"] [class="second"]')

▸ 屬性過濾器

過濾器過濾對象
:input所有 input 元素
:text所有 text input 元素
:password所有 password input 元素
:radio所有 radio button 元素
:checkbox所有 checkbox 元素
:submit所有 submit button 元素
:image所有 img 元素
:reset所有 reset button 元素
:button所有 button 元素
:file所有 file input 元素
:selected所有下拉選單裡被選擇的元素
:enabled所有啟用元素 (CSS 預設)
:disabled所有停用元素 (CSS disabled 屬性)
:checked所有被選擇的 radio button 或 checkbox 元素

(2) jQuery 方法

∗ jQuery 方法

▸ 以點號加方法名稱來表示,例如:.html()

▸ 當利用 jQuery 選擇元素時,所選到的物件有預設屬性 .length,也就是所選元素的數量

▸ 所選到的元素稱為 Matched setjQuery selection

▸ 如果沒有選到任何元素,呼叫 jQuery 方法並不會產生錯誤,只是沒有效果

▸ 許多 jQuery 方法可同時用來「取出」或「設定」資料,取出資料不給參數,設定資料則給參數

▸ 使用方式:先選擇元素,接著以點號呼叫方法來應用到所有選到的元素,例如:

# .html():取出第一個元素的內容
# .html(<content>):設定所有選擇元素的內容
<ul>
  <li>123</li>
  <li>456</li>
  <li>789</li>
</ul>
var content = $('li').html();    // 將第一個 <li> 元素的內容指派給變數 content → 123
$('li').html('abc');             // 將所有 <li> 元素的內容設為 abc
<ul>
  <li>abc</li>
  <li>abc</li>
  <li>abc</li>
</ul>

∗ 迴圈 (Looping)

▸ 使用純 JavaScript 程式,如果要對一群元素進行操作,程式設計師必須自行撰寫迴圈,一個一個處理

▸ 使用 jQuery 函式庫則只要使用一個方法,即可對所有所選到的元素進行處理,此稱為隱含迴圈 (Implicit iteration)

▸ 例如:將 <em> 元素加上 .seasonal,將所有 .hot 的元素再加上 .favorite

✶ 下載 assets7.zip, 解壓縮後將 ch7.css 置於 ch7/css/ 目錄中, 其餘影像均置於 ch7/img/ 目錄中
looping.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/ch7.css">
</head>
<body>

<div id="page">
  <h1 id="header">清單</h1>
  <h2>買雜貨</h2>
  <ul>
    <li id="one" class="hot"><em>新鮮</em>無花果</li>
    <li id="two" class="hot">松子</li>
    <li id="three" class="hot">蜂蜜</li>
    <li id="four">香醋</li>
  </ul>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<script src="js/looping.js"></script>
</body>
</html>
js/looping.js
$(document).ready(function() {

  $('li em').addClass('seasonal');
  $('li.hot').addClass('favorite');

});
# $('li em'):選擇被 <li> 包含的 <em> 元素
# .addClass(...):加上 CSS 類別
# $('li.hot'):選擇有類別 hot 的元素 (總共 3 個)

∗ 鏈接 (Chaining)

▸ 如果需要對於選擇的元素進行多種處理,可將方法串連,稱為鏈接 (Chaining),例如:

$('li[id!="one"]').hide().delay(500).fadeIn(1400);

▸ 也可以寫為:

$('li[id!="one"]')
  .hide()
  .delay(500)
  .fadeIn(1400);

▸ 如果鏈接方法中的某個方法失敗,其後的方法就不執行

設定元素內容的方法可以鏈接,但取出元素內容的方法不可鏈接

∗ 檢查網頁是否完成載入

▸ 將程式寫在 $(document).ready() 方法中,確保網頁載入完畢才執行程式

$(document).ready(function() {
  // Your code here
});

▸ 也可以縮寫為:

$(function() {
  // Your code here
});

▸ 將程式置於網頁最後(在 </body> 之前),也有相同效果

(3) 元素內容處理

∗ 取出/更改元素內容方法

方法說明
.html() 取出或設定元素內容,可包含 HTML 碼
.text() 取出或設定元素文字內容,取出:不包含 HTML 碼,設定:HTML 碼以文字顯示
.replaceWith() 置換
.remove() 移除
.append() 內部加入,a.append(b):將 b 加入 a 的內容中
.appendTo() 內部加入,b.appendTo(a):同上

∗ 取出元素內容

.html():取出第一個元素的 HTML 內容,例如:

<ul>
  <li><em>abc</em>def</li>
  <li>ghi</li>
  <li>jkl</li>
</ul>
$('ul').html()
<li><em>abc</em>def</li>
<li>ghi</li>
<li>jkl</li>
$('li').html()
<em>abc</em>

.text():取出所有元素的 文字 內容,例如:

<ul>
  <li><em>abc</em>def</li>
  <li>ghi</li>
  <li>jkl</li>
</ul>
$('ul').text()
abcdef
ghi
jkl
$('li').text()
abcdefghijkl

∗ 練習

▸ 將 <ul> 的內容複製一份

get-html.html (類似 looping.html):
... 
<script src="js/get-html.js"></script>
...
js/get-html.js
$(document).ready(function() {

  $('ul').append($('ul').html());

});
✶ 取出 <ul> 的所有內容再附加到 <ul> 後面

▸ 將 <ul> 裡的所有文字列在最後成為一行

get-text.html (類似 looping.html):
... 
<script src="js/get-text.js"></script>
...
js/get-text.js
$(document).ready(function() {

  $('ul').append('<p>' +  $('ul').text() + '</p>');

});
✶ 取出 <ul> 的文字內容,再以段落元素加到 <ul> 後面

∗ 更改元素內容

.html(<content>):設定元素的內容,HTML 碼正常運作

.text(<content>):設定元素的文字內容,HTML 碼以文字方式顯示

.replaceWith(<content>):置換元素的內容,並且回覆這些元素

.remove():刪除元素

∗ 練習:設定元素內容

changing-content.html (類似 looping.html):

... 
<script src="js/changing-content.js"></script>
...

js/changing-content.js

$(document).ready(function() {

  $('li:contains("松子")').text('杏仁');
  $('li.hot').html(function() {
    return '<em>' + $(this).text() + '</em>';
  });
  $('li#four').remove();

});

$('li:contains("松子")').text('杏仁'):選擇 <li> 且內容包含「松子」的元素,將內容改為「杏仁」

$('li.hot').html(...):選擇 <li> 且類別為 hot 的元素,且將本元素文字內容加上<em>標籤

('li#four').remove():刪除 id 為 four<li> 元素

(4) 元素處理

∗ 元素操作方法

方法說明
.before(<content>)插入在元素之前
.after(<content>)插入在元素之後
.prepend(<content>)插入在元素的內容之前
.append(<content>)插入在元素的內容之後
.clone()複製元素
.wrap(<content>)以標籤包住
.unwrap()去除外部標籤
.detach()分離元素,與 .remove() 相同, 但刪除的資料會保留,便於之後重新插入
.empty()移除元素的所有子節點
.add(<content>)將物件加入元素中

∗ 產生內含 HTML 元素的 jQuery 物件 (jQuery object),例如:

▸ 將一個空元素的 jQuery 物件設定給變數 $newItem:

var $newItem = $('<li>');
→ 習慣上會在變數名稱前加上 $ 符號,以說明此變數是 jQuery 物件,而非一般 JavaScript 物件

▸ 將含有內容的 jQuery 物件設定給變數 $newItem,再插入在選擇元素的內容之後:

var $newItem = $('<li class=new>項目</li>');
$('ul').append($newItem);

∗ 練習:加入新內容

adding-new-content.html (類似 looping.html):

... 
<script src="js/adding-new-content.js"></script>
...

js/adding-new-content.js

$(document).ready(function() {

  $('ul').before('<p class="notice"></p>');
  $('li.hot').prepend('+ ');
  var $newItem = $('<li><em>傳統風味</em>醬油</li>');
  $('li:last').after($newItem);

})

$('ul').before('<p ...>...</p>'):在 <ul> 元素之前插入一個 <p> 元素

$(...).prepend('+ '):在所選元素的內容前面插入加號

var $newItem = $('<li>...</li>'):產生一個 <li> 元素,並指派給變數 $newItem

$(...).after($newItem):在所選元素之後插入 $newItem 物件

∗ 練習

cut-copy-paste.html (類似 looping.html):

...
<div id="page">
  ...
  <li id=four>香醋</li> 
  <p>"大多數人都錯失機會,因為機會看起來都像是非常辛苦的工作。"<br>
    - 湯馬斯.愛迪生</p>
</div>
...
<script src="js/cut-copy-paste.js"></script>
...

js/cut-copy-paste.js

$(document).ready(function() {

  var $p = $('p');
  var $cloneQuote = $p.clone();

  $p.remove();
  $cloneQuote.insertAfter('h2');
  var $moveItem = $('#one').detach();
  $moveItem.appendTo('ul');

});

var $cloneQuote = $p.clone():將所選到的 <p> 元素 (引述愛迪生的話) 複製一份

$p.remove():將 <p> 元素移除

$cloneQuote.insertAfter('h2'):插入到 <h2> 之後

var $moveItem = $(...).detach():將元素剪下

$moveItem.appendTo('ul'):將元素加入 <ul> 內容之後 (或 $('ul').append($moveItem);)

(5) 屬性處理

∗ 屬性方法

方法說明
.attr() 取出/設定屬性 (取出:0 或 1 個參數,設定:2 個參數)
.removeAttr() 移除屬性
.removeClass() 移除 CSS 類別
.css() 取出或設定 CSS

∗ 練習

attributes.html (類似 looping.html):

... 
<script src="js/attributes.js"></script>
...

js/attributes.js

$(document).ready(function() {

  $('li#three').removeClass('hot');
  $('li.hot').addClass('favorite');
  $('ul').attr('id', 'group');

});

.removeClass('hot'):移除 CSS 類別 hot

.addClass('favorite'):加入 CSS 類別 favorite

.attr('id', 'group'):加入 id="group" 屬性

∗ 取出/設定 CSS 特性

▸ 取出 CSS 特性,如果選到多個元素,回覆第一個元素的 CSS 特性

$('selector').css('cssName');
✶ 例如取出背景顏色:var bgColor = $('li').css('background-color');

▸ 設定 CSS 特性,如果選到多個元素,每個元素都會設定

$('selector').css('cssName', 'value');
✶ 例如設定背景顏色:$('li').css('background-color', 'red');
✶ 可以加減值,例如:
$('li').css('padding-left', '+=20');     // 加 20px
$('li').css('padding-right', '-=20');    // 減 20px

▸ 利用物件字面表示法 (Object literal notation) 設定多個 CSS 特性,例如:

$('li').css({
  'background-color': '#272727',
  'padding-left': '20'
});

∗ 練習:變更 CSS 設定

css.html (類似 looping.html):

... 
<script src="js/css.js"></script>
...

js/css.js

$(document).ready(function() {

  var bgColor = $('li').css('background-color');
  $('ul').append('<p>顏色是:' + bgColor + '</p>');
  $('li').css({
    'background-color': '#c5a996',
    'border': '1px solid #fff',
    'color': '#000',
    'padding-left': '+=75'
  });

});

(6) jQuery 迴圈

∗ 利用 jQuery 迴圈設定所有選到的元素

▸ jQuery 的許多方法已經可以一次設定所有選到的元素 (稱為隱含迴圈)

▸ 但有些時候還是需要使用迴圈針對每一個元素進一步處理,例如:

✶ 處理所有元素的內容 (jQuery 方法只會回覆第一個元素的內容)
✶ 對每個元素進行一系列的運算 (jQuery 方法只能進行一次運算)

▸ jQuery 迴圈語法:

$('li').each(function([index]) {
  // Your code here
});
each() 函式的參數可以是一個具名或匿名函式
✶ jQuery 自動提供迴圈索引 (index,從 0 開始,亦可使用其他名稱),只要指定為函式參數即可使用
✶ 在函式中,this 指的是目前正在處理的元素,$(this) 指的是利用目前元素所產生的 jQuery 物件
✶ 例如:在每個元素加上一個新元素
$('li').each(function() {
  var id = this.id;
  $(this).append('<em class="order">' + id + '</em>');
});
# var id = this.id:取出 id 屬性值
* 此處最好使用純 JavaScript 來取出元素的 id 屬性
* jQuery的語法:
var id = $(this).attr('id');
→ 需要先產生 jQuery 物件,然後再呼叫 .attr()方法,反而效能較差
# $(this).append('<em ...</em>'):附加一個新 <em>元素
✶ 使用 return false 來停止後續處理,例如:
$('li').each(function() {
  ... 
  if (...) {
    return false;  // 跳出.each()迴圈
  }
});

∗ 練習:使用 .each() 方法

each.html (類似 looping.html):

... 
<script src="js/each.js"></script>
...

js/each.js

$(document).ready(function() {

  $('li').each(function() {
    var id = this.id;
    $(this).append('<span class="order">' + id + '</span>');
  });

});

(7) 事件方法

∗ jQuer 事件方法:.on()

▸ 跨平台,無需寫倒退程式

▸ 語法 (方括號為可有可無):

$(<selector>).on(<event>, [<selector>,] [<data>,] function([e]) { 
  // Your code here
});
✶ 必要兩個參數 (<event>, function([e])):選擇元素,如果事件發生,就執行匿名函式;如果有給 e 參數,jQuery會自動將事件物件 e 傳給函式
✶ 可加一個 selector:進一步篩選元素
✶ 可加一個 data:增加傳入函式的參數,格式為物件字面表示法 (Object literal)

▸ 亦可使用事件代表語法:

$(<delegation>).on(<event>, <selector>, [<data>,] function([e]) { 
  // Your code here
});

▸ 例 1:使用者點擊 <li> 觸發事件,匿名函式將事件型態指派給 eventType 變數

$(document).on('click', 'li', function(e) {
  var eventType = e.type;
});
$(document).on('click focus', 'li', function(e) {    // Handle two events: click and focus
  // Your code here
});

▸ 例 2:使用者點擊 <li> 觸發事件,但排除 id 為 four<li>

$(document).on('click', 'li:not(#four)', function(e) {
  // Your code here
});

▸ 例 3:使用者點擊 <li> 觸發事件,排除 id 為four<li> ,並將 status 變數傳入匿名函式, status 的值為 important

$(document).on('click', 'li:not(#four)', {status: 'important'}, function(e) { 
  var status = e.data.status;
  // Your code here
});

∗ jQuery 事件物件屬性

屬性 說明
e.type 事件型態 (click, mousemove, ...)
e.which 所按下的按鍵或按鈕
e.data 程式傳入的參數
e.target 發生事件的元素
e.pageX
e.pageY
滑鼠水平、垂直位置 (相對視域左上角)

▸ 鍵盤事件 (e.which) 表: https://css-tricks.com/snippets/javascript/javascript-keycodes/

∗ 練習:點擊某項目時,在該項目顯示點擊日期與事件名稱

event-object.html (類似 looping.html):

... 
<script src="js/event-object.js"></script>
...

js/event-object.js

$(document).ready(function() {

  $(document).on('click', 'li', function(e) {
    $('li em').remove();
    var date = new Date();
    var month = date.getMonth() + 1;
    var dateString = date.getFullYear() + '-' + month + '-' + date.getDate();
    
    $(this).append('<span class=date>' + dateString + ' ' + e.type + '</span>');
  });

});

$('li em').remove() :刪除所有在 <li> 裡面的 <em> 元素

new Date() :產生目前時間物件

dateString :設定日期格式

$(this).append(...) :在目前元素內容後面附加資料

∗ 練習:點擊或滑鼠縈繞某項目時產生內容及事件名稱

event-delegation.html (類似 looping.html) :

... 
    </ul>
    <p id="notes">點擊或移到熱賣商品...</p>
</div>
...
<script src="js/event-delegation.js"></script>
...

js/event-delegation.js

$(document).ready(function() {

  var listItem, itemStatus, eventType;
  
  $(document).on('click mouseover', 'li:not(#four)', {status: 'important'}, function(e) {
    listItem = '項目:' + e.target.textContent + '<br>';
    itemStatus = '狀態:' + e.data.status + '<br>';
    eventType = '事件:' + e.type;
    $('#notes').html(listItem + itemStatus + eventType);
  });

});

e.target.textContent 亦可使用 $(this).text()

∗ 作業 1

(8) 效果

∗ 基本效果

方法 說明
.show() 顯示元素
.hide() 隱藏元素
.toggle() 切換顯示或隱藏元素
.delay() 延遲執行

∗ 淡化效果

方法 說明
.fadeIn(<speed> [, <callback>]) 元素淡入
.fadeOut(<speed> [, <callback>]) 元素淡出
.fadeToggle(<speed> [, <callback>]) 以淡化方式切換顯示或隱藏元素
.fadeTo(<speed>, <opacity> [, <callback>]) 元素淡化 (逐漸改變透明度)

<speed>:速度 ('slow''fast'、 或毫秒數值)

<callback>:回呼函式 (可有可無)

<opacity>:最終的透明度值 (0 ~ 1)

∗ 滑動效果

方法 說明
.slideUp() 元素向上滑出消失
.slideDown() 元素向下滑入顯示
.slideToggle() 以滑動方式切換顯示或隱藏元素

∗ 練習:標題向下滑入,雜貨項目一個個淡入,點擊時淡出

effect.html (類似 looping.html):

...
<script src="js/effect.js"></script>
...

js/effect.js

$(document).ready(function() {

  $('h2').hide().slideDown();
  
  $('li').hide().each(function(index) {
    $(this).delay(700*index).fadeIn(700);
  });
  $(document).on('click', 'li', function() {
    $(this).fadeOut(700);
  });
  
});

$('h2').hide().slideDown() :先隱藏 <h2> 標籤, 然後向下滑入

▸ 每一個 <li>:先全部隱藏,各元素接續延遲執行,然後以 0.7 秒的時間淡入

▸ 使用者點擊 <li>:以 0.7 秒時間淡出

∗ 動畫 (Animation)

方法 說明
.animate() 產生動畫
.stop() 停止動畫

▸ 語法:

.animate({
  // Style to change
} [, speed] [, easing] [, function() {...}]);
✶ // Style to change:需要呈現的動畫,透過 CSS 的變化來完成
✶ 可以加上速度 (Speed) 參數:動畫的時間 (毫秒),也可以使用 slowfast
✶ 可以加上緩和 (Easing) 參數:linear (線性轉換) 或 swing (開始及結束慢,中間快)
✶ 可以加上動畫完成後的回呼函式 (Callback function)

∗ jQuery 相對 CSS 特性的名稱 (將 CSS 名稱的短橫線格式改為駝峰式)

bottom maxWidth paddingLeft borderBottomWidth
left minWidth paddingRight borderLeftWidth
right margin paddingTop borderRightWidth
top marginBottom fontSize borderTopWidth
backgroundPositionX marginLeft letterSpacing borderSpacing
backgroundPositionY marginRight worSpacing
height marginTop lineHeight
width outlineWidth textIndent
maxHeight padding borderRadius
minHeight paddingBottom borderWidth

∗ 練習:點擊項目後,項目往右移動並消失

animation.html (類似 looping.html):

...
<script src="js/animation.js"></script>
...

js/animation.js

$(document).ready(function() {
  
  $(document).on('click', 'li', function() {
    $(this).animate({
      opacity: 0.0,
      paddingLeft: '+=80',
    }, 500, function() {
      $(this).remove();
    });
  });
  
});

$(this).animate(...):在目前元素執行動畫,從目前狀態轉換到透明度 0.0 ,且右移 80px

▸ 轉換時間 0.5 秒

▸ 轉換完成後,回呼匿名函式,將該項目移除 (因此以下的項目會上移)

∗ 作業 2

(9) 在 DOM 樹中遊走

∗ 選擇器

方法 說明
.parent() 父母元素
.parents() 所有父母元素
.children() 所有子元素
.siblings() 所有兄弟姊妹元素
.next() 後一個兄弟姊妹
.nextAll() 後面的所有兄弟姊妹
.prev() 前一個兄弟姊妹
.prevAll() 前面的所有兄弟姊妹
.find(<selector>) 符合選擇器的子孫元素
.closest(<selector>) 符合選擇器的最接近祖先元素

∗ 練習:動態加入顯示按鈕,點擊按鈕後雜貨項目浮現,然後按鈕消失

traversing.html (類似 looping.html):

...
<script src="js/traversing.js"></script>
...

js/traversing.js

$(document).ready(function() {

  $('ul').hide();
  $('h2').append('<a class="show" href="#">顯示</a>');
  
  $(document).on('click', 'h2', function() {
    var $this = $(this);
    $this.next().fadeIn(500).children('.hot').addClass('complete');
    $this.find('a').fadeOut(1000);
  });

});

$('ul').hide():將選單隱藏

$h2.append(...):在 <h2> 裡加上 <a> 連結, class="show" 讓其顯示成按鈕

$(document).on('click', 'h2', ...):監聽點擊事件

$this.next():選擇目前元素的的下一個兄弟 (亦即 <ul>)
.fadeIn(500)<ul> 以 0.5 秒時間淡入
.children('.hot'):選擇 <ul> 的孩子們 (亦即 <li>) 有 hot 的 CSS 類別
.addClass('complete'):加入 CSS 類別 complete (因此顯示灰色)
$this.find('a').fadeOut(1000):在目前元素裡選擇孩子 <a> 元素,以 1 秒時間淡出

(10) 加入與篩選元素

∗ 加入元素

方法 說明
.add(<selector>) 加入所選元素

∗ 篩選元素

方法 說明
.filter(<selector>) 符合的元素
.find(<selector>) 符合的子孫元素
.not(<selector>)
:not(<selector>)
不符合的元素 (函式與篩選)
.has(<selector>)
:has(<selector>)
子孫符合的元素 (函式與篩選)
.contains(<text>) 符合文字的元素

▸ 例如以下兩者是相同的:

$('li').not('.hot').addClass('cool');
$('li:not(".hot")').addClass('cool');

∗ 測試內容

方法 說明
.is(<selecter>) 元素是否符合

∗ 練習:選擇元素,改變類別,插入文字

filters.html (類似 looping.html):

...
<script src="js/filters.js"></script>
...

js/filters.js

$(document).ready(function() {

  var $items = $('li');
  
  $items.filter('.hot:last').removeClass('hot');
  $('li:not(".hot")').addClass('cool');
  $items.has('em').addClass('complete');
  $items.filter('.hot').prepend('優先項目:');
  $('li:contains("蜂蜜")').append(' (當地)');

});

var $items = $('li'):選擇所有 <li> 元素並指派給變數 $items

$items.filter('.hot:last').removeClass('hot'):選擇有類別 hot 者,並選擇最後一個,然後將該類別移除 (因此「蜂蜜」項目的 hot 類別被移除)

✶ 同於:$('li.hot:last').removeClass('hot')

$('li:not(".hot")').addClass('cool'):選有沒有類別 hot 者,加入 cool 類別 (因此「蜂蜜」和「香醋」兩項目會顯示綠色)

$items.has('em').addClass('complete'):有 <em> 的元素加入 CSS 類別 complete (因此「新鮮無花果」項目顯示灰色)

$items.filter('.hot').prepend('優先項目:');:針對每一個項目, 如果有 hot 類別,前面加上「優先項目:」字樣

✶ 同於:$('li.hot').prepend('優先項目:');

$('li:contains("蜂蜜"))...:蜂蜜項目後面加上「(當地)」字樣

(11) 排序

∗ jQuery 選擇的元素以陣列儲存

▸ 索引值從 0 開始

▸ 可以利用類似 CSS 選擇器的方式,利用索引值來篩選,例如:$('li:lt(3)')

∗ 以索引值選擇元素

方法 說明
.eq(<n>)
:eq(<n>)
排序等於 <n> 的元素 (函式與篩選)
.lt(<n>)
:lt(<n>)
排序小於 <n> 的元素 (函式與篩選)
.gt(<n>)
:gt(<n>)
排序大於 <n> 的元素 (函式與篩選)

▸ 以下兩者相同:

$('li:lt(2))
$('li').lt(2)

∗ 練習:利用索引進一步篩選元素

index.html (類似 looping.html):

...
<script src="js/index.js"></script>
...

js/index.js

$(document).ready(function() {

  $('li:lt(2)').removeClass('hot');
  $('li').eq(0).addClass('complete');
  $('li:gt(2)').addClass('cool');

});

$('li:lt(2)').removeClass(...):選擇索引值小於 2 的 <li> 元素並移除 hot 類別 (因此第 1、2 項去除紅色)

$('li').eq(0).addClass(...):將排序 0 的 <li> 元素加上 complete 類別 (因此第 1 項顯示灰色)

$('li:gt(2)').addClass(...):選擇索引值大於 2 的 <li> 元素並加上 cool 類別 (因此第 3 項顯示綠色)

(12) 表單

∗ 選擇表單元素

方法 說明
:button <button><input type="button"> 元素
:checkbox <input type="checkbox"> 元素
:checked <input type="checkbox"<input type="radio"> 元素被選擇者
:disabled 被停用的元素
:enabled 被啟用的元素
:focus 目前聚焦的元素
:file <input type="file"> 元素
:image <input type="image"> 元素
:input 所有 input, textarea, select, 與 button 元素
:password <input type="password"> 元素
:radio <input type="radio"> 元素
:reset 重設元素
:selected <select> 元素裡被選擇的 <option> 元素
:submit <input type="submit"> 元素
:text <input type="text"> 元素或者沒有 type 屬性的元素

∗ 取出表單元素值

方法 說明
.val() 取出第一個選到的 <input>, <select>, 或 <textarea> 元素的值 (這些元素有 value 屬性)

∗ 表單事件

事件 (Event) 說明
blur 當元素失焦
change <input> 的值變動
focus 當元素聚焦
select <select> 的值變動
submit 當表單送出

∗ 練習:加入新雜貨

▸ 一開始顯示「新雜貨」按鈕

▸ 按下按鈕後,出現表單輸入框

▸ 填入雜貨名稱並按下「加入」鈕後,出現在清單中

form.html (類似 looping.html):

...
<div id="page">
  <h1 id="header">清單</h1>
  <h2>買雜貨</h2>
  <ul>
    ...
  </ul>
</div>

<div id="newItemButton"><button id="showForm" href="#">新項目</button></div>
<form id="newItemForm" method="post" action="#">
  <input id="itemDesc" type="text" placeholder="加入說明" ...>
  <input id="addButton" type="submit" value="加入">
</form>
...
<script src="js/form.js"></script>
...

js/form.js

$(document).ready(function() {
  
  var $newItemButton = $('#newItemButton');
  var $newItemForm = $('#newItemForm');
  var $textInput = $('input:text');
  
  $newItemButton.show();
  $newItemForm.hide();
  
  $(document).on('click', '#showForm', function() {
    $newItemButton.hide();
    $newItemForm.show();
    $textInput.focus();
  });
  
  $(document).on('submit', '#newItemForm', function() {
    $('li:last').after('<li>' + $textInput.val() + '</li>');
    $newItemButton.show();
    $newItemForm.hide();
    $textInput.val('');
    return false;
  });
  
});

▸ 首先選到 3 個元素:$newItemButton, $newItemForm, $textInput

$newItemButton.show(), $newItemForm.hide():顯示「新雜貨」按鈕,隱藏表單

$(document).on('click', '#showForm', ...):將點擊事件綁定按鈕,點擊後隱藏按鈕、顯示表單、並聚焦輸入欄

$(document).on('submit', '#newItemForm', ...):將送出事件綁定表單

$('li:last').after(...):產生一個新 <li> 元素,其內容即為使用者輸入的資料,然後將元素置於最後一個 <li> 之後
$newItemButton.show(), $newItemForm.hide():顯示按鈕,隱藏表單
$textInput.val(''):清空輸入框
return false:取消瀏覽器預設行為 (表單不送出)

∗ 作業 3

(13) 方框尺寸

∗ 方框尺寸

方法 說明
.width()
.width(<pixels>)
取出或設定方框寬度 (不含 padding, border, margin)
.height()
.height(<pixels>)
取出或設定方框高度 (不含 padding, border, margin)
.innerWidth() 取出方框寬度 (含 padding)
.innerHeight() 取出方框高度 (含padding)
.outerWidth() 取出方框寬度 (含 padding, border)
.outerHeight() 取出方框高度 (含 padding, border)
.outerWidth(true) 取出方框寬度 (含 padding, border, margin)
.outerHeight(true) 取出方框高度 (含 padding, border, margin)

▸ 取出資料時,函式回覆第一個選到的元素

▸ 設定資料時,參數可給像素值、em、pt、或百分比,除像素值為純數值外,其餘都需加單位成為字串,例如:'50em', '50px', '50%'

boxSize

∗ 練習:取出及設定方框寬度

dimension.html (類似 looping.html):

...
<script src="js/dimension.js"></script>
...

js/dimension.js

$(document).ready(function() {

  var listHeight = $('#page').height();
  $('ul').append('<p>高度:' + listHeight + '像素</p>');
  $('li#one').width(180);
  $('li#two').width('50%');
  $('li#three').offset({top:100, left:200});

});

$('#page').height():取得區塊元素的寬度

$('ul').append(...):在 <ul> 裡最後附加一個元素

$(...).width(180):設定元素寬度為 180px

$(...).width('50%'):設定元素寬度為其環境寬度的一半

$(...).offset({top:100, left:200}):設定元素相對於 document 物件位置的位移,距頂端 100px,距左端 200px

(14) 位置

∗ 設定捲軸及位置

方法 說明
.scrollLeft()
.scrollLeft(<pos>)
取出或設定左右捲軸位置 (單位:像素)
.scrollTop()
.scrollTop(<pos)
取出或設定上下捲軸位置
.offset()
.offset({top:<pos>, left:<pos>})
取出或設定位置 (相對於文件左上角)
.position()
.position({top:<pos>, left:<pos>})
取出或設定位置 (相對於父元素左上角)

∗ 練習:設定廣告的滑入與滑出

position.html (類似 looping.html):

...
<div id="page">
  ...
  <ul>
    ...
  </ul>
  <p id="footer">©雜貨王</p>
  <div id="slideAd">到雜貨王購物享9折優惠</div>
</div>

<script src="js/position.js"></script>
...

js/position.js

$(document).ready(function() {
  
  var $window = $(window);
  var $slideAd = $('#slideAd');
  
  $window.on('scroll', function() {
    if($window.scrollTop() + $window.height() == $(document).height()) {
      $slideAd.animate({'right': 0}, 250);
    }
    else {
      $slideAd.stop().animate({'right': -360}, 250);
    }
  });
  
});

var $window = ..., var slideAd = ...:選到目標元素

$window.on('scroll' ...:綁定捲動事件

if ($(window).scrollTop() + ... :已到達文件最下方

$slideAd.animate({'right': 0}, 250):以 0.25 秒速度滑到右端距離為 0 (滑入)

$slideAd.stop():停止目前的動畫

.animate({'right': -360}, 250):以 0.25 秒速度滑到右端距離為 -360px (滑出)

∗ 作業 4

上一章       下一章