《JavaScript DOM 编程艺术》是JavaScript入门级的书,主要以案例形式推进学习,下面是我的读书笔记。
第二章 JavaScript语法
1、用JavaScript编写的代码必须通过HTML/XHTML文档才能执行。
第一种方式是将JavaScript代码放到文档<head>标签中的<script>标签之间。
一种更好的方式是把JavaScript代码存为一个扩展名为.js的独立文件。
最好的做法是把<script>标签放到HTML文档的最后,</body>标签之前,这样能使浏览器更快的加载页面。
2、JavaScript注释 :
单行//,多行/**/
3、数据类型:
(1)字符串必须包在引号里,单引号或双引号都可以。在整个脚本中保持一致。
例如:var mood=‘happy’;
var mood1=”happy”;
(2)数值
例如:var age=33.25;
(3)布尔型
例如:var married=true;
4、数组:在JavaScript中,数组可以用关键字Array声明。声明数组的同时还可以指定数组的初始元素个数,也就是这个数组的长度。
例如:var beatles=Array(4);
无法预知某个数组有多少个元素时,可以在声明数组时不给出元素个数。
例如:var beatles=Array();
填充数组
例如:beatles[0]=”John”;
beatles[1]=”Paul”;
beatles[2]=”George”;
beatles[3]=”Ringo”;
声明数组的同时对它进行填充
例如:var beatles=Array(“John”,”Paul”,”George”,”Ringo”);
var beatles=[“John”,”Paul”,”George”,”Ringo”];
数组元素不必非得是字符串,可以把一些布尔值存入一个数组,可以把一组数组存入一个数组,甚至可以把这3种数据类型混在一起存入一个数组。
例如:var lennon=[“John”,1940,false];
5、对象:与数组类似,对象也是使用一个名字表示一组值。对象的每个值都是对象的一个属性。使用点号获取属性。
例如:var lennon=Object();
lennon.name="John";
lennon.year=1998;
lennon.living=false;
创建对象还有一种更简洁的语法,即花括号语法。
var lennon={name:"John",year:1940,living:false};
用对象来代替传统数组的做法意味着可以通过元素的名字而不是下标数字来引用它们,这大大提高脚本的可读性。
创建一个新的beatles数组,并用刚才创建的lennon对象来填充它的第一个元素。
var beatles=Array();
beatles[0]=lennon;
我们不是使用beatles[0][0]而是使用beatles[0].name得到值”John”。
在此基础上,做进一步的改进:把beatles数组也声明为对象而不是传统数组。这样一来,我们就能使用更有意义且更容易记忆的字符串值作为下标去访问这个数组里的元素了。
var beatles={};
beatles.vocalist=lennon;
6、函数:
一个简单的示例函数:function shout(){
var beatles=Array("John","Paul","George","Ringo");
for (var count=0;count<beatles.length;count++) {
alert(beatles[count]);
}
}
shout();
定义一个函数的语法:
function name(arguments){
statements;
}
我们把传递给函数的数据成为参数(arguments)。
例如:function multiply(num1,num2){
var total=num1*num2;
alert(total);
}
multiply(2,5);
函数不仅能够(以参数的形式)接收数据,还能够返回数据。返回一个数值、一个字符串或一个布尔值。这需要用到return语句。
例如:function multiply(num1,num2){
var total=num1*num2;
return total;
}
我们可以把函数当做一种数据类型来使用,这意味着可以把一个函数的调用结果赋给一个变量。
例如(把华氏温度值95转化为摄氏温度值):function convertToCelsius(temp){
var result=temp-32;
result=result/1.8;
return result;
}
var temp_fahrenheit=95;
var temp_celsius=convertToCelsius(temp_fahrenheit);
alert(temp_celsius);
命名规则:在命名变量时,用下划线来分隔各个单词,在命名函数时,从第二个单词开始把每个单词的第一个字母写成大写形式(也就是所谓的驼峰命名法)。
7、变量的作用域:
如果在某个函数中使用了var,那个变量就将被视为一个局部变量,它只存在于这个函数的上下文中;反之,如果没有使用var,那个变量就将被视为一个全局变量。
例如:
function square(num){
var total=num*num;//局部变量
return total;
}
var total=50;
var number=square(20);
alert(total);//结果为50
function square(num){
total=num*num;//全局变量
return total;
}
var total=50;
var number=square(20);
alert(total);//结果为400
8、对象:对象是由一些属性和方法组合在一起而构成的一个数据实体。
包含在对象里的数据可以通过属性和方法访问。
属性是隶属于某个特定对象的变量。方法是只有某个特定对象才能调用的函数。
在JavaScript里,属性和方法都用”点”语法来访问。
Object.property
Object.method();
JavaScript语言里的对象可以分为三种类型:
9、用户定义对象:创建对象的实例。实例是对象的具体个体。
为给定对象创建一个新实例需要使用new关键字。例如:var jeremy=new Person;
JavaScript里并没有Person对象,我们可以利用JavaScript来创建自己的对象,术语为用户自定义对象。
10、内建对象:JavaScript提供了一系列预先定义好的对象,这些可以拿来用的对象称为内建对象。
(1)数组就是内建对象。当我们使用new关键字去初始化一个数组时,其实是在创建一个Array对象的新实例。var beatles=new Array();
当需要了解某个数组有多少元素时,利用Array对象的length属性来获得这一信息。beatles.length;
(2)Math对象:Math对象的round方法可以把十进制数值舍入为一个与之最接近的整数。
var num=7.561;
var num=Math.round(num);
alert(num);
(3)Date对象;Date对象可以用来存储和检索与特定日期和时间有关的信息。JavaScript解释器将自动地使用当前日期和时间对它进行初始化。Date对象提供了getDate()、getHours()、getMonth()等一系列方法。例如getDate()方法告诉我们给定的日期是星期几。
var current_date=new Date();
var today=current_date.getDay();
alert(today);
11、宿主对象:这些对象不是由JavaScript语言本身而是由它的运行环境提供的。这个环境就是浏览器。由浏览器提供的预定义对象被称为宿主对象。
宿主对象包括Form、Image、Element等。我们可以通过这些对象获得关于网页上表单、图像和各种表单元素等信息。
另外一种宿主对象也能用来获得网页上的任何一个元素的信息,它就是document对象。
第三章 DOM
1、DOM:
(1)文档:DOM中的D
当创建了一个网页并把它加载到Web浏览器中时,DOM就在幕后悄然而生。它把你编写的网页文档转换为一个文档对象。
(2)对象:DOM中的O
document对象的只要功能就是处理网页的内容。
(3)模型:DOM中的M
DOM代表着加载到浏览器窗口的当前网页。浏览器提供了网页地图(模型),而我们可以通过JavaScript去读取这个地图(模型)。
2、节点
(1)元素节点:标签的名字就是元素的名字。例如:文本段落元素的名字是“p”。
(2)文本节点:<p>元素包含着文本”Don’t forget to buy this stuff”。它是一个文本节点。文本节点总是包含在元素节点的内部。但并非所有的元素节点都包含有文本节点。例如<ul>没有包含任何文本节点,它包含着其他的元素节点(一些<li>元素),后者包含着文本节点。
(3)属性节点:例如几乎所有的元素都有一个title属性,而我们可以利用这个属性对包含在元素里的东西做出准确的描述。在DOM中,title=”a gengle reminder”是一个属性节点。属性节点总是被包含在元素节点中。并非所有的元素都包含着属性,但所有的属性都被元素包含。
3、获取元素
(1)getElementById
document.getElementById(id);这个调用将返回一个对象,这个对象对应着document对象里的一个独一无二的元素,那个元素的HTMLid属性值是XX,可以用typeof操作符来验证这一点。typeof操作符可以告诉我们它的操作数是一个字符串、数值、函数、布尔值还是对象。
例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>what to buy</h1>
<p title="a gentle reminder">Don't forget to buy this stuff</p>
<ul id="purchases">
<li>A tin of beans</li>
<li class="sale">Cheese</li>
<li class="sale important">Milk</li>
</ul>
<script type="text/javascript">
alert(typeof document.getElementById("purchases"));
</script>
</body>
</html>
(2)getElementsByTagName
getElementsByTagName方法返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。类似于getElementById,这个方法也是只有一个参数的函数,它的参数是标签的名字。
element.getElementsByTagName(tag)
返回的是一个对象数组。这个数组里的每个元素都是一个对象。可以通过一个循环语句和typeof操作符去遍历这个数组来验证这一点。
var items=document.getElementsByTagName("li");
for(var i=0;i<items.length;i++){
alert(typeof items[i]);
}
把getElementById和getElementsByTagName结合起来运用。
例如:前面的例子都是通过document对象调用getElementsByTagName的,如果只想知道id属性值是purchases的元素包含着多少个列表项,必须通过一个更具体的对象去调用这个方法。
var shopping=document.getElementById("purchases");
var items=shopping.getElementsByTagName("*");
alert(items.length);
(3)getElementsByClassName
getElementsByClassName这个方法让我们能够通过class属性中的类名来访问元素。
与getElementsByTagName方法类似,getElementsByClassName这个方法也只接受一个参数,就是类名。
getElementsByClassName(class);
这个方法的返回值也与getElementsByTagName类似,都是一个具有相同类名的元素的数组。
例如:var shopping=document.getElementById("purchases");
var sales=shopping.getElementsByClassName("sale");
alert(sales.length);
4、获取和设置属性
(1)getAttribute
getAttribute函数只有一个参数:你打算查询的属性的名字。
object.getAttribute(attribute);
与我们之前介绍过的方法不同,getAttribute方法不属于document对象,所以不能通过document对象调用,它只能通过元素节点对象调用。
例如:var paras=document.getElementsByTagName("p");
for(var i=0;i<paras.length;i++){
var title_text=paras[i].getAttribute("title");
if(title_text)
alert(title_text);
}
(2)setAttribute
setAttribute()允许我们对属性节点的值做出修改。与getAttribute一样,setAttribute也只能用于元素节点。
object.setAttribute(attribute,value);
例如:var shopping=document.getElementById("purchases");
alert(shopping.getAttribute("title"));
shopping.setAttribute("title","a list of goods");
alert(shopping.getAttribute("title"));
如果setAttribute用在属性原先不存在的节点上,会先创建这个属性,然后设置它的值。如果setAttribute用在一个本身就有这个属性的元素节点上,这个属性的值就会被覆盖掉。
例如:var paras=document.getElementsByTagName("p");
for(var i=0;i<paras.length;i++){
var title_text=paras[i].getAttribute("title");
if(title_text){
paras[i].setAttribute("title","brand new title text");
alert(paras[i].getAttribute("title"));
}
}
setAttribute做出的修改不会反应在文档本身的源代码里。
第四章 案例研究:JavaScript图片库
案例:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Image</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
<a href="img/Qingdao1.jpg" title="五四广场">五四广场</a>
</li>
<li>
<a href="img/Qingdao2.jpg" title="栈桥">栈桥</a>
</li>
<li>
<a href="img/Suzhou1.jpg" title="苏博">苏州博物馆</a>
</li>
<li>
<a href="img/Suzhou2.jpg" title="寒山寺">寒山寺</a>
</li>
</ul>
<img id="placeholder" src="img/default.jpg" alt="default image">
<script src="gallery.js"></script>
</body>
</html>
JavaScript:
//whichPic代表着一个元素节点,即指向某个图片的<a>元素
function showPic(whichPic){
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
}
1、事件处理函数:
在特定事件发生时调用特定的JavaScript代码。例如,如果想在鼠标指针悬停在某个元素上时触发一个动作,就需要使用onmouseover事件处理函数,如果想在鼠标指针离开某个元素时触发一个动作,就需要使用onmouseout事件处理函数。想在用户单击某个链接时触发一个动作,就需要使用onclick事件处理函数。
this关键字:“这个对象”
添加事件处理函数的语法如下所示:
event=”JavaScript statement(s)”
我们可以把任意数量的JavaScript语句放在这对引号之间,只要把各条语句用分号隔开即可。
onclick="showPic(this);" //this表示这个<a>元素节点
这时我们会遇到一个问题:点击这个链接时,不仅showPic函数被调用。链接被点击的默认行为也会被调用。
事件处理函数的工作机制:在给某个元素添加了事件处理函数后,一旦事件发生,相应的JavaScript代码就会得到执行。被调用的JavaScript代码可以返回一个值,这个值将被传递给那个事件处理函数。例如,我们给某个链接添加一个onclick事件处理函数(把onclick事件处理函数作为属性嵌入<a>标签),并让这个事件处理函数所触发的JavaScript代码返回布尔值true或false。当这个链接被点击时,如果那段JavaScript代码返回的值是true,onclick事件处理函数就认为“这个链接被点击了”;反之,如果返回的值是false,onclick事件处理函数就认为“这个链接没有被点击”。
<a href="http://www.baidu.com" onclick="return false;">baidu </a>
当点击这个链接时,因为onclick事件处理函数所触发的JavaScript代码返回给它的值是false,所以这个链接的默认行为没有被触发。
下面是修改后的版本:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Image</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
<a href="img/Qingdao1.jpg" onclick="showPic(this); return false;" title="五四广场">五四广场</a>
</li>
<li>
<a href="img/Qingdao2.jpg" onclick="showPic(this); return false;" title="栈桥">栈桥</a>
</li>
<li>
<a href="img/Suzhou1.jpg" onclick="showPic(this); return false;" title="苏博">苏州博物馆</a>
</li>
<li>
<a href="img/Suzhou2.jpg" onclick="showPic(this); return false;" title="寒山寺">寒山寺</a>
</li>
</ul>
<img id="placeholder" src="img/default.jpg" alt="default image">
<script src="gallery.js"></script>
</body>
</html>
JavaScript:
//whichPic代表着一个元素节点,即指向某个图片的<a>元素
function showPic(whichPic){
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
}
2、childNodes属性:获取任何一个元素的所有子元素,它是一个包含这个元素全部子元素的数组。
用法element.childNodes
例如:
function countBodyChildren(){
var body_element=document.getElementsByTagName("body")[0];
alert(body_element.childNodes.length);
}
window.onload=countBodyChildren;
3、nodeType属性:
用法:node.nodeType
元素节点的nodeType属性值是1,属性节点的nodeType属性值是2,文本节点的nodeType属性值是3。
4、nodeValue属性:用来得到(和设置)一个节点的值。(改变某个元素节点所包含的文本)
用法:node.nodeValue
5、firstChild和lastChild属性:
childNodes[0]可以写为firstChild。
node.firstChild等价于node.childNodes[0]
DOM还提供里一个与之对应的lastChild属性。
node.firstChild代表着childNodes数组的最后一个元素。等价于node.childNodes[node.childNodes.length-1]。
最终版本(添加了图片的文字描述,描述内容为title的值):
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Image</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
<a href="img/Qingdao1.jpg" onclick="showPic(this); return false;" title="五四广场">五四广场</a>
</li>
<li>
<a href="img/Qingdao2.jpg" onclick="showPic(this); return false;" title="栈桥">栈桥</a>
</li>
<li>
<a href="img/Suzhou1.jpg" onclick="showPic(this); return false;" title="苏博">苏州博物馆</a>
</li>
<li>
<a href="img/Suzhou2.jpg" onclick="showPic(this); return false;" title="寒山寺">寒山寺</a>
</li>
</ul>
<img id="placeholder" src="img/default.jpg" alt="default image">
<p id="description">Image description</p>
<script src="gallery.js"></script>
</body>
</html>
JavaScript:
//whichPic代表着一个元素节点,即指向某个图片的<a>元素
function showPic(whichPic){
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
var text=whichPic.getAttribute("title");
var description=document.getElementById("description");
description.firstChild.nodeValue=text;
}
第五章 最佳实践
1、JavaScript使用window对象的open()方法来创建新的浏览器窗口。这个方法有三个参数:
window.open(url,name,features)
这三个参数都是可选的。
第一个参数是想在新窗口里打开的网页URL地址。如果省略这个参数,屏幕上将弹出一个空白的浏览器窗口。
第二个参数是新窗口的名字。可以在代码里通过这个名字与新窗口进行通信。
最后一个参数是一个以逗号分隔的字符串,其内容是新窗口的各种属性。这些属性包括新窗口的尺寸(宽度和高度)以及新窗口被启用或禁用的各种浏览功能(工具条、菜单条、初始位置等等)。对于这个参数应该掌握以下原则,新窗口的浏览功能要少而精。
例如:
function popUp(winURL){
window.open(winURL,"popUp","width=480,height=550");
}
调用popUp函数的一个方法是使用伪协议。
2、“javascript:”伪协议 :
“真”协议用来在因特网上的计算机之间传输数据包,如HTTP协议、FTP协议等。伪协议则是一种非标准化的协议。“javascript:”伪协议让我们通过一个链接来调用JavaScript函数。
<a href="javascript:popUp('http://www.baidu.com');">Example</a>
这条语句在支持“javascript:”伪协议的浏览器中运行正常,较老的浏览器会尝试打开那个链接但失败,支持这种伪协议但禁用了JavaScript功能的浏览器会什么也不做。这种做法非常不好。
另外的做法:
<a href="#" onclick="popUp('http://www.baidu.com'); return false;">Example</a>
因为HTML指令里使用了return false语句,这个链接不会真的被打开。
很遗憾,这个技巧与“javascript:”伪协议调用JavaScript代码的做法同样槽糕,因为它们都不能平稳退化。如果用户已经禁用了浏览器的JavaScript功能,这样的链接将毫无用处。(机器人把各种网页添加到搜索引擎的数据库里,目前只有极少数的机器人能够理解JavaScript代码)
改进的做法:
<a href="http://www.baidu.com/" onclick="popUp(this.href); return false;">Example</a>
在此前介绍的所有技巧当中,这个技巧是最有用的,但它还有改进的余地。这个技巧最明显的不足是,每当需要打开新窗口时,就不得不把一些JavaScript代码嵌入标记文档中。如果能把包括时间处理函数在内的所有JavaScript代码全部放在外部文件里,这个技巧将更加完善。
3、分离JavaScript
可以在外部JavaScript文件里把一个事件添加到HTML文档中的某个元素上。
element.event=action
例如:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="img/default.jpg" class="popUp">popUp</a>
<a href="http://www.baidu.com/">Example</a>
</body>
<script src="js/popUp.js"></script>
</html>
JavaScript:
window.onload=prepareLinks;
function prepareLinks(){
var links=document.getElementsByTagName("a");
for(var i=0;i<links.length;i++){
if(links[i].getAttribute("class")=="popUp"){
links[i].onclick=function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
function popUp(winURL){
window.open(winURL,"popUp","width=480,height=550");
}
4、性能考虑
(1)尽量少访问DOM和尽量减少标记
(2)合并和放置脚本
例如:
<script src="js/functionA.js"></script>
<script src="js/functionB.js"></script>
<script src="js/functionC.js"></script>
<script src="js/functionD.js"></script>
推荐的做法是把functionA.js、functionB.js、functionC.js、functionD.js合并到一个脚本文件中。这样,可以减少加载页面时发送的请求数量,而减少请求数量通常都是在性能优化时首先考虑的。
(3)压缩脚本
所谓压缩脚本,指的是把脚本文件中不必要的字节,如空格和注释,统统删除,从而达到“压缩”文件的目的。
通常,为了与非精简版本分开,最好在精简副本的文件名加上min字样。
第六章 案例研究:图片库改进版
1、第四章图片库改进(JavaScript与HTML分离)
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Image</title>
</head>
<body>
<h1>Snapshots</h1>
<ul id="imggallery">
<li>
<a href="img/Qingdao1.jpg" title="五四广场">五四广场</a>
</li>
<li>
<a href="img/Qingdao2.jpg" title="栈桥">栈桥</a>
</li>
<li>
<a href="img/Suzhou1.jpg" title="苏博">苏州博物馆</a>
</li>
<li>
<a href="img/Suzhou2.jpg" title="寒山寺">寒山寺</a>
</li>
</ul>
<img id="placeholder" src="img/default.jpg" alt="default image">
<p id="description">Image description</p>
<script src="js/gallery.js"></script>
</body>
</html>
JavaScript:
function showPic(whichPic){
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
var text=whichPic.getAttribute("title");
var description=document.getElementById("description");
description.firstChild.nodeValue=text;
}
window.onload=prepareGallery;
function prepareGallery(){
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById("imggallery")) return false;
var gallery=document.getElementById("imggallery");
var links=gallery.getElementsByTagName("a");
for(var i=0;i<links.length;i++){
links[i].onclick=function(){
showPic(this);
return false;
}
}
}
2、匿名函数:在代码执行时创建函数的办法。
3、假设有两个函数:firstFunction和secondFunction。如果想让它们俩都在页面加载时得到执行,应该怎么办?
如果把他们逐一绑定到onload事件上,它们当中只有最后的那个才会被实际执行。
window.onload=firstFunction;
window.onload=secondFunction;
secondFunction将取代firstFunction。
(1)可以先创建一个匿名函数来容纳这两个函数,然后把那个匿名函数绑定到onclick事件上。
window.onload=function(){
firstFunction();
secondFunction();
}
(2)弹性最佳的解决方案:
函数addLoadEvent,只有一个参数:打算在页面加载完毕时执行的函数的名字。
下面时addLoadEvent函数的代码清单:
function addLoadEvent(func){
var oldonload=window.onload;
if(typeof window.onload!='function'){
window.onload=func;
}else{
window.onload=function(){
oldonload();
func();
}
}
}
这将把那些在页面加载完毕时执行的函数创建为一个队列。如果想把刚才那两个函数添加到这个队列里去,只需写出以下代码就行了
addLoadEvent(firstFunction);
addLoadEvent(secondFunction);
3、对showPic函数的改进:
function showPic(whichPic){
if(!document.getElementById("placeholder")) return false;
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if(document.getElementById("description")){//description元素是可选的,如果存在,它将被更新,否则会被忽略
var text=whichPic.getAttribute("title");
var description=document.getElementById("description");
description.firstChild.nodeValue=text;
}
reruen true;
}
4、对showPic函数增加更多的检查:
function showPic(whichPic){
if(!document.getElementById("placeholder")) return false;
var source=whichPic.getAttribute("href");//分解出图片的文件路径,把路径存入变量source
var placeholder=document.getElementById("placeholder");
if(placeholder.nodeName!="IMG") return false;
placeholder.setAttribute("src",source);
if(document.getElementById("description")){//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;
}
在实际工作中,自己决定是否需要这些检查。它们针对的是HTML文档有可能不在你控制范围内的情况。
5、键盘访问:
onkeypress事件处理函数是专门用来处理键盘事件的,按下键盘上任何一个按键都会触发onkeypress事件。
上述例子:links[i].onkeypress=links[i].onclick;把onlink事件的所有功能赋给onkeypress事件
这个事件处理函数很容易出问题,用户每按下一个按键都会触发它。
在几乎所有的浏览器里,用Tab键移动到某个链接然后按下回车键的动作也会触发onclick事件。
最好不要使用onkeypress事件处理函数,onclick事件处理函数已经能够满足需要,它对键盘支持的访问相当完美。
第七章 动态创建标记
1、网页的结构由标记负责创建,JavaScript函数只用来改变细节,而不改变其底层结构。这是绝大多数JavaScript函数的工作原理。JavaScript也可以用来改变网页的结构和内容。通过创建新元素和改变现有元素来改变网页结构。
2、传统的方法
(1)document.write
例如:document.write("<p>aaaaaaaaaa.</p>");
(2)innnerHtml属性
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="testid">
<p>this is<em>my</em> content.</p>
</div>
<script type="text/javascript" src="js/ch7.js"></script>
</body>
</html>
JavaScript:
window.onload=function(){
var testdiv=document.getElementById("testid");
alert(testdiv.innerHTML);
}
用DOM去看testid内的标记,是如下的结构:
这个标记从innerHTML属性的角度看则简单的多,就innerHTML属性看来,id为testid的标记里面只有一个值为<p>this is<em>my</em> content.</p>的HTML字符串。
当你需要把一大段HTML内容插入网页时,innerHTML属性更适用。它即支持读取,又支持写入。
例如:
HTML:
<div id="testid">
</div>
JavaScript:
window.onload=function(){
var testdiv=document.getElementById("testid");
testdiv.innerHTML="<p>inserted <em>this</em> content.</p>";
}
标准的DOM都可以用来替代innerHTML.
3、DOM方法
在DOM看来,一个文档就是一个节点树,如果你想在节点树上添加内容,就必须插入新的节点。
(1)createElement方法(创建元素节点)
编辑HTML如下
<div id="testid"></div>
把一段文本插入testdiv元素。用DOM语言来说,就是想添加一个p元素节点,并把这个节点作为div元素节点的一个子节点。
这项任务需要分两个步骤完成:
(1)创建一个新的元素(2)把这个新元素插入节点树。
第一步用DOM的createElement来完成。
用法:document.createElement(nodeName)
下面这条语句将创建一个p元素:
document.createElement(“p”);
(2)appendChild方法
把新创建的节点插入某个文档节点树的最简单的办法是让它成为这个文档某个现有节点的一个子节点。
用法:parent.appendChild(child)
(3)createTextNode方法
创建一个文本节点。
用法:document.createTextNode(text);
例如:
HTML:
<div id="testid">
</div>
<script type="text/javascript" src="js/ch7.js"></script>
JavaScript:
window.onload=function(){
var para=document.createElement("p");
var txt1=document.createTextNode("This is ");
para.appendChild(txt1);
var emphasis=document.createElement("em");
var txt2=document.createTextNode("my ");
emphasis.appendChild(txt2);
para.appendChild(emphasis);
var txt3=document.createTextNode("content.");
para.appendChild(txt3);
var testdiv=document.getElementById("testid");
testdiv.appendChild(para);
}
4、重回图片库
在HTML中有一个图片和一段文字仅仅是为showPic脚本服务的。用DOM方法来创建它们才是最合适的选择。
把图片标签和文字标签从HTML中删除。
JavaScript:
function preparePlaceholder(){
var placeholder=document.createElement("img");
placeholder.setAttribute("id","placeholder");
placeholder.setAttribute("src","img/default.jpg");
placeholder.setAttribute("alt","默认图片");
vara description=document.createElement("p");
description.setAttribute("id","description");
var desctext=document.createTextNode("Image description");
description.appendChild(desctext);
document.getElementsByTagName("body")[0].appendChild(placeholder);
document.getElementsByTagName("body")[0].appendChild(description);
}
以上代码依赖于一个细节:追加到最后一个元素后面。
5、在已有元素前插入一个新元素
insertBefore()方法
在调用此方法时,你必须告诉它三件事:
- 新元素:你想插入的元素(newElement)。
- 目标元素:你想把这个新元素插入到哪个元素(targetElement)之前。
- 父元素:目标元素的父元素(parentElement)。
用法:parentElement.insertBefore(newElement,targetElement)
例如:
把placeholder插入到图片清单的前面。
var garllery=document.getElementById("imggallery");
gallery.parentNode.insertBefore(placeholder,gallery);
6、在现有方法后插入一个新元素
DOM本身没有提供insertAfter方法
利用DOM方法和属性编写一个insertAfter函数:
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if(parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{ parent.insertBefore(newElement,targetElement.nextSibling);//目标元素的下一个兄弟元素
}
}
7、Ajax
使用Ajax可以做到只更新页面的一小部分,其他内容(如:标志、导航、头部、脚部)都不用重新加载。用户仍然像往常一样点击链接,已经加载的页面中只有一小部分区域会更新,而不必再次加载整个页面了。
Ajax的主要优势就是对页面的请求以异步的方式发送到服务器。而服务器不会用整个页面来响应请求,它会在后台处理请求,与此同时用户还能继续浏览页面并与页面交互。你的脚本可以按需加载和创建页面内容,而不会打断用户的浏览体验。
Ajax依赖JavaScript。
Ajax技术的核心就是XMLHttpRequest对象。这个对象充当着浏览器中的脚本(客户端)与服务器端之间的中间人角色。以往的请求都由浏览器发出,而JavaScript通过这个对象可以自己发出请求,同时也自己处理响应。
XMLHttpRequest对象有许多的方法,其中最有用的是open方法,它用来指定服务器上将要访问的文件,指定请求类型:GET、POST或SEND。这个方法的第三个参数用于指定请求是否以异步方式发送和处理。
例如:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ajax</title>
</head>
<body>
<div id="new"></div>
<script type="text/javascript" src="js/addLoadEvent.js"></script>
<script type="text/javascript" src="js/getHttpObject.js"></script>
<script type="text/javascript" src="js/getNewContent.js"></script>
</body>
</html>
JavaScript:
function getHttpObject(){
return new XMLHttpRequest();
}
function getNewContent(){
var request=getHttpObject();
if(request){
request.open("GET","example.txt",true);
request.onreadystatechange=function(){
if(request.readyState==4){
var para=document.createElement("p");
var txt=document.createTextNode(request.responseText);
para.appendChild(txt);
document.getElementById("new").appendChild(para);
}
};
request.send(null);
}else{
alert("Sorry,your brower doesn\'t support XMLHttpRequest");
}
}
addLoadEvent(getNewContent);
onreadystatechange是一个事件处理函数,它会在服务器给XMLHttpRequest对象送回响应的时候被触发执行。在这个处理函数中,可以根据服务器的具体响应做相应的处理。
服务器在向XMLHttpRequest对象发回响应时,该对象有许多属性可用,浏览器会在不同的阶段更新readyState属性的值,它有5个可能的值:
0表示未初始化
1表示正在加载
2表示加载完毕
3表示正在交互
4表示完成
只要readyState属性的值变成了4,就可以访问服务器发送回来的数据了。
访问服务器发送回来的数据要通过两个属性完成。一个是responseText属性,这个属性用于保存文本字符串形式的数据。另一个属性是responseXML属性,用于保存Content-Type头部中指定为“text/xml”的数据,其实是一个DocumentFragment对象。可以使用各种DOM方法来处理这个对象。
注意:在使用Ajax时,千万要注意同源策略。使用XMLHttpRequest对象发送的请求只能访问与其所在的HTML处于同一个域中的数据,不能像其他域发送请求。
第八章 充实文档的内容
1、显示“缩略语列表”
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>explanatoin</title>
<link rel="stylesheet" href="css/explanation.css">
</head>
<body>
<h1>What is the Document Object Model</h1>
<p>
The <abbr title="World Wide Web Consortium">W3C</abbr> defines the <abbr title="Document Object Model">DOM</abbr> as:
</p>
<blockquote cite="http://www.w3.org/DOM/">
<p>
A platform- and language-neutral interface that will allow programs and scripts to dynamically access and update the content,structure and style of document.
</p>
</blockquote>
<p>
It is an <abbr title="Applation Programming Interface">API</abbr>
that can be used to navigate <abbr title="HyperText Markup Language">HTML</abbr>
and <abbr title="eXtensible Markup Language">XML</abbr> documents.
</p>
<script type="text/javascript" src="js/explanation.js"></script>
</body>
</html>
JavaScript:
window.onload=displayAbbreviations;
function displayAbbreviations(){
if(!document.getElementsByTagName || !document.createElement || !document.createTextNode) return false;
//取得所有缩略词
var abbreviations=document.getElementsByTagName("abbr");
if(abbreviations.length<1) return false;
var defs=new Array();
for(var i=0;i<abbreviations.length;i++){
//遍历缩略词
var definition=abbreviations[i].getAttribute("title");
var key=abbreviations[i].lastChild.nodeValue;
defs[key]=definition;
}
//创建定义列表
var dlist=document.createElement("dl");
for(key in defs){
var definition=defs[key];
//创建列表标题
var dtitle=document.createElement("dt");
var dtitle_text=document.createTextNode(key);
dtitle.appendChild(dtitle_text);
//创建列表描述
var ddesc=document.createElement("dd");
var ddesc_text=document.createTextNode(definition);
ddesc.appendChild(ddesc_text);
dlist.appendChild(dtitle);
dlist.appendChild(ddesc);
}
//创建标题
var header=document.createElement("h2");
var header_text=document.createTextNode("Abbreviations");
header.appendChild(header_text);
document.body.appendChild(header);
document.body.appendChild(dlist);
}
2、显示“文献来源链接表”
JavaScript:
addLoadEvent(displayCitations);
function displayCitations(){
if(!document.getElementsByTagName || !document.createTextNode || !document.createElement)
return false;
var quotes=document.getElementsByTagName("blockquote");
for(var i=0;i<quotes.length;i++){
if(!quotes[i].getAttribute("cite"))
continue;
var url=quotes[i].getAttribute("cite");
var quoteElements=quotes[i].getElementsByTagName("*");
if(quoteElements.length<1)
continue;
var elem=quoteElements[quoteElements.length-1];
var link=document.createElement("a");
var link_text=document.createTextNode("source");
link.appendChild(link_text);
link.setAttribute("href",url);
var superscript=document.createElement("sup");
superscript.appendChild(link);
elem.appendChild(superscript);
}
}
3、显示“快捷键清单”
HTML:
在<body>标签后添加:
<ul id="navigation">
<li><a href="index.html" accesskey="1">Home</a></li>
<li><a href="search.html" accesskey="4">Search</a></li>
<li><a href="contact.html" accesskey="9">Contact</a></li>
</ul>
JavaScript:
addLoadEvent(displayAccessKeys);
function displayAccessKeys(){
if(!document.getElementsByTagName || !document.createElement || !document.createTextNode)
return false;
var links=document.getElementsByTagName("a");
var akeys=new Array();
for(var i=0;i<links.length;i++){
var current_link=links[i];
if(!current_link.getAttribute("accesskey")) continue;
var key=current_link.getAttribute("accesskey");
var text=current_link.lastChild.nodeValue;
akeys[key]=text;
}
var list=document.createElement("ul");
for(key in akeys){
var text=akeys[key];
var str=key+":"+text;
var item=document.createElement("li");
var item_text=document.createTextNode(str);
item.appendChild(item_text);
list.appendChild(item);
}
var header=document.createElement("h3");
var header_text=document.createTextNode("AccessKeys");
header.appendChild(header_text);
document.body.appendChild(header);
document.body.appendChild(list);
}
第九章 CSS-DOM
1、三位一体的网页
结构层:网页的结构层由HTML或XMHTL之类的标记语言负责创建。
表示层:表示层由CSS负责完成
行为层:行为层负责内容应该如何响应事件这一问题。是JavaScript语言和DOM主宰的领域。
2、style属性
style属性包含元素的样式,是一个对象。
3、获取样式:获取对象的color属性:element.style.color
获取对象的font-family属性与color属性略有不同,因为font与family之间的连字符与JavaScript语言中的减法操作符相同,JavaScript会把它解释为减号。当你需要引用一个中间带减号的CSS属性时, DOM要求你用驼峰命名法,CSS属性font-family变为DOM属性fontFamily。
DOM的style属性提取不到外部CSS文件里声明的样式和放在<head>部分的<style>标签里的样式。
4、设置样式:element.style.property=value;
例如:<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
<script>
window.onload=function(){
var para=document.getElementById("example");
para.style.color="black";
}
</script>
</head>
<body>
<p id="example" style="color: gray; font-family: 'arial, helvetica, sans-serif';">
An example of a paragraph
</p>
</body>
</html>
5、何时该用DOM脚本设置样式
(1)根据元素在节点树里的位置来设置样式
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>Hold the front page.</h1>
<p>This first paragraph leads you in.</p>
<p>Now you get the nitty-gritty of the story.</p>
<p>The most import information is delivered first.</p>
<h1>Extral.</h1>
<p>Futher developments are unfolding.</p>
<p>You can read all about it here.</p>
<script type="text/javascript" src="js/styleHeaderSiblings.js"></script>
</body>
</html>
JavaScript:
window.onload=styleHeaderSiblings;
function styleHeaderSiblings(){
if(!document.getElementsByTagName) return false;
var headers=document.getElementsByTagName("h1");
for(var i=0;i<headers.length;i++){
var elem=getNextElement(headers[i].nextSibling);
elem.style.fontWeight="bold";
elem.style.fontSize="1.2em";
}
}
function getNextElement(node){
if(node.nodeType==1){
return node;
}
if(node.nextSibling){
return getNextElement(node.nextSibling);
}
return null;
}
(2)根据某种条件反复设置某种样式
交替变换它们的背景色。CSS3样式设置:
tr:nth-child(odd){background-color:#ffc;}
tr:nth-child(even){background-color:#fff;}
如果nth-child()不可用,编写一个JavaScript函数。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>itinerary</title>
<link rel="stylesheet" href="css/format.css">
</head>
<body>
<table>
<caption>Itinerary</caption>
<tr>
<th>When</th>
<th>Where</th>
</tr>
<tr>
<td>June 9th</td>
<td>Portland<abbr title="Oregon">OR</abbr></td>
</tr>
<tr>
<td>June 10th</td>
<td>Seattle<abbr title="Washington">WA</abbr></td>
</tr>
<tr>
<td>June 17th</td>
<td>Sacramento<abbr title="California">CA</abbr></td>
</tr>
</table>
</body>
</html>
CSS:
body{
font-family: "arial, helvetica, sans-serif";
background-color: #fff;
color: #000;
}
table{
margin: auto;
border:1px solid #699;
}
caption{
margin: auto;
padding: .2em;
font-size: 1.2em;
font-weight: bold;
}
th{
font-weight: normal;
font-style: italic;
text-align: left;
border:1px solid #699;
background-color: #9cc;
color: #000;
}
th,td{
width:10em;
padding: .5em;
}
JavaScript:
window.onload=stripeTables;
function stripeTables(){
if(!document.getElementsByTagName) return false;
var tables=document.getElementsByTagName("table");
var odd,rows;
for(var i=0;i<tables.length;i++){
odd=false;
rows=tables[i].getElementsByTagName("tr");
for(var j=0;j<rows.length;j++){
if(odd==true){
rows[j].style.backgroundColor="#ffc";
odd=false;
}else{
odd=true;
}
}
}
}
6、className属性:可以用className属性得到一个元素的class属性。
修改styleHeaderSiblings,设置样式时不需要直接与style属性打交道。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.intro{
font-weight: bold;
font-size:1.2em;
}
.disclaimer{
color:green;
}
</style>
</head>
<body>
<h1>Hold the front page.</h1>
<p class="disclaimer">This first paragraph leads you in.</p>
<p>Now you get the nitty-gritty of the story.</p>
<p>The most import information is delivered first.</p>
<h1>Extral.</h1>
<p>Futher developments are unfolding.</p>
<p>You can read all about it here.</p>
<script type="text/javascript" src="js/styleHeaderSiblings.js"></script>
</body>
</html>
JavaScript:
window.onload=styleHeaderSiblings;
function styleHeaderSiblings(){
if(!document.getElementsByTagName) return false;
var headers=document.getElementsByTagName("h1");
for(var i=0;i<headers.length;i++){
var elem=getNextElement(headers[i].nextSibling);
/*elem.style.fontWeight="bold";
elem.style.fontSize="1.2em";*/
elem.className="intro";
}
}
function getNextElement(node){
if(node.nodeType==1){
return node;
}
if(node.nextSibling){
return getNextElement(node.nextSibling);
}
return null;
}
不足:通过class属性设置某个元素的class属性时将替换(而不是追加)该元素原有的class设置。
改进:添加一个新函数
function addClass(element,value){
if(!element.className){
element.className=value;
}else{
newClassName=element.className;
newClassName+=" ";
newClassName+=value;
element.className=newClassName;
}
}
调用:addClass(elem,"intro");
结果与前面完全相同,区别在于现在是通过CSS而不是DOM去设置样式。
7、对函数进行抽象:styleHeaderSiblings函数只适用于h1元素,class属性值intro也是硬编码在函数代码里的。
把这些具体的值转换为这个函数的参数,可以让它成为一个更通用的函数。
addLoadEvent(function(){
styleElementSiblings("h1","intro");
});
function styleElementSiblings(tag,theclass){
if(!document.getElementsByTagName) return false;
var elems=document.getElementsByTagName(tag);
for(var i=0;i<elems.length;i++){
var elem=getNextElement(elems[i].nextSibling);
addClass(elem,theclass);
}
}
function getNextElement(node){
if(node.nodeType==1){
return node;
}
if(node.nextSibling){
return getNextElement(node.nextSibling);
}
return null;
}
第十章 用JavaScript实现动画效果
1、时间
JavaScript函数setTimeOut能够让某个函数在经过 一段预订的时间之后才开始执行,这个函数带有两个参数:第一个参数通常是一个字符串,其内容是将要执行的那个函数的名字;第二个参数是一个数值,它以毫秒为单位设定了需要经过多长时间后才开始执行第一个参数所给出的函数。
setTimeOut(“function”,interval);
在绝大多数时候,把这个函数调用赋值给一个变量。
variable= setTimeOut(“function”,interval);
如果想取消某个正在排队等待执行的函数,可以用一个名为clearTimeout的函数。
clearTimeOut(variable);
例如:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Whee</title>
</head>
<body>
<p id="message">Whee!</p>
<script type="text/javascript" src="js/addLoadEvent.js"></script>
<script type="text/javascript" src="js/positionMessage.js"></script>
</body>
</html>
JavaScript:
addLoadEvent(positionMessage);
function positionMessage(){
if(!document.getElementById) return false;
if(!document.getElementById("message")) return false;
var elem=document.getElementById("message");
elem.style.position="absolute";
elem.style.left="50px";
elem.style.top="100px";
movement=setTimeout("moveMessage()",5000);//movement全局变量
}
function moveMessage(){
if(!document.getElementById) return false;
if(!document.getElementById("message")) return false;
var elem=document.getElementById("message");
elem.style.left="200px";
}
元素的移动以渐变的方式发生:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Whee</title>
</head>
<body>
<p id="message">Whee!</p>
<script type="text/javascript" src="js/addLoadEvent.js"></script>
<script type="text/javascript" src="js/moveElement.js"></script>
<script type="text/javascript" src="js/positionMessage.js"></script>
</body>
</html>
JavaScript:
moveElement.js:
function moveElement(elementID,final_x,final_y,interval){
if(!document.getElementById) return false;
if(!document.getElementById(elementID)) return false;
var elem=document.getElementById(elementID);
var xpos=parseInt(elem.style.left);
var ypos=parseInt(elem.style.top);
if(xpos==final_x && ypos==final_y){
return true;
}
if(xpos<final_x){
xpos++;
}
if(xpos>final_x){
xpos--;
}
if(ypos<final_y){
ypos++;
}
if(ypos>final_y){
ypos--;
}
elem.style.left=xpos+"px";
elem.style.top=ypos+"px";
var repeat="moveElement('"+elementID+"','"+final_x+"','"+final_y+"','"+interval+"')";
movement=setTimeout(repeat,interval);//movement全局变量
}
positionMessage.js:
addLoadEvent(positionMessage);
function positionMessage(){
if(!document.getElementById) return false;
if(!document.getElementById("message")) return false;
var elem=document.getElementById("message");
elem.style.position="absolute";
elem.style.left="50px";
elem.style.top="100px";
moveElement("message",200,100,10);
//movement=setTimeout("moveMessage()",5000);//movement全局变量
}
2、实用的动画
CSS的overflow属性用来处理一个元素的尺寸超出其容器尺寸的情况。overflow属性的可取值有4种:visible、hidden、scroll、auto。
visible:不剪裁溢出的内容。浏览器将把溢出的内容呈现在其容器元素的显示区域以外,全部内容都可见。
hidden:隐藏溢出的内容。内容只显示在其容器元素的显示区域里,这意味着只有一部分内容可见。
scroll:浏览器对溢出的内容进行隐藏。但显示一个滚动条以便让用户能够滚动看到内容的其它部分。
auto:类似于scroll,但浏览器只在确实发生溢出时才显示滚动条。如果内容没有溢出,就不显示滚动条。
例如:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/link.css">
</head>
<body>
<h1>Web Design</h1>
<p>These are the things you should know.</p>
<ol id="linklist">
<li>
<a href="structure.html">Structure</a>
</li>
<li>
<a href="presentation.html">Presentation</a>
</li>
<li>
<a href="behavior.html">Behavior</a>
</li>
</ol>
<div id="slideshow">
<img src="img/Suzhou2.jpg" alt="building block of web design" id="preview">
</div>
<script type="text/javascript" src="js/addLoadEvent.js"></script>
<script type="text/javascript" src="js/moveElement.js"></script>
<script type="text/javascript" src="js/prepareSlideshow.js"></script>
</body>
</html>
CSS:
#slideshow{
width: 320px;
height: 960px;
position: relative;
overflow: hidden;
}
JavaScript:
addLoadEvent(prepareSlideshow);
function prepareSlideshow(){
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
if(!document.getElementById("preview")) return false;
if(!document.getElementById("linklist")) return false;
var preview=document.getElementById("preview");
preview.style.position="absolute";
preview.style.left="0px";
preview.style.top="0px";
//取得列表中的所有链接
var list=document.getElementById("linklist");
var links=list.getElementsByTagName("a");
//为mouseover事件添加动画效果
links[0].onmouseover=function(){
moveElement("preview",-320,0,10);
}
links[1].onmouseover=function(){
moveElement("preview",-640,0,10);
}
links[2].onmouseover=function(){
moveElement("preview",-960,0,10);
}
}
鼠标指针在链接之间快速的来回移动,动画效果将变得混乱起来。
改进:
moveElement.js
var elem=document.getElementById(elementID);
if(elem.movement){
clearTimeout(elem.movement);
}
elem.movement=setTimeout(repeat,interval);//为元素创建属性
javaScript允许为元素创建属性
element,property=value;
4、改进动画效果
如果那个元素与它的目的地距离较远,就让它每次前进一大步。如果那个元素与它的目的地距离较近,就让它每次前进一小步。
Math.ceil(nnumber)向上取整
Math.floor(bumber)向下取整
Math.round(number)把任意浮点数舍入为与之最接近的整数
JavaScript:
var dist=0;
if(xpos==final_x && ypos==final_y){
return true;
}
if(xpos<final_x){
dist=Math.ceil((final_x-xpos)/10);
xpos=xpos+dist;
}
if(xpos>final_x){
dist=Math.ceil((xpos-final_x)/10);
xpos=xpos-dist;
}
if(ypos<final_y){
dist=Math.ceil((final_y-ypos)/10);
ypos=ypos+dist;
}
if(ypos>final_y){
dist=Math.ceil((ypos-final_y)/10);
ypos=ypos-dist;
}
5、添加安全检查
if(!elem.style.left){
elem.style.left="0px";
}
if(!elem.style.top){
elem.style.top="0px";
}
6、生成HTML标记
HTML文档里包含一些只是为了能够用JavaScript代码实现动画效果而存在的标记。用JavaScript代码来生成它们。
创建div元素,创建img元素,把新创建的img元素放入新创建的div元素。最后让这些新创建的元素紧跟着出现在链接清单的后面。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/link.css">
</head>
<body>
<h1>Web Design</h1>
<p>These are the things you should know.</p>
<ol id="linklist">
<li>
<a href="structure.html">Structure</a>
</li>
<li>
<a href="presentation.html">Presentation</a>
</li>
<li>
<a href="behavior.html">Behavior</a>
</li>
</ol>
<script type="text/javascript" src="js/addLoadEvent.js"></script>
<script type="text/javascript" src="js/insertAfter.js"></script>
<script type="text/javascript" src="js/moveElement.js"></script>
<script type="text/javascript" src="js/prepareSlideshow.js"></script>
</body>
</html>
CSS:
#slideshow{
width: 320px;
height: 960px;
position: relative;
overflow: hidden;
}
#preview{
position: absolute;
}
JavaScript:
prepareSlideshow.js
addLoadEvent(prepareSlideshow);
function prepareSlideshow(){
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
if(!document.getElementById("linklist")) return false;
var slideshow=document.createElement("div");
slideshow.setAttribute("id","slideshow");
var preview=document.createElement("img");
preview.setAttribute("src","img/Suzhou2.jpg");
preview.setAttribute("alt","building blocks of web design");
preview.setAttribute("id","preview");
slideshow.appendChild(preview);
var list=document.getElementById("linklist");
insertAfter(slideshow,list);
//取得列表中的所有链接
var links=list.getElementsByTagName("a");
//为mouseover事件添加动画效果
links[0].onmouseover=function(){
moveElement("preview",-320,0,10);
}
links[1].onmouseover=function(){
moveElement("preview",-640,0,10);
}
links[2].onmouseover=function(){
moveElement("preview",-960,0,10);
}
}
insertAfter.js
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if(parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
附:
addLoadEvent.js:
function addLoadEvent(func){
var oldonload=window.onload;
if(typeof window.onload!='function'){
window.onload=func;
}else{
window.onload=function(){
oldonload();
func();
}
}
}
insertAfter.js:
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if(parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{
parent.insertBefore(newElement,targetElement.nextSibling);
}
}