前言:在《DOM编程艺术》中初步实现的图片库的总结(一)中,有很多不足之处:比如事件处理嵌套在HTML中,显得如此笨重和屌丝;没有对showPic函数进行相应的安全检查等,本篇文章对上述问题做了全面的升级。
--------------------开始---------------------
1.首先要把HTML
部分进行改造
去掉嵌套在HTML
中的事件处理代码,并且为了js能操作<ul>
标签,需要对<ul>
标签添加ID属性值
<h1>电影天堂</h1>
<ul id="filmlist">
<li>
<a href="images/01灰姑娘.jpg" title="灰姑娘">灰姑娘</a>
</li>
<li>
<a href="images/02千与千寻.jpg" title="千与千寻">千与千寻</a>
</li>
<li>
<a href="images/03哆啦A梦.jpg" title="哆啦A梦">哆啦A梦</a>
</li>
<li>
<a href="images/04当幸福来敲门.jpg" title="当幸福来敲门">当幸福来敲门</a>
</li>
</ul>
<!--占位符图片-->
<img id="placeholder" src="images/placeholder.jpg" alt="hehehe">
<!--一段描述-->
<p id="description">选择一张图片</p>
2.获取<ul>
标签中的节点a
,遍历并且绑定事件处理
function prepareFilm(){
if(!document.getElementsByTagName){
return false;
}
if(!document.getElementById){
return false;
}
if(!document.getElementById("filmlist")){
return false;
}
var list = document.getElementById("filmlist");
var links = list.getElementsByTagName("a");
for(var i = 0; i<links.length; i++){
links[i].onclick = function(){
showPic(this);
return false;
}
}
}
3.本例非必需:共享onload
事件
本例中必须执行prepareFilm
函数才能对onclick
事件进行绑定,但是这个函数又不能在HTML文档加载之前执行,网页加载完毕时会触发一个onload
事件,但是需要执行的函数有多个逐一添加又麻烦,而且后续的函数会覆盖上一个,所以就有必要封装一个addLoadEvent
函数把将要执行的函数作为参数传进去,
//共享onlond事件,封装成一个函数,@func是页面加载时需要执行的那个函数。
//如果window.onload在页面加载时还没有绑定任何函数,就把需要执行的函数添加给它、
//如果这个处理函数已经绑定了函数,就把新函数追加到现有指令的末尾
function addLoadEvent(func){
//把现有的window.onload存入变量oldonload
var oldonload = window.onload;
if(typeof window.onload != 'function'){
window.onload = func;
}else{
window.onload = function(){
oldonload();
func();
}
}
}
但是这个时候还有一些bug,就是没有对showPic
函数进行必要的安全检查,而showPic
函数要被prepareFilm
函数调用,假如它获取不到图片呢?
4.对showPic
函数进行安全检查
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;
}
但是还是有问题,就是此时prepareFilm
函数做了一个假设:showPic
函数肯定会正常返回,基于这一假设,prepareFilm
函数在执行showPic
函数时就会提前返回一个true,从而取消了onclick事件的默认行为。所以是否要返回一个false值取消onclick默认行为,应该由showPic函数决定,图片切换成功返回true,图片切换失败,返回false。
所以此时应该把prepareFilm
函数最后两句改为:return !showPic(this);
5.添加更多的检查
(1)假设每个链接都有title属性,假如不存在把text值设置为空;
(2)placeholder是否存在?假设那是一张图片(本例中它确实是图片),为了验证这个情况,可以用nodeName属性增加这一项测试。
下面是添加更多的检查之后的showPic函数代码:
function showPic(whichpic){
if(!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
if(placeholder.nodeName != "IMG") return false;
placeholder.setAttribute("src" , source);
if(document.getElementById("description")){
var text = whichpic.getAttribute("title")?whichpic.getAttribute("title"):"";
var description = document.getElementById("description");
if(description.firstChild.nodeType == 3){
description.firstChild.nodeValue = text;
}
}
return true;
}
6.调用addLoadEvent
函数
//在页面加载完成后调用prepareFilm函数
addLoadEvent(prepareFilm);
7.完整代码
老规矩,上完整源码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>example</title>
<style>
h1 {
color: #333;
}
a {
color: gray;
font-weight: bold;
text-decoration: none;
}
ul {
padding: 0;
}
li {
float: left;
padding: 1em;
list-style-type: none;
}
img {
display: block;
clear: both;
}
</style>
</head>
<body>
<h1>电影天堂</h1>
<ul id="filmlist">
<li>
<a href="images/01灰姑娘.jpg" title="灰姑娘">灰姑娘</a>
</li>
<li>
<a href="images/02千与千寻.jpg" title="千与千寻">千与千寻</a>
</li>
<li>
<a href="images/03哆啦A梦.jpg" title="哆啦A梦">哆啦A梦</a>
</li>
<li>
<a href="images/04当幸福来敲门.jpg" title="当幸福来敲门">当幸福来敲门</a>
</li>
</ul>
<!--占位符图片-->
<img id="placeholder" src="images/placeholder.jpg" alt="hehehe">
<!--一段描述-->
<p id="description">选择一张图片</p>
<!--以下是js代码-->
<script>
function showPic(whichpic){
if(!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
if(placeholder.nodeName != "IMG") return false;
placeholder.setAttribute("src" , source);
if(document.getElementById("description")){
var text = whichpic.getAttribute("title")?whichpic.getAttribute("title"):"";
var description = document.getElementById("description");
if(description.firstChild.nodeType == 3){
description.firstChild.nodeValue = text;
}
}
return true;
}
function prepareFilm(){
if(!document.getElementsByTagName){
return false;
}
if(!document.getElementById){
return false;
}
if(!document.getElementById("filmlist")){
return false;
}
var list = document.getElementById("filmlist");
var links = list.getElementsByTagName("a");
for(var i = 0; i<links.length; i++){
links[i].onclick = function(){
return showPic(this)?false:true;
}
}
}
//共享onlond事件,封装成一个函数,@func是页面加载时需要执行的那个函数。
//如果window.onload在页面加载时还没有绑定任何函数,就把需要执行的函数添加给它、
//如果这个处理函数已经绑定了函数,就把新函数追加到现有指令的末尾
function addLoadEvent(func){
//把现有的window.onload存入变量oldonload
var oldonload = window.onload;
if(typeof window.onload != 'function'){
window.onload = func;
}else{
window.onload = function(){
oldonload();
func();
}
}
}
//在页面加载完成后调用prepareFilm函数
addLoadEvent(prepareFilm);
</script>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。