jQuery網頁元素操控
【網頁元素操作】
在網頁上動態地增減元素是撰寫AJAX網頁時重要的課題,傳統Javascript常用的做法是透過document.createElement("tagName")的方式建立元素,再一一設定屬性,最後透過appendChild()方法將元素新增在某個父元素之下。如以下的例子:
<body onload="createElem()">
<div id="dvDisp">Welcome to </div>
<script type="text/javascript">
function createElem() {
var a = document.createElement("a");
a.href = "http://msdn.microsoft.com/zh-tw/default.aspx";
a.target = "_blank";
var img = document.createElement("img");
img.src = "http://i3.msdn.microsoft.com/Platform/Controls/Masthead/resources/msdn.logo.jpg";
img.alt = "MSDN Logo";
a.appendChild(img);
document.getElementById("dvDisp").appendChild(a);
}
</script>
</body>
每個屬性都要分開來指定十分瑣碎煩人,不少過去專攻IE的網頁開發者或許會想到,為何不用outerHTML直接指定HTML標籤?
不是乾淨俐落多了。只可惜並不是每種瀏覽器都支援outerHTML,但好消息是IE領先提出的innerHTML已被主流瀏覽器採納為DOM的標準規格。因此上述例子可以再簡化:
function createElem() {
var a = document.createElement("a");
a.href = "http://msdn.microsoft.com/zh-tw/default.aspx";
a.target = "_blank";
a.innerHTML = "<img src='http://i3.msdn.microsoft.com/Platform/Controls/Masthead/resources/msdn.logo.jpg' alt='MSDN Logo' />";
document.getElementById("dvDisp").appendChild(a);
}
當然,使用document.getElementById("dvDisp").innerHTML += "<a href='.... 略 ....
</a>"的寫法也是可行,但是若dvDisp的內容複雜時,重設innerHTML會致使dvDisp的所有內容重新產生,效率較差。
補充: http://www.quirksmode.org/dom/w3c_html.html 可以查到各瀏覽器對innerHTML, outerHTML,
innerText等屬性的支援現況。
jQuery裡巧妙地利用暫建物件的做法,讓我們可以跨瀏覽器用類似指定outerHTML的方式建立元素,以上的例子可直接寫成:
$(function() {
$("#dvDisp").append($("<a href='http://msdn.microsoft.com/zh-tw/default.aspx' target='_blank'>" +
"<img src='http://i3.msdn.microsoft.com/Platform/Controls/Masthead/resources/msdn.logo.jpg' alt='MSDN Logo' />" +
"</a>"));
});
除了可以直接指定HTML標籤建立元素,jQuery還提供了許多操弄元素的方便函數:
在以下的說明中,X, Y可為HTML標籤、元素物件或Selector
- html(), html(val) 讀取或設定innerHTML
- text(), text(val) 讀取或設定innerText
- $(X).append( Y ) 在X內新增Y當成最後的子元素
- $(X).appendTo( Y ) 將X附加到Y內作為最後的子元素
- $(X).prepend( Y ) 將Y插入X內當作第一個子元素
- $(X).prependTo( Y ) 將X插入Y內當作第一個子元素
- $(X).after( Y ) 將Y接在X後方
- $(X).before( Y ) 在Y插入到X前方
- $(X).insertAfter( Y ) 將X接在Y的後方
- $(X).insertBefore( Y ) 將X插入到Y的前方
-
$(X).wrap( Y )
用Y將X包起來(與wrapAll最大的差別在於wrap時每個X都會被一個Y包住)
- $(X).wrapAll( Y ) 將所有X元素集中在一起並用一個Y包起來
- $(X).wrapInner( Y ) 將X的子元素用Y包起來
- $(X).replaceWith( Y ) 將X置換成Y
- $(X).replaceAll( Y ) 以X去置換Y
- $(X).clone() 複製一份X
這裡用一個簡單的範例,展示動態新增元素用jQuery做起來不過是幾行程式的功夫。
我們做一個積木接接樂,上方的<div id="dvPool">裡放入四色方塊(<div class="Square">),下方則是<div
id="dvWorkBench">,選取dvPool中的方塊後,我們利用clone()複製<div
class="Square">,放入dvWorkBench中。dvWorkBench中的方塊在點選後會取得焦點(addClass("Focus");),若有設定焦點,之後再插入方塊時,會安插在焦點方塊的後方。
配合CSS設定,以上的互動操作,扣除註解不到20行程式碼就可以完成。(見程式範例檔: AddElementDone.htm)
$(function() {
//Pool中產生四色方塊
var colors = ["red", "green", "blue", "yellow"];
//利用$.each跑迴圈, callback中, this就是陣列中的元素
$.each(colors, function() {
$("#dvPool")
.append("<div class='Square' style='background-color:" + this + "'></div>");
});
//點選後觸發新增到下方動作
$("#dvPool .Square").click(function() {
var newSquare =
$(this).clone()
.click(function() {
//取消目前的焦點方塊
$(".Focus").removeClass("Focus");
//點選者設成焦點方塊
$(this).addClass("Focus");
});
//有焦點物件時,加在其後方
if ($(".Focus").length > 0)
$(".Focus").after(newSquare);
//否則就直接加在最後一個
else
$("#dvWorkBench").append(newSquare);
});
});
【共用函數補充】
在以上的範例中,我們提到了$.each()這個函數,事實上,jQuery還有不少好用的共用函數,在此一道做個補充:
- 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中(若同名屬性存在則覆寫之),很常用於指定參數的預設值,例如:
var finalSetting = { };
var defaultSetting = { limit: 256, maxRows: 16, maxCols: 16 };
var userOption = { maxRows: 10 };
//第一個參數物件會被修改,為了保持defaultSetting不被更動,放在第二個參數
$.extend(finalSetting, defaultSetting, userOption);
$.each(finalSetting, function(i, val) {
alert(i + "->" + val);
});
-
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。
【範例檔案下載】