9
8
2009
1

火狐CTRL+F5刷新页面的一个细节

火狐里CTRL+F5刷新页面后

接下去的任何操作都不加载缓存,而是去网上下载新文件

Category: JavaScript | Tags: 火狐
9
7
2009
2

[JavaScript]选中文本框内的文字

 

Obj.select();

 

 That All.

Category: JavaScript | Tags: javascript 选中文字
8
18
2009
0

[JQuery]一个替换html标签为实体字符的方法

先用<div/>临时取得要转换的值

var msg = $("<div/>").text("<br />").html();

msg就是转换好的值 &lt;br /&gt;

Category: JavaScript | Tags:
8
11
2009
1

[JavaScript]解决页面onresize缩放时多次调用的问题

IE8简直太脆弱了,加了一段监听窗口缩放的代码就不时的挂掉

发现Gmail的邮件列表用到了监听浏览器窗口的事件,不一样的是设置了一个延迟执行,这样就解决了多次调用的问题

这样ie8挂掉的几率应该就小多了吧!

var timer = null;
window.onresize(function(){
    if(timer == null){
        timer = setTimeout(function(){
            //缩放后你要执行的代码
            doWhatUWant();
            timer = null;
        },200);
    }
});

 

update:

今天继续测试页面时,ie8再次假死,怨念

也就是说设置这样一个延迟操作只能让挂掉的几率变小,但是我正在做这个是一个聊天的页面,一旦是挂掉了,聊天信息就全没了,用户会发疯的

于是继续搜索找到了下面的这个解决方法

传送:feiyu.asgard.cn/article_225.html

解决IE6,IE7下resize事件不断触发造成浏览器假死的问题

注:本示例采用jquery,原理都通用,用其他库或是不用库,只要改下代码即可。

有时,我们要在网页的resize事件中执行相关js代码。但是在ie6,ie7下,如果你缩放浏览器,resize事件会不断触发,造成假死现 象。把以下代码存为html文件,加上jquery.js,然后在ie6,ie7下打开,然后缩放下试试(假死后请用任务管理器结束任务):

<!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">
<head>
<title>1</title>
<script src="jquery.js"></script>
<script>
var i=0;
$(function() {
 $(window).resize(function() {
  $("body").append("<p>" + (++i) + "</p>");
 });
});
</script>
</head>
<body></body>
</html>

为了解决该问题,以前采用setTimeout和clearTimeout来做,但是效果并不理想。虽然不会假死了,但测试结果是resize事件 还是会不断被执行,在资源管理器中监视时发现resize几次后CPU占用就上去了(根据setTimeout所定的延迟决定占用量)。

经过GOOGLE及反复试验,终于有较好解决该问题的方法。先看代码:

<!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">
<head>
<title>3</title>
<script type="text/javascript" src="jquery.js"></script>
<script>
var i=0;
$(function() {
 if($.browser.msie && ("6.0,7.0".indexOf($.browser.version) != -1)) {
  $("body").append(
  '<div id="fix-ie-resize" style="width:100%;height:100%;position:absolute;z-index:-999;"></div>'
  );
  $("#fix-ie-resize").resize(function() {
   $("body").append("<p>" + (++i) + "</p>");
  });
 }
 else{
  $(window).resize(function() {
   $("body").append("<p>" + (++i) + "</p>");
  })
 }
});
</script>
<style>
body{margin:0;}
</style>
</head>
<body>
</body>
</html>

代码意思为:

判断浏览器是否是IE6或IE7,如果是的话,向body中加入一个长宽都是100%的无内容层,并且把resize事件绑定在该层上。

如果是其他浏览器,则直接绑定到window的resize事件。

Category: JavaScript | Tags: javascript 页面缩放
7
28
2009
0

[JavaScript]匿名函数参数的问题

分两种写法:

自己声明参数名

(function(x,y){
    alert(x+','+y);
})(1,2)
//显示 1,2

 

