moveToElementText()

moveToElementText()是動態HTML(DHTML)的高級特性,使用它可以實現很多和文本有關的任務,例如搜尋和選擇文本。

基本介紹

  • 中文名:moveToElementText()
  • 對象:動態HTML(DHTML)
  • 屬性:boundingHeight
  • 方法:moveStart 更改範圍
TextRange對象是動態HTML(DHTML)的高級特性,使用它可以實現很多和文本有關的任務,例如搜尋和選擇文本。文本範圍讓您可以選擇性的將字元、單詞和句子從文檔中挑選出來。TextRange對象是在HTML文檔將要顯示的文本流上建立開始和結束位置的抽象對象。
下面是TextRange的常用屬性與方法:
屬性
boundingHeight 獲取綁定TextRange對象的矩形的高度
boundingLeft 獲取綁定TextRange 對象的矩形左邊緣和包含TextRange對象的左側之間的距離
offsetLeft 獲取對象相對於版面或由offsetParent屬性指定的父坐標的計算左側位置
offsetTop 獲取對象相對於版面或由offsetParent屬性指定的父坐標的計算頂端位置
htmlText 獲取綁定TextRange對象的矩形的寬度
text 設定或獲取範圍內包含的文本
方法
moveStart 更改範圍的開始位置
moveEnd 更改範圍的結束位置
collapse 將插入點移動到當前範圍的開始或結尾
move 摺疊給定文本範圍並將空範圍移動給定單元數
execCommand 在當前文檔、當前選中區或給定範圍上執行命令
select 將當前選擇區置為當前對象
findText 在文本中搜尋文本並將範圍的開始和結束點設定為包圍搜尋字元串。
使用TextRange對象通常包括三個基本的步驟:
1.創建文本範圍
2.設定開始點和結束點
3.對範圍進行操作
Html代碼
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> <script language="javascript"> function moveCursor() {   var temp = this.txtNum.value;   if(isNaN(temp))   {  alert("請輸入一個數字");  return;   }   var rng = this.txtTest.createTextRange();    rng.move("character",temp);   rng.select();  } </script> </HEAD> <BODY> <input type="text" name="txtTest" value="明·羅貫中《三國演義》第二十一回 操曰:“夫英雄者,胸懷大志,腹有良謀,有包藏宇宙之機,吞吐天地之志者也。" size="100"><br> 移動游標到第<input type="text" name="txtNum" size="5">個位置 <input type="button" name="btnMove" value="移動" onclick="moveCursor()"> </BODY> </HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""><META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""><script language="javascript"> function moveCursor(){  var temp = this.txtNum.value;   if(isNaN(temp))  {  alert("請輸入一個數字"); return;  }   var rng = this.txtTest.createTextRange();   rng.move("character",temp);   rng.select(); } </script></HEAD><BODY> <input type="text" name="txtTest" value="明·羅貫中《三國演義》第二十一回 操曰:“夫英雄者,胸懷大志,腹有良謀,有包藏宇宙之機,吞吐天地之志者也。" size="100"><br> 移動游標到第<input type="text" name="txtNum" size="5">個位置 <input type="button" name="btnMove" value="移動" onclick="moveCursor()"> </BODY> </HTML>
1.createTextRange()
創建一個TextRange對象,BODY、TEXT、TextArea、BUTTON等元素都支持這個方法。該方法返回一個TextRange對象。
2.move("Unit"[,count])
move()方法執行兩個操作。首先,方法在前一個結束點的位置重疊當前文檔,將這裡作為一個插入點;下一步,它將插入點向前或向後移動任意個字元、單詞或句子單位。
方法的第一個參數是字元串,它指定的單位有character(字元)、word(詞)、sentence(段落)、textedit。textedit值將插入點移動到整個文本範圍的結束處(不需要參數)。如果指定為前三種單位,忽略參數時默認值為1,也可以指定一個整數值來指示單元數,正數代表向前移動,負數代表向後移動。
注意在move()方法執行後範圍仍是重疊的。
3.select()
select()方法選擇當前文本範圍內的文本,這裡的顯示游標也必須利用它來實現,因為所謂的"游標"可以理解為邊界重合的範圍
搜尋文本中的字元串
Html代碼
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <BODY> <textarea name="txtBox" rows="7" cols="50" id="txtBox"> 菊花台 (滿城盡帶黃金甲主題曲) 歌手:周杰倫 專輯:依然范特西 你的淚光 柔弱中帶傷 慘白的月彎彎 勾住過往 夜太漫長 凝結成了霜 是誰在閣樓上冰冷的絕望 雨輕輕淌 朱紅色的窗 我一生在紙上 被風吹亂 夢在遠方 化成一縷霞 隨風飄散 你的模樣 菊花慘澹地傷 你的笑容已泛黃 花落人斷腸 我心事靜靜淌 北風亂夜未央 你的影子剪不斷 徒留我孤單在湖面生霜 </textarea><br> <input type="text" value="輸入要查詢的內容" id="txtFind"> <input type="button" value="查找下一個" onclick="findText(txtFind.value)"> <script language="javascript"> var rng = txtBox.createTextRange(); function findText(str) {   if(str=="")   return;   //定義一個變數,作為moveStart()函式的偏移量,即開始點跳過選擇文本   var num = 0;   if(document.selection)    num = document.selection.createRange().text.length;   //每次調用函式,結束點都為末尾,而開始點是跳過選擇文本後的新開始點   rng.moveStart("character",num);   rng.moveEnd("character",txtBox.value.length);   //搜尋到後選擇文本    if(rng.findText(str))   rng.select();   //搜尋到最後的範圍還是找不到,則提示搜尋完畢,並重新恢復rng最初的範圍(否則無法執行新搜尋)    if(rng.text!=str)    {    alert("搜尋完畢");   rng = txtBox.createTextRange();   } }  </script> </BODY> </HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""><META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""></HEAD><BODY> <textarea name="txtBox" rows="7" cols="50" id="txtBox">菊花台 (滿城盡帶黃金甲主題曲) 歌手:周杰倫 專輯:依然范特西 你的淚光 柔弱中帶傷 慘白的月彎彎 勾住過往 夜太漫長 凝結成了霜 是誰在閣樓上冰冷的絕望 雨輕輕淌 朱紅色的窗 我一生在紙上 被風吹亂 夢在遠方 化成一縷霞 隨風飄散 你的模樣 菊花慘澹地傷 你的笑容已泛黃 花落人斷腸 我心事靜靜淌 北風亂夜未央 你的影子剪不斷 徒留我孤單在湖面生霜 </textarea><br> <input type="text" value="輸入要查詢的內容" id="txtFind"> <input type="button" value="查找下一個" onclick="findText(txtFind.value)"> <script language="javascript">var rng = txtBox.createTextRange(); function findText(str){  if(str=="")  return;   //定義一個變數,作為moveStart()函式的偏移量,即開始點跳過選擇文本  var num = 0;   if(document.selection)    num = document.selection.createRange().text.length;   //每次調用函式,結束點都為末尾,而開始點是跳過選擇文本後的新開始點   rng.moveStart("character",num);   rng.moveEnd("character",txtBox.value.length);   //搜尋到後選擇文本    if(rng.findText(str))  rng.select();   //搜尋到最後的範圍還是找不到,則提示搜尋完畢,並重新恢復rng最初的範圍(否則無法執行新搜尋)    if(rng.text!=str)    {    alert("搜尋完畢");   rng = txtBox.createTextRange();  }}  </script> </BODY> </HTML>
上面的例子演示了利用moveStart()和moveEne()方法選擇範圍,出現的幾個方法的說明如下:
4.moveStart("Unit"[,count])與moveEnd("Unit"[,count])
moveStart()與moveEnd()方法類似於move()方法,默認情況下開始點為容器第一個字元、結束點為最後一個字元
我們可以修改上面的selectText()函式來證明:
function selectText()
{
var rng = txtBox.createTextRange();
rng.moveStart("character",1);
rng.moveEnd("character",-1);
rng.select();
}
將開始點向前移動一個字元、結束點向後移動一個字元,運行後可以看到選擇的範圍是除第1個字元和最後1個字元的整個文本範圍。
5.collapse([Boolean])
可以用collapse()方法把文本範圍從當前尺寸重疊成字元間的單個插入點。collapse()方法的可選參數是Boolean值,它指出範圍是在當前範圍的開始點重合,還是結束點重合。默認值為true,在開始點重合:
5.findText("searchString"[,searchScope,flags])
TextRange對象最有用的方法之一是findText()方法,其默認行為是從開始點到結束點瀏覽文本範圍,搜尋一個不區分大小寫的字元串匹配。如果在範圍中發現一個實例,範圍的開始點和結束點就放到這個文本中,方法返回true;否則返回false,開始點和結束點都不動。方法僅搜尋顯示文本,而任何標記或屬性都不會被搜尋。
可選參數searchScope是一個整數值,它指示從開始點的字元數,值越大,包含在搜尋範圍的文本越多;負值將迫使搜尋操作從當前開始點向後搜尋。
可選參數flag用來設定搜尋是否區分大小寫,或者是否僅匹配整個單詞。參數是整數值,它用按位組合的數學方法計算單個值,這些值能容納一個或多個設定。匹配整個單詞的值為2;匹配大小寫的值為4;如果只想匹配一項,則只提供希望的值就夠了,但對於兩種行為,要用位操作XOR操作符(^操作符)使值為6。
findText()方法最常用的套用包括範圍中的查找和替換操作,以及格式化一個字元串的實例,因為搜尋通常以範圍的當前開始點開始,所以再次查詢要將開始點移到範圍中匹配文本的末尾(如示例3),移動後才能使findText()繼續瀏覽剩下的文本範圍,來查找另一個匹配。可以使用collapse(false)方法迫使開始點移動第一個匹配的範圍的結束點。所以示例3的findText()函式也可以修改為:
<script language="javascript">
var rng = txtBox.createTextRange();
function findText(str)
{
if(str=="")
return;
if(rng.findText(str))
{
rng.select();
rng.collapse(false);
}
//搜尋到最後的範圍還是找不到,則提示搜尋完畢,並重新恢復rng最初的範圍(否則無法執行新搜尋)
else
{
alert("搜尋完畢");
rng = txtBox.createTextRange();
}
}
</script>
6.parentElement()
parentElement()方法返回包含文本範圍容器的引用
獲得游標選中文本的DOM對象
Html代碼
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> <script> function getParElem() { var rng = document.selection.createRange(); var container = rng.parentElement(); //alert(container.getAttribute("id")||container.getAttribute("value")||container.getAttribute("type")); alert(container.tagName); } </script> </HEAD> <BODY> 這是只屬於Body的文本 <div>這是包含在div里的文本</div> <p>這是包含在p裡面的文本</p> <div><strong>這是包含在div->strong里的文本</strong></div> <input type="button" value="選擇文本後點擊" onClick="getParElem()"> </BODY> </HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""><META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""><script>function getParElem(){ var rng = document.selection.createRange(); var container = rng.parentElement(); //alert(container.getAttribute("id")||container.getAttribute("value")||container.getAttribute("type")); alert(container.tagName);}</script></HEAD><BODY> 這是只屬於Body的文本<div>這是包含在div里的文本</div><p>這是包含在p裡面的文本</p> <div><strong>這是包含在div->strong里的文本</strong></div> <input type="button" value="選擇文本後點擊" onClick="getParElem()"></BODY> </HTML>
Range對象
Range對象表示文檔的連續範圍區域,如用戶在瀏覽器視窗中用滑鼠拖動選中的區域。
dom標準Range對象
在ie中使用TextRange對象
range對象常用的建立方法
在開發中除了上述文檔中的標準建立方法,大多如下方式建立
標準dom:
var range=window.getSelection().getRangeAt(0);
ie:
var range=document.selection.createRange();
注意:標準dom是從window中獲取selection對象,而ie是從document對象中獲取。
標準dom range對象(以下稱dom rang)和ie的TextRange對象(以下稱TextRange),在操作模式上有很大區別,可以說dom range是基於dom結構控制的,TextRange是基於文本節點位元組控制的,閱讀下面示例會更好理解這二者的操作模式。以下所說的range對象是指在html結構中進行選擇和更改(designMode=on contentEditable=true狀態下)操作,在textarea中的操作比這簡單,不是當前的研究環境。
range對象的具體方法和屬性請查看上邊列出的相關api文檔,下面對實際開發過程中常用功能講解
1.區域選擇 獲取區域中文本
TextRange的區域選擇
TextRange對象主要使用以下方法控制區域的選擇:moveStart moveEnd move
這三個函式使用相同的參數語法:fn(sUnit [, iCount])
第一個參數是指移動的單位,可以使用的參數:character(字元)、word(詞)、sentence(段落)、textedit(整個編輯區)
第二個參數指移動的數量單位,負數向所在位置之前移動,正數向所在位置之後移動。
在實際開發中一般使用character,其他幾個參數在中文環境和html編輯時,和預想位置有偏差。
例1:TextRange選擇游標前4個字元
代碼如下:
var rg=document.selection.createRange();
rg.moveStart("character",-4);
rg.select();//顯式選擇文本區域,不調用此函式也可以獲得選擇的內容
var text=rg.text;//獲得選擇的文本
var htmlText=rg.htmlText;//獲得選擇文本的html代碼
用rg.htmlText獲得選擇文本的html代碼,但獲得結果不盡人意,
如:<b>aaaa</b>bb ,當選擇aabb段時,.htmlTex返回的是<b>aa</b>bb而不是aa</b>bb
其他常用位置控制函式:
collapse: 合併前後選擇點,true為開始點,false為結尾點。
moveToPoint: 移動游標到坐標 moveToBookmark: 移動到書籤。
dom range的區域選擇
dom range對象選擇區域主要以dom節點為為坐標,所有邊界移動和區域選擇函式都是以dom節點為參照的
setEnd()setStart()是控制範圍的前邊界點和後邊界點位置的函式,
有兩個參數,第一個參數是dom節點,第二個參數是偏移量,這個參數和TextRange.move中不同,是相對於dom節點的偏移量。
如:有文位元組點node1 nodeValue是aaabbbccc,setStart(node1,3)則設定開始位置在字元a、b之間
那如何像例1一樣選擇游標前4個字元呢,這需要了解dom range對象的幾個屬性:
endContainer 包含範圍的結束點的 dom節點。
endOffset endContainer 中的結束點位置。
startContainer 包含範圍的開始點的 dom節點。
startOffset startContainer 中的開始點位置。
例2:dom range選擇游標前4個字元
代碼如下:
var rg=window.getSelection().getRangeAt(0);
rg.setStart(rg.startContainer,rg.startOffset-4);//獲得當前range strat所在節點和偏移量,計算後作為參數
//在調用setStart後即顯式選擇,與TextRange不同
var text=rg.toString();//獲得選擇文本
rg.collapse(false);//collapse函式與TextRange.collapse相同
例2中range選擇範圍操作適用於單一的文本內容,如果是html內容就需要進一步計算才能正確得到,總的來看dom range在複雜dom結 構中進行相對範圍選擇是比較麻煩的。
另外,dom range沒有直接的方法獲得選擇內容的html代碼。在html可編輯狀態下可以通過surroundContents()方法用一個span之類的標籤包裹住內容後再通過innerHTML獲得內容,但是在選擇範圍邊界點在html開始和結束標籤內時(如:<a>123</a>邊界點在a標籤內)會拋出一個異常。
以下是測試用完整代碼,包含例1和例2的代碼和一個測試用html可編輯區。
代碼如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!--
window.onload=function(){
var iframeContent="";
var divContent="";
var divChange=false;
var iframeChange=false;
var $=function(s){return document.getElementById(s);}
$("ifram_div").innerHTML+='<div id="infoIframe">iframe</div><iframe id="youretextarea" style="height:200px;width:99%;" class="_editbox"></iframe>';
var fw=$("youretextarea").contentWindow;
var f=fw.document;
f.designMode = 'On';
f.contentEditable = true;
f.open();
f.writeln('<html><style>p{margin:0px;padding:0px;}body{margin:0px;padding:0px;font:16/18px Arial;}</style><body><b>aaaa</b><u>bbbb</u>cccddd</body></html>');
f.close();
if(f.attachEvent){
f.attachEvent("onkeyup",fun1);
}else{
fw.addEventListener("keyup",fun1,true);
}
function fun1(){
if(f.selection){
var rg=f.selection.createRange();
rg.moveStart("character",-4);
//rg.select();//顯式選擇文本區域,不調用此函式也可以獲得選擇的內容
var text=rg.text;//獲得選擇的文本
var htmlText=rg.htmlText;//獲得選擇文本的html代碼
alert(text);
}else{
var rg=fw.getSelection().getRangeAt(0);
rg.setStart(rg.startContainer,rg.startOffset-4);//獲得當前range strat所在節點和偏移量,計算後作為參數
//在調用setStart後即顯式選擇,與TextRange不同
var text=rg.toString();//獲得選擇文本
rg.collapse(false);//collapse函式與TextRange.collapse相同
alert(text);
}
}
}
//-->
</SCRIPT>
<div id="ifram_div"></div>
</BODY>
</HTML>
2.插入文本
TextRange插入文本
使用TextRang插入文本比較簡單,直接調用pasteHTML()方法就可以直接插入html代碼。
Dom Range插入文本
使用Dom Range插入文本相對複雜一些,Dom Range對象使用insertNode()方法實現插入,但是insertNode是在Range的開始位置插入一 個節點,參數是一個節點而不是字元串,我們可以通過插入文本節點實現,如果使用document.createTextNode建立文本節點,文本中的HTML標記會自動轉換,但空格是個特例,並不會自動轉換為 ,這使我在開發代碼縮進時很頭疼,最後解決的辦法,是使用Rang.createContextualFragment,這個方法雖然在文檔中沒有找到,但測試多個瀏覽器都支持此方法,此方法返回的是一個DocumentFragment對
象。以下是示例代碼:
例3:
Js代碼
代碼如下:
var rg = window.getSelection().getRangeAt(0);
var fragment = rg.createContextualFragment(str);
rg.insertNode(fragment);
這段代碼雖然實現插入了文本,但是游標位置卻在插入文本之前,因為“insertNode是在Range的開始位置插入一 個節點”,接下來我們實現游標的控制,這需要設定Range對象的位置,並更新Selection對象的Range,代碼如下:
例4:
Js代碼
代碼如下:
var selection=window.getSelection();
var rg=selection.getRangeAt(0);
var fragment = rg.createContextualFragment(str);
var oLastNode = fragment.lastChild; //獲得DocumentFragment的末尾位置
rg.insertNode(fragment);
rg.setEndAfter(oLastNode);//設定末尾位置
rg.collapse(false);//合併範圍至末尾
selection.removeAllRanges();//清除range
selection.addRange(rg);//設定range
以下是一個代碼縮進功能的部分代碼作為示例:按tab鍵時會在當前位置,插入4個空格,解決在編輯時不能輸入tab的問題。實際套用中的功能包括多行縮進和自動縮進。
代碼如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!--
window.onload=function(){
var iframeContent="";
var divContent="";
var divChange=false;
var iframeChange=false;
var $=function(s){return document.getElementById(s);}
$("ifram_div").innerHTML+='<div id="infoIframe">iframe</div><iframe id="youretextarea" style="height:200px;width:99%;" class="_editbox"></iframe>';
var fw=$("youretextarea").contentWindow;
var f=fw.document;
f.designMode = 'On';
f.contentEditable = true;
f.open();
f.writeln('<html><style>p{margin:0px;padding:0px;}body{margin:0px;padding:0px;font:16/18px Arial;}</html>');
f.close();
if(f.attachEvent){
f.attachEvent("onkeydown",fun1);
}else{
fw.addEventListener("keydown",fun1,true);
}
function fun1(e){
ee=e||window.event;
var code=e.charCode||e.keyCode;
var strTab=" ";
if(code==9){//tab鍵
if(f.selection){//ie
e.returnValue=false;//取消瀏覽器默認動作 ie
var rg=f.selection.createRange();
rg.pasteHTML(strTab);
}else{
e.preventDefault();//取消瀏覽器默認動作
var selection=fw.getSelection();
var rg=selection.getRangeAt(0);
var fragment = rg.createContextualFragment(strTab);
var oLastNode = fragment.lastChild; //獲得DocumentFragment的末尾位置
rg.insertNode(fragment);
rg.setEndAfter(oLastNode);//設定末尾位置
rg.collapse(false);//合併範圍至末尾
selection.removeAllRanges();//清除range
selection.addRange(rg);//設定range
}
}
}
}
//-->
</SCRIPT>
<div id="ifram_div"></div>
</BODY>
</HTML>
3.替換
綜合介紹的選擇和插入的方法可完成替換功能,TextRange比較簡單pasteHTML方法會替換原來Range選中的文本,Dom Range的insertNode不會刪除原range選中內容,需要調用deleteContents()方法先刪除選擇內容。

相關詞條

熱門詞條

聯絡我們