走过平凡人生、留下平凡足迹 注册 | 登陆
浏览模式: 标准 | 列表全部文章

jQuery中文入门指南

中文版译者:Keel

此文以实例为基础一步步说明了jQuery的工作方式。现以中文翻译(添加我的补充说明)如下。如有相关意见或建议请麻烦到我的 BLOG 写个回复或者 EMAIL 告知。

英文原版:http://jquery.bassistance.de/jquery-getting-started.html ,感谢原文作者 Jörn Zaefferer

本文发布已征求原作者同意。

另外我认为在学习过程中,有两个API文档你要打开随时查看:

» 阅读全文

Tags: ajax, jquery

JQuery 事件

JQuery中的事件(转帖) bind(type,data,fn) 为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数。这个事件处理函数会接收到一个事件对象,可以通过它来阻止(浏览器)默认的行为。如果既想取消默认的行为,又想阻止事件起泡,这个事件处理函数必须返回false。 多数情况下,可以把事件处理器函数定义为匿名函数(见示例一)。在不可能定义匿名函数的情况下,可以传递一个可选的数据对象作为第二个参数(而事件处理器函数则作为第三个参数),见示例二。 返回值:jQuery 参数: type(String)一个事件类型 data(Object)(可选)作为event.data传递给事件处理器函数的额外数据 fn(Function)绑定到事件上的函数 例子: $("p").bind("click", function(){ alert( $(this).text() ); }); 之前:

Hello

结果: alert("Hello") 例子:为事件对象传递一些额外的数据 function handler(event) { alert(event.data.foo); } $("p").bind("click", {foo: "bar"}, handler) 结果: alert("bar") 例子:通过返回false来取消默认的行为并阻止事件起泡 $("form").bind("submit", function() { return false; }) 例子:通过使用preventDefault方法来仅仅取消默认的动作 $("form").bind("submit", function() { return false; }) 例子:通过使用 stopPropagation 方法只阻止事件起泡 $("form").bind("submit", function(event){ event.stopPropagation(); }); blur() 触发每一个匹配元素的blur事件。这个函数会调用执行绑定到blur事件的所有函数。 注意:这个函数不会调用相应元素的blur方法!如果需要通过代码来使一个元素获得焦点,必须使用DOM方法,例如:$("#myinput")[0].blur(); 返回值:jQuery 例子: $("p").blur(); 之前:

Hello