不声明参数(通过arguments数组取得)

(function(){
    alert(arguments[0]+','+arguments[1]);
})(1,2)
//显示 1,2

 

事实上只用知道参数的顺序和个数就可以自己定义参数名取得参数值

 

 

 

6
5
2009
0

[JQuery]捕捉按键keyCode的问题

今天遇到一个小问题代码如下

$("#input_textarea").keydown(function(){
    alert(event.keyCode);
})

提示event未定义

input_textarea是一个文本输入框

我想能在输入时捕获按下的是哪个键,以前不用JQuery时是通过这样的写法:(w3c的写法)

<textarea id="input_textarea" onkeydown="alert(event.keyCode)"></textarea>

找了半天,终于知道原来jquery已经帮我封装好了,连浏览器类型都不用判断,方法如下

$("#input_textarea").keydown(function(event){
    alert(event.keyCode);
})

看来以后还是要学习一下jquery的源码,才能了解更多底层的东西啊!

另外赞一下jquery,确实太喜欢了,以前要用上百行解决的问题50行内就能解决,一定要深入研究!

 

 

Category: JavaScript | Tags: 事件 jquery javascript
2
11
2009
0

[XML][JavaScript]XML DOM 浏览器差异

不同的浏览器在 XML DOM 中处理空文本节点的方式是不同的。
 

实例

下面的例子使用 XML 文件 books.xml

函数 loadXMLDoc(),位于外部 JavaScript 中,用于加载 XML 文件。

显示节点列表的长度
本例显示了一个节点列表的长度。在 IE 和其他浏览器中,结果是不同的。
忽略节点间的空文本
本例检查节点的 nodeType,且仅处理元素节点。

DOM 解析中的浏览器差异

所有现代浏览器都支持 W3C DOM 规范。

不过,浏览器之间是有差异的。重要的区别有两点:

  • 加载 XML 的方式
  • 处理空白和换行的方式

在 “解析 XML DOM” 这一节,已经解释了加载 XML 的不同方式。

在本节中,我们将讲解处理空白和换行的不同方式。

DOM - 空白和换行

XML 经常在节点之间含有换行或空白字符。这是在使用简单的编辑器(比如记事本)时经常出现的情况。

下面的例子(由记事本编辑)在每行之间含有 CR/LF,在每个子节点之前含有两个空格:

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

Firefox,以及其他一些浏览器,会把空的空白或换行作为文本节点来处理,而 Internet Explorer 不会这样。

下面的代码片段显示 (books.xml 的) 根元素拥有多少个子节点:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.documentElement.childNodes;
document.write("Number of child nodes: " + x.length);

例子解释:

  • 通过使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  • 获取根元素的子节点
  • 输出子节点数目

结果取决于所使用的浏览器。Firefox 输出 9,而 IE 输出 4。

TIY

忽略节点间的空文本

如需忽略元素节点之间的空文本节点,需要检查节点类型。元素节点的类型是 1:

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.documentElement.childNodes;

for (i=0;i<x.length;i++)
{ 
if (x[i].nodeType==1)
  {// only process element nodes 
  document.write(x[i].nodeName);
  document.write("<br />");
  } 
}

例子解释:

  • 通过使用 loadXMLDoc() 把 "books.xml" 载入 xmlDoc 中
  • 获取根元素的子节点
  • 检查每个子节点的节点类型。如果节点类型是 "1",则是元素节点

TIY(简单) 或者 TIY(完整)

2
11
2009
0

[JavaScript]动态得到select控件选中的值

 

<html>
<head>
<script type="text/javascript">
function getElements(){
    var x=document.getElementsByTagName("select");
    for(var i=0; i<x.length; i++){
        alert(x[i][x[i].selectedIndex].value);
    }
}
</script>
</head>
<body>
<select>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
</select>
<br />
<select>
<option value=a>a</option>
<option value=b>b</option>
<option value=c>c</option>
</select>
<br />
<input type="button" onclick="getElements()" value="选中了什么?" />
</body>
</html>
 
