2009年5月15日星期五

Comet:基于 HTTP 长连接的“服务器推”技术

很多应用譬如监控、即时通信、即时报价系统都需要将后台发生的变化实时传送到客户端而无须客户端不停地刷新、发送请求。本文首先 介绍、比较了常用的“服务器推”方案,着重介绍了 Comet - 使用 HTTP 长连接、无须浏览器安装插件的两种“服务器推”方案:基于 AJAX 的长轮询方式;基于 iframe 及 htmlfile 的流方式。最后分析了开发 Comet 应用需要注意的一些问题,以及如何借助开源的 Comet 框架-pushlet 构建自己的“服务器推”应用。

“服务器推”技术的应用

传统模式的 Web 系统以客户端发出请求、服务器端响应的方式工作。这种方式并不能满足很多现实应用的需求,譬如:

  • 监控系统:后台硬件热插拔、LED、温度、电压发生变化;
  • 即时通信系统:其它用户登录、发送信息;
  • 即时报价系统:后台数据库内容发生变化;

这 些应用都需要服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求。“服务器推”技术在现实应用中有一些解决方案,本文将这些解决方案分为两 类:一类需要在浏览器端安装插件,基于套接口传送信息,或是使用 RMI、CORBA 进行远程调用;而另一类则无须浏览器安装任何插件、基于 HTTP 长连接。

将“服务器推”应用在 Web 程序中,首先考虑的是如何在功能有限的浏览器端接收、处理信息:

  1. 客户端如何接收、处理信息,是否需要使用套接口或是使用远程调用。客户端呈现给用户的是 HTML 页面还是 Java applet 或 Flash 窗口。如果使用套接口和远程调用,怎么和 JavaScript 结合修改 HTML 的显示。
  2. 客户与服务器端通信的信息格式,采取怎样的出错处理机制。
  3. 客户端是否需要支持不同类型的浏览器如 IE、Firefox,是否需要同时支持 Windows 和 Linux 平台。


基于客户端套接口的“服务器推”技术

Flash XMLSocket

如果 Web 应用的用户接受应用只有在安装了 Flash 播放器才能正常运行, 那么使用 Flash 的 XMLSocket 也是一个可行的方案。

这种方案实现的基础是:

  1. Flash 提供了 XMLSocket 类。
  2. JavaScript 和 Flash 的紧密结合:在 JavaScript 可以直接调用 Flash 程序提供的接口。

具 体实现方法:在 HTML 页面中内嵌入一个使用了 XMLSocket 类的 Flash 程序。JavaScript 通过调用此 Flash 程序提供的套接口接口与服务器端的套接口进行通信。JavaScript 在收到服务器端以 XML 格式传送的信息后可以很容易地控制 HTML 页面的内容显示。

关于如何去构建充当了 JavaScript 与 Flash XMLSocket 桥梁的 Flash 程序,以及如何在 JavaScript 里调用 Flash 提供的接口,我们可以参考 AFLAX(Asynchronous Flash and XML)项目提供的 Socket Demo 以及 SocketJS(请参见 参考资源)。

Javascript 与 Flash 的紧密结合,极大增强了客户端的处理能力。从 Flash 播放器 V7.0.19 开始,已经取消了 XMLSocket 的端口必须大于 1023 的限制。Linux 平台也支持 Flash XMLSocket 方案。但此方案的缺点在于:

  1. 客户端必须安装 Flash 播放器;
  2. 因为 XMLSocket 没有 HTTP 隧道功能,XMLSocket 类不能自动穿过防火墙;
  3. 因为是使用套接口,需要设置一个通信端口,防火墙、代理服务器也可能对非 HTTP 通道端口进行限制;

不过这种方案在一些网络聊天室,网络互动游戏中已得到广泛使用。

Java Applet 套接口

在客户端使用 Java Applet,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 建立与服务器端的套接口连接,从而实现“服务器推”。

这种方案最大的不足在于 Java applet 在收到服务器端返回的信息后,无法通过 JavaScript 去更新 HTML 页面的内容。



基于 HTTP 长连接的“服务器推”技术

Comet 简介

浏 览器作为 Web 应用的前台,自身的处理功能比较有限。浏览器的发展需要客户端升级软件,同时由于客户端浏览器软件的多样性,在某种意义上,也影响了浏览器新技术的推广。 在 Web 应用中,浏览器的主要工作是发送请求、解析服务器返回的信息以不同的风格显示。AJAX 是浏览器技术发展的成果,通过在浏览器端发送异步请求,提高了单用户操作的响应性。但 Web 本质上是一个多用户的系统,对任何用户来说,可以认为服务器是另外一个用户。现有 AJAX 技术的发展并不能解决在一个多用户的 Web 应用中,将更新的信息实时传送给客户端,从而用户可能在“过时”的信息下进行操作。而 AJAX 的应用又使后台数据更新更加频繁成为可能。


图 1. 传统的 Web 应用模型与基于 AJAX 的模型之比较
图 1. 传统的 Web 应用模型与基于 AJAX 的模型之比较

“ 服务器推”是一种很早就存在的技术,以前在实现上主要是通过客户端的套接口,或是服务器端的远程调用。因为浏览器技术的发展比较缓慢,没有为“服务器推” 的实现提供很好的支持,在纯浏览器的应用中很难有一个完善的方案去实现“服务器推”并用于商业程序。最近几年,因为 AJAX 技术的普及,以及把 IFrame 嵌在“htmlfile“的 ActiveX 组件中可以解决 IE 的加载显示问题,一些受欢迎的应用如 meebo,gmail+gtalk 在实现中使用了这些新技术;同时“服务器推”在现实应用中确实存在很多需求。因为这些原因,基于纯浏览器的“服务器推”技术开始受到较多关注,Alex Russell(Dojo Toolkit 的项目 Lead)称这种基于 HTTP 长连接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。目前已经出现了一些成熟的 Comet 应用以及各种开源框架;一些 Web 服务器如 Jetty 也在为支持大量并发的长连接进行了很多改进。关于 Comet 技术最新的发展状况请参考关于 Comet 的 wiki。

下面将介绍两种 Comet 应用的实现模型。

基于 AJAX 的长轮询(long-polling)方式

图 1 所示,AJAX 的出现使得 JavaScript 可以调用 XMLHttpRequest 对象发出 HTTP 请求,JavaScript 响应处理函数根据服务器返回的信息对 HTML 页面的显示进行更新。使用 AJAX 实现“服务器推”与传统的 AJAX 应用不同之处在于:

  1. 服务器端会阻塞请求直到有数据传递或超时才返回。
  2. 客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
  3. 当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。

图 2. 基于长轮询的服务器推模型
图 2. 基于长轮询的服务器推模型

一 些应用及示例如 “Meebo”, “Pushlet Chat” 都采用了这种长轮询的方式。相对于“轮询”(poll),这种长轮询方式也可以称为“拉”(pull)。因为这种方案基于 AJAX,具有以下一些优点:请求异步发出;无须安装插件;IE、Mozilla FireFox 都支持 AJAX。

在 这种长轮询方式下,客户端是在 XMLHttpRequest 的 readystate 为 4(即数据传输结束)时调用回调函数,进行信息处理。当 readystate 为 4 时,数据传输结束,连接已经关闭。Mozilla Firefox 提供了对 Streaming AJAX 的支持, 即 readystate 为 3 时(数据仍在传输中),客户端可以读取数据,从而无须关闭连接,就能读取处理服务器端返回的信息。IE 在 readystate 为 3 时,不能读取服务器返回的数据,目前 IE 不支持基于 Streaming AJAX。

基于 Iframe 及 htmlfile 的流(streaming)方式

iframe 是很早就存在的一种 HTML 标记, 通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。


图 3. 基于流方式的服务器推模型
图 3. 基于流方式的服务器推模型

上 节提到的 AJAX 方案是在 JavaScript 里处理 XMLHttpRequest 从服务器取回的数据,然后 Javascript 可以很方便的去控制 HTML 页面的显示。同样的思路用在 iframe 方案的客户端,iframe 服务器端并不返回直接显示在页面的数据,而是返回对客户端 Javascript 函数的调用,如“<script type="text/javascript">js_func(“data from server ”)</script>”。服务器端将返回的数据作为客户端 JavaScript 函数的参数传递;客户端浏览器的 Javascript 引擎在收到服务器返回的 JavaScript 调用时就会去执行代码。

图 3 可以看到,每次数据传送不会关闭连接,连接只会在通信出现错误时,或是连接重建时关闭(一些防火墙常被设置为丢弃过长的连接, 服务器端可以设置一个超时时间, 超时后通知客户端重新建立连接,并关闭原来的连接)。

