打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Prototype(1.5 rc2)使用指南

Prototype1.5 rc2)使用指南

资料来源于网上,种子张整理了一下而已.版权属于原作者.忘记他是谁了,就没有请出来,不好意思了,呵呵.

().序言

在写这个指南之前,先介绍一下Prototype主要是干吗的,如果你比较关注ajax/javascipt方面的应用,你应该早就听说过这个 javascript framework Prototype是一个基础的javascript应用框架,先引用一段官方网站的介绍

Prototype is a JavaScript framework that aims to ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype is quickly becoming the codebase of choice for web application developers everywhere.

根据作者自己的介绍,Prototype的目的是为了更方便的开发javascript的应用,使用它可以更加方便简单的使用javascript编程,开发出面向对象的javascript程序,Prototype中包含包含了一个功能强大好用的ajax框架,Prototype是一个基础性的框架,很多更高层次的框架都以它为基础,例如scriptaculous效果库

Prototype中包含一下几个部分:

base: Prototype中应用的基本功能,基本上其他所有部分都依赖于它,包括用于面向对象风格的Class.createObject.extend,一个Try对象,函数绑定,number扩展,PeriodicalExecuter(周期性执行某个函数的功能)

string: String原型的扩展,为string添加了strip,escapeHTML等等好用的方法

enumerable: 枚举类型(array, hash, range)的父类对象,提供枚举类型的共同方法

array: Array原型的扩展,为array添加了indexOfwithout等方法

hash: javascript提供了一个好用简单的Hash实现

range: 继承于enumerable,一个范围(例如367)对象

ajax: 一个功能强大好用的ajax框架

dom: 对基于浏览器的开发提供了很好的跨浏览器封装,并添加很多强大的功能

selector: 提供了使用classcss等选择元素的功能

form: 关于表单的一些功能

event: 简单的夸平台事件封装

position: 提供了一些关于元素位置方面的功能

可以说Prototype就想一把瑞士军刀,为javascipt封装了很多通用的功能,大大简化了javascript应用的开发,给javascript开发人员增添了很大的信心,Prototype可以运行于以下平台,使用它再也不用各种跨平台等问题烦恼了

* Microsoft Internet Explorer for Windows, version 6.0 and higher

* Mozilla Firefox 1.0/Mozilla 1.7 and higher

* Apple Safari 1.2 and higher

不过要注意的是:要想很好的理解Prototype,应该首先理解一下javascript面向对象开发的一些知识以后的文章将对Prototype中具体的每个功能中的方法做一个详细的介绍,包括作用,实例等Prototype官方网站是:http://prototype.conio.net/ ,目前发布版还只是1.4, 但是现在的1.5已经发生了很大的变化,而且很多基于prototype的库使用的都是1.5的,所以强烈建议通过svn下载最新版代码

 

().Prototype1.5 rc2)使用指南之base.js

base.js中包含下面的内容

类的创建与继承:

Class.create(): 创建一个类,例如 person=Class.create()

Object.extend(destination, source): source中方法属性copydestination(使用for property in source),需要注意的是,javascript中除了基本类型(Number, Boolean)外都是引用类型,所以这种copy一般只是copy引用而已,destinationsource还是指向同一个方法或对象属性 (function array object)

在面向对象的编程中,一般通过Class.create新建一个类,如果这个类继承于另一个类,一般使用Object.extend (class.prototype, parentClass.prototype)或者Object.extend(class.prototype, aparentClassInstance)

Object构造函数的扩展:

Object是其他对象实例的构造函数(var a=new Object()),也是所有其他类的父类,对Object直接扩展(注意不是扩展Object.prototype,扩展 Object.prototype相当于添加实例方法)相当于为Object类添加静态方法

Object.inspect(object): 调用objectinspect(如果定义了)toString方法,返回一个对象的字符串表示

Object.keys(object): 返回一个对象的所有属性和方法名称组成的数组, 例如Object.keys(document.body)

Object.values(object):返回一个对象的所有属性和方法的值组成的数组, 例如Object.values(docuement)

Object.clone(object): 返回一个对象的clone版本,其实是执行Object.extent方法把object中的方法属性copy到一个新对象中,然后返回这个对象

函数邦定:

定义了Function对象的两个方法,bindbindAsEventListener,这两个方法是一个函数的两个方法,对于javac#程序员来说,看到这个也许感到很惊讶,因为在他们看来函数只是一个程序语句组织结构而已—>怎么还有方法,而且还可以扩展?这也是javascript等脚本语言相对于java等一个非常强大的功能,函数也是一个对象,函数名就是这个对象的名称,只要你愿意,你也可以使用 new Function()来定义函数,所以为函数定义方法也就很正常不过了

这两个函数的主要作用是为了解决使用javascript面向对象风格编程中this的引用问题,在javasctiptthis关键字始终指向调用该函数的对象或者指向使用callapply方法指定的对象(具体这方面的知识可以自己google一下,以下系列对prototype的介绍也假设读者对javascript语言比较熟悉了,如果不熟悉可以找本javascript权威指南这本书看看) 要理解这个问题首先要理解 始终指向这个问题,就是this这个关键字比较特殊,不能把他当成一般的变量名看待,最常见的一个错误就是在返回函数的调用中使用this,例如return function(){this.aMethod()}, 当你下次调用这个返回的匿名方法时,这个this引用的内容又指向了调用这个函数的对象了,记住的一点的this是个关键字,不是变量名,不会产生闭包