Category: JavaScript | Tags: javascript 动态表单
2
2
2009
11

[javascript]javascript的URL编码和解码

在 使用url进行参数传递时,经常会传递一些中文名的参数或URL地址,在后台处理时会发生转换错误。在有些传递页面使用GB2312,而在接收页面使用 UTF8,这样接收到的参数就可能会与原来发生不一致。使用服务器端的urlEncode函数编码的URL,与使用客户端javascript的 encodeURI函数编码的URL,结果就不一样。

javaScript中的编码方法:
escape() 方法:
采用ISO Latin字符集对指定的字符串进行编码。所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码 (xx等于该字符在字符集表里面的编码的16进制数字)。比如,空格符对应的编码是%20。unescape方法与此相反。不会被此方法编码的字 符: @ * / +

英文解 释:MSDN JScript Reference: The escape method returns a string value (in Unicode format) that contains the contents of [the argument].

All spaces, punctuation, accented characters, and any other non- ASCII characters are replaced with %xx encoding, where xx is equivalent to the hexadecimal number representing the character.

For example, a space is returned as "%20."

Edge Core Javascript Guide: The escape and unescape functions let you encode and decode strings.

The escape function returns the hexadecimal encoding of an argument in the ISO Latin character set.

The unescape function returns the ASCII string for the specified hexadecimal encoding value.



encodeURI() 方法:把URI字符串采用UTF-8编码格式转化成escape格式的字符串。不会被此方法编码的字符:! @ # $& * ( ) = : / ; ? + '

英文解 释:MSDN JScript Reference: The encodeURI method returns an encoded URI.

If you pass the result to decodeURI, the original string is returned.

The encodeURI method does not encode the following characters: ":", "/", ";", and "?".

Use encodeURIComponent to encode these characters. Edge Core Javascript Guide: Encodes a Uniform Resource

Identifier (URI) by replacing each instance of certain characters by one, two, or three escape sequences representing the UTF- 8 encoding of the character



encodeURIComponent() 方法:把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相 比,这个方法将对更多的字符进行编码,比如 / 等字符。所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编 码之后URL将显示错误。不会被此方法编码的字符:! * ( )

英文解 释:MSDN JScript Reference: The encodeURIComponent method returns an encoded URI. If you pass the result to decodeURIComponent, the original string is returned.

Because the encodeURIComponent method encodes all characters, be careful if the string represents a path such as /folder1 /folder2 /default.html. The slash characters will be encoded and will not be valid if sent as a request to a web server. Use the encodeURI method if the string contains more than a

single URI component. Mozilla Developer Core Javascript Guide: Encodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one,

two, or three escape sequences representing the UTF- 8 encoding of the character.



 
因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面 的charset是一致的时候),只需要使用escape。如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用 encodeURI或者encodeURIComponent。

       另外,encodeURI/encodeURIComponent是在javascript1.5之后引进的,escape则在javascript1.0版本就有。

英文注 释:The escape() method does not encode the + character which is interpreted as a space on the server side as well as generated by forms with spaces in their fields.

Due to this shortcoming, you should avoid use of escape() whenever possible. The best alternative is usually encodeURIComponent().

Use of the encodeURI() method is a bit more specialized than escape() in that it encodes for URIs [REF] as opposed to the querystring,

which is part of a URL. Use this method when you need to encode a string to be used for any resource that uses URIs and needs certain characters to remain un- encoded. Note that this method does not encode the ' character, as it is a valid character within URIs.Lastly, the encodeURIComponent() method should be used in most

cases when encoding

a single component of a URI. This method will encode certain chars that would normally be recognized as special chars for URIs so that many components may be included.

Note that this method

