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
}