/*PrototypeJavaScriptframework,version1.4.0
*(c)2005SamStephenson<sam@conio.net>
*
*PrototypeisfreelydistributableunderthetermsofanMIT-stylelicense.
*Fordetails,seethePrototypewebsite:http://prototype.conio.net/
*这是一个JavaScript的框架,致力于简化动态的Web开发,完全按照面对对象的思想
*进行Javascript开发,添加了迭代器的概念增强Javascript的设计能力。
*Prototype框架构思独特充满了技巧性的代码,方便易用的工具类!
*
/*--------------------------------------------------------------------------*/
/*【Prototype】定义一个全局对象,提供一个全局的基本信息和工具*/
varPrototype={
Version:'1.4.0',//可以作为版本检测用
//用于脚本检测的正则表达式,经常使用所以放在这里起到全局常量的作用
ScriptFragment:'(?:<script.*?>)((/n|/r|.)*?)(?:<//script>)',
emptyFunction:function(){},//空函数
K:function(x){returnx}//K方法返回参数本身,在后面经常用到
}
/*========================================================================================*/
/*
*【Class】对象的作用只有一个就是提供了一个定义类的模式
*仅含有create一个方法,返回一个构造函数。
*一般使用如下
*varX=Class.create();返回一个类型
*要使用X类型,需继续用newX()来获取一个实例这与C#JAVA类似
*返回的构造函数会执行名为initialize的方法,initialize是Ruby对象的构造器方法名字。
*此时initialize方法还没有定义,其后的代码中创建新类型时会建立相应的同名方法,可以看作是一个抽象方法。
*从C#角度讲可以理解为用Class.create()创建一个继承Object基类的类。
*
*/
varClass={
create:function(){
returnfunction(){//下面使用Apply方法传递参数是一个常用的技巧
this.initialize.apply(this,arguments);
}
}
}
/*========================================================================================*/
//Abstract是一个空对象,它的作用仅仅是作为一个抽象的命名空间,所有在该对象下定义的类都是抽象类
//从而从形式上与实体类分开
varAbstract=newObject();
/*
*Object是所有对象的基类,这个基类有两个静态方法
*/
//把Source的所有属性和方法传递给Destination,实现了继承的效果
Object.extend=function(destination,source){
for(propertyinsource){
destination[property]=source[property];
}
returndestination;
}
//观察Object的组成,需要参数中的object实现自己的inspect方法
Object.inspect=function(object){
try{
if(object==undefined)return'undefined';
if(object==null)return'null';
returnobject.inspect?object.inspect():object.toString();
}catch(e){
if(einstanceofRangeError)return'';
throwe;
}
}
/*========================================================================================*/
//【Function】是所有函数对象的基类,可以通过对它的扩展实现对所有函数对象添加功能
/*这里在绑定的时候旧可以传递参数而不是调用的时候才指定参数,bind方法接收多个参数
将函数绑定到第一个参数指定的对象上,并返回该方法的调用句柄
*/
Function.prototype.bind=function(){
//$A()方法的作用是把参数专为数组
//数组的shift方法作用是删除数组的第一个元素
var__method=this,args=$A(arguments),object=args.shift();
returnfunction(){
return__method.apply(object,args.concat($A(arguments)));
//这里的$A(arguments)是条用返回函数句柄时传递的参数,不是bind方法的参数
}
}
/**
*和bind一样,不过这个方法一般用做html控件对象的事件处理。所以要传递event对象
*好像是重载了_method方法
*/
Function.prototype.bindAsEventListener=function(object){
var__method=this;
returnfunction(event){
return__method.call(object,event||window.event);
}
}
/*========================================================================================*/
//【Function】是所有数值类型的基类
Object.extend(Number.prototype,{
toColorPart:function(){//RGB-》16进制颜色
vardigits=this.toString(16);
if(this<16)return'0'+digits;
returndigits;
},
succ:function(){//数值加一vara=1;varb=a.succ;那么b=2
returnthis+1;
},
times:function(iterator){
//这里的参数iterator是一个迭代器作用就是循环调用指定次数的iterator函数
//$R(start,end,exclusive)是创建ObjectRnge对象的快捷方式
$R(0,this,true).each(iterator);
returnthis;
}
});
/*========================================================================================*/
//提供了一个方法these,要求参数是函数的句柄,可以有多个。作用就是返回第一个成功执行的函数的返回值
varTry={
these:function(){
varreturnValue;
for(vari=0;i<arguments.length;i++){
varlambda=arguments[i];
try{
returnValue=lambda();
break;
}catch(e){}
}
returnreturnValue;
}
}
/*========================================================================================*/
//定时器类用来实现Window.setInterval的效果,在给定时间间隔执行某一个函数,增加了对重复执行的控制S
varPeriodicalExecuter=Class.create();
PeriodicalExecuter.prototype={
initialize:function(callback,frequency){
//构造函数指定回调函数和执行频率,单位是秒
this.callback=callback;
this.frequency=frequency;
this.currentlyExecuting=false;
this.registerCallback();
},
/*开始调用定时器,无需显示调用,在构造函数中就实现了自动调用,这一下面的
this.onTimerEvent.bind(this)如果写成this.onTimerEvent则this指针就会指向widows对象即setInterval的默认对象
从而不能正确的引用到下面两个函数上,也就失去了对正在执行函数的控制
*/
registerCallback:function(){
setInterval(this.onTimerEvent.bind(this),this.frequency*1000);
},
//下面的函数相当于是回调函数的一个代理,setInterval是到了指定的时间就会强制执行而这里
//加入了一个判断如果callback函数执行的时间超过了一个时间片,则阻止其被重复执行
onTimerEvent:function(){
if(!this.currentlyExecuting){
try{
this.currentlyExecuting=true;
this.callback();
}finally{
this.currentlyExecuting=false;
}
}
}
}
/*使用举例:
functionGetOnlineCount()
{//获得在线人数
}
newPeriodicalExecuter(GetOnlineCount,10)每10秒获取一次
*/
/*========================================================================================*/
/*框架核心内容--------【基础工具类】
/*========================================================================================*/
/*document.getElementById(id)获取一个指定ID的结点,是这个方法的快捷方式和扩展
可以指定多个参数返回一个对象数组。参数也不一定是ID也可以是对象本身的引用,例如
$('id')等价于$($('id'))
*/
function$(){
varelements=newArray();
for(vari=0;i<arguments.length;i++){
varelement=arguments[i];
if(typeofelement=='string')
element=document.getElementById(element);
if(arguments.length==1)
returnelement;
elements.push(element);
}
returnelements;
}
/*========================================================================================*/
//【String】类的扩展
//删除字符串中的HTML标记
Object.extend(String.prototype,{
stripTags:function(){
returnthis.replace(/<//?[^>]+>/gi,'');
},
//删除字符串中的脚本块
stripScripts:function(){
returnthis.replace(newRegExp(Prototype.ScriptFragment,'img'),'');
},
//提取字符串中的所有脚本块,作为数组返回,每一个脚本作为一个数组元素
extractScripts:function(){
varmatchAll=newRegExp(Prototype.ScriptFragment,'img');
varmatchOne=newRegExp(Prototype.ScriptFragment,'im');
return(this.match(matchAll)||[]).map(function(scriptTag){
return(scriptTag.match(matchOne)||['',''])[1];
});
},
//提取字符串中的脚本并执行
evalScripts:function(){
returnthis.extractScripts().map(eval);
},
//将字符串进行html编码例如"<"--》"<"
escapeHTML:function(){
vardiv=document.createElement('div');
vartext=document.createTextNode(this);
div.appendChild(text);
returndiv.innerHTML;
},
//对字符串进行html解码例如"<"--》"<"
unescapeHTML:function(){
vardiv=document.createElement('div');
div.innerHTML=this.stripTags();
returndiv.childNodes[0]?div.childNodes[0].nodeValue:'';
},
//将查询字符串格式的字符串转换为键值对数组
//例如vars="a=1&b=2&c=3";vars2=s.toQueryParams();s2为{a:1,b:2,c:3}
toQueryParams:function(){
varpairs=this.match(/^/??(.*)$/)[1].split('&');
returnpairs.inject({},function(params,pairString){
varpair=pairString.split('=');
params[pair[0]]=pair[1];
returnparams;
});
},
//字符串转换为字符数组"abc"-->['a','b','c']
toArray:function(){
returnthis.split('');
},
//连字符--》骆驼样式'good-man'-->'goodMan'
camelize:function(){
varoStringList=this.split('-');
if(oStringList.length==1)returnoStringList[0];
varcamelizedString=this.indexOf('-')==0
?oStringList[0].charAt(0).toUpperCase()+oStringList[0].substring(1)
:oStringList[0];
for(vari=1,len=oStringList.length;i<len;i++){
vars=oStringList[i];
camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);
}
returncamelizedString;
},
//得到字符串的组成结构
inspect:function(){
return"'"+this.replace('//','').replace("'",'///'')+"'";
}
});
//定义了一个等价的函数
String.prototype.parseQuery=String.prototype.toQueryParams;
/*========================================================================================*/
//【Enumerable】可枚举接口是整个1.4.0框架的核心工具,所有实现此接口的类必须要实现_each(iterator)方法
var$break=newObject();//首先定义了两个异常对象,用于进行迭代计算的控制
var$continue=newObject();
varEnumerable={
//用于对对象的每一个元素遍历执行iterator迭代器函数
each:function(iterator){
varindex=0;//可选参数表示元素在枚举对象的次序
try{
this._each(function(value){//value是枚举元素的值
try{
iterator(value,index++);
}catch(e){
if(e!=$continue)throwe;
}
});
}catch(e){
if(e!=$break)throwe;
}
},
//判断是否所有的枚举元素都能使iterator返回true
all:function(iterator){
varresult=true;
this.each(function(value,index){
result=result&&!!(iterator||Prototype.K)(value,index);
if(!result)throw$break;
});
returnresult;
},
//判断是否有枚举元素能使iterator返回true,有一个就是True
any:function(iterator){
varresult=true;
this.each(function(value,index){
if(result=!!(iterator||Prototype.K)(value,index))
throw$break;
});
returnresult;
},
//对所有的枚举元素执行iterator迭代器函数结果作为一个数组返回
collect:function(iterator){
varresults=[];
this.each(function(value,index){
results.push(iterator(value,index));
});
returnresults;
},
//第一个素能使iterator返回true的枚举元素的值,没有返回undefined
detect:function(iterator){
varresult;
this.each(function(value,index){
if(iterator(value,index)){
result=value;
throw$break;
}
});
returnresult;
},
//找到所有的能使iterator迭代器函数返回true的枚举元素作为一个数组返回
findAll:function(iterator){
varresults=[];
this.each(function(value,index){
if(iterator(value,index))
results.push(value);
});
returnresults;
},
//找到素有匹配pattern的枚举元素,结果作为数组返回,iterator可选,如果不指定旧返回素有匹配pattern的枚举元素
grep:function(pattern,iterator){//正则模式迭代器
varresults=[];
this.each(function(value,index){
varstringValue=value.toString();
if(stringValue.match(pattern))
results.push((iterator||Prototype.K)(value,index));
})
returnresults;
},
//判断枚举对象中是否含有参数Object指定的值
include:function(object){
varfound=false;
this.each(function(value){
if(value==object){
found=true;
throw$break;
}
});
returnfound;
},
//将memo作为iterator的第一个参数,枚举元素作为iterator的第二个参数,枚举元素的次序作为第三个
//参数每次迭代器的返回值将作为下一个iterator的memo参数,从而所有的迭代执行都通过memo联系起来了
inject:function(memo,iterator){
this.each(function(value,index){
memo=iterator(memo,value,index);
});
returnmemo;
},
//对所有的枚举元素执行method方法后面是要传递的参数
invoke:function(method){
varargs=$A(arguments).slice(1);
returnthis.collect(function(value){
returnvalue[method].apply(value,args);
});
},
//返回的最大的迭代器执行结果
max:function(iterator){
varresult;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value>=(result||value))
result=value;
});
returnresult;
},
//反之
min:function(iterator){
varresult;
this.each(function(value,index){
value=(iterator||Prototype.K)(value,index);
if(value<=(result||value))
result=value;
});
returnresult;
},
//返回两个数组一组能使iterator返回true另一组返回false
partition:function(iterator){
vartrues=[],falses=[];
this.each(function(value,index){
((iterator||Prototype.K)(value,index)?
trues:falses).push(value);
});
return[trues,falses];
},
//获取所有枚举元素的property属性值作为数组的返回
pluck:function(property){
varresults=[];
this.each(function(value,index){
results.push(value[property]);
});
returnresults;
},
//与findall相反
reject:function(iterator){
varresults=[];
this.each(function(value,index){
if(!iterator(value,index))
results.push(value);
});
returnresults;
},
//根据iterator的结果排序最小的在前面作为数组返回
sortBy:function(iterator){
returnthis.collect(function(value,index){
return{value:value,criteria:iterator(value,index)};
}).sort(function(left,right){
vara=left.criteria,b=right.criteria;
returna<b?-1:a>b?1:0;
}).pluck('value');
},
//枚举对象--》数组
toArray:function(){
returnthis.collect(Prototype.K);
},
//接收多个枚举对象参数,最后一个可以是迭代器用于阵列转换
zip:function(){
variterator=Prototype.K,args=$A(arguments);
if(typeofargs.last()=='function')
iterator=args.pop();
varcollections=[this].concat(args).map($A);
returnthis.map(function(value,index){
iterator(value=collections.pluck(index));
returnvalue;
});
},
//返回枚举对象的字符串描述
inspect:function(){
return'#<Enumerable:'+this.toArray().inspect()+'>';
}
}
//等价函数定义
Object.extend(Enumerable,{
map:Enumerable.collect,
find:Enumerable.detect,
select:Enumerable.findAll,
member:Enumerable.include,
entries:Enumerable.toArray
});
/*========================================================================================*/
//【Array】数组对象
//参数转换为数组,如果参数定义了toarray则直接调用,否则枚举获得数组
var$A=Array.from=function(iterable){
if(!iterable)return[];
if(iterable.toArray){
returniterable.toArray();
}else{
varresults=[];
for(vari=0;i<iterable.length;i++)
results.push(iterable[i]);
returnresults;
}
}
//数组对象继承了Enumerable接口
Object.extend(Array.prototype,Enumerable);
Array.prototype._reverse=Array.prototype.reverse;
Object.extend(Array.prototype,{
//实现了枚举接口方法,用于对数组内的元素执行迭代器
_each:function(iterator){
for(vari=0;i<this.length;i++)
iterator(this[i]);
},
//清空数组
clear:function(){
this.length=0;
returnthis;
},
//取得第一个元素
first:function(){
returnthis[0];
},
//取得最后一个元素
last:function(){
returnthis[this.length-1];
},
//删除数组元素中所有的nullundefined值作为新数组返回,原数组不受影响
compact:function(){
returnthis.select(function(value){
returnvalue!=undefined||value!=null;
});
},
//展开所有数组元素不再嵌套
flatten:function(){
returnthis.inject([],function(array,value){
returnarray.concat(value.constructor==Array?
value.flatten():[value]);
});
},
//数组中删除指定的元素,返回删除后的结果,原数组不受影响
without:function(){
varvalues=$A(arguments);
returnthis.select(function(value){
return!values.include(value);
});
},
//Value元素在数组中的索引值
indexOf:function(object){
for(vari=0;i<this.length;i++)
if(this[i]==object)returni;
return-1;
},
//反转数组
reverse:function(inline){
return(inline!==false?this:this.toArray())._reverse();
},
//删除数组中第一个元素并返回这个元素的值
shift:function(){
varresult=this[0];
for(vari=0;i<this.length-1;i++)
this[i]=this[i+1];
this.length--;
returnresult;
},
//得到数组的字符串描述例如arr=[1,2,3]----->"[1,2,3]"
inspect:function(){
return'['+this.map(Object.inspect).join(',')+']';
}
});
/*========================================================================================*/
//【Hash】哈希对象
varHash={
//实现枚举接口方法从而使Hash对象也是枚举对象
_each:function(iterator){
for(keyinthis){
varvalue=this[key];
if(typeofvalue=='function')continue;
varpair=[key,value];
pair.key=key;
pair.value=value;
iterator(pair);
}
},
//所有键数组
keys:function(){
returnthis.pluck('key');
},
//所有值数组
values:function(){
returnthis.pluck('value');
},
//合并哈希表,键相同就覆盖调用者
merge:function(hash){
return$H(hash).inject($H(this),function(mergedHash,pair){
mergedHash[pair.key]=pair.value;
returnmergedHash;
});
},
//键值对组成查询字符串的形式
toQueryString:function(){
returnthis.map(function(pair){
returnpair.map(encodeURIComponent).join('=');
}).join('&');
},
//获取Hash对象的字符串描述
inspect:function(){
return'#<Hash:{'+this.map(function(pair){
returnpair.map(Object.inspect).join(':');
}).join(',')+'}>';
}
}
/*哈希表不是类而是对象所以不能用new的方法创建,而是用$H()函数
这个方法吧一个对象转换为哈希对象,对象的属性名为key值为value
可枚举!!
*/
function$H(object){
varhash=Object.extend({},object||{});
Object.extend(hash,Enumerable);
Object.extend(hash,Hash);
returnhash;
}
/*========================================================================================*/
//【ObjectRange】用于进行指定次数的循环运算,同样继承于枚举接口并实现_each方法
//有了这个方法基本上Javascript里面就不用for循环了
ObjectRange=Class.create();
Object.extend(ObjectRange.prototype,Enumerable);
Object.extend(ObjectRange.prototype,{
//构造函数同事指定了3个参数的值
initialize:function(start,end,exclusive){
this.start=start;//其实索引
this.end=end;//结束索引
this.exclusive=exclusive;//表示是否包含结束索引
},
_each:function(iterator){
varvalue=this.start;
do{
iterator(value);
value=value.succ();
}while(this.include(value));
},
//重写枚举接口的include方法,判断改循环的索引是否包含参数value的指定的值
include:function(value){
if(value<this.start)
returnfalse;
if(this.exclusive)
returnvalue<this.end;
returnvalue<=this.end;
}
});
//使用$R()方法快速创建objectRange对象
var$R=function(start,end,exclusive){
returnnewObjectRange(start,end,exclusive);
}
/*========================================================================================*/
/*【Ajax模块】
/*========================================================================================*/
//【ajax对象】
varAjax={//创建浏览器兼容的XMLHttpRequest对象
getTransport:function(){
returnTry.these(
function(){returnnewActiveXObject('Msxml2.XMLHTTP')},
function(){returnnewActiveXObject('Microsoft.XMLHTTP')},
function(){returnnewXMLHttpRequest()}
)||false;
},
//当前激活的请求数目
activeRequestCount:0
}
//【Ajax.Responders对象】
Ajax.Responders={
responders:[],//表示所有响应处理代理
_each:function(iterator){
this.responders._each(iterator);
},
//注册一个响应代理
register:function(responderToAdd){
if(!this.include(responderToAdd))
this.responders.push(responderToAdd);
},
//删除一个响应代理
unregister:function(responderToRemove){
this.responders=this.responders.without(responderToRemove);
},
//分发一个回调函数,让所有半酣callback回调函数事件标识符的响应代理都被调用
//传递三个参数最后一个可选表示Json对象
dispatch:function(callback,request,transport,json){
this.each(function(responder){
if(responder[callback]&&typeofresponder[callback]=='function'){
try{
responder[callback].apply(responder,[request,transport,json]);
}catch(e){}
}
});
}
};
Object.extend(Ajax.Responders,Enumerable);
//统计当前活动请求的数目
Ajax.Responders.register({
//开始创建了一个请求
onCreate:function(){
Ajax.activeRequestCount++;
},
//请求结束
onComplete:function(){
Ajax.activeRequestCount--;
}
});
//【Ajax.Base类】进行服务器通信的基类
Ajax.Base=function(){};
Ajax.Base.prototype={
setOptions:function(options){
this.options={
method:'post',
asynchronous:true,
parameters:''
}
Object.extend(this.options,options||{});
},
responseIsSuccess:function(){
returnthis.transport.status==undefined
||this.transport.status==0
||(this.transport.status>=200&&this.transport.status<300);
},
responseIsFailure:function(){
return!this.responseIsSuccess();
}
}
//【Ajax.Request类】用于向服务器端发送请求,封装了XmlHttpRequest
Ajax.Request=Class.create();
Ajax.Request.Events=
['Uninitialized','Loading','Loaded','Interactive','Complete'];
Ajax.Request.prototype=Object.extend(newAjax.Base(),{
initialize:function(url,options){
this.transport=Ajax.getTransport();
this.setOptions(options);//使用基类方法设置
this.request(url);
},
//向指定url发送请求一般不会显示调用
request:function(url){
varparameters=this.options.parameters||'';
if(parameters.length>0)parameters+='&_=';
try{
this.url=url;
if(this.options.method=='get'&¶meters.length>0)
this.url+=(this.url.match(//?/)?'&':'?')+parameters;
Ajax.Responders.dispatch('onCreate',this,this.transport);
this.transport.open(this.options.method,this.url,
this.options.asynchronous);
if(this.options.asynchronous){
this.transport.onreadystatechange=this.onStateChange.bind(this);
setTimeout((function(){this.respondToReadyState(1)}).bind(this),10);
}
this.setRequestHeaders();
varbody=this.options.postBody?this.options.postBody:parameters;
this.transport.send(this.options.method=='post'?body:null);
}catch(e){
this.dispatchException(e);
}
},
//设置请求的Http头类内部使用一般无需显示调用
setRequestHeaders:function(){
varrequestHeaders=
['X-Requested-With','XMLHttpRequest',
'X-Prototype-Version',Prototype.Version];
if(this.options.method=='post'){
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
/*Force"Connection:close"forMozillabrowserstoworkaround
*abugwhereXMLHttpReqeuestsendsanincorrectContent-length
*header.SeeMozillaBugzilla#246651.
*/
if(this.transport.overrideMimeType)
requestHeaders.push('Connection','close');
}
if(this.options.requestHeaders)
requestHeaders.push.apply(requestHeaders,this.options.requestHeaders);
for(vari=0;i<requestHeaders.length;i+=2)
this.transport.setRequestHeader(requestHeaders[i],requestHeaders[i+1]);
},
//检测XMLHttpRquest对象的onstatechange事件类内部使用一般无需显示调用
onStateChange:function(){
varreadyState=this.transport.readyState;
if(readyState!=1)
this.respondToReadyState(this.transport.readyState);
},
//获取指定的Http头的内容
header:function(name){
try{
returnthis.transport.getResponseHeader(name);
}catch(e){}
},
//如果服务器返回了Http头"X-JOSN"则将其作为js执行并返回执行结果
evalJSON:function(){
try{
returneval(this.header('X-JSON'));
}catch(e){}
},
//将XMLHttpRequest返回的responseText作为JS语句执行并返回执行结果
evalResponse:function(){
try{
returneval(this.transport.responseText);
}catch(e){
this.dispatchException(e);
}
},
//处理XMLHttpRequest的readystate属性根据成功或失败调用Options对象中相应的回调函数
//同时通知Ajax.Responders中注册的响应处理句柄
respondToReadyState:function(readyState){
varevent=Ajax.Request.Events[readyState];
vartransport=this.transport,json=this.evalJSON();
if(event=='Complete'){
try{
(this.options['on'+this.transport.status]
||this.options['on'+(this.responseIsSuccess()?'Success':'Failure')]
||Prototype.emptyFunction)(transport,json);
}catch(e){
this.dispatchException(e);
}
if((this.header('Content-type')||'').match(/^text//javascript/i))
this.evalResponse();
}
try{
(this.options['on'+event]||Prototype.emptyFunction)(transport,json);
Ajax.Responders.dispatch('on'+event,this,transport,json);
}catch(e){
this.dispatchException(e);
}
/*AvoidmemoryleakinMSIE:cleanuptheoncompleteeventhandler*/
if(event=='Complete')
this.transport.onreadystatechange=Prototype.emptyFunction;
},
dispatchException:function(exception){
(this.options.onException||Prototype.emptyFunction)(this,exception);
Ajax.Responders.dispatch('onException',this,exception);
}
});
/*========================================================================================*/
//【Ajax.Updater类】用于将获取的内容填充到指定的容器中去
Ajax.Updater=Class.create();
Object.extend(Object.extend(Ajax.Updater.prototype,Ajax.Request.prototype),{
//重写了构造函数
initialize:function(container,url,options){
this.containers={
success:container.success?$(container.success):$(container),
failure:container.failure?$(container.failure):
(container.success?null:$(container))
}
this.transport=Ajax.getTransport();
this.setOptions(options);//可以指定evalscripts属性和insertion属性
varonComplete=this.options.onComplete||Prototype.emptyFunction;
this.options.onComplete=(function(transport,object){
this.updateContent();
onComplete(transport,object);
}).bind(this);
this.request(url);
},
updateContent:function(){
varreceiver=this.responseIsSuccess()?
this.containers.success:this.containers.failure;
varresponse=this.transport.responseText;
if(!this.options.evalScripts)
response=response.stripScripts();
if(receiver){
if(this.options.insertion){
newthis.options.insertion(receiver,response);
}else{
Element.update(receiver,response);
}
}
if(this.responseIsSuccess()){
if(this.onComplete)
setTimeout(this.onComplete.bind(this),10);
}
}
});
/*========================================================================================*/
//【Ajax.PeriodicalUpdater类】用于定时执行服务器异步调用,功能与Updater相同只是有了定时功能
Ajax.PeriodicalUpdater=Class.create();
Ajax.PeriodicalUpdater.prototype=Object.extend(newAjax.Base(),{
initialize:function(container,url,options){
this.setOptions(options);
this.onComplete=this.options.onComplete;
//区别就在下面两个属性频率衰减参数指数增长!只要有一次不同旧回复原有频率
this.frequency=(this.options.frequency||2);
this.decay=(this.options.decay||1);
this.updater={};
this.container=container;
this.url=url;
this.start();
},
start:function(){
this.options.onComplete=this.updateComplete.bind(this);
this.onTimerEvent();
},
stop:function(){
this.updater.onComplete=undefined;
clearTimeout(this.timer);
(this.onComplete||Prototype.emptyFunction).apply(this,arguments);
},
updateComplete:function(request){
if(this.options.decay){
this.decay=(request.responseText==this.lastText?
this.decay*this.options.decay:1);
this.lastText=request.responseText;
}
this.timer=setTimeout(this.onTimerEvent.bind(this),
this.decay*this.frequency*1000);
},
onTimerEvent:function(){
this.updater=newAjax.Updater(this.container,this.url,this.options);
}
});
/*========================================================================================*/
/*【文档操作的封装】
/*========================================================================================*/
//返回了一个数组包含了所有符合条件的结点的引用
document.getElementsByClassName=function(className,parentElement){//parentElement不指定就在全局查找
varchildren=($(parentElement)||document.body).getElementsByTagName('*');
return$A(children).inject([],function(elements,child){
if(child.className.match(newRegExp("(^|//s)"+className+"(//s|$)")))
elements.push(child);
returnelements;
});
}
/*【Element对象】用于对文档结点做一些统一的操作
*/
if(!window.Element){
varElement=newObject();
}
Object.extend(Element,{
visible:function(element){
return$(element).style.display!='none';
},
//指定结点可见性的切换
toggle:function(){
for(vari=0;i<arguments.length;i++){
varelement=$(arguments[i]);
Element[Element.visible(element)?'hide':'show'](element);
}
},
hide:function(){
for(vari=0;i<arguments.length;i++){
varelement=$(arguments[i]);
element.style.display='none';
}
},
show:function(){
for(vari=0;i<arguments.length;i++){
varelement=$(arguments[i]);
element.style.display='';
}
},
remove:function(element){
element=$(element);
element.parentNode.removeChild(element);
},
//将html片段填充到element指定的结点中
update:function(element,html){
$(element).innerHTML=html.stripScripts();
setTimeout(function(){html.evalScripts()},10);
},
//获得element的绝对高度
getHeight:function(element){
element=$(element);
returnelement.offsetHeight;
},
classNames:function(element){
returnnewElement.ClassNames(element);
},
hasClassName:function(element,className){
if(!(element=$(element)))return;
returnElement.classNames(element).include(className);
},
addClassName:function(element,className){
if(!(element=$(element)))return;
returnElement.classNames(element).add(className);
},
removeClassName:function(element,className){
if(!(element=$(element)))return;
returnElement.classNames(element).remove(className);
},
//removeswhitespace-onlytextnodechildren
cleanWhitespace:function(element){
element=$(element);
for(vari=0;i<element.childNodes.length;i++){
varnode=element.childNodes[i];
if(node.nodeType==3&&!//S/.test(node.nodeValue))
Element.remove(node);
}
},
empty:function(element){
return$(element).innerHTML.match(/^/s*$/);
},
//将浏览器的滚动条滚动到指定的结点的位置
scrollTo:function(element){
element=$(element);
varx=element.x?element.x:element.offsetLeft,
y=element.y?element.y:element.offsetTop;
window.scrollTo(x,y);
},
//得到element的结点的绝对样式
getStyle:function(element,style){
element=$(element);
varvalue=element.style[style.camelize()];
if(!value){
if(document.defaultView&&document.defaultView.getComputedStyle){
varcss=document.defaultView.getComputedStyle(element,null);
value=css?css.getPropertyValue(style):null;
}elseif(element.currentStyle){
value=element.currentStyle[style.camelize()];
}
}
if(window.opera&&['left','top','right','bottom'].include(style))
if(Element.getStyle(element,'position')=='static')value='auto';
returnvalue=='auto'?null:value;
},
//设置结点样式varstyle={background-color:'black',color:'red'}Element.setStyle($('div1'),style)
setStyle:function(element,style){
element=$(element);
for(nameinstyle)
element.style[name.camelize()]=style[name];
},
//获得结点的宽度高度该方法无论结点是否可见都能获得其大小
getDimensions:function(element){
element=$(element);
if(Element.getStyle(element,'display')!='none')
return{width:element.offsetWidth,height:element.offsetHeight};
//All*Widthand*Heightpropertiesgive0onelementswithdisplaynone,
//soenabletheelementtemporarily
varels=element.style;
varoriginalVisibility=els.visibility;
varoriginalPosition=els.position;
els.visibility='hidden';
els.position='absolute';
els.display='';
varoriginalWidth=element.clientWidth;
varoriginalHeight=element.clientHeight;
els.display='none';
els.position=originalPosition;
els.visibility=originalVisibility;
return{width:originalWidth,height:originalHeight};
},
//相对定位
makePositioned:function(element){
element=$(element);
varpos=Element.getStyle(element,'position');
if(pos=='static'||!pos){
element._madePositioned=true;
element.style.position='relative';
//Operareturnstheoffsetrelativetothepositioningcontext,whenan
//elementispositionrelativebuttopandlefthavenotbeendefined
if(window.opera){
element.style.top=0;
element.style.left=0;
}
}
},
//取消相对定位
undoPositioned:function(element){
element=$(element);
if(element._madePositioned){
element._madePositioned=undefined;
element.style.position=
element.style.top=
element.style.left=
element.style.bottom=
element.style.right='';
}
},
//使结点隐藏超出的部分overflow=relative
makeClipping:function(element){
element=$(element);
if(element._overflow)return;
element._overflow=element.style.overflow;
if((Element.getStyle(element,'overflow')||'visible')!='hidden')
element.style.overflow='hidden';
},
undoClipping:function(element){
element=$(element);
if(element._overflow)return;
element.style.overflow=element._overflow;
element._overflow=undefined;
}
});
prototype源码解读
最新推荐文章于 2025-06-10 22:38:01 发布