2.2.1 $()函數
DOM提供了 document.getElementById方法,可以根據傳入的頁面元素的id返回相應的元素對象。$()函數是 document.getElementById函數的一個簡化寫法,它比DOM中的方法功能更加強大,比如$()函數可以接受多個參數,返回滿足條件的 Array對象。在Prototype中$()函數的實現代碼如例2-1所示。
例2-1 $()函數
function $() {
var results = [], element;
for (var i = 0; i < arguments.length; i++) { // 可以傳入多個參數
element = arguments[i];
// 如果參數的類型是字符串
if (typeof element == 'string')
element = document.getElementById(element);
results.push(Element.extend(element)); // 將得到的對象加入results數組
}
// 如果只返回一個對象,直接返回該對象,如果返回了多個對象,則返回包含所有這些對象的數組
return results.length < 2 ? results[0] : results;
}
從例2-1中可以看到,當$()只有1個輸入參數 時,它和document.getElementById是等效的,而當$()擁有多個輸入參數時,其返回值是一個Array對象,這個數組包含了所有符 合條件的對象。例2-2中分別用1個和多個參數調用了$()方法,注意示例中的黑體字。
例2-2 $()函數應用示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>chapter 3</title>
<script type="text/javascript" language="javascript"
src="prototype.js" ></script>
<script type="text/javascript" language="javascript">
function test1() {
var div = $("div1"); // 單個參數
alert(div.innerHTML); // 輸出div1的HTML文本
}
function test2() {
var divs = $("div1", "div2"); // 多個參數
for (var i = 0; i < divs.length; i++) {
alert(divs[i].innerHTML); // 依次輸出div1、div2的HTML文本
}
}
</script>
</head>
<body>
<div id="div1">
div1
</div>
<div id="div2">
div2
</div>
<input type="button" value="click1" οnclick="test1()" />
<input type="button" value="click2" οnclick="test2()" />
</body>
</html>
2.2.2 $A()函數
$A()函數可以將一個可枚舉的對象轉換爲一個Array對象,它和Array.from()是等效的。例2-3是Prototype中$A()函數的實現代碼。
例2-3 $A()函數
var $A = Array.from = function(iterable) {
if (!iterable) return [];// 如果iterable對象不存在,返回空數組
if (iterable.toArray) { // 如果iterable有toArray方法,返回iterable.toArray()
return iterable.toArray();
} else {
var results = [];
for (var i = 0; i < iterable.length; i++)
results.push(iterable[i]);
return results;//返回對象數組
}
}
可以看到,$A()函數是通過兩種方式返回 Array對象的。第一種方式是如果傳入的對象已經實現了toArray方法,那麼則直接調用其toArray方法;第二種方式是通過循環的方式返回對象 的數組。使用第二種方式的前提是傳入的對象具有length屬性,並且可以通過序號索引其內部的所有對象。例2-4是$A()函數的應用示例,注意示例中 的黑體字。
例2-4 $A()函數應用示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>chapter 3</title>
<script language="javascript" src="prototype.js"
type="text/javascript"></script>
<script language="javascript" type="text/javascript">
function showOptions() {
// 獲取所有option對象的集合
var someNodeList = $("lstFramework").getElementsByTagName("option");
// 通過$A方法把option對象的集合轉換爲Array對象
var nodes = $A(someNodeList);
var info = [];
nodes.each (function(node){ // 遍歷nodes,添加到info數組中
info.push(node.value + ": " + node.innerHTML);
});
alert(info.join("/r/n"));
}
</script>
</head>
<body>
<form>
<select id="lstFramework" size="10">
<option value="1">Prototype</option>
<option value="2">Script.aculo.us</option>
<option value="3">Dojo</option>
<option value="4">YUI</option>
</select>
<input οnclick="showOptions();" type="button" value="Show the options">
</form>
</body>
</html>
圖2-1 $A函數應用示例
例2-4是通過點擊“Show the options”按鈕觸發onclick事件的響應函數showOptions,函數showOptions使用$A方法將lstFramework 的option對象集合轉換爲數組輸出,相應的輸出結果如圖2-1所示。
2.2.3 $F()函數
$F()是另一個經常使用的快捷方式,它是 Form.Element.getValue()函數的縮寫。$F()函數用來求得頁面中輸入控件的輸入值,它的輸入參數可以是目標控件的id值,也可以 是目標控件對象本身。$F支持的輸入控件包括<input>系列(即type=submit / hidden / password / text / checkbox / radio)、下拉列表<select>控件(多選的情況下,$F將會返回所有選中值的Array對象)和<textarea> 控件。例2-5給出了$F()函數的應用示例,該示例通過點擊按鈕觸發onclick事件的響應函數test,調用$F()方法獲得輸入控件 “username”的輸入值,然後輸出。
例2-5 $F()函數應用示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>chapter 3</title>
<script type="text/javascript" language="javascript"
src="prototype.js" ></script>
<script type="text/javascript" language="javascript">
function test() {
alert($F("userName"));
}
</script>
</head>
<body>
<form>
<input type="text" id="userName" value="test username">
<input type="button" value="click" οnclick="test()">
</form>
</body>
</html>
2.2.4 $H()函數
Hash對象Prototype中定義了Hash對 象一個用於模擬Hash數據結構,$H()函數的功能是將對象轉換爲Hash對象。$H函數將Hash對象的方法和屬性通過Object.extend方 法擴展到目標對象上,這樣返回的對象就具有了Hash對象的方法,如keys方法,values方法等等。下面是$H()函數的一個應用示例:
<script>
function test() {
// 創建一個對象
var obj = {
key1: 1,
key2: 2,
key3: 3
};
// 將其轉換爲Hash對象
var hash = $H(obj);
alert(hash.toQueryString());
}
</script>
2.2.5 $R()函數
$R()函數是new ObjectRange(start, end, exclusive)的縮寫形式,它根據指定的起始邊界返回相應的對象範圍。在Prototype中$R()函數的定義如例2-6所示。
例2-6 $R()函數定義
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
},
_each: function(iterator) {
var value = this.start;
do {
iterator(value);
value = value.succ();
} while (this.include(value));
},
// include函數的作用是判斷value是否包含在對象範圍之內
include: function(value) {
if (value < this.start)
return false;
if (this.exclusive) // 注意exclusive參數僅在判斷上界是有效
return value < this.end;
return value <= this.end;
}
});
var $R = function(start, end, exclusive) {
// 定義$R方法,$R是new ObjectRange(start, end, exclusive)的一個簡單寫法或快捷方式
return new ObjectRange(start, end, exclusive);
}
可以看到,ObjectRange類是由 Enumerable類繼承而來,它的初始化參數start、end和exclusive分別代表ObjectRange對象的下界、上界以及是否排除上 界的值。這裏需要注意的是,exclusive參數僅僅對上界起作用,從ObjectRange的include方法的實現代碼中不難看出這一點。例2- 7給出了$R()函數的應用示例,其中比較了exclusive參數分別爲true和false時的區別。
例2-7 $R()函數應用示例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>chapter 3</title>
<script type="text/javascript" language="javascript"
src="prototype.js" ></script>
<script>
// 依次輸出1,2,3,4
function test_R1(){
var range = $R(1, 5, true);
range.each(function(value, index){
alert(value);
});
}
// 依次輸出1,2,3,4,5
function test_R2(){
var range = $R(1, 5, false);
range.each(function(value, index){
alert(value);
});
}
</script>
</head>
<body>
<form>
<input type="button" value="click (exclusive = true)"
οnclick="test_R1()" />
<input type="button" value="click (exclusive = false)"
οnclick="test_R2()" />
</form>
</body>
</html>
2.2.6 $$()函數
$$()函數是Prototype 1.5新增的一個快捷方式,它允許開發人員通過CSS樣式選擇頁面中的元素。熟悉XPath的讀者會發現,CSS選擇符在語法形式上和XML文檔的XPath十分類似,Prototype支持的CSS選擇符包括以下幾種類型:
l 元素標籤名稱,例如:$$(“li”)。
l 元素ID,例如:$$(“#fixtures”)。
l CSS類名,例如:$$(“.first”)。
l 元素是否具有某個屬性,例如:$$(“h1[class]”)。
l 元素的某個屬性是否符合特定的條件,例如:$$('a[href="#"]')、$$('a[class~="internal"]')、$$('a[href!=#]')。
l 上面所有這些CSS選擇符的類型可以自由組合,形成一個複合的CSS選擇符,例如:$$('li#item_3[class][href!="#"]')。
l 不同的CSS選擇符(包括複合CSS選擇符)之間用空格分隔,就組成了一個多層的CSS選擇符,它通過指定目標元素的父節點甚至更多層父節點的CSS樣式屬性來定位目標元素。例如:$$('div[style] p[id] strong')。
例2-8給出了一個$$()函數的測試頁面示例,讀者可以在該頁面中輸入不同的CSS選擇符表達式,測試結果。
例2-8 $$()函數測試頁面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>chapter 3</title>
<style type="text/css" media="screen">
/* <![CDATA[ */
#testcss1 { font-size:11px; color: #f00; }
#testcss2 { font-size:12px; color: #0f0; display: none; }
/* ]]> */
</style>
<script type="text/javascript" language="javascript"
src="prototype.js" ></script>
<script>
function test() {
// 根據輸入的CSS選擇符,切換相應元素的顯示
$$($F('csspath')).each(
function(item) {
Element.toggle(item);
}
);
}
</script>
</head>
<body>
<form>
<div id="fixtures">
<h1 class="title">Some title <span>here</span></h1>
<p id="p" class="first summary">
<strong id="strong">This</strong> is a short blurb
<!-- 該頁面元素具備 first和internal兩種CSS樣式-->
<a id="link_1" class="first internal" href="#">with a link</a> or
<a id="link_2" class="internal highlight" href="#">
<em id="em">two</em>
</a>.
</p>
<ul id="list">
<li id="item_1" class="first">
<a id="link_3" href="#" class="external">
<span id="span">Another link</span>
</a>
</li>
<li id="item_2">Some text</li>
<li id="item_3" xml:lang="es-us" class="">Otra cosa</li>
</ul>
</div>
<input type="text" value="" id="csspath" />
<input type="button" value="click" οnclick="test()" />
</form>
</body>
</html>
例2-8的運行頁面如圖2-2所示,在文本輸入框中輸入一個CSS選擇符(例如“.title”),點擊“click”按鈕即可切換相應的頁面元素(即Some title here)的顯示/隱藏狀態。
(a) 在文本輸入框中輸入CSS選擇符“.title” (b) 頁面元素“Some title here”隱藏
圖2-2 $$函數應用示例
2.2.7 Try.these()函數
在程序開發的過程中有時會遇到這樣的情況:在若干個函數中開發人員不能確定哪一個會返回正確的結果,只能依次嘗試。Prototype中Try.these()函數爲開發人員提供了一個很簡便的方式來解決類似的問題。Try.these()函數的的定義如例2-9所示。
例2-9 Try.these()函數
var Try = {
these: function() {
// 返回結果
var returnValue;
for (var i = 0; i < arguments.length; i++) {
// 輸入參數爲多個function對象
var lambda = arguments[i];
try {
// 如果其中一個函數成功返回,則返回該函數的結果
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
}
從上述代碼中可以看到,Try.these()函數 的每一個參數都必須是一個無參的JavaScript方法。在Prototype框架中,實現Ajax對象的getTransport方法就用到了 Try.these()函數,getTransport方法的作用是返回一個XMLHttpRequest對象,而在不同瀏覽器中創建 XMLHttpRequest對象的方式是不同的。通過Try.these ()函數可以依次嘗試各種瀏覽器創建XMLHttpRequest對象的方法,直到成功爲止。例2-10所示爲Ajax對象的getTransport方 法的實現代碼。
例2-10 Ajax對象的getTransport方法的實現代碼
var Ajax = {
getTransport: function() {
// 嘗試以下3種創建XMLHttpRequest對象的方法
// 1. Mozilla瀏覽器中的XMLHttpRequest對象
// 2. 創建ActiveX對象"Msxml2.XMLHTTP"
// 3. 創建ActiveX對象"Microsoft.XMLHTTP"
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},
// 當前活動的Ajax請求計數
activeRequestCount: 0
}