Number的扩展(注意num也可以看成对象,其实是在使用的时候系统自动打包成Number对象)

toColorPart:把数字转换为可以用于表示color16进制值:例如 7.toColorPart()=>"07"28.toColorPart()=>"1C"

succ: 返回num++, 但不改变num本身的值,其实就是 return this1

times:对从0到这个数字轮流调用一个函数, 例如function a(n){docuement.write(n)}, 10.times(a), 将显示012345678910, 注意函数也是一个对象,而且与其他对象并没有实质的区别

Try对象: Try对象提供了一个很有趣的功能, 先看一下如下的代码:

var Ajax = { 

getTransport: function() {   

   return Try.these(     

              function() {return new XMLHttpRequest()},    

              function() {return new ActiveXObject(’Msxml2.XMLHTTP’)},     

             function() {return new ActiveXObject(’Microsoft.XMLHTTP’)}   )

     || false;

   }

Try对象提供了一个方法these, 这个方法接受一个函数类型的参数列表,然后轮流执行这些函数,当其中一个函数没有产生错误时,就停止执行,并且返回这个函数返回的值,自己慢慢体会吧

PeriodicalExecuter(周期性执行器)对象

这个对象是对setInterval方法的简单封装,使用方法如下

var a=new PeriodicalExecuter(callback, frequency ) ,其中callback指要执行的函数名 frequency 每次执行的时间间隔

要停止的话,调用这个对象的stop方法就可以了 a.stop() 

 

()Prototype1.5 rc2)使用指南之string.js

下面介绍PrototypeString对象的扩展部分:

这部分主要为string对象添加了几个很有用的方法:

strip(): 去掉字符串两边的空白, 例如"  jj  ".strip()返回"jj"

stripTags():去掉字符串中的html标签

stripScripts(): 去掉字符串中的javascript代码段

extractScripts(): 返回字符串中的javascript代码,返回数组

evalScripts(): 执行字符串中的javascript代码

escapeHTML():将字符串中的html代码转换为可以直接显示的格式, 例如将< 转化为 < ,在ie6中有bug,执行这个操作返回的字符串,将多个连在一起的空白变成了一个,所以很多换行什么的都被去掉了

unescapeHTML(): escapeHTML的反向过程

truncate(length, truncation): 截断,例如"abcdefghigkl".truncate(10)返回abcdefg, truncation默认为"" toQueryParams(separator)/parseQuery(separator):将一个querystring转化为一个hash表(其实是一个对象,在javascript中对象可以当成hash表来用,因为对象的属性或方法可以通过object[propertyName]来访问)

toArray(): return this.split(‘), 转化为一个字符数组

camelize(): background-color的形式转化为backgroundColor形式,用在style/css

capitalize(): 返回一个首字母大写的字符串

inspect(useDoubleQuotes): 返回字符串的表示形式, 例如"sdfj\"sfa".inspect() 返回 “’sdfj"sfa’”

gsub(pattern, replacement)pattern是一个正则表达式,replacement是一个函数(或者是一个template字符串),对于字符串中每个匹配pattern的部分使用replacement处理,然后将 replacement返回的值将原来匹配的部分替换掉,例如"skdjfAsfdjkAdk".gsub(/A/,function(match) {return match[0].toLowerCase()}), 将字符串所有的A转化为a, 注意pattern中不要添加g选项,因为gsub会递归的执行match方法

sub(pattern, replacement, count) gsub的另一种形式,不过可以设置执行的次数

scan(pattern, iterator): gsub差不多,但是返回的是字符串本身,也就是说对于pattern中的每个匹配执行iterator,但是不返回替换的字符串"skdjfAsfdjkAdk".gsub(/A/,function(){alert have a A})

underscore(): ‘borderBottomWidth’.underscore()  -> ‘border_bottom_width’

dasherize(): ‘Hello_World’.dasherize()  -> ‘Hello-World’

Template模板类:

使用方法:

var template = new Template(replacement, pattern);               

template.evaluate(object) 有点像php中的模板,默认(没有提供pattern){propertyName}形式的东西替换了object的属性值

().Prototype1.5 rc2)使用指南之Enumerable.js

Enumerable是一个抽象对象(需要说明的是,javascript中并没有类的概念,所指的类也就是一个函数,继承一般指的是一个对象()将它的方法属性copy(通过Object.extend, copy的是引用)到子类(函数)prototype属性(一个对象)中)

Enumerable不能直接使用,它被很多枚举类型(HashArrayRange等)所继承,继承的类型都要实现一个_each方法,提供具体类型的枚举方法

Enumerable为其他子类提供了如下的方法:

