十三
导航和打开窗口
使用window.open()方法既可以导航到一个特定的URL,也可以打开一个新的浏览器窗口。这个方法可以接受4个参数:要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。通常只需传递第一个参数,最后一个参数只在不打开新窗口的情况下使用。
如果为window.open()传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的URL:
//等同于< a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
调用你这行代码,就如同用户单击了href属性为http://www.wrox.com/,target属性为“topFrame”的链接。如果有一个名叫“topFrame”的窗口或者框架,就会在该窗口或框架加载这个URL;否则,就会创建一个新窗口并将其命名为“topFrame”。此外,第二个参数也可以是下列任何一个特殊的窗口名称:_self、_parent、_top 和_blank。
弹出窗口
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
//调整大小
wroxWin.resizeTo(500,500);
//移动位置
wroxWin.moveTo(100,100);
//调用 close()方法还可以关闭新打开的窗口
wroxWin.close();
close()方法仅适用于通过window.open()打开的弹出窗口。对于浏览器的主窗口,如果没有得到用户的允许是不能关闭它的。不过,弹出窗口倒是可以调用top.close()在不经用户允许的情况下关闭自己。弹出窗口关闭之后,窗口的引用仍然存在,但除了像下面这样检测其closed属性之外,已经没有其他用处了。
wroxWin.close();
alert(wroxWin.closed); //true
弹出窗口屏蔽程序
大多数浏览器都内置有弹出窗口屏蔽程序,而没有内置此类程序的浏览器,也可以安装Yahoo!Toolbar等带有内置屏蔽程序的实用工具。结果就是用户可以将绝大多数不想看到弹出窗口屏蔽掉。
准确地检测出窗口是否被屏蔽:
var blocked = false;
try {
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null) {
blocked = true;
}
} catch (ex) {
blocked = true;
}
if (blocked) {
alert("The popup was blocked!");
}
在任何情况下,以上代码都可以检测出调用window.open()打开的弹出窗口是不是被屏蔽了。但要注意的是,检测弹出窗口是否被屏蔽只是一方面,它并不会阻止浏览器显示与被屏蔽的弹出窗口有关的消息。
间歇调用和超时调用
JavaScript是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。
超时调用需要使用window对象的setTimeout()方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。其中,第一个参数可以是一个包含JavaScript代码的字符串(就和在eval()函数中使用的字符串一样),也可以是一个函数:
//不建议传递字符串
setTimeout("alert('Hello world!') ", 1000);
//推荐的调用方式
setTimeout(function () {
alert("Hello world!");
}, 1000);
调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用。这个超时调用ID是计划执行代码的唯一标识符,可以通过它来取消超时调用。要取消尚未执行的超时调用计划,可以调用clearTimeout()方法并将相应的超时调用ID作为参数传递给它:
//设置超时调用
var timeoutId = setTimeout(function () {
alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);
超时调用的代码都是在全局作用域中执行的,因此函数中this的值在非严格模式下指向window对象,在严格模式下是undefined。
//不推荐传递字符串
setInterval("alert('Hello world!') ", 10000);
//推荐的调用方式
setInterval(function () {
alert("Hello world!");
}, 10000);
取消间歇调用的重要性要远远高于取消超时调用,因为在不加干涉的情况下,间歇调用将会一直执行到页面卸载:
var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//如果执行次数达到了max设置的值,则取消后续尚未执行的调用
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
在这个例子中,变量num每半秒钟递增一次,当递增到最大值时就会取消先前设定的间歇调用。这个模式也可以使用超时调用来实现:
var num = 0;
var max = 10;
function incrementNumber() {
num++;
//如果执行次数未达到max设定的值,则设置另一次超时调用
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
可见,在使用超时调用时,没有必要跟踪超时调用ID,因为每次执行代码之后,如果不再设置另一次超时调用,调用就会自行停止。一般认为,使用超时调用来模拟间歇调用的是一种最佳模式。在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动。
系统对话框
浏览器通过alert()、confirm()和prompt()方法可以调用系统对话框向用户显示信息。系统对话框与在浏览器中显示的网页没有关系,也不包含HTML。它们的外观由操作系统及(或)浏览器设置决定,而不是由CSS决定。此外,通过这几个方法打开的对象框都是同步和模态的。也就是说,显示这些对话框的时候代码会停止执行,而关掉这些对话框后代码又会恢复执行。
还有两个可以通过JavaScript打开的对话框,即“查找”和“打印”。这两个对话框都是异步显示的,能够将控制权立即交还给脚本。这两个对话框与用户通过浏览器菜单的“查找”和“打印”命令打开的对话框相同。而在JavaScript中则可以像下面这样通过window对象的find()和print()方法打开它们:
//显示“打印”对话框
window.print();
//显示“查找”对话框
window.find();
location对象
location是最有用的BOM对象之一。它既是window对象的属性,也是document对象的属性;换句话说,window.location和document.location引用的是同一个对象。location对象的用处不只是表现在它保存着当前文档的信息,还表现在它将URL解析weixiup独立的片段,让开发人员可以通过不同的属性访问这些片段:
查询字符串参数
function getQueryStringArgs() {
//取得查询字符串并去掉开头的问好
var qs = (location.search.length > 0 ? location.search.substring(1) : ""),
//保存数据的对象
args = {},
//取得每一项
items = qs.length ? qs.split("&") : [],
item = null,
name = null,
value = null,
//在for循环中使用
i = 0,
len = items.length;
//逐个将每一项添加到args对象中
for (i = 0; i < len; i++) {
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
位置操作
使用location对象可以通过很多方式来改变浏览器的位置。首先,也是最常用的方式,就是使用assign()方法并为其传递一个URL:
location.assign("http://www.wrox.com");
这样就可以立即打开新URL并在浏览器的历史记录中生成一条记录。如果是将location.href或window.location设置为一个URL值,也会以该值调用assign()方法,例如,下面代码与显式调用assign()方法的效果完全一样:
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
另外,修改location对象的其他属性也可以改变当前加载的页面:
//假设初始URL为:http://www.wrox.com/WileyCDA/
//将URL修改为:"http://www.wrox.com/WileyCDA/#section1"
location.hash = "#section1";
//将URL修改为:"http://www.wrox.com/WileyCDA/?q=javascript"
location.search = "?q=javascript";
//将URL修改为:"http://www.yahoo.com/WileyCDA/"
location.hostname = "www.yahoo.com";
//将URL修改为:"http://www.yahoo.com/mydir/"
location.pathname = "mydir";
//将URL修改为:"http://www.yahoo.com:8080/WileyCDA/"
location.port = 8080;
在IE8Firefox 1Safari 2+Opera 9+ Chrome中,修改hash的值会在浏览器的历史记录中生成一条新记录。在IE的早期版本中,hash属性不会在用户单击“后退”和“前进”按钮时被更新,而只会在用户单击包含hash的URL时会被更新。
当通过上述任何一种方式修改URL后,浏览器的历史记录中就会生成一条新记录,因此用户通过单击“后退”按钮都会导航到前一个页面。要禁用这种行为,可以使用replace()方法。这个方法只接受一个参数,即要导航到的URL;结果虽然会导致浏览器位置改变,但不会在历史记录中生成新记录。在调用replace()方法之后,用户不能回到前一个页面。
<!DOCTYPE html>
<html>
<head>
<title>You won't be able to get back here</title>
</head>
<body>
<p>Enjoy this page for a second, because you won't be coming back here.</p>
<script type="text/javascript">
setTimeout(function () {
location.replace("http://www.wrox.com/");
}, 1000);
</script>
</body>
</html>
如果将这个页面加载到浏览器中,浏览器就会在1秒中后重新定向到www.wrox.com。然后,“后退”按钮将处于禁用状态,如果不重新输入完整的URL,则无法返回示例页面。
与位置有关的最后一个方法是reload(),作用是重新加载当前显示的页面。如果调用reload()时不传递任何参数,页面就会以最有效的方式重新加载。也就是说,如果页面自上次请求以来并没有改变过,页面就会从浏览器缓存中重新加载。如果要强制从服务器重新加载,则需要向下面这样为方法传递参数true:
location.reload(); //重新加载(有可能从缓存中加载)
location.reload(true); //重新加载(从服务器重新加载)
位于reload()调用之后的代码可能会也可能不会执行,这样取决于网络延迟或系统资源等因素。为此,最好将reload()放在代码的最后一行。