DOM1級主要是在定義HTML和XML文檔的低層結構筷频。D2和D3則在這個結構的基礎上引入了更多的交互能力林束。它們被分為了許多模塊:
- DOM Level 2 Core:為1級核心添加了更多方法和屬性
- DOM Level 2 Views:為文檔定義了基于樣式信息的不同視圖
- DOM Level 2 Events:說明了如何使用事件與DOM文檔交互
- DOM Level 2 Style:有關CSS
- DOM Level 2 Traversal and Range:遍歷和選擇的新API
- DOM Level 2 HTML:添加了新方法和屬性的HTML
DOM變化
DOM2級核心沒有引進新類型惹恃,增強了既有類型庇茫。DOM3級核心既引進了新類型又增強了既有類型。
DOM Level 2 Views搀菩、DOM Level 2 HTML也提供了新的屬性和方法焊虏。
重點之一是對命名空間的支持。
看瀏覽器兼不兼容:
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命名空間的變化
有了XML命名空間秕磷,不同XML文檔的元素就可以混合在一起。技術上說HTML不支持XML命名空間炼团,但JSP澎嚣,XHTML支持疏尿。
命名空間使用xmlns特性來指定。XHTML的命名空間是http://www.w3.org/1999/xhtml易桃。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example XHTML page</title>
</head>
<body>
Hello world!
</body>
</html>
在上面的例子中褥琐,所有元素都默認為XHTML命名空間的元素。想要明確的指定那些元素屬于這個命名空間就要使用前綴:
<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>
這時所有的XHTML元素的前綴都要是這個才行晤郑,有時為了避免沖突敌呈,也需要用命名空間來限定特性。這個在使用單一語言來編寫XML文檔時沒啥用造寝,但是在多語言時就有用了:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example XHTML page</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="width:100%; height:100%">
<rect x="0" y="0" width="100" height="100" style="fill:red"/>
</svg>
</body>
</html>
或
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example XHTML page</title>
</head>
<body>
<s:svg xmlns:s="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="width:100%; height:100%">
<s:rect x="0" y="0" width="100" height="100" style="fill:red"/>
</s:svg>
</body>
</html>
這個例子中通過設置命名空間磕洪,將svg標識為了與包含文檔無關的元素。此時svg元素的所有子元素以及這些元素的所有特性都屬于了http://www.w3.org/2000/svg诫龙。所以即便這是一個XHTML文檔析显,其中的svg代碼還是有效的。
DOM2同時提供了相應的查詢和創(chuàng)建有命名空間歸屬的節(jié)點版本的方法签赃。
Node類型的變化
在DOM2級中谷异,node類型包含下列特定于命名空間的屬性。
- localName:不帶命名空間前綴的節(jié)點名稱
- namespaceURI:命名空間URI
- prefix:命名空間前綴
DOM3級中有如下方法: - isDefaultNamespace(namespaceURI):看看當前節(jié)點的默認命名空間是不是傳入的參數(shù)
- lookupNamespaceURI(prefix):返回給定前綴的命名空間
- lookupPrefix(namespaceURI):返回給定URI的前綴
這里有個神奇的事情:
//這里比較有趣锦聊,svg節(jié)點的defaultNameSpace不是我們給他設置的那個而是上一級的歹嘹。
alert(svg.isDefaultNamespace("http://www.w3.org/1999/xhtml")); //true
alert(svg.isDefaultNamespace("http://www.w3.org/2000/svg")); //false
Document類型的變化
createElementNS(namespaceURI, tagName)
createAttributeNS(namespaceURI, attributeName)
getElementsByTagNameNS(namespaceURI, tagName)
Element類型的變化
getAttributeNS(namespaceURI,localName)
getAttributeNodeNS(namespaceURI,localName)
getElementsByTagNameNS(namespaceURI, tagName)
hasAttributeNS(namespaceURI,localName)
removeAttriubteNS(namespaceURI,localName)
setAttributeNS(namespaceURI,qualifiedName,value)
setAttributeNodeNS(attNode)
NamedNodeMap 類型的變化
getNamedItemNS(namespaceURI,localName)
removeNamedItemNS(namespaceURI,localName)
setNamedItemNS(node)
其他方面變化
DocumentType
新增3個屬性publicId、systemId孔庭、internalSubset
Document類型的變化
importNode()
這個方法用于導入一個來自其他文檔的節(jié)點appendChild()如果加入一個來自其他文檔的節(jié)點會報錯尺上。這個方法會把別的文檔的節(jié)點轉化成本文檔的。這個方法有點像cloneCode()史飞,都是接收一個節(jié)點和一個布爾值尖昏,返回淺復制或深復制的節(jié)點,只不過這個節(jié)點的ownerDocument會被重置构资。
var newNode = document.importNode(oldNode, true);
document.body.appendChild(newNode);
defaultView
這個指針指向擁有給定文檔的窗口或框架抽诉,View。IE不支持吐绵,I使用parentWindow迹淌,所以要是想判斷文檔歸屬的窗口:
var parentWindow = document.defaultView || document.parentWindow;
createDocumentType()、createDocument()
document.implementation的方法己单,Core唉窃。創(chuàng)建一個DocumentType、創(chuàng)建一個新文檔
//新建一個XHTML文檔
var doctype = document.implementation.createDocumentType("html",
" -//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype);
createHTMLDocument()
用來創(chuàng)建一個完整的HTML文檔纹笼,包括html纹份,head,body,title蔓涧。接收的字符串參數(shù)會放到title里件已。HTML
Node類型的變化
isSupported()
當前節(jié)點具有的能力
if (document.body.isSupported("HTML", "2.0")){
}
isSameNode()、isEqualNode()
DOM3
isSameNode()代表兩個節(jié)點引用同一個對象元暴。
isEqualNode()代表兩個節(jié)點類型相同篷扩,屬性相同,屬性值相等茉盏。
//相等鉴未,不相同的兩個節(jié)點
var div1 = document.createElement("div");
div1.setAttribute("class", "box");
var div2 = document.createElement("div");
div2.setAttribute("class", "box");
alert(div1.isSameNode(div1)); //true
alert(div1.isEqualNode(div2)); //true
alert(div1.isSameNode(div2)); //false
setUserData()
這個方法比較神奇,可以為節(jié)點額外添加數(shù)據(jù)鸠姨,3個參數(shù):鍵铜秆,值,處理函數(shù)享怀。這個處理函數(shù)會在節(jié)點被復制羽峰,導入新文檔,刪除添瓷,重命名時被調(diào)用梅屉。這個函數(shù)接受5個參數(shù):操作類型(1、2鳞贷、3坯汤、4),數(shù)據(jù)鍵搀愧、數(shù)據(jù)值惰聂、源節(jié)點、目標節(jié)點咱筛。
/***********************Node類型的新方法:setUserData(),不過Safari和chrome都不支持貌似********/
var div = document.createElement("div");
div.setUserData("name", "Nicholas", function(operation, key, value, src, dest){
if (operation == 1){
dest.setUserData(key, value, function(){});
}
});
var newDiv = div.cloneNode(true);
alert(newDiv.getUserData("name")); //"Nicholas"
框架的變化
框架和內(nèi)嵌框架HTMLFrameElement搓幌、HTMLIFrameElement。這兩個類型有新屬性contentDocument迅箩。指向表示框架內(nèi)容的文檔對象溉愁。
在此之前無法通過元素獲得這個對象,這個對象是Document類型的饲趋。IE8之前不支持拐揭,可以使用contentWindow。contentWindow所有瀏覽器都支持奕塑。
var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
樣式
要支持DOM2級CSS
var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0");
var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2", "2.0");
訪問元素的樣式
任何支持style特性的HTML元素在JS中都有一個對應的style屬性堂污。它是CSSStyleDeclaration的實例,這里包含通過HTML的style特性指定的所有樣式信息龄砰,但不包含外部與內(nèi)嵌樣式表的樣式盟猖。樣式通過屬性訪問讨衣,駝峰命名。
var myDiv = document.getElementById("myDiv");
myDiv.style.backgroundColor = "red";
myDiv.style.width = "100px";
myDiv.style.height = "200px";
myDiv.style.border = "1px solid black";
DOM樣式屬性和方法
屬性和方法用來訪問和修改樣式扒披。
- ? cssText:訪問CSS中的特性代碼值依,設置時覆蓋原來的。
- length:CSS屬性的數(shù)量
- parentRule:CSSRule對象
- getPropertyCSSValue(propertyName):給定屬性的CSSValue
- getPropertyPriority(propertyName):如果給定屬性有!important則返回"important"碟案,否則空字符串。
- getPropertyValue(propertyName):給定屬性值 ?
- item(index):給定位置的CSS屬性名稱
- removeProperty(propertyName):從樣式表中刪除給定屬性
- setProperty(propertyName,value,priority):為給定屬性設置值和優(yōu)先級颇蜡。
var prop, value, i, len;
for (i=0, len=myDiv.style.length; i < len; i++){
prop = myDiv.style[i]; //myDiv.style.item(i)
value = myDiv.style.getPropertyValue(prop);
alert(prop + " : " + value);
}
計算的樣式
style只包含直接寫在HTML里的特性价说,但是不支持樣式表的。這是個大問題风秤。
document.defaultView.getComputedStyle()
這個方法接收兩個參數(shù)鳖目,要取得計算樣式的元素和一個偽元素字符串。返回一個CSSStyleDeclaration缤弦。包含所有計算后的屬性领迈。
IE不支持,但是IE每個節(jié)點都有一個currentStyle屬性碍沐,這里包含了計算后的屬性狸捅。
計算后樣式只讀。
var myDiv = document.getElementById("myDiv");
var computedStyle = document.defaultView.getComputedStyle(myDiv, null);
//IE不支持累提,使用currentStyle
//var computedStyle = myDiv.currentStyle;
alert(computedStyle.height); // "200px"
操作樣式表
CSSStyleSheet類型表示樣式表尘喝,繼承自StyleSheet,后者可以作為一個基礎接口來定義非CSS樣式表斋陪。CSSStyleSheet繼承了如下屬性朽褪。
- disabled:樣式表是否被禁用
- href:樣式表的URL
- media:樣式表支持的媒體類型集合
- ownerNode:指向擁有當前樣式表節(jié)點的指針,IE不支持
- parentStyleSheet:當前樣式表通過@import導入的情況下无虚,這個屬性指向導入它的樣式表
- title:ownerNode中title的值
- type:表示樣式表類型的字符串
- cssRules:樣式表中包含的樣式規(guī)則的集合缔赠,IE使用rules
- ownerRule:當前樣式表通過@import導入的情況下,指向表示導入的規(guī)則友题,IE不支持
- deleteRule(index):刪除cssRules集合中指定位置的規(guī)則嗤堰,IE使用removeRule()
- insertRule(rule,index):向cssRules集合中指定位置插入rule字符串,IE使用addRule()
應用于文檔的所有樣式通過document.styleSheets集合來表示咆爽。
var sheet = null;
for (var i=0, len=document.styleSheets.length; i < len; i++){
sheet = document.styleSheets[i];
alert(sheet.href);
}
直接通過link梁棠,style元素取得CSSStyleSheet。
function getStyleSheet(element){
return element.sheet || element.styleSheet;
}
var link = document.getElementsByTagName("link")[0];
var sheet = getStyleSheet(link);
alert(sheet.href);
CSSRule對象
這個對象表示樣式表中的每一條規(guī)則斗埂。它是一個基類符糊,不止是CSS規(guī)則,包括@import呛凶、@font-face男娄、@page、@charset等。不過其中最常用的當然是CSS規(guī)則咯模闲,是CSSStyleRule類型建瘫,有下面這些屬性:
- cssText:文本咯,只讀的尸折,包括選擇符啰脚,花括號等等一整套
- parentRule:如果當前規(guī)則是導入的規(guī)則,這個屬性引用導入規(guī)則实夹,否則為null
- parentStyleSheet:規(guī)則所歸屬的樣式表
- selectorText:規(guī)則的選擇符文本
- style:CSSStyleDeclaration 對象橄浓,通過這個可以設置和取得規(guī)則中的樣式值
- type:規(guī)則類型的常量值
var sheet = document.styleSheets[0]; //取得樣式表
var rules = sheet.cssRules || sheet.rules; //為兼容IE
var rule = rules[0];
alert(rule.selectorText);
alert(rule.cssText);
alert(rule.style.cssText);
alert(rule.style.height);
//這里的修改并不成功?亮航?荸实??
rule.style.height = "2000ps";
alert(rule.style.height);
創(chuàng)建規(guī)則
//添加規(guī)則
function insertRule(sheet, selectorText, cssText, position){
if (sheet.insertRule){
sheet.insertRule(selectorText + "{" + cssText + "}", position);
} else if (sheet.addRule){
sheet.addRule(selectorText, cssText, position);
}
}
刪除規(guī)則
//刪除規(guī)則
function deleteRule(sheet, index){
if (sheet.deleteRule){
sheet.deleteRule(index);
} else if (sheet.removeRule){
sheet.removeRule(index);
}
}
元素尺寸大小
偏移量
元素的可見大小由其內(nèi)容缴淋,內(nèi)邊距准给,滾動條和邊框大小決定,并不包括外邊距重抖。有下面4個屬性:
- offsetHeight
- offsetWidth
- offsetLeft
- offsetTop
其中offsetLeft和offsetTop是相對包含它的元素而言的露氮。包含元素的引用保存在offsetParent中,這個并不一定是元素的父節(jié)點仇哆,而是父節(jié)點中第一個有大小的元素沦辙,比如td的就是table而不是tbody。
由于這里的偏移都是基于父元素的讹剔,想要獲得絕對偏移就需要迭代父元素油讯。
偏移量屬性只讀,每次讀取時是現(xiàn)計算的延欠。代價比較大陌兑,最好保存起來用。
//獲得元素絕對上偏移
function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while (current !== null){
actualTop += current. offsetTop;
current = current.offsetParent;
}
return actualTop;
}
客戶區(qū)大小
clientWidth由捎、clientHeight包括內(nèi)邊距和內(nèi)容
滾動大小
- scrollHeight:元素內(nèi)容真正的高度
- scrollWidth:真正的寬度
- scrollLeft:被隱藏的內(nèi)容區(qū)域左側的像素數(shù)
- scrollTop:頂部的
scrollLeft和scrollTop都可以設置兔综,用來自動滾動元素。
確定元素大小
每個元素有個方法:getBoundingClientRect()
這個方法返回一個矩形對象狞玛,包含 4個屬性left软驰,top,right心肪,bottom锭亏。不過有個小問題,IE8及以前的版本會認為文檔左上角的坐標是(2,2)硬鞍,其他的都是正常的(0,0)慧瘤。
還有就是有的老瀏覽器可能不支持這個方法戴已,使用之前的getElementLeft()函數(shù)得到left,再加加offsetWidth得到right锅减。
function getBoundingClientRect(element){
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
//在支持getBoundingClientRect方法的情況下
if (element.getBoundingClientRect){
//這里利用了函數(shù)自身的屬性糖儡,如果這個函數(shù)剛才已經(jīng)執(zhí)行過了。arguments.callee.offset就已經(jīng)存在了
//就說明這個瀏覽器的調(diào)整量已經(jīng)設置過了怔匣,直接使用就好了握联。就不必執(zhí)行下面這個開銷比較大的代碼塊了
if (typeof arguments.callee.offset != "number"){
//利用一個新元素,將他設置在瀏覽器的左上角劫狠,再獲取它的top值
//看看這個瀏覽器的偏差是多少拴疤,反向減掉
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
};
//在支持getBoundingClientRect方法的情況下,使用之前的getElementLeft()函數(shù)得到left独泞,再加加offsetWidth得到right
//這個方法可能不太準確,不過誰叫你不支持getBoundingClientRect的
} 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
}
}
}
var rect = getBoundingClientRect(document.getElementById("myDiv"));
alert(rect.bottom);
alert(rect.top);
alert(rect.left);
alert(rect.right);
遍歷
DOM2級遍歷和范圍模塊定義了兩個用于輔助完成順序遍歷DOM結構的類型苔埋。NodeIterator和TreeWalker懦砂。這兩個類型能夠基于給定的節(jié)點進行深度優(yōu)先遍歷。IE不支持组橄。
檢測兼容:
var supportsTraversals = document.implementation.hasFeature("Traversal", "2.0");
var supportsNodeIterator = (typeof document.createNodeIterator == "function");
var supportsTreeWalker = (typeof document.createTreeWalker == "function");
NodeIterator
document.createNodeIterator()來創(chuàng)建荞膘,這個方法有4個參數(shù):
- root:搜索起點
- whatToShow:要遍歷那些類型的節(jié)點 ?
- filter:NodeFilter對象,或者表示接受還是拒絕某種節(jié)點的函數(shù)
- entityReferenceExpansion:在HTML中沒啥用
whatToShow通過應用一個或多個過濾器來確定要訪問哪些節(jié)點玉工。位掩碼羽资。
- NodeFilter.SHOW_ALL
- NodeFilter.SHOW_ELEMENT
- NodeFilter.SHOW_ATTRIBUTE
- NodeFilter.SHOW_TEXT
- NodeFilter.SHOW_CDATA_SECTION
- NodeFilter.SHOW_ENTITY_REFERENCE
- NodeFilter.SHOW_ENTITYE
- NodeFilter.SHOW_PROCESSING_INSTRUCTION
- NodeFilter.SHOW_COMMENT
- NodeFilter.SHOW_DOCUMENT
- NodeFilter.SHOW_DOCUMENT_TYPE
- NodeFilter.SHOW_DOCUMENT_FRAGMENT
- NodeFilter.SHOW_NOTATION
var whatToShow = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;
var filter = {
acceptNode: function(node){
return node.tagName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
};
//直接定義函數(shù)也行
// var filter = function(node){
// return node.tagName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
// };
var iterator = document.createNodeIterator(document.documentElement, NodeFilter.SHOW_ELEMENT, filter, false);
//或者遍歷所有節(jié)點
iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false);
var node = iterator.nextNode();
while (node !== null) {
alert(node.tagName);
node = iterator.nextNode();
}
NodeIterator的兩個方法是nextNode()和previousNode(),在遍歷到頭的時候遵班,這兩個方法返回null屠升。
TreeWalker
TreeWalker是高級的NodeIterator:
- parentNode() ?
- firstChild() ?
- lastChild() ?
- nextSibling() ?
- previousSibling()
- nextNode()
- previousNode()
創(chuàng)建和NodeIterator接受一樣的參數(shù),不過過濾器在這里有些不同狭郑,有3種返回值:NodeFilter.FILTER_SKIP腹暖、NodeFilter.FILTER_REJECT、NodeFilter.FILTER_ACCEPT翰萨。reject會跳過該節(jié)點及其子樹脏答,skip就單單跳過這個節(jié)點。
var walker = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, null, false);
walker.firstChild();
walker.nextSibling();
var node = walker.firstChild();
while (node !== null) {
alert(node.tagName);
node = walker.nextSibling();
}
它還有一個currentNode屬性亩鬼,表示上一次遍歷的節(jié)點殖告,這個屬性可以設置,就改變了繼續(xù)遍歷的起點雳锋。
IE啥都不支持
范圍
范圍用來選擇文檔中的一個區(qū)域而不必考慮節(jié)點的界限黄绩。在常規(guī)的DOM操作不能更有效的修改文檔時,范圍往往可以實現(xiàn)目的魄缚。除IE外都支持宝与,IE8及以前有自己的實現(xiàn)方式焚廊。
DOM中的范圍(除IE8及以下瀏覽器外支持的范圍)
使用createRange()方法創(chuàng)建DOM范圍。新創(chuàng)建的范圍與創(chuàng)建它的文檔相關聯(lián)习劫,不能用于其它文檔咆瘟。在創(chuàng)建了范圍并設置了其位置之后,可以針對范圍的內(nèi)容實現(xiàn)多種操作诽里,從而實現(xiàn)對底層DOM樹的更精細的控制袒餐。
每個范圍由一個Range類型的實例表示,這個實例由很多屬性和方法谤狡,下列屬性提供了當前范圍在文檔中的位置信息灸眼。
- startContainer:包含范圍起點的節(jié)點,也就是選區(qū)中第一個節(jié)點的父節(jié)點
- startOffset:范圍在startContainer中起點的偏移量墓懂。如果startContainer是文本節(jié)點焰宣、注釋節(jié)點或CDATA節(jié)點,那么startOffset就是范圍起點之前跳過的字符數(shù)量捕仔。否則就是范圍中第一個子節(jié)點在父節(jié)點(startContainer)中的索引
- endContainer:包含范圍終點的節(jié)點
- endOffset:范圍在endContainer中終點的偏移量
- commonAncestorContainer:startContainer和endContainer共同的祖先節(jié)點在文檔樹中位置最深的那個
用DOM范圍實現(xiàn)簡單選擇
selectNode()匕积、selectNodeContents()
這兩個方法都接受一個DOM節(jié)點作為參數(shù),然后使用該節(jié)點中的信息來填充范圍榜跌,selectNode()選擇整個節(jié)點包括子節(jié)點闪唆;selectNodeContents()只選擇節(jié)點的子節(jié)點。
<body>
<div id="myDiv" data-appId="12345" data-myname="Nicholas">
哈哈哈我在div里
<span>測試Span</span>
<a>我是一個a標簽~~~~~</a>
</div>
</body>
var range1 = document.createRange();
var range2 = document.createRange();
var div = document.getElementById("myDiv");
range1.selectNode(div);
range2.selectNodeContents(div);
alert(range1.startContainer.tagName); //body
alert(range1.endContainer.tagName); //body
alert(range1.commonAncestorContainer.tagName); //body
alert(range1.startOffset); //這個div在body中的索引哦,1
alert(range1.endOffset); //startOffset+1,因為只選擇了一個節(jié)點
alert(range2.startContainer.tagName); //div
alert(range2.endContainer.tagName); //div
alert(range2.commonAncestorContainer.tagName); //div
alert(range2.startOffset); //永遠都是0
alert(range2.endOffset); //子節(jié)點數(shù)目
如果想要更精細的控制钓葫,有下面這些方法:
- setStartBefore(refNode):將范圍起點設置在refNode之前悄蕾,refNode就成為了范圍中第一個節(jié)點。startContainer會被設為refNode.parentNode础浮,startOffset會被設成refNode在其父節(jié)點childNodes中的索引帆调。
- setStartAfter(refNode)
- setEndBefore(refNode)
- setEndAfter(refNode)
用DOM范圍實現(xiàn)復雜選擇
setStart()和setEnd()
這兩個方法接受兩個參數(shù):一個參照節(jié)點和一個偏移量值。setStart()的參照節(jié)點會變成startContainer霸旗,偏移量會變成startOffset贷帮;setEnd()同理。
var div = document.getElementById("myDiv");
var textNode = div.childNodes[1].firstChild;
var worldNode = div.lastChild;
var range = document.createRange();
range.setStart(textNode, 4);
range.setEnd(worldNode, 0);
alert(range); //an /n 我是一個a標簽~~~~~
操作DOM范圍中的內(nèi)容
創(chuàng)建范圍時诱告,內(nèi)部會為這個范圍創(chuàng)建一個文檔片段撵枢,范圍所屬的所有節(jié)點都會被添加到這個文檔片段中,為了創(chuàng)建這個文檔片段精居,范圍的格式必須正確有效锄禽,這就意味著要有正確的DOM結構,但是像我們剛才那樣選擇靴姿,起始和結束都在一個節(jié)點的內(nèi)部沃但,這樣的DOM結構并不正確。不過范圍知道自己缺少哪些標簽佛吓,并重新構建有效的DOM結構宵晚。不過在你真正對DOM做出修改之前垂攘,范圍是不會修改DOM結構的,也確實沒必要淤刃。
在創(chuàng)建了范圍之后晒他,就可以使用各種方法對范圍的內(nèi)容進行操了,表示范圍的內(nèi)部文檔片段中所有節(jié)點都只是指向文檔中相應節(jié)點的指針逸贾。
- deleteContents():刪除范圍中所包含的內(nèi)容陨仅。
- extractContents():同樣是刪除,只不過會返回范圍的文檔片段铝侵∽粕耍可以將其插入其他地方。
- cloneContents():復制內(nèi)容
var fragment = range.extractContents();
document.getElementById("myButton").parentNode.appendChild(fragment);
插入DOM范圍中的內(nèi)容
對于這里的方法要注意咪鲜,范圍并不會在使用這里的方法的時候自動創(chuàng)建有效的DOM結構狐赡,這對insertNode()的影響不大,但是對 surroundContents()就有影響了疟丙,因為這很可能出現(xiàn)錯亂的DOM結構猾警。
insertNode()方法在范圍選區(qū)的開始插入一個節(jié)點
var span = document.createElement("span");
span.style.color = "red";
span.appendChild(document.createTextNode("Inserted text"));
range.insertNode(span);
surroundContents()環(huán)繞范圍插入節(jié)點,后臺會做這些事情:
- 提取范圍中的內(nèi)容
- 將給定節(jié)點插入到文檔中原來范圍所在位置
- 將文檔片段內(nèi)容添加到給定節(jié)點中
如果你選中的是像之前那樣不完整的DOM節(jié)點隆敢。。崔慧。那這里就會添加失敗拂蝎。。惶室。這里范圍不會自己創(chuàng)建有意義的DOM結構
var div = document.getElementById("myDiv");
var textNode = div.childNodes[1].firstChild;
var range = document.createRange();
range.selectNode(textNode);
var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
alert(range);
折疊DOM范圍
collapse()
折疊后的范圍不選擇文檔的任何部位温自,傳入true可以折疊到范圍起始位置,false折疊到范圍結束位置皇钞。通過范圍的collapsed可以檢測是否折疊悼泌,這個屬性就是檢測范圍的起始和結尾是不是同一個位置,如果是夹界,就算不是使用collapse()折疊的也會返回true馆里。這個可以用來檢測范圍是不是空的。
比較DOM范圍
compareBoundaryPoints()
比較兩個范圍是否有公共起點和終點
alert(range1.compareBoundaryPoints(Range.START_TO_START, range2));
Range.START_TO_START(0) ?比較起點
Range.START_TO_END(1) ? 第一個的起點和第二個的終點
Range.END_TO_END(2) ?
Range.END_TO_START(3)
第一個點在第二個前面-1可柿,相等0鸠踪,后面1。
復制DOM范圍
var newRange = range.cloneRange();
清理DOM范圍
range.detach(); //從文檔中分離
range = null; //解除引用
IE8及更早版本中的范圍
IE8以及之前的版本不支持DOM范圍复斥,但是支持一種文本范圍营密。
可以在文檔和元素上創(chuàng)建文本范圍,在元素上創(chuàng)建的文本范圍只能在本元素內(nèi)使用目锭。
var range = document.body.createTextRange();
簡單選擇
findText()接收一個字符串评汰,可選的傳入方向值纷捞,返回一個布爾
這個方法會找到第一次出現(xiàn)的給定文本,并將范圍移過來環(huán)繞該文本被去。
var range = document.body.createTextRange();
var found = range.findText("我是");
var foundAgain = range.findText("我是", 1);
alert(found); //true
alert(range.text);
alert(foundAgain);
alert(range.text);
moveToElementText()接收一個節(jié)點主儡,并選擇這個節(jié)點所有的文本,如果這個元素里有HTML標簽编振,使用htmlText屬性可以同時獲取到標簽和文本缀辩。
range.moveToElementText(div);
alert(range.text);
alert(range.htmlText);
parentElement()可以得到選區(qū)的父節(jié)點
復雜選擇
move()、moveStart()踪央、moveEnd()臀玄、expand()
這些方法都接收兩個參數(shù),移動單位和移動單位的數(shù)量畅蹂,移動單位是字符串:"character"健无、? "word"、? "sentence"液斜、"textedit"累贤。
expand("word")會將現(xiàn)有的選區(qū)里單詞不全的選全。
move會先折疊選區(qū)少漆,再將范圍移動指定的單位數(shù)量臼膏。然后再moveStart()、moveEnd()手動展開選區(qū)示损。
操作內(nèi)容
range.text = "Howdy";
range.pasteHTML("<em>Howdy</em>");
折疊范圍
collapse()
這個倒是和DOM范圍一樣渗磅。不過檢測時要使用boundingWidth、boundingHeight检访、boundingLeft始鱼、boundingTop這些是范圍的尺寸信息,以像素為單位脆贵,boundingWidth為0就代表范圍折疊了医清。
比較范圍
compareEndPoints()
這個是差不多的方法,"StartToStart""StartToEnd""EndToEnd""EndToStart"
range1.compareEndPoints("StartToStart", range2)
還有兩個特別的方法:
range1.isEqual(range2)
range1.inRange(range2)
復制IE范圍
var newRange = range.duplicate();