each(iterator): iterator是一个函数对象, 这个方法调用具体类型的_each方法对自身包含的每个对象调用iterator,例如如果Enumerable具体指的是一个Arrayeg: var a=[2,3,4], a.each(iterator)方法将依次调用iterator(2,0) ,iterator(3,1), iterator(4,3),其中第二个参数指的是索引。这个方法几乎在Enumerable中的每个方法中都要用到

eachSlice(number, iterator):将Enumerable 类型对象每个每个按照number分开,例如[1,2,3,4,5].eachSlice(3)=>[[1,2,3],[4,5]], 没有提供iterator, iterator=Prototype.K: function(k){return k}Prototype中的很多iterator默认值都是这个,或者是Prototype.emptyFunction: function() {},其实实际上返回的是[iterator([1,2,3]),iterator([4,5])]

all(iterator): Enumerable类型中的每个值调用iterator,如果其中有一个返回false,则返回false,否则返回true,相当于判断是否每个值执行iterator都是"true"

any(iterator): all相反,判断是否每个值都是"false"(是否有一个值是true

collect(iterator)/map: 对每个值调用iterator,将结果组成一个新的数组返回

detect(iterator)/find: 对每个值调用iterator,如果有一个不为false,则返回这个执行iterator后不为false的值(不是返回执行iterator后的值),相当于找出第一个真值

findAll(iterator)/select: 相当于detect, 但是找出所有的真值,返回一个数组

grep(pattern, iterator):返回所以符合pattern的值,iterator提供的话,则返回执行iterator的值

include(object)/member: 数组中是否包含object

inGroupsOf(number, fillWith): eachSlice的变异版本,按照number将对象分开,如果分开后的数组的最后一个值的length小于number, 则用fillwith填充, 例如[1,2,3,4,5].inGroupsOf(3)=>[[1,2,3],[4,5,null]]

inject(memo, iterator): 注入

invoke(method): 调用

max(iterator): 最大值

min(iterator): 最小值

partition(iterator): 分离

pluck(property): 采集

reject(iterator): 不合格的产品, findAll相反

sortBy(iterator): 根据iterator排序,如果调用的对象是Array的话,直接调用内置的sort(iterator)就行了

toArray()/entries: 将调用对象的每个值组成一个数组返回

zip(): 例如[2,3,4].zip([5,6,7])=>[[2,5],[3,6],[4,7]], 如果最后一个参数类型为function,将返回[iterator([2,5]),iterator([3,6]),iterator([4,7])],

inspect(): Enumerable对象的字符串表示

().Prototype1.5 rc2)使用指南之array.js

$A = Array.from(iterable): iterable转化为数组,如果iterable定义了toArray方法,就调用这个方法,否则利用iterablelength属性进行枚举, 如果iterable没有length属性的话就返回空数组[]

Array对象除了扩展Enumerable对象的方法外,另外扩展了如下的几个方法,

注意以下方法除了clear外都不改变原来数组,而是返回一个新数组:

clear(): 清除数组,利用arr.length=0

first(): 返回第一个元素

last():返回最后一个元素

compact(): 去除数组中值为nullundefined的元素

flatten(): 将数组扁平化,例如[3,4,[6,7]]变为[3,4,6,7]

without(): 去除指定的元素, 可以指定多个值, 例如[4,56,7,8].without(4,7) 返回[568]

indexOf(object): 返回指定的元素在数组中的索引,不包含则返回-1

reverse(inline)Array内置函数reverse的增强,当inlinetrue时,跟内置的reverse函数效果一样,改变原数组的值,否则不改变原来的值

reduce(): 如果数组只有一个元素,则返回这个元素,否则返回数组本身

uniq(): 返回没有重复元素的数组

clone(): 返回一个跟数组相同的数组,Array中的toArray方法覆盖了Enumerable中的toArray方法,指向了这个方法

inspect(): 跟数组的toString方法类似,返回对象的字符串表示,例如[2,3].inspect() 返回 "[2,3]"

().Prototype1.5 rc2)使用指南之hash.js

Hash对象(关联数组)Prototype新建的一个对象,要创建一个Hash对象可以调用$H(object)方法,使用这个方法将生成一个基于 object对象的Hash对象,生成的Hash对象将object的属性名作为key,将object的属性值最为键值,因为javascript本身的特点(对象本身就是关联数组) ,所以实现Hash也很简单,Prototype中的Hash只是javascript的关联数组(对象)而已

Prototype中的Hash对象继承自Enumerable对象,所以也具有Enumerable对象的所有属性和方法,另外它具有以下的方法:

keys(): 返回hash的键值数组

values(): 返回值得数组

merge(hash): 合并两个hash

toQueryString(): stringtoQueryParams方法想法,将hash转化为一个querystring, 会调用encodeURIComponent对键和值进行编码

inspect(): hash的字符串表示

因为hash只是javascript的一个普通的对象而已,所以添加一个键值对使用: hash[key]=value就可以了,删除一个键值对使用 detele hash[key]就可以了

().Prototype1.5 rc2)使用指南之range.js

Range对象是一个继承自Enumerable"范围"对象,你可以把它看成[x,x+1,x+2,x+3……x+n]的数组看待,但是比这样的数组更节省存储空间,因为range对象只是保存xx+n而已

