DOM1级主要定义的是HTML和XML文档的底层结构。DOM2级和DOM3级在这个结构基础上引入了更多的交互能力,也支持更高级的XML特性。为此DOM2级和DOM3级分为了很多的模块(模块直接具有某种关联),分别描述了DOM的某个非常具体的子集。这些模块如下:

  • DOM2级核心:在1级核心基础上构建,为节点添加了更多属性和方法;
  • DOM2级视图:为文档定义了基于样式信息的不同视图;
  • DOM2级事件:说明了如何使用事件与DOM文档交互;
  • DOM2级样式:定义了如何以编程方式来访问和改变CSS样式信息;
  • DOM2级遍历和范围:引入了遍历DOM文档和选择其特定部分的新接口;
  • DOM2级HTML:在1级HTML基础上构建,添加了更多的属性、方法和新接口。

DOM变化

DOM2级和DOM3级的目的在于扩展DOM API,以满足操作XML的所有需求,同时提供更好的错误处理级特性检测能力。

通过下列代码来确定浏览器是否支持这些DOM模块:

var supportsDOM2Core = document.implementation.hasFeature("Core","2.0");
var supportsDOM3Core = document.implementation.hasFeature("Core","3.0");
var supportsDOM2HTML = document.implementation.hasFeature("HTML","2.0");
var supportsDOM2Views = document.implementation.hasFeature("Views","2.0");
var supportsDOM2XML = document.implementation.hasFeature("XML","2.0");

针对XML命名空间的变化

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:head>
<xhtml:title>Example XHTML page</xhtml:title>
</xhtml:head>
<xhtml:body xhtml:class="home">
Hello world!
</xhtml:body>
</xhtml:html>

样式

访问元素的样式

对于使用短横线(例如:background-image)的css属性名,必须将其转换为驼峰大小写形式,才能通过JavaScript来访问。如下:

var myDiv = document.getElementById('myDiv');
myDiv.style.backgroundColor = 'red'; myDiv.style.width = '200px';
myDiv.style.height = '200px'; myDiv.style.border = '1px solid #ccc';

其中一个不能直接转化的css属性为float。由于float为JavaScript的保留字,因此不能作为属性名。“DOM2级样式”规范规定对象上相应的属性名应该是cssFloat。除了IE浏览器,其它浏览器都支持这个属性。而IE支持的是styleFloat。

DOM样式属性和方法

“DOM2级样式”规范为style对象定义了一些属性和方法,常用:

  • cssText:通过它可以访问到style特性中的css代码。
  • length:应用给元素的css属性的数量。
  • getPropertyValue(propertyName):返回给定属性的字符串值。
  • item(index):返回给定位置的css属性的名称。
  • removeProperty(propertyName):从样式中删除给定的属性。
  • setProperty(propertyName,value,priority):将给定的属性设置为相应的值,并加上优先权标志(“important”或者一个空字符串)。
var myDiv = document.getElementById('page1');
myDiv.style.cssText = "display:block;width:300px;background:red;color:#fff;"
console.log(myDiv.style.cssText); //display: block; width: 300px; background: red; color: rgb(255, 255, 255);

设置cssText是为元素应用多项变化最快捷的方式,因为可以一次性的应用所有变化。

var myDiv = document.getElementById('page1');
var i,len,prop,value;
for(i =0, len = myDiv.style.length; i < len; i++){
prop = myDiv.style[i]; //或者 myDiv.style.item(i)
value = myDiv.style.getPropertyValue(prop);
console.log(prop + ":" + value);
}
myDiv.style.removeProperty('font-size');

计算的样式

虽然style对象能够提供支持style特性的任何元素的样式信息,但它不包含从其它样式表层叠而来并影响当前元素的样式信息。“DOM2级样式”增强了document.defaultView,提供了getComputedStyle()方法。这个方法接收两个参数:要取得计算样式的元素和一个伪元素字符串(例如":after")。如果不需要伪元素,那么第二个参数可以为null。getComputedStyle()方法返回一个CSSStyleDeclaration对象(与style属性的类型相同),其中包含当前元素的所有计算的样式。

var myDiv = document.getElementById('page1');
var computedStyle = document.defaultView.getComputedStyle(myDiv,null);
console.log(computedStyle.width);
console.log(computedStyle.backgroundColor);

IE不支持getComputedStyle()方法,但是在IE中,每个具有style属性的元素还有一个currentStyle属性。这个属性是CSSStyleDeclaration的实例,包含当前元素全部计算后的样式。