does not encode the ' character, as it is a valid character within URIs.

 
1.编码处理函数
1) encodeURI 返回一个对URI字符串编码后的结果。URL是最常见的一种URI;
2) decodeURI 将一个已编码的URI字符串解码成最原始的字符串返回;
3) 举例: < Script language = " javascript " > 输出结果如下: encodeStr: http://www.amigoxie.com/index.jsp?name=%E9%98%BF%E8%9C%9C%E6%9E%9C decodeStr: http://www.amigoxie.com/index.jsp?name=xind
 
2. 数值处理函数
1) parseInt 将一个字符串指定的进制转换为一个整数,语法格式为: parseInt(numString, [radix]) 第一个参数是要进行转换的字符串,是介于2到36之间的数值,用于指定进行字符串转换时所用的进制。 举例如下: 输出结果如下: 默认情况下的结果:32:32;032:26;0x32:50 转为2进制的结果:32:NaN;032:0;0x32:0 转为8进制的结果:32:26;032:26;0x32:0 转为16进制的结果:32:50;032:50;0x32:50 11001010转换后的结果: 2进制:202;16进制:285216784 8进制:2359816;10进制:11001010 43abc转换后:43;abc43转换后:NaN;abc转换后:NaN
2) parseFloat方法 该方法将一个字符串转换成对应的小数。 eg. 输出结果如下: 4.11 5.1 3) isNaN方法 该方法用于检测前两个方法返回值是否为非数值型,如果是,返回true,否则,反回false
 
转至:http://hi.baidu.com/blueyund/blog/item/dc060bd1bb8e5cd4562c8436.html
Category: JavaScript | Tags: javascript url编码
1
8
2009
0

[javascript][Ajax][XML]Ajax 和 XML: 五种常见 Ajax 模式

 

可立即使用这些非常有用的 Ajax 设计模式

 
文档选项
将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送

讨论

样例代码


 

Jack D Herrington (jherr@pobox.com), 高级软件工程师, Leverage Software Inc.
 

2007 年 3 月 20 日

Asynchronous JavaScript + XML(Ajax)无疑是 2006 年最热门的技术术语,且有望在 2007 得到进一步发展。但是对您的应用程序来说它究竟有什么意义呢?Ajax 应用程序中哪一种常见架构模式应用最广泛呢?本文将介绍五种常见 Ajax 设计模式,可以使用它们作为工作的基础。

的确,Ajax 是 Web 2.0 热门术语,所有人都希望将其应用于自己的站点。但是它对我们究竟有什么意义?工程师该如何在架构的层面上将其集成到自己的站点中?在这篇文章中,我将介绍 Ajax 的基本知识,并展示一些已经成为 Web 2.0 开发最佳实践的 Ajax 设计模式。

请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。

首先,Ajax 仅仅是一个涉及一组技术的术语,包括 Dynamic HTML(DHTML)和 XMLHTTPRequest 对象。DHTML 由三个元素组合而成,它们分别是超文本标记语言(Hypertext Markup Language,HTML)、JavaScript 代码和级联样式表(Cascading Style Sheet,CSS)。在 Web 页面使用 JavaScript 代码,可以动态地改变页面,包括添加、删除或更改页面内容。这就是 DHTML 的动态 部分。JavaScript 代码使用 XMLHTTPRequest 对象在加载页面后向服务器请求数据。

这两种元素的组合 —— 从服务器动态请求数据然后使用这些数据更改页面 —— 就是 Ajax 的本质,也是 Web 2.0 站点的动态特性。

但这并没有真正告诉您如何实际应用这些特性以及如何在站点中使用它们。因此,需要一组简单的设计模式。 如果您对这个术语感到陌生,本文推介了一本非常优秀的同名书籍(参见 参考资料)。这本书针对工程师经常面对的任务提供了一组实现模式。它不仅提供了设计系统的最佳实践,还介绍了工程师谈论代码时用到的术语。

本文介绍了五种常见 Ajax 设计模式。它们在使用 HTML、XML 和 JavaScript 代码从服务器获取数据方面有所不同。我先介绍最简单的模式,它将使用来自服务器的新 HTML 页面来更新页面。

