1### Menu
第11 章 DOM 擴(kuò)展
11.1.1 querySelector()方法
11.1.2 querySelectorAll()方法
11.1.3 element.matches() element.webkitMatchesSelector()方法
11.2 元素遍歷
HTML5 - 11.3.1 與類(lèi)相關(guān)的擴(kuò)充
HTML5 - 11.3.2 焦點(diǎn)管理
HTML5 - 11.3.3HTMLDocument的變化
HTML5 - 11.3.4 字符集屬性
HTML5 - 11.3.5 自定義數(shù)據(jù)屬性
HTML5 - 11.3.6 插入標(biāo)記
- innerHTML 屬性
- outerHTML 屬性
- insertAdjacentHTML()方法
- 內(nèi)存與性能問(wèn)題
11.4 專(zhuān)有擴(kuò)展
- 11.4.1 文檔模式
- 11.4.2 children屬性
- 11.4.3 contains()方法 & compareDocumentPosition()方法
- 11.4.4 插入文本
- 1. innerText 屬性
- 2. outerText 屬性 - 11.4.5 滾動(dòng)
第12 章 DOM2 和DOM3
12.2 樣式
- 12.2.1 訪問(wèn)元素的樣式
- DOM 樣式屬性和方法
- 計(jì)算的樣式
- 12.2.2 操作樣式表
- CSS 規(guī)則
- 創(chuàng)建規(guī)則
- 刪除規(guī)則
- 12.2.3 元素大小
- 偏移量
- 客戶區(qū)大小
- 滾動(dòng)大小
- 確定元素大小
- 12.3 遍歷
- 12.3.1 NodeIterator
- 12.3.2 TreeWalker
- 12.4 范圍
- 12.4.1 DOM中的范圍
- 用 DOM 范圍實(shí)現(xiàn)簡(jiǎn)單選擇
- 用 DOM 范圍實(shí)現(xiàn)復(fù)雜選擇
- 操作 DOM 范圍中的內(nèi)容
- 插入 DOM 范圍中的內(nèi)容
- 折疊 DOM 范圍
- 比較 DOM 范圍
- 復(fù)制 DOM 范圍
- 清理 DOM 范圍
- 12.4.1 DOM中的范圍
-
11.1.1 querySelector()方法
- querySelector()方法接收一個(gè) CSS 選擇符,返回與該模式匹配的第一個(gè)元素,如果沒(méi)有找到匹配的元素,返回 null。
//取得 body 元素
var body = document.querySelector("body");
//取得 ID 為"myDiv"的元素
var myDiv = document.querySelector("#myDiv");
//取得類(lèi)為"selected"的第一個(gè)元素
var selected = document.querySelector(".selected");
//取得類(lèi)為"button"的第一個(gè)圖像元素
var img = document.body.querySelector("img.button");
- 通過(guò) Document 類(lèi)型調(diào)用 querySelector()方法時(shí),會(huì)在文檔元素的范圍內(nèi)查找匹配的元素。而通過(guò) Element 類(lèi)型調(diào)用 querySelector()方法時(shí),只會(huì)在該元素后代元素的范圍內(nèi)查找匹配的元素。
- CSS 選擇符可以簡(jiǎn)單也可以復(fù)雜,視情況而定。如果傳入了不被支持的選擇符, querySelector()會(huì)拋出錯(cuò)誤。
-
11.1.2 querySelectorAll()方法
- querySelectorAll() 方法接收的參數(shù)與 querySelector()方法一樣,都是一個(gè) CSS 選擇符,返回的是一個(gè) NodeList 的實(shí)例。
- 只要傳給 querySelectorAll()方法的 CSS 選擇符有效,該方法都會(huì)返回一個(gè) NodeList 對(duì)象,而不管找到多少匹配的元素。如果沒(méi)有找到匹配的元素, NodeList 就是空的。
- 與 querySelector()類(lèi)似,能夠調(diào)用 querySelectorAll()方法的類(lèi)型包括 Document、DocumentFragment 和 Element。
//取得某<div>中的所有<em>元素(類(lèi)似于 getElementsByTagName("em"))
var ems = document.getElementById("myDiv").querySelectorAll("em");
//取得類(lèi)為"selected"的所有元素
var selecteds = document.querySelectorAll(".selected");
//取得所有<p>元素中的所有<strong>元素
var strongs = document.querySelectorAll("p strong");
- 要取得返回的 NodeList 中的每一個(gè)元素,可以使用 item()方法,也可以使用方括號(hào)語(yǔ)法
var i, len, strong;
for (i=0, len=strongs.length; i < len; i++){
strong = strongs[i]; //或者 strongs.item(i)
strong.className = "important";
}
11.1.3 element.matches() element.webkitMatchesSelector()方法
- 這個(gè)方法接收一個(gè)參數(shù),即 CSS 選擇符,如果調(diào)用元素與該選擇符匹配,返回 true;否則,返回 false。
- 在取得某個(gè)元素引用的情況下,使用這個(gè)方法能夠方便地檢測(cè)它是否會(huì)被 querySelector() 或 querySelectorAll()方法返回。
- webkitMatchesSelector() // 除了IE其它瀏覽器用這個(gè)方法match
- msMatchesSelector():IE瀏覽器用這個(gè)方法
if (document.body.webkitMatchesSelector("body.page1")){
//true
}
-
11.2 元素遍歷
- 在使用 childNodes時(shí)會(huì)返回除了元素節(jié)點(diǎn)以外的所有節(jié)點(diǎn),為了彌補(bǔ)這一差異,而同時(shí)又保持 DOM 規(guī)范不變, Element Traversal 規(guī)范(www.w3.org/TR/ElementTraversal/)新定義了一組屬性。
- Element Traversal API 為 DOM 元素添加了以下 5 個(gè)屬性。
- childElementCount:返回子元素(不包括文本節(jié)點(diǎn)和注釋?zhuān)┑膫€(gè)數(shù)。
- firstElementChild:指向第一個(gè)子元素; firstChild 的元素版。
- lastElementChild:指向最后一個(gè)子元素; lastChild 的元素版。
- previousElementSibling:指向前一個(gè)同輩元素; previousSibling 的元素版。
- nextElementSibling:指向后一個(gè)同輩元素; nextSibling 的元素版。
支持的瀏覽器為 DOM 元素添加了這些屬性,利用這些元素不必?fù)?dān)心空白文本節(jié)點(diǎn)
-
HTML5 - 11.3.1 與類(lèi)相關(guān)的擴(kuò)充
- 1. getElementsByClassName()方法
- 可以通過(guò) document對(duì)象及所有 HTML 元素調(diào)用該方法;
- getElementsByClassName()方法接收一個(gè)參數(shù),該參數(shù)可以是一個(gè)或多個(gè)類(lèi)名字符串,通過(guò)空格分隔;
- 該方法會(huì)返回element或document的后代元素中匹配的元素,返回的是NodeList動(dòng)態(tài)集合類(lèi)型;
//取得所有類(lèi)中包含"username"和"current"的元素,類(lèi)名的先后順序無(wú)所謂
var allCurrentUsernames = document.getElementsByClassName("username current");
//取得 ID 為"myDiv"的元素中帶有類(lèi)名"selected"的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");
- 2. classList 屬性
- 通過(guò) className 屬性為element添加、刪除和替換類(lèi)名。
- 這個(gè) classList 屬性是新集合類(lèi)型 DOMTokenList 的實(shí)例。與其他 DOM 集合類(lèi)似;
- DOMTokenList 有一個(gè)表示自己包含多少元素的 length 屬性,而要取得每個(gè)元素可以使用 item()方法,也可以使用方括號(hào)語(yǔ)法。此外,這個(gè)新類(lèi)型還定義如下方法。
- add(value):將給定的字符串值添加到列表中。如果值已經(jīng)存在,就不添加了。
- contains(value):表示列表中是否存在給定的值,如果存在則返回 true,否則返回 false。
- remove(value):從列表中刪除給定的字符串。
- toggle(value):如果列表中已經(jīng)存在給定的值,刪除它;如果列表中沒(méi)有給定的值,添加它。
//刪除"disabled"類(lèi)
div.classList.remove("disabled");
//添加"current"類(lèi)
div.classList.add("current");
//切換"user"類(lèi)
div.classList.toggle("user");
//確定元素中是否包含既定的類(lèi)名
if (div.classList.contains("bd") && !div.classList.contains("disabled")){
//執(zhí)行操作
)
//迭代類(lèi)名
for (var i=0, len=div.classList.length; i < len; i++){
doSomething(div.classList[i]);
}
HTML5 - 11.3.2 焦點(diǎn)管理
- document.activeElement 屬性,這個(gè)屬性始終會(huì)引用 DOM 中當(dāng)前獲得了焦點(diǎn)的元素。
- 元素獲得焦點(diǎn)的方式有頁(yè)面加載、用戶輸入(通常是通過(guò)按 Tab 鍵)和在代碼中調(diào)用 focus()方法。
var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
- document.hasFocus()方法,這個(gè)方法用于確定文檔是否獲得了焦點(diǎn)。
var button = document.getElementById("myButton");
button.focus();
alert(document.hasFocus()); //true
11.3.3 HTML5 - HTMLDocument的變化
- 1. readyState 屬性
- Document 的 readyState 屬性有兩個(gè)可能的值:
- loading,正在加載文檔;
- complete,已經(jīng)加載完文檔。
if (document.readyState == "complete"){
//執(zhí)行操作
}
2. 兼容模式
檢測(cè)頁(yè)面的兼容模式 document.compatMode ;
在標(biāo)準(zhǔn)模式下, document.compatMode 的值等于"CSS1Compat",
而在混雜模式下, document.compatMode 的值等于"BackCompat"
3. head 屬性
document.head 屬性,引用文檔的<head>元素。
HTML5 - 11.3.4 字符集屬性
- charset
- charset屬性表示文檔中實(shí)際使用的字符集,也可以用來(lái)指定新字符集。
- 默認(rèn)情況下,這個(gè)屬性的值為"UTF-16",但可以通過(guò)<meta>元素、響應(yīng)頭
部或直接設(shè)置 charset 屬性修改這個(gè)值。來(lái)看一個(gè)例子。
alert(document.charset); //"UTF-16"
document.charset = "UTF-8";
- defaultCharset
- 另一個(gè)屬性是 defaultCharset,表示根據(jù)默認(rèn)瀏覽器及操作系統(tǒng)的設(shè)置,當(dāng)前文檔默認(rèn)的字符集應(yīng)該是什么。如果文檔沒(méi)有使用默認(rèn)的字符集,那 charset 和 defaultCharset 屬性的值可能會(huì)不一樣;
HTML5 - 11.3.5 自定義數(shù)據(jù)屬性
- HTML5 規(guī)定可以為元素添加非標(biāo)準(zhǔn)的屬性,但要添加前綴 data-,目的是為元素提供與渲染無(wú)關(guān)的信息,或者提供語(yǔ)義信息。這些屬性可以任意添加、隨便命名,只要以 data-開(kāi)頭即可。
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
- 添加了自定義屬性之后,可以通過(guò)元素的 dataset 屬性來(lái)訪問(wèn)自定義屬性的值。 dataset 屬性的值是 DOMStringMap 的一個(gè)實(shí)例,也就是一個(gè)名值對(duì)兒的映射。
var div = document.getElementById("myDiv");
//取得自定義屬性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;
//設(shè)置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
HTML5 - 11.3.6 插入標(biāo)記
- 1. innerHTML 屬性
- 在讀模式下, innerHTML 屬性返回與調(diào)用元素的所有子節(jié)點(diǎn)(包括元素、注釋和文本節(jié)點(diǎn))對(duì)應(yīng)的 HTML 標(biāo)記。
- 在寫(xiě)模式下, innerHTML 會(huì)根據(jù)指定的值創(chuàng)建新的 DOM 樹(shù),然后用這個(gè) DOM 樹(shù)完全替換調(diào)用元素原先的所有子節(jié)點(diǎn)。
- 在子節(jié)點(diǎn)的內(nèi)容被替換后,被替換的元素節(jié)點(diǎn)的屬性,事件處理等還會(huì)留在屬性里,所以需要先刪除屬性和的事件,在做替換;
div = document.createElement("div");
div.innerHTML = "outside left <b>bold font...</b> out right";
document.body.appendChild(div)
- 并不是所有元素都支持 innerHTML 屬性。不支持 innerHTML 的元素有: <col>、 <colgroup>、<frameset>、 <head>、 <html>、 <style>、 <table>、 <tbody>、 <thead>、 <tfoot>和<tr>。
- 2. outerHTML 屬性
- 在讀模式下, outerHTML 返回調(diào)用它的元素及所有子節(jié)點(diǎn)的 HTML 標(biāo)簽。在寫(xiě)模式下, outerHTML會(huì)根據(jù)指定的 HTML 字符串創(chuàng)建新的 DOM 子樹(shù),然后用這個(gè) DOM 子樹(shù)完全替換調(diào)用元素。
- 在子節(jié)點(diǎn)的內(nèi)容被替換后,被替換的元素節(jié)點(diǎn)的屬性,事件處理等還會(huì)留在屬性里,所以需要先刪除屬性和的事件,在做替換;
<div id="content">
<p>in div paragraph..</p>
</div>
<script>
div = document.getElementById("content");
div.outerHTML = "<p>It's replace content <strong>paragraph111</strong></p>";
// It's replace content paragraph111
</script>