要创建一个Range对象调用$R(start, end, exclusive) 函数就可以了,exclusive指定是否包含end本身,如果没有指定或为false则包含end,否则不包含,你可以利用Enumerable中定义的方法来操作range对象,range对象只是实现了Enumerable对象需要的枚举逻辑_each和覆盖了include方法而已

().Prototype1.5 rc2)使用指南之ajax

Prototype中的ajax.js提供了一个非常好用的ajax框架,一般应用中简单的调用以下代码就可以了

new Ajax.Request(

    url, {method: “get”,

    onSuccess: showFilter,

    onFailure: function(request){alert(”Server error!”)},

    onException: showError}

  );

这个框架中提供了如下的对象和方法等:

Ajax对象:

只有一个getTransport方法,返回一个XMLHttpRequest对象,另外有一个activeRequestCount属性,反映当前正在处理的ajax数量

Ajax.Responders对象:

继承自Enumerable,管理全局Ajax的请求,具有如下方法

register(responder):注册一个管理ajax请求的对象

unregister(responder):撤销一个管理ajax请求的对象

dispatch(callback, request, transport, json):触发注册的处理对象的方法

这个对象一般很少使用,系统中已经使用如下的代码注册了一个处理对象

Ajax.Responders.register({

  onCreate: function() {

    Ajax.activeRequestCount++;

  },

  onComplete: function() {

    Ajax.activeRequestCount–;

  }

});

Ajax.Base类:

Ajax的基类, 只有一个方法setOptions(options), 默认request参数如下,你可以在新建Ajax.request时指定:

method:       ‘post’,

asynchronous: true,

contentType:  ‘application/x-www-form-urlencoded’,

encoding:     UTF-8,

Ajax.Request类:

ajax主要的类,继承自ajax.base类,客户端使用 new Ajax.Request(url,options) 调用,options是一个对象(关联数组), options中可以指定methodasynchronouscontentTypeencodingparameters postBodyusername,password等选项,其中parameters可以是字符传或者关联数组象,

另外在options中还可以通过requestHeaders指定request heads,其中requestHeaders可以是数组(例如[Connection,Close,aheadkey,aheadvalue])或一个关联数组;

options中最重要的选项就是指定ajax的回调方法,可以定义onComplete, onSuccess, onFailure, onException(执行过程中发生异常调用的方法,主要为onComplete, onSuccess, onFailure等回调方法产生的),甚至可以定义on404,on503这样的回调方法,它们的参数为(transport, json),其中transport为请求的XMLHttpRequest对象, jsonevalJSON的结果

如果返回的是一个javascript文件(根据返回的Content-type头判断)将会执行evalResponse方法,另外Ajax.Request对象还有一个evalJSON方法,取得文件的时候就会执行

这个对象的方法列表如下:

request(url) : 发送请求,new的时候就已经调用了,所以一般不需要使用

success(): 判断request是否成功了

getHeader(name):根据name得到request head

evalJSON(): 执行getHeader(X-JSON),并返回结果

evalResponse(): 执行返回的responseText并返回

Ajax.Updater:

继承自Ajax.Request,只是比Ajax.Request增加了更新html元素的功能,一般使用方法是new Ajax.Updater(element, url, options), element可以是一个元素,也可以是{success:e1,failure:e2}这种形式,

默认情况下不会执行返回结果中的javascript,如果你先执行,你可以指定options中的evalScriptstrue

默认情况下是替换指定元素的内容,如果你希望是添加,可以指定optionsinsertion参数, insertion是一个Insertion.BeforeInsertion.TopInsertion.Bottom Insertion.After(将在dom.js中介绍)

Ajax.PeriodicalUpdater:

继承自Ajax.Base,周期性的更新一个html元素的内容,这个类会调用Ajax.Updaterhtml元素进行周期性的更新,使用方法为new Ajax.PeriodicalUpdater(container, url, options), 参数跟Ajax.Updater差不多,其中options可以设置frequency(默认为2)decaydecay指的是当请求的内容没有变化的时候,frequency需要延长的倍数,默认是1,例如如果decay设为2frequency设为3而内容一直没有变化,则请求的时间依次会变为 3,6,12,24

start(): 开始更新, 初始化的时候会自动调用

stop(): 停止更新

().Prototype1.5 rc2)使用指南之dom.js

这部分提供了很多(写的都有点烦了)方便的操作dom的方法:包含有名的$方法、document.getElementsByClassName方法,以及Element对象、Insertion对象

以下部分一个一个的详细介绍:

$(element)getElementById的封装,element可以是一个元素的id或元素本身,也可以是一个数组,这时返回一个数组,使用$方法,会自动调用Element.extend(element)方法,这样的话使元素可以直接调用 Element中的方法, 例如Element.hide(element)可以写成这样$(element).hide()

document.getElementsByClassName(className, parentElement): 根据class选择元素

Element.extend(element): 扩展element,使element可以直接调用ElementForm.ElementForm中定义的方法

Element对象的方法:

