如下:原始的JavaScript图片库
JavaScript代码如下:
function showPic(whichpic){
var source=whichpic.getAttribute("href");
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
var text=whichpic.getAttribute("title");
var description=document.getElementById("description");
description.firstChild.nodeValue=text;
}
调用此函数的HTML文件:
<!DOCTYPE html>
<html>
<head>
<title>Image Gallery</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
<a href="images/1.jpg" title="美丽的风景一" onclick="showPic(this); return false;">风景一</a>
</li>
<li>
<a href="images/2.jpg" title="美丽的风景二" onclick="showPic(this); return false;">风景二</a>
</li>
<li>
<a href="images/3.jpg" title="美丽的风景三" onclick="showPic(this); return false;">风景三</a>
</li>
<li>
<a href="images/4.jpg" title="美丽的风景四" onclick="showPic(this); return false;">风景四</a>
</li>
</ul>
<img id="placeholder" src="images/5.jpg" alt="my image gallery"/>
<p id="description">choose an image.</p>
<script src="scripts/showPic.js"></script>
</body>
</html>
问题:我们将从平稳退化,向后兼容,分离JavaScript这几方面来改进
一:是否支持平稳退化
如果用户的浏览器禁用了JavaScript功能会怎样?通过检查代码,我们的脚本已经为此留出了退路,即使JavaScript功能被禁用,用户也可以浏览图片库里的图片,所有链接正常工作。只不过用户体验会比JavaScript差一点,但网页的基本内容并未受到损害。
<li>
<a href="images/1.jpg" title="美丽的风景一" onclick="showPic(this); return false;">风景一</a>
</li>
图片库通过了第一个测试。
二:它的JavaScript与HTML标记是分离的吗
<li>
<a href="images/1.jpg" title="美丽的风景一" onclick="showPic(this); return false;">风景一</a>
</li>
如上图片库的代码,明显网页的行为层(JavaScript)与其结构层(HTML)混杂在一起。
我们可以给图片库的每一个链接里添加一个class属性将JavaScript代码与HTML文档关联起来,但是分别添加事件处理函数很麻烦,所以我们可以给整个清单设置一个独一无二的ID要简单的多。
<ul id="imagegallery">
<li>
<a href="images/1.jpg" title="美丽的风景一" onclick="showPic(this); return false;">风景一</a>
</li>
...
</ul>
(1)添加事件处理函数
现在需要编写一个简短的函数把有关操作关联到onclick事件上,命名为prepareGallery,下面是我想让这个函数完成的工作:
检查当前浏览器是否理解getElementsByTagName;
检查当前浏览器是否理解getElementById;
检查当前网页是否出存在一个id为imagegallery的元素;
遍历imagegallery元素中的所有链接;
设置onclick事件,让它在有关链接被点击时完成以下操作:把这个链接作为参数传递给showPic函数,取消链接被点击时的默认行为,不让浏览器打开这个链接;
按这个过程完成JavaScript函数:
function prepareGallery(){
//检查点
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById("imagegallery")) return false;
//创建变量
var gallery=document.getElementById("imagegallery");
var links=gallery.getElementsByTagName("a");
//遍历
for (var i = 0; i< links.length; i++) {
//改变行为
links[i].onclick=function(){
showPic(this);
return false; //阻止浏览器打开默认链接行为
}
}
}
(2)共享onload事件
如果在HTML文档完成加载之前执行脚本,此时的DOM是不完整的,我们应该让prepareGallery函数在网页加载完毕之后立刻执行,网页加载完毕会触发一个onload事件,这个事件与window对象相关联,为了让事态的发展不偏离计划,必须把prepareGallery函数绑定到这个事件上,若要加载完毕时执行多个函数可以用addLoadEvent函数:
//页面加载完毕时执行函数
function addLoadEvent(func) {
var oldonload=window.onload; //把现有的window.onload事件处理函数的值存入变量
if (typeof window.onload!='function') {
window.onload=func; //若事件处理函数还未绑定函数,将新函数添加给它
}else{
window.onload=function(){ //若已经绑定了,就将新函数添加到现有指令的末端
oldonload();
func();
}
}
// body...
}
上面addLoadEvent函数可将页面加载完毕时执行的函数创建为一个队列,当我们执行函数prepareGallery时只需写出下面这行代码:
addLoadEvent(prepareGallery);
三.不要做太多假设
我们需要增加一些语句检查元素placeholder和description是否存在:
function showPic(whichpic){
if (!document.getElementById("placeholder")) return false; //函数必须完成的任务
var source=whichpic.getAttribute("href");
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (document.getElementById("description")) { //这个描述属于锦上添花
var text=whichpic.getAttribute("title");
var description=document.getElementById("description");
description.firstChild.nodeValue=text;
}
return true;
}
但是又有一个问题,当把placeholder图片从标记文档里删掉再刷新页面,就会出现无论点击imagegallery清单里哪一个链接都没有响应,这说明不能平稳退化,因此我们要以showPic()函数的返回值设置onclick事件的默认行为:
links[i].onclick=function(){
return !showPic(this); //图片切换成功返回true,切换不成功返回false
}
四.优化
我们对showPic()函数进行优化,假设每个链接都有一个title,那么我们要检查title属性是否真的存在,存在就返回true,并且text变量被赋值为title值;若不存在,返回false,则text将被赋值为一个空字符串(“ ”)。
if (whichpic.getAttribute("title")){
var text=whichpic.getAttribute("title");
}else{
var text="";
}
或者另一种方法:
var text=whichpic.getAttribute("title")?whichpic.getAttribute("title"):" "; //?是一个三元运算符,问号后面是变量的两种可能取值
五.键盘访问
在showPic()函数中,链接都是通过鼠标点击实现,然而有些人更喜欢使用键盘来点击,我们可以通过tab键从这个链接移动到另一个链接,然后按下回车键启用当前连接,有个onkeypress的事件处理函数专门用来处理键盘事件:
links[i].onclick=function(){
return showPic(this)?false:true;
}
links[i].onkeypress=links[i].onclick;
但是我们一般不用onkeypress事件处理函数,因为这将会使那些只使用键盘访问的用户将永远无法离开当前链接。而onclick事件处理函数已经能满足需要,且它对键盘访问的支持相当完美。
六.把JavaScript与CSS结合起来
关于CSS的用法在这里将不再详述。
七.DOM Core和HTML-DOM
以上javascript代码只用到以下几个DOM方法:
getElementById
getElementsByTagName
getAttribute
setAttribute
这些都是DOM Core的组成部分,它们并不专属于Javascript,支持DOM的任何一种程序设计语言都可以使用它们。
在使用javascript语言和DOM为HTML文件编写脚本时,还有很多属性可供选择,例如onclick,这些属性属于HTML-DOM,它在DOM Core出现之前 就已经被人们熟悉,HTML-DOM可以将如下语句简化:
document.getElementsByTagName("form"); 简化为:document.forms
element.getAttribute("src"); 简化为:element.src
var source=whichpic.getAttribute("href"); 简化为 var source=whichpic.href
placeholder.setAttribute("src",source); 简化为 placeholder.src=source;
一般DOM Core方法更容易使用,但可以根据个人喜好和具体情况作出选择。