ProtoType-JavaScript类库
prototype.js 是什么?
prototype.js是由Sam Stephenson写的一个javascript类库。这个构思奇妙,而且兼
容标准的类库,能帮助你轻松建立有高度互动的web2.0 特性的富客户端页面。
可以从:
下在最新的prototype.js的javascript类库
一、一些实用的函数
这个类库带有很多预定义的对象和实用函数,使用这些函数的目的显然是把你从一些重复的打字中解放出来 。
1、使用$()方法
$() 方法是在 DOM 中使用过于频繁的 document.getElementById() 方法的一个便利的简写,就像这个 DOM 方法一样,这个方法返回参数传入的 id的那个元素。
比起 DOM 中的方法,这个更胜一筹。你可以传入多个 id 作为参数然后 $() 返回一个带有所有要求的元素对象的一个 Array 对象。
<HTML>
<HEAD>
<TITLE>未来蓝图</TITLE>
<script src="./js/prototype.js"></script>
<script>
function test1()
{
var d = $('d1');
alert(d.innerHTML);
}
function test2()
{
var divs = $('d1','d2');
for(i=0;i<divs.length;i++)
{
alert(divs[i].innerHTML);
}
}
</script>
</HEAD>
<BODY>
<div id="d1">
<p>This is a paragraph</p>
</div>
<div id="d2">
<p>This is another paragraph</p>
</div>
<input type="button" value=Test1 onclick="test1();"><br>
<input type="button" value=Test2 onclick="test2();"><br>
</BODY>
</HTML>
备注:另外一个好处是,这个函数能传入用string 表示的对象ID,也可以传入对象本身,这样,在建立其它能传两种类型的参数函数时非常有用。
2、使用$F()函数
$F()函数是另一个大收欢迎的“快捷键”,它能用于返回任何表单输入控件的值,比如text box,select。这个方法也能用元素id或元素本身做为参数。
<script>
function test3()
{
alert( $F('userName') );
}
</script>
<input type="text" id="userName" value="Joe Doe"><br>
<input type="button" value=Test3 οnclick="test3();"><br>
3、使用$A()函数
$A()函数能把它接收到的单个的参数转换成一个Array对象。
这个方法,结合被本类库扩展了的Array类,能方便的把任何的可枚举列表转换成或拷贝到一
个Array对象。一个推荐的用法就是把DOM Node Lists转换成一个普通的Array对象,从
而更有效率的进行遍历,请看下面的例子。
<script>
function showOptions()
{
var someNodeList = $('lstEmployees').getElementsByTagName('option');
var nodes = $A(someNodeList);
nodes.each(function(node){
alert(node.nodeName + ': ' + node.innerHTML);
});
}
</script>
<select id="lstEmployees" size="10">
<option value="5">Buchanan, Steven</option>
<option value="8">Callahan, Laura</option>
<option value="1">Davolio, Nancy</option>
</select>
<input type="button" value="Show the options" οnclick="showOptions();" >
4、使用 $H() 函数
$H()函数把一些对象转换成一个可枚举的和联合数组;类似的Hash对象。
<script>
function testHash()
{
//let's create the object
var a =
{
first: 10,
second: 20,
third: 30
};
//now transform it into a hash
var h = $H(a);
alert(h.toQueryString()); //displays: first=10&second=20&third=30
}
</script>
5、使用$R()函数
$R()是new ObjectRange(lowBound,upperBound,excludeBounds)的缩写。
跳到ObjectRange 类文档可以看到一个关于此类的完整描述. 此时,我们还是先来看一个例子以展示这个缩写能代替哪些方法吧。其它相关的一些知识可以在Enumerable 对象文档中找到。
<script>
function demoDollar_R(){
var range = $R(10, 20, false);
range.each(function(value, index){
alert(value);
});
}
</script>
<input type="button" value="Sample Count" οnclick="demoDollar_R();" >
使
6、使用Try.these()函数
Try.these() 方法使得实现当你想调用不同的方法直到其中的一个成功这种需求变得
非常容易, 他把一系列的方法(函数)作为参数并且按顺序的一个一个的执行这些方法直到其中的一个成功执行,不在向下执行其他的函数,返回成功执行的那个方法的返回值。
在下面的例子中,new ActiveXObject("Microsoft.XMLHTTP")在一些浏览器中好用,但
是new XMLHttpRequest()”在另一些浏览器中正常工作。 使用Try.these()方法我们可以得到
正常工作的那个方法的返回值。
<script type="text/javascript">
function getxhr()
{
return Try.these(f1,f2);
}
var f1=function()
{
alert("fun1");
return new ActiveXObject("Microsoft.XMLHTTP");
};
var f2=function()
{
alert("fun2");
return new XMLHttpRequest();
};
</script>注意:给Try.these()传递的是函数的引用,而不能调用函数。
二、Ajax包中的类
上面提到的通用的方法非常好,但是面对它吧,它们不是最高级的那类应用。它们是吗?你很可能自己编写了这些甚至在你的脚本里面有类似功能的方法。
对prototype.js感兴趣的原因很可能是由于它的AJAX能力。所以让我们解释当你需要完成AJAX逻辑的时候,这个包如何让它更容易。
Ajax包中的对象是预定义的对象,由这个包创建,为了封装和简化编写AJAX 功能涉及的代码。 这个包对象包含一系列的封装AJAX逻辑的类。我们来看看其中几个类。
1、使用Ajax.Request类
如果你不使用任何的帮助程序包,你很可能编写了整个大量的代码来创建XMLHttpRequest对象并且异步的跟踪它的进程,然后解析出响应,然后处理它。当你不需要支持多于一种类型的浏览器时你会感到非常的幸运。
为了支持 AJAX 功能。这个包定义了 Ajax.Request 类。
假如你有一个应用程序可以通过url http://192.168.9.66/app/get_sales?empID=1234&year=1998与服务器通信。服务器端返回数据响应。
用 Ajax.Request对象和服务器通信并且得到数据是非常简单的。下面的例子演示了它是如何完成的。
服务器端代码:
package org.wllt.www.prototype;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SearchEmployee extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html");
//PrintWriter out = response.getWriter();
PrintWriter out =null;
String empid=request.getParameter("empID");
String joindate=request.getParameter("year");
System.out.println(empid+"---"+joindate);
try{
Thread.sleep(6000);
}catch(Exception e){
e.printStackTrace();
}
out.println(empid+"---"+joindate);
}
}
Js代码:
<html>
<head>
<title>searchEmp.html</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="./js/prototype.js"></script>
<script>
function searchSales()
{
var empID = $F('lstEmployees');
var y = $F('lstYears');
var url = ' http://192.168.2.66/PrototypePrj/SearchEmployee';
var pars = 'empID='+empID+'&year='+y;
var myAjax = new Ajax.Request(
url,{
method:'get',
parameters:pars,
contentType:'application/x-www-form-urlencoded',
encoding:'UTF-8',
onCreate:function(){
alert("XMLHttpRequest创建!");
},
onComplete:function(v){
alert("服务器端响应完成"+v.status);
},//是回调函数
onSuccess:showResponse,//showResponse是回调函数。当服务器完成响应,把响应值作为参数传给回调函数
onFailure:function(v){
alert("服务器异常!"+v.status);
},
asynchronous:false
});
alert("在和服务器交互之后的代码!");
}
function showResponse(originalRequest)
{
//put returned Data in the textarea
$('result').value = originalRequest.responseText;
}
</script>
</head>
<body>
<select id="lstEmployees" size="10" onchange="searchSales()">
<option value="5">Buchanan, Steven</option>
<option value="8">Callahan, Laura</option>
<option value="1">Davolio, Nancy</option>
</select>
<select id="lstYears" size="3" onchange="searchSales()">
<option selected value="1996">1996</option>
<option value="1997">1997</option>
<option value="1998">1998</option>
</select>
<br><textarea id=result cols=60 rows=10></textarea>
</body>
</html>
你注意到传入 Ajax.Request构造方法的第二个对象了吗?参数{method: 'get', parameters: pars, onComplete: showResponse} 表示一个匿名JSON格式的js对象的真实写法。 它表示你传入的这个对象有一个名为 method 属性值为 'get',另一个属性名为 parameters 包含HTTP请求的查询字符串,和一个onComplete 属性指定了当readystate在某个状态下要调用函数showResponse。
还有一些其它的属性可以在这个对象里面定义和设置,如 asynchronous,可以为true 或 false 来决定AJAX对服务器的调用是否是异步的(默认值是 true)。
这个参数定义AJAX调用的选项。在我们的例子中,在第一个参数通过HTTP GET命令请求那个url,传入了变量 pars包含的查询字符串, onComplete表示Ajax.Request 对象在它完成接收响应的时候将调用showResponse 方法(回调函数)。
XMLHttpRequest在HTTP请求期间将报告进度情况。这个进度被描述为五个不同阶段:Create、 Loading, Loaded, Interactive, 或 Complete。你可以使 Ajax.Request 对象在任何阶段调用自定义方法,Complete 是最常用的一个。想调用自定义的方法只需要简单的在请求的选项参数中为名onXXXXX 属性提供自定义的方法对象。 就像我们例子中的 onComplete 。你传入的方法将会被用一个参数调用,这个参数是 XMLHttpRequest 对象自己。你将会用这个对象去得到返回的数据并且或许检查包含有在这次调用中的HTTP结果代码的 status 属性的值。
还有另外两个有用的选项用来处理结果。我们可以在onSuccess 选项处传入一个方法,当AJAX无误的执行完后调用, 相反的,也可以在onFailure选项处传入一个方法,当服务器端出现错误时调用。正如onXXXXX 选项传入的方法一样,(onSuccess和onFailure后面的方法)这两个方法在被调用的时候也传入一个带有AJAX请求的XMLHttpRequest对象作为参数。
该例子没有用任何有趣的方式处理这个数据响应, 我们只是把响应的数据放进了一个文本域里面。对这个响应的一个典型的应用很可能就是找到其中的想要的信息,然后更新页面中的某些元素。
Ajax.Responders类
这个对象维持一个在Ajax 相关事件发生时将被调用的对象的列表。比如,你要设置一个全局钩子来处理 Ajax 操作异常,那么你就可以使用这个对象。
在1.4.0版本中,一种新的事件回传处理被引入。如果你有一段代码总是要为一个特殊的事件执行,而不管是哪个AJAX调用引发它,那么你可以使用新的Ajax.Responders对象。
假设你想要在一个AJAX调用正在运行时,显示一些提示效果,像一个不断转动的图标之类的,你可以使用两个全局事件Handler来做到,其中一个在第一个调用开始时显示图标,另一个在最后一个调用完成时隐藏图标。看下面的例子。
<script>
var myGlobalHandlers ={
onCreate: function()
{
Element.show('systemWorking');
},
onComplete: function()
{
if(Ajax.activeRequestCount == 0)
{
Element.hide('systemWorking');
}
}
};
Ajax.Responders.register(myGlobalHandlers);
</script>
<div id='systemWorking'><img src='./imgs/loading.gif'>Loading...</div>
2、使用Ajax.Updater类
如果你的服务器的端返回的信息已经是HTML了,那么使用这个程序包中 Ajax.Updater 类将使Ajax的开发变得更加容易。使用Updater只需提供页面的哪一个元素需要被AJAX请求返回的HTML填充(更新)就可以了。
案例:
(1)服务器端
package org.wllt.www.actions;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet
{
public TestServlet()
{
}
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=GBK");
System.out.println(request.getParameter("someParameter"));
PrintWriter out = response.getWriter();
out.print("<div style='background:000066;color:FFFFFF'>未来蓝图提示今天:"+new Date()+"</div>");
out.flush();
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
this.doPost(request, response);
}
}
(2)客户端
<script>
function getHTML()
{
var url = 'http://192.168.5.66:8000/test/TestServlet';
var pars = 'someParameter=wllt';
//Updater构造方法
varmyAjax=new Ajax.Updater(
'placeholder',
url,{
method: 'post',
parameters: pars}
);
}
</script>
<input type=button value=GetHtml οnclick="getHTML()">
<div id="placeholder"></div>
你可以看到,这段代码比前面的例子更加简洁,不包括 onComplete 方法,但是在构造方法中传入了一个元素id。 我们来稍稍修改一下代码来描述如何在客户端处理服务器端错误成为可能。
响应脚本执行
如果你的服务器逻辑响应的文本中既包含HTML 标记也包含JavaScript 代码, Ajax.Updater对象可以执行那段JavaScript代码。为了使这个对象对响应的文本为JavaScript执行,你只需在最后参数的对象构造方法中简单加入evalScripts: true属性。但是值得提醒的是,像这个选项名evalScripts暗示的,这些脚本会被执行,但是它们不会被加入到页面的脚本中。我们假定请求地址返回的内容中有这样的脚本和其它代码:
<script language="javascript" type="text/javascript">
function sayHi()
{
alert('Hi');
}
</script>
<input type=button value="Click Me" οnclick="sayHi()">
当你点击按钮的时候,会实现相应的功能; 但是如果上面的代码是服务器端相应的内容,那么这些脚本不会如你所期望的那样工作,原因是这段脚本会被执行,但像上面这样的脚本执行并不会创建一个名叫sayHi的函数,它什么也不做。如果要创建一个函数,我们应当把代码改成下面这个样子:
<script language="javascript" type="text/javascript">
sayHi=function(){
alert('Hi');
};
</script>
<input type=button value="Click Me" οnclick="sayHi()">
为什么我们在上面的代码中不使用var关键字来声明这个变量呢(指sayHi),因为那样做创建出来的函数将只是当前脚本块的一个局部变量(至少在IE中是这样)。不写var关键字,创建出来的对象的作用域就是我们所期望的window(整个网页)。
上面的应用代码如下:
(1) 服务器端
package org.wllt.www.actions;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet
{
public TestServlet()
{
}
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
{
response.setContentType("text/html;charset=GBK");
System.out.println(request.getParameter("someParameter"));
PrintWriter out =response.getWriter();
out.println("<script language=/"javascript/" type=/"text/javascript/">");
out.println("sayHi=function(){");
out.println("alert('Hi');");
out.print("}");
out.println("</script>");
out.println("<input type=button value=/"Click Me/" οnclick=/"sayHi()/">");
out.flush();
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
}
(2)客户端
<script>
function getHTML()
{
var url = 'http://192.168.5.66:8000/test/TestServlet';
var pars = 'someParameter=ABC';
var myAjax = new Ajax.Updater(
{success:'placeholder'},
url,{
method:'get',
parameters:pars,
onFailure:reportError,
evalScripts:true
});
}
function reportError(request)
{
alert('Sorry. There was an error.');
}
</script>
<input type=button value=GetHtml onclick="getHTML()">
<div id="placeholder" onclick="alert(this.outerHTML);">原来的内容</div>
三、Enumeration枚举(Iterator)
1、each(function(元素,[下标]){…})
建一个Array,用elements组织它们,再建一个循环结构(例如for,foreach,while)通过index数字来访问每一个element,再用这个element做一些动作。
当你想到这时,你会发现几乎每次写循环代码你都会迟早用到一个Array。那么,如果Array对象能够提供更多的功能给它们的迭代器使用不是很爽吗?确实是这样,事实上很多的编程语言都在它们的Array或其它类似的结构中(如Collections,Lists)提供一些这样的功能。
现在好了,prototype.js了给我们一个 Enumerable对象,它实现了很多和可迭代数据进行交互的窍门。和原有的JS对象相比prototype.js更上一层楼,它对Array 类s扩展了所有枚举要用的函数。
在标准的javascript中,如果你想把一个array中的所有elements显示出来,你可以像下面代码这样写得很好:
<script>
function showList(){
var simpsons = ['Homer', 'Marge', 'Lisa', 'Bart', 'Meg'];
for(i=0;i<simpsons.length;i++)
{
alert(simpsons[i]);
}
}
</script>
<input type="button" value="Show List" οnclick="showList();" >
如果改写成prototype.js,我们可以把它生写成这样
<script language="javascript" type="text/javascript">
function showList()
{
var simpsons = ['Homer', 'Marge', 'Lisa', 'Bart', 'Meg'];
simpsons.each(function(familyMember,i){
alert(familyMember+"---"+i);
});
}
showList();
</script>
一个参数传递给each函数,each把它理解成迭代器函数。
就如我们上面提到的,把你的Array中的elements当成相同的类型使用相同的属性和函数是很通用(Common,不知该翻译成通用还是庸俗)的。让我们看看怎么样利用我们新的马力强劲的Arrays的迭代功能吧。
依照标准找到一个element。
<script>
function findEmployeeById(emp_id){
var listBox = $('lstEmployees')
var options = listBox.getElementsByTagName('option');
options = $A(options);
var opt = options.find( function(employee){
return (employee.value == emp_id);
});
alert(opt.innerHTML); //displays the employee name
}
</script>
<select id="lstEmployees" size="10" >
<option value="5">Buchanan, Steven</option>
<option value="8">Callahan, Laura</option>
<option value="1">Davolio, Nancy</option>
</select>
<input type="button" value="Find Laura" οnclick="findEmployeeById(8);" >
现在我们再下一城,看看如何过滤一个Array中的元素,从每个元素中得到我们想要的成员。
<script>
function showLocalLinks(paragraph){
paragraph = $(paragraph);
var links = $A(paragraph.getElementsByTagName('a'));
//find links that do not start with 'http'
var localLinks = links.findAll( function(link){
var start = link.href.substring(0,4);
return start !='http';
});
//now the link texts
var texts = localLinks.pluck('innerHTML');
//get them in a single string
var result = texts.inspect();
alert(result);
}
</script>
<p id="someText">
This <a href="http://othersite.com/page.html">text</a> has
a <a href="#localAnchor">lot</a> of
<a href="#otherAnchor">links</a>. Some are
<a href="http://wherever.com/page.html">external</a>
and some are <a href="#someAnchor">local</a>
</p>
<input type=button value="Find Local Links" οnclick="showLocalLinks('someText')">
上面的代码仅仅是一点小小的实现,就体现这种语法的强大。
异常处理:
我们将加入更多的选项, 指定处理错误的一个方法。这个是用 onFailure 选项来完成的。我们也指定了一个 placeholder 只有在成功请求之后才会被填充(更新)。为了完成这个目的我们修改了第一个参数从一个简单的元素id到一个带有两个属性的Json对象, success (一切OK的时候被用到) 和 failure (服务器端有地方出问题比如异常等的时候被用到) 在下面的例子中没有用到failure属性,而仅仅在 onFailure 处使用了 reportError 方法。
<script>
function getHTML()
{
var url = 'http://192.168.5.66:8000/test/TestServlet';
var pars = 'someParameter=ABC';
var myAjax = new Ajax.Updater(
{success: 'placeholder'},
url,{
method: 'get',
parameters: pars,
onFailure: reportError
});
}
//在调用该函数的时候把XMLHttpRequest作为参数传递
function reportError(request)
{
alert('Sorry. There was an error.');
}
</script>
<input type=button value=GetHtml οnclick="getHTML()">
<div id="placeholder"></div>
四、Form包中的类
(1)、Form.serialize(参数)
参数:参数为form的ID
功能:将Form中所有Input对象的值转化为一个URL String,方便把Form转为用 URL Get方式
(2)、Form.Element.serialize(表单域)
参数:参数为输入框的ID
功能: Input对象的值转化为一个URL String,方便把Form转为用 URL Get方式
五、Element中的API
(1)、Element.show(id)
把元素显示 参数是元素id
(2)、Element.hidden(id)
把元素隐藏 参数是元素id
(3)、Element.remove (id)
把元素删除 参数是元素id
(4)、Element.replace(id,替换的html或元素的HTML);
比如Element.replace("myDiv2",'<img src="./images/1.jpg">');
把元素替换 参数是元素被替换的id 第二参数是替换的html或元素的HTML