3. insertAdjacentHTML()方法
-
插入標(biāo)記的最后一個(gè)新增方式是 insertAdjacentHTML()方法。這個(gè)方法最早也是在 IE中出現(xiàn)的,它接收兩個(gè)參數(shù):插入位置和要插入的 HTML 文本。第一個(gè)參數(shù)必須是下列值之一:
- "beforebegin",在當(dāng)前元素之前插入一個(gè)緊鄰的同輩元素;
- "afterbegin",在當(dāng)前元素之下插入一個(gè)新的子元素或在第一個(gè)子元素之前再插入新的子元素;
- "beforeend",在當(dāng)前元素之下插入一個(gè)新的子元素或在最后一個(gè)子元素之后再插入新的子元素;
- "afterend",在當(dāng)前元素之后插入一個(gè)緊鄰的同輩元素
//作為前一個(gè)同輩元素插入
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");
//作為第一個(gè)子元素插入
element.insertAdjacentHTML("afterbegin", "<p>Hello world!</p>");
//作為最后一個(gè)子元素插入
element.insertAdjacentHTML("beforeend", "<p>Hello world!</p>");
//作為后一個(gè)同輩元素插入
element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
-
4. 內(nèi)存與性能問(wèn)題
- 在子節(jié)點(diǎn)的內(nèi)容被替換后,被替換的元素節(jié)點(diǎn)的屬性,事件處理等還會(huì)留在屬性里,所以需要先刪除屬性和的事件,在做替換;
- 如果在一個(gè)循環(huán)體里多次調(diào)用innerHTML、outerHtml會(huì)影響性能,最好把return的內(nèi)容先賦給一個(gè)變量,讓后在調(diào)用innerHTML。
11.4 專(zhuān)有擴(kuò)展
- 11.4.1 文檔模式
- doctype 最好使用標(biāo)準(zhǔn)模式 <!DOCTYPE html>
- 11.4.2 children屬性
- children屬性是 HTMLCollection 的實(shí)例,和childNodes一樣返回子節(jié)點(diǎn),但是不返回textNode等其他節(jié)點(diǎn),只返回子元素節(jié)點(diǎn);
- 11.4.3 contains()方法 & compareDocumentPosition()方法
- 返回元素節(jié)點(diǎn)是否被包含;
- alert(htmlNode.contains(bodyNode)); // true
- 返回alert(bodyNode.contains(htmlNode)); // false
compareDocumentPosition()方法
- 后面的給定元素的相對(duì)參考元素(前面的調(diào)用元素)位置,并返回位置掩碼;
<div id="mydiv">
<ul>
<p id="myp"><span id="myspan">spanaaa</span></p>
<li>line 1</li>
<li>line 2</li>
<li>line 3</li>
</ul>
</div>
<script>
mydiv = document.getElementById("mydiv");
myspan = document.getElementById("myspan");
// 包含8 + 居前2 = 10
document.write(myspan.compareDocumentPosition(mydiv))
// 被包含16 + 居后4 = 20
document.write(mydiv.compareDocumentPosition(myspan))
</script>
- 11.4.4 插入文本
-
- innerText 屬性
- 設(shè)置 innerText 永遠(yuǎn)只會(huì)生成當(dāng)前節(jié)點(diǎn)的一個(gè)子文本節(jié)點(diǎn),而為了確保只生成一個(gè)子文本節(jié)點(diǎn),
就必須要對(duì)文本進(jìn)行 HTML 編碼。利用這一點(diǎn),可以通過(guò) innerText 屬性過(guò)濾掉 HTML 標(biāo)簽。方法是
將 innerText 設(shè)置為等于 innerText,這樣就可以去掉所有 HTML 標(biāo)簽,比如:
div.innerText = div.innerText;
-
- outerText 屬性
- 與innerText 屬性作用相同,只是替換會(huì)替換整個(gè)元素;
-
第12 章 DOM2 和DOM3
- OM1 級(jí)主要定義的是 HTML 和 XML 文檔的底層結(jié)構(gòu)。 DOM2 和 DOM3 級(jí)則在這個(gè)結(jié)構(gòu)
的基礎(chǔ)上引入了更多的交互能力,也支持了更高級(jí)的 XML 特性。為此, DOM2 和 DOM3
級(jí)分為許多模塊(模塊之間具有某種關(guān)聯(lián)),分別描述了 DOM 的某個(gè)非常具體的子集。這些模塊
如下。 - DOM2 級(jí)核心(DOM Level 2 Core):在 1 級(jí)核心基礎(chǔ)上構(gòu)建,為節(jié)點(diǎn)添加了更多方法和屬性。
- DOM2 級(jí)視圖(DOM Level 2 Views):為文檔定義了基于樣式信息的不同視圖。
- DOM2 級(jí)事件(DOM Level 2 Events):說(shuō)明了如何使用事件與 DOM 文檔交互。
- DOM2 級(jí)樣式(DOM Level 2 Style):定義了如何以編程方式來(lái)訪問(wèn)和改變 CSS 樣式信息。
- DOM2 級(jí)遍歷和范圍(DOM Level 2 Traversal and Range):引入了遍歷 DOM 文檔和選擇其特定
部分的新接口。 - DOM2 級(jí) HTML(DOM Level 2 HTML):在 1 級(jí) HTML 基礎(chǔ)上構(gòu)建,添加了更多屬性、方法和
新接口。
DOM 變化
- 可以通過(guò)下列代碼來(lái)確定瀏覽器是否支持這些 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");
12.2 樣式
- 確定瀏覽器是否支持 DOM3 級(jí)定義的 CSS3 能力
alert(document.implementation.hasFeature("CSS3.0", "3.0")); // true
- 12.2.1 訪問(wèn)元素的樣式
- 通過(guò)元素的style屬性來(lái)操作樣式;
//設(shè)置背景顏色
myDiv.style.backgroundColor = "red";
- 對(duì)于使用短劃線(分隔不同的詞匯,例如 background-image)的 CSS 屬性名,必須將其轉(zhuǎn)換成駝峰大小寫(xiě)形式,才能通過(guò) JavaScript 來(lái)訪問(wèn);例如:()background-image > style.backgroundImage)
- 在標(biāo)準(zhǔn)模式下,所有度量值都必須指定一個(gè)度量單位。
myDiv.style.width = "100px";
myDiv.style.height = "200px";
- 1. DOM 樣式屬性和方法
// cssText:get or set element of style;
mydiv.style.cssText = "width: 25px; height: 100px; background-color: green";
alert(mydiv.style.cssText);
// parentRule: The following JavaScript code gets the parent CSS style rule from a CSSStyleDeclaration:
var declaration = document.styleSheets[0].cssRules[0].style;
var rule = declaration.parentRule;
// getPropertyPriority :檢查rule的給定的property是否設(shè)置了!important,如果是就返回"important"
var declaration1 = document.styleSheets[0].cssRules[0].style;
var isImportant = declaration1.getPropertyPriority('margin') === 'important';
// style.getPropertyValue: 返回css屬性的值
// The following JavaScript code queries the value of the margin property in a CSS selector rule:
var declaration2 = document.styleSheets[0].cssRules[0].style;
var value = declaration2.getPropertyValue('margin'); // "1px 2px"
// style.removeProperty: 刪除css屬性
var declaration3 = document.styleSheets[0].cssRules[0].style;
var oldValue = declaration3.removeProperty('background-color');
// style.setProperty: 添加css屬性
var declaration = document.styleSheets[0].cssRules[0].style;
declaration.setProperty('border-width', '1px 2px');
// Equivalent to:
// declaration.borderWidth = '1px 2px';
2. 計(jì)算的樣式
- document.defaultView.getComputedStyle(element, null)
- 所有計(jì)算的樣式都是只讀的;不能修改計(jì)算后樣式對(duì)象中的 CSS 屬性。此外,計(jì)算后的樣式也包含屬于瀏覽器內(nèi)部樣式表的樣式信息,因此任何具有默認(rèn)值的 CSS 屬性都會(huì)表現(xiàn)在計(jì)算后的樣式中。
- 返回一個(gè)CSSStyleDeclaration 對(duì)象(與 style 屬性的類(lèi)型相同),其中包含當(dāng)前元素的所有計(jì)算的樣式,可以通過(guò)這個(gè)對(duì)象get到element計(jì)算后的最終樣式;
<style>
#myp {
border:1px solid red;
color: #ff00d8;
font-size:30px;
}
#mydiv {
background-color: pink;
}
</style>
</head>
<body>
<div id="mydiv">
<p id="myp" style="color:purple;font-size:30px;background-color: dodgerblue;">in div paragraph..</p>
</div>
<script>
function notinarray(obj, arr) {
var i = arr.length;
while (i--) {
if (arr[i] === obj) {
return false;
}
}
return true;
}
myp = document.getElementById("myp");
// return CSSStyleDeclaration對(duì)象 of this element
computedStyle = window.getComputedStyle(myp, null);
// // 找到跟element對(duì)應(yīng)的那條規(guī)則的cssText; cssRulesText = 內(nèi)嵌cssRule + inline cssRule
var cssRulesText = (document.styleSheets[0].cssRules[0].style.cssText) + " " + myp.style.cssText;
// 正則得到css屬性名;
var patt=new RegExp(/([a-z-]+):/g);
// css屬性去重;
dictre = [];
while (true){
var re = patt.exec(cssRulesText);
if (re==null){break}
if (notinarray(re[1], dictre)){
dictre.push(re[1])
}
}
// 打印this element的 css屬性computed值
for (let i=0, len=dictre.length; i<len; i++){
let attr = dictre[i];
document.write(attr, " : ", computedStyle[attr], "<br> ")
}
// border : 1px solid rgb(255, 0, 0) // 只有chrome會(huì)顯示border屬性的值
// color : rgb(128, 0, 128)
// font-size : 30px
// background-color : rgb(30, 144, 255)
12.2.2 操作樣式表
-
CSSStyleSheet 繼承自 StyleSheet,后者可以作為一個(gè)基礎(chǔ)接口來(lái)定義非 CSS 樣式表。從StyleSheet 接口繼承而來(lái)的屬性如下。
- disabled:表示樣式表是否被禁用的布爾值。這個(gè)屬性是可讀/寫(xiě)的,將這個(gè)值設(shè)置為 true 可以禁用樣式表。
- href:如果樣式表是通過(guò)<link>包含的,則是樣式表的 URL;否則,是 null。
- media:當(dāng)前樣式表支持的所有媒體類(lèi)型的集合。與所有 DOM 集合一樣,這個(gè)集合也有一個(gè)length 屬性和一個(gè) item()方法。也可以使用方括號(hào)語(yǔ)法取得集合中特定的項(xiàng)。如果集合是空列表,表示樣式表適用于所有媒體。在 IE 中, media 是一個(gè)反映<link>和<style>元素 media特性值的字符串。
- ownerNode:指向擁有當(dāng)前樣式表的節(jié)點(diǎn)的指針,樣式表可能是在 HTML 中通過(guò)<link>或<style/>引入的(在 XML 中可能是通過(guò)處理指令引入的)。如果當(dāng)前樣式表是其他樣式表通過(guò)@import 導(dǎo)入的,則這個(gè)屬性值為 null。 IE 不支持這個(gè)屬性。
- parentStyleSheet:在當(dāng)前樣式表是通過(guò)@import 導(dǎo)入的情況下,這個(gè)屬性是一個(gè)指向?qū)胨臉邮奖淼闹羔槨?/li>
- title: ownerNode 中 title 屬性的值。
- type:表示樣式表類(lèi)型的字符串。對(duì) CSS 樣式表而言,這個(gè)字符串是"type/css"。除 了 disabled 屬 性 之 外 , 其 他 屬 性 都 是 只 讀 的 。 在 支 持 以 上 所 有 這 些 屬 性 的 基 礎(chǔ) 上 ,CSSStyleSheet 類(lèi)型還支持下列屬性和方法:
- cssRules:樣式表中包含的樣式規(guī)則的集合。 IE 不支持這個(gè)屬性,但有一個(gè)類(lèi)似的 rules 屬性。
- ownerRule:如果樣式表是通過(guò)@import 導(dǎo)入的,這個(gè)屬性就是一個(gè)指針,指向表示導(dǎo)入的規(guī)則;否則,值為 null。 IE 不支持這個(gè)屬性。
- deleteRule(index):刪除 cssRules 集合中指定位置的規(guī)則。 IE 不支持這個(gè)方法,但支持一個(gè)類(lèi)似的 removeRule()方法。
- insertRule(rule,index):向 cssRules 集合中指定的位置插入 rule 字符串。 IE 不支持這
個(gè)方法,但支持一個(gè)類(lèi)似的 addRule()方法。
- 應(yīng)用于文檔的所有樣式表是通過(guò) document.styleSheets 集合來(lái)表示的。通過(guò)這個(gè)集合的 length屬性可以獲知文檔中樣式表的數(shù)量,而通過(guò)方括號(hào)語(yǔ)法或 item()方法可以訪問(wèn)每一個(gè)樣式表。
也可以直接通過(guò)<link>或<style>元素取得 CSSStyleSheet 對(duì)象。 DOM 規(guī)定了一個(gè)包含CSSStyleSheet 對(duì)象的屬性,名叫 sheet;除了 IE,其他瀏覽器都支持這個(gè)屬性。 IE 支持的是styleSheet 屬性。要想在不同瀏覽器中都能取得樣式表對(duì)象,可以使用下列代碼。
function getStyleSheet(element){
return element.sheet || element.styleSheet;
}
//取得第一個(gè)<link/>元素引入的樣式表
var link = document.getElementsByTagName("link")[0];
// 這里的 getStyleSheet()返回的樣式表對(duì)象與 document.styleSheets 集合中的樣式表對(duì)象相同。
var sheet = getStylesheet(link);
1. CSS 規(guī)則
CSSRule 對(duì)象表示樣式表中的每一條規(guī)則。實(shí)際上, CSSRule 是一個(gè)供其他多種類(lèi)型繼承的基類(lèi)型,其中最常見(jiàn)的就是 CSSStyleRule 類(lèi)型,表示樣式信息(其他規(guī)則還有@import、 @font-face、@page 和@charset,但這些規(guī)則很少有必要通過(guò)腳本來(lái)訪問(wèn))。 CSSStyleRule 對(duì)象包含下列屬性。
- cssText:返回整條規(guī)則對(duì)應(yīng)的文本。由于瀏覽器對(duì)樣式表的內(nèi)部處理方式不同,返回的文本可能會(huì)與樣式表中實(shí)際的文本不一樣; Safari 始終都會(huì)將文本轉(zhuǎn)換成全部小寫(xiě)。 IE 不支持這個(gè)屬性。
- parentRule:如果當(dāng)前規(guī)則是導(dǎo)入的規(guī)則,這個(gè)屬性引用的就是導(dǎo)入規(guī)則;否則,這個(gè)值為null。 IE 不支持這個(gè)屬性。
- parentStyleSheet:當(dāng)前規(guī)則所屬的樣式表。 IE 不支持這個(gè)屬性。
- selectorText:返回當(dāng)前規(guī)則的選擇符文本。由于瀏覽器對(duì)樣式表的內(nèi)部處理方式不同,返回的文本可能會(huì)與樣式表中實(shí)際的文本不一樣(例如, Safari 3 之前的版本始終會(huì)將文本轉(zhuǎn)換成全部小寫(xiě)) 。在 Firefox、 Safari、 Chrome 和 IE 中這個(gè)屬性是只讀的。 Opera 允許修改 selectorText。
- style:一個(gè) CSSStyleDeclaration 對(duì)象,可以通過(guò)它設(shè)置和取得規(guī)則中特定的樣式值。
- type:表示規(guī)則類(lèi)型的常量值。對(duì)于樣式規(guī)則,這個(gè)值是 1。 IE 不支持這個(gè)屬性。
其中三個(gè)最常用的屬性是 cssText、 selectorText 和 style。 cssText 屬性與 style.cssText屬性類(lèi)似,但并不相同。前者包含選擇符文本和圍繞樣式信息的花括號(hào),后者只包含樣式信息(類(lèi)似于元素的 style.cssText)。此外, cssText 是只讀的,而 style.cssText 也可以被重寫(xiě)。
大多數(shù)情況下,僅使用 style 屬性就可以滿足所有操作樣式規(guī)則的需求了。這個(gè)對(duì)象就像每個(gè)元素上的 style 屬性一樣,可以通過(guò)它讀取和修改規(guī)則中的樣式信息。
// 假設(shè)這條規(guī)則位于頁(yè)面中的第一個(gè)樣式表中,而且這個(gè)樣式表中只有這一條樣式規(guī)則
div.box {
background-color: blue;
width: 100px;
height: 200px;
}
var sheet = document.styleSheets[0];
var rules = sheet.cssRules || sheet.rules; //取得規(guī)則列表
var rule = rules[0]; //取得第一條規(guī)則
alert(rule.selectorText); //"div.box"
alert(rule.style.cssText); //完整的 CSS 代碼
alert(rule.style.backgroundColor); //"blue"
alert(rule.style.width); //"100px"
alert(rule.style.height); //"200px"
- 使用這種方式,可以像確定元素的行內(nèi)樣式信息一樣,確定與規(guī)則相關(guān)的樣式信息。與使用元素的方式一樣,在這種方式下也可以修改樣式信息。
var sheet = document.styleSheets[0];
var rules = sheet.cssRules || sheet.rules; //取得規(guī)則列表
var rule = rules[0]; //取得第一條規(guī)則
rule.style.backgroundColor = "red"
//以這種方式修改規(guī)則會(huì)影響頁(yè)面中適用于該規(guī)則的所有元素。
//如果有兩個(gè)帶有 box 類(lèi)的<div>元素, 這兩個(gè)元素都會(huì)應(yīng)用修改后的樣式。
2. 創(chuàng)建規(guī)則
function insertRule(sheet, selectorText, cssText, position){
if (sheet.insertRule){
sheet.insertRule(selectorText + "{" + cssText + "}", position);
} else if (sheet.addRule){
sheet.addRule(selectorText, cssText, position);
}
}
//下面是調(diào)用這個(gè)函數(shù)的示例代碼。
insertRule(document.styleSheets[0], "body", "background-color: silver", 0);
3. 刪除規(guī)則
var sheet = document.styleSheets[0];
function deleteRule(sheet, index){
if (sheet.deleteRule){ // 除IE以外的瀏覽器的方法
sheet.deleteRule(index);
} else if (sheet.removeRule){ // IE瀏覽器的方法
sheet.removeRule(index);
}
}
- 12.2.3 元素大小
1. 偏移量
- 包括元素在屏幕上占用的所有可見(jiàn)的空間。
- offsetHeight:元素在垂直方向上占用的空間大小,以像素計(jì)。包括元素的高度、(可見(jiàn)的)水平滾動(dòng)條的高度、上邊框高度和下邊框高度。
- offsetWidth:元素在水平方向上占用的空間大小,以像素計(jì)。包括元素的寬度、(可見(jiàn)的)垂直滾動(dòng)條的寬度、左邊框?qū)挾群陀疫吙驅(qū)挾取?/li>
- offsetLeft:元素的左外邊框至包含元素的左內(nèi)邊框之間的像素距離。
- offsetTop:元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離。
- offsetLeft 和 offsetTop 屬性與包含元素有關(guān),包含元素的引用保存在 offsetParent屬性中。
- 要想知道某個(gè)元素在頁(yè)面上的偏移量,將這個(gè)元素的 offsetLeft 和 offsetTop 與其 offsetParent的相同屬性相加,如此循環(huán)直至根元素,就可以得到一個(gè)基本準(zhǔn)確的值。
// 以下獲取x軸上的偏移量
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while (current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
// 以下獲取y軸上的偏移量
function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while (current !== null){
actualTop += current. offsetTop;
current = current.offsetParent;
}
return actualTop;
}
- 這兩個(gè)函數(shù)利用 offsetParent 屬性在 DOM 層次中逐級(jí)向上回溯,將每個(gè)層次中的偏移量屬性合計(jì)到一塊。
-
對(duì)于簡(jiǎn)單的 CSS 布局的頁(yè)面,這兩函數(shù)可以得到非常精確的結(jié)果。對(duì)于使用表格和內(nèi)嵌框架布局的頁(yè)面,由于不同瀏覽器實(shí)現(xiàn)這些元素的方式不同,因此得到的值就不太精確了。
圖片.png
2. 客戶區(qū)大小
元素內(nèi)容及其內(nèi)邊距所占據(jù)的空間大??;
-
clientWidth
- 元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度;
-
clientHeight
-
屬性是元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度;
客戶區(qū)大小
-
客戶區(qū)大小就是元素內(nèi)部的空間大小,因此滾動(dòng)條占用的空間不計(jì)算在內(nèi)。
最常用到這些屬性的情況,就是確定瀏覽器視口大小的時(shí)候。
function getViewport(){
if (document.compatMode == "BackCompat"){ //混雜模式用這個(gè)
return {
width: document.body.clientWidth,
height: document.body.clientHeight
};
} else {
return {
width: document.documentElement.clientWidth, //標(biāo)準(zhǔn)模式用這個(gè)
height: document.documentElement.clientHeight
};
}
}
//這個(gè)函數(shù)會(huì)返回一個(gè)對(duì)象,包含兩個(gè)屬性: width和 height;
//表示瀏覽器視口(<html>或<body>元素)的大小。
3. 滾動(dòng)大小
- scrollHeight:在沒(méi)有滾動(dòng)條的情況下,元素內(nèi)容的總高度。
- scrollWidth:在沒(méi)有滾動(dòng)條的情況下,元素內(nèi)容的總寬度。
- scrollLeft:被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)。通過(guò)設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置。
- scrollTop:被隱藏在內(nèi)容區(qū)域上方的像素?cái)?shù)。通過(guò)設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置。
- 帶有垂直滾動(dòng)條的頁(yè)面總高度就是 document.documentElement.scrollHeight;
-
對(duì)于不包含滾動(dòng)條的頁(yè)面而言,scrollWidth 和 clientWidth相等, scrollHeight 和 clientHeight 相等;
滾動(dòng)大小 - 通過(guò) scrollLeft 和 scrollTop 屬性確定元素當(dāng)前滾動(dòng)的狀態(tài)
- 在元素尚未被滾動(dòng)時(shí),這兩個(gè)屬性的值都等于 0。
- 如果元素被垂直滾動(dòng)了,那么 scrollTop 的值會(huì)大于 0,且表示元素上方不可見(jiàn)內(nèi)容的像素高度。
- 如果元素被水平滾動(dòng)了,那么 scrollLeft 的值會(huì)大于 0,且表示元素左側(cè)不可見(jiàn)內(nèi)容的像素寬度。
- 通過(guò) scrollLeft 和 scrollTop 屬性設(shè)置元素的滾動(dòng)位置。
- 因此將元素的scrollLeft 和 scrollTop 設(shè)置為 0,就可以重置元素的滾動(dòng)位置。
//檢測(cè)元素是否位于頂部,如果不是就將其回滾到頂部。
function scrollToTop(element){
if (element.scrollTop != 0){
element.scrollTop = 0;
}
}
4. 確定元素大小
-
viewport(視口)
- 等于瀏覽器窗口,擁有瀏覽器窗口的寬度和高度,<html>元素使用viewport寬度的100%(在未手動(dòng)設(shè)置html元素寬度情況下)。用document.documentElement.clientWidth獲取viewport的寬度。
document.write(div.clientWidth,"<br>")
document.write(div.clientHeight,"<br>")
-
元素大小
用element.offsetWidth 和 element.offsetHeight 獲取元素大小,元素大小包括
document.write("element", div.offsetWidth,"<br>")
document.write("element", div.offsetHeight,"<br>")
元素大小 page343
1. 偏移量
offsetWidth - 返回元素寬,元素寬包括內(nèi)容區(qū) + 左右內(nèi)邊距 + 左右邊框;
offsetHeight - 返回元素高,元素寬包括內(nèi)容區(qū) +上下內(nèi)邊距 + 上下邊框;
offsetLeft - 表示該元素的border左外邊緣與已定位的父容器(offsetParent對(duì)象)左padding外邊緣的距離(不包括父元素border);
offsetTop - 表示該元素的border上外邊緣與已定位的父容器(offsetParent對(duì)象)上padding外邊緣的距離(不包括父元素border);
2. Client 客戶區(qū)大小
clientWidth - 元素內(nèi)容寬+內(nèi)邊距 大小,不包括邊框(IE下實(shí)際包括)、外邊距、滾動(dòng)條部分;
clientHeight - 元素內(nèi)容高+內(nèi)邊距 大小,不包括邊框(IE下實(shí)際包括)、外邊距、滾動(dòng)條部分;
clientLeft - 返回內(nèi)邊距的邊緣和邊框的外邊緣之間的水平距離,也就是左邊框?qū)挾龋?/p>
clientTop - 返回內(nèi)邊距的邊緣和邊框的外邊緣之間的垂直距離,也就是上邊框?qū)挾龋?/p>
3. 滾動(dòng)大小
scrollWidth - 是只讀屬性,是元素內(nèi)容寬度(左padding外邊緣 - 右padding外邊緣,不包括滾動(dòng)條),包括溢出而在屏幕上不可見(jiàn)的內(nèi)容。
scrollHeight - 是只讀屬性,是元素內(nèi)容高度(上padding外邊緣 - 下padding外邊緣,不包括滾動(dòng)條),包括溢出而在屏幕上不可見(jiàn)的內(nèi)容。
scrollLeft - 可以獲取 or 設(shè)置一個(gè)元素的內(nèi)容水平滾動(dòng)的像素?cái)?shù)(左邊被隱藏內(nèi)容的寬度的px值);
scrollTop - 可以獲取 or 設(shè)置一個(gè)元素的內(nèi)容垂直滾動(dòng)的像素?cái)?shù)(頂部被隱藏內(nèi)容的高度的px值);
比如元素的scrollHeight是1015,clientHeight是303,那么scrollTop就是712;
4. 確定元素大小
每個(gè)元素都提供了一個(gè) getBoundingClientRect()方法。這個(gè)方法返回會(huì)一個(gè)矩形對(duì)象,包含 6 個(gè)屬性: left、 top、 right 和 bottom。還有width和height。這些屬性給出了元素在頁(yè)面中相對(duì)于視口(瀏覽器的視口就是body元素或者h(yuǎn)tml元素的左上角)的位置。
getBoundingClientRect()的width屬性 == offsetWidth的值;
getBoundingClientRect()的Height屬性 == offsetHeight的值;
12.3 遍歷
-
12.3.1 NodeIterator
- 可以使用 document.createNodeIterator()方
法創(chuàng)建它的新實(shí)例。接受4個(gè)參數(shù):- 1.root:想要作為搜索起點(diǎn)的樹(shù)中的節(jié)點(diǎn)。
- 2.whatToShow:表示要訪問(wèn)哪些節(jié)點(diǎn)的數(shù)字代碼。
- NodeFilter.SHOW_ALL:顯示所有類(lèi)型的節(jié)點(diǎn)。
- NodeFilter.SHOW_ELEMENT:顯示元素節(jié)點(diǎn)。
- NodeFilter.SHOW_ATTRIBUTE:顯示特性節(jié)點(diǎn)。由于 DOM 結(jié)構(gòu)原因,實(shí)際上不能使用這個(gè)值。
- NodeFilter.SHOW_TEXT:顯示文本節(jié)點(diǎn)。
- NodeFilter.SHOW_CDATA_SECTION:顯示 CDATA 節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- NodeFilter.SHOW_ENTITY_REFERENCE:顯示實(shí)體引用節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- NodeFilter.SHOW_ENTITYE:顯示實(shí)體節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- NodeFilter.SHOW_PROCESSING_INSTRUCTION:顯示處理指令節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- NodeFilter.SHOW_COMMENT:顯示注釋節(jié)點(diǎn)。
- NodeFilter.SHOW_DOCUMENT:顯示文檔節(jié)點(diǎn)。
- NodeFilter.SHOW_DOCUMENT_TYPE:顯示文檔類(lèi)型節(jié)點(diǎn)。
- NodeFilter.SHOW_DOCUMENT_FRAGMENT:顯示文檔片段節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- NodeFilter.SHOW_NOTATION:顯示符號(hào)節(jié)點(diǎn)。對(duì) HTML 頁(yè)面沒(méi)有用。
- 3.filter:是一個(gè) NodeFilter 對(duì)象,或者一個(gè)表示應(yīng)該接受還是拒絕某種特定節(jié)點(diǎn)的函數(shù)。
- 每個(gè) NodeFilter 對(duì)象只有一個(gè)方法,即 acceptNode();如果應(yīng)該訪問(wèn)給定的節(jié)點(diǎn),該方法返回 NodeFilter.FILTER_ACCEPT,如果不應(yīng)該訪問(wèn)給定的節(jié)點(diǎn),該方法返回 NodeFilter.FILTER_SKIP。由于 NodeFilter 是一個(gè)抽象的類(lèi)型,因此不能直接創(chuàng)建它的實(shí)例。在必要時(shí),只要?jiǎng)?chuàng)建一個(gè)包含 acceptNode()方法的對(duì)象,然后將這個(gè)對(duì)象傳入createNodeIterator()中即可。
- 可以使用 document.createNodeIterator()方
// 創(chuàng)建一個(gè)只顯示<p>元素的節(jié)點(diǎn)迭代器。
var filter = {
acceptNode: function(node){
return node.tagName.toLowerCase() == "p" ?
NodeFilter.FILTER_ACCEPT :
NodeFilter.FILTER_SKIP;
}
};
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
filter, false);
// 也可以是一個(gè)與 acceptNode()方法類(lèi)似的函數(shù)
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);
4.entityReferenceExpansion:布爾值,表示是否要擴(kuò)展實(shí)體引用。這個(gè)參數(shù)在 HTML 頁(yè)面中沒(méi)有用,因?yàn)槠渲械膶?shí)體引用不能擴(kuò)展。
-
NodeIterator 方法
- nextNode() - 向前前進(jìn)一步
- previousNode() - 向后后退一步
<div id="div1">
<p><b>Hello</b> world!</p>
<ul>
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
</ul>
</div>
// 遍歷<div>元素中的所有元素
<script>
var div = document.getElementById("div1");
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, null, false);
var node = iterator.nextNode();
while (node !== null) {
alert(node.tagName); //輸出標(biāo)簽名
node = iterator.nextNode();
}
// 只想返回遍歷中遇到的<li>元素, 把下面的過(guò)濾器傳入第三個(gè)參數(shù)即可;
var filter = function(node){
return node.tagName.toLowerCase() == "li" ?
NodeFilter.FILTER_ACCEPT :
NodeFilter.FILTER_SKIP;
};
</script>
-
12.3.2 TreeWalker
- TreeWalker 是 NodeIterator 的一個(gè)更高級(jí)的版本。除了包括 nextNode()和 previousNode()在內(nèi)的相同的功能之外,這個(gè)類(lèi)型還提供了下列用于在不同方向上遍歷 DOM 結(jié)構(gòu)的方法。
- 方法
- parentNode():遍歷到當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn);
- firstChild():遍歷到當(dāng)前節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn);
- lastChild():遍歷到當(dāng)前節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn);
- nextSibling():遍歷到當(dāng)前節(jié)點(diǎn)的下一個(gè)同輩節(jié)點(diǎn);
- previousSibling():遍歷到當(dāng)前節(jié)點(diǎn)的上一個(gè)同輩節(jié)點(diǎn)。
//可以用 TreeWalker來(lái)代替 NodeIterator
var div = document.getElementById("div1");
var filter = function(node){
return node.tagName.toLowerCase() == "li"?
NodeFilter.FILTER_ACCEPT :
NodeFilter.FILTER_SKIP;
};
var walker= document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT,
filter, false);
var node = iterator.nextNode();
while (node !== null) {
alert(node.tagName); //輸出標(biāo)簽名
node = iterator.nextNode();
}
- filter 可以返回的值有所不同。除了 NodeFilter.FILTER_ACCEPT 和 NodeFilter.FILTER_SKIP 之外,還可以使用 NodeFilter.FILTER_REJECT, 會(huì)跳過(guò)相應(yīng)節(jié)點(diǎn)及該節(jié)點(diǎn)的整個(gè)子樹(shù)。例如,將前面例子中的
NodeFilter.FILTER_SKIP 修改成 NodeFilter.FILTER_REJECT,結(jié)果就是不會(huì)訪問(wèn)任何節(jié)點(diǎn)。這是因?yàn)榈谝粋€(gè)返回的節(jié)點(diǎn)是<div>,它的標(biāo)簽名不是"li",于是就會(huì)返回 NodeFilter.FILTER_REJECT,這意味著遍歷會(huì)跳過(guò)整個(gè)子樹(shù)。在這個(gè)例子中, <div>元素是遍歷的根節(jié)點(diǎn),于是結(jié)果就會(huì)停止遍歷。 - TreeWalker 真正強(qiáng)大的地方在于能夠在 DOM 結(jié)構(gòu)中沿任何方向移動(dòng)。使用 TreeWalker遍歷 DOM 樹(shù),即使不定義過(guò)濾器,也可以取得所有<li>元素。
var div = document.getElementById("div1");
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
walker.firstChild(); //轉(zhuǎn)到<p>
walker.nextSibling(); //轉(zhuǎn)到<ul>
var node = walker.firstChild(); //轉(zhuǎn)到第一個(gè)<li>
while (node !== null) {
alert(node.tagName);
node = walker.nextSibling();
}
- TreeWalker 類(lèi)型還有一個(gè)屬性:currentNode
- 表示任何遍歷方法在上一次遍歷中返回的節(jié)點(diǎn)。通過(guò)設(shè)置這個(gè)屬性也可以修改遍歷繼續(xù)進(jìn)行的起點(diǎn)。
var node = walker.nextNode();
alert(node === walker.currentNode); //true
walker.currentNode = document.body; //修改起點(diǎn)
12.4 范圍
-
12.4.1 DOM中的范圍
- document.createRange()來(lái)創(chuàng)建 DOM 范圍
- startContainer:range起始節(jié)點(diǎn)的父節(jié)點(diǎn)(即選區(qū)中第一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn))。
- startOffset:范圍中選中第一個(gè)節(jié)點(diǎn)在其父節(jié)點(diǎn)的 childNodes 集合中的索引。
- endContainer:range最終節(jié)點(diǎn)的父節(jié)點(diǎn)(即選區(qū)中最后一個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn))。
- endOffset:范圍中最后一個(gè)子節(jié)點(diǎn)(終點(diǎn))在其父節(jié)點(diǎn)的 childNodes 集合中的索引。如果selectNode 選擇的只有一個(gè)節(jié)點(diǎn),那么endOffset會(huì)返回startOffset的值+1
- commonAncestorContainer: startContainer 和 endContainer 共同的祖先節(jié)點(diǎn)在文檔樹(shù)中位置最深的那個(gè)(也就是離startContainer 和 endContainer 最近的共同祖先節(jié)點(diǎn) )。
-
1. 用 DOM 范圍實(shí)現(xiàn)簡(jiǎn)單選擇
- selectNode() :選擇整個(gè)節(jié)點(diǎn),包括其子節(jié)點(diǎn);
- selectNodeContents(): 只選擇節(jié)點(diǎn)的子節(jié)點(diǎn)。
- <p>p content<b>bold font</b>p content</p>
<!DOCTYPE html>
<html>
<body>
<p id="p1"><b>Hello</b> world!</p>
</body>
</html>
<script>
var range1 = document.createRange(); // create range ins
range2 = document.createRange();
p1 = document.getElementById("p1");
range1.selectNode(p1); // select element p
range2.selectNodeContents(p1); // select element p 的content 不包括element p
</script>
- 其他方法
- setStartBefore(Node):將范圍的起點(diǎn)設(shè)置在 Node 之前,因此 Node 也就是范圍選區(qū)中的第一個(gè)子節(jié)點(diǎn)。
- setStartAfter(Node):將范圍的起點(diǎn)設(shè)置在 Node 之后,因此 Node 也就不在范圍之內(nèi)了,其下一個(gè)同輩節(jié)點(diǎn)才是范圍選區(qū)中的第一個(gè)子節(jié)點(diǎn)。
- setEndBefore(Node):將范圍的終點(diǎn)設(shè)置在 Node 之前,因此 Node 也就不在范圍之內(nèi)了,其上一個(gè)同輩節(jié)點(diǎn)才是范圍選區(qū)中的最后一個(gè)子節(jié)點(diǎn)。
- setEndAfter(Node):將范圍的終點(diǎn)設(shè)置在 Node 之后,因此 Node 也就是范圍選區(qū)中的最后一個(gè)子節(jié)點(diǎn)。
<div id="mydiv">
<ol id="myol">
<li>ol Coffee</li>
<li>ol Tea</li>
<li>ol Milk</li>
</ol>
<p>a paragraph line...</p>
<ul id="myul">
<li>ul Coffee</li>
<li>ul Tea</li>
<li>ul Milk</li>
</ul>
</div>
<script>
olNode = document.getElementById("myol");
ulNode = document.getElementById("myul");
var range1 = document.createRange(); //創(chuàng)建range
var range2 = document.createRange(); //創(chuàng)建range
range1.setStartBefore(olNode); // 把range的起點(diǎn)放在olNode前面(olNode是range中的第一個(gè)節(jié)點(diǎn))
range1.setEndAfter(ulNode); //把range的終點(diǎn)放在ulNode后面 (ulNode是range的最后一個(gè)節(jié)點(diǎn))
document.write(range1.endOffset, "<br>") // 6
</script>
-
2. 用 DOM 范圍實(shí)現(xiàn)復(fù)雜選擇
- setStart() 方法
- 根據(jù)參數(shù)選擇range第一個(gè)節(jié)點(diǎn), 參數(shù)一傳入start節(jié)點(diǎn)的父節(jié)點(diǎn)(startContainer), 參數(shù)二傳入start節(jié)點(diǎn)在父節(jié)點(diǎn)中的索引(startOffset)。
- setEnd() 方法
- 根據(jù)參數(shù)選擇range最后一個(gè)節(jié)點(diǎn), 參數(shù)一傳入end節(jié)點(diǎn)的父節(jié)點(diǎn)(endContainer), 參數(shù)二傳入end節(jié)點(diǎn)在父節(jié)點(diǎn)中的索引加1(endOffset)。
- setStart() 方法
<body>
ol Coffee ol Tea ol Milk a paragraph line... ul Coffee ul Tea ul Milk
<div id="mydiv">
<ol id="myol">
<li>ol Coffee</li>
<li>ol Tea</li>
<li>ol Milk</li>
</ol>
<p>a paragraph line...</p>
<ul id="myul">
<li>ul Coffee</li>
<li>ul Tea</li>
<li>ul Milk</li>
</ul>
</div>
<script>
// range定在ol到ul
divNode = document.getElementById("mydiv");
rangeIns = document.createRange();
rangeIns.setStart(divNode, 1);
//用父節(jié)點(diǎn)的childNodes的遍歷確定setEnd節(jié)點(diǎn)的偏移值(跟endOffset一樣是childnodes的length從1開(kāi)始計(jì)算的所以結(jié)果需要加1)
divChilds = divNode.childNodes;
for (i=0, len=divChilds.length; i<len; i++){
if (divChilds[i].nodeName.toLowerCase() == "ul"){
rangeIns.setEnd(divNode, i+1)
}
}
document.write(rangeIns)
</script>
3. 操作 DOM 范圍中的內(nèi)容
-
deleteContents()
- Range.deleteContents() 移除來(lái)自 Document的Range 內(nèi)容。
-
extractContents()
- Range.extractContents() 也會(huì)從文檔中移除范圍選區(qū)。但是會(huì)返回一個(gè)[object DocumentFragment] ,就是range中的范圍;
-
Range.cloneContents()
- 返回 clone 的 Range。 返回是[object DocumentFragment] ;
4.插入 DOM 范圍中的內(nèi)容
Range.insertNode(Node) 是在Range的起始位置插入節(jié)點(diǎn)。
該方法將把指定的節(jié)點(diǎn)(和它的所有子孫節(jié)點(diǎn))插入文檔范圍的開(kāi)始點(diǎn)。當(dāng)該方法返回時(shí),當(dāng)前范圍將包括新插入的節(jié)點(diǎn)。如果 newNode 已經(jīng)是文檔的一部分,那么它將被從當(dāng)前位置刪除,然后重新插入范圍的開(kāi)始點(diǎn)。如果 newNode 是 DocumentFragment 節(jié)點(diǎn),那么插入的不是它自身,而是它的子孫節(jié)點(diǎn),按順序插入范圍的開(kāi)始點(diǎn)。
如果包含當(dāng)前范圍的開(kāi)始點(diǎn)的節(jié)點(diǎn)是 Text 節(jié)點(diǎn),那么在發(fā)生插入操作前,它將被分割成兩個(gè)相鄰的節(jié)點(diǎn)。如果 newNode 是 Text 節(jié)點(diǎn),在插入文檔后,它不會(huì)與任何相鄰的 Text 節(jié)點(diǎn)合并。要合并相鄰的節(jié)點(diǎn),需要調(diào)用nodeObject.normalize()方法。
Range.surroundContents()方法將Range對(duì)象的內(nèi)容移動(dòng)到一個(gè)新的節(jié)點(diǎn)中, 并將這個(gè)新節(jié)點(diǎn)放回到range區(qū)域.如果選定的Range區(qū)域包含僅有一個(gè)節(jié)點(diǎn)標(biāo)簽的Text. 那標(biāo)簽將不會(huì)自動(dòng)成對(duì)生成,操作將失敗.
<div id="div1"><p id="p1"><b id="myb">Hello</b> world!</p></div>
<script>
var range1 = document.createRange();
range2 = document.createRange();
p1 = document.getElementById("myb");
range1.selectNode(p1.firstChild); //選中范圍是<b>標(biāo)簽
var span = document.createElement("span"); //創(chuàng)建新節(jié)點(diǎn)
span.style.backgroundColor = "yellow"; //給新節(jié)點(diǎn)添加樣式
// span.innerText = "i am span"; ////就算給新節(jié)點(diǎn)添加文本, 也會(huì)被覆蓋
// range1.insertNode(span)
range1.surroundContents(span); //1.提取范圍內(nèi)容;2.將新節(jié)點(diǎn)插入范圍的位置;3.把原來(lái)的范圍內(nèi)容插入新節(jié)點(diǎn)中;
- 5. 折疊 DOM 范圍
- Range.collapse(bool) 方法向邊界點(diǎn)折疊該 Range 。折疊后的 Range 為空,不包含節(jié)點(diǎn)內(nèi)容。
- 參數(shù) true 表示折疊到范圍的起點(diǎn),參數(shù) false 表示折疊到范圍的終點(diǎn)。
- 要確定 Range 是否已折疊,使用Range.collapsed 屬性。
range.collapse(true); //折疊到起點(diǎn)
alert(range.collapsed); //輸出 true
-
6. 比較 DOM 范圍
- Range.compareBoundaryPoints()
- compareBoundaryPoints() 方法比較兩個(gè)范圍的位置。
- compareBoundaryPoints(how,sourceRange)
- how:聲明如何執(zhí)行比較操作(即比較哪些邊界點(diǎn))。它的合法值是 Range 接口定義的常量。
- sourceRange 要與當(dāng)前范圍進(jìn)行比較的范圍。
- 如果當(dāng)前范圍的指定邊界點(diǎn)位于 sourceRange 指定的邊界點(diǎn)之前,則返回 -1。如果指定的兩個(gè)邊界點(diǎn)相同,則返回 0。如果當(dāng)前范圍的邊界點(diǎn)位于 sourceRange 指定的邊界點(diǎn)之后,則返回 1。
描述 - 該方法將比較當(dāng)前范圍的邊界點(diǎn)和指定的 sourceRange 的邊界點(diǎn),并返回一個(gè)值,聲明它們?cè)谠次臋n中的相對(duì)位置。參數(shù) how 指定了比較兩個(gè)范圍的哪個(gè)邊界點(diǎn)。該參數(shù)的合法值和它們的含義如下:
- Range.START_TO_START - 比較兩個(gè) Range 節(jié)點(diǎn)的開(kāi)始點(diǎn)
- Range.END_TO_END - 比較兩個(gè) Range 節(jié)點(diǎn)的結(jié)束點(diǎn)
- Range.START_TO_END - 用 sourceRange 的開(kāi)始點(diǎn)與當(dāng)前范圍的結(jié)束點(diǎn)比較
- Range.END_TO_START - 用 sourceRange 的結(jié)束點(diǎn)與當(dāng)前范圍的開(kāi)始點(diǎn)比較
-
常量 Range.START_TO_END 指定與當(dāng)前范圍的 end 點(diǎn)和 sourceRange 的 start 點(diǎn)進(jìn)行比較。同樣,常量 Range.END_TO_START 指定比較當(dāng)前范圍的 start 點(diǎn)和指定范圍的 end 點(diǎn)。
My總結(jié):也就是前面的range和后面的range比較,START_TO_END,前面range的end和后面range的start比較
-
7. 復(fù)制 DOM 范圍
- 可以使用 cloneRange()方法復(fù)制范圍。這個(gè)方法會(huì)創(chuàng)建調(diào)用它的范圍的一個(gè)副本。
- 新創(chuàng)建的范圍與原來(lái)的范圍包含相同的屬性,而修改它的端點(diǎn)不會(huì)影響原來(lái)的范圍。
var newRange = range.cloneRange();
-
8. 清理 DOM 范圍
- 在使用完范圍之后,最好是調(diào)用 detach()方法,以便從創(chuàng)建范圍的文檔中分離出該范圍。調(diào)用detach()之后,就可以放心地解除對(duì)范圍的引用,從而讓垃圾回收機(jī)制回收其內(nèi)存了。
range.detach(); //從文檔中分離
range = null; //解除引用


