龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > php编程 >

结合AJAX的PHP开发之后退、前进和刷新(1)(2)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
用cookie缓冲 我们需要应用程序的历史记录在整个浏览器会话中都存在。只要用户仍在查看相册页面,历史堆栈对象就会一直存在。每当发生更改的时候,

用cookie缓冲

我们需要应用程序的历史记录在整个浏览器会话中都存在。只要用户仍在查看相册页面,历史堆栈对象就会一直存在。每当发生更改的时候,这个类就会将整个历史记录复制到浏览器cookie中。如果用户在同一个浏览器会话中离开该页之后又返回,那么将返回他离开该应用程序时所在的同一个位置。

编写类

我们来看看历史堆栈中需要存储的数据或属性。前面已经讨论了堆栈(数组)和指针。stack_limit属性可以防止因为数据过多而造成的cookie溢出(参见清单 1)。在实践中,我们希望在删除最老的记录之前能够存储40-50个事件。出于测试的目的,我们将该值设置为15。

清单  1  历史堆栈的构造,包括类的属性

function HistoryStack ()
{
 this.stack = new Array();
 this.current = -1;
 this.stack_limit = 15;
}

除了这三个属性外,该类还需要一些方法来添加元素、检索堆栈数据以及将堆栈数据保存到浏览器cookie 中。首先看一看addResource()方法,它用于将记录压入历史堆栈的堆栈顶部(参见清单 2)。注意,如果堆栈的长度超过了stack_limit,那么最老的记录将从堆栈中移走。

清单 2  addResource() 方法,向历史堆栈的堆栈顶部添加记录

HistoryStack.prototype.addResource = function(resource)
{
 if (this.stack.length > 0) {
this.stack = this.stack.slice(0, this.current + 1);
 }
 this.stack.push(resource);
 while (this.stack.length > this.stack_limit) {
this.stack.shift();
 }
 this.current = this.stack.length - 1;
 this.save();
};

给历史堆栈添加的以下三个方法用于从该类中获取信息(参见清单 3)。getCurrent()返回堆栈指针指向的当前记录,这在堆栈中导航的时候非常有用。hASPrev()和 hasNext()方法返回Boolean值,告诉我们当前记录之前或之后是否还有记录,或者指示我们到达了堆栈顶部或堆栈尾部。这些方法很简单,但是确定后退和前进按钮的状态时很有用。

清单 3  历史堆栈定义的方法

HistoryStack.prototype.addResource = function(resource)
HistoryStack.prototype.getCurrent = function ()
{
 return this.stack[this.current];
};

HistoryStack.prototype.hasPrev = function()
{
 return (this.current > 0);
};

HistoryStack.prototype.hasNext = function()
{
 return (this.current < this.stack.length - 1 && this.current > -1);
};

现在就可以向历史堆栈中添加记录并确定所在的位置了。但还是无法在堆栈中导航。清单 4中定义的go() 方法允许我们在堆栈中来回移动。通过传递正或负的增量就可以在堆栈中向前或向后移动。这与JavaScript内置的location.go()方法类似。既然模仿内置功能,为何不根据这些已有的方法建立模型呢?

此外,我们还可用该方法实现刷新功能。可以通过传递正或负的参数在堆栈中导航。传递零时则会刷新当前页面。

清单 4  历史堆栈的 go() 方法

HistoryStack.prototype.go = function(increment)
{
 // Go back...
 if (increment < 0) {
this.current = Math.max(0, this.current + increment);

// Go forward...
 } else if (increment > 0) {
this.current = Math.min(this.stack.length - 1,this.current + increment);
// Reload...
 } else {
location.reload();
 }
 this.save();
};

到目前为止,只要 HistoryStack对象存在于当前文档中,这个新建的类就能正常工作。我们已经讨论了刷新页面会造成数据丢失的问题,现在来解决它。清单 5 中添加了在浏览器cookie中设置和访问数据的方法。所要做的只是设置每个cookie的名称值对。因为只需要在浏览器会话中保存cookie,而不需要设置有效期。为了简化示例,我们不考虑其他参数,如secure、domain和path。

注意:如果该类需要对cookie做复杂处理,更明智的办法是使用完全独立的cookie管理类。建立和读取cookie有点偏离历史堆栈的正题。如果JavaScript允许指定方法和属性访问的作用域,也可以将这些方法设成私有的。

清单 5  建立和访问浏览器 cookie 的方法

HistoryStack.prototype.setCookie = function(name, value)
{
 var cookie_str = name + "=" + escape(value);
 document.cookie = cookie_str;
};

HistoryStack.prototype.getCookie = function(name)
{
 if (!name) return '';
 var raw_cookies, tmp, i;
 var cookies = new Array();
 raw_cookies = document.cookie.split('; ');
 for (i=0; i < raw_cookies.length; i++) {
tmp = raw_cookies[i].split('=');
cookies[tmp[0]] = unescape(tmp[1]);
 }
 if (cookies[name] != null) {
return cookies[name];
 } else {
return '';
 }
};

定义了管理任何cookie的方法之后,可以编写另外两个类专门处理历史堆栈的类。save()方法将堆栈转化成字符串并保存到cookie中,load() 重新将字符串解析成用于管理历史堆栈的数组(参见清单 6)。

清单 6  save() 和 load() 方法

HistoryStack.prototype.save = function()
{
 this.setCookie('CHStack', this.stack.toString());
 this.setCookie('CHCurrent', this.current);
};

HistoryStack.prototype.load = function()
{
 var tmp_stack = this.getCookie('CHStack');
 if (tmp_stack != '') {
this.stack = tmp_stack.split(',');
 }

 var tmp_current = parseInt(this.getCookie('CHCurrent'));
 if (tmp_current >= -1) {
this.current = tmp_current;
 }
};

测试类

可以用简单的HTML页面和一些JavaScript来测试完成的类。测试页面将在上方显示历史记录按钮,只有活动的按钮是突出显示并且可以单击的。我们没有建立复杂的测试应用程序,该页面在每次单击链接时仅仅生成随机数。这些数字就是记录到历史堆栈中的事件。堆栈也在页面上显示,指针标记的当前记录用粗体显示。

清单 7  测试历史堆栈的简单 HTML 页面

<html>
<head>
<title></title>
</head>

<body>

<div id="historybuttons"></div>
<div>
<a href="#" onclick="do_add(); return false;">Add Random
Resource</a>
</div>
<div id="output" style="margin-top:40px;"></div>

</body>
</html>

精彩图集

赞助商链接