var myDiv = document.getElementById('page1');
var computedStyle = myDiv.currentStyle;
console.log(computedStyle.width);
console.log(computedStyle.backgroundColor);

操作样式表

CSSStyleSheet类型表示的是样式表。应用于文档的所有样式表是通过document.styleSheets集合来表示的。

var sheet = null;
for(var i =0, len = document.styleSheets.length; i < len; i++){
sheet = document.styleSheets[i];
console.log(sheet.href);
}

上面例子是获取每一个样式表的href属性。

不同浏览器的document.styleSheets返回的样式表不同,DOM规定了一个包含CSSStyleSheet对象的属性,名叫sheet,除了IE浏览器,其它浏览器都支持;IE支持的是styleSheet属性。在不同浏览器取得样式表对象,代码如下:

function getStyleSheet(element){
return element.sheet || element.styleSheet;
} //取得第一个link元素引入的样式表
var link = document.getElementsByTagName('link')[0];
var sheet = getStyleSheet(link);
console.log(sheet);

得到的结果如下图:

这里的getStyleSheet()返回的样式表对象和document.styleSheets集合中的样式表对象相同。

元素大小

1.偏移量

  • offsetHeight:元素在垂直方向上占用的空间大小,以像素计算。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度。
  • offsetWidth:元素在水平方向上占用的空间大小,以像素计算。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框宽度和右边框宽度。
  • offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离。
  • offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离。

其中offsetLeft和offsetTop属性跟包含元素有关,包含元素的引用保存在offsetParent属性中。offsetParent属性不一定与parentNode的值相等。

例如,<td>元素的offsetParent是作为其祖先元素的<table>元素,因为<table>是在DOM层次中距<td>最近的一个具有大小的元素。如下图:

计算某个元素在页面上的偏移量,如下代码分别取得元素的左和上偏移量:

function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while(current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
} function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while(current !== null){
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
} var myDiv = document.getElementById('page1');
console.log(getElementLeft(myDiv));
console.log(getElementTop(myDiv));

2.客户区大小

元素的客户区大小,指的是元素内容及其内边距所占据的空间大小。有关客户区大小的属性有两个:clientWidth和clientHeight。

  • clientWidth:元素内容区宽度加上左右内边距宽度(因此滚动条占据的空间不计算在内)。
  • clientHeight:元素内容区高度加上上下内边距高度(因此滚动条占据的空间不计算在内)。

如图所示描述:

例如:要确认浏览器视口大小,可以使用document.documentElement或document.body(IE7之前的版本中)的clientWidth和clientHeight。

function getViewPort(){
if(document.compatMode == 'BackCompat'){ //IE7浏览器之前
return {
width:document.body.clientWidth,
height:document.body.clientHeight
}
}else{ //标准浏览器 document.compatMode 为CSS1Compat
return {
width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
}
}
} var result = getViewPort();
console.log(result.width);
console.log(result.height);

3.滚动大小

滚动大小,指的是包含滚动内容的元素的大小。有的元素(例如<html>元素),即使没有执行任何代码也能自动添加滚动条;但另外一些元素,需要通过设置css的overflow属性进行设置才能滚动。以下有四个跟滚动相关的属性:

  • scrollHeight:在没有滚动条的情况下,元素内容的总高度。
  • scrollWidth:在没有滚动条的情况下,元素内容的总宽度。
  • scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。
  • scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。

其中scrollHeight和scrollWidth主要用于确定元素内容的实际大小。比如带有垂直滚动条的页面总高度为document.documentElement.scrollHeight。

对于不包含滚动条的页面而言,scrollWidth和scrollHeight与clientWidth和clientHeight之间的关系并不十分清晰。在这种情况下,基于document.documentElement查看这些属性会在不同浏览器之间发现一些不一致的问题,如下描述:

  • Firefox中这两组属性始终是相等的,但大小代表的是文档内容区域的实际尺寸,而非视口的尺寸。
  • Opera、Safari3.1及更高版本、Chrome中的这两组属性是有差别的,scrollWidth和scrollHeight等于视口大小,而clientWidth和clientHeight等于文档内容区域的大小。
  • IE(标准模式)中的这两组属性不相等,其中scrollWidth和scrollHeight等于文档内容区域的大小,而clientWidth和clientHeight等于视口的大小。

在确定文档的总高度时(包括基于视口的最小高度时),必须取得scrollWidth/scrollHeight和clientWidth/clientHeight中的最大值,才能在跨浏览器的环境中得到精确的结果。下面代码:

var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);
var docWidth = Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);

注意,运行在混杂模式下的IE,需要用document.body替换document.documentElement。

检测元素是否位于顶部,不是就将其滚到顶部:

function scrollToTop(element){
if(element.scrollTop != 0){
element.scrollTop = 0;
}
}

4.确定元素的大小

每个元素有getBoundingClientRect()方法,这个方法返回一个矩形对象。包含4个属性:left、top、right和bottom。这些属性给出了元素在页面中相对于视口的位置。但是浏览器的实现稍有不同,IE8及更早版本认为文档的左上角坐标为(2,2),而其它的浏览器包括IE9把(0,0)作为起点坐标。下面实现一个跨浏览器兼容的getBoundingClientRect版本:

function getBoundingClientRect(element){
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
if(element.getBoundingClientRect){
if(typeof arguments.callee.offset != 'number'){
var temp = document.createElement('div');
temp.style.cssText = "position:absolute;top:0;left:0;";
document.body.appendChild(temp);
arguments.callee.offset = - temp.getBoundingClientRect().top - screenTop;
document.body.removeChild(temp);
temp = null;
}
var rect = element.getBoundingClientRect();
var offset = arguments.callee.offset; return {
left:rect.left + offset,
right:rect.right +offset,
top:rect.top + offset,
bottom:rect.bottom + offset
}; }else{
var actualLeft = getElementLeft(element);
var actualTop = getElementTop(element); return {
left:actualLeft - scrollLeft,
right:actualLeft + element.offsetWidth - scrollLeft,
top:actualTop - screenTop,
bottom:actualTop + element.offsetHeight - scrollTop
};
}
}

范围

为了让开发人员更方便的控制页面,“DOM2级遍历和范围”模块定义了“范围”(range)接口。通过范围可以选择文档中的一个区域,而不必考虑节点的界限(选择在后台完成,对用户是不可见的)。在常规的DOM操作不能更有效地修改文档时,使用范围往往可以达到目的。但IE以专有的方式实现了自己的范围特性。

DOM中的范围

DOM2级在Document类型中定义了createRange()方法。在兼容DOM的浏览器中,这个方法属于document对象。使用hasFeature或者直接检测该方法。如下代码:

var supportsRange = document.implementation.hasFeature("Range","2.0");
var alsoSupportsRange = (typeof document.createRange == 'function');

如果浏览器支持范围,就可以使用createRange()来创建DOM范围,如下所示:

var range = document.createRange();

每个范围由一个Range类型的实例表示,这个实例拥有很多的属性和方法。下列属性提供了当前范围在文档中的位置信息。

  • startContainer:包含范围起点的节点(即选区中第一个节点的父节点)。
  • startOffset:范围在startContainer中的起点的偏移量。如果startContainer是文本节点、注释节点、CDATA节点,那么startOffset就是范围起点之前跳过的字符数量。否则,startOffset就是范围中第一个子节点的索引。
  • endContainer:包含范围终点的节点(即选区中最后一个节点的父节点)。
  • endOffset:范围在endContainer中终点的偏移量(与startOffset遵循相同的取值规则)。
  • commonAncestorContainer:startContainer和endContainer共同的祖先节点在文档树中位置最深的那个。

在把范围放到文档中特定的位置时,这些属性都会被赋值。

1.用DOM范围实现简单选择

要使用范围来选择文档中的一部分,最简单的方式是使用selectNode()和selectNodeContents()。这两个方法都接受一个参数,即一个DOM节点,然后使用该节点的信息来填充范围,其中selectNode()方法选择整个节点,包括其子节点;而selectNodeContents()方法则只选择节点的子节点。如下例子:

<body>
<p id="p1"><b>Hello</b> world!</p>
<script type="text/javascript">
var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById('p1');
range1.selectNode(p1);
range2.selectNodeContents(p1);
</script>
</body>

2.用DOM范围实现复杂选择

要创建复杂的范围就得使用setStart()和setEnd()方法。这两个方法都接受两个参数:一个参照节点和一个偏移量值。

3.操作DOM范围中的内容

  • deleteContents():从文档中删除范围所包含的内容。
  • extractContents():从文档中移除范围选区,跟deleteContents()的方法的区别在于会返回范围的文档片段。
  • cloneContents():创建范围对象的一个副本。

4.插入DOM范围中的内容

  • insertNode()
  • surroundContents()