visible: function(element):判断element是否可见, 参数element可以是元素本身或元素id(下面的方面的参数基本上都是这样的)

toggle: function(element):反转element的可见性

hide: function(element):隐藏元素

show: function(element):显示元素

remove: function(element):移除元素

update: function(element, html) :使用html更新element的内容,html中的script会执行(下同)

replace: function(element, html):将element替换为html

inspect: function(element)element的字符串表示

recursivelyCollect: function(element, property): 递归收集, 例如Element.recursivelyCollect(element, "parentNode")返回element所有的祖先节点, 注意只返回nodeType == 1的元素,也就是不返回文本元素

ancestors: function(element): 等同于上面的例子,返回元素的所有祖先节点

descendants: function(element): 返回所有子孙节点

immediateDescendants: function(element):返回元素的直接的子孙节点(子节点)的数组

previousSiblings: function(element):返回元素前面的兄弟节点

nextSiblings: function(element):返回位于元素后面的兄弟节点

siblings: function(element):返回元素所有的兄弟节点

match: function(element, selector):使用Selectormatch方法匹配元素(Selector将在后面介绍), selector参数是一个css selector表达式或者Prototype中的一个Selector实例,如果element匹配selector则返回true,否则返回 false,例如对于一个classNamelogcssdiv来说,下面的表达式返回true, $(element).match("div.logcss") 待续。。

up(element, expression, index):利用Selector.findElement方法找到element元素的祖先节点中符合表达式expression的所有元素组成的数组索引为index的元素,也可以忽略expression(默认为*,表示匹配所有元素)index(默认为0),直接这样调用up(element, index)up(element)

down(element, expression, index):跟up一样,只是返回的是子孙节点

previous(element, expression, index):返回前面的兄弟节点

next(element, expression, index):返回后面的兄弟节点

getElementsBySelector(element,args)Selector.findChildElements(element, args)的封装,args表示可以传递多个参数,每个参数是一个css selector表达式,返回element的子孙节点中符合任何一个css selector表达式的元素组成的数组

getElementsByClassName(element, className):返回element中的子孙节点中符合clsssName的元素

readAttribute(element, name)return $(element).getAttribute(name),之所以添加这个方法是因为在IESafari(Mac)getAttribute不是一个真正的函数,它没有callapply等方法,所以在很多时候调用会出现错误(Prototype中很多地方使用了函数的这两个方法),例如下面的例子(官方文档中的一个例子),就只能使用readAttribute

<div id="widgets">

 <div class="widget" widget_id="7">…</div>

 <div class="widget" widget_id="8">…</div>

 <div class="widget" widget_id="9">…</div>

</div>

$$(’div.widget’).invoke(’readAttribute’, ‘widget_id’)

// ["7", "8", "9"]

getHeight: function(element):返回元素高度,return element.offsetHeight

classNames: function(element):返回一个Element.ClassNames对象,改对象提供对元素class的操作,包括addremoveset等,一般很少使用,使用Element.addClassName等方法就可以了(就在下面)

hasClassName: function(element, className) :判断element是否含有className

addClassName: function(element, className) :给element添加一个class

removeClassName: function(element, className) :移除元素中的一个class

observe():调用Event对象(Prototype中的,将在后面介绍)observe方法为元素注册事件handle

stopObserving() :移除注册的事件handle

cleanWhitespace: function(element):移除元素中空白的文本子节点

empty: function(element):判断元素是否为空

childOf: function(element, ancestor) :判断element是否为ancestor的子孙节点

scrollTo: function(element) :滚动条移动到元素所在的地方

getStyle: function(element, style) :得到元素某个css样式的值,例如$(element).getStyle("float")

setStyle: function(element, style) :设置元素的css样式,style十一个对象,例如element.setStyle({left: "40px", "background-color":"#666"})

getDimensions: function(element) :得到元素的尺寸,即使元素是隐藏的也可以正确的返回,返回 return {width: originalWidth, height: originalHeight}这样的关联数组

makePositioned: function(element) :当元素的position css属性为static或不存在使,将次属性更改为relative

undoPositioned: function(element) :跟makePositioned相反的操作

makeClipping: function(element) :把元素变成clipping(切片),也就是设置元素的overflow属性为hidden

undoClipping: function(element):反转上面的方法对元素所做的修改

hasAttribute(element):判断元素是否有某个属性

Element对象的方法是不是不少啊,哈哈,下面介绍有关Insertion的四个类

Insertion.Before:将内容插入到元素的前面,内容在元素外面

Insertion.Top:将内容插入到元素的顶部,内容在元素里面

Insertion.Bottom:将内容插入到元素的底部,内容在元素里面

Insertion.After:将内容插入到元素后面,内容在元素外面

使用它们的方法比较简单:new Insertion.where(element, content),其中where表示上面的BeforeTop等,contenthtml字符串,注意其中javascript片断会执行

终于写完了,PrototypeElement方法还真不少

虽然以前觉得自己对Prototype还比较熟悉,写的也有点累,但是发现自己收获仍然挺大的,为了写出这些方法的具体作用和用法,必须强迫自己一行行的把Prototype的代码弄清楚,使自己对Prototype中很多精巧的写法有了更深刻的认识和理解

