《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)

时间:2022-04-02 13:07:21

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);

得到的结果如下图:

《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)

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

元素大小

1.偏移量

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

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

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

《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)

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

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:元素内容区高度加上上下内边距高度(因此滚动条占据的空间不计算在内)。

如图所示描述:

《JavaScript高级程序设计》笔记:DOM2和DOM3(十二)

例如:要确认浏览器视口大小,可以使用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. &lt&semi;javascript高级程序设计&gt&semi;笔记

    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高级程序设计笔记 &lt&semi;第五章&gt&semi; 引用类型

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

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

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

随机推荐

  1. 初学者对于MVC架构模式学习与理解

    理解MVC的工作原理,明白一个网页是如何显示出来的 之前一直盲目的在慕课上看视频,脑袋里想着要理解mvc,看了mvc相关的视频,看完之后就觉得空白白的,M,V,C各代表什么我知道,但是这个究竟有啥意思 ...

  2. 关于C&num;操作数据库ExecuteNonQuery&lpar;&rpar;的返回值问题

    ) { retValue = AccessCon.ExecuteSql(sql = "update salesData set sellingPrize='" + man.Sell ...

  3. 在Sublime Text3上面更加方便愉快的写php

    写php代码,elcipse体积太大,开起来太麻烦,记事本又没有什么标识,稍不留神就会出现;没加.大括号没对全的尴尬情况.所以我选择使用Sublime. 推荐几个 sublime插件:sublimeL ...

  4. WCF之多个协定

    多个协定”示例演示如何在一个服务上实现多个协定,以及如何配置终结点以便与实现的每个协定进行通信 1.服务端代码如下(服务实现了两个协定,增加了黄色所示代码): class Program { stat ...

  5. 30道四则运算题目---课堂作业--软件工程c&plus;&plus;

    问题:设计一程序,给二年级小学生随机产生四则运算题目. 一.设计思考问题: 1.四则运算需要俩个运算数和一个运算符. 2.如何产生随机数? 3.如何实现随机产生四则运算? 4.题目是否符合小学生学习范 ...

  6. 应用TcpListener实现的socket服务器端

    前言 项目中要实现一个简单的socket服务器端,采用了TcpListener这个类.除了基本的功能之外,有几处需要注意的点. 要能同时接收多个客户端的连接,当然,不需要几千个那么多. 要能探测到客户 ...

  7. POJ 2481-Cows(BIT)

    题意: n个牛,每个牛对应一个区间,对于每个牛求n个区间有几个包含该牛的区间. 分析: 先 区间右边界从大到小排序,相同时左边界小到大,统计第i头牛即左边界在前i-1头左边界的正序数. #includ ...

  8. POJ 2986 A Triangle and a Circle 圆与三角形的公共面积

    计算几何模板 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h& ...

  9. 11g Rac 切换

    <pre name="code" class="sql">[grid@devrac1 ~]$ crsctl status res -t ------ ...

  10. Sql存储过程解密方法

    在网上查到这样一个存储过程解密的方法,用起来简单,收藏到这里: )) AS ------------------------sql2000大于40000的----------------- --原作: ...