图片库改进版
6.1 本章内容
- 把事件处理移除文档
- 向后兼容
- 确保可访问
6.2 最终代码展示
效果
点击切换
javascript代码
function showPic(whichPic) {
// 检测图片元素是否存在
if (document.getElementById("placeholder") == null) return false;
// 展示图片
var source = whichPic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
// 查看是否为IMG元素
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");
description.firstChild.nodeValue = text;
}
return true;
}
function prepareGallery() {
// 检测浏览器是否理解getElemntById()方法
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 () {
return showPic(this) ? false : true;
}
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != "function") {
window.onload = func;
} else {
window.onload = function () {
oldonload();
func();
}
}
}
addLoadEvent(prepareGallery);
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Gallery</title>
<link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen">
</head>
<body>
<h1>图片库</h1>
<ui id="imageGallery">
<li><a href="image/toWest/monkey.webp" title="悟空"><img src="image/toWest/monkey.webp" alt="悟空"></a></li>
<li><a href="image/toWest/tulv.webp" title="唐僧"><img src="image/toWest/tulv.webp" alt="唐僧"></a></li>
<li><a href="image/toWest/pig.webp" title="八戒"><img src="image/toWest/pig.webp" alt="八戒"></a></li>
<li><a href="image/toWest/wujing.webp" title="悟净"><img src="image/toWest/wujing.webp" alt="悟净"></a></li>
<li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘"><img src="image/whiteSnake/whiteSnake.webp"
alt="白娘娘"></a></li>
<li><a href="image/whiteSnake/doctor.webp" title="许仙">
<img src="image/whiteSnake/doctor.webp" alt="许仙"></a>
</li>
<li><a href="image/whiteSnake/greenSnake.webp" title="小青"><img src="image/whiteSnake/greenSnake.webp" alt="小青">
</a></li>
</ui>
<img id="placeholder" src="image/gallery.webp" alt="placeholder">
<p id="description">选择一个图片</p>
<script type="text/javascript" src="scripts/showPic.js"></script>
</body>
</html>
CSS代码
#imageGallery {
list-style: none;
margin: 0;
}
#imageGallery li {
display: inline-flex;
}
#imageGallery li a img {
max-width: 90px;
max-height: 80px;
}
#placeholder img {
display: inline-block;
margin: 0 auto;
width: 300px;
height: 400px;
}
body {
font-family: Arial, Helvetica, sans-serif;
color: #333;
background-color: #ccc;
margin: 1em 10%;
}
h1 {
color: #333;
background-color: transparent;
}
a {
color: #c60;
background-color: transparent;
font-weight: bold;
text-decoration: none;
}
ul {
padding: 0;
}
li {
float: left;
padding: 10px 10px 10px 0px;
list-style-type: none;
}
img {
display: flex;
clear: both;
max-width: 300px;
max-height: 400px;
}
6.3 回顾
原始 图片库javascript代码
function showPic(whichPic) {
// 展示图片
document.getElementById("placeholder").setAttribute("src", whichPic.getAttribute("href"));
// 显示描述
var description = document.getElementById("description");
var text = whichPic.getAttribute("title");
description.firstChild.nodeValue = text;
}
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image Gallery</title>
<link rel="stylesheet" type="text/css" href="styles/layout.css">
</head>
<body>
<h1>图片库</h1>
<ui>
<li><a href="image/toWest/monkey.webp" title="悟空" onclick="showPic(this);return false;">悟空</a></li>
<li><a href="image/toWest/tulv.webp" title="唐僧" onclick="showPic(this);return false;">唐僧</a></li>
<li><a href="image/toWest/pig.webp" title="八戒" onclick="showPic(this);return false;">八戒</a></li>
<li><a href="image/toWest/wujing.webp" title="悟净" onclick="showPic(this);return false;">悟净</a></li>
<li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘" onclick="showPic(this);return false;">白娘娘</a></li>
<li><a href="image/whiteSnake/doctor.webp" title="许仙" onclick="showPic(this);return false;">许仙</a></li>
<li><a href="image/whiteSnake/greenSnake.webp" title="小青" onclick="showPic(this);return false;">小青</a></li>
</ui>
<img id="placeholder" src="image/gallery.png" alt="placeholder">
<p id="description">选择一个图片</p>
<script type="text/javascript" src="scripts/showPic.js"></script>
</body>
</html>
6.4 它支持平稳退化吗
问题一:JS被禁用,上述代码是否能正常运行?
答案:JS被禁用,支持,点击时,通过href直接跳转到图片界面,通过浏览器回退可以进入每个界面
但是如果使用js伪协议就会出现问题,比如:
<a href="#" onclick="showPic(this);return false;">悟空</a>
因此,在href中设置路径是最好的选择。
6.5 它的JavaScript与HTML标记是否分离
网页的行为层(JavaScript)和结构层(HTML)是否分离?
答案:否
<li><a href="image/toWest/monkey.webp" title="悟空" onclick="showPic(this);return false;">悟空</a></li>
理想情况下,HTML标记应该只负责结构,JavaScript应该只负责行为。但是HTML标记中包含了JavaScript代码,这就违背了分离原则。
修改后的HTML代码如下:
<ui id="imageGallery">
<li><a href="image/toWest/monkey.webp" title="悟空">悟空</a></li>
<li><a href="image/toWest/tulv.webp" title="唐僧">唐僧</a></li>
<li><a href="image/toWest/pig.webp" title="八戒">八戒</a></li>
<li><a href="image/toWest/wujing.webp" title="悟净">悟净</a></li>
<li><a href="image/whiteSnake/whiteSnake.webp" title="白娘娘">白娘娘</a></li>
<li><a href="image/whiteSnake/doctor.webp" title="许仙">许仙</a></li>
<li><a href="image/whiteSnake/greenSnake.webp" title="小青">小青</a></li>
</ui>
对列表中相同的方法使用id=“image-gallery”
6.5.1 添加事件处理函数
事件处理函数需要实现
- 检测浏览器是否理解getElemntById()方法
- 检测浏览器是否理解getElemntByTagName()方法
- 检查网页是否存在一个id为"imageGallery"的元素
- 遍历"imageGallery"元素中的所有链接
- 设置onclick事件处理函数,点击时完成如下操作:
- 调用showPic()函数,显示图片
- 显示描述
- 阻止默认行为
function prepareGallery() {
// 检测浏览器是否理解getElemntById()方法
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;
}
}
}
6.5.2 共享onload事件处理函数
在网页加载完成后执行prepareGallery函数
window.onload = function() {
prepareGallery();
}
为了兼容可能存在要加载多个函数
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != "function") {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
addLoadEvent(prepareGallery);
到此为止,实现prepareGallery函数,可以正常运行。
6.6 不要做太多的假设
在prepareGallery函数中,我们假设了document.getElementById()方法存在,但是如果浏览器不支持该方法,该函数将无法正常运行。
因此不用在showPic函数中使用document.getElementById()方法
但是,代码里面还是假设了一定存在id为"placeholder"的元素和"description"元素,并未检测到是否存在。
因此,在showPic函数中,我们也需要添加对这两个元素的检测。这里图片显示是核心功能,描述是锦上添花,因此只做到点击图片,在占位符placeholder显示
function showPic(whichPic) {
// 检测图片元素是否存在
if (document.getElementById("placeholder") == null) 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;
}
此时,图片库改进版已经可以正常运行,并且兼容了JS被禁用情况。
后面还有一种描述不明白,“把placeholder图片从标记文档里删掉,并在浏览器刷新界面,无论点击imageGallery中的哪个链接都没有反应”?(我实测好像可以)这里记录优化方法
links[i].onclick = function() {
showPic(this);
return false;
}
// 修改为根据showPic函数返回值判断是否成功显示图片
links[i].onclick = function() {
return !showPic(this);
先这样吧,没看懂
6.7 优化
看下代码清单
function showPic(whichPic) {
// 检测图片元素是否存在
if (document.getElementById("placeholder") == null) 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;
}
这里witchPic默认存在title属性,但是如果没有title属性,则会报错,因此可以优化一下,如下:
if (whichPic.getAttribute("title")) {
var text = whichPic.getAttribute("title");
} else {
var text = "";
}
// 或者
var text = whichPic.getAttribute("title") ? whichPic.getAttribute("title") : "";
检查description元素是否为文本
if (document.getElementById("description") && document.getElementById("description").firstChild.nodeType == 3) {
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
}
在一般工作中,可以根据需要进行判断
6.8 键盘访问
现在代码假设用户只能通过鼠标点击图片,但是如果用户通过键盘Tab键切换到图片,则无法触发事件。
这里添加onkeypress事件处理函数,按下tab可以移动链接,按下enter可以触发事件。
links[i].onkeypress = function(event) {
if (event.keyCode == 13) {
if (showPic(this)) ? true : false;
}
}
书里原文是按下任意键可以触发事件
links[i].onkeypress = links[i].onclick;
这里就是js和html分离的好处,可以让html代码更加简洁,js代码可以更加灵活。
实际上,在几乎所有浏览器,tab键都可以切换到链接,enter键就可以触发onclick事件。因此,这里的优化并没有带来实际的好处。
6.9 把JavasScript与CSS结合起来
css可以设置图片的大小,位置,边框等,可以让图片库更加美观。
在head标签中加入如下代码:
<link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen">
在css文件,利用id="imageGallery"中加入如下代码:
这个地方和书里不一样,我百科下载的图片,大小不一,调整了一下样式
最终css代码如下:
#imageGallery {
list-style: none;
margin: 0;
}
#imageGallery li {
display: inline-flex;
}
#imageGallery li a img {
max-width: 90px;
max-height: 80px;
}
#placeholder img {
display: inline-block;
margin: 0 auto;
width: 300px;
height: 400px;
}
body {
font-family: Arial, Helvetica, sans-serif;
color: #333;
background-color: #ccc;
margin: 1em 10%;
}
h1 {
color: #333;
background-color: transparent;
}
a {
color: #c60;
background-color: transparent;
font-weight: bold;
text-decoration: none;
}
ul {
padding: 0;
}
li {
float: left;
padding: 10px 10px 10px 0px;
list-style-type: none;
}
img {
display: flex;
clear: both;
max-width: 300px;
max-height: 400px;
}
把图片链接转换成微缩图。
<a href="image/toWest/monkey.webp" title="悟空">
<img src="image/toWest/monkey.webp" alt="悟空">
</a>
6.10 DOM Core和HTML-DOM
这里使用的DOM方法getElemntById()、getElementsByTagName()、setAttribute()和getAttribute()等都是DOM Core中的方法。
不单单js,HTML等标记语言也可以用
HTML-DOM的方法onkeypress()、onclick()等都是HTML-DOM中的方法。
在HTML-DOM提供了许多描述HTML元素的属性,如获取图片src属性
var img = element.getElementById("myImg");
// 也可以使用
var img = element.src;
这些属性和方法可以互换
本书主要使用DOM Core中的方法,HTML-DOM中的方法可以作为补充。
6.11后记
本章主要介绍了图片库的改进版,主要内容是:
- 事件处理移除文档
- 向后兼容
- 确保可访问
结构和行为分离的程度越大越好。
下章将介绍如何利用DOM提供的方法和属性去创建HTML元素,并插入HTML文档中。
6.12参考
- HTML DOM
- 《JavaScprpt DOM 编程艺术(第2版)》
- 主要内容由Fitten Code生成, 强烈推荐