写这个教程的主要目的是为了给大家一个快速的参考,大家还是对照着源代码看才会真正有所提高

这时我第一次写比较完整的一个教程,错误幼稚的地方在所难免,希望大家批评指正,互相学习提高,

().Prototype使用指南之Selector

Selector是利用css selector来匹配选择页面元素的,所以要理解Selector首先应该对css selector有所理解,下面是css2 selector的语法,当然很多浏览器只是支持其中的一部分,Prototype 中的Selector主要支持tag选择器、class选择器和id选择器,还有属性(attribute)选择器,基本上包含我们平时所用的所有类型

The following table summarizes CSS2 selector syntax, 详细的可以看http://www.w3.org/TR/REC-CSS2/selector.html:

Pattern

Meaning

Described in section

*

Matches any element.

Universal selector

E

Matches any E element (i.e., an element of type E).

Type selectors

E F

Matches any F element that is a descendant of an E element.

Descendant selectors

E > F

Matches any F element that is a child of an element E.

Child selectors

E:first-child

Matches element E when E is the first child of its parent.

The :first-child pseudo-class

E:link E:visited

Matches element E if E is the source anchor of a hyperlink of which the target is not yet visited (:link) or already visited (:visited).

The link pseudo-classes

E:active E:hover E:focus

Matches E during certain user actions.

The dynamic pseudo-classes

E:lang(c)

Matches element of type E if it is in (human) language c (the document language specifies how language is determined).

The :lang() pseudo-class

E + F

Matches any F element immediately preceded by an element E.

Adjacent selectors

E[foo]

Matches any E element with the “foo” attribute set (whatever the value).

Attribute selectors

E[foo=”warning”]

Matches any E element whose “foo” attribute value is exactly equal to “warning”.

Attribute selectors

E[foo~=”warning”]

Matches any E element whose “foo” attribute value is a list of space-separated values, one of which is exactly equal to “warning”.

Attribute selectors

E[lang|=”en”]

Matches any E element whose “lang” attribute has a hyphen-separated list of values beginning (from the left) with “en”.

Attribute selectors

DIV.warning

HTML only. The same as DIV[class~=”warning”].

Class selectors

E#myid

Matches any E element ID equal to “myid”.

ID selectors

Selector中包含Selector对象和类,

Selector对象具有下面两个方法:

match(element):元素是否与本selector匹配,在Element中已经介绍了
findElements(parentNode)
parentNode中所有匹配本selector的子孙元素列表

使用方法也很简单 var s=new Selector(expression); s.match(element); s.findElements($(element)),其中expression可以是如下方式 "div""#id"".class""div#id""div[attribute]""div[attribute=fff]""div[attribute!=sdf]"

其中Selector也有几个静态方法,它们分别是:

matchElements(elements, expression):返回elements中符合expression的元素列表
findElement(elements, expression, index)
:返回elements中符合expression的元素列表中索引为index的元素
findChildElements(element, expressions)
:找出element的子孙元素中符合expressions的元素列表,其中expressions是一个expression数组,其中的expression支持"div li.#id"形式

$$方法:只是简单的调用return Selector.findChildElements(document, $A(arguments))

虽然Selector有这么多方法,但是大部分都是内部调用的,我们一般都很少使用,因为我们有个一个方便的方法$$,对于绝大部分情况已经足够了

(十一).Prototype1.5 rc2)使用指南之form

这一部分提供了很多与表单操作有关的功能,包括以下部分,当通过$方法返回元素时,可以直接通过$(element).method()调用:

Form对象:提供了操作整个表单的一些方法
Form.Element
对象:提供了操作某个表单元素的方法
TimedObserver
类:周期性表单监视器,当表单元素值改变的时候执行一个回调函数,有FormElement两种类型
EventObserver
类:利用事件来监视表单元素,当表单元素值改变的时候执行一个回调函数,有FormElement两种类型

Form对象:

reset(form)form.reset()
serializeElements(elements)
:将elements中的元素序列化,就是返回指定的所有元素的queryString的形式,便于在xmlhttp或其他地方使用
serialize(form)
:序列化整个表单
getElements(form)
:返回表单的所有可序列化元素
getInputs(form, typeName, name)
:返回所有符合typeNamenameinput元素
disable(form)
:使整个表单处于不可用状态
enable(form)
:是整个表单可用
findFirstElement(form)
:返回类型为‘input’, ’select’, ‘textarea’的第一个可用的非隐藏元素
focusFirstElement(form)
:使findFirstElement(form)返回的元素得到焦点

Form.Element对象:

focus(element) select(element)html元素内置方法的封装,除了返回元素本身
serialize(element)
:序列化指定的表单元素,返回key=value的形式,返回的string已经encodeURIComponent
getValue(element)
:返回元素的值
clear(element)
:清除元素的值
present(element)
:判断元素的值是否非空
activate(element)
:使元素获得焦点
disable(element)
:使元素不可用
enable(element)
:是元素可用

$F = Form.Element.getValue 方便使用

