JavaScript DOM编程艺术 读书笔记
第3章 DOM
1.DOM:D代表document(文档),O代表object(对象),M代表model(模型),DOM把一份文档表示成一棵“树”
2.节点(node):文档是由节点构成的集合,每个节点都是一个对象
(1)元素节点(element node):<html>、<head>、<body>、<p>、<ul>等标签的名字就是元素的名字
(2)文本节点(text node) :一般文本节点包含在元素节点里面
(3)属性节点(attribute node): 属性节点也包含在元素节点里,比如最常见的class、id
3.获取元素的方法
(1)document.getElementById:返回一个与那个有给定id属性值的元素节点相对应的对象。注意:返回的是对象
(2)document.getElementsByTagName:返回一个对象数组,每个对象分别对应着文档里有给定标签的一个元素。注意:返回的是一个数组
(3)document.getElementsByClassName:通过class属性中的类名来访问元素,返回一个对象数组
4.获取和设置属性(两者只能作用于元素节点)
(1)object.getAttribute(attribute):通过以上方法找到元素后,可以使用getAttribute()方法把它的各种属性的值查询出来
传入参数:所查询的属性的名字。 注意:不能通过document对象调用,只能通过一个元素节点对象调用
(2)object.setAttribute(attribute,value):允许对属性节点的值做出修改
使用此方法设置属性,查看源文件可以见属性值未被修改
5.DOM工作模式:先加载文档的静态内容,再以动态方式对它们进行刷新,动态刷新不影响文档的静态内容
第4章 案例研究:javascript图片库
1.setAttribute可以用其他方法代替,直接设置:element.value = "the new value",相当于element.setAttribute("value","the new value")
2.childNodes 属性
在一棵节点树上,childNodes属性可以用来获取任何一个元素的所有子元素,它是一个包含这个元素全部子元素的数组
由childNodes属性返回元素所有类型的节点。不仅仅是元素节点,几乎每一种东西都会成为一个节点,甚至空格和换行都会被解释为节点
3.nodeType属性
可以用node.nodeType获取节点的nodeType属性
元素节点的nodeType属性值是1,属性节点的nodeType属性值是2,文本节点的nodeType属性值是3
4.nodeValue属性
可以用来改变一个文本节点的值,方法node.nodeValue
5.firstChild和lastChild属性
分别对应childNodes[0]和childNodes[childNodes.length-1]
6.事件处理函数:在预定义事件发生时让预先安排好的JavaScript代码开始执行,用术语说就是“触发一个动作”。onmourseover、onmourseon、onclick等。
第5章 最佳实践
1.平稳退化:确保网页在没有javascript时也能正常工作
2.渐进增强:用一些额外的信息层去包裹原始数据
3.分离JavaScript:把网页的结构和内容与JavaScript脚本的动作行为分开,利用Class和id属性作为“挂钩”在分离的js中操纵
4.向后兼容:对于不能使用js或部分dom方法的古老浏览器,通过返回false推出js,避免崩溃
5.性能考虑:确定脚本执行的性能最优
第6章 案例研究:图片库改进版
共享onload:addLoadEvent函数
1 function addLoadEvent(func) { 2 var oldonload=window.onload; 3 if(typeof window.onload != 'function'){ 4 window.onload=func; 5 } else { 6 window.onload= function (){ 7 oldonload(); 8 func(); 9 } 10 } 11 }
1.把现有的window.onload事件处理函数存入变量oldonload.
2.如果在这个处理函数上还没有绑定任何函数,就向平时一样把函数添加给它.
3.如果在这个处理函数上已经绑定了一些函数,就把新函数追加到现有函数末尾.
第7章 动态创建标记
1.document.write()方法:可以方便快捷地把字符串插入到文档里,但其使用方法违背了“分离JavaScript”原则,因此避免使用这个方法。
2.innerHTML属性:既能用于读取,又能用于写入。但利用这个技术无法区分“插入一段html内容”与“写入一段html内容”。一旦使用innerHTML,它的全部内容将被替换。
3.createElement方法
document.createElement(nodename);创建一个元素节点,只不过属于文档碎片,没有成为DOM节点树的一部分,需要被添加进DOM树
4.appendChild方法
parent.appendChild(child);把新创建的节点插入某个文档的节点树,让它成为这个文档某个现有节点的子节点
5.createTextNode方法
document.createNode(text);创建一个文本节点,注意它与createElement的差别
6.insertBefore()方法
parentElement.insertBefore(newElement,targetElement);把一个新元素插入到一个现有元素的前面,必须告诉它父元素(parentElement)、新元素(newElement)、目标元素(targetElement)。
7.insertAfter()函数 (DOM中没有此方法)
1 function insertAfter(newElement,targetElement){ 2 var parent=targetElement.parentNode; 3 if(parent.lastChild==targetElement){ 4 parent.appendChild(newElement); 5 } else { 6 parent.insertBefore(newElement,targetElement.nextSibling); 7 } 8 }
nextSibling属性:目标元素的下一个兄弟节点。
第8章 充实文档的内容
不能滥用DOM,谨记渐进增强和平稳退化。JavaScript脚本只应该用来充实文档的内容,要避免使用DOM技术创建核心内容
第9章 CSS-DOM
1.何时该用DOM脚本设置样式 :
(1)根据元素在节点树里的位置来设置样式
(2)根据某种条件反复设置某种样式
2.当在js中操纵style属性时,像font-famliy这样的属性不能直接出现在js中,因为js保留-、+这些符号作运算符。font-family应写作fontFamily
3.使用elemennt.sytle.property = value;可以为css属性刷新值。如果value是属性值,需要单引号或双引号括起来,如果是变量就不能有引号
4.事件响应:使用属性设置:onmouseover、onmouseout。用法:para.onmouseover=fucntion(){}
5.不应该用DOM直接添加/修改style的值,而是应该使用className属性为元素节点添加、追加、刷新属性,再用对应CSS控制表现
6.所有可以抽象化的具体函数都应该进行抽象化,使其成为通用函数模块化重用
第10章 动画效果
1.JS可以通过按照预定的时间间隔重复调用一个函数,从而随时间推移改变某个元素样式,即创建动画
2.setTimeout("function",interval):第一个参数是字符串,内容是将要执行的那个函数的名字。第二个参数是一个值,它以毫秒为单位设定需要经过多长时间才开始执行由第一个参数所给出的函数
3.clearTimeout(variable):可以取消某个正在排队等待执行的函数,需要将要取消的setTimeout函数赋值给一个变量,再在clearTimeout里调用这个变量作参数
4.清除setTimeout的方法——利用元素创建属性
第12章 综合示例
1.基本函数
(1)addLoadEvent 函数
function addLoadEvent(func) {
var oldonload = window.onload;
if(typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
(2)insertAfter 函数
function insertAfter(newElement, targetElement) {
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement, targetElement.nextSibling);
}
}
(3)addClass 函数
function addClass(element, value) {
if(!element.className) {
element.className = value;
} else {
newClassName = element.className;
newClassName += " ";
newClassName += value;
element.className = newClassName;
}
}
2.index 页面
(1)highlightPage 函数 (页面突出显示)
function highlightPage() {
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
var headers = document.getElementsByTagName('header');
if(headers.length == 0) return false;
var navs = headers[0].getElementsByTagName('nav');
if(navs.length == 0) return false;
var links = navs[0].getElementsByTagName('a');
for(var i = 0; i < links.length; i++) {
var linkurl;
for(var i = 0; i < links.length; i++) {
linkurl = links[i].getAttribute('href');
if(window.location.href.indexOf(linkurl) != -1) {
links[i].className = "here";
var linktext = links[i].lastChild.nodeValue.toLowerCase();
document.body.setAttribute('id', linktext);
}
}
}
}
(2)moveElement 函数
function moveElement(elementID, final_x, final_y, interval) {
if(!document.getElementById) return false;
if(!document.getElementById(elementID));
var elem = document.getElementById(elementID);
if(elem.evenment) {
clearTimeout(elem.evenment);
}
if(!elem.style.left) {
elem.style.left = "0px";
}
if(!elem.style.top) {
elem.style.top = "0px";
}
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) {
var dist = Math.ceil((final_x - xpos) / 10);
xpos += dist;
}
if(xpos > final_x) {
var dist = Math.ceil((xpos - final_x) / 10);
xpos -= dist;
}
if(ypos < final_y) {
var dist = Math.ceil((final_y - ypos) / 10);
ypos += dist;
}
if(ypos > final_y) {
var dist = Math.ceil((ypos - final_y) / 10)
ypos -= dist;
}
elem.style.left = xpos + "px";
elem.style.top = ypos + "px";
var repeat = "moveElement('" + elementID + "'," + final_x + "," + final_y + "," + interval + ")";
elem.evenment = setTimeout(repeat, interval);
}
(3)prepareSlideshow 函数 (幻灯片效果)
function prepareSlideshow() { if(!document.getElementsByTagName) return false; if(!document.getElementById) return false; if(!document.getElementById("intro")) return false; var intro = document.getElementById("intro"); var slideshow = document.createElement("div"); slideshow.setAttribute("id", "slideshow"); var frame = document.createElement("img"); frame.setAttribute("src", "images/frame.gif"); frame.setAttribute("alt", ""); frame.setAttribute("id", "frame"); slideshow.appendChild(frame); var preview = document.createElement("img"); preview.setAttribute("src", "images/slideshow.gif"); preview.setAttribute("alt", "a glimpse of what awaits you"); preview.setAttribute("id", "preview"); slideshow.appendChild(preview); insertAfter(slideshow, intro); var links = document.getElementsByTagName("a"); for(var i = 0; i < links.length; i++) { links[i].onmouseover = function() { var destination = this.getAttribute("href"); if(destination.indexOf("index.html") != -1) { moveElement("preview", 0, 0, 5); } if(destination.indexOf("about.html") != -1) { moveElement("preview", -150, 0, 5); } if(destination.indexOf("photos.html") != -1) { moveElement("preview", -300, 0, 5); } if(destination.indexOf("live.html") != -1) { moveElement("preview", -450, 0, 5); } if(destination.indexOf("contact.html") != -1) { moveElement("preview", -600, 0, 5); } } } }
3.about 页面
(1)showSection 函数
function showSection(id) { var sections = document.getElementsByTagName('section'); for(var i = 0; i < sections.length; i++) { if(sections[i].getAttribute('id') != id) { sections[i].style.display = 'none'; } else { sections[i].style.display = 'block'; } } }
(2)prepareInternalnav 函数 (内部导航)
function prepareInternalnav() { if(!document.getElementsByTagName) return false; if(!document.getElementById) return false; var articles = document.getElementsByTagName('article'); if(articles.length == 0) return false; var navs = articles[0].getElementsByTagName('nav'); if(navs.length == 0) return false; var links = navs[0].getElementsByTagName('a'); for(var i = 0; i < links.length; i++) { var sectionId = links[i].getAttribute('href').split('#')[1]; if(!document.getElementById(sectionId)) continue; document.getElementById(sectionId).style.display = 'none'; //页面加载后,默认隐藏所有部分 links[i].destination = sectionId; //自定义属性,其作用域持久存在 links[i].onclick = function() { showSection(this.destination); return false; } } }
4.photos 页面
(1)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')) return false; if(whichpic.getAttribute('title')) { var text = whichpic.getAttribute('title'); } else { var text = ''; } var description = document.getElementById('description'); if(description.firstChild.nodeType == 3) { description.firstChild.nodeValue = text; } return false; }
(2)preparePlaceholder 函数
function preparePlaceholder() { if(!document.createElement) return false; if(!document.createTextNode) return false; if(!document.getElementById) return false; if(!document.getElementById('imagegallery')) return false; var placeholder = document.createElement('img'); placeholder.setAttribute('id', 'placeholder'); placeholder.setAttribute('src', 'images/placeholder.gif'); placeholder.setAttribute('alt', 'my image gallery'); var description = document.createElement('p'); description.setAttribute('id', 'description'); var desctext = document.createTextNode('Choose an image'); description.appendChild(desctext); var gallery = document.getElementById('imagegallery'); insertAfter(description, gallery); insertAfter(placeholder, description); }
(3)prepareGallery 函数 (图片库)
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() { return showPic(this); } } }
5.live 页面
(1)stripeTables 函数
function stripeTables() { if(!document.getElementsByTagName) return false; var tables = document.getElementsByTagName('table'); for(var i = 0; i < tables.length; i++) { var odd = false; var rows = tables[i].getElementsByTagName('tr'); for(var j = 0; j < rows.length; j++) { if(odd == true) { addClass(rows[j], 'odd'); odd = false; } else { odd = true; } } } }
(2)highlightRows 函数
function highlightRows() { if(!document.getElementsByTagName) return false; var rows = document.getElementsByTagName('tr'); for(var i = 0; i < rows.length; i++) { rows[i].oldClassName = rows[i].className; rows[i].onmouseover = function() { addClass(this, 'highlight'); } rows[i].onmouseout = function() { this.className = this.oldClassName; } } }
(3)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 current_abbr = abbreviations[i]; if(current_abbr.childNodes.length < 1) continue; var definition = current_abbr.getAttribute('title'); var key = current_abbr.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); } if(dlist.childNodes.length == 0) return false; var header = document.createElement('h3'); var header_text = document.createTextNode('Abbreviations'); header.appendChild(header_text); var articles = document.getElementsByTagName('article'); if(articles.length == 0) return false; var container = articles[0]; container.appendChild(header); container.appendChild(dlist); }
6.contact 页面
(1)focusLabels 函数
function focusLabels() { if(!document.getElementsByTagName) return false; var labels = document.getElementsByTagName('label'); for(var i = 0; i < labels.length; i++) { if(!labels[i].getAttribute('for')) continue; labels[i].onclick = function() { var id = this.getAttribute('for'); if(!document.getElementById(id)) return false; var element = document.getElementById(id); element.focus(); } } }
(2)reseFields 函数
function resetFields(whichform) { if(Modernizr.input.placeholder) return; for(var i = 0; i < whichform.elements.length; i++) { var element = whichform.elements[i]; if(element.type == "submit") continue; if(!element.getAttribute('placeholder')) continue; element.onfocus = function() { if(this.value == this.getAttribute('placeholder')) { this.value = ""; } } element.onblur = function() { if(this.value == "") { this.value = this.getAttribute('placeholder'); } } element.onblur(); } }
(3)validateForm 函数
function validateForm(whichform) { for(var i = 0; i < whichform.elements.length; i++) { var element = whichform.elements[i]; if(element.getAttribute("required") == 'required') { if(!isFilled(element)) { alert("Please fill in the " + element.name + " field."); return false; } } if(element.getAttribute("type") == 'email') { if(!isEmail(element)) { alert("The " + element.name + " field must be a valid email address."); return false; } } } return true; }
(4)prepareForms 函数
function isFilled(field) { return(field.value.length > 1 && field.value != field.placeholder); } function isEmail(field) { return(field.value.indexOf("@") != -1 && field.value.indexOf(".") != -1); } function prepareForms() { for(var i = 0; i < document.forms.length; i++) { var thisform = document.forms[i]; resetFields(thisform); thisform.onsubmit = function() { if(!validateForm(this)) return false; var article = document.getElementsByTagName('article')[0]; if(submitFormWithAjax(this, article)) return false; return true; } } }