zoukankan      html  css  js  c++  java
  • 《JavaScript高级程序设计》学习笔记——DOM

    Author:chemandy


    第十章 DOM

    DOM是针对XML和HTML文档的一个API:即规定了实现文本节点操控的属性、方法,具体实现由各自浏览器实现。

    1. 节点层次

    1) 文档节点:document,每个文档的根节点。

    2) 文档元素:即<html>元素,文档最外层元素,文档节点第一个子节点。

    3) Node类型:

    ①Node是DOM中各种节点类型的基类型,共享相同的基本属性和方法。

    □ Node.Element_NODE(1);

    □ Node.ATTRIBUTE_NODE(2);

    □ Node.TEXT_NODE(3);

    □ Node.CDATA_SECTION_NODE(4);

    □ Node.ENTITY_REFERENCE_NODE(5);

    □ Node.ENTITY_NODE(6);

    □ Node.PROCESSING_INSTRUCTION_NODE(7);

    □ Node.COMMENT_NODE(8);

    □ Node.DOCUMENT_NODE(9);

    □ Node.DOCUMENT_TYPE_NODE(10);

    □ Node.DOCUMENT_FRAGMENT_NODE(11);

    □ Node.NOTATION_NODE(12);

    每种节点的nodeType属性返回上述类型之一,为一常量。

    通过节点nodeType属性与数字值比较,可得节点类型。

    ②nodeName和nodeVlue属性。

    ③每个节点的子节点信息保存在childNodes属性中,childNodes属性中保存一个NodeList对象。

    □ NodeList对象,类数组对象,有length属性,但非Array的实例。

    □ 访问NodeList中的节点,可以通过方括号,也可以使用item()方法。

    var firstChild = someNode.ChildNodes[0];

    var secondChild = someNode.ChildNodes.item(1);

    var count = someNode.childNodes.length;

    □ 将NodeList转为数组对象。

    function convertToArray(nodes){

    var array = null;

    try{

    array = Array.prototype.slice.call(nodes,0); //非IE

    }catch(ex){

    array = new Array();

    for(var i = 0,len = nodes.length; i < len; i++){

    array.push(nodes[i]);

    }

    }

    return array;

    }

    ④parentName属性:指向文档树中父节点。

    ⑤previousSibling属性和nextSibling属性:前一个/下一个同胞节点。

    ⑥firstChild属性和lastChild属性:前一个/后一个子节点。

    ⑦hasChildNodes()方法:含子节点返回true,反之返回false。

    ⑧appendChild()方法:向childNodes列表末尾添加一个子节点,返回新增节点。

    ⑨insertBefore()方法:两个参数:要插入的节点和作为参照的节点。返回新增节点。

    ⑩replaceChild()方法:两个参数:要插入的节点和要替换节点。返回新增节点。

    ⑾removeChild()方法:移除节点。

    ⑿cloneNode()方法:接受一个布尔值。true为深复制,复制节点及子节点。false为浅复制,仅复制本身节点。

    ⒀nomalize()方法:处理文档树中文本节点。

    4) Document类型(针对document对象)

    ①Document类型表示文档,是HTMLDocument类型的一个实例,表示整个HTML页面。document对象是window对象的一个属性,可作全局对象访问。

    ②documentElement属性;该属性始终指向HTML页面中的<html>元素。

    ③body属性;直接指向<body>元素。

    ④doctype属性:访问<!DOCTYPE>,各浏览器支持不一致。用处有限。

    ⑤title属性:可获得和设置title的文本。

    ⑥URL属性:地址栏中的URL。

    ⑦domain属性:页面的域名(可设置,有限制)

    ⑧referrer属性:保存链接到当前页面的那个页面的URL

    ⑨getElementById()方法:传入元素的ID,返回元素节点。

    ⑩getElementsByTagName()方法:传入元素名,返回NodeList。

    □ 在HTML中返回一个HTMLCollection对象,与NodeList类似。

    □ 访问HTMLCollection对象:方括号语法,item()方法,namedItem()方法,HTMLCollection对象还可通过元素的name特性取得集合中的项。

    ⑾getElementsByName()方法:返回带有给定name特性的所有元素。

    ⑿特殊集合,这些集合都是HTMLCollection对象。

    □ document.anchors:包含文档中所有带name特性的<a>元素。

    □ document.applets:包含文档中所有的<applet>元素。

    □ document.forms:包含文档中所有的<form>元素。

    □ document.images:包含文档中所有的<img>元素。

    □ document.links:包含文档中所有带href属性的<a>元素。

    ⒀DOM一致性检测:document.implementation属性就为此提供相应信息和功能的对象。

    □ 此对象有一个方法:hasFeature():两个参数:要检测的DOM功能的名称及版本号。

    □ 功能:Core、XML、HTML、Views、StyleSheets、CSS、CSS2、Events、UIEvents、MouseEvents、MutationEvents、HTMLEvents、Range、Traversal、LS、LS-Async、Validation

    ⒁将输出流写入网页:write()、writeln()、open()和close()。

    5) Element类型

    ①用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问。

    ②可用nodeName属性或tagName属性访问元素标签名。tagName会在HTML中返回大写标签名,在XML中会原样返回。

    (1)HTML元素

    ■所有HTML元素都由Element类型子类HTMLElement类型表示,其属性如下:

    □id:元素在文档中的唯一标识符。

    □title:有关元素的附加说明信息,一般通过工具提示条显示出来。

    □lang:元素内容的语言代码,很少使用。

    □dir:语言的方向,值为“ltr”或“rtl”,很少使用。

    □className:与元素的class特性对应,即为元素指定的css类。

    上述这些属性都可以用来取得或修改相应的特性值。

    (2)取得特性

    ①getAttribute()方法:可以取得公认特性和自定义特性的值。

    □任何元素的所有特性,也可以通过DOM元素本身的属性来访问。alert(div.id);alert(div.align);

    □只有公认的(非自定义的)特性才会以属性的形式添加到DOM对象中。

    □style特性通过getAttribute()访问得特性值CSS文本。通过属性访问得一个对象。

    □onclick特性:getAttribute(),返回JS代码字符串。通过属性访问返回一个函数。

    □一般通过属性取得特性,只有在取自定义特性值时,才用getAttribute()。

    (3)设置特性

    ①setAttribute():两个参数,要设置的特性名和值。如果特性已经存在,setAttribute()会以指定的值替换现有的值;如果特性不存在,setAttribute()则创建该属性并设置相应的值。

    □此方法既可以操作HTML特性也可以操作自定义特性。

    □所有公认特性都是属性,因此直接给属性赋值可以设置特性的值。

    □IE6、IE7中,setAttribute()设置class、style,事件处理程序会每没有任何效果。但不建议通过属性设置特性。

    ②removeAttribute():彻底删除元素的特性(IE6不支持)。

    (4)attributes属性

    ①此属性包含一个NameNodeMap对象(类似NodeList的“动态”集合)。元素的每一个特性有一个Attr节点表示,每个节点保存在NameNodeMap对象中。

    □getNameItem(name):返回返回nodeName属性等于name的节点

    □removeNameItem(name):从列表中移除nodeName属性等于name的节点。

    □setNameItem(node):向列表中添加节点,以节点的nodeName属性为索引。

    □item(pos):返回位于数字pos位置的节点。

    (5)创建元素

    ①使用document.createElement()方法可以创建新元素。参数:标签名。

    ②IE中createElement()可传入完整的元素标签,防止IE7以及IE6问题:

    □不能设置动态创建的<iframe>元素的name特性

    □不能通过表单的reset()方法重设动态创建的<input>元素。

    □动态创建的type特性值为“reset”的<button>元素重设不了表单。

    □动态创建的一批name相同的单选按钮彼此毫无关系。

    if(client.browser.ie&&client.brower.ie<=7){

    var iframe = document.createElement("<iframe name = \"myframe\"></iframe>");

    }

    (6)元素的子节点

    ①元素的childNode属性中包含了它的所有子节点:元素、文本节点、注释或处理指令。

    □一般浏览器解析childNodes时会把元素节点空间的空白符解析为文本节点,而IE不会。因此遍历执行操作需要检查nodeType属性。

    For(var i= 0, len = element.childNode.length; i> len; i++){

    If(element.childNodes[i].nodeType == 1){

    //执行某些操作

    }

    }

    □元素节点支持getElementByTagName()方法。

    6) Text类型

    ①文本节点由Text类型表示,包含纯文本内容,不含HTML代码。

    □不支持(没有)子节点

    □nodeValue属性、data属性可访问Text节点中包含的文本。

    ②操作文本节点

    □appendData(text):将text添加到节点的末尾。

    □deleteData(offset,count):从offset位置开始删除count个字符。

    □insertData(offset,text):在offset位置插入text;

    □replaceData(offset,count,text):用text替换从offset指定的位置开始到offset+count为止处的字符串。

    □splitText(offset):从offset指定位置将当前文本节点分成两文本节点。

    □substringData(offset,count):提取offset指定的位置开始到offset+count为止处的字符串。

    □文本节点有一个length属性,保存节点中字符的数目。而nodeValue.length和data.length中也保存着同样的值。

    ○修改文本节点值时字符串经HTML编码,特殊符号转义:

    div.firstChild.nodeValue = "Some<strong>other</strong>"; //输出Some&lt;Strong&gt;other&lt;/strong&gt

    ③创建文本节点

    □使用document.createTextNode()创建新文本节点。参数:要插入的文本(自动按HTML或XML格式编码)

    ④规范化文本节点

    □DOM操作中可向同一父元素插入多个文本节点,但会造成混乱。

    □通过node类型继承的normalize()方法可合并同一父元素上的所有文本节点。

    ⑤分割文本节点

    □Text类型方法splitText():与node方法normalize()相反传入一个位置参数,从该位置拆分成两个文本节点,返回后面的文本节点。

    □分割文本节点是从文本节点中提取数据的一种常用DOM解析技术。

    7) Comment类型

    □Comment类型与Text类型继承自相同的基类,因此它拥有除splitText()之外所有字符串操作方法。

    □可使用document.createComment()创建注释节点。

    8) CDATASection类型

    □CDATASection类型只针对基于XML的文档表示CDATA区域。

    □CDATASection类型继承自Text类型,拥有除splitText()之外所有方法。

    □各大浏览器均无法正确解析这种类型。

    9) DocumentType类型

    □IE不支持

    □在DOM1级中DocumentType对象不能动态创建。

    □DocumentType对象保存在document.doctype中。

    ◇name属性:文档类型名称。

    ◇entities属性:文档类型描述的实体的NamedNodeMap对象。

    ◇notation属性:文档类型描述的符号的NamedNodeMap对象。

    10) DocumentFragment类型

    □DOM规定文档片段(document fragment)是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外资源。

    □文档片段不能添加到文档中,只会添加文档片段作为“仓库”保存的节点。

    var fragment = document.createDomFragment();

    var ul = document.getElementById("myList");

    var li = null;

    for(var i= 0; i<3; i++){

    li = document.createElement("li");

    li.appendChild(document.createTextNode("haha"));

    fragment.appendChild(li);

    }

    ul.appendChild.appendChild(li);

    □可以通过appendChild()或insertBefore()将文档片段中内容添加到文档中。

    11) Attr类型

    □是节点,但特性不被认为是DOM文档树的一部分。很少使用这类节点。

    □Attr对象3个属性:

    ◇name属性:特性名称(如nodeName)

    ◇value属性:特性的值(如nodeValue)

    ◇specified属性:布尔值,用以区别特性是在代码中指定的还是默认的。

    □不建议直接访问特性节点。建议用getAttribute()

    setAttribute()、removeAttribute()方法。0

    二、DOM扩展

    1. 呈现模式

    ①document对象的compatMode属性

    □值为“CSS1Compat”即标准模式。

    □值为“BackCompact”即混杂模式。

    ②IE8为document对象引入documentMode新属性,返回数值:5(混杂模式)、7(仿真模式)、8(标准模式)

    2. 滚动

    □滚动方法都是作为HTMLElement类型的扩展存在,可再元素节点上使用。

    □scrollIntoView(bool):滚动浏览器窗口或容器元素,以便在视口(viewport)中看到元素。(参数为true或省略,则滚动到顶部)。

    □scrollIntoViewIfNeeded(bool):只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,让当前元素可见。(Safari和Chorme实现)。

    □scrollByLines(lineCount):将元素的内容滚动指定的行数的高度,lineCount可为正/负数。(safari和Chrome可用)

    3. children属性

    □children属性中只包含元素的子节点中那些也是元素的节点。

    □作为HTMLCollection对象。

    □Firefox不支持,IE中的children集合会包含注释节点。

    4. contains()方法

    □应在作搜索起点的祖先节点上调用,传入要检测的节点作参数。返回true则传入节点作为当前节点后代。

    □Firefox不支持contains()方法,在DOM3级实现替代的compareDocumentPosition()方法,确定两个节点间关系。Safari2.x以下版本不支持。

    兼容各浏览器代码:

    function contains(refNode, otherNode){

    if(typeof refNode.contains == "function" && (!client.engine.webkit || client.engin.webkit >=552)){

    return refNode.contains(otherNode);

    }else if(tyepof refNode.compareDocumentPosition =="function"){

    return !!(refNode.compareDocumentPosition(otherNode)&16);

    }else{

    var node = otherNode.parentNode;

    do{

    if(node === refNode){

    Return true;

    }else{

    node = node.parentNode;

    }

    }while(node !== null);

    return false;

    }

    }

    5. 操作内容

    ①innerText属性

    □可读取节点文档书中由浅入深的所有文本。

    □通过inner.Text属性设置节点文本,会移除先前存在的所有子节点,完全改变了DOM树。

    □赋给此属性的文本将自动进行HTML编码。

    □Firefox不支持innerText,但支持作用类似的textContent属性。

    □innerText:支持IE、Safari、Opera、Chrome

    □textContent:支持Safari、Firefox、Opera、Chrome

    兼容代码:

    function getInnerText(element){

    return (typeof element.textContent == "string")?element.textContent:element.innerText;

    }

    function setInnerText(element, text){

    if(typeof element.textContent == "string"){

    element.textContent = text;

    }else{

    element.innerText = text;

    }

    }

    ②innerHTML属性

    □读取信息时,返回当前元素所有子节点的HTML表现。

    □写入信息时,会按照指定的值创建新的DOM子树,并以该子树替换当前元素的所有子节点。

    □innerHTML限制:插入<script>元素不会被执行。插入<style>也有类似问题。

    □并不是所有元素都有innerHTML属性。不支持的元素有<col>、<colgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<title>和<tr>。

    ③outerText属性

    □与innerText基本相同,区别在于写入信息时,会替换包含节点

    □Firefox不支持

    □不建议使用。

    ④outerHTML属性

    □与innerHTML基本相同,区别在于写入信息时,会替换包含节点。

    □Firefox不支持

    □不建议使用

    ⑤内存与性能问题

    □innerText、innerHTML、outerText、outerHTML替换子节点可能会导致浏览器的内存问题。被删除的子树中的元素设置的事件处理程序或具有值为JS对象的属性,依旧存在于内存中。

    □插入大量新HTML时,使用HTML要比通过多次DOM操作有效率得多。

    三、DOM操作技术

    1. 动态脚本

    ①插入外部文件:

    function loadScript(url){

    var script = document.createElement("script");

    script.type = "text/javascript";

    script.src = url;

    document.body.appendChild(script);

    }

    ②指定JavaScript代码方式

    □IE中将<script>视为一个特殊元素,不允许DOM访问其子节点。

    兼容方式:

    function loadScriptString(code){

    var script = document.createElement("script");

    script.type = "text/javascript";

    try{

    script.appendChild(document.createTextNode(code));

    }catch(ex){

    script.text = code;

    }

    document.body.appendChild(script);

    }

    2. 动态样式

    ①外部链接

    function loadStyles(url){

    var link = document.createElement("link");

    link.rel = "stylesheet";

    link.href = url;

    var head = document.getElementsByTagName("head")[0];

    head.appendChild(link);

    }

    ②使用<style>元素来包含嵌入式CSS

    □IE将<style>视为一个特殊的、与<script>类似的节点,不允许访问其子节点。

    □在重用一个<style>元素并再次设其styleSheet.cssText属性,有可能导致浏览器崩溃。

    fucnction loadStyleString(css){

    var style = document.createElement("style");

    style.type = "text/css";

    try{

    style.appendChild(document.createTextNode(css));

    }catch(ex){

    style.styleSheet.cssText = css;

    }

    var head = document.getElementsByTagName("head")[0];

    head.appendChild(style);

    }

    3. 操作表格

    ①为<table>元素添加的属性和方法

    □caption:保存着对<caption>元素(如果有)地指针;

    □tBodies:是一个<tobdy>元素的 HTMLCollection;

    □tFoot:保存着对<tfoot>元素(如果有)的指针;

    □tHead:保存着对<thead>元素(如果有)的指针;

    □rows:是一个表格中所有行的HTMLCollection;

    □createTHead():创建<thead>元素,将其放到表格中,返回引用。

    □createCaption():

    □deleteTHead():删除<thead>元素。

    □deleteTFoot():

    □deleteCaption():

    □deleteRow(pos):

    □insertRow(pos):向rows集合中指定位置插入一行。

    ②为<tbody>元素添加的属性和方法有:

    □rows:保存着<tbody>元素中行的HTMLCollection。

    □deleteRow(pos):删除指定位置的行;

    □insertRow(pos):向rows集合中的指定位置插入一行,返回插入行的引用。

    ③为<tr>元素添加的属性和方法

    □cells:保存着<tr>元素中单元格的HTMLCollection;

    □deleteCell(pos):删除指定位置的单元格。

    □insertCell(pos):向cells集合中指定位置插入一单元格,返回插入的单元格引用。

    4. 使用NodeList

    □NodeList及其“近亲”NamedNodeMap(Element类型中的attribute属性)和HTMLCollection,这三个集合都是“动态的”,每当文档结构发生变化时,它们都会得到更新。

    □尽量减少访问NodeList的次数。因每次访问NodeList,都会运行一次基于文档的查询。可考虑将从NodeList取得的值缓存起来。

    第十一章 DOM2和DOM3

    一、DOM变化

    1. 针对XML命名空间的变化

    ①Node类型的变化

    ■DOM2级中,Node类型包含下列特定于命名空间的属性。

    □localName:不带命名空间前缀的节点名称。

    □namespaceURI:命名空间URI,未指定则为null。

    □prefix:命名空间前缀,未指定则为null。

    ■DOM3级

    □isDefaultNamespace(namespaceURI):指定的namespaceURI在当前的默认命名空间的情况下返回true。

    □lookupNamespaceURI(prefix):返回给定prefix的命名空间。

    □lookupPrefix(namespaceURI):返回给定namespaceURI的前缀。

    ②Document类型变化

    ■DOM2级中,与命名空间有关

    □createElementNS(namespaceURI, tagName):使用给定的tagName创建一个属于命名空间namespaceURI的新元素。

    □createAttributeNS(namespaceURI, attributeName):

    □getElementBytagNameNS(namespaceURI, tagName):

    ③Elment类型的变化

    ■DOM2级核心中

    □getAttributeNS(namespaceURI, localName)

    □getAttributeNodeNS(namespaceURI, localName)

    □getElementsByTagNameNS(namespaceURI, localName)

    □hasAttributeNS(namespaceURI, localName)

    □removeAttributeNS(namespaceURI, localName)

    □setAttributeNodeNS(attrNode):设置属于命名空间namespaceURI的特性节点。

    ④NamedNodeMap类型的变化

    □getNamedItemNS(namespaceURI, localName)

    □removeNamedItemNS(namespaceURI, localName)

    □setNamedItemNS(node):添加node,这个节点已事先指定了命名空间信息。

    2. 其他方面的变化

    ①DocumentType类型的变化

    □新增3个属性:publicId、systemId和internalSubset

    □publicId、systemId表示文档类型声明中的两个信息段。

    □internalSubset:用于访问包含在文档类型声明中的额外定义。

    ②Document类型的变化

    □importNode()方法:从一个文档中取得一个节点,然后将其导入到另一个文档,使其成为文档结构的一部分。

    ◇每个节点都有一个ownerDocument属性,表示所属文档。

    ◇appendChild()传入节点属于不同文档,会导致错误。

    ◇importNode()方法与Element的cloneNode方法非常相似,接受两个参数:要复制的节点和一个表示是否复制子节点的布尔值。返回原节点的副本,但能够在当前文档中使用。

    □defaultView属性:保存着一个指针,指向拥有给定文档的窗口(或框架)。

    ◇IE不支持此属性,但有等价属性parentWindow。

    ◇确定文档归属窗口兼容代码:

    var parentWindow = document.defaultView || document.parentWindow;

    □createDocuemntType():创建一个新的DocumentType节点,接受三个参数:文档类型名称、publicId、systemId。

    □createDocument()方法:创建新文档。三个参数:针对文档中元素的namespaceURI、文档元素的标签名、新文档的文档类型。

    □“DOM2级HTML”模块为document.implementation新增一个方法,名叫createHTMLDocument()。只接受title中的文本作为参数。返回新HTML文档。包括<html>、<head>、<title>和<body>。

    ③Node类型的变化

    □isSupported()方法:与DOM1级中document.implementation引入的hasFeature()方法类似。用于确定当前节点具有什么能力。两个参数:特性名和特性版本号。

    □isSameNode()方法:传入节点,与引用节点为同一个节点则返回true。

    □isEqualNode()方法:传入节点,与引用节点相等返回true。

    □setUserData()方法:将数据指定给节点。三个参数:要设置的键,实际的数据和处理函数。

    ◇处理函数接受5个参数:表操作类型的数值(1复制2导入3删除4重命名)、数据键、数据值、源节点和目标节点。

    var div = document.createElement("div");

    div.setUserData("name","Nicholas",fucntion(operation, key, value, src, dest){

    if(operation == 1){

    dest.setUserData(key,value);

    }

    });

    ④框架的变化

    □框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示。

    □contentDocument属性:DOM2级中框架、内框架的新属性。此属性包含一个指针,指向表示框架内容的文档对象。

    □contentDocument属性是Document类型实例,因此可以像使用其他HTML文档一样使用它,包括所有属性和方法。

    □IE8之前不支持框架中的contentDocument属性,但支持一个叫contentWindow属性,返回框架的window对象。

    □访问内嵌框架文档对象兼容代码:

    var iframe = document.getElementById("myIframe");

    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

    二、样式

    1. 访问元素的样式

    ①style属性

    □支持style特性的HTML元素在JS中都有一个对应的style属性。

    □这style对象是cssStyleDeclaration的实例,包含通过style特性指定的样式。

    □在style特性指定的任何CSS属性都将表现为这个style对象的相应属性。对于使用短划线的CSS属性名,必须转换成驼峰大小写形式才能通过js访问。其中float属性不可直接使用。IE用styleFloat访问,其他浏览器用cssFloat访问。

    □如果没有为元素设置style特性,那style对象中可能会包含一些默认值,但这些值不反映元素正确的样式信息。

    ②DOM样式属性和方法

    1)DOM2级还为style对象定义了一些属性和方法。在提供特性值时也可修改样式。

    □cssText:访问style特性中的css代码。

    □length:应用给元素的css属性数量。

    □parentRule:表示css信息的CSSRule对象。

    □getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象,含两个属性cssText和cssValueType。

    □getProperytPriority(propertyName):如果给定的属性使用了!important设置,则返回“important”,否则返回空字符串。

    □item(index):返回给定位置的CSS属性的名称。

    □removeProperyt(propertyName):从样式中删除给定属性。

    □setProperty(propertyName, value, priority):将给定属性设置为相应的值,并加上优先权标志(“important”或者一个空字符串)。

    2)使用

    □设计length属性的目的,就是将其与item()方法配套使用。以便迭代元素中定义的css属性。

    □Firefox、Safari、Opera9及更高、chrome均支持这些属性和方法。IE只支持cssText。

    □getPropertyCSSValue()只有Safari和chrome支持。

    ③计算的样式

    □“DOM2级样式”增强了document.defaultView,提供了getComputedStyle()方法。

    □getComputedStyle():2个参数:要取得计算样式的元素和一个伪元素字符串(如:after)。如果不需要伪元素信息,第二个参数可以为null。返回一个CSSStyleDeclaration对象(与style属性类型相同)。

    □IE不支持getComputedStyle()方法。但IE中有style特性的元素均有一个currentStyle属性(CSSStyleDeclaration的实例)包含当前元素全部计算后的样式。

    □计算样式兼容代码:

    var myDiv = document.getElementById("myDiv");

    var computedStyle = document.defaultView.getComputedStyle(mydiv, null) || myDiv.currentStyle;

    alert(computedStyle.width);

    alert(computedStyle.height);

    2. 操作样式表

    ①CSSStyleSheet类型

    1)操控<link>元素样式表和<style>元素样式表。

    2)确定浏览器是否支持DOM2级样式表。

    var supportDOM2StyleSheets = document.implementation.hasFeature("StyleSheet","2.0");

    3)CSSStyleSheet继承自StyleSheet,后者可以作为一个基础接口来定义非CSS样式表。从StyleSheet接口继承而来的属性如下:

    □disabled:表示样式表是否被禁用的布尔值。可读/写。设为true则禁用。

    □href:如果样式表是通过<link>包含的,则是样式表的URL,否则是null。

    □media:当前样式表支持的所有媒体类型的集合。与所有DOM集合一样,有length属性和item()方法。

    □ownerNode:指向拥有当前样式表的节点的指针。若通过@import导入则属性为null。IE不支持此属性。

    □parentStyleSheet:当前样式表是通过@import导入的情况下,这个属性指向导入它的样式表的指针。

    □title:ownerNode中title属性的值。

    □type:表示样式表类型的字符串。对css样式表而言,这个字符串是“type/css”。

    ■以上属性除disabled外,全部只读。

    4)CSSStyleSheet在上述基础上添加以下属性和方法:

    □cssRule:样式表中包含的样式规则的集合。IE不支持,但有类似的rules属性。

    □ownerRule:如果样式表是通过@import导入的,这个属性就是一个指针,指向表示导入的规则;否则为null。IE不支持这个属性。

    □deleRule(index):删除cssRules集合中指定位置的规则。IE不支持,但支持一类似的removeRule()方法。

    □insertRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持,但支持类似的addRule()方法。

    5)获取样式表对象

    □应用于文档的所有样式表是通过document.styleSheets集合来表示的。通过这个集合的length属性可以获取文档中样式表的数量,而通过方括号语法或item()方法可以访问每一个样式表。

    var sheet = null;

    for(var i = 0, len = document.styleSheets.length; i < len; i++){

    sheet = document.styleSheets[i];

    alert(sheet.href);

    }

    □不同浏览器的document.styleSheets返回的样式表也不同。所有浏览器都会包含<style>元素和rel特性被设置为“stylesheet”的<link>元素引入的样式表。

    □可直接通过<link>或<style>元素取得CSSStyleSheet对象。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);

    ②CSS规则

    1)CSSRule对象表示样式表中的每一条规则,是一个供其他多种类型继承的基类型,其中最常见的就是CSSStyleRule类型,表示样式信息。

    2)CSSStyleRule对象包含下列属性:

    □cssText:返回整条规则对应的文本,IE不支持。

    □parentRule:如果当前规则是导入的规则,这属性引用的就是导入规则;否则这个值为null。IE不支持。

    □parentStyleSheet:当前规则所属的样式表。IE不支持。

    □selectorText:返回当前规则的选择符文本。

    □style:一个CSSStyleDeclaration对象,可以通过它设置和取得规则中特定的样式值。

    □type:表示规则类型的常量值。对于样式规则,这个值是1。IE不支持。

    ■其中最常用的属性是cssText、selectorText和style。

    □cssText属性与style.cssText属性类似但并不相同。前者包含选择符文本和围绕样式信息的花括号,后者只含样式信息(类似于元素的style.cssText)。而cssText只读,style.cssText可读/写。

    var sheet = document.styleSheets[0];

    var rules = sheet.cssRules || sheet.rules;

    var rule = rules[0];

    alert(rule.style.backgroundColor);

    rule.style.backgroundColor="red";

    ③创建规则

    □insertRule()方法:接受两个参数:规则文本和表达在哪里插入规则的索引。//IE不支持

    sheet.insertRule("body{background-color:silver}",0); //DOM方法。

    □addRule():IE中支持。两个必选参数:选择符文本和CSS样式信息。一个可选参数:插入规则的位置。//仅IE支持

    Sheet.addRule("body","background-color:silver",0);

    □跨浏览器兼容

    function insertRule(sheet, selectorText, cssText, position){

    if(sheet.insertRule){

    sheet.insertRule(selectorText + "{" + cssText + "}", position);

    }else if(sheet.addRule){

    sheet.addRule(selectorText,cssText,position);

    }

    }

    调用:insertRule(document.styleSheets[0], "body", "background-color:red", 0);

    □当需要添加的规则多时,操作繁琐。建议采用动态加载样式表。

    ④删除规则

    □sheet.deleteRule(0); //DOM方法,IE不支持

    Sheet.removeRule(0); //IE方法,两者都是传入要删除的规则的位置。

    □跨浏览器兼容:

    function deleteRule(sheet, index){

    if(sheet.deleteRule){

    Sheet.deleteRule(index);

    }else if(sheet.removeRule){

    Sheet.removeRule(index);

    }

    }

    调用方式:deleteRule(document.styleSheets[0],0);

    □这种做法不是实际web开发中常见做法。删除规则会影响CSS层叠效果。慎用。

    3. 元素大小(非DOM2级样式,但所有浏览器支持)

    ①偏移量(offset dimension)

    定义:包括元素在屏幕上占用的所有可见的空间。元素的可见大小由其高度、宽度决定,包括所有内边距、滚动条和边框大小(注意,不包括外边距)

    □offsetHeight:元素在垂直方向上占用的空间大小,以像素计。

    □offsetWidth:元素在水平方向上占用的空间大小,以像素计。

    □offsetLeft:元素左边框至包含的左内边框之间的像素距离。

    □offsetTop:元素的上边框至包含元素的上内边框之间的像素距离。

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

    △这些属性是只读的,每次访问需要重新计算。若重复使用,应保存在局部变量中。

    ②客户区大小(client dimension)

    元素内容及其内边距所占大小。滚动条占用空间不算在内。

    □clientWidth属性:元素内容区宽度加上左右内边距宽度。

    □clientHeight属性:元素内容区高度加上上下内边距高度。

    □确定浏览器视口大小可用document.documentElement或document.body(IE6的混杂模式中)。

    function getViewport(){

    if(document.compatMode == "BackCompat"){

    return{

    document.body.clientWidth,

    height:document.body.clientheight

    };

    }else{

    return{

    document.documentElement.clientWidth,

    height:document.documentElement.clientHeight

    };

    }

    }

    ③滚动大小

    指包含滚动内容的元素的大小。

    □scrollHeight:在没有滚动条的情况下,元素内容的总高度。

    □scrollWidth:在没有滚动条的情况下,元素内容的总宽度。

    □scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。

    □scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。

    ◇在确定文档的总高度时(包括基于视口的最小高度时),必须取得scrollWidth/clientWidth和scrollHeight/clientHeight中的最大值,保证跨浏览器。

    Var docHeight = Max.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);

    Var docWidth = Max.max(document.documentElement.scrollWidth,document.docuemntElement.clientWidth);

    注:对于运行在混杂模式下的IE,则需要用document.body代替document.documentElement。

    ◇通过scrollLeft和scrollTop属性既可以确定元素当前的滚动状态,也可以设置元素滚动位置。

    function scrollToTop(element){

    if(element.scrollTop != 0){

    element.scrollTop = 0;

    }

    }

    ④确定元素大小

    □IE、Firefox3及更高和Opera9.5及更高为每一个元素提供了一个getBoundingClientRect()方法。这个方法返回一个矩形对象,含4个属性:left、top、right和bottom。这些属性给出了元素在页面中相对于视口的位置。但IE认为左上角坐标为(2,2),其他浏览器认为是(0,0)。

    function getBoundingClientRect(element){

    var scrollTop = document.documentElement.scrollTop;

    var scrollLeft = document.documentElement.scrollLeft;

    if(element.getBoundingClientRect){

    If(typeof arguments.callee.offset != "number"){

    var temp = document.createElement("div");

    temp.style.cssText = "position:absolute;left:0;top:0;";

    document.body.appendChild(temp);

    arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;

    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 - scrollTop,

    bottom: actualTop + element.offsetHeight - scrollTop

    }

    }

    }

    三、遍历

    ①概况:“DOM2级遍历和范围”模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreWalker。这两个类型能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作。

    □在与DOM兼容版本中可访问这些对象。IE不支持遍历。

    □检查浏览器对DOM2级遍历能力的支持。

    var supportsTraversals = document.implementation.hasFeature("Traversal","2.0");

    var supportsNodeIterator = (typeof document.createNodeIterator == "function");

    var supportsTreeWalker = (typeof document.createTreeWalker == "function");

    ②NodeIterator

    1)可以使用document.createNodeIterator()方法创建它的新实例。

    接受4个参数:

    □root:想要作为搜索起点的树种的节点。

    □whatToShow:表示要访问哪些节点的数字代码。

    □filter:是一个NodeFilter对象,或者一个表示应该接受还是拒绝某种特定节点的函数。

    □entityReferenceExpansion:布尔值,表示是否要扩展实体引用。此参数在HTML页面中没有用。

    ■whatToShow参数是一个位掩码,其值以常量形式在NodeFilter类型中定义。

    □NodeFilter.SHOW_ALL:显示所有类型的节点。

    □NodeFilter.SHOW_ELEMENT:显示元素节点。

    □NodeFilter.SHOW_ATTRIBUTE:显示特性节点。由于DOM结构原因,实际上不能使用这个值。

    □NodeFilter.SHOW_TEXT:显示文本节点。

    □NodeFilter.SHOW_CDATA_SECTION:显示CDATA节点。对HTML无用。

    □NodeFilter.SHOW_ENTITY_REFERENCE:显示实体引用节点。对HTML无用。

    □NodeFilter.SHOW_ENTITYPE:显示实体节点。对HTML无用。

    □NodeFilter.SHOW_PROCESSING_INSTRUCTION:显示处理指令节点。对HTML无用。

    □NodeFilter.SHOW_COMMENT:显示注释节点。

    □NodeFilter.SHOW_DOCUMENT:显示文档节点。

    □NodeFilter.SHOW_DOCUMENT_TYPE:显示文档类型节点。

    □NodeFilter.SHOW_DOCUMENT_FRAGMENT:显示文档片段节点。对HTML无用。

    □NodeFilter.SHOW_NOTATION:显示符号节点。对HTML无用。

    ◇除了NodeFilter_SHOW_ALL外,可以使用按位或操作符来组合多个选项。

    var whatToShow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;

    ◇用filter参数自定义NodeFilter对象或一个过滤器函数。

    NodeFilter对象只有一个方法,即acceptNode(),访问则放回NodeFilter.FILTER_ACCEPT,不访问则返回NodeFilter.FILTER_SKIP

    例1:迭代器

    var filter= {

    acceptNode:function(node)P{

    return node.tagName.toLowerCase()=="p" ? 

    NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;

    }

    }

    };

    var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);

    例2:filtr参数也可以是一个与acceptNode方法类似的函数。

    var filter = function(node){

    return node.tagName.toLowerCase() == "p" ? 

    NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;

    };

    var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);

    2)NodeIterator类型主要两个方法:nextNode()和previousNode()。

    var div = document.getElemetnById("div1");

    var iterator = document.createNodeIterator(div,NodeFilter.SHOW_ELEMENT,null,false);

    var node = iterator.nextNode();

    while(node !== null){

    alert(node.tagName);

    node = iterator.nextNode();

    }

    ③TreeWalker

    1)TreeWalker是NodeIterator的一个更高级版本。除了有nextNode()和previousNode()外,还有下列用于在不同方向上遍历DOM结构的方法:

    □parentNode():遍历到当前节点的父节点。

    □firstChild():遍历到当前节点的第一个子节点。

    □lastChild():便历到当前节点的最后一个子节点。

    □nextSibling():遍历到当前节点的下一个同辈节点。

    □previousSibling():遍历到当前节点的上一个同辈节点。

    2)创建TreeWalker对象要使用document.createTreeWalker()方法,接受4个参数,与document.createNodeIterator()方法相同。

    □其中第3个参数filter返回值除了可以返回NodeFilter.FITER_ACCEPT和NodeFilter.FILTER_SKIP外,还可以使用NodeFILTER_REJECT(作用:跳过相应的节点及该节点的整个子树)。

    □TreeWalker强大之处在于能够在DOM结构中沿任何方向移动。

    ◇例:遍历DOM树,即使不定义过滤器,也可以取得所有<li>元素。

    var div = document.getElementById("div1");

    var walker = document.createTreeWalker(div,NodeFilter.SHOW_ELEMENT,null,false);

    walker.firstChild();

    walker.nextSibling();

    var node = walker.firstChild();

    while(node !== null)}

    alert(node.tagName);

    node = walker.nextSibling();

    }

    □TreeWalker类型还有一个属性,名叫currentNode,表示任何遍历方法在上一次遍历中返回的节点。

    四、范围

    基本定义:

    通过范围可以选择文档中的一个区域,而不必考虑节点的界限(选择在后台完成,对用户看不见)。在常规DOM操作中不能更有效地修改文档时,使用范围往往可以达到目的。

    1.DOM中的范围

    ①概况:

    1)DOM2级在Document类型中定义了createRange()方法。

    □检查是否支持范围:

    var supportsRange = document.implementation.hasFeature("Range","2.0");

    var alsoSupportsRange = (typeof document.createRange == "function");

    □创建DOM范围: var range = document.createRange();

    2)Range类型实例中,提供当前范围在文档中的位置信息的属性:

    □startContainer:包含范围起点的节点(即选取中第一个节点的父节点)

    □startOffset:范围在startContainer中起点的偏移量。如StartContainer是文本节点,则startOffset就是范围起点之前跳过的字符数量。否则,startOffset就是范围中第一个子节点在父节点中的索引。

    □endContainer:包含范围终点的节点(即选取最后一个节点的父节点)。

    □endOffset:范围在endContainer中终点的偏移量(规则如startoffset)

    □commonAncestorContainer:startContainer和endContainer共同的祖先节点在文档树种位置最深的那个。

    ②用DOM范围实现简单选择:

    1)使用范围选择文档中的一部分:

    □selectNode():传入一个DOM节点,选择整个节点,包括子节点作范围。

    □selectNodeContents():传入一个DOM节点,只选择子节点作范围。

    2)更精细地控制范围:

    □setStartBefore(refNode):将范围的起点设置在refNode之前,因此refNode也就是范围选取中第一个子节点。范围的位置属性自动更新。

    □setStartAfter(refNode):

    □setEndBefore(refNode):

    □setEndAfter(refNode):

    ③用DOM范围实现复杂选择:

    □setStart():传入一个参照点和一个偏移量。参照节点成startContainer,而偏移量成startOffset。

    □setEnd():传入一参照点和一个偏移量。参照节点成endContainer,而偏移量成endOffset。

    <p id="p1"><b>Hello</b> world!</p>  //使用范围选择l到o。

    var p1 = document.getElementById("p1");

    var helloNode = p1.firstChild.firstChild;

    var worldNode = p1.lastChild;

    var range = document.createRange();

    range.setStart(helloNode,2);

    range.setEnd(worldNode,3);

    ④操作DOM范围中的内容

    □在调用操作方法时,后台会为范围创建有效的文档片段及DOM结构。P275

    □deleteContents():从文档中删除范围所包含的内容。

    □extractContents():从文档中删除范围内容,返回范围文档片段。

    ⑤插入DOM范围中的内容

    □insertNode():向范围选区的开始处插入一个节点。

    □surroundContents():接受一个参数,即环绕范围内容的节点。

    a.提取出范围中的内容(类似执行extractContent())

    b.将给定节点插入到文档中原来范围所在的位置上。

    c.将文档片段的内容添加到给定节点中。

    ⑥折叠DOM范围

    □所谓折叠范围,就是指范围中未选择文档的任何部分。

    □collapse()方法:一个参数布尔值。true折叠到范围起点,false折叠到范围终点。可以用collapsed属性检查是否已经折叠。

    range.collapse(true);  //折叠到起点

    alert(range.collapsed);  //输出true

    ⑦比较DOM范围

    在有多个范围的情况下,可以使用compareBoundaryPoints()方法来确定这些范围是否有公共的边界(起点或终点)。两个参数:表示比较方式的常量和要比较的范围。

    比较方式常量值:

    □Range.START_TO_START(0):比较第一个范围和第二个范围起点。

    □Range.START_TO_END(1):

    □Range.END_TO_END(2):

    □Range.END_TO_STRAT(3):

    ⑧复制DOM范围

    □cloneRange()方法:var newRange = range.cloneRange();

    ⑨清理DOM范围

    □调用detach()方法,从文档分离出范围。

    range.detach();  //从文档中分离

    range = null; //解除引用

    2.IE中的范围

    ①概况:

    □IE不支持DOM范围。支持类似的文本范围(text range)。

    □文本范围处理的主要是文本(不一定是DOM节点)。通过<body>、<button>、<input>和<textarea>等元素调用createTextRange()方法。

    □通过document创建的范围可以在页面中的任何地方使用。

    var range = document.body.createTextRange();

    ②用IE范围实现简单选择

    □findText()方法:找到第一次出现的给定文本,并将范围移过来以环绕该文本。返回布尔值,表示是否找到文本。

    ◇使用text属性可返回范围中文本。

    var range = document.body.createTextRange();

    var found = range.findText("Hello");

    ◇可为findText传入另一个参数,负值即当前位置向后搜,正值则向前搜。

    □moveToElementText()方法:类似DOM中selectNode()方法。接受一个DOM元素,并选择该元素的所有文本,包括HTML标签。

    ◇范围可用htmlText属性取得范围全部内容,包括HTML。

    ③使用IE范围实现复杂选择

    □4个方法:move()、moveStart()、moveEnd()、expand();两个参数:移动单位和移动单位数量。移动单位为以下一种字符串:

    ◇"character":逐个字符地移动。

    ◇"word":逐个单词(一系列非空格字符地移动)

    ◇"sentence":逐个句子(一系列句号、问好或感叹号结尾的字符地移动)

    ◇"textedit":移到当前范围选取的开始或结束位置。

    □moveStart():移动到范围起点;moveEnd()移动到范围终点。

    □expand():将任何部分选择的文本全部选中。

    □move()方法:首先会折叠当前范围(起点终点相等),然后将范围移动指定的单位数量。

    ④操作IE范围中的内容

    □范围仅含文本可通过text属性读写文本。

    □pasteHTML()方法:向范围插入HTML代码。

    ⑤折叠IE范围

    □collapse()方法:传入布尔值,true折叠到起点,false折叠到终点。

    □检查折叠是否完毕:boundingWidth属性等于0

    var isCollapse = (range.boundingWidth == 0);

    ⑥比较IE范围

    □compareEndPoints()方法:两个参数:比较类型和要比较的范围。

    ◇比较类型取值字符串:“startToStart”“StartToEnd”、“EndToEnd”和“EndToStart”。

    ◇如果第一个范围边界位于第二个前,返回-1;相等返回0;在后面返回1.

    □isEquanl()用于确定两个范围是否相等。

    □inRange()用于确定一个范围是否包含另一个范围。

    ⑦复制IE范围

    使用duplicate()方法,复制文本范围,返回副本。

    var newRange = range.duplicate();

  • 相关阅读:
    e621. Activating a Keystroke When Any Child Component Has Focus
    e587. Filling Basic Shapes
    e591. Drawing Simple Text
    e595. Drawing an Image
    e586. Drawing Simple Shapes
    e636. Listening to All Key Events Before Delivery to Focused Component
    在 PL/SQL 块的哪部分可以对初始变量赋予新值? (选择1项)
    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)
    你判断下面语句,有什么作用?(单选)
    Oracle数据库表空间与数据文件的关系描述正确的是( )
  • 原文地址:https://www.cnblogs.com/chemandy/p/2161980.html
Copyright © 2011-2022 走看看