Form.Element.Observer以及Form.Observer类:

周期性监视表单元素,如果表单或表单元素的值有改变时,执行执行一个回调函数,使用方式如下:

var oser=new Form.Element.Observer(element, frequency, callback)
or oser=new Form.Observer(form, frequency, callback)
callback
可以定义两个参数 form/elementForm.serialize()/value

Form.Element.EventObserverForm.EventObserver类:

这两个类跟上面的差不多,只是不是周期性的监视,而是利用元素的changeclick事件来监视表单元素的变化,当发生变化时执行callback,参数跟上面一样

 

(十二).Prototype1.5 rc2)使用指南之event.js

在介绍PrototypeEvent对象前先介绍一下浏览器中的事件模型,浏览器中的事件主要有HTML事件、鼠标事件和键盘事件,前两种事件比较好理解,这里主要解释一下键盘事件以及它在IEfirefox中的区别

键盘事件包括keydownkepresskeyup三种,每次敲击键盘都会(依次?)触发这三种事件,其中keydownkeyup是比较低级的接近于硬件的事件,通俗的理解是这两个事件可以捕获到你敲击了键盘中某个键;而keypress是相对于字符层面的较为高级点的事件,这个事件能够捕捉到你键入了哪个字符。可以这样理解,如果你敲击了A键,keydownkeyup事件只是知道你敲击了A键,它并不知道你敲的是大写的A(你同时按下了Shift)还是敲的是小写a,它是以""为单位,你敲入了大写的A,它只是当成你敲下了shiftA两个键而已,但是keypress可以捕捉到你是敲入的大写的A还是小写的a

还要理解一个概念是键盘中的键分为字符(可打印)键和功能键(不可打印),功能键包括Backspace, Enter, Escape, the arrow keys, Page Up, Page Down, and F1 through F12

下面说一下键盘事件的具体使用方法,

键盘事件的event对象中包含一个keyCode属性,IE中只有这一个属性,当为keydownkeyup 事件是,keycode属性表示你具体按下的键(也称为virtual keycode),当捕捉的是keypress事件时keyCode属性指的是你键入的字符(character code)

firefox中情况有些不同,event对象包含一个keyCode属性和一个charCode属性,keydownkeyup事件的时候,keyCode表示的就是你具体按的键,charCode0;当捕捉的是keypress事件时,keyCode0charCode指的是你按下的字符

当捕捉的是keypress事件时, 当你按的是可打印字符时,keyCode0charCode指的是你按下的字符的键值,当你按的是不可打印字符时,keyCode为按下的键的键值,charCode0

注意:功能键不会触发keypress事件,因为keypress对应的就是可打印的字符,但是有一点IEFF 中的区别,你按下一个字符键的同时按下alt键,在IE中不触发keypress事件,但是在ff中可触发,我发现在IE中按下ctrl键的时候只有按下 q键会触发事件其他的要么不会触发事件,要么被浏览器IE自身捕获了,例如你按下ctrl_A,全选某个东西,你按ctrl_S保存文件,但是在FF中就 好多了,事件都是先传递到网页,再向外传递

鉴于IEFF中的区别,如果你比较懒的话,建议只使用keydowkeyup事件,这两种事件的使用在IEFF中基本上没有区别,也不要捕获ctrl_A等被浏览器定义为快捷键的事件

键盘事件event对象还有三个其他的属性altKey, ctrlKey, and shiftKey 来判断你按下一个键的时候是否按下了alt等键,这三个属性使用比较简单,三种事件都可以使用,也不存在ieff的兼容性问题

Prototype中的Event中又如下属性:

  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_HOME:     36,
  KEY_END:      35,
  KEY_PAGEUP:   33,
  KEY_PAGEDOWN: 34,

以及下面的方法:

element(event) :返回触发事件的元素
isLeftClick(event)
:判断是否按下的左键
pointerX(event)
:事件触发时鼠标的横坐标,对于非鼠标事件,在ff中没有此信息,但在ie中有?
pointerY(event)
:事件触发时鼠标所在位置的纵坐标
stop(event)
:阻止事件向上传播和浏览器的默认处理方法
findElement(event, tagName)
:找到触发事件的元素的所有祖先元素中的tagNametagName的一个元素
observe(element, name, observer, useCapture)
:注册事件处理函数
stopObserving(element, name, observer, useCapture)
:撤销注册的事件

(十三).Prototype1.5 rc21.5 rc2)版指南最后一篇之Position

Positionprototype中定义的一个对象,提供了操作DOM中与位置相关的方法,要很好的理解元素在页面中的位置,可以参考这篇文章:Relatively Absolute

具体代码如下,按照代码说说,其中英文是作者的注释,中文红色的才是偶的说明或翻译英文的注释,采用顶式注释法(注释在要说明的代码的上面)说明

  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  //