模式 1. 替换 HTML 片段

最常见的 Ajax 任务也许就是向服务器请求更新的 HTML 并使用它更新部分页面。可能需要周期性地完成这一任务 —— 比如,更新股市报价。也可能要按需更新 —— 比如,对搜索请求进行响应。

清单 1 中的代码从服务器请求一个页面然后将内容放入页面主体的 <div> 标记中。


清单 1. Pat1_replace_div.html
                
<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'htmlDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /pat1_replace_div.html/, 'pat1_content.html' );
loadUrl( url );
</script>
<body>
Dynamic content is shown between here:<br/>
<div id="htmlDiv" style="border:1px solid black;padding:10px;">
</div>
And here.<br/>
</body>
</html>

清单 2 展示了代码请求的内容。


清单 2. Pat1_content.html
                
HTML encoded content goes here.

要查看真实环境的演示,请查看这个在线版本 pat1_replace_div.html 在新窗口中打开链接以查看 pat1_replace_div.html .

在 Firefox 中加载页面后,可以看到 图 1 所示的结果。


图 1. 替换了 <div> 标记的页面
替换了标记的页面

现在回到 清单 1 中的代码,来观察一些内容。第一个要注意的是 loadUrl() 函数,它从服务器请求一个 URL。该函数使用 XMLHTTPRequest 对象向服务器请求新内容。它还指定了一个回调函数 —— 本例中,是 processReqChange —— 当浏览器收到内容时将调用它。

processReqChange 函数将查看对象以确定请求是否完成。如果是的话,该函数将页面 <div> 标记的 innerHTML 设置为响应的文本。

<div> 标记作为一个动态内容的占位符,这是 Ajax 代码的主要组成部分。这些标记没有可见的表示形式(除非添加边框,像我这样做),但它们很好地标记了内容的放置位置。工程师还使用 <span> 标记用于可代替的片段,稍后我将对其进行演示。<div><span> 标记的不同之处是前者加入了一个断行符(如一个段落),而后者使用边线勾画出一节内联文本。

暂时回到 processReqChange 函数,该函数对 statusreadyState 的值进行检查非常重要。有些浏览器可能只在请求完成时才调用这个函数,而也有些浏览器会不断回调该函数从而告诉代码请求依然在运行。

选项卡式显示变体

该模式的另一种变体就是创建一个选项卡样式的显示。 清单 3 展示了一个简单的选项卡式 Ajax 界面。


清单 3. Pat1_tabs.html
                
<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'tabDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( tab ) {
  var url = window.location.toString();
  url = url.replace( /pat1_tabs.html/, tab );
  ...
}

function tab1() { loadUrl( 'pat1_tab1_content.html' ); }
function tab2() { loadUrl( 'pat1_tab2_content.html' ); }
tab1();
</script>
<body>
<a href="javascript: void tab1();">Tab 1<a> 
<a href="javascript: void tab2();">Tab 2<a>
<div id="tabDiv" style="border:1px solid black;padding:10px;">
</div>
</body>
</html>

清单 4 显示了第一个选项卡的内容。


清单 4. Pat1_tab1_content.html
                
Tab 1 content

清单 5 显示了第二个选项卡的内容。


清单 5. Pat1_tab2_content.html
                
Tab 2 content

要查看真实环境的演示,请查看在线版本 pat1_tabs.html 在新窗口打开链接以查看 pat1_tabs.html .

当我在自己的浏览器上显示该页面时,我看到了第一个选项卡,如 图 2 所示。


图 2. 第一个选项卡的内容
第一个选项卡的内容

然后单击第二个选项卡的链接。浏览器检索第二个选项卡的内容然后将它显示在选项卡区域,如 图 3 所示。


图 3. 第二个选项卡的内容
第二个选项卡的内容