5.折叠DOM范围

  • collapse()

6.比较DOM范围

  • compareBoundaryPoints()

7.复制DOM范围

  • cloneRange()

8.清理DOM范围

  • detach()
ranage.detach();
range = null;

《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)的更多相关文章

  1. javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记

    1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...

  2. JavaScript高级程序设计笔记 事件冒泡和事件捕获

    1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...

  3. JavaScript高级程序设计笔记之面向对象

    说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...

  4. javascript高级程序设计--笔记01

    概述 JavaScript的实现包含三个部分: 1  核心(ECMAScript)   提供核心语言功能 2  文档对象模型(DOM)  一套提供了访问以及操作网页内容的API 3  浏览器对象模型( ...

  5. JavaScript高级程序设计笔记(一)

    ---恢复内容开始--- 前三章为基础知识,为了方便以后查看,所以比较啰嗦.这里对函数的基本操作没有记录. 1.JavaScript的实现 虽然 JavaScript 和 ECMAScript 通常都 ...

  6. <javascript高级程序设计>笔记

    1.要讲一个值转换成其对应的Boolean类型 ,可以调用转型函数Boolean(). var message=“hello world!”; var messageAsBoolean=Boolean ...

  7. javaScript高级程序设计笔记 2

    Undefinde Null Boolean Number String    基本类型 Object    引用类型 只有引用类型才能动态的添加属性 赋值基本类型和引用类型也不相同,复制的基本类型的 ...

  8. javaScript高级程序设计笔记 1

    核心  ECMAScript 文档对象模型  DOM 浏览器对象模型 BOM 延迟脚本  defer typeof操作符      判断字符类型  返回   undefined  boolean  s ...

  9. Javascript高级程序设计笔记 <第五章> 引用类型

    一.object类型 创建object实例的方式有两种: //第一种使用new操作符跟构造函数 var person= new Object(); person.name="小王" ...

  10. Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)

    var obj = {'a':'a'}; var fun = function (){} console.log(typeof obj);//object console.log(typeof fun ...

随机推荐

  1. Vue 进阶之路(四)

    之前的文章我们已经对 vue 有了初步认识,这篇文章我们通过一个例子说一下 vue 的样式绑定. 现在我们想要是想这样一个需求,页面上有个单词,当我们点击它的时候颜色变为红色,再点击一次变为原来的颜色 ...

  2. Windows Server 2016 安装虚拟机版黑群晖

    硬件配置 Dell R730 CPU: Intel(R) Xeon(R) CPU E5-2603 v4 @1.70GHz(6 cores) Ram: 16Gb HDD: 系统-600GB SAS X2 ...

  3. Hi3516EV300专业型HD IP Camera SoC

    Hi3516EV300芯片特点: 处理器内核 ARM Cortex A7@ 900MHz,32KB I-Cache,32KB D-Cache /128KB L2 cache 支持 Neon 加速,集成 ...

  4. The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

    使用EF时,在Limda表达式中( query.Where(x => x.CheckInDate >= bd.Date);)查询的时候抛出了这个异常,网上查到的发现,并不能解决问题. 后来 ...

  5. Windows系统配置OutLook邮箱教程一

    本示例演示Windows系统中OutLook邮箱设置 1.打开控制面板->类型选择小图标->找到Mail(Microsoft OutLook 2016). 2.鼠标左键双击Mail. 3. ...

  6. Devops step by step

    接着上次分享的devops历程[Followme Devops实践之路], 大家希望能够出一个step by step手册, 那今天我就来和手把手来一起搭建这么一套环境, 演示整个过程! 实验环境需要 ...

  7. 最短路问题之Bellman-ford算法

    题目: 最短路:给定两个顶点,在以这两个点为起点和终点的路径中,边的权值和最小的路径.考虑权值为点之间的距离. 单源最短路问题,Bellman-ford算法 思路:每次循环检查所有边,可优化. 应用于 ...

  8. Reading task(Introduction to Algorithms. 2nd)

    Introduction to Algorithms 2nd ed. Cambridge, MA: MIT Press, 2001. ISBN: 9780262032933. Introduction ...

  9. Java数据结构和算法 - 数组

    Q: 数组的创建? A: Java中有两种数据类型,基本类型和对象类型,在许多编程语言中(甚至面向对象语言C++),数组也是基本类型.但在Java中把数组当做对象来看.因此在创建数组时,必须使用new ...

  10. Python 闭包小记

    闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...