JS學習11(DOM2&DOM3)

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é)點,后臺會做這些事情:

  1. 提取范圍中的內(nèi)容
  2. 將給定節(jié)點插入到文檔中原來范圍所在位置
  3. 將文檔片段內(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(); 
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卖氨,一起剝皮案震驚了整個濱河市会烙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌双泪,老刑警劉巖持搜,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異焙矛,居然都是意外死亡葫盼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門村斟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贫导,“玉大人抛猫,你說我怎么就攤上這事『⒌疲” “怎么了闺金?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長峰档。 經(jīng)常有香客問我败匹,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮绊谭,結果婚禮上浪南,老公的妹妹穿的比我還像新娘四瘫。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著炼七,像睡著了一般。 火紅的嫁衣襯著肌膚如雪布持。 梳的紋絲不亂的頭發(fā)上豌拙,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音题暖,去河邊找鬼姆蘸。 笑死,一個胖子當著我的面吹牛芙委,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狂秦,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼灌侣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了裂问?” 一聲冷哼從身側響起侧啼,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堪簿,沒想到半個月后痊乾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡椭更,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年哪审,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虑瀑。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡湿滓,死狀恐怖滴须,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叽奥,我是刑警寧澤扔水,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站朝氓,受9級特大地震影響魔市,放射性物質發(fā)生泄漏。R本人自食惡果不足惜赵哲,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一待德、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧誓竿,春花似錦磅网、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至毙死,卻和暖如春燎潮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扼倘。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工确封, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人再菊。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓爪喘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纠拔。 傳聞我的和親對象是個殘疾皇子秉剑,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容