只有在使用拖动的时候元素包含在有滚动条的元素中才需要设置为true
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  //
当页面被scrolled后,使用withinIncludingScrolloffset的时候需要先调用这个方法
  prepare: function() {
    //
横向滚动条滚动的距离
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    //
纵向滚动条滚动的距离
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

//元素由于滚动条偏移的总距离 
realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

//元素在页面中由offsetParent累积的offset,当offsetParent都没有滚动条时,就是元素在页面中的位置
cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

//元素相对于containing block("nearest positioned ancestor")的位置,也就是相对于最近的一个position设置为relative或者absolute的祖先节点的位置,如果没有就是相对于 body的位置,跟style.topstyle.left一样?
positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if(element.tagName==’BODY’) break;
        var p = Element.getStyle(element, ‘position’);
        if (p == ‘relative’ || p == ‘absolute’) break;
      }
    } while (element);
    return [valueL, valueT];
  },
  
  //offsetParent
  offsetParent: function(element) {
    if (element.offsetParent) return element.offsetParent;
    if (element == document.body) return element;

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, ‘position’) != ’static’)
        return element;

    return document.body;
  },
 
  // caches x/y coordinate pair to use with overlap
  //
判断指定的位置是否在元素内
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

//within差不多,不过考虑到滚动条,也许是在元素上面,但不是直接在上面,因为滚动条也许已经使元素不可见了 
withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  //
在调用这个方法前,必须先调用within,返回在with指定的位置在水平或者垂直方向上占用的百分比
  overlap: function(mode, element) { 
    if (!mode) return 0; 
    if (mode == ‘vertical’)
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == ‘horizontal’)
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

//返回元素相对页面的真实位置 
page: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent==document.body)
        if (Element.getStyle(element,’position’)==’absolute’) break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!window.opera || element.tagName==’BODY’) {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

//设置targetsource的位置,大小 
clone: function(source, target) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {})

    // find page position of source
    source = $(source);
    var p = Position.page(source);

    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(target,’position’) == ‘absolute’) {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + ‘px’;
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + ‘px’;
    if(options.setWidth)  target.style.width = source.offsetWidth + ‘px’;
    if(options.setHeight) target.style.height = source.offsetHeight + ‘px’;
  },

//elementposition设置为absolute的模式 
absolutize: function(element) {
    element = $(element);
    if (element.style.position == ‘absolute’) return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = ‘absolute’;
    element.style.top    = top + ‘px’;;
    element.style.left   = left + ‘px’;;
    element.style.width  = width + ‘px’;;
    element.style.height = height + ‘px’;;
  },

//elementposition设置为absolute的模式 
relativize: function(element) {
    element = $(element);
    if (element.style.position == ‘relative’) return;
    Position.prepare();

    element.style.position = ‘relative’;
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + ‘px’;
    element.style.left   = left + ‘px’;
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
  }
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, ‘position’) == ‘absolute’) break;
       
      element = element.offsetParent;
    } while (element);
   
    return [valueL, valueT];
  }
}

终于把Prototype的所有部分都写完了,哈哈,越来越佩服自己的耐力了

下一步决定写写Scriptaculous这个超级流行的效果库

Prototype1.5的下载为什么不简单点

这几天在论坛和博客上看到很多人问Prototype1.5怎么下载,为什么下载这么困难呢?
Prototype
的官方网站是:http://prototype.conio.net/,如果你一下子找不到,到google上搜索Prototype就找到了
下载当然要到官方网站下载了,但是问题是Prototype官方网站更新太慢,首页上的下载连接还是prototype1.4的,而且只是一个单独的js文件
那么怎么下载最新版本的呢?
1
,如果你只想得到一个单独的js文件使用的话,其实官方网站提供了最新版1.5的下载, 下面连接就是下载地址了http://dev.rubyonrails.org/browser/trunk/railties/html/javascripts/prototype.js?format=raw
2
,如果你想得到详细的源文件以及测试代码,需要通过svn下载:使用下面的命令就可以了:svn co http://dev.rubyonrails.org/svn/rails/spinoffs/prototype
如果你没有svn的话,我已经下载打包了传到51js论坛中,查看下面连接的帖子中有下载的:http://bbs.51js.com/viewthread.php?tid=65070&highlight=prototype

想必很多prototype爱好者都一直在等待着prototype1.5的发布,虽然等待的时间很长,但是这一令人激动的一天终于到来了
因为网友提醒
,今天访问prototype网站,发现原来的网址已经自动跳转到新的网站去了, 作者使用了一个独立的域名 http://www.prototypejs.org/
刚才在google里搜索prototype,发现搜索结果中出现的已经是新网站了,google爬虫也蛮勤快的嘛
更让人高兴的是,一向被人诟病的文档问题这一版有了非常大的提高,可以说是有了质的飞跃,以前的版本基本上没有文档,要使用只有自己理解了,
现在在它的官方网站上有专门的API参考以及一些使用的例子,看来作者真正的关于这个问题来了,prototype爱好者应该高兴一把了哈哈,赶快到prototype官方网站下载了Engoy 如果感觉阅读英文是一种折磨的话,可以参考我以前写的prototype 1.5使用指南系列文章.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
jQuery核心源码core.js分析
Jquery核心
jQuery中的编程范式
关于一些前端js框架的源码研究
Array.prototype.filter用在nodelist为什么会出现报错
$到底是什么
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服