使 用 iframe 请求一个长连接有一个很明显的不足之处:IE、Morzilla Firefox 下端的进度栏都会显示加载没有完成,而且 IE 上方的图标会不停的转动,表示加载正在进行。Google 的天才们使用一个称为“htmlfile”的 ActiveX 解决了在 IE 中的加载显示问题,并将这种方法用到了 gmail+gtalk 产品中。Alex Russell 在 “What else is burried down in the depth's of Google's amazing JavaScript?”文章中介绍了这种方法。Zeitoun 网站提供的 comet-iframe.tar.gz,封装了一个基于 iframe 和 htmlfile 的 JavaScript comet 对象,支持 IE、Mozilla Firefox 浏览器,可以作为参考。(请参见 参考资源



使用 Comet 模型开发自己的应用

上面介绍了两种基于 HTTP 长连接的“服务器推”架构,更多描述了客户端处理长连接的技术。对于一个实际的应用而言,系统的稳定性和性能是非常重要的。将 HTTP 长连接用于实际应用,很多细节需要考虑。

不要在同一客户端同时使用超过两个的 HTTP 长连接

我 们使用 IE 下载文件时会有这样的体验,从同一个 Web 服务器下载文件,最多只能有两个文件同时被下载。第三个文件的下载会被阻塞,直到前面下载的文件下载完毕。这是因为 HTTP 1.1 规范中规定,客户端不应该与服务器端建立超过两个的 HTTP 连接, 新的连接会被阻塞。而 IE 在实现中严格遵守了这种规定。

HTTP 1.1 对两个长连接的限制,会对使用了长连接的 Web 应用带来如下现象:在客户端如果打开超过两个的 IE 窗口去访问同一个使用了长连接的 Web 服务器,第三个 IE 窗口的 HTTP 请求被前两个窗口的长连接阻塞。

所以在开发长连接的应用时, 必须注意在使用了多个 frame 的页面中,不要为每个 frame 的页面都建立一个 HTTP 长连接,这样会阻塞其它的 HTTP 请求,在设计上考虑让多个 frame 的更新共用一个长连接。

服务器端的性能和可扩展性

一般 Web 服务器会为每个连接创建一个线程,如果在大型的商业应用中使用 Comet,服务器端需要维护大量并发的长连接。在这种应用背景下,服务器端需要考虑负载均衡和集群技术;或是在服务器端为长连接作一些改进。

应 用和技术的发展总是带来新的需求,从而推动新技术的发展。HTTP 1.1 与 1.0 规范有一个很大的不同:1.0 规范下服务器在处理完每个 Get/Post 请求后会关闭套接口连接; 而 1.1 规范下服务器会保持这个连接,在处理两个请求的间隔时间里,这个连接处于空闲状态。 Java 1.4 引入了支持异步 IO 的 java.nio 包。当连接处于空闲时,为这个连接分配的线程资源会返还到线程池,可以供新的连接使用;当原来处于空闲的连接的客户发出新的请求,会从线程池里分配一个线 程资源处理这个请求。 这种技术在连接处于空闲的机率较高、并发连接数目很多的场景下对于降低服务器的资源负载非常有效。

但 是 AJAX 的应用使请求的出现变得频繁,而 Comet 则会长时间占用一个连接,上述的服务器模型在新的应用背景下会变得非常低效,线程池里有限的线程数甚至可能会阻塞新的连接。Jetty 6 Web 服务器针对 AJAX、Comet 应用的特点进行了很多创新的改进,请参考文章“AJAX,Comet and Jetty”(请参见 参考资源)。

控制信息与数据信息使用不同的 HTTP 连接

使用长连接时,存在一个很常见的场景:客户端网页需要关闭,而服务器端还处在读取数据的堵塞状态,客户端需要及时通知服务器端关闭数据连接。服务器在收到关闭请求后首先要从读取数据的阻塞状态唤醒,然后释放为这个客户端分配的资源,再关闭连接。

所以在设计上,我们需要使客户端的控制请求和数据请求使用不同的 HTTP 连接,才能使控制请求不会被阻塞。

在 实现上,如果是基于 iframe 流方式的长连接,客户端页面需要使用两个 iframe,一个是控制帧,用于往服务器端发送控制请求,控制请求能很快收到响应,不会被堵塞;一个是显示帧,用于往服务器端发送长连接请求。如果是基 于 AJAX 的长轮询方式,客户端可以异步地发出一个 XMLHttpRequest 请求,通知服务器端关闭数据连接。

在客户和服务器之间保持“心跳”信息

在浏览器与服务器之间维持一个长连接会为通信带来一些不确定性:因为数据传输是随机的,客户端不知道何时服务器才有数据传送。服务器端需要确保当客户端不再工作时,释放为这个客户端分配的资源,防止内存泄漏。因此需要一种机制使双方知道大家都在正常运行。在实现上:

  1. 服务器端在阻塞读时会设置一个时限,超时后阻塞读调用会返回,同时发给客户端没有新数据到达的心跳信息。此时如果客户端已经关闭,服务器往通道写数据会出现异常,服务器端就会及时释放为这个客户端分配的资源。
  2. 如果客户端使用的是基于 AJAX 的长轮询方式;服务器端返回数据、关闭连接后,经过某个时限没有收到客户端的再次请求,会认为客户端不能正常工作,会释放为这个客户端分配、维护的资源。
  3. 当服务器处理信息出现异常情况,需要发送错误信息通知客户端,同时释放资源、关闭连接。

Pushlet - 开源 Comet 框架

Pushlet 是一个开源的 Comet 框架,在设计上有很多值得借鉴的地方,对于开发轻量级的 Comet 应用很有参考价值。

观察者模型

Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。

客户端 JavaScript 库

pushlet 提供了基于 AJAX 的 JavaScript 库文件用于实现长轮询方式的“服务器推”;还提供了基于 iframe 的 JavaScript 库文件用于实现流方式的“服务器推”。

JavaScript 库做了很多封装工作:

  1. 定义客户端的通信状态:STATE_ERROR、STATE_ABORT、STATE_NULL、STATE_READY、STATE_JOINED、STATE_LISTENING;
  2. 保存服务器分配的会话 ID,在建立连接之后的每次请求中会附上会话 ID 表明身份;
  3. 提供了 join()、leave()、subscribe()、 unsubsribe()、listen() 等 API 供页面调用;
  4. 提供了处理响应的 JavaScript 函数接口 onData()、onEvent()…

网页可以很方便地使用这两个 JavaScript 库文件封装的 API 与服务器进行通信。

客户端与服务器端通信信息格式

pushlet 定义了一套客户与服务器通信的信息格式,使用 XML 格式。定义了客户端发送请求的类型:join、leave、subscribe、unsubscribe、listen、refresh;以及响应的事件类型:data、join_ack、listen_ack、refresh、heartbeat、error、abort、subscribe_ack、unsubscribe_ack。

服务器端事件队列管理

pushlet 在服务器端使用 Java Servlet 实现,其数据结构的设计框架仍可适用于 PHP、C 编写的后台客户端。

Pushlet 支持客户端自己选择使用流、拉(长轮询)、轮询方式。服务器端根据客户选择的方式在读取事件队列(fetchEvents)时进行不同的处理。“轮询”模式下 fetchEvents() 会马上返回。”流“和”拉“模式使用阻塞的方式读事件,如果超时,会发给客户端发送一个没有新信息收到的“heartbeat“事件,如果是“拉”模式,会把“heartbeat”与“refresh”事件一起传给客户端,通知客户端重新发出请求、建立连接。

客户服务器之间的会话管理

服务端在客户端发送 join 请求时,会为客户端分配一个会话 ID, 并传给客户端,然后客户端就通过此会话 ID 标明身份发出 subscribe 和 listen 请求。服务器端会为每个会话维护一个订阅的主题集合、事件队列。

服务器端的事件源会把新产生的事件以多播的方式发送到每个会话(即订阅者)的事件队列里。



小结

本文介绍了如何在现有的技术基础上选择合适的方案开发一个“服务器推”的应用,最优的方案还是取决于应用需求的本身。相对于传统的 Web 应用, 目前开发 Comet 应用还是具有一定的挑战性。

“ 服务器推”存在广泛的应用需求,为了使 Comet 模型适用于大规模的商业应用,以及方便用户构建 Comet 应用,最近几年,无论是服务器还是浏览器都出现了很多新技术,同时也出现了很多开源的 Comet 框架、协议。需求推动技术的发展,相信 Comet 的应用会变得和 AJAX 一样普及。


Come from: http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

2009年5月14日星期四

CSS 压缩与优化工具

书写 CSS 的时候只要注意一些常用缩写语法和掌握了十八般技巧,如 0 是不需要定义单位的,盒的上右下左原则,如左右相同可以定义为 10px 0 20px 这样,normal 值可以用 400 表示,bold 用 700 表示,那么写出来的 CSS 一般就不错了。如果需要消除 CSS 中一些多余空白,使用手工方式未免太繁琐,这就需要一些压缩优化工具来帮忙,这类网站很多,大多都是基于 CSSTidy 这个免费优化程序 (如 Clean CSS),它的客户端版本还支持 Windows, Linux, OSX。除了 CSSTidy 之外我还比较喜欢 CSS Compressor 这个工具。

主要介绍一下 CSS Compressor,它是 CSS Drive 提供的 CSS 压缩工具,不但操作简单,压缩效果也很好。在默认的普通模式中有三种压缩选项,Light 代表只清除缩进空白,Normal 可以让每个属性写成一行 (推荐),而 Super Compact 模式不推荐,它会清楚掉所有多余空白,把整个 CSS 写成一行,不利于以后的阅读和修改。对注释也提供三种清除选项,第一是不清除,第二是清除所有,第三个是清除大于多少字符的注释。在书写 CSS 中建议全部使用小写,CSS Compressor 的缺点就是没法像 CSSTidy 一样把大写转换为小写。

沿用 Clean CSS 风格、CSSTidy 1.2 引擎,自己搭建了一个 CSSTidy - CSS 整形与优化工具,把它放在 Blog 側边,有需要时可以随时点击进去,不用再去 Clean CSS 了。

Come from: http://www.osxcn.com/css/css-compressor.html

2009年5月12日星期二

8个设计规范的表格Table CSS样式应用

如果说是Table把我带入了网站设计的大学的话,那么DIV+CSS则把我带入了Web设计的殿堂。虽然现在的Web设计者都在推崇DIV+CSS的网站设计,但不落入盲目应用的队列,灵活运用Table的特色来做一些前台的功能效果的话,那可能会让你的工作进程大大的缩短,并减少很多不必要的冗余CSS代码。

Table表格本身就是Html网站设计中最基本的组成部分,还记得刚开始在FrontPage里欣喜地用一个Table框画出的简单页面吗?那时的我们就已经在为Table的无所不能而折服了。而在现在的DIV+CSS页面设计中,很多人将Table的概念抛之脑后,统统使用DIV+CSS来实现所有页面排版,从而,在一些列表设计中凭白增加了CSS代码的比重,其实,灵活地把Talbe应用到DIV+CSS网页标准中去,会受益更多。

本文菠菜搜集介绍了一系列的Table设计及应用技巧,希望在你的项目开发中可以很好地融汇应用进去,提高你的页面灵活度和可读性。

让我们从一个简洁的Table设计实例开始吧!

1,FLUIDMIND.ORG

这是一个非常简单的table应用的例子,它的1px边框及行列的长宽设置使得整个的表格表现出来的内容更直观易读。

这个table是对上面那个的改进,增加了背景色并减少了横向border的数量,使得表格数据垂直方向的对比性更强。

这个table则对上面效果的横向可读性作了改进,通过为header设置相对于其他元素更为突出的背景色实现。

通过设置橙色和table内部的虚线框,使得table的外观更具视觉辨识度。

使用单双行间的交替色提高table的可读性。这种效果更适合阅读习惯,减轻视觉疲劳。

这种设计使用间隔色和突出的header背景色,更适合data显示。

 

2,MOTHERRUSSIA.POLYESTER.SE

这是一个使用jQuery建立表格的应用,这个Table jQuery插件设计的也是非常的简单易用,。

在这个设计中,使用了黑底白字的显示效果,并且将header行用渐变的对比色、分类图标和内容块区分开来,该设计最特色的功能就是,使用jQuery TableSorter Pager可以将每列的数据进行递增和递减排序。

文档地址:http://motherrussia.polyester.se/docs/tablesorter/

 

3,EXT JS

Ext JS号称是Cross-Browser Rich Internet Application Framework(跨浏览器的Internet多应用框架),确实,这个table项目真的非常的强大,看看它的演示效果就知道了。

这是一个XML Grid实例,告诉你怎么load XML数据形成grid。这个table有蓝色和灰色两种风格。你可以点击这里查看实例演示

这是另一个来自Ext JS的table设计实例。这个实例教你怎么创建一个可以进行单元格编辑功能的table。所有的table内容全部可以由你来定义。你可以点击这里查看实例演示

 

4,ZAPATEC

很喜欢这个table设计效果,包括它的3D效果和灵活的可操作性,都让我叹为观止。这个table的边框设计的很好,使整个的table看起来有了3D效果。还有header的背景图设计和当前操作行的突出色彩都是非常的到位。

实例演示地址:点击这里查看

 

5,VALIDWEB.NL

又一个单双行交替色使用的table设计,整个的鼠标操作事件的样式做的很不错。点击这里查看一个实例。

 

6,VEERLE.DUOH.COM

来自知名博客Veerle.com的一个table设计实例,除了很好的色彩搭配外,其可用性也是非常的好。

详细的文档可参考博客原文:http://veerle.duoh.com/blog/comments/a_css_styled_table/

 

7,ASKTHECSSGUY.COM

这个设计充分利用了橙色素的对比度,来区分heade行和第一列。如果你是要在一个大的table中,突出显示一个单元格数据的话,这个效果就非常的有用了。当鼠标点击某一个单元格时,该单元格的样式会突出显示。实例的最终演示效果,查看这里

 

8,SMASHINGMAGAZINE.COM

这是一个来自著名的技术博客SMASHINGMAGAZINE的一个table应用项目,该项目把table的应该发挥到了一个如火纯清的地步,有很多实用的例子可供参考。

最后,告诉大家一个链接地址http://icant.co.uk/csstablegallery/ - 该网站整理里非常多的CSS Table设计实例,在你进行table设计时,不妨先去看看别人的东西。文章翻译整理自:30+ Nicest Table CSS Designs You Can Apply Into Your Project

Come from: http://www.jz123.cn/text/076482.html

2009年5月4日星期一

CSS fixed 定位( FF / IE6 )

fixed 定位主要是以 window 物件區塊做定位依據,所以不會隨頁面捲動而變動定位。


以往要達成這種模式的定位都要利用 JavaScript 的 onscroll 事件去達成,是蠻吃重的一種方法,而且流暢度也不好,會有閃爍的現象。


利用 fixed 定位可以簡化 JavaScript 的開發和負擔,而且又穩定且簡單設定。



body{
height:1200px;
/* prevent screen flash in IE6(解決 IE6 不正常閃爍) */
background:url(nothing.txt) white fixed;
}
div{
background:#FF0066;
border:4px solid #FF9999;
}
/* 水平置中 */
.fixed-center{
width:100px;
height:100px;
position:fixed;
top:50%;
left:50%;

/* 上邊界計算 */
/* -(border-top-width + padding-top + (height/2) ) */
/* 或者是整體高除以二(offsetHeight/2) */
margin-top:-52px;
/* 左邊界計算 */
/* -(border-left-width + padding-left + (width/2) ) */
/* 或者是整體寬除以二(offsetWidth/2) */
margin-left:-52px;

/* position fixed for IE6 */
_position: absolute;
_margin-top:0;
/* clientHeight:不包含邊匡的區塊高度( padding + height ) */
/* offsetHeight:包含邊匡的區塊高度( border + padding + height ) */
_top:expression(documentElement.scrollTop + ( documentElement.clientHeight-this.offsetHeight )/2
);
}
.fixed-top-center{
width:100px;
height:100px;
position:fixed;
top:0;
left:50%;
margin-left:-52px;

/* position fixed for IE6 */
_position: absolute;
_top:expression(documentElement.scrollTop);
}
.fixed-bottom-center{
width:100px;
height:100px;
position:fixed;

bottom:0;
left:50%;
margin-left:-52px;

/* position fixed for IE6 */
_position: absolute;
_top:expression( documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight );
}


展示頁面(Demo Page)

Come from: http://jax-work-archive.blogspot.com/2008/10/css-fixed-ff-ie6.html

如何优化JavaScript脚本的性能

随着网络的发展,网速和机器速度的提高,越来越多的网站用到了丰富客户端技术。而现在Ajax则是最为流行的一种方式。JavaScript是一种解释型语言,所以能无法达到和C/Java之类的水平,限制了它能在客户端所做的事情,为了能改进他的性能,我想基于我以前给JavaScript做过的很多测试来谈谈自己的经验,希望能帮助大家改进自己的JavaScript脚本性能。

语言层次方面

循环

循环是很常用的一个控制结构,大部分东西要依靠它来完成,在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环,事实上,这三种循环中for(in)的效率极差,因为他需要查询散列键,只要可以就应该尽量少用。for(;;)while循环的性能应该说基本(平时使用时)等价。

而事实上,如何使用这两个循环,则有很大讲究。我在测试中有些很有意思的情况,见附录。最后得出的结论是:

  • 如果是循环变量递增或递减,不要单独对循环变量赋值,应该在它最后一次读取的时候使用嵌套的++--操作符。

  • 如果要与数组的长度作比较,应该事先把数组的length属性放入一个局部变量中,减少查询次数。

举例,假设arr是一个数组,最佳的遍历元素方式为:

for(var i=0, len = arr.length;i<len;i++){...}

或者,如果无所谓顺序的话:

for(var i=arr.length;i>0;i--){...}

局部变量和全局变量

局部变量的速度要比全局变量的访问速度更快,因为全局变量其实是全局对象的成员,而局部变量是放在函数的栈当中的。

不使用Eval

使用eval相当于在运行时再次调用解释引擎对内容进行运行,需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版(关于闭包的内容请参考函数式编程的有关内容)

减少对象查找

因为JavaScript的解释性,所以a.b.c.d.e,需要进行至少4次查询操作,先检查a再检查a中的b,再检查b中的c,如此往下。所以如果这样的表达式重复出现,只要可能,应该尽量少出现这样的表达式,可以利用局部变量,把它放入一个临时的地方进行查询。

这一点可以和循环结合起来,因为我们常常要根据字符串、数组的长度进行循环,而通常这个长度是不变的,比如每次查询a.length,就要额外进行一个操作,而预先把var
len=a.length
,则就少了一次查询。

字符串连接

如果是追加字符串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr

如果要连接多个字符串,应该少使用+=,如

s+=a;
s+=b;
s+=c;

应该写成

s+=a + b + c;

而如果是收集字符串,比如多次对同一个字符串进行+=操作的话,最好使用一个缓存。怎么用呢?使用JavaScript数组来收集,最后使用join方法连接起来,如下

var buf = new Array();
for(var i = 0; i < 100; i++){
buf.push(i.toString());
}
var all = buf.join("");

类型转换

类型转换是大家常犯的错误,因为JavaScript是动态类型语言,你不能指定变量的类型。

1.
把数字转换成字符串,应用"" + 1,虽然看起来比较丑一点,但事实上这个效率是最高的,性能上来说:

("" + ) > String() > .toString() > new String()

这条其实和下面的“直接量”有点类似,尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。

String()属于内部函数,所以速度很快,而.toString()要查询原型中的函数,所以速度逊色一些,new String()用于返回一个精确的副本。

2.
浮点数转换成整型,这个更容易出错,很多人喜欢使用parseInt(),其实parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,我们应该使用Math.floor()或者Math.round()

另外,和第二节的对象查找中的问题不一样,Math是内部对象,所以Math.floor()其实并没有多少查询方法和调用的时间,速度是最快的。

3.
对于自定义的对象,如果定义了toString()方法来进行类型转换的话,推荐显式调用toString(),因为内部的操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String,所以直接调用这个方法效率会更高

使用直接量

其实这个影响倒比较小,可以忽略。什么叫使用直接量,比如,JavaScript支持使用[param,param,param,...]来直接表达一个数组,以往我们都使用new Array(param,param,...),使用前者是引擎直接解释的,后者要调用一个Array内部构造器,所以要略微快一点点。

同样,var foo = {}的方式也比var foo = new Object();快,var reg = /../;要比var reg=new RegExp()快。

字符串遍历操作

对字符串进行循环操作,譬如替换、查找,应使用正则表达式,因为本身JavaScript的循环速度就比较慢,而正则表达式的操作是用C写成的语言的API,性能很好。

高级对象

自定义高级对象和DateRegExp对象在构造时都会消耗大量时间。如果可以复用,应采用缓存的方式。

DOM相关

插入HTML

很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低,如果需要直接插入HTML,可以找一个容器元素,比如指定一个div或者span,并设置他们的innerHTML来将自己的HTML代码插入到页面中。

对象查询

使用[""]查询要比.items()更快,这和前面的减少对象查找的思路是一样的,调用.items()增加了一次查询和函数的调用。

创建DOM节点

通常我们可能会使用字符串直接写HTML来创建节点,其实这样做

  1. 无法保证代码的有效性

  2. 字符串操作效率低

所以应该是用document.createElement()方法,而如果文档中存在现成的样板节点,应该是用cloneNode()方法,因为使用createElement()方法之后,你需要设置多次元素的属性,使用cloneNode()则可以减少属性的设置次数——同样如果需要创建很多元素,应该先准备一个样板节点。

定时器

如果针对的是不断运行的代码,不应该使用setTimeout,而应该是用setIntervalsetTimeout每次要重新设置一个定时器。

其他

脚本引擎

据我测试Microsoft的JScript的效率较Mozilla的Spidermonkey要差很多,无论是执行速度还是内存管理上,因为JScript现在基本也不更新了。但SpiderMonkey不能使用ActiveXObject

文件优化

文件优化也是一个很有效的手段,删除所有的空格和注释,把代码放入一行内,可以加快下载的速度,注意,是下载的速度而不是解析的速度,如果是本地,注释和空格并不会影响解释和执行速度。

总结

本文总结了我在JavaScript编程中所找到的提高JavaScript运行性能的一些方法,其实这些经验都基于几条原则:

  1. 直接拿手头现成的东西比较快,如局部变量比全局变量快,直接量比运行时构造对象快等等。

  2. 尽可能少地减少执行次数,比如先缓存需要多次查询的。

  3. 尽可能使用语言内置的功能,比如串链接。

  4. 尽可能使用系统提供的API,因为这些API是编译好的二进制代码,执行效率很高

同时,一些基本的算法上的优化,同样可以用在JavaScript中,比如运算结构的调整,这里就不再赘述了。但是由于JavaScript是解释型的,一般不会在运行时对字节码进行优化,所以这些优化仍然是很重要的。

当然,其实这里的一些技巧同样使用在其他的一些解释型语言中,大家也可以进行参考。

参考

附录1

由于是以前做过的测试,测试代码已经不全,我补充了一部分如下:

var print;

if(typeof document != "undefined" ){
    print = function(){
  document.write(arguments[0]);
 }
}else if(typeof WScript != "undefined" ){
    print = function(){
        WScript.Echo(arguments[0],arguments[1],arguments[2]);
    }
}

function empty(){
}

function benchmark(f){
    var i = 0;
    var start = (new Date()).getTime();

    while(i < pressure){
        f(i++);
    }
    var end = (new Date()).getTime();
    WScript.Echo(end-start);
}

/*
i=0
start = (new Date()).getTime();
while(i < 60000){
    c = [i,i,i,i,i,i,i,i,i,i];
    i++;
}
end = (new Date()).getTime();
WScript.Echo(end-start);
i=0
start = (new Date()).getTime();
while(i < 60000){
    c = new Array(i,i,i,i,i,i,i,i,i,i);
    i++;
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
*/

function internCast(i){
    return "" + i;
}

function StringCast(i){
    return String(i)
}
function newStringCast(i){
    return new String(i)
}
function toStringCast(i){
    return i.toString();
}
function ParseInt(){
    return parseInt(j);
}
function MathFloor(){
    return Math.floor(j);
}
function Floor(){
    return floor(j);
}
var pressure = 50000;
var a  = "";
var floor = Math.floor;
j = 123.123;
print("-------------\nString Conversion Test");
print("The empty:", benchmark(empty));
print("intern:", benchmark(internCast));
print("String:");
benchmark(StringCast);
print("new String:");
benchmark(newStringCast);
print("toString:");
benchmark(toStringCast);
print("-------------\nFloat to Int Conversion Test");
print("parseInt");
benchmark(ParseInt);
print("Math.floor");
benchmark(MathFloor);
print("floor")
benchmark(Floor);

function newObject(){
    return new Object();
}

function internObject(){
    return {};
}
print("------------\nliteral Test");
print("runtime new object", benchmark(newObject));
print("literal object", benchmark(internObject));

附录2

代码1:

    for(var i=0;i<100;i++){
        arr[i]=0;
    }


代码2:

    var i = 0;
    while(i < 100){
        arr[i++]=0;
    }


代码3:

    var i = 0;
    while(i < 100){
        arr[i]=0;
        i++;
    }


在firefox下测试这两段代码,结果是代码2优于代码1和3,而代码1一般优于代码3,有时会被代码3超过;而在IE
6.0下,测试压力较大的时候(如测试10000次以上)代码2和3则有时候优于代码1,有时候就会远远落后代码1,而在测试压力较小(如5000次),则代码2>代码3>代码1。

代码4:

    var i = 0;
    var a;
    while(i < 100){
        a = 0;
        i++;
    }


代码5:

    var a;
    for(var i=0;i<100;i++){
        a = 0;
    }

上面两段代码在Firefox和IE下测试结果都是性能接近的。

代码6:

    var a;
    var i=0;
    while(i<100){
        a=i;
        i++;
    }


代码7:

    var a;
    var i=0;
    while(i<100){
        a=i++;
    }


代码8:

    var a;
    for(var i=0;i<100;i++){
        a = i;
    }


代码9:

    var a;
    for(var i=0;i<100;){
        a = i++;
    }

这四段代码在Firefox下6和8的性能接近,7和9的性能接近,而6,
8 < 7, 9;

最后我们来看一下空循环

代码10:

    for(var i=0;i<100;i++){   }


代码11:

    var i;
    while(i<100){        i++;    }

最后的测试出现了神奇的结果,Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值,于是我没有放在一开始给大家看。

Come from: http://shiningray.cn/improve-javascript-performance.html

JavaScript 效率優化

最近開始重視 JavaScript 的效率問題,原因在於感到自己寫的網頁越來越不流暢,其中大量的計算跟無法避免的迴圈愈來愈多,加上 UI 介面跟動態效果的需要,使得瀏覽器的負荷過大,所以這是個需要重視的問題,這直接的影響網站名聲的好壞。

要如何作效率優化呢?因為 JavaScript 是直譯語言,無法透過編譯器加以優化,所以只能從撰寫方式下手。

下面有一個效率很差的例子:


for (var i=0; i<data.length; i++) {
document.getElementById("link").innerHTML+=data[i];
document.getElementById("link").hreh+="&"+data[i];
document.getElementById("link").title+=data[i]+",";
document.getElementById("link").className+=data[i]+" ";
document.getElementById("link").name+=data[i]+"_";
}


當中有幾個影響效率的問題:
  1. 過渡的使用 getElementById 搜尋 DOM 物件,尤其是在 for 迴圈中
  2. 大量的存取 length、innerHTML 等成員變數
  3. 多次的存取 data[i],這跟上一個差不多



這些問題的修改方法:

/*利用暫存變數作處理*/
var temp1='',temp2='',temp3='',temp4='',temp5='';
/*利用 l 紀錄 length 的值,以避免多次存取成員變數*/
for (var i=0,l=data.length; i<l; i++) {
/*利用 d 紀錄 data[i] 的值,以避免多次存取成員變數*/
d=data[i];
temp1+=d;
temp2+="&"+d;
temp3+=d+",";
temp4+=d+" ";
temp5+=d+"_";
}
/*利用暫存變數紀錄 DOM 物件*/
var link=document.getElementById("link");
link.innerHTML+=temp1;
link.hreh+=temp2;
link.title+=temp3;
link.className+=temp4;
link.name+=temp5;



實驗 1000 筆資料的結果:
第 1 個耗時:5625(msec)
第 2 個耗時:47(msec)
展示(demo)

參考來源:
JavaScript loop performance
随時innerHTMLに書き込んだ場合と一括して書き込んだ場合
innerHTMLとinnerText/textContentの速度比較
getElementByID、変数、withによる参照速度比較
シリアルサーチと正規表現の速度比較

Come from: http://jax-work-archive.blogspot.com/2008/05/javascript.html

前端开发规范

文档作者技术部前台开发组
2008年02月第二次修改

目录
更新日志: 3
第一部分 文档需求、说明及参与人员 4
第二部分 静态页面规范 5
一 静态页面基本规范 5
二 XHTML标准 5
三 图片规范 7
第三部分 CSS样式书写规范 9
一 样式命名规范 9
二 id命名规范 9
三 字体样式的命名 10
四 样式文件结构(样式表构成管理) 10
五 样式书写技巧 10
六 样式书写格式统一 14
七 过长的内容 14
第四部分 注释规范 15
一 HTML注释 15
二 CSS样式注释 15
第五部分 JavaScript脚本语言,Ajax等代码书写规范 16
一 命名规范 16
二 关于变量 16
三 注意事项 16
第六部分 其他重要说明 17
一 前台页面开发本地测试 17
第七部分 静态页面源文件备份规范 18
一项目开发源文件备份规范 18
二项目维护源文件备份规范 18
第八部分 附件 19
附件2:XHTML标准 19



更新日志:
。。。。

第一部分 文档需求、说明及参与人员

文档目的:为规范前台页面开发,便于前台开发成员页面维护,产出高质量的页面。

文档说明:本规范文档一经确认,前台开发所有人员必须按本文档规范进行前台页面开发。本文档如有不对或者不合适的地方请及时提出,经前台开发人员讨论后决定可以更改此文档。
特别说明:如有不能或不合适按本文档开发的项目或页面,请向主管人员做出说明;

参与人员: 王曼香,蒋楚,胡佳音,周锡波
版本说明:2008年2月版



第二部分 静态页面规范

一 静态页面基本规范
1.静态页面命名应根据项目文档中程序页面文件命名;例如程序页面文件名为index.aspx则静态页面的文件名应为index.html或index.shtml;
2.静态页面XHTML代码应采用自动缩进的形式编写,这样代码层次结构清晰;
3.根据项目文档选择页面编码格式,一般为UTF-8;非项目页面着统一采用UTF-8,特殊项目或有特定需求的按需求确定编码格式;
4.非特殊情况下必须把CSS外部链接放到页面的顶部(<head>… </ head>标签之间);
5.非特殊情况下必须把JS代码或外部链接放到页面的底部(</ body>标签之前);
6.书写链接地址时,必须避免重定向,例如:href="http://www.5fad.com/" ,即须在URL地址后面加上“/”;
7.在页面中尽量避免使用XHTML标签的样式属性,即style="…";
8.尽量减少页面的HTTP请求:
8.1.合并压缩的多个JS到一个文件中;
8.2.合并压缩的多个CSS到一个文件中, 能写成样式背景的图片,必须写在样式中;
9.尽量减少DIV的嵌套层数;
10.统一域名下的项目页面链接使用相对路径(例如:../top100/songtop.aspx),而不是绝对路径(例如:http://www.5fad.com/top100/songtop.aspx);
11. 给区块代码和套程序的循环的第一条数据加上注释(详见“注释”章节);

二 XHTML标准
1. 每个页面必须宣告使用哪一种DTD,目前非特殊情况下我们采用XHTML 1.0 Transitional DTD (一般为:<!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">),即DreamWeaver 8和cs3版本默认的DTD;
2.所有XHTML代码必须全部小写;
3. XHTML标签的属性值必须用双引号(””)括起来,并且一定要有值,不能简写缩写;
4. 双标记签都要有开始和结束标签,单标记标签的后面一定要加“/”,例如:<br />等,并且有正确的层次;
5.非特殊情况下要求表现和内容分离,代码中不要涉及任何表现的元素,例如:style、font等;
6.id属性,同一页面不要重复使用同一id;
7.给重要图片加上alt属性;给重要的元素和截断的元素加上title;
8.所有标签必须进行合理的嵌套,体现文档的结构,并有利于搜索引擎的查询;
9.使用正确的注释方法(详见“注释”章节);
10. 原则上,我们禁止用 <img width=? height=?> 来人为干预图片显示的尺寸,而且建议 <img> 标签中不要带上width 和height 两个属性,这是因为制作过程中,图片往往需要反复的修改,这样可以避免人为干预图片显示的尺寸,尽可能的发挥浏览器自身的功能;但是这样的一个副作用是当 网页还未加载图片时,不会留出图片的站位大小,可能会造成网页在加载过程中抖动(如果图片是插在一个固定大小的表格里的,不会有这个现象),尤其是当图片 的尺寸较大时,这种现象会很明显,所以当预料到这种会明显导致网页抖动的情况会发生时,请大家务必在最后给 <img>附上 width 和 height 属性。、
11.行距建议用百分比来定义,常用的两个行距的值是line-height: 150%.
12.表格:在排布表格之前,认真思考一个最佳的方案,表格的嵌套尽量控制在三层以内,禁止使用 <colspan> <rowspan>标记,也就是横纵合并单元格,这两个标记会带来许多麻烦。
※ 表格嵌套必须条理清晰一目了然,各区块独立性强,便于修改。主要框架使用绝对像素,以免产生变形。一个网页要尽量避免用整个一张大表格,所有的内容都嵌套 在这个大表格之内,因为浏览器在解释页面的元素时,是以表格为单位逐一显示,如果一张网页是嵌套在一个大表格之内,那么很可能造成的后果就是,当浏览者敲 入网址,他要先面对一片空白很长时间,然后所有的网页内容同时出现。如果必须这样做,请分段加入<tbody>标记,以便能够使这个大表格分 块显示。
13. flash的嵌入方法错误。<embed>最早是Netscape的私有标签,即使后来为IE所支持,但始终没有被W3C承认,在 XHTML1.0没有<embed>这个标签。W3C主张的是采用<object>标签。为了解决不同浏览器的兼容,有一个变通 的解决方法是2个标签都采用。完整的示例代码如下(flash背景为透明): <object classid="clsid:27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" width="300" height="100"> <param name="quality" value="high"> <param name="wmode" value="transparent"> <param name="SRC" value="test.swf"> <embed src="test.swf" wmode="transparent" quality="high" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="300" height="100"> </embed> </object>
关于flash是否符合标准,是一个存在争议的问题。更多说明:参考http://www.blueidea.com/tech/site/2004/1920.asp
14.在页面中碰到有单选框、复选框的时候要给单选框、复选框加上<lable></lable>标签;

15.XHTML标准标签和不赞成使用的标签,参见下表:
XHTML标准标签(如表):
标签类型 标签
结构 html,head,body,div,span
Meta信息 DOCTYPE,title,link,meta,style
文本 p,h1,h2,h3,h4,h5,h6,strong,em,abbr,acronym,address,bdo,blockquote,
cite,q,code,ins,del,dfn,kbd,pre,samp,var,br
链接 a,base
图片和对象 img,area,map,object,param
列表 ul,ol,li,dl,dt,dd
表格 table,tr,td,th,tbody,thead,tfoot,col,colgroup,caption
表单 form,input,textarea,select,option,optgroup,button,label,fieldset,legend
脚本 script,noscript
表现 b,i,tt,sub,sup,big,small,hr
其他 一般属性
… … … …

◎ XHTML的语法规范可参考附件2:《XHTML标准》

三 图片规范
1.图片统一放在images文件夹下面;
2.图片格式:图片只允许采用gif(256 128 64 32...)jpg(小于80比)压缩格式,要平衡图片质量与文件大小,不过分损失质量情况下尽量减小页面下载数据量。
一般的规律颜色层次变化少的图用gif,反之jpg. 图片切割严格按照像素内容边缘动刀。
3. 图片命名规范
3.1.名称全部用小写英文字母、数字、下划线的组合,其中不得包含汉字、空格和特殊字符;目录名应以英文、拼音为主。尽量用一些大家都能看懂的词汇。使得你自己和工作组的每一个成员能够方便的理解每一个文件的意义。
3.2.名称分为头尾两部分,用下划线隔开。
3.3.样例说明见下表:
图片分类 命名
广告、装饰图案等长方形的图片 ad_
标志性的图片 log_
在页面上位置不固定并且带有链接的小图片(按钮) btn_
导航图片 nav_
菜单图片 men_
装饰用的照片取名 pic_
不带链接表示标题的图片取名 tit_
小图标 ico_
背景图片 bg_
… … … …
依照此原则类推,名字要让旁人搞得懂。
尾部分用来表示图片的具体含义。
样例,大家应该能够一眼看明白图片的意义:
ad_sohu.gif、 ad_sina.gif、men_aboutus.gif、men_job.gif、tit_news.gif、log_police.gif、 log_national.gif、pic_people.jpg、pic_hill.jpg、ico_arrow.gif
注:
1.在开发页面的时候我们通常会遇到一些数据图片,比如:MV的缩略图,个性化头像等,这些图片统一使用001.gif,002.jpg,003.gif…依次命名,这些图片在项目正式上线后,应在服务器上删除,备份文件中仍需保留;
2.目前尽量不使用带透明度的PNG格式的图片;

第三部分 CSS样式书写规范

一 样式命名规范
1.class 命名采用小写英文字母、数字、下划线的组合,其中不得包含汉字、空格和特殊字符;。例如:.tit(标题),.com_u(评论人),.l01(某一块的左边)等,
2.样式名称以数字开头无效
3.部分命名解释约定(后期不断更新,以“附件1. 命名解释约定”的形式):
解释含义 命名
左边(右边) .l(.r)或.l... (.r...)
标题 .tit_...
按钮 .btn_...
文本框 .inp_...
下拉框 .sel_...
文本区域 .tex_...
数据图片 .pic_...
小图标 .ico_...
背景图片 .bg_...
… … … …
注:书写样式并不一定遵循本约定。

二 id命名规范
1.id命名采用英文单词、组合命名,字母应全部小写,多个单词应采用下划线分割。例如:#title(标题),#comment_user(评论人)等,杜绝使用拼音命名样式;
要求命名:
1.1.直观命名:用位置的词汇来对其命名。这种方法使得类以及id的名称如下面所示:
#top-panel,#horizontal-nav,#left-side ,#center-column,#right-col
1.2.结构化命名(结构,功能,内容):用页面区块名称的词汇来对其命名。这种方法使得类以及id的名称如下面所示:
#branding ,#main-nav ,#subnav ,#main-content ,#sidebar
1.3. 惯例:最常用类/id名称的示例列表:
header ,content ,nav ,sidebar ,footer
2.尽量不缩写,除非一看就明白的单词;
3.注意id名称以数字开头无效;

三 字体样式的命名
1.静态文字命名格式:f_颜色数值_字号(字体状态)
例如:.f_f30_12 (#ff3300颜色的12号静态文字)
.f_fd3360_12b (#fd3360颜色的12号粗体静态文字)
2.链接命名格式:l_颜色名称_字号(字体状态)_链接样式或者f_颜色数值_字号(字体状态)_链接样式
例如:.l_ff3300_12 (#ff3300颜色的12号无下划线链接文字)
.l_ff3300_12b(#ff3300颜色的12号粗体无下划线链接文字)
.l_ff3300_12b_u(#ff3300颜色的12号粗体有下划线链接文字)

四 样式文件结构(样式表构成管理)
1.首页一个样式(index.css)包括字体样式等;
2.头部底部样式(top.css);
3.内页样式
内页样式根据具体的项目、页面布局设计可以考虑一个或多个内页样式,一般考虑如下:
3.1.如果所有内页布局相近可考虑一个内页样式并且加上相应的注释(详见“注释”章节);
3.2.如果有几个内页布局相近可考虑这几个内页一个样式并且加上相应的注释(详见“注释”章节);
4.详细页一个样式(detail.css);

五 样式书写技巧
样式书写技巧主要优点是提高书写效率,节省样式代码,提高网页浏览速度。
1.CSS的缩写
Web 网站可用性的关键指标是速度,更确切地说,是页面能以多快的速度出现在访问者的浏览器窗口里。影响速度的因素有很多种,包括Web服务器的速度、访问者的 Internet连接情况,以及浏览器必须下载的文件大小。尽管你无法控制服务器和连接的速度,但是你可以控制构成网站Web页面的文件大小。

为 了让网站能够更快,Web的建设者都会按常规地压缩和优化网站上的每一个图像文件,这常常使得为了将文件的大小减少几个百分点而牺牲了图像的质量。由于 CSS样式表是纯文本文件,和图像相比相对较小,所以Web建设者很少考虑采取措施减少其CSS样式表文件的大小。但是,通过使用CSS缩写以及其他的一 些简单技巧,你可以在很大程度上减少样式表的大小。在我对自己样式表的一次非正式的特别测试中,我把文件的大小降低了大约25-50%。
1.1.CSS属性值的缩写:是一些专用的性质名,用来代替多个相关性质的集合。
通常可以缩写的属性margin,padding,border,font,color,background等等…
CSS 的缩写性质(shorthand property)是一些专用的性质名,用来代替多个相关性质的集合。例如,间隙性质(padding property)是顶部间隙(padding-top)、右侧间隙(padding-right)、底部间隙(padding-bottom)和左侧间 隙(padding-left)的缩写。

使用速写性质让你能够把多个性质/属性对(property/attribute pair)压缩进CSS样式表的一行代码里。例如,想一想下面的代码:
.sample1 {margin-top: 15px;margin-right: 20px;margin-bottom: 12px;margin-left: 24px;padding-top: 5px;padding-right: 10px;padding-bottom: 4px;padding-left: 8px;border-top-width: thin;border-top-style: solid;border-top-color: #000000;}
将它用一些缩写性质来替代就能够把代码减少为下面这样,两者的实际效果是完全一样的:
.sample1 {margin: 15px 20px 12px 24px;padding: 5px 10px 4px 8px;border-top: thin solid #000000;}
要注意,缩写性质还有多个属性,每一个(属性)都对应一个被组合进入缩写性质的常规性质。属性由空白隔开。
当属性是类似的值的时候,例如用于边框空白性质(margin property)的线性测量的时候,接在缩写性质之后的属性的顺序很重要。属性的次序是从顶部(顶部的边框空白)开始,然后围绕格子(box)按顺时针次序继续。
如果缩写性质的所有属性都是相同的,那么你可以简单地列出单个属性,然后在前面将它复制四遍。因此,下面的两个性质是相等的:
margin: 5px 5px 5px 5px;
margin: 5px;
类似的,你可以使用接在边框空白或者间隔性质之后的两个属性来代表顶部/底部和右侧/左侧属性对。
margin: 5px 10px 5px 10px;
margin: 5px 10px;
属性的顺序在它们是不相似的值的时候是不重要的。因此,边框颜色、边框风格和边框宽度等属性可以以任何顺序接在大纲性质(outline property)之后。忽略某个属性等同于从样式规则里忽略掉对应的常规性质。
下面是CSS缩写性质的列表以及它们所表示的常规性质。
background(背景):背景附件、背景颜色、背景图像、背景位置、背景重复
border(边框):边框颜色、边框风格、边框宽度
border-bottom(底部边框):底部边框颜色、底部边框样式、底部边框宽度
border-left(左侧边框):左侧边框颜色、左侧边框样式、左侧边框宽度
border-right(右侧边框):右侧边框颜色、右侧边框样式、右侧边框宽度
border-top(顶部边框):顶部边框颜色、顶部边框样式、顶部边框宽度
cue(声音提示):前提示、后提示
font(字体):字体、字号、字体样式、字体粗细、字体变体、线高度、字体大小调整、字体拉伸
list-style(列表样式):列表样式图像、列表样式位置、列表样式类型
margin(空白):顶部空白、右侧空白、底部空白、左侧空白
outline(大纲):大纲颜色、大纲样式、大纲宽度
padding(间隙):顶部间隙、右侧间隙、底部间隙、左侧间隙
pause(暂停):后暂停、前暂停

2.减少空格:减少CSS样式表大小的另一种方法是从文档里删掉大多数无用的空白。换句话说,将每条规则打破放进一行代码里,即把原来插入到代码里用来把每个性质/属性分割到不同行的换行符和缩进符删掉。
例如,下面的代码示例在内容上相同,但是第二个要精炼得多:
h1 {font-size: x-large;
font-weight: bold;
color: #FF0000;}

h1 {font-size: x-large; font-weight: bold; color: #F00}

3.合并具有相同属性和属性值的样式:就是把具有相同属性和属性值的样式的样式名称(样式选择符)写在一起,用逗号隔开(英文状态);再在后面写样式属性。
例如,下面的代码示例在内容上相同,但是第二个要精炼得多:
.nav1 {font-size:14px; font-weight: 700; color: #F00}
.nav2 {font-size:14px; font-weight: 700; color: #F00}
.nav3 {font-size:14px; font-weight: 700; color: #F00}
等同于:
.nav1, .nav2, .nav3 {font-size:14px; font-weight: 700; color: #F00}
4. 同名样式继承(本部分内容不做强行要求):就是一个页面调用一个或多个样式表时,在这个或者这些样式表中出现两个(或两个以上)样式名一样的样式。这时这 个样式的属性等于两个(或两个以上)同名样式的属性加起来。如果两个(或两个以上)样式同名样式的属性有重叠,则页面将以就近原则解析样式属性。
例如:
.ls1 {font-size: 9pt;text-align: left;width: 300px;}
.ls1{border: 5px solid #ffcc00}
.ls1{line-height:20px}
等同于:
.ls1 {font-size: 9pt;text-align: left;width: 300px; border: 5px solid #ffcc00; line-height r: 20px }

5.样式重用(本部分内容不做强行要求):就是再页面中,一个div容器同时调用两个(或两个以上)不同样式,那么这个div容器的样式属性等于两个(或两个以上)样式的属性加起来
例如:
Css:
.ls0{font-size: 9px;text-align: left;width: 300px;}
.ls1{border: 1px solid #ffcc00}
.ls2{border: 1px solid #ff3300}

Div:
<div class=”ls0 ls1”></div>
<div class=”ls0 ls2”></div>


6.样式的解析
6.1.例如以下样式:主要解决样式重名,区分同名样式在不同属性,使样式层次结构更加分明;
写法:
样式名+空格+样式名{…}
例如:
Css:
.top .left { font-size: 12px;text-align: left;width: 300px;}
Div:
<div class=”top”>
<div class=”left”>这里是left被解析为font-size: 9pt;text-align: left;width: 300px</div>
</div>
<div class=”bottom”>
<div class=”left”>这里是left不被解析</div>
</div>

这里left样式表示在且仅在top样式容器下被解析。

7.为了保证不同浏览器上字号保持一致,字号建议用像素px来定义,
8.字体要求:宋体(汉字)或Arial(字母,数字)
六 样式书写格式统一
每条样式写成一行;

七 过长的内容
经常会碰到一些歌曲名,歌手名内容过长,字打不下的情况,这时我们要写样式来限定字符长度;




第四部分 注释规范
发布版本应删除所有的注释:
一 HTML注释
正确的注释规范:<!--这里是注释-->感叹号后面2个横线,结束时2个横线;
不要在注释内容中使“--”
“--”只能发生在XHTML注释的开头和结束,也就是说,在内容中它们不再有效。例如下面的代码是错误的:
<!--这里是注释-----------这里是注释-->
<!-----------这里是注释-----------这里是注释----------->
用等号或者空格替换内部的虚线,这样是正确的:
<!--这里是注释============这里是注释-->

二 CSS样式注释

由于CSS+DIV制作页面,样式代码多,布局比较复杂,更便于页面后期的维护,更改,所以有必要在样式上加上注释。注释规法如下:
1.注释规范
/*这里是注释*/
例如:. news {…}/* 这里是高度自动撑 */


第五部分 JavaScript脚本语言,Ajax等代码书写规范

一 命名规范
1.变量命名必须为 小写英文字母;
另外常用临时变量不用这么复杂。如下表
变量类型 变量命名 备注
数字 Number i, j; l, m, n; p, q; x, y 主要用于循环变量和坐标,而且喜欢成对出现
字符串 String s
单个字符 Character c 虽然本质上还是字符串
对象 Object o
错误 Error e 常用于catch

2.类的命名使用骆驼命名规则,就是每个单词的第一个字母要大写,间隔字符为空,即没有间隔;
例如: Account, EventHandler;
3.简写单词不能使用大写名称作为变量名,例如:
getInnerHtml(),getXml(),XmlDocument;
4.方法的命令必须为动词或者是动词短语: obj.getSomeValue();

二 关于变量
1.变量必须在声明、初始化以后才能使用,即便是 NULL 类型;
2.变量不能产生歧义;
3.相关的变量集应该放在同一代码块中,非相关的变量集不应该放在同一代码块中;
4.变量应该尽量保持最小的生存周期(即可以用局部变量的地方不要用全局变量);

三 注意事项
1.每行代码结束必须叫分号(;);
2.if…else…必须有完整的语法结构,即if(…){…}else{…};

注:其他JS的规范可参加《JavaScript脚本语言规范》
第六部分 其他重要说明

一 前台页面开发本地测试
在 前台页面开发过程中及开发结束需经过多浏览器测试;目前必须测试的浏览器为:Internet Explorer 6、Internet Explorer 7、Mozilla Firefox 2、Opera 9、Safari;建议测试的浏览器Internet Explorer 5.5。
1. 固定内容测试
测试在多浏览器下显示的页面是否一致,是否在多浏览器下和设计稿保持一致;要求精确到一个像素;
2.脚本测试
测试在多浏览器下脚本代码功能的一致性;
3.不确定内容测试
比如网友留言,网友消息,主页日志等,就是版块内容由网友发布,没有固定的格式,宽高和元素等。这时我们就必须模拟各种网友发布的内容,并测试高度自动撑开,宽度扯开,等等。
4.宽屏或高分辨率显示器测试
最后一项测试是宽屏或高分辨率(目前认为横向1280px分辨率)显示器下测试,测试页面是否错位,位移,等等

第七部分 静态页面源文件备份规范
静态页面源文件中的JS和CSS分为开发版本和发布版本;
一项目开发源文件备份规范
备份人员在项目上线,备份静态页面时,需对静态页面文件夹html重命名,格式为:html_备份时间(时间格式yy-mm-dd ),例如再2007年09月01日对静态页面文件夹html的备份应命名为:html_07-09-01;
其中HTML目录下JS和CSS文件夹中的文件分别为开发版本的JS和CSS文件;HTML目录下JS_Release和CSS_Release目录下分别为发布版本的JS和CSS压缩文件
二项目维护源文件备份规范
◎在项目修改维护期间,备份前台页面源文件的等存放文件夹命名为:html_项目修改日期;例如:前台页面源文件07年9月22日修改,则命名为:html_07_09_22;,以确保新设计稿源文件备份不会覆盖上一版本的设计稿源文件;
◎将vss上的上一版本的静态页面备份目录放入old文件夹;
◎ 前台页面源文件最新的备份文件应与线上的页面保持一致;



第八部分 附件

附件2:XHTML标准
--------------------------------------------------------------------------------------
你可以通过开始书写严格的HTML代码来为你的XHML之路做准备

How To Get Ready For XHTML
如何开始XHTML呢?
XHTML is the next generation of HTML, but it will of course take some time before browsers and other software products are ready for it.
XHTML是HTML的下一代语言,当然,在新的浏览器和其他的相关软件产品出现之前,它将延迟一段时间才能普及。
In the meantime there are some important things you can do to prepare yourself for it. As you will learn from this tutorial, XHTML is not very different from HTML 4.01, so bringing your code up to 4.01 standards is a very good start. Our complete HTML 4.01 reference can help you with that.
其间,有一些重要的事情你能够去做来为它的学习做准备。就像你可以从这篇指南学到的东西一样,XHTML不是与HTML4.01有很多不同的,所以把你的代码改写程4.01标准是一种非常好的开始,我们完整的HTML4.01参考可以帮助你解决这个问题。
In addition, you should start NOW to write your HTML code in lowercase letters, and NEVER make the bad habit of skipping end tags like the </p>.
另外,现在你应该开始用小写字母来书写你的HTML代码了,并且永远不要再像以前那样有跳过像</p>这样的结尾标记的坏习惯了。
Happy coding!
陶醉于编码之中吧!

The Most Important Differences:
两者最主要的不同:
XHTML elements must be properly nested
XHTML documents must be well-formed
Tag names must be in lowercase
All XHTML elements must be closed
XHTML元素必须正确的嵌套
XHTML文档必须有良好的格式
标记的名字必须用小写字母
左右的XHTML元素都必须有关闭符

Elements Must Be Properly Nested
元素(标记)必须被正确的嵌套

In HTML some elements can be improperly nested within each other like this:
在HTML中,有些标记能够非正确的相互嵌套,就像这样:

<b><i>This text is bold and italic</b></i>

In XHTML all elements must be properly nested within each other like this:
在XHTML中所有的标记必须被正确的嵌套,像这样:
<b><i>This text is bold and italic</i></b>

Note: A common mistake in nested lists, is to forget that the inside list must be within an li element, like this:
注意:在列表嵌套的时候大家经常会犯一个错误,那就是忘记了插入的新的列表必须在一个<li>标记中,像这样
<ul>
<li>Coffee</li>
<li>Tea
<ul>
<li>Black tea</li>
<li>Green tea</li>
</ul>
<li>Milk</li>
</ul>

This is correct:
正确的写法
<ul>
<li>Coffee</li>
<li>Tea
<ul>
<li>Black tea</li>
<li>Green tea</li>
</ul>
</li>
<li>Milk</li>
</ul>

Notice that we have inserted a </li> tag after the </ul> tag in the "correct" code example.
在这段正确的代码示例中,注意到我们在</ul>之后加了一个</li>标记吗?

Documents Must Be Well-formed
文档必须格式良好
All XHTML elements must be nested within the <html> root element. All other elements can have sub (children) elements. Sub elements must be in pairs and correctly nested within their parent element. The basic document structure is:
所有的XHTML标记必须被嵌套使用在<html>根标记之中。所有其他的标记能有自己的子标记。位于父标记之内的子标记也必须成对的而且正确的嵌套使用。一个网页的基本结构是这样:

<html>
<head> ... </head>
<body> ... </body>
</html>

Tag Names Must Be In Lower Case
标记的名字必须用小写字母
This is because XHTML documents are XML applications. XML is case-sensitive. Tags like <br> and <BR> are interpreted as different tags.
这是因为XHTML文档是XML的应用程序,XML是大小写敏感的,像<br>和<BR>是会被认为为两种不共的标记的。
This is wrong:
错误的:
<BODY>
<P>This is a paragraph</P>
</BODY>

This is correct:
正确的

<body>
<p>This is a paragraph</p>
</body>

All XHTML Elements Must Be Closed
所有的XHTML标记都必须有关闭符
Non-empty elements must have an end tag.
非空的标记必须有一个关闭符。
This is wrong:
这是错误的:

<p>This is a paragraph
<p>This is another paragraph

This is correct:
这才是正确的

<p>This is a paragraph</p>
<p>This is another paragraph</p>

Empty Elements Must Also Be Closed
空标记也必须有关闭符
Empty elements must either have an end tag or the start tag must end with />.
空标记必须有关闭符或以开始符加上 />来结束
This is wrong:
错误的代码

This is a break<br>
Here comes a horizontal rule:<hr>
Here's an image <img src="happy.gif" alt="Happy face">

This is correct:
正确的:

This is a break<br />
Here comes a horizontal rule:<hr />
Here's an image <img src="happy.gif" alt="Happy face" />

IMPORTANT Compatibility Note:
关于兼容性的重要的注释:
To make your XHTML compatible with today's browsers, you should add an extra space before the "/" symbol like this: <br />, and this: <hr />.
为了使你的XHTML能够兼容现在的浏览器,你必须在/符号之前加一个特殊的空格,就像这样:<br /><hr />

Come from: http://www.cnblogs.com/yuzhongwusan/archive/2008/08/18/1270450.html

前端工程师应该关注什么

前端开发大众手册(包括工具、网址、经验等)

一直觉得前端开发缺个手册,这是个体力活。不过总得有人来干。

今天闲来无事,把一些工具(online和client的)、常用网址、以及经验总结等罗列出来和大家分享下。这个标题起地大了点,肯定会有很多地方没列到,包括类目的分法也可能考虑不周,所以还请大家积极补充指正,可以直接留言,也可以发邮件给我(sorrycc#gmail.com)。之所以加上“大众”两字,因为以下资源对于高手来说可能早就很熟悉了。

另外想提一句,工具是死的,好不好用得看你会不会用。比如Firefox、Fiddler等,除了显而易见的功能以外,都有一些小的技巧,掌握了可以让你事半功倍。

更新记录:

  • [20081025] 第一版

快捷导航:

另外还搞了个Firefox插件《前端开发工具集》,把资源整合到一个菜单下,方便查询。数据放在线上(Google AppEngine),速度应该会有保证,更新也会比较方便哈,见图。

在线工具集

常用Firefox插件

IE下的调试工具

  • Fiddle2 —— 非常强悍的一款http流查看工具,默认支持IE,其他浏览器可以设置将{Document}\Scripts\BrowserPAC.js设为代理进行使用。Firefox下可用上述"Fiddler 开关"进行快速切换。支持插件
  • IE Developer Toolbar —— 查看元素、禁用缓存、禁用CSS\JS、Outline元素、查看生成的源码等功能,IE8自带了一个加强版的。
  • Microsoft Script Debugger + Companion.JS —— 调试JS用,虽然报错还是有误差,但是我已经满足了。安装顺序是:Microsoft Script Debugger,Companion.JS,在"IE选项-高级"里取消禁用脚本调试
  • 多版本IE共存两种方案:
    • IE7/8 + IE Tester —— 大众型配置,可以基本满足日常需要。
    • IE6 + Internet Explorer Collection —— 在IE 6用户占绝对优势以及IE 6神奇bug满天飞的时代,我还是推荐这种方案,因为只有神奇的原装IE 6,才能抵挡运营神奇的问题。另外如果还有其他机器可供支配的话,建议再装个IE 8 + IE Tester,因为IE 8下的Developer Toolbar还是有很大改进的,调试起来会方便一些。
  • 以下三个软件相对不重要些:

参考手册

批处理工具

IDE及其他工具

Bookmarklet(右键另存)

开发者社区及权威网站

推荐订阅的博客和网站(排名不分先后)

Come from: http://www.chencheng.org/blog/2008/10/25/f2e-manual/

前端开发常用工具之开发工具篇

由于近年来RIA相关技术的兴起,WEB前端相关职位已经开始出现在越来越多的互联网公司中,而且越来越受到人们的重视。

现在做前端与前些年(PS设计出效果图,dreamweaver拉出界面,就可以交由后台程序员来套程序了)已经完全不同。由于浏览器运行环境以及RIA项目需求的特殊性,WEB前端所涉及的东西也越来越多,web标准、多浏览器兼容、程序性能、JS内存泄露、js/Ajax的调试...很多很多的问题摆到了WEB前端开发人员身上,因此如果能有一些相关的小工具来辅助我们,相信对于我们的项目开发效率和开发难度上都会有所改善。

尽管本人在前端开发方面还有太多太多的未知,但是在实际开发中也积累了不少各类各样的前端开发用的小工具,有些工具对于我们的项目来说甚至是事半功倍的。

废话不多说,我就分类来分享一下本人所用到一些工具,一来自己做个总结,二来希望能对其它做开发的朋友有所帮助。

这篇文章主要介绍关于开发方面的相关的工具。

1、Aptana

说到Aptana,我想每一位做前端技术的朋友都应该已经知道它的大名了。Aptana是一个基于Eclipse的致力于前端开发(JavaScript)的工具,其功能非常强大,而且是开源项目(Profession版收费)。

它具有以下特点:

1、JavaScript,HTML,CSS代码提示
2、代码结构(大纲):显示JavaScript,HTML和CSS的代码结构。 
3、代码语法错误提示。 
4、支持Aptana UI自定义和扩展。 
5、支持跨平台。 
6、支持流行AJAX框架的Code Assist功能:AFLAX,Dojo,JQuery,MochiKit,Prototype,Rico,script.aculo.us,Yahoo UI。 
7、JS代码在IE/FF下的断点调试。
8、插件丰富,如AIR、PHP、Ruby、Python等语言的开发插件。
9、内置其自行开发的Ajax应用服务器Aptana Jaxer。

对于纯前端的开发来讲,特别是js的开发来讲,aptana真的是不可多的的好工具。

2、Spket

Spket也是一个基于Eclipse构建起来的开源JS开发工具。可单独使用,也可作为eclipse插件使用。具有强大的JS、Ajax框架代码提示功能。特别是开发Jquery/ExtJS时,使用这个插件可以为开发带来极大的方便,免去记忆和查找大量复杂API之苦。特别推荐使用EXT的开发人员使用,这个工具应该是当前开发extjs的首推工具了,网上甚至有人称其为“Ext开发人员的紫色匕首”。

3、TopStyle

这个工具真是太有名了,我想每位做前端的人可能都要比我还要熟悉它,它是一款功能专注于CSS设计的辅助工具,功能十分丰富,包括:可以选取特定的浏览器或CSS阶层、内建的样式表检查器、内部的预览能力、以颜色标示的编辑器,以及样式预览等,具体可以到这里看介绍:[URL=]http://baike.baidu.com/view/662735.htm[/URL]。

4、JSA 优秀的JS代码压缩混淆工具

这个本来应该不算开发工具,但是不知归到哪里比较好,而且觉得这个对于最终代码发布来说还是一个很有用的工具,因此这里就推荐一下。JSA是用基于JAVA开发的js脚本压缩工具,文件后缀是jar格式的,因此需要你的电脑首先安装了JRE运行环境。该压缩工具采用的压缩算法,可以使你的JS代码达到最小,从而加速页面的加载速度。

5、PlayColor/飞鱼网页尺/SWFDecompiler

这里推荐的三款工具主要使用于界面和美工设计。

PlayColor是一块小巧的取色工具,在网页设计中,特别是参考一些设计资源的配色时,这个工具能为我们带来很大的方便。

飞鱼网页尺是一个用来测量屏幕中两点之间距离的小工具,这个在前端页面的设计制作中也用的比较多,当然可取代的工具也不少,有兴趣的大家可以网上找找。

SWFDecompiler:大名顶顶的Flash反编译工具,有时候我们再网上看到很多有用的Flash,但是由于没有源码,即没办法应用到我们的项目中,又不能学习研究其源码,有了这个工具,你的想法基本就可以实现了。

这几个工具这里就不给出下载地址了,baidu/google一下,N多可以下载的。

2009年5月2日星期六

阿门_百度百科

阿门[amen]:amen。希伯来语,意思是"真实的",与希伯来语"真理"一词有关。在公众祈祷结束后通常说"我同意"。如果某人不同意,他不必说"阿们"。"耶和华以色列的神是应当称颂的,从亘古直到永远。愿众民都说:阿们!"(诗篇106:48)。在以赛亚书65:16中神两次被描写成阿们的神("真实的神")。新约圣经中希腊字是希伯来语的一种音译,耶稣常用在这个词组中:如在约翰福音5:24,25中"我实实在在地告诉你们"。它还用作一种对耶稣的称呼。耶稣在启示录3:14中说:"那为阿们的,为诚信真实见证的,在神创造万物之上为元首的。"保罗说在耶稣里一切都是放心的:"神的应许,不论有多少,在基督都是是的。所以借着他也都是实在(实在:原文是阿们)的,叫神因我们得荣耀。那在基督里坚固我们和你们,并且膏我们的就是神"(哥林多后书1:20-21)。

谁都知道,“阿门”是全世界基督徒都听得懂的两个语词之一。(另一个是哈利路亚)。因为全世界任何语文的圣经中,都把这两个语词的译音保留下来。并在所有教会的祷告赞美中,很自然地直接应用。所以无论操什么方言语文的基督徒,在任何地方,只要开口呼出阿门(或哈利路亚),人就知道你是一个基督徒了。

“阿门”到底是什么意思呢?

在希伯来文中,“阿门”这个词原来的意思是指“靠得信住reliable,确定sure,真实true”或“愿事情是这样成就so let it be”。旧约圣经中,摩西写律法时,就已应用了“阿门”这个语词。当以色列民众对耶和华律法的要求作出群体性的响应时,就发出阿门为他们心中正面的承诺(民五:22;申廿七:15-26)。以后,先知耶利米,以及尼希米,向百姓重申律法时,也获得类同的反应(耶十一:5;尼五:3)。这种向祈祷中的誓言和律法的咒诅应以阿门的,是愿意负起所承诺的一切后果。旧约诗篇中,作者在祝祷或赞颂前后,加上阿们,是说明自己对祷文或颂词,具有确实的诚意。

新约希腊文的阿门,只是希伯来文的音译。初期教会的基督徒,在聚会中,有人领导祷告时,全众就沿用他们原先在犹太会堂所习惯的,向神诚心地应以阿门。自此,教会信徒都会在祷告后,应声阿们。是对所表达的祷告,真心诚意的向神献上。同时也表示愿意顺服天上神的权柄,以达成神在人身上的意愿。

圣经福音书的记载中,主耶稣常用阿门这个词,是在他开口教训人的时候。他常说:“我实在告诉你们。”这“实在”(verily/truely)原文就是阿门。当主耶稣向人说:“我阿门的告诉你”,他是带着神的权柄讲话。而这“我”字也就刻划出他自己就是神,在马太用了卅一次,马可用十三次,连最不用希伯来词语的路加,(路加福音中从不用“和散那、阿爸、以利、拉比”等这类希伯来词的)也用了六次。路加这样地应用,一定有他明显的用意。而约翰却更隆重地,每次都用两个相联的阿门。中文圣经就译为“我实实在在的告诉你们”(我阿门阿门的告诉你们),共用了廿五次。这样的用法,并非法利赛人和文士敢用的,因为那是带有权柄的。但主耶稣却清楚认识,神的应许将透过他必要应验。约翰在启示录中进一步的指明,这位主耶稣就是阿门(启三:14)。他不但在末世作真实的见证,而且他也正是那位宇宙的创造者。他就是神。正如先知以赛亚也宣布过,这位神确是“真实的神”(the God of Amen)。(赛六十五:16重复两次)。“阿门”乃是神的名称。

保罗书信及希伯来书中把阿门接在祷告和祝福之后,使写信的人为受信的会众(教会的弟兄姊妹)所献上的祝祷,更加肯定,更加有能力。原来祝祷赞颂是带领会众存有敬虔的心到神面前来崇拜。并且在心底里也发出“阿门”作感恩的响应。正为这缘故,保罗就强调,凡在公众祝祷感恩的语言,都必须是大家听得懂的(林前十四:16)。不然,别人怎样与你说阿门呢?为了响应主耶稣再来的应许和盼望,在启示录中也两次用阿门(启廿二:20,一:7),很确切地表达了愿主再临的心愿。

整本圣经对阿门的描述和应用,提醒我们基督徒以虔诚敬拜的心来到神的面前。很肯定的接受神的应许,很真实的诉说我们的心意。又以感恩祝祷的心灵,等候我们主耶稣基督的再临。

"阿门"的意思是"诚如所愿",阿门虽是基督徒在信经宣告、唱诗赞美和祷告中最常用的词,但其在圣经中的本义,似乎已经由于人本主义对教会的侵蚀而被逐渐遗忘了。对于大部分基要主义者和福音派人士来说,阿门的意思就是"我觉得好",这种主观式的以人为中心的态度,在过往的两个世纪中几乎主宰了整个的欧美教会,也直接影响到中国教会。

路斯德尼考察"阿门"一词指出,"阿门"经常是对上帝律法的赞同,在《启示录》中,是与基督见证人身份直接联系在一起的。"基督是阿门,因为他是'为诚信真实见证的',律法是由他宣布的,他也见证一切对律法的冒犯,任何人如果不是在基督的赎罪里接受死刑,他最终就会对那些冒犯律法的人执行死刑。"[7]丘顿在其神学力作中重申:"根据圣经神学,阿门的真正意思是很强烈的。实际上,阿门是一个誓言:说阿门,就是祈求圣约的咒诅临到自己(参考民5:21-22;申27:15-26;尼5:12-13)。作为我们的阿门,基督藉着他完全的顺服,救赎的献祭,在天庭持续的代祷(林后1:20;加3:13;来7:22-28;9:24-28;10:10-14),基督是圣约之应许的保证人。因此,在敬拜仪式中,当我们对上帝的圣言说阿门的时候,既是一个誓言,也是承认我们的救赎并不是依赖我们自己持守圣约,而是完完全全依赖耶稣基督对圣约完全的持守,他亲自代替我们处于圣约的规定之下,代替我们担当了圣约的咒诅。"[8]加尔文高度赞誉主祷文,以为"我们向上帝所当求,或可能求的,都包括在这一祷文里了,这祷文是亲自传授给我们的。基督是天父赐给我们的最好的老师,而且是我们惟有要听从的,因为基督是上帝的永恒智慧;……这一祷告是如此地齐备完全,所以凡有与它的异议不相符或没有关系的,就是不虔、无益,而不为上帝所许可的"[9]。因此,当我们祷告完毕,在说阿门的时候,我们要省察自己:有没有在耶稣基督里与上帝和好?有没有以上帝为本,并以他为乐?有没有以上帝启示的律法为标准?"愿上帝怜悯我们,赐福与我们,用脸光照我们"(诗67:1)。"阿门"是立约的誓言,是我们在上帝面前宣誓要遵行上帝的律法,实在是严肃的事情。我们的祷告虽是与我们在天上的父交通,有基督徒的喜乐和自由,但同时也是严肃的事情。

"当日摩西吩咐百姓说:…不坚守遵行这律法言语的,必受咒诅。百姓都要说:阿门"(申27:11-26)!"你的话是我脚前的灯,是我路上的光。你公义的典章,我曾起誓遵守,我必按誓而行。我甚是受苦,耶和华啊,求你照你的话将我救活。耶和华啊,求你悦纳我口中的赞美为供物,又将你的典章教训我。我的姓名常在危险之中,我却不忘记你的律法。恶人为我设下网罗,我却没有偏离你的训词。我以你的法度为永远的产业,因这是我心中所喜爱的。我的心专向你的律例,永远遵行,一直到底"(诗119:105-112);"你到上帝的殿要谨慎脚步。因为近前听,胜过愚昧人献祭,他们本不知道所作的是恶。你在上帝面前不可冒失开口,也不可心急发言。因为上帝在天上,你在地下,所以你的言语要寡少"

"阿门":Amen这一词据希伯来原文含有"坚定"的意思。在旧约,当人民领受王的命令的时候,说"阿门"表示:遵命(王上1:36);当人民受警戒的时候,说"阿门"表示:领受(民5:22;申27:15-26);当百姓听先知说预言时,说"阿门"表示:诚心所愿(耶28:1-3、5、6)。

因此,新约基督徒在称谢、颂赞、祝福、感谢、祷告神完了的时候,也都要说"阿门"表示:实实在在,但愿如此(罗1:25;9:5;林前14:15-16;加6:18;太6:9-13;林后1:20)。保罗说,神的应许,不论有多少,在基督都是是的,所以藉着他也都是实在的,(原文即"阿门",林后1:20)。是以主耶稣基督自称为诚信真实的,为"阿门" 的。(启3:14)

===========================

"祷告奉耶稣的名,阿们!"、"奇怪,你们基督徒为什么祷告结束时要说阿们呢?常听你们说阿们,到底是什么意思呢?"

这句话几乎是每次祷告词最后的"公式",基督徒也常说阿们,但阿们并不是结束的意思,原是希伯来语,原意为"是,上主"或"盼望是这样"。在旧约圣经中多被用来同意别人的话,不论是祈求或咒诅。它也是宗教礼仪的闭幕词,而在新约圣经中,"阿们"也用在礼仪或经文上,通常被译为"实实在在、确确实实"的意思,用在祷告结尾是请求上帝垂听我们的祷告。而耶稣常说:"我实实在在地告诉你们",所以这是个很慎重的字词。因此,当你们在祷告结尾时,别忘了诚心地求上帝垂听,好好地说:"奉耶稣的名,阿们!"

=====================================

Amen

阿门,M.D.

Mir Amen Dehlavi (1745~1806)

印度乌尔都语作家,原名密尔·阿曼,曾用笔名鲁

特夫发表诗作。出身于德里的穆斯林贵族。1781年迁居

加尔各答,晚年在威廉堡学院任编译员。他的成名作品

是《花园与春天》(1803),取材于民间故事和神话传说。

它写古罗马一皇帝外出私访高人,途中巧遇四个王子出

身的游方僧,各叙身世,由此穿插了寓言、神话和叙述

恋爱、冒险的十几个故事,想象丰富,情节曲折,文笔

生动。它反映了印度莫卧儿王朝时代的社会风貌,德里

的习俗,以及中古时期波斯和阿拉伯的社会制度、风土

人情和文化生活对印度的影响。在语言运用上,它把传

统的波斯语成语、谚语、典故、比喻与印度的民间语言

结合,成为德里标准语,开创了白话文时代,这部作品

至今仍被认为是19世纪乌尔都语的典范。

(李宗华)

阿门

中文意思就是“同心合一”

Come from: http://baike.baidu.com/view/64.htm

2009年4月29日星期三

Events/jQuery.Event

From jQuery JavaScript Library

jQuery's event system normalizes the event object according to W3C standards. The event object is guaranteed to be passed to the event handler (no checks for window.event required). Most properties from the original event are copied over to our wrapper object.

jQuery.Event

The object constructor is exposed and can be used when calling trigger.
You don't need to use the new operator, it is optional.

Check trigger's documentation to see how to combine it with your own event object.

Example:

Create a new jQuery.Event object without the new operator.

var e = jQuery.Event("click"); 


Example:

Create a new jQuery.Event object with the new operator.

var e = new jQuery.Event("click"); 


Attributes

event.type

Describes the nature of the event.

Return value: String
Example:

$("a").click(function(event) {
  alert(event.type);
});
Result:
 "click"


event.target

Contains the DOM element that issued the event.
This can be the element that registered for the event or a child of it.

Fixed where necessary (IE, Safari).

Use to implement event delegation.

Return value: Element
Example:

$("a[href=http://google.com]").click(function(event) {
  alert(event.target.href);
});
Result:
"http://google.com"


Example:

Implements a simple event delegation: The click handler is added to an unordered list, and the children of it's li children are hidden. Clicking one of the li children toggles (see toggle()) their children.

function handler(event) {
  var $target = $(event.target);
  if( $target.is("li") ) {
    $target.children().toggle();
  }
}
$("ul").click(handler).find("li > ").hide();


event.data

Contains the optional data passed to jQuery.fn.bind when the current executing handler was bound.

Return value: Anything
Example:

$("a").each(function(i) {
  $(this).bind('click', {index:i}, function(e){
     alert('my index is ' + e.data.index);
  });
});


event.relatedTarget

On mouse movement, contains the DOM element which the mouse was previously on when moving onto or off of an element.

Fixed where necessary.

Return value: Element
Example:

$("a").mouseout(function(event) {
  alert(event.relatedTarget);
});


event.currentTarget

The current DOM element within the event bubbling phase. This attribute will always be equal to the this of the function.

Return value: Element
Example:

$("p").click(function(event) {
  alert( event.currentTarget.nodeName );
});
Result:
"P"


event.pageX/Y

The pageX/Y property pair returns the mouse coordinates relative to the document.

Fixed where necessary (IE).

Return value: String
Example:

$("a").click(function(event) {
  alert("Current mouse position: " + event.pageX + ", " + event.pageY );
});
Result:
"Current mouse position: 130, 640"


event.result

Will contain the last value returned by an event handler (that wasn't undefined).

Return value: Anything
Example:

$("p").click(function(event) {
  return "hey"
});
$("p").click(function(event) {
  alert( event.result );
});
Result:
"hey"


event.timeStamp

The timestamp (in milliseconds) when the event was created.

Return value: Number
Example:

var last;
$("p").click(function(event) {
   if( last )
      alert( "time since last event " + event.timeStamp - last );
   last = event.timeStamp;
});


Methods

event.preventDefault()

Prevents the browser from executing the default action. Use the method isDefaultPrevented to know whether this method was ever called (on that event object).

Fixed where necessary (IE).

Return value: undefined

Example:

Stops the browser from changing the page to the href of any anchors.

$("a").click(function(event){
  event.preventDefault();
  // do something
});


event.isDefaultPrevented()

Returns whether event.preventDefault() was ever called on this event object.

Return value: true/false

Example:

Checks whether event.preventDefault() was called.

$("a").click(function(event){
  alert( event.isDefaultPrevented() );
  event.preventDefault();
  alert( event.isDefaultPrevented() );
});


event.stopPropagation()

Stops the bubbling of an event to parent elements, preventing any parent handlers from being notified of the event.

Note that this will not prevent other handlers on the same element from running. This method works for custom events triggered with trigger, as well.

Use the method event.isPropagationStopped() to know whether this method was ever called (on that event object).

Fixed where necessary (IE).

Return value: undefined

Example:

Prevents other event handlers from being called.

$("p").click(function(event){
  event.stopPropagation();
  // do something
});


event.isPropagationStopped()

Returns whether event.stopPropagation() was ever called on this event object.

Return value: true/false

Example:

Checks whether event.stopPropagation() was called.

$("p").click(function(event){
  alert( event.isPropagationStopped() );
  event.stopPropagation();
  alert( event.isPropagationStopped() );
});


event.stopImmediatePropagation()

Keeps the rest of the handlers from being executed.
This method also stops the bubbling by calling event.stopPropagation().

Use event.isImmediatePropagationStopped() to know whether this method was ever called (on that event object).

Return value: undefined

Example:

Prevents other event handlers from being called.

$("p").click(function(event){
  event.stopImmediatePropagation();
});
$("p").click(function(event){
  // This function won't be executed
});


event.isImmediatePropagationStopped()

Returns whether event.stopImmediatePropagation() was ever called on this event object.

Return value: true/false

Example:

Checks whether event.stopImmediatePropagation() was called.

$("p").click(function(event){
  alert( event.isImmediatePropagationStopped() );
  event.stopImmediatePropagation();
  alert( event.isImmediatePropagationStopped() );
});


Come from: http://docs.jquery.com/Events/jQuery.Event

JavaScript的事件代理比你想的要简单

如果你想进一步了解如何用JavaScript来为网页添加交互性的话,你也许已经听过JavaScript的事件代理(event delegation)了,并且会觉得只有那些牛逼烘烘的JavaScript程序员才会关心这样复杂的设计模式。事实上,如果你已经知道怎么样去添加JavaScript的事件处理器(event handler),实现事件代理也是件轻而易举的事情。

JavaScript事件是所有网页交互性的根基(我指的是真正的互动性,而不仅是那些CSS的下拉菜单)。在传统的事件处理中,你按照需要为每一个元素添加或者是删除事件处理器。然而,事件处理器将有可能导致内存泄露或者是性能下降——你用得越多这种风险就越大。JavaScript事件代理则是一种简单的技巧,通过它你可以把事件处理器添加到一个父级元素上,这样就避免了把事件处理器添加到多个子级元素上。

它是怎么运作的呢?

事件代理用到了两个在JavaSciprt事件中常被忽略的特性:事件冒泡以及目标元素。当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。对任何一个事件来说,其目标元素都是原始元素,在我们的这个例子中也就是按钮。目标元素它在我们的事件对象中以属性的形式出现。使用事件代理的话我们可以把事件处理器添加到一个元素上,等待事件从它的子级元素里冒泡上来,并且可以很方便地判断出这个事件是从哪个元素开始的。

这对我有什么好处呢?

想象一下现在我们有一个10列、100行的HTML表格,你希望在用户点击某一单元格的时候做点什么。比如说有一次我就需要让表格中的每一个单元格在被点击的时候变成可编辑状态。如果把事件处理器加到这1000个单元格将会产生一个很大的性能问题,并且有可能导致内存泄露甚至是浏览器的崩溃。相反地,使用事件代理的话,你只需要把一个事件处理器添加到table元素上就可以了,这个函数可以把点击事件给截下来,并且判断出是哪个单元格被点击了。

用代码写出来的话是什么样呢?

代码很简单,我们所要关心的只是如何检测目标元素而已。比方说我们有一个table元素,ID是“report”,我们为这个表格添加一个事件处理器以调用editCell函数。editCell函数需要判断出传到table来的事件的目标元素。考虑到我们要写的函数中可能会重复用到这一功能,所以我们把它单独放到一个名为getEventTarget的函数中:

function getEventTarget(e) {
  e = e || window.event;
  return e.target || e.srcElement;
}

e这个变量表示的是一个事件对象,我们只需要写一点点跨浏览器的代码来返回目标元素。在IE里目标元素放在srcElement属性中,而在其它浏览器里则是target属性。

接下来就是editCell函数了,这个函数调用到了getEventTarget函数。一旦我们得到了目标元素之后,剩下的事情就是看看它是否是我们所需要的那个元素了。

function editCell(e) {
  var target = getEventTarget(e);
  if(target.tagName.toLowerCase() === 'td') {
    // DO SOMETHING WITH THE CELL
  }
}

editCell函数中,我们通过检查目标元素标签名称的方法来确定它是否是一个表格的单元格。这种检查也许过于简单了点;如果它是这个目标元素单元格里的另一个元素呢?我们需要为代码做一点快速修改以便于其找出我们所需要的那个父级的td元素。如果说有些单元格不需要被编辑怎么办呢?此种情况下我们可以为那些不可编辑的单元格添加一个指定的样式名称,然后在把单元格变成可编辑状态之前先检查它是否不包含那个样式名称。选择总是多样化的,你只需找到适合你应用程序的那一种就可以了。

有哪些优点和缺点呢?

JavaScript事件代理带来的好处有:

  • 那些需要创建的以及驻留在内存中的事件处理器少了。这是很重要的一点,我们得到了性能上的提升,同时降低了崩溃的风险。
  • 在DOM更新后无须重新绑定事件处理器了。如果你的页面是动态生成的,比如说通过Ajax,你不需要再在元素被载入或者卸载的时候来添加或者删除事件处理器了。

潜在的问题也许并不那么明显,但是一旦你注意到这些问题,你就可以轻松地避免它们:

  • 你的事件管理代码有成为性能瓶颈的风险,所以尽量使它能够短小精悍。
  • 不是所有的事件都能冒泡的。blurfocusloadunload不能像其它事件一样冒泡。事实上blurfocus可以用事件捕获而非事件冒泡的方法获得(在非IE的浏览器中),不过我们改天再说这个吧。
  • 在管理鼠标事件的时候有些需要注意的地方。如果你的代码处理mousemove事件的话你遇上性能瓶颈的风险可就大了,因为mousemove事件触发得非常频繁。而mouseout则因为其怪异的表现而变得很难用事件代理来管理。

总结

已经有一些使用主流类库的事件代理示例出现了,比如说用jQueryPrototype以及Yahoo! UI的。你也可以找到那些不用任何类库的例子,比如说Usable Type blog上的这一个。

在你需要的时候,事件代理将成为你工具箱里一件得心应手的工具,而且它真的很容易实现。

Come from: http://www.yeeyan.com/articles/view/luosheng/24593

Javascript Dump Method

Javascript Dump Method

The Dump method is based on one of the tags available in Coldfusion ( <cfdump>) providing the ability to display simple and complex variables in a user friendly way that is perfect for debugging/inspecting data. There is no way to do this with javascript and often I had wanted a method to do this. This method will do just that allowing for an infinite amount of data nesting complete with color coding for different data types, the ability to show/hide the data's type (String/Number/Boolean/Object/Array/Function), expandable and collapsible tables/keys and cross browser support.

Click on the buttons bellow to see some examples in action, toggle the Show Data Types box to see javascript data typing in action (not possible in Coldfusion).

Thanks to John Wilson for providing the jQuery plugin.

Browser Support

Internet Explorer 6, Internet Explorer 7, Firefox 1.5, Opera 8, Safari 1.2 (Mac), Firefox (Mac) - all tested, should also work in most other browsers

Download

Click here to download the latest version (1.08)
Click here to download the latest jQuery plugin

Usage

dump(value, [showTypes])
@ param value (Any) value to dump
@ param [showTypes] (Boolean) optional to display each key/value's type
@ return (Void) returns nothing

Examples

dump(myObject, true); // opens a dump window displaying key/value types of myObject
dump([123,456,789], false); // opens a dump window not displaying key/value types of the array passed
dump('string value', false); // opens a dump window showing the string value

Come from: http://www.netgrow.com.au/files/javascript_dump.cfm

生如夏花之绚烂,死如秋叶之静美

逝去的绚丽
您的阳光对着我的心头的冬天微笑,
从来不怀疑它的春天的花朵。
---泰戈尔《飞鸟集》


鸟儿愿为一朵云。
云儿愿为一只鸟。
---泰戈尔《飞鸟集》
  


我的昼间之花,落下它那被遗忘的花瓣。
在黄昏中,这花成熟为一颗记忆的金果。
---泰戈尔《飞鸟集》


神希望我们酬答他,在于他送给我们的花朵,
而不在于太阳和土地。
---泰戈尔《飞鸟集》 
 


小花问道:“我要怎样地对你唱,怎样地崇拜你呢?太阳呀?”
太阳答道:“只要用你的纯洁的素朴的沉默。”
---泰戈尔《飞鸟集》


这寡独的黄昏,幕着雾与雨,
我在我的心的孤寂里,感觉到它的叹息。
---泰戈尔《飞鸟集》 


完全”为了对“不全”的爱,把自己装饰得美丽。
---泰戈尔《飞鸟集》


那些把灯背在背上的人,
把他们的影子投到了自己前面。
---泰戈尔《飞鸟集》


心是尖锐的,不是宽博的,
它执着在每一点上,却并不活动。
---泰戈尔《飞鸟集》
 


这面纱等候着在夜间卸去。
---泰戈尔《飞鸟集》


花儿低低的对看花的人说:
“少顾念我罢,我的朋友!
让我自己安静着,开放着,
你们的爱是我的烦扰。”
---冰心《繁星》


“你离我有多远呢,果实呀?”
“我藏在你心里呢,花呀。”
---泰戈尔《飞鸟集》


是为了它那不曾要求,不曾知道,
不曾记得的小小的需要。
---泰戈尔《飞鸟集》


小孩子! 你可以进我的园, 你不要摘我的花
看玫瑰的刺儿, 刺伤了你的手。
---冰心《繁星》


这个渴望是为了那个在黑夜里感觉得到,
在大白天里却看不见的人。
---泰戈尔《飞鸟集》


安静些吧,我的心,这些大树都是祈祷者呀。
---泰戈尔《飞鸟集》


打开门-- 让蓝天没有阻挡地泻进来,
让花的芬芳香进我的房间。
---泰戈尔《打开门》


幼花的蓓蕾开放了, 它叫道:
“亲爱的世界呀,请不要萎谢了。”
---泰戈尔《飞鸟集》


使生如夏花之绚烂,死如秋叶之静美。
---泰戈尔《飞鸟集》

2009年4月28日星期二

IE和Firefox浏览器CSS网页布局不同点

 我们讨论的主题CSS网页布局,最令大家头疼的问题就是浏览器兼容性,虽然webjx.com介绍过很多这方向的知识,但依然让很多开发人员晕头转向,今天的这篇文章,将列出css和javascript在IE和Firefox中二十三个不同点,希望对大家的学习有所帮助。

一、document.formName.item("itemName") 问题 
  问题说明:IE下,可以使用 document.formName.item("itemName") 或 document.formName.elements ["elementName"];Firefox下,只能使用document.formName.elements["elementName"]。
  解决方法:统一使用document.formName.elements["elementName"]。

二、集合类对象问题
  问题说明:IE下,可以使用 () 或 [] 获取集合类对象;Firefox下,只能使用 [ ]获取集合类对象。
解决方法:统一使用 [] 获取集合类对象。

三、自定义属性问题
  问题说明:IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用 getAttribute() 获取自定义属性;Firefox下,只能使用 getAttribute() 获取自定义属性。
  解决方法:统一通过 getAttribute() 获取自定义属性。

四、eval("idName")问题
  问题说明:IE下,可以使用 eval("idName") 或 getElementById("idName") 来取得 id 为 idName 的HTML对象;Firefox下,只能使用 getElementById("idName") 来取得 id 为 idName 的HTML对象。
  解决方法:统一用 getElementById("idName") 来取得 id 为 idName 的HTML对象。

五、变量名与某HTML对象ID相同的问题
  问题说明:IE下,HTML对象的ID可以作为 document 的下属对象变量名直接使用,Firefox下则不能;Firefox下,可以使用与HTML对象ID相同的变量名,IE下则不能。
  解决方法:使用 document.getElementById("idName") 代替 document.idName。最好不要取HTML对象ID相同的变量名,以减少错误;在声明变量时,一律加上var关键字,以避免歧义。

六、const问题
  问题说明:Firefox下,可以使用const关键字或var关键字来定义常量;IE下,只能使用var关键字来定义常量。
  解决方法:统一使用var关键字来定义常量。

七、input.type属性问题
  问题说明:IE下 input.type 属性为只读;但是Firefox下 input.type 属性为读写。
  解决办法:不修改 input.type 属性。如果必须要修改,可以先隐藏原来的input,然后在同样的位置再插入一个新的input元素。

八、window.event问题
  问题说明:window.event 只能在IE下运行,而不能在Firefox下运行,这是因为Firefox的event只能在事件发生的现场使用。
  解决方法:在事件发生的函数上加上event参数,在函数体内(假设形参为evt)使用 var myEvent = evt?evt:(window.event?window.event:null)
       示例:


<input type="button" onclick="doSomething(event)"/> 
<script language="javascript"> 
function doSomething(evt) { 
var myEvent = evt?evt:(window.event?window.event:null)
... 
}

九、event.x与event.y问题
  问题说明:IE下,even对象有x、y属性,但是没有pageX、pageY属性;Firefox下,even对象有pageX、pageY属性,但是没有x、y属性。
  解决方法:var myX = event.x ? event.x : event.pageX; var myY = event.y ? 
event.y:event.pageY;
  如果考虑第8条问题,就改用myEvent代替event即可。

十、event.srcElement问题
  问题说明:IE下,even对象有srcElement属性,但是没有target属性;Firefox下,even对象有target属性,但是没有srcElement属性。
  解决方法:使用srcObj = event.srcElement ? event.srcElement : event.target;
  如果考虑第8条问题,就改用myEvent代替event即可。

十一、window.location.href问题
  问题说明:IE或者Firefox2.0.x下,可以使用window.location或window.location.href;Firefox1.5.x下,只能使用window.location。
  解决方法:使用 window.location 来代替 window.location.href。当然也可以考虑使用 location.replace()方法。

十二、模态和非模态窗口问题
  问题说明:IE下,可以通过showModalDialog和showModelessDialog打开模态和非模态窗口;Firefox下则不能。
  解决方法:直接使用 window.open(pageURL,name,parameters) 方式打开新窗口。 
  如果需要将子窗口中的参数传递回父窗口,可以在子窗口中使用window.opener来访问父窗口。如果需要父窗口控制子窗口的话,使用var subWindow = window.open(pageURL,name,parameters); 来获得新开的窗口对象。

十三、frame和iframe问题
  以下面的frame为例: 
  <frame src="http://www.webjx.com/123.html" id="frameId" 
name="frameName" /> 
  (1)访问frame对象
  IE:使用window.frameId或者window.frameName来访问这个frame对象;
  Firefox:使用window.frameName来访问这个frame对象;
  解决方法:统一使用 window.document.getElementById("frameId") 来访问这个frame对象;
  (2)切换frame内容
  在IE和Firefox中都可以使用window.document.getElementById("frameId").src = "webjx.com.html"或window.frameName.location = "webjx.com.html"来切换frame的内容;
  如果需要将frame中的参数传回父窗口,可以在frame中使用parent关键字来访问父窗口。

十四、body载入问题
  问题说明:Firefox的body对象在body标签没有被浏览器完全读入之前就存在;而IE的body对象则必须在body标签被浏览器完全读入之后才存在。
  [注] 这个问题尚未实际验证,待验证后再来修改。
  [注] 经验证,IE6、Opera9以及FireFox2中不存在上述问题,单纯的JS脚本可以访问在脚本之前已经载入的所有对象和元素,即使这个元素还没有载入完成。

十五、事件委托方法
  问题说明:IE下,使用 document.body.onload = inject; 其中function inject()在这之前已被实现;在Firefox下,使用 document.body.onload = inject();
  解决方法:统一使用 document.body.onload=new Function(’inject()’); 或者 document.body.onload = function(){/* 这里是代码 */}
  [注意] Function和function的区别

十六、访问的父元素的区别
  问题说明:在IE下,使用 obj.parentElement 或 obj.parentNode 访问obj的父结点;在firefox下,使用 obj.parentNode 访问obj的父结点。
  解决方法:因为firefox与IE都支持DOM,因此统一使用obj.parentNode 来访问obj的父结点。

十七、cursor:hand VS cursor:pointer
  问题说明:firefox不支持hand,但ie支持pointer ,两者都是手形指示。
  解决方法:统一使用pointer。

十八、innerText的问题.
  问题说明:innerText在IE中能正常工作,但是innerText在FireFox中却不行。
  解决方法:在非IE浏览器中使用textContent代替innerText。
  示例:


if(navigator.appName.indexOf("Explorer") >-1){ 
document.getElementById(’element’).innerText = "my text"; 
} else{ 
document.getElementById(’element’).textContent = "my text"; 


  [注] innerHTML 同时被ie、firefox等浏览器支持,其他的,如outerHTML等只被ie支持,最好不用。

十九、对象宽高赋值问题
  问题说明:FireFox中类似 obj.style.height = imgObj.height 的语句无效。
  解决方法:统一使用 obj.style.height = imgObj.height + ’px’;

二十、Table操作问题
  问题说明:ie、firefox以及其它浏览器对于 table 标签的操作都各不相同,在ie中不允许对table和tr的innerHTML赋值,使用js增加一个tr时,使用appendChild方法也不管用。
  解决方法:


//向table追加一个空行: 
var row = otable.insertRow(-1); 
var cell = document.createElement("td"); 
cell.innerHTML = ""; 
cell.className = "XXXX"; 
row.appendChild(cell); 

  [注] 由于俺很少使用JS直接操作表格,这个问题没有遇见过。建议使用JS框架集来操作table,如JQuery。

二一、ul和ol列表缩进问题
  消除ul、ol等列表的缩进时,样式应写成:list-style:none;margin:0px;padding:0px; 
  其中margin属性对IE有效,padding属性对FireFox有效。← 此句表述有误,详细见↓
  [注] 这个问题尚未实际验证,待验证后再来修改。
  [注] 经验证,在IE中,设置margin:0px可以去除列表的上下左右缩进、空白以及列表编号或圆点,设置padding对样式没有影响;在Firefox 中,设置margin:0px仅仅可以去除上下的空白,设置padding:0px后仅仅可以去掉左右缩进,还必须设置list-style:none才 能去除列表编号或圆点。也就是说,在IE中仅仅设置margin:0px即可达到最终效果,而在Firefox中必须同时设置margin:0px、 padding:0px以及list-style:none三项才能达到最终效果。

二二、CSS透明问题
  IE:filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=60)。 
  FF:opacity:0.6。
  [注] 最好两个都写,并将opacity属性放在下面。

二三、CSS圆角问题
  IE:ie7以下版本不支持圆角。
  FF: -moz-border-radius:4px,或者-moz-border-radius-topleft:4px;-moz-border- radius-topright:4px;-moz-border-radius-bottomleft:4px;-moz-border- radius- bottomright:4px;。
  [注] 圆角问题是CSS中的经典问题,建议使用JQuery框架集来设置圆角,让这些复杂的问题留给别人去想吧。

  关于CSS中的问题实在太多了,甚至同样的CSS定义在不同的页面标准中的显示效果都是不一样的。更多的知识请参考webjx.com的文章。一个合乎发展的建议是,页面采用标准DHTML标准 编写,较少使用table,CSS定义尽量依照标准DOM,同时兼顾IE、Firefox、Opera等主流浏览器。BTW,很多情况下,FF和 Opera的CSS解释标准更贴近CSS标准,也更具有规范性。

Come from: http://www.zdwx.com/Knowledge/Art-4194-9.html