<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JAVA & XML & JAVASCRIPT & AJAX & CSS

    Web 2.0 技術(shù)儲(chǔ)備............

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      77 隨筆 :: 17 文章 :: 116 評(píng)論 :: 0 Trackbacks
    2級(jí)DOM定義了一個(gè)createRange()方法,如果是按照DOM此標(biāo)準(zhǔn)的瀏覽器(IE并不是支持此標(biāo)準(zhǔn)的,但是IE里的屬性或方法卻遠(yuǎn)比標(biāo)準(zhǔn)中定義的多得多),它屬于document對(duì)象,所以創(chuàng)建一個(gè)range對(duì)象要這樣做:

    var oRange = document.createRange();

    如果你要檢測(cè)你的瀏覽器是否支持此標(biāo)準(zhǔn)Range對(duì)象,可以用hasFeature()方法來檢測(cè):

    var supportsDOMRanges = document.implementation.hasFeature("Range", "2.0");
    if (supportsDOMRange) {
    var oRange = document.createRange();
    //range code here
    }
    Range對(duì)象進(jìn)行簡(jiǎn)單的選擇
    最簡(jiǎn)單用Range進(jìn)行選擇,用selectNode()或者selectNodeContents()方法,這兩個(gè)方法只有一個(gè)接收參數(shù),一個(gè)DOM節(jié)點(diǎn)。

    selectNode()方法選擇全部節(jié)點(diǎn),包括它的孩子,而selectNodeContents()選擇的節(jié)點(diǎn)只是它的孩子。如
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oRange1 = document.createRange();
    var oRange2 = document.createRange();
    var oP1 = document.getElementById("p1");
    oRange1.selectNode(oP1);
    oRange2.selectNodeContents(oP1);
    </script>
    oRange1和oRange2包含上面所說的兩種方法,但是看了下面的示圖相信你能很快明白這兩個(gè)方法的區(qū)別:
    uploads/200609/30_160954_domranges1.gif


    當(dāng)你創(chuàng)建了一個(gè)Range對(duì)象時(shí),Range實(shí)例就會(huì)有以下的屬性:
    startContainer — 返回range對(duì)象從何開始的節(jié)點(diǎn)對(duì)象(父節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn))
    startOffset — 返回Range開始的偏移量(offset),如果startContainer是一個(gè)文本節(jié)點(diǎn),注釋節(jié)點(diǎn),或者是CDATA節(jié)點(diǎn),這個(gè)屬性返回文本的偏移量,否則返回第一個(gè)節(jié)點(diǎn)的索引。
    endCOntainer — 返回Range對(duì)象最后一個(gè)節(jié)點(diǎn)對(duì)象(父節(jié)點(diǎn)的最后一個(gè)節(jié)點(diǎn))
    endOffset — 返回Range結(jié)束時(shí)的偏移量(offset)特性與startOffset相同。
    commonAncestorContainer — 返回第一個(gè)包含該Range對(duì)象的節(jié)點(diǎn)。

    注:這些屬性均為只讀屬性(read-only),startOffset和endOffset將在下文中有較詳細(xì)的解釋。

    下面這段代碼將說明這些屬性,請(qǐng)?jiān)贛ozilla firefox里運(yùn)行(支持此標(biāo)準(zhǔn)的瀏覽器——DOM2級(jí),IE里將無效):
    <html>
    ?<head>
    ?<title>DOM Range Example</title>
    ?<script type="text/javascript">
    ?function useRanges() {
    ?var oRange1 = document.createRange();
    ?var oRange2 = document.createRange();
    ?var oP1 = document.getElementById("p1");
    ?oRange1.selectNode(oP1);
    ?oRange2.selectNodeContents(oP1);
    ?
    ?document.getElementById("txtStartContainer1").value
    ????= oRange1.startContainer.tagName;
    ?document.getElementById("txtStartOffset1").value =
    ????oRange1.startOffset;
    ?document.getElementById("txtEndContainer1").value =
    ????oRange1.endContainer.tagName;
    ?document.getElementById("txtEndOffset1").value =
    ????oRange1.endOffset;
    ?document.getElementById("txtCommonAncestor1").value =
    ????oRange1.commonAncestorContainer.tagName;
    ?document.getElementById("txtStartContainer2").value =
    ????oRange2.startContainer.tagName;
    ?document.getElementById("txtStartOffset2").value =
    ????oRange2.startOffset;
    ?document.getElementById("txtEndContainer2").value =
    ????oRange2.endContainer.tagName;
    ?document.getElementById("txtEndOffset2").value =
    ????oRange2.endOffset;
    ?document.getElementById("txtCommonAncestor2").value =
    ????oRange2.commonAncestorContainer.tagName;
    ?}
    ?</script>
    ?</head>
    ?<body><p id="p1"><b>Hello</b> World</p>
    ?<input type="button" value="Use Ranges" onclick="useRanges()" />
    ?<table border="0">
    ?<tr>
    ?<td>
    ?<fieldset>
    ?<legend>oRange1</legend>
    ?Start Container:
    ????<input type="text" id="txtStartContainer1" /><br />
    ?Start Offset:
    ????<input type="text" id="txtStartOffset1" /><br />
    ?End Container:
    ????<input type="text" id="txtEndContainer1" /><br />
    ?End Offset:
    ????<input type="text" id="txtEndOffset1" /><br />
    ?Common Ancestor:
    ????<input type="text" id="txtCommonAncestor1" /><br />
    ?</fieldset>
    ?</td>
    ?<td>
    ?<fieldset>
    ?<legend>oRange2</legend>
    ?Start Container:
    ????<input type="text" id="txtStartContainer2" /><br />
    ?Start Offset:
    ????<input type="text" id="txtStartOffset2" /><br />
    ?End Container:
    ????<input type="text" id="txtEndContainer2" /><br />
    ?End Offset:
    ????<input type="text" id="txtEndOffset2" /><br />
    ?Common Ancestor:
    ????<input type="text" id="txtCommonAncestor2" /><br />
    ?</fieldset>
    ?</td>
    ?</tr>
    ?</table>
    ?</body>
    </html>
    上面的代碼將不作注釋了,有什么問題,在評(píng)論中留言。

    Range中還有一些其它的方法:
    setStartBefore(node) — 設(shè)置Range的相對(duì)于node節(jié)點(diǎn)的起始位置
    setStartAfter(node) — 同上
    setEndBefore — 設(shè)置Range的相對(duì)于node節(jié)點(diǎn)的結(jié)束位置
    setEndAfter — 同上



    復(fù)雜的DOM Range

    建立復(fù)雜的DOM range需要使用setStart()和setEnd()兩個(gè)方法,這兩個(gè)方法有兩個(gè)參數(shù):一個(gè)是一個(gè)節(jié)點(diǎn)(node)引用和一個(gè)偏移(offset)。
    setStart方法節(jié)點(diǎn)的引用是startContainer,偏移則是startOffset;
    setEnd()方法時(shí),節(jié)點(diǎn)引用為endContainer,偏移就是endOffset。

    使用這兩個(gè)方法與selectNode()和selectNodeContents()方法相似。比如,下面的useRanges()函數(shù)的前一個(gè)示例,可以使用setStart()和setEnd():

    function useRanges() {
    ?var oRange1 = document.createRange();
    ?var oRange2 = document.createRange();
    ?var oP1 = document.getElementById("p1");
    ?var iP1Index = -1;
    ?for (var i=0; i < oP1.parentNode.childNodes.length; i++) {
    ?if (oP1.parentNode.childNodes[i] == oP1) {
    ?iP1Index = i;
    ?break;
    ?}
    ?}
    ?
    ?oRange1.setStart(oP1.parentNode, iP1Index);
    ?oRange1.setEnd(oP1.parentNode, iP1Index + 1);
    ?oRange2.setStart(oP1, 0);
    ?oRange2.setEnd(oP1, oP1.childNodes.length);
    ?//textbox assignments here
    }

    注意這個(gè)選擇節(jié)點(diǎn)時(shí)的代碼(oRange1),你必須指定oP1父節(jié)點(diǎn)里所有childNodes集合里的一個(gè)索引。

    而選擇內(nèi)容時(shí)的代碼(oRange2),則不需要額外的考慮,

    從剛才的例子來從這段HTML里(code <p id="p1"><b>Hello</b> World</p>)
    選擇從hello中的llo開始到從World中的Wo開始的Range,我們用setStart()和setEnd(),很容易就可以做到。

    首先,我們必須用常規(guī)的DOM方法得到文本節(jié)點(diǎn)的引用還有就是容器p1的引用。
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    說明:
    文本Hello實(shí)際上是容器p1的孫子節(jié)點(diǎn),所以我們可以用oP1.firstChild得到<b>元素,oP1.firstChild.firstChild也就是Hello文本節(jié)點(diǎn)的引用了,而World則就是容器p1的最后一個(gè)節(jié)點(diǎn)了。

    下一步,建立range然后設(shè)置偏移(offset):
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    說明:
    對(duì)于setStart(),偏移(offset)為2,因?yàn)樽帜竘在該文本節(jié)點(diǎn)中(即Hello中)的位置是2,(位置是從0開始計(jì)算的),設(shè)置setEnd()方法中的偏移為3,原因同上,需要注意的是World前面有一個(gè)空格,空格也是占位置的。如圖:
    uploads/200609/30_141714_domranges3.gif


    注意:
    (Mozilla DOM Range bug #135928)在 Mozilla低版本瀏覽器 執(zhí)行此Range方法時(shí),如果setStart()和setEnd()都指向同一個(gè)文本節(jié)點(diǎn)會(huì)出現(xiàn)異常

    用DOM Range做一些操作
    當(dāng)創(chuàng)建一個(gè)Range對(duì)象時(shí),在Range里的所有對(duì)象之上,已經(jīng)創(chuàng)建了一個(gè)文檔的fragment節(jié)點(diǎn)。在這之前,Range對(duì)象必須合格證你選擇的這段Range是一個(gè)well-formed(格式良好)。
    比如以面這段Range
    uploads/200609/30_165636_domranges4.gif

    很明顯的,在這里,并不是一個(gè)well-formed,上面說過了,當(dāng)創(chuàng)建一個(gè)Range時(shí),會(huì)自動(dòng)產(chǎn)生一個(gè)fragment,在這里,framgment自動(dòng)動(dòng)態(tài)的添加一些元素,以保證Range的正確性:
    <p><b>He</b><b>llo</b> World</p>
    也就是自動(dòng)加上了開始標(biāo)簽<b>,使得整個(gè)Range變?yōu)?lt;b>llo</b> Wo,fragment的示意圖為:
    uploads/200609/30_170131_domranges5.gif

    當(dāng)此fragment創(chuàng)建后,你就可以用Range的一些方法來操作它了。

    最簡(jiǎn)單的一個(gè)操作就是:deleteContents()方法,這個(gè)方法將刪除Range選中的部分,在上面的操作之后進(jìn)行deleteContents(),那么余下的HTML就為:
    <p><b>He</b>rld</p>
    之所以加上閉合標(biāo)簽</b>,上面也說了,也是Range為了確保它是well-formed。

    extractContents()方法類似于deleteContents(),但具體操作不同,extractContents()是將選中的Range從DOM樹中移到一個(gè)fragment中,并返回此fragment,復(fù)制下面這些代碼然后在Mozilla Firefox里運(yùn)行,看看結(jié)果你就明白了。——?jiǎng)h除的<b>llo</b> Wo作為一個(gè)fragment被添加到body的末端。
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    var oFragment = oRange.extractContents();
    document.body.appendChild(oFragment);
    </script>

    cloneContents()方法可以克隆選中Range的fragment,比如:
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    var oFragment = oRange.cloneContents();
    document.body.appendChild(oFragment);
    </script>

    這個(gè)方法類似于extractContents(),但是不是刪除,而是克隆。


    從Range中插入一些數(shù)據(jù)

    前一節(jié)的幾個(gè)方法解決了如何移除range中所選中的fragment。現(xiàn)在說明如何添加內(nèi)容到Range中。
    insertNode()方法可以插入一個(gè)節(jié)點(diǎn)到Range中。假如我想把以下的節(jié)點(diǎn)插如Range中,將如何操作呢?
    <span style="color: red">Inserted text</span>

    看下面的代碼:
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    var oSpan = document.createElement("span");
    oSpan.style.color = "red";
    oSpan.appendChild(document.createTextNode("Inserted text"));
    ?
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    oRange.insertNode(oSpan);
    </script>

    那么原來的HTML將會(huì)變成這樣:
    <p id="p1"><b>He<span style="color: red">Inserted text</span>llo</b> World</p>

    surroundContents()的參數(shù)為一個(gè)node,它將這個(gè)node加入到Range,下面看這個(gè)示例。
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    var oSpan = document.createElement("span");
    oSpan.style.backgroundColor = "yellow";
    ?
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    oRange.surroundContents(oSpan);
    </script>

    在oRange選取的范圍內(nèi)有一個(gè)我們新生成的節(jié)點(diǎn)span,因此選取的Range的背景變成了黃色。

    collapse()方法:

    collapse()方法只有一個(gè)布爾型的參數(shù),該參數(shù)為可選的,也就是說,可以有,也可以沒有,默認(rèn)為false。
    true時(shí)折疊到Range邊界的首部,為false時(shí)折疊到Range尾部。即

    uploads/200609/30_174339_domranges6.gif
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oHello = oP1.firstChild.firstChild;
    var oWorld = oP1.lastChild;
    var oRange = document.createRange();
    oRange.setStart(oHello, 2);
    oRange.setEnd(oWorld, 3);
    oRange.collapse(true);
    </script>

    如果你想知道該Range是否已經(jīng)折疊,可以用collapsed屬性來得到true或者false。看下面的例子。
    <p id="p1">Paragraph 1</p><p id="p2">Paragraph 2</p>
    <script>
    var oP1 = document.getElementById("p1");
    var oP2 = document.getElementById("p2");
    var oRange = document.createRange();
    oRange.setStartAfter(oP1);
    oRange.setStartBefore(oP2);
    alert(oRange.collapsed); //outputs "true"
    </script>
    上面的代碼輸為true。雖然我們沒有用collapse方法,但是由于我們的Range設(shè)置開始為1末端到p2的首端,沒有任何元素。即</p>(Range開始)(Range結(jié)束)<p id="p2">,所以顯示的是true。

    Range邊界的比較

    compareBoundaryPoints()方法,語法形式如下:
    compare = comparerange.compareBoundaryPoints(how,sourceRange)

    參數(shù)含義:
    compare —— 返回1, 0, -1.(0為相等,1為時(shí),comparerange在sourceRange之后,-1為comparerange在sourceRange之前)
    how —— 為Range常數(shù):END_TO_END|END_TO_START|START_TO_END|START_TO_START
    sourceRange —— 一個(gè)Range對(duì)象的邊界。

    看下面的例子:
    <p id="p1"><b>Hello</b> World</p>
    <script>
    var oRange1 = document.createRange();
    var oRange2 = document.createRange();
    var oP1 = document.getElementById("p1");
    oRange1.selectNodeContents(oP1);
    oRange2.selectNodeContents(oP1);
    oRange2.setEndBefore(oP1.lastChild);
    alert(oRange1.compareBoundaryPoints(Range.START_TO_START, oRange2));
    //outputs 0
    alert(oRange1.compareBoundaryPoints(Range.END_TO_END, oRange2));
    //outputs 1;
    </script>
    下圖為這兩個(gè)Range的示意圖,結(jié)合代碼和上面的說明,可以清晰的分析出結(jié)果了。
    uploads/200610/01_022322_domranges7.gif


    克隆(clone)Range

    這個(gè)操作很簡(jiǎn)單,只需要一句語句即可:
    var oNewRange = oRange.cloneRange();

    cloneRange()方法將返回一個(gè)當(dāng)前Range的副本,當(dāng)然,它也是Range對(duì)象。

    清除Range所占的系統(tǒng)資源

    當(dāng)你創(chuàng)建了Range對(duì)象最好用detach()方法來清除它所占的系統(tǒng)資源。雖然不清除,GC(垃圾收集器)也會(huì)將其收集,但用detach()釋放是一個(gè)好習(xí)慣。語法為:
    oRange.detach();

    下面一個(gè)示例在Mozilla中,利用Range可以模擬出IE中的element.insertAdjacentHTML()方法,
    if (browser.isMozilla) {
    ?HTMLElement.prototype.insertAdjacentHTML = function (sWhere, sHTML) {
    ?var df; var r = this.ownerDocument.createRange();
    ?switch (String(sWhere).toLowerCase()) {
    ?case "beforebegin":
    ?r.setStartBefore(this);
    ?df = r.createContextualFragment(sHTML);
    ?this.parentNode.insertBefore(df, this);
    ?break;
    ?case "afterbegin":
    ?r.selectNodeContents(this);
    ?r.collapse(true);
    ?df = r.createContextualFragment(sHTML);
    ?this.insertBefore(df, this.firstChild);
    ?break;
    ?case "beforeend":
    ?r.selectNodeContents(this);
    ?r.collapse(false);
    ?df = r.createContextualFragment(sHTML);
    ?this.appendChild(df);
    ?break;
    ?case "afterend":
    ?r.setStartAfter(this);
    ?df = r.createContextualFragment(sHTML);
    ?this.parentNode.insertBefore(df, this.nextSibling);
    ?break;
    ?}
    ?};
    }
    參考文檔:

    Professional JavaScript for Web Developers(Wrox)
    Mozilla Develop Center Document
    posted on 2006-10-24 09:41 Web 2.0 技術(shù)資源 閱讀(322) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 成人黄软件网18免费下载成人黄18免费视频 | 日韩精品在线免费观看| 亚洲精品宾馆在线精品酒店| 国产AV无码专区亚洲AV毛网站| 国产在线98福利播放视频免费| 成人免费激情视频| 国内精品久久久久影院免费| 特级毛片在线大全免费播放| 亚洲精品亚洲人成在线| 91亚洲自偷在线观看国产馆| 亚洲国产精品无码av| 亚洲精品无码久久不卡| 国产人妖ts在线观看免费视频| 国产成人无码免费看视频软件| 一级毛片aaaaaa免费看| 免费网站观看WWW在线观看| 一级黄色免费毛片| 免费手机在线看片| 国产青草亚洲香蕉精品久久| 亚洲精品理论电影在线观看| 亚洲香蕉久久一区二区三区四区| 日韩亚洲Av人人夜夜澡人人爽| 亚洲av永久无码精品网站| 中文字幕亚洲专区| 国产AV无码专区亚洲AV漫画 | 黄页网站在线免费观看| 久久久久亚洲AV无码去区首| 亚洲精品无码成人片久久不卡 | 免费羞羞视频网站| 真实乱视频国产免费观看| 毛片a级三毛片免费播放| 在线观看av永久免费| 我们的2018在线观看免费高清| 国产大片免费网站不卡美女| 国产一卡二卡四卡免费| 日韩亚洲国产高清免费视频| 99国产精品永久免费视频| 国产又黄又爽又猛免费app| 成人黄动漫画免费网站视频 | 久久亚洲精品成人AV| 久久夜色精品国产噜噜亚洲AV|