这是该设计模式的最典型用法 —— 从用户那里获得请求并使用新的内容更新部分显示,本例演示了创建选项卡显示的技巧。应用程序端的价值就是您可以为用户下载非常轻量级的页面,用户可以根据自己的需求访问这些内容。

在 Ajax 出现之前,最常见的技术是将所有的选项卡都放在页面上,然后根据需要显示或隐藏它们。这就是说即使从来不查看第二个选项卡,也会为其创建 HTML,既浪费服务器时间又浪费带宽。使用这种新的 Ajax 方法,只有当用户请求第二个选项卡时才会为其创建 HTML。

read more 变体

要查看真实环境的演示,请查看在线版本 pat1_readmore.html 在新窗口打开链接以查看 pat1_readmore.html.

该模式的另一个变化就是 Read more 链接,如 图 4 所示。


图 4. 我的博客登录处的 Read more 链接
Read more 链接

假如想希望阅读更多关于我遛狗的经历,可以单击 Read more 链接,使该链接替换为完整的故事,如 图 5 所示。


图 5. 单击 Read more 链接后显示的页面
单击 Read more 后

这样做的好处是顾客可以在无需刷新页面的情况下获得更多内容。

清单 6 显示了该页的代码。


清单 6. Pat1_readmore.html
                
<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( "moreSpan" );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) { ... }

function getMore()
{
  var url = window.location.toString();
  url = url.replace( /pat1_readmore.html/, 'pat1_readmore_content.html' );
  loadUrl( url );
}
</script>
<body>
<h1>Walking the dog</h1>
I took my dog for a walk today. 
<span id="moreSpan">
<a href="javascript: void getMore()">Read more...</a>
</span>
</body>
</html>

清单 7 显示了 “read more” 部分的内容。


清单 7. Pat1_readmore_content.html
                
It was a nice day out. Warm and sunny. My dog liked getting out for a stretch.

这些代码演示的是 <span> 标记的用法,而非 <div> 标记。所使用的方法取决于用户界面(UI)的需求。但是正如您所看到的那样,无论哪种方法使用起来都很简单。

为页面获取新的 HTML 只是其中一件事情,如果您希望 JavaScript 代码在页面中使用数据执行一些更智能化的任务该怎么办呢?如何使用结构化的方式将数据发送到浏览器呢?毫无疑问,这正是使用 XML 的原因。





 
回页首


模式 2. 读取 XML 数据

出于某些原因,Ajax 已成为 XML 的同义词,尽管 XML 不是绝对必要的。从上面几个例子可以看出,您完全可以返回简单的文本甚至是 HTML 片段 —— 或者 Extensible HTML(XHTML)—— 代码。但是发送 XML 自有其优势所在。

清单 8 显示的 Ajax 代码首先向服务器请求图书记录,然后将数据显示在页面内的表格中。


清单 8. Pat2_xml.html
                
<html>
<head>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 && req.responseXML ) {
    var dtable = document.getElementById( 'dataBody' );
    var nl = req.responseXML.getElementsByTagName( 'book' );
    for( var i = 0; i < nl.length; i++ ) {
      var nli = nl.item( i );
      var elAuthor = nli.getElementsByTagName( 'author' );
      var author = elAuthor.item(0).firstChild.nodeValue;
      var elTitle = nli.getElementsByTagName( 'title' );
      var title = elTitle.item(0).firstChild.nodeValue;

      var elTr = dtable.insertRow( -1 );

      var elAuthorTd = elTr.insertCell( -1 );
      elAuthorTd.innerHTML = author;

      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = title;
} } }

function loadXMLDoc( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /pat2_xml.html/, 'pat2_xml_data.xml' );
loadXMLDoc( url );
</script>
</head>
<body>
<table cellspacing="0" cellpadding="3" width="100%">
<tbody id="dataBody">
<tr>
  <th width="20%">Author</th>
  <th width="80%">Title</th>
</tr>
</tbody>
</table>
</body>
</html>