结果: alert('Hello'); blur(fn) 在每一个匹配元素的blur事件中绑定一个处理函数返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的blur事件的一个方法例子: $("p").blur( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

change(fn) 在每一个匹配元素的change事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的change事件的一个方法 例子: $("p").change( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

click() 触发每一个匹配元素的click事件。这个函数会调用执行绑定到click事件的所有函数 返回值:jQuery 例子: $("p").click(); 之前:

Hello

结果: alert('Hello'); click( fn ) 在每一个匹配元素的click事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的click事件的一个方法 例子: $("p").click( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

dblclick( fn ) 在每一个匹配元素的dblclick事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的dblclick事件的一个方法 例子: $("p").dblclick( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

error( fn ) 在每一个匹配元素的error事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的error事件的一个方法 例子: $("p").error( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

focus() 触发每一个匹配元素的focus事件。这个函数会调用执行绑定到focus事件的所有函数。 注意:这个函数不会调用相应元素的focus方法!如果需要通过代码来使一个元素获得焦点,必须使用DOM方法,例如:$("#myinput")[0].focus(); 返回值:jQuery 例子: $("p").focus(); 之前:

Hello

结果: alert('Hello'); focus( fn ) 在每一个匹配元素的focus事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的focus事件的一个方法 例子: $("p").focus( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

hover( over, out ) 一个模仿悬停事件(鼠标移动到一个对象上面,及移出这个对象)的方法。这是一个自定义的方法,它为频繁使用的任务提供了一种“保持在其中”的状态。 当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数。当鼠标移出这个元素时,会触发指定的第二个函数。而且,会伴随着对鼠标是否仍然处在特定元素中的检测(例如,处在div中的图像),如果是,则会继续保持“悬念”状态,而不触发移出事件(修正了使用mouseout事件的一个常见错误)。 返回值:jQuery 参数: over(Function)鼠标移动元素上触发的函数 out(Function)鼠标移出元素出发的函数 例子: $("p").hover(function(){ $(this).addClass("hover"); },function(){ $(this).removeClass("hover"); }); keydown( fn ) 在每一个匹配元素的keydown事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)在每一个匹配元素的keydown事件中绑定的处理函数 例子: $("p").keydown( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

keypress( fn ) 在每一个匹配元素的keypress事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)在每一个匹配元素的keypress事件中绑定的处理函数 例子: $("p").keypress( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

keyup( fn ) 在每一个匹配元素的keyup事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)在每一个匹配元素的keyup事件中绑定的处理函数 例子: $("p").keyup( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

load( fn ) 在每一个匹配元素的load事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的load事件的一个方法 例子: $("p").load( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

mousedown( fn ) 在每一个匹配元素的mousedown事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的mousedown事件的一个方法 例子: $("p").mousedown( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

mousemove( fn ) 在每一个匹配元素的mousemove事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的mousemove事件的一个方法 例子: $("p").mousemove( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

mouseout( fn ) 在每一个匹配元素的mouseout事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的mouseout事件的一个方法 例子: $("p").mouseout( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

mouseover( fn ) 在每一个匹配元素的mouseover事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的mouseover事件的一个方法 例子: $("p").mouseover( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

mouseup( fn ) 在每一个匹配元素的mouseup事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的mouseup事件的一个方法 例子: $("p").mouseup( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

one( type, data, fn ) 为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数。在每个对象上,这个事件处理函数只会被执行一次。其他规则与bind()函数相同。这个事件处理函数会接收到一个事件对象,可以通过它来阻止(浏览器)默认的行为。如果既想取消默认的行为,又想阻止事件起泡,这个事件处理函数必须返回 false。 多数情况下,可以把事件处理器函数定义为匿名函数(见示例一)。在不可能定义匿名函数的情况下,可以传递一个可选的数据对象作为第二个参数(而事件处理器函数则作为第三个参数),见示例二。 返回值:jQuery 参数: type(String)一个事件类型 data(Object)(可选)作为event.data传递给事件处理器函数的额外数据 fn(Function)绑定到事件上的函数 例子: $("p").one("click", function(){ alert( $(this).text() ); }); 之前:

Hello

结果: alert("Hello") ready(fn) 当DOM载入就绪可以查询及操纵时绑定一个要执行的函数。这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度。 简单地说,这个方法纯粹是对向window.load事件注册事件的替代方法。通过使用这个方法,可以在DOM载入就绪能够读取并操纵时立即调用你所绑定的函数,而99.99%的JavaScript函数都需要在那一刻执行。 请确保在元素的onload事件中没有注册函数,否则不会触发$(document).ready()事件。 可以在同一个页面中无限次地使用$(document).ready()事件。其中注册的函数会按照(代码中的)先后顺序依次执行。 返回值:jQuery 参数: fn(Function)当DOM准备好的时候执行的方法 例子: $(document).ready(function(){ Your code here... }); 例子: Uses both the shortcut for $(document).ready() and the argument to write failsafe jQuery code using the $ alias, without relying on the global alias. jQuery(function($) { // Your code using failsafe $ alias here... }); resize( fn ) 在每一个匹配元素的resize事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的resize事件的一个方法 例子: $("p").resize( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

scroll( fn ) 在每一个匹配元素的scroll事件中绑定一个处理函数 返回值:jQuery 参数: fn(Function)绑定到每一个匹配元素的scroll事件的一个方法 例子: $("p").scroll( function() { alert("Hello"); } ); 之前:

Hello

结果:

Hello

select() 触发每一个匹配元素的select事件。这个函数会调用执行绑定到select事件的所有函数,并且在匹配元素上调用浏览器的默认动作。这个默认的动作可以通过从绑定到select事件的方法中返回false避免。 返回值:jQuery 例子: $("p").select(); 之前:

Hello

结果: alert('Hello');

Tags: ajax, jquery

jQuery学习十五天 (11-15)

15 Days of jQuery(Day 11) --- 使用不苛刻的javascript代码实现多文件上传

 

好几个月以前,当我在追逐互联网上AJAX热潮的时候,我在 FiftyFourEleven网站上发现了一篇使用创新的javascript代码实现当时正在困扰我的“ 单文件元素实现多文件上传”的文章。

所以当我想写作《15天漫游jQuery》的时候,我第一个想到的就是用jQuery实现这个功能。

接触易用性狂热爱好者

几天前当我检查网站记录的时候,发现了一条遗漏的文章trackback。跟过去看的时候我发现我的两篇jQuery文章被作者引用来证明他为什么讨厌javascript。

根据这个人的说法,任何工具或技术如果没有将易用性放在第一位都将成为垃圾。

尽管我很不同意这位仁兄一杆子打死的态度,但他还是让我对这篇详细教程有所留意。当我在编写一个简单网页效果的时候,我会尽量小心谨慎的处理。这样如果网站访客们决定关闭javascript代码执行功能的时候,他们仍然可以正常使用网站的功能。

关于第一价值的两个教程

  • 使用一个文件输入元素实现多文件上传,并让整个交互过程流畅舒适。
  • 让多文件上传更加人性化,但要避免以牺牲可用性为代价。关键在于使用不苛刻的javascript代码制作多文件输入区域。

演示

  • 只有一个文件输入元素,但添加了jQuery和其他代码实现较为亲近用户的多文件上传功能。

演示一地址

  • 在页面(x)html代码中使用了多个文件输入元素,但通过jQuery调整为与第一个演示类似的显示页面效果。优点是代码是不苛刻的。。。即使关闭了javascript执行,用户也能上传多个文件。

演示二地址

解释

单文件输入框

jQuery的$(document).ready() 函数的工作有两个:

在文档下载量最大的时候创建一个div元素。 查找文件上传框(假设这里只有一个),然后给它附上一个onChange事件。

$("input[@type=file]").change(function(){
doIt(this, fileMax);
});

doit()函数(简单又好记,呵呵~)检查是否达到了最大文件数量限制,如果不是,它会隐藏当前文件输入框,在父div里添加一个新的文件输入框,将输入框内的文件名使用id “files_list”作为标记,在最后添加一个“删除”按钮。

在DOM树中导航,我使用jQuery的parent()函数,然后用remove()函数移除元素。我还使用了append()和prepend()函数分别添加文件名和新的输入框。

两个关键点

- 最大文件上传数量设定:

var fileMax = 3;

- 输入框必须有适当的定位措施:

<input type="file" class="upload" name="fileX[]"/>

这样弄以后输入框可疑由访问者决定添加还是删除,没有任何关于id或名称的操作。当这个窗体代码发送给服务器端脚本的时候,相关信息就已经被存放在了一个数组中了。

多文件输入框

首先,文件允许上传的数量由页面中的文件输入框的数量决定。其次,你仍然需要通过某种方法为每个输入框接收到的内容用一个数组存放。

<input type="file" class="upload" name="fileX[]"/>

第二个演示跟前面的比起来最大的不同在于,我遍历了每个文件输入框并在其内容有改动时执行doit()函数。通过遍历每一个输入框,我可以为我的代码添加有用的额外信息:输入框内容在“堆栈”中的顺序。

换句话说,当这段代码执行时,它会特别指定第一个输入框,或者第二个,抑或第三个。

代码见下:

$("input[@type=file]:nthoftype("+
n+")")

jQuery的灵活性允许我们使用CSS和XPath描述语句定位指定的元素位置。

你会发现当一个文件被选中时,文件输入框都会被文件名称覆盖。点击文件名就可以选择其他不同的文件。


 

15 Days of jQuery(Day 12) --- jQuery Lightbox (插件)

 

Cody Lindley 移植的第一版“ Thickbox”让我第一次感受到了jQuery的魅力。后来他又做了一些 代码升级以修复若干跨浏览器的兼容性问题。

一些需要注意的地方

$(document).ready 取代了TB_init() 函数,作用是在每个包含对象名“thickbox”的链接上附加一个onClick事件。

function TB_init(){
$("a.thickbox").click(function(){
var t = this.title || this.innerHTML || this.href;
TB_show(t,this.href);
this.blur();
return false;
});

当这些链接被点击时,TB_show()函数就将执行。

$("body")
.append("<div id='TB_overlay'></div><div id='TB_window'></div>");
$("#TB_overlay").click(TB_remove);
$(window).resize(TB_position);
$(window).scroll(TB_position);
$("#TB_overlay").show();
$("body").append("<div id='TB_load'><div id='TB_loadContent'><img
src='images/circle_animation.gif' /></div></div>");

如你所见,在文档body元素前添加了两个div元素。换句话说,这两个div元素将被添加在页面html代码的body关闭元素前。

覆盖的div将使用一个特定的包含不透明外表的CSS文件指定表现。TB_window的代码用来通过AHAH在页面中放置一张图片或者加入另一个页面。$(window).resize 和$(window).scroll 告诉jQuery在用户重新调整窗口大小或者拖动页面翻页的时候执行TB_position函数。这是保证Thickbox始终保持在窗口中心部位的手段。

接下来,Cody查询url的后缀。

var urlString = /.jpg|.jpeg|.png|.gif|.html|.htm|.php|.cfm|.asp|.aspx|.jsp|.jst|.rb|.txt/g;
var urlType = url.match(urlString);
if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif'){//code to show images

如果这是一个图片文件,则jQuery的append函数会添加html代码到适当位置。

$("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img
id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"'
alt='"+caption+"'/></a>"
+ "<div id='TB_caption'>"+caption+"</div><div
id='TB_closeWindow'><a href='#' id='TB_closeWindowButton'>close</a></div>");
$("#TB_closeWindowButton").click(TB_remove);

另外,远程文件将使用jQuery的load()函数导入。

$("#TB_ajaxContent").load(url, function(){

 

15 Days of jQuery(Day 13) --- jQuery 表格

 

一位叫Klaus的朋友编写了一个小插件, 用jQuery实现可用性极佳的javascript表格

设置好正确的(x)HTML 和CSS后,你可以像下面那样创建表格:

$.tabs(”container”); first tab on by default 如果你像在默认位置“上方”再添加一个表格: $.tabs(”container”, 2); second tab on

Klaus这里 示例,你可以看看最终效果。

我的改版

我稍微修改了Klaus的代码,添加了一个简单的表单用来生成表格的表头

用法:

非常简单。只需要输入每个表格的表头(最多5个),然后点击表单下方的按钮。下一个页面将生成结果HTML代码,你可以复制然后粘贴到文件中。

你还需要 下载Klaus网站的CSS文件,做些你自己的修改,当然还要上传jQuery框架库到你的服务器上。

这里是表格生成器的地址。


 

15 Days of jQuery(Day 14) --- Javascript 工具提示

 

Cody Lindley ,Thickbox的作者,日前发布了 jTip - jQuery 工具提示。

我对其中很多想法和思路拍案叫绝。我知道你已经看过很多类似的工具提示代码了。但是,Cody 的方法已经在我的工作中显露出了闪光点。

当我检查HTML代码时,我发现了一个大问题,可访问性。链接在javascript关闭的时候无法工作。我并不是倾向于一定要实现全面的可访问性,只是在这里我认为可以有其他更具亲和力的方式实现相同的功能。

尤其是,我个人不喜欢那种为了可访问性而去牺牲可用性来实现在提示框上链接另一个页面链接的方法。我喜欢这个提示框 - 不是对Cody不尊重,只是在我这里我“需要”它能够在各种情况下工作。

今天我要提供给大家的是Cody的工具提示代码的小小修改。如果你不是Cody工具提示的爱好者的话,我的改版对你来说也许不是很在意。但如果你喜欢他的作品同时希望它可以在javascript关闭的时候照常工作,这个也许是你需要的。

我的改动

让我产生修改想法的,是他的代码在Yahoo上的应用。我不喜欢他使用的代码:

<a href="yahoo.htm?width=175&amp;link=http://www.yahoo.com"
name="Before You Click..."
id="yahooCopy"
class="jTip">Go To Yahoo</a>

所以我重写了他的部分代码,成了现在这个样子:

<a href="http://www.yahoo.com"
rel="yahoo.htm?width=175&link=yahoo&name=Before%20
%20You%20Click..."
id="yahooCopy"
class="jTip">
Go To Yahoo</a>

我的示例

改进:HTML标准校验

我的代码可以通过w3.org的测试

改进:命名

在我修改Cody的代码的时候我发现他使用了一个用来存储链接名称的叫做“title”的变量名,这会导致一些混淆。

我标出了这个命名问题,即使我认为这不过是个小小的失误。

改进:可用性

使用我的代码,你可以让每个提示框都含有真实链接地址到另一个文档,不管内部的还是外部的。或者你只是想要那个提示框,不想关心可用性,你同样可以让链接部分留空。

选择权在你。

感谢

Cody提供了伟大的代码,帮助我节省了大量的时间和精力。我的修改只是对原有代码的轻微“调整”,希望朋友们喜欢。

Tags: ajax, javascript, php, jquery

jQuery学习十五天 (6-10)

 

15 Days of jQuery(Day 6) --- 更安全的Contact Forms,不带CAPTCHA

 

这次的教程内容贴近我擅长的技术方向:安全的contact forms。

就像我在前一篇教程中提到的那样,一个最普通的contact forms可以帮助访客同你进行通信来往而不需要暴露你的电子邮件地址给那些可恶的垃圾邮件制造者们。

但如果spammer们已经盯上你,没有什么比一个不安全的contact foms更糟糕的了。想象一下你的网络空间提供商发给你一封措辞强烈的电子邮件,通知说:他们发现你的网站发送了大批量的性药广告以及其他垃圾邮件,另外,直到你停止这种行为之前,你的网站都将处于离线状态–谢谢!

那么,今天我要在这篇教程里告诉大家的是一种在任何contact forms上添加一个额外安全层的简单方法-即使你没有使用我提供的超级安全、超级灵活的Ultimate Form Mail。

当前状况

你意识到spammer们已经通过远程探测技术发现了你的contact forms的弱点,而你希望他们走开。

难点

你不想使用CAPTCHA(Completely Automated Public Turing Test to Tell Computers and Humans Apart),因为你明白,让你的访客先去阅读那些歪七扭八的字母数字才能发送消息只能抑制他们想要互动的欲望,而不是促进它。(数字验证的缺陷)

关键点:你希望那些坏家伙们堵车到天黑,同时希望那些好孩子们一条大道通罗马。

解决方案

你将学会在页面加载的时候使用jQuery来给你的contact forms添加一些隐藏的标签信息。当窗体信息被提交到服务器端的时候,你可以用一些简单的php代码实现如下的步骤:

隐藏的标签被识别出来 隐藏标签的信息与你的网站访客下载到浏览器上的cookie里的某项标志相一致 隐藏标签的有效时间还未过期 换句话说,你的访客们只有在一段有限的时间内才可以填写窗体并进行发送。如果一个spammer尝试通过远程调用来提交窗体信息到你的服务器,他们将会发现自己踢到了一块又厚又硬的铁板,不付出点代价休想通过。

我将要告诉你的这种方法是从一位非常聪明的同事Chris Shiflett提供的蓝本基础上修改而成的。他是位专业的安全专家,对php程序员经常遇到的安全问题了如指掌(我怎么感觉他又要忍不住提到他的Ultimate Form Mail 了~~汗)。

教程

基于上次那篇《斑马线表格轻松制作》的反响良好,我决定再次制作一次类似的“手把手图文教程”。虽然要花费些时间,但很值得这么做。

手把手教程

DEMO

源代码

银弹?1)

银弹是软件领域的说法,意为解决一切问题的方法。这个来源于欧洲的传说,说是只有银弹可以消灭狼人。

“那么,现在我的窗体就是100%安全的,可以假设任何免费的cntact forms程序,然后高枕无忧了?”

呃。。。非也。

这种安全模式基于一个关键的假定:Spammer们总是会拿软柿子捏,浪费时间去解决一个狡猾的对手对他们来说就是浪费金钱。

现在, 好好听着,我的朋友们:

这个技术,尽管相当健壮,但仍然不是解决目前脆弱的窗体处理程序问题的灵丹妙药。

我的这些安全建议的目的是为了让spammer们知难而退。小偷们入室盗窃之前总会进行仔细踩点,他们只对那些可以用最小代价获取最大利益的房间感兴趣。

换句话说,如果在他们动手之前有99%的机会挡住他们的试探,而且实现起来相当容易,为什么不试一试呢?这才是此项技术要实现的目标。

但这还是治标不治本,不能解决所有问题。


 

15 Days of jQuery(Day 7) --- 样式表切换

 

我第一次看到样式表切换器是在A List Apart或者Simple Bits,那是两个设计师最应该去的网站。

从那以后,我找到了很多可以让访客通过鼠标点击某个地方切换样式表的方法。但最近我要写一篇如何 使用jQuery编写简单代码实现它的教程。

我将向你们逐步解说整个的过程,不仅仅因为要展示jQuery代码的简介,同时也要揭示jQuery库中的若干高级特性。

首先,代码

$(document).ready(function()
{
$('.styleswitch').click(function()
{
switchStylestyle(this.getAttribute("rel"));
return false;
});
var c = readCookie('style');
if (c) switchStylestyle(c);
});
function switchStylestyle(styleName)
{
$('link[@rel*=style]').each(function(i)
{
this.disabled = true;
if (this.getAttribute('title') == styleName) this.disabled = false;
});
createCookie('style', styleName, 365);
}

其他这里没有提到的部分是你将在后面看到的创建和读取cookie的函数。

熟悉的开篇

$(document).ready(function()
{
$('.styleswitch').click(function()

告诉jQuery“以最快的速度查找所有包含对象名‘styleswitch’的元素,并在他们被鼠标点击时执行一个函数”。

看起来不错。当鼠标点击预先指定的元素时,switchStylestyle函数将被调用。从现在开始是重点。

这句话什么意思?

第一次看到这句代码的时候我的脑子有些卡壳:

$('link[@rel*=style]').each(function(i) {

在互联网上搜索了一下后我空手而归。最后不得不找到了jQuery的作者John Resig,向他咨询。

他直接给了我一个jQuery网站的页面地址,里面讲解了若干jQuery提供的高级特性(xpath),可以用来查找并操作页面中的若干元素。

如果你看过这些东西你就能明白上面那句神秘的代码的含义是告诉jQuery“查找所有带rel属性并且属性值字符串中包含‘style’的link链接元素”。

嗯?

让我们看看如何编写包含一个主样式表,两个备用样式表的页面:

<link rel="stylesheet" type="text/css" href="styles1.css" title="styles1" media="screen" />
<link rel="alternate stylesheet" type="text/css" href="styles2.css" title="styles2" media="screen" />
<link rel="alternate stylesheet" type="text/css" href="styles3.css" title="styles3" media="screen" />

我们可以看到所有样式表都含有一个包含‘style’字串的rel属性。

所以结果一目了然,jQuery轻松定位了页面中的样式表链接。

下一步?

each()函数将遍历所有这些样式表链接,并执行下一行中的代码:

this.disabled = true;
if (this.getAttribute('title') == styleName) this.disabled = false;

“首先禁用所有的样式表链接,然后开启任何title属性值与switchStylestyle函数传递过来的字串相同的样式表”

一把抓啊,不过很有效。

现在我们需要保证的是那些样式表存在并且有效。

完整代码和演示

既然 Kelvin Luck已经编写了这些代码,我就不在这里重复了。

DEMO

我相信Kelvin的灵感是从 这个网站那里得到的,我们正好可以看看使用其他工具实现这个功能是否要比jQuery更加复杂冗长。


 

15 Days of jQuery(Day 8) --- 使用Javascript(jQuery)实现圆角边框

 

当我看到这些实现圆角边框的HTML源代码的时候,我发现这很适合用来写一篇jQuery教程–使用wrap()、prepend()、append() 函数。

这里是原先的HTML代码,我们将从这里开始:

<div class="dialog"> 
  <div class="hd"> 
    <div class="c"></div> 
  </div> 
  <div class="bd"> 
    <div class="c"> 
      <div class="s"> 
        <main 
          content goes here > 
      </div> 
    </div> 
  </div> 
  <div class="ft"> 
    <div class="c"></div> 
  </div> 
</div>

现在我们怎么使用jQuery来精简这段代码呢?

首先,我们需要一个“钩子”,一个特殊的HTML元素,或者一个id,或者一个对象名–来告诉jQuery处理的目标。

现在我们改成了这个样子:

<div class=“roundbox”> <main content goes here > </div> 下一步,我们使用jQuery来将剩下的代码添加进去:

$(document).ready(function(){ $("div.roundbox") .wrap('<div 
class="dialog">'+ 
'<div class="bd">'+ 
'<div class="c">'+ 
'<div class="s">'+ 
'</div>'+ 
'</div>'+ 
'</div>'+ 
'</div>'); 
});

其他Div标记去哪里了?

仔细观察代码,你就会发现它们都跑到了js代码里面,在wrap函数执行时它们将嵌套在“钩子Div”的内部。

细心的观众会发现我漏掉了部分代码。这是因为jQuery中的wrap()函数要求div标签必须严格对称嵌套才能工作。

具体的,我去掉了下面两个部分:

<div class="hd"><div class="c"></div></div> 
<div class="ft"><div class="c"></div></div>

添加和预置一体化

下一步我们将会通过prepend和append函数将这两段代码添加进带有dialog对象名的div标记内部,并且使用“连锁”方法。

$('div.dialog').prepend('<div class="hd">'+ 
'<div class="c"></div>'+ 
'</div>')
.append('<div class="ft">'+ 
'<div class="c"></div>'+ 
'</div>');

示例及代码

我已经在网上放置了一个演示页面供大家查看。建议你看一下页面的源代码,体会jQuery给页面代码带来的清爽和便捷。

这些代码来自 Schillmania的一篇文章,个人推荐大家下载包含点缀图片的zip打包,非常精美。

不使用图片的圆角边框

有很多方法可以实现圆角边框–有些方法甚至不需要图片。

在jQuery的网站上有一个用来制作无图圆角边框的插件。虽然不是适合所有人(或者说所有程序),但也值得学习。

看看它的漂亮代码吧(使用时):

$(document).bind("load", function(){ 
$("#box1").corner()
});

 

15 Days of jQuery(Day 9) --- 快速和略显粗劣的AJAX视频教程

 

今天我的想法有点改变。近段时间以来我一直考虑注册一个YouTube帐号来上传一些教程录像,现在我终于做出了决定并上传了一个。在这里我将手把手的向大家演示为你的网站添加一些AJAX基本应用的方法。

录像很短,因为YouTube对上传影片的长度有限制(10分钟以内)。当然由于制作仓促,错误在所难免。比如在某个地方我称CGI为“服务器端脚本”,而更准确的说法应该是“服务器端语言”。

这是AJAX,还是AHAH,抑或AXAH?

你将看到的东西其实更接近AHAH而不是纯粹的AJAX。

有什么区别么?AJAX中的“X”代表着XML。但更多时候人们喜欢使用简单的文本或者javascript代码或者单独文件而不是那种复杂冗长的XML。对此有篇文章有详细论述:AJAX vs. AHAH

至于AXAH。。。 Cody Lindley的文章可以解释一切。对AJAX的一些工作理念有兴趣的读者可以看一下。

教程录像

这个页面上有我提供的演示。


 

15 Days of jQuery(Day 10) --- 使用jQuery Javascript 库实现“即点即改”的AJAX化

 

以前我在Quirksmode网站见过这种代码,后来又在24 Ways网站看到了一个更具Web 2.0风格的方案。这次我将为大家展示两种使用jQuery实现相同功能(甚至更好)的方法。

目标

一个用AJAX(或AHAH)技术设计的页面,访问者无需离开就可以在看到的(x)HTML 页面上编辑内容。

方案

点击需要编辑的文本,变幻出一个带有保存和取消按钮的textarea。修改的部分将通过AHAH传送至服务器端的一个PHP脚本文件,用来更新数据库(MySQL或普通文件)。

演示

AJAX式即点即改演示

在这第一个演示中,我使用了一个id为“editinplace”的div元素。当鼠标划过这里时,背景颜色将变成浅黄色。点击文本将启动一些DOM操作,div元素被一个textarea元素取代–内中包含原先的文本。

点击保存按钮将向服务器端的PHP脚本文件发送新的HTML内容,并重新输出收到的新文本内容(通过 $_POST)。

在真实应用环境下,你还应当添加一个安全性检测,然后才能更新数据库并返回更新后的页面内容,同事告知jQuery执行成功的信息。

但在这个例子中,所有的修改都是成功的,发送给PHP脚本的信息将原封不动的返回到jQuery代码,显示到一个普通的警告窗口里。

解释

开头部分说了很多次了,如果你不想使用jQuery提供的document.ready函数,尽可以选择你自己中意的init()函数。

$(document).ready(function(){
setClickable();
});

页面上第一个被执行的就是这个setClickable()函数。它的任务就是做以下内容:

查找包含id为“editinplace”的div元素,然后告诉jQuery在这些div被点击时执行某些操作。

function setClickable() {
$('#editInPlace').click(function() {

读取div内部的HTML代码的任务将交给jQuery的html()函数来完成。这些HTML将会额外添加若干代码以组成textarea里的保存和取消按钮。

var textarea = '<div><textarea rows="10" cols="60">'+$(this).html()+'</textarea>';
var button = '<div><input type="button" value="SAVE"
class="saveButton" /> OR <input type="button" value="CANCEL"
class="cancelButton" /></div></div>';
var revert = $(this).html();

同样还是这些在div内部找到的HTML代码将会赋值给一个叫做“revert”的变量。这个变量将用来在取消按钮被按下的事件中输出原始文本。

var revert = $(this).html();

jQuery的DOM函数“after”用来将新生的textarea HTML代码放置在我们指定的div元素后。我在后面紧跟着连锁上了一个remove()方法 来移除div元素以节省代码。

$(this).after(textarea+button).remove();

在使用jQuery的时候,我通过对象名来定位保存和取消按钮对象。我指示jQuery在任一按钮按下时触发最后一个函数“saveChanges”。我告诉了jQuery在div元素被点击时做什么事情,但我没有在最后加上分号因为我希望在这个div操作语句后面连锁其他方法。

$('.saveButton').click(function(){saveChanges(this, false);});
$('.cancelButton').click(function(){saveChanges(this, revert);});
})

我再连锁了一个简单的mouseover和mouseout事件,告诉jQuery在鼠标指针掠过我们指定的div元素(id=editInPlace)的时候添加和移除一个对象。

.mouseover(function() {
$(this).addClass("editable");
})
.mouseout(function() {
$(this).removeClass("editable");
});
};//end of function setClickable

函数“saveChanges”将以按钮对象做为第一个参数,而cancel参数则取两种值,false或者保存在revert变量中的html代码内容。

function saveChanges(obj, cancel) {

如果cancel为假,则函数将保存更改并使用html格式发送给服务器端的php脚本。我在这里使用了jQuery内置的一个DOM函数实现对textarea内容的提取操作:parent()和siblings()。

if(!cancel) {
var t = $(obj).parent().siblings(0).val();

DOM基础超出了本系列教程的范围,但在这个应用中我只是告诉了jQuery“对象(保存按钮)有一个父元素(div)。。。去找到它。那个元素拥有一个或多个DOM树同级对象。。。我只想找到其中的第一个。然后提取那个对象的所有内容。”

(稍等。。。如果你对DOM风格的代码不是很熟悉的话,前面我的注释可能并不好理解。我还是建议你之前google一下“DOM javascript”或者其他相关的信息。)

这些html赋值给了t变量,现在要通过POST方法把它发送给test2.php。

$.post("test2.php",{
content: t
},function(txt){
alert( txt);
});
}

如果cancel有一个值,那么必然是保存在revert变量中的原始html内容。所以,在这个时候我希望变量t变为原始html内容。

else {
var t = cancel;
}

下一步是通过jQuery提供的DOM函数放置一个新的div元素,id为“editInPlace”,在这之后包含了textarea元素。。。然后删除掉这个div元素。

$(obj).parent().parent().after('<div id="editInPlace">'+t+'</div>').remove()

在果壳中,这将告诉jQuery“在DOM树中上跃两次。将HTML代码附在到达位置的对象之后,然后移除那个对象。”

最后,我们再次调用setClickable函数并关闭saveChange()函数。重调setClickable()函数的含义是重新设置onMouseover,onMouseout,和onClick事件到初始状态。

setClickable();
}

第二个示例

第二个方法非常类似但也有点复杂。

示例二

没有用到庞大的单独div元素,这个示例将每个段落p标签变换成单独的可编辑区域。

这里的难度在于你如何在向服务器端脚本发送数据时指定正确的段落p标签。

在这里我通过为每个p标签编号并将这个编号一同发送给服务器端的php脚本的方式解决了问题。你会在alert窗口中看到php脚本是如何“知道”哪个p标签里的内容被修改的。

已知的问题

现实的应用中,你在使用类似的功能时首先需要验证更改的内容的合法性,然后才能将数据发送到服务器端。显然在这里我们刻意把这些内容忽略掉了。

Tags: ajax, javascript, php, jquery

jQuery学习十五天 (1-5)

  • 15 Days of jQuery(Day 0)---JQuery - What, Why, When, Where, Who

what

jQuery是一个了不起的javascript库,它可以是我们用很少的几句代码就可以创建出漂亮的页面效果。从网站的方面说,这使得javascript更加有趣。

如果你这样想:“孩子,我需要另外一个javascript库,就好比我I need another hole in my head”那么加入这个俱乐部吧。这正是我第一次遇到的时候所想的。

我已经用过了Moo.fx, Scriptaculous, TW-SACK, 和 Prototype. 我曾参与了RICO, Yahoo YUI和其他一些库的开发。

没有了PHPjavascript和我一点也不亲近了。但是我还是尽全力保持头脑清醒,并尽量保持用AJAX去思考。

所以当我遇到jQuery的时候我想:“还需要另外一个javascript库吗?不了,谢谢…”

why

为什么我改变我我对jQuery的看法,以及为什么你要考虑去使用它? 很简单,只要你看一眼过使用jQuery的页面你就会发现它是如此的简单易用.只用很少的几行,就能表现出很优雅的效果. 有一天当我突然看到一些用jQuery写的代码时我一下子豁然开朗了. 早茶的过程中,我例行公务的去翻阅我的订阅,去看每日必看的设计博客的时候我看到了一个用jQuery写的javascript的例子.事实证明,这些代码还是有些和浏览器关联的bug,不过这些概念还是我以前从来没有见过的.

还有那些代码…

代码看起来很简单看起来不像我以前见过的.但也不无道理.

我开始通读文档,并且惊奇的发现用一点点代码竟然能做这么多事情.

when

你应当在你需要的时候使用jQuery.

给你一个小型的库文件 DOM强大的控制能力 不费吹灰之力的工作,和少许的努力.

或者

快速的通过AJAX 没有大量无用的代码 和一些基本的动画效果

但是

如果你需要超级花式效果,动画,拖放,和超级平稳动画,那么你可能想使用Prototype.他是一个有大量动画效果的类库.

where

你可以jQuery的官方网站下载到他的源代码(10K).

who

jQuery was created by John Resig.

» 阅读全文

Tags: ajax, javascript, php, jquery

Ajax基础教程 2.1 - XMLHttpRequest对象概述

在使用XMLHttpRequest对象发送请求和处理响应之前,必须先用JavaScript创建一个XMLHttpRequest对象。由于XMLHttpRequest不是一个W3C标准,所以可以采用多种方法使用JavaScript来创建XMLHttpRequest的实例。Internet ExplorerXMLHttpRequest实现为一个ActiveX对象,其他浏览器(如FirefoxSafariOpera)把它实现为一个本地JavaScript对象。由于存在这些差别,JavaScript代码中必须包含有关的逻辑,从而使用ActiveX技术或者使用本地JavaScript对象技术来创建XMLHttpRequest的一个实例。

» 阅读全文

Ajax基础教程 1.4 - 可用性问题

前面谈到的都是用户的期望,除此以外,可用性也不能不提。Ajax方法相当新,还没有多少成熟的最佳实践。不过,标准Web设计原则还是适用的。随着时间推移,当越来越多的人开始尝试这种方法时,就会发现可能存在哪些限制,并建立适当的指导原则。也就是说,你应该让用户来指导你。根据在应用中使用Ajax的方式,你可能会动态地改变页面中的某些部分,习惯于整个浏览器刷新的用户可能不会注意到与以前相比有什么变化。这个问题引出了一些新的特性,如37signals所普及的黄褪技术(Yellow Fade TechniqueYFT),这个特性已经用在Ajax的招牌应用Basecamp中了。

基本说来,YFT是指“取页面中有变化的部分,并置为黄色”。假设你的应用原本没有大量使用黄色,用户就很可能会注意到这种改变。过一段时间后,再让黄色逐渐褪色,直到恢复为原来的背景色。当然,你也可以选用你喜欢的其他颜色,只要能把用户的注意力吸引到有变化的部分。

可能YTF并不适用于你的应用,你也可以选择用一种不那么张扬但仍很有用的方式来提醒用户。Gmail在右上角显示了一个闪动的红色“Loading”加载记号,提醒用户正在获取数据(见图1-7)。

1-7 Gmail的“Loading”记号

究竟要使用YFT还是其他类似的技术,实际上取决于你的用户。最简单的方法是让一组用户代表来进行测试。可以通过文字问卷,也可以使用基于Web的原型应用,这要看你处在设计过程的哪个阶段。但是不论如何测试,在真正采用Ajax完成复杂设计之前都应该取得一些用户反馈。

而且要从小处做起。在刚开始使用Ajax时,不应该马上就创建一个可调整列的动态门户网站,而是应该先试着处理客户端验证,逐步转向服务器端。待有所了解后,可以再尝试更动态的使用,如填写一个下拉列表,或者设置某些默认文本。

不管你要如何应用Ajax,记住别做稀奇古怪的事情。我们知道,这不算是一个学术性的建议。不过,目前这方面还没有严格的规则。先听听用户怎么说,部署之前一定要先做测试,而且要记住,如果太过古怪,用户很快就会点击“跳过本页”链接跳过你精心设计的这些部分。

要知道使用Ajax 时有几个常犯的错误。我们已经讨论过,有变化时如何向用户提供可视化的提示,不仅如此,Ajax还会以其他方式改变标准的Web方法。首先,不同于IFRAME和隐藏框架,通过XHR做出请求不会修改浏览器的历史栈。在许多情况下这没有什么问题(你可能会点击后退箭头,只是要看看是不是什么都没有改变,但这么做能有几次呢?),不过,如果你的用户确实想用后退按钮,就有问题了。

其次,与其他基于浏览器的方法不同,Ajax不会修改地址栏中显示的链接,这表明你不能轻松地为一个页面建立书签,或者向朋友发送一个链接。对于许多应用来说,可能没有这个要求,但是如果你的网站专门为人提供行车路线之类的东西,就要针对这个问题提供一个解决方案。

有一点很重要,使用Ajax不要过度。记住,JavaScript会在客户端的浏览器上运行,如果有数千行JavaScript代码,可能会让用户感觉速度太慢。如果脚本编写不当,就会很快失去控制,特别是当通信量增加时。

Ajax允许你异步地完成操作,这个最大的优点同时也是它最突出的缺点。我们以前总是告诉用户,Web应用是以一种请求/响应模式完成操作的,用户也已经接受了这种思想。但是用了Ajax,就不再有这个限制。我们可以只修改页面的一部分,如果用户没想到这一点,他们很可能会被搞糊涂。所以,你要注意一定要让用户明白这一点,不要想当然地以为他们知道。记住,只要有疑问,就要请用户代表进行测试!

Tags: ajax, javascript, php

Ajax基础教程 1.3 - Web应用的发展历程

最初,所有Web页面都是静态的,用户请求一个资源,服务器再返回这个资源。什么都不动,什么都不闪。坦率地讲,对于许多Web网站来说,这样也是可以的,这些网站的Web页面只是电子形式的文本,在一处生成,内容固定,再发布到多处。在浏览器发展的最初阶段,Web页面的这种静态性不成问题,科学家只是使用因特网来交换研究论文,大学院校也只是通过因特网在线发布课程信息。企业界还没有发现这个新“渠道”会提供什么商机。实际上,以前公司主页显示的信息通常很少,无非是一些联系信息或者只是一些文档。不过没过多久,Web用户就开始有新的要求了,希望能得到更动态的网上体验。个人计算机成为企业不可或缺的资源,而且从个人宿舍到住家办公室开始出现越来越多的计算机。随着Windows 95的问世,随着人们已经领教了Corel WordPerfectMicrosoft Excel丰富的功能,用户的期望也越来越高。

1.3.1  CGI

要让Web更为动态,第一个办法是公共网关接口(Common Gateway InterfaceCGI)。与静态的Web获取不同,使用CGI可以创建程序,当用户发出请求时就会执行这个程序。假设要在Web网站上显示销售的商品,你可以利用CGI脚本来访问商品数据库,并显示结果。通过使用简单的HTML表单和CGI脚本,可以创建简单的网上店面,这样别人就可以通过浏览器来购买商品。编写CGI脚本可以用多种语言,从PerlVisual Basic都可以,这使得掌握不同编程语言的人都能编写CGI脚本。

不过,要创建动态的Web页面,CGI并不是最安全的方法。如果采用CGI,将允许别人在你的系统上执行程序。大多数情况下这可能没有问题,但是倘若某个用户有恶意企图,则很可能会利用这一点,让系统运行你本来不想运行的程序。尽管存在这个缺陷,到如今CGI仍在使用。

1.3.2  applet

很显然,CGI可以有所改进。19955月,Sun公司的John GageAndreessen(目前在Netscape通信公司)宣布一种新的编程语言诞生,这就是JavaNetscape Navigator为这种新语言提供了支持,最初是为了支持机顶盒。(你可能原认为最早涉足智能家居的公司是MicrosoftSony其实不然。)就像所有革命都机缘巧合一样,Java和因特网的出现恰到好处,在适当的时间、适当的地点横空出世,JavaWeb上发布仅几个月,就已经有成千上万的人下载。由于NetscapeNavigator支持Java,动态Web页面掀开了新的一页:applet时代到来了。

applet允许开发人员编写可嵌入在Web页面上的小应用程序。只要用户使用支持Java的浏览器,就可以在浏览器的Java虚拟机(Java Virtual MachineJVM)中运行applet。尽管applet可以做很多事情,但它也存在一些限制:通常不允许它读写文件系统,它也不能加载本地库,而且可能无法启动客户端上的程序。除了这些限制外,applet是在一个沙箱安全模型中运行的,这是为了有助于防止用户运行恶意代码。

对许多人来说,最初接触Java编程语言就是从applet开始的,当时这是创建动态Web应用的一种绝好的方法。applet允许你在浏览器中创建一个胖客户应用,不过要在平台的安全限制范围内。当时,在很多领域都广泛使用了applet,但是,Web社区并没有完全被applet“征服”[2]。胖客户的开发人员都很熟悉一个问题:必须在客户端上部署适当的Java版本。因为applet在浏览器的虚拟机中运行,所以开发人员必须确保客户端安装了适当版本的Java。尽管这个问题也可以解决,但它确实妨碍了applet技术的进一步推广。而且如果applet写得不好,很可能对客户主机造成影响,这使许多客户对于是否采用基于applet的解决方案犹豫不定。如果你还不太熟悉applet,请看图1-1,图中显示了Sun公司提供的时钟applet

1-1 Sun的时钟applet

1.3.3  JavaScript

与此同时,Netscape创建了一种脚本语言,并最终命名为JavaScript(建立原型时叫做Mocha,正式发布之前曾经改名为LiveWireLiveScript,不过最后终于确定为JavaScript)。设计JavaScript是为了让不太熟悉JavaWeb设计人员和程序员能够更轻松地开发applet(当然,Microsoft也推出了与JavaScript相对应的脚本语言,称为VBScript)。NetscapeBrendan Eich来设计和实现这种新语言,他认为市场需要的是一种动态类型脚本语言。由于缺乏开发工具,缺少有用的错误消息和调试工具,JavaScript很受非议,但尽管如此,JavaScript仍然是一种创建动态Web应用的强大方法。

最初,创建JavaScript是为了帮助开发人员动态地修改页面上的标记,以便为客户提供更丰富的体验。人们越来越认识到,页面也可以当作对象,因此文档对象模型(Document Object ModelDOM)应运而生。刚开始,JavaScriptDOM紧密地交织在一起,但最后它们还是“分道扬镳”,并各自发展。DOM是页面的一个完全面向对象的表示,该页面可以用某种脚本语言(如JavaScriptVBScript)进行修改。

最后,万维网协会(World Wide Web ConsortiumW3C)介入,并完成了DOM的标准化,而欧洲计算机制造商协会(ECMA)批准JavaScript作为ECMAScript规约。根据这些标准编写的页面和脚本,在遵循相应原则的任何浏览器上都应该有相同的外观和表现。

在最初的几年中,JavaScript的发展很是坎坷,这是许多因素造成的。首先,浏览器支持很不一致,即使是今天,同样的脚本在不同浏览器上也可能有不同的表现;其次,客户可以自由地把JavaScript关闭,由于存在一些已知的安全漏洞,往往鼓励用户把JavaScript关掉。由于开发JavaScript很有难度(你会用alert吗?),许多开发人员退避三舍,有些开发人员干脆不考虑 JavaScript,认为这是图形设计人员使用的一种“玩具”语言。许多人曾试图使用、测试和调试复杂的JavaScript,并为此身心俱疲,所以大多数人在经历了这种痛苦之后,最终只能满足于用JavaScript创建简单的基于表单的应用。

1.3.4  servletASPPHP……太多了

尽管applet是基于Web的,但胖客户应用存在的许多问题在applet上也有所体现。在大量使用拨号连接的年代(就算是今天,拨号连接也很普遍),要下载一个复杂applet的完整代码,要花很多时间,用户不能承受。开发人员还要考虑客户端上的Java版本,有些虚拟机还有更多的要求[3]。理想情况下只需提供静态的Web页面就够了,毕竟,这正是设计因特网的本来目的。当然,尽管静态页面是静态的,但是如果能在服务器上动态地生成内容,再把静态的内容返回,这就太好了。

Java问世一年左右,Sun引入了servlet。现在Java代码不用再像applet那样在客户端浏览器中运行了,它可以在你控制的一个应用服务器上运行。这样,开发人员就能充分利用现有的业务应用,而且,如果需要升级为最新的Java版本,只需要考虑服务器就行了。Java推崇“一次编写,到处运行”,这一点使得开发人员可以选择最先进的应用服务器和服务器环境,这也是这种新技术的另一个优点。servlet还可以取代CGI脚本。

servlet向前迈出了很大一步。servlet提供了对整个Java应用编程接口(API)的完全访问,而且提供了一个完备的库可以处理HTTP。不过,servlet不是十全十美的。使用servlet设计界面可能很困难。在典型的servlet交互中,先要从用户那里得到一些信息,完成某种业务逻辑,然后使用一些“打印行”创建HTML,为用户显示结果。代码清单1-1所示的代码就相当常见。

代码清单1-1 简单的servlet代码

response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();

 

        out.println("<html>");

        out.println("<head>");

        out.println("<title>Servlet SimpleServlet</title>");

        out.println("</head>");

        out.println("<body>");

        out.println("<h1>Hello World</h1>");

        out.println("<p>Imagine if this were more complex.</p>");

        out.println("</body>");

        out.println("</html>");

 

        out.close();

以上这一小段代码可以生成图1-2所示的一个相当简单的Web页面。

1-2 代码清单1-1中简单servlet的输出

servlet不仅容易出错,很难生成可视化显示,而且还无法让开发者尽展其才。一般地,编写服务器端代码的人往往是软件开发人员,他们只是对算法和编译器很精通,但不是能设计公司精美网站的图形设计人员。业务开发人员不仅要编写业务逻辑,还必须考虑怎么创建一致的设计。因此,很有必要将表示与业务逻辑分离。因此JSPJavaServer Pages)出现了。

在某种程度上,JSP是对 Microsoft Active Server Pages (ASP)做出的回应。MicrosoftSunservlet规约上所犯的错误汲取了教训,并创建了ASP来简化动态页面的开发。Microsoft增加了非常好的工具支持,并与其Web服务器紧密集成。JSPASP的设计目的都是为了将业务处理与页面外观相分离,从这个意义上讲,二者是相似的。虽然存在一些技术上的差别(Sun也从Microsoft那里学到了教训),但它们有一个最大的共同点,即Web设计人员能够专心设计页面外观,而软件开发人员可以专心开发业务逻辑。代码清单1-2显示了一个简单的JSP

代码清单1-2 简单的JSP

<%@page contentType="text/html"%>

<%@page pageEncoding="UTF-8"%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

    "http://www.w3.org/TR/html4/loose.dtd">

 

<html>

     <head>

          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

          <title>Hello World</title>

     </head>

     <body>

 

     <h1>Hello World</h1>

     <p>This code is more familiar for Web developers.</p>

 

     </body>

</html>

这个代码会生成图1-3所示的输出。

1-3 简单JSP的输出

当然,MicrosoftSun并没有垄断服务器端解决方案。还有许多其他的方案在这个领域都有一席之地,如PHPColdFusion等等。有些开发人员喜欢新奇的工具,还有一些则倾向于更简单的语言。目前来看,所有这些解决方案完成的任务都是一样的,它们都是要动态生成HTML。在服务器端生成内容可以解决发布问题。不过,与使用胖客户或applet所做的工作相比,用户从原始HTML得到的体验就太过单调和苍白了。下面几节将介绍几种力图提供更丰富用户体验的解决方案。

1.3.5  Flash

并不是只有MicrosoftSun在努力寻找办法来解决动态Web页面问题。1996年夏天,FutureWave发布了一个名叫FutureSplash Animator的产品。这个产品起源于一个基于Java的动画播放器,FutureWave很快被Macromedia兼并,Macromedia则将这个产品改名为Flash

利用Flash,设计人员可以创建令人惊叹的动态应用。公司可以在Web上发布高度交互性的应用,几乎与胖客户应用相差无几(见图1-4)。不同于appletservletCGI脚本,Flash不需要编程技巧,很容易上手。在20世纪90年代末期,掌握Flash是一个很重要的特长,因为许多老板都非常需要有这种技能的员工。不过,这种易用性也是有代价的。

1-4 Flash应用

像许多解决方案一样,Flash需要客户端软件。尽管许多流行的操作系统和浏览器上都内置有所需的Shockwave播放器插件,但并非普遍都有。虽然能免费下载,但由于担心感染病毒,使得许多用户都拒绝安装这个软件。Flash应用可能还需要大量网络带宽才能正常地工作,另外,由于没有广泛的宽带连接,Flash的推广受到局限(因此产生了“跳过本页”之类的链接)。虽然确有一些网站选择建立多个版本的Web应用,分别适应于不同的连接速度,但是许多公司都无法承受支持两个或更多网站所增加的开发开销。

总之,创建Flash应用需要专用的软件和浏览器插件。applet可以用文本编辑器编写,而且有一个免费的Java开发包,Flash则不同,使用完整的Flash工具包需要按用户数付费,每个用户需要数百美元。尽管这些因素不是难以逾越的障碍,但它们确实减慢了Flash在动态Web应用道路上的前进脚步。

1.3.6  DHTML革命

MicrosoftNetscape发布其各自浏览器的第4版时,Web开发人员有了一个新的选择:动态HTMLDynamic HTMLDHTML)。与有些人想像的不同DHTML不是一个W3C标准,它更像是一种营销手段。实际上,DHTML结合了HTML、层叠样式表(Cascading Style SheetsCSS)、JavaScriptDOM。这些技术的结合使得开发人员可以动态地修改Web页面的内容和结构。

最初DHTML的反响很好。不过,它需要的浏览器版本还没有得到广泛采用。尽管IENetscape都支持DHTML,但是它们的实现大相径庭,这要求开发人员必须知道他们的客户使用什么浏览器。而这通常意味着需要大量代码来检查浏览器的类型和版本,这就进一步增加了开发的开销。有些人对于尝试这种方法很是迟疑,因为DHTML还没有一个官方的标准。不过,将来新标准有可能会出现。

1.3.7  XML衍生语言

20世纪90年代中期,基于SGML衍生出了W3C的可扩展标记语言(eXtensible Markup LanguageXML),自此以后,XML变得极为流行。许多人把XML视为解决所有计算机开发问题的灵丹妙药,以至于XML几乎无处不在。实际上,Microsoft就已经宣布,Office 12将支持XML文件格式。

如今,我们至少有4XML衍生语言可以用来创建Web应用(W3CXHTML不包括在内):MozillaXULXAMJ,这是结合Java的一种开源语言;MacromediaMXML MicrosoftXAML

XULXUL(读作“zool”)代表XML用户界面语言(XML User Interface Language),由Mozilla基金会推出。流行的Firefox浏览器和Thunderbird邮件客户端都是用XUL编写的。利用XUL,开发人员能构建功能很丰富的应用,这个应用可以与因特网连接,也可以不与因特网连接。为了方便那些熟悉DHTML的开发人员使用,XUL设计为可以跨平台支持诸如窗口和按钮等标准界面部件。虽然XUL本身不是标准,但它是基于各种标准的,如HTML 4.0CSSDOMXMLECMAScript等等。XUL应用可以在浏览器上运行,也可以安装在客户端主机上。

当然,XUL也不是没有缺点。它需要Gecko引擎,而且目前IE还没有相应的插件。尽管Firefox在浏览器市场中已经有了一定的份额,但少了IE的支持还是影响很大,大多数应用都无法使用XUL。目前开展的很多项目都是力图在多个平台上使用XUL,包括Eclipse

XAML