邊做邊學jQuery系列05 - jQuery的樣式、屬性、欄位內容存取語法

課程錄製時間: 2009年
jQuery的樣式、屬性、欄位內容存取語法

【選取功能延伸】

除了用Selector語法取得符合特定條件的網頁元素外,我們還可以對結果群組做一些後續處理

  • eq( N ) 傳回群組中第N個jQuery物件(get(N)傳回的是元素本身)
  • hasClass( className ) 檢查是否設定了特定的CSS類別,結果傳回true/false
  • filter( expr ) 使用Selector語法對群組進行篩選
  • filter( fn ) 使用自訂函數對群組進行篩選,自訂函數可以接收index參數或由this存取元素本身,傳回true或false決定保留或剔除
  • is( expr ) 使用Selector語法對群組進行篩選,如果篩選後個數大於零時傳回true
  • map( callback ) 透過自訂函數,對群組中的每個元素進行轉換
  • not( expr ) 利用Selector語法剔除指定條件的元素
  • slice( start, end ) 取出群組中第start到第end個元素
  • add( expr ) 跟另一個Selector語法查詢得到的結果群組合併在一起
  • children( expr ) 用Selector對群組裡各元素的子元素進行篩選
  • contents( ) 傳回元素的所有子元素集合(childNodes),若為IFrame則傳回內容網頁(contentDocument)
  • find( expr ) 以Selector語法篩選其下的所有元素(不限直接隸屬,子元素下的子元素也包含在內)
  • next( expr ) 找出緊臨的下一個同層元素,支援Selector語法篩選
  • nextAll( expr ) 找出排在該元素後方的所有同層元素,支援Selector語法篩選
  • offsetParent( ) 元素在座標定位上所屬的容器元素,例如: 元素為<td>時傳回<table>
  • parent( expr ) 元素所屬的父元素,可利用Selector進行篩選
  • parents( expr ) 傳回元素的所有上層元素(包含父元素的父元素,會一層一層往上找),可透過Selector語法進行篩選。例如: $("#theInput").parents("tr:first")可找出輸入欄位所在的<tr>,在寫編輯UI互動時很有用。
  • closest( expr ) 1.3版新增,用Selector在父系元素中找出最內層者,等同於上述所說parents("tr:first")在做的事。
  • prev( expr ) 找出緊臨的上一個同層元素,可傳入Selector進行篩選
  • prevAll( expr ) 找出排在該元素前方的所有同層元素,支援Selector語法篩選
  • siblings( expr ) 找出與該元素位屬同層的所有元素(父元素是同一個的兄弟姐妹,但不含自己),支援Selector語法篩選
  • andSelf( ) 在進行find等操作後,再回頭將當初的對象也合併入結果群組中。例如: $("#myDiv").nextAll("div").andSelf()可以得到#myDiv後方旳所有同層<div>再加上#myDiv本身
  • end( ) 將操作對象切換回先前的對象。原本的$("#myDiv").children("p").addClass("clsName1"),此時操作對象已是#myDiv下的所有<p>了,此時若要再對#myDiv下的所有<span>做動作,除了另寫一列$("#myDiv").children("span").addClass("clsName2")之外,還可透過end(),再把對象切回到#myDiv,改寫成一行$("#myDiv").children("p").addClass("clsName1").end().children("span").addClass("clsName2")

以下來做個簡單的練習,我們先做一固9x9的表格,要產生出按下任何一格時,將該格所屬橫列塗成綠色,該格所屬直行塗成紅色,該格塗黑的效果。

 

$(function() {
    $("#matrix td").click(function() {
        var td = $(this);
        //將所有格子全部塗白
        td.parents("table:first").find("td")
        .css("background-color", "white");
        //用parent()取得<td>所屬<tr>
        var tr = td.parent();
        //全列塗紅
        tr.children().css("background-color", "red");
        //以index()找出是第幾欄, 稍後要用於nth-child
        //以1起算,故先加1
        var nthChild = tr.children().index(td) + 1;
        //將表格所有其他<tr>塗綠
        tr.siblings().find("td:nth-child(" + nthChild + ")")
        .css("background-color", "green");
        //本格塗黑
        td.css("background-color", "black");
    });
});

再來一個例子,假想點選格子時來決定出一塊範圍大小。

$(function() {
    $("#matrix td").click(function() {
        var td = $(this);
        //將所有格子全部塗白
        td.parents("table:first").find("td")
        .css("background-color", "white");
        //用parent()取得<td>所屬<tr>
        var tr = td.parent();
        //以index()找出是第幾欄, 稍後要用於nth-child
        //以1起算,故先加1
        var nthChild = tr.children().index(td) + 1;
        //該列及以上只塗右半部
        tr.prevAll().andSelf().find("td:nth-child(" + nthChild + ")")
        .nextAll().css("background-color", "blue");
        //該列以下全塗
        tr.nextAll().children().css("background-color", "blue");
    });
});

這兩題大家可以先用傳統Javascript寫法試做一次,再驗證jQuery的程式碼是不是簡短許多。

【樣式與屬性】

檥式(CSS Style)與屬性(Attribute)的操作很簡單,應用卻很廣泛,在先前的範例中已出現過序次。要指定元素的外觀樣式,可以透過指定或移除樣式類別方式為之,即使用addClass( className )及removeClass( className),另外hasClass( className )會傳回Boolean指出元素是否被指定了特定的樣式類別,toggleClass( className )則可用在需要來回切換樣式類別的場合,例如: 第一次呼叫時加上樣式類別、第二次則移除、第三次再加上,以此類推。

另外,我們也可以單獨指定某個樣式屬性,透過css( key, value )的方式進行, css("background-color", "blue") 的語法例子在先前已出現過多次,如果一次要設定多個CSS屬性,也可利用之前介紹過的匿名物件技巧,寫成 css({ backgroundColor:"blue", color:"white",  cursor:"pointer" }) 。另外,我們也可以透過函數來決定設定值的寫法,例如以下的例子可以將所有<div>的寬度放大兩倍。

$("div").css("width", function() { return $(this).with() * 2; });

以上談的都是設定CSS,若要取得CSS屬性值,只傳入屬性名稱一個參數即可,例如: alert($("#myDiv").css("color"))。

針對元素的位置、寬度、高度,有幾個專屬的函數:

  • offset() 傳回一個包含top, left值的物件,用以表示元素相對於document的座標
  • position() 傳回一個包含top, left值的物件,用以表示元素相對於其容器元素的座標
  • scrollTop() 傳回元素的垂直捲動位移
  • scrollTop( val ) 設定元素的垂直捲動位移
  • scrollLeft() 傳回元素的水平捲動位移
  • scrollLeft( val ) 設定元素的水平捲動位移
  • height() 傳回元素的高度
  • height( val ) 設定元素的高度
  • width() 傳回元素的寬度
  • width( val ) 設定元素寬度
  • innerHeight() 傳回內部高度(扣除border及padding)
  • innerWidth() 傳回內部寬度(扣除border及padding)
  • outerHeight( true/false ) 傳回外部高度,預設扣除border及padding,傳入參數決定是否包含margin
  • outerWidth( true/false ) 傳回外部寬度,預設扣除border及padding,傳入參數決定是否包含margin

關於margin, border, padding的定義,可參考W3C的Box Model說明,如下圖。(圖片來源: http://www.w3.org/TR/CSS2/box.html)

存取屬性的相關函數語法與CSS幾乎完全相同,attr( key, value )可以設定屬性值,attr( key )可以讀取屬性值,removeAttr( key )則是移除屬性值,利用匿名物件參數則可以一次設定多個屬性,如果要利用自訂邏輯決定屬性值,一樣可以透過attr( key, fn )的方式達成。

屬性除了用來讀取或設定一些預設如href, link, src等元素既有屬性外,還可以自訂屬性名稱,用來保存我們想放在元素上的特殊資訊,當成Metadata的儲存處所,例如以下的練習範例。

建立一個9x9的格子陣列,以亂數方式選定十個<td>放入十顆地雷,利用<td>的onclick事件,在點擊到埋有地雷的格子時,以橘底顯示所有地雷、紅底顯示引爆點,並彈出BOOM爆炸訊息。在<td>上,我們自訂一個屬性mine = "true"來標示是否埋有地雷。

$(function() {
    var tdCol = $("#matrix td");
    //以亂數任選10個格子以設定mine attribute方式埋入地雷
    for (var i = 0; i < 10; i++) {
        var idx = 0;
        //加入do while邏輯以避免埋在重覆的格子中
        do {
            idx = Math.floor(Math.random() * tdCol.length);
        } while (tdCol.eq(idx).attr("mine") == "true");
        //設定mine attribute
        tdCol.eq(idx).attr("mine", "true");
    }
    //設定點選事件
    $("#matrix td").click(function() {
        var td = $(this);
        //比對屬性決定是否踩到地雷
        if (td.attr("mine") == "true") {
            td.closest("table")
            //利用td[mine=true]選取所有地雷格子塗色
            .find("td[mine=true]")
            .css("background-color", "orange")
            //踩中位置塗紅色
            td.css("background-color", "red");
            alert("BOOM!");
        }
        else //未踩中塗灰色
            td.css("background-color", "#cccccc");
    });
});

【元素內容存取】

取得元素的內容或輸入欄位的數值是開發前端程式時的重要工作之一,jQuery提供了html()、text()可取得innerHTML及innerText內容,html( val )、text( val )則可以設定。值得一提的是,innerText是只有IE提供的DOM API,在其他瀏覽器中另有存取方法,jQuery提供了通透性,用text()/text( val )就能在不同瀏覽器實踐了讀/寫innerText的效果。

至於<input>欄位的數值存取與設定,同理推演就是val()及val( val )了,而在不同的輸入欄位格式上處理方式有些許不同:

  • textbox, password, textarea 可以直接使用val()及val( val )讀取及設定欄位內容
  • select 若為單選,val()傳回的是字串,而val( val )要傳入的也是字串。當為多選時(<select multiple="multiple">時,則val()會傳回字串陣列,由所有選取的選項內容組成,同理此時要設定時也要傳入陣列。
  • radio 實務上多半有多個<input type="radio">指定同樣的name,但指定不同的value,在使用時選取同一群radio(可透過#name)以val()取得被選取radio的值。要設定時,則是選取該群radio,再傳入單一字串的陣列,例如: val([ str ]),就可選取value與str相同的radio。
  • checkbox 比較特殊一些,它常用於多選選項,所以若要一口氣找出所有被勾選的項目,通常可以善用:checked這個虛擬類別(Pseudo Class)一次將被勾選的checkbox找出來,再逐一用val()取值。而要設定時則與radio相同,先選取所有可能選項的checkbox,傳入字串陣列,jQuery會逐一比對,將吻合者勾選起來。

以下是程式範例:

<input type="text" class="inp" /><br />
<textarea class="inp" ></textarea><br />
<select class="inp" id="selSingle">
<option>Opt1</option><option>Opt2</option><option>Opt3</option>
</select><br />
<select multiple="multiple" class="inp" id="selMulti">
<option>Opt1</option><option>Opt2</option><option>Opt3</option>
</select>
<div id="rdo">
<input type="radio" name="r" value="Radio1" />RDO1
<input type="radio" name="r" value="Radio2" />RDO2
</div>
<div id="cbx">
<input type="checkbox" value="Checkbox1" />CBX1
<input type="checkbox" value="Checkbox2" />CBX2
<input type="checkbox" value="Checkbox3" />CBX3
</div>
<input type="button" value="Set Value" onclick="setVal()" />
<input type="button" value="Show Value" onclick="showVal()" />
<script type="text/javascript">
    function setVal() {
        $("input:text").val("TextBox");
        $("textarea").val("TextArea!");
        $("#selSingle").val("Opt2");
        $("#selMulti").val(["Opt1", "Opt3"]);
        $("#rdo input").val(["Radio2"]);
        $("#cbx input").val(["Checkbox1", "Checkbox3"]);
    }
    function showVal() {
        $(".inp").each(function() {
            var v = $(this).val();
            alert(this.tagName + "->" + v);
        });
        alert("Radio: " + $("#rdo input").val());
        $("#cbx input:checkbox:checked").each(function() {
            alert("Checkbox: " + $(this).val());
        });
    }
</script>

【範例檔案下載】

歡迎推文分享:



 
RSS
【工商服務】
OrcsWeb: Windows Server Hosting
twMVC

關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。