清单 9 显示了该页面的数据。


清单 9. Pat2_xml_data.xml
                
<books>
  <book>
    <author>Jack Herrington</author>
    <title>Code Generation in Action</title>
  </book>
  <book>
    <author>Jack Herrington</author>
    <title>Podcasting Hacks</title>
  </book>
  <book>
    <author>Jack Herrington</author>
    <title>PHP Hacks</title>
  </book>
</books>

要查看真实环境的演示,请查看在线版本 pat2_xml.html 在新窗口打开链接以查看 pat2_xml.html.

在浏览器中加载页面时,我看到了如 图 6 所示的结果。


图 6. XML 显示页面
XML 显示页面

此页面和上一个模式中显示的页面之间最大的区别就是 processReqChange 函数,这里没有使用 responseText,而是 responseXML,这是一个 XML 文档对象模型(Document Object Model,DOM),该模型只有在来自服务器的响应是正确编码的 XML 时才是可用的。

通过使用 responseXML,我请求了 XML 文档的 <book> 标记的列表。然后分别从中获取 <title><author> 元素。接下来,为每本书向表中添加一行,再为每行添加包含作者和题目数据的单元格。

这是 XML 数据的最基本应用。更复杂的 JavaScript 代码可以执行客户端排序或根据返回的数据进行搜索。

遗憾的是,传递 XML 数据的缺点是需要浏览器多花费一些时间来解析整个 XML 文档。同样,JavaScript 代码在 XML 中查找数据也很复杂(参见 清单 8)。一个替代办法是从服务器请求 JavaScript 代码。





 
回页首


模式 3. 读取 JavaScript 数据

从服务器请求 JavaScript 数据这种技术通常用于 JavaScript Object Notation(JSON)这种良好的代码。返回 JavaScript 数据的优点就是能够使浏览器高效地解析并创建使用起来更加简单的 JavaScript 数据结构。

让我们将 清单 8 中从服务器读取 XML 的代码修改为从服务器读取 JavaScript 数据的代码。新代码如 清单 10 所示。


清单 10. Pat3_js.html
                
<html><head><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dtable = document.getElementById( 'dataBody' );
    var books = eval( req.responseText );
    for( var b in books ) {
      var elTr = dtable.insertRow( -1 );

      var elAuthorTd = elTr.insertCell( -1 );
      elAuthorTd.innerHTML = books[b].author;

      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = books[b].title;
} } }

...

所有的 HTML 代码保持不变。processReqChange 函数仅仅更改为读取 eval 从而从服务器返回 JavaScript 数据。该函数随后使用 eval 的 JavaScript 对象作为数据源,后者又将其添加到表中。

清单 11 显示了来自服务器的 JavaScript 数据。


清单 11. Pat3_js_data.js
                
[ { author: 'Jack Herrington', title: 'Code Generation in Action' },
{ author: 'Jack Herrington', title: 'Podcasting Hacks' },
{ author: 'Jack Herrington', title: 'PHP Hacks' }
]

要查看真实环境的演示,请查看在线版本 pat3_js.html 在新窗口中打开链接以查看 pat3_js.html .

为什么众多 Ajax 应用程序工程师更喜欢使用 JavaScript 代码而不是 XML 来对数据编码?答案很明显。JavaScript 代码更容易读取和管理,并且也更容易被浏览器处理。

收集和显示所有的数据之后,即可看到 Ajax 的重点就是显示当前数据 —— 当前 最重要的部分。那么,如何保证总是能够从服务器获得最新的数据呢?





 
回页首


模式 4. 避免浏览器缓存

浏览器会尝试化 Web 流量,所以如果您对同一个 URL 请求两次,很可能还不如重新请求一次页面,您的浏览器将仅仅使用浏览器缓存中存储的页面。所以,Ajax 应用程序中另一个常见模式是使用 URL 中的随机元素来保证浏览器不会返回一个缓存的结果。

我最喜欢的技巧就是向 URL 添加当前时间的数字值。 清单 12 展示了这一技巧。


清单 12. Pat4_cache.html
                
<html>
<script>
...

function loadUrl( url ) {
  url = url + "?t="+((new Date()).valueOf());
  ...
}

...

要查看真实环境的演示,请查看在线版本 pat4_cache.html 在新窗口中打开链接以查看 pat4_cache.html .

代码取自 清单 1,对 URL 字符串执行了一些额外的 JavaScript 文本操作。我将 URL 连接到一个新的参数 t,它具有一个时间值。服务器是否能识别这个值实际上并不重要。这只不过是用来确保浏览器忽视其基于 URL 的页面缓存。





 
回页首


模式 5. 替换多个 HTML 片段

最后要演示的这个模式是第一个模式的高级版本:包含来自服务器内容的 <div> 标记的替代物。Web 应用程序中的一个常见问题是在响应用户输入时,必须更新显示页面中的一些区域。举例来说,在一个股票报价应用程序中,显示页面的一部分可能会展示最近的报价,而另一部分则显示最近报价的列表。

为更新显示页面中的多个区域,我使用了服务器的 XML 响应,它包含每个部分的数据。然后,使用一个正则表达式将响应分解为单个部分。清单 13 显示了这种技巧。


清单 13. Pat5_multi_segment.html
                
<html>
<head>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var one = req.responseText.match( /\<one\>(.*?)\<\/one\>/ );
    document.getElementById( 'divOne' ).innerHTML = one[1];
    var two = req.responseText.match( /\<two\>(.*?)\<\/two\>/ );
    document.getElementById( 'divTwo' ).innerHTML = two[1];
} }

function loadXMLDoc( url ) { ... }

var url = window.location.toString();
url = url.replace( /pat5_multi_segment.html/, 'pat5_data.xml' );
loadXMLDoc( url );
</script>
</head>
<body>

This is the content for segment one:<br/>
<div id="divOne" style="border:1px solid black;padding:10px;">
</div>
And segment two:<br/>
<div id="divTwo" style="border:1px solid black;padding:10px;">
</div>

</body>
</html>

清单 14 展示了来自服务器的数据。


清单 14. Pat5_data.xml
                
<segments>
  <one>Content for segment one</one>
  <two>Content for segment <b>two</b></two>
</segments>

要查看真实环境的演示,请查看在线版本 pat5_multi_segment.html 在新窗口中打开链接以查看 pat5_multi_segment.html .

在浏览器中加载这段代码时,将看到 图 7 所示的结果。


图 7. 使用服务器的数据更新显示页面中的两部分
显示其中的两部分

在页面代码中,我还可以使用 XML 响应,因为服务器返回的是有效的 XML。但是使用正则表达式比从 XML 代码中分解单独部分更加简单。





 
回页首


结束语

Ajax 的功能之强大与之被误解和误用的程度相当。本文中演示的模式为在 Web 应用程序中使用 Ajax 提供了一个不错的起点。除了使用这里提供的代码,我还建议您关注以下 Web 2.0 革命带来的某些出色的 Ajax 和 Web UI 库。其中最主要的是 Prototype.js 库,它提供了向浏览器发送以及从浏览器获取数据的简便方法,以及浏览器间兼容的方法更新 Web 页面内容。使用这些库的价值在于工程师可以在广泛的浏览器和平台上专注地维护和测试它们,这样可省去大量的工作和麻烦。

无论从哪方面说,就像本文中的模式演示的那样,Ajax 可以为您的应用程序添加动态行为。

关于作者

 

Jack D. Herrington 是一位有着超过 20 年经验的高级软件工程师。他是 Code Generation in ActionPodcasting HacksPHP Hacks 这三本书的作者。他还发表了 30 多篇文章。可以通过 jherr@pobox.com 与 Jack 联系。

Category: JavaScript | Tags:

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com