2010-03-19 18 views
10

我正在開發一個類似於Web應用程序的富文本編輯器,基本上是一個用JavaScript編寫的XML編輯器。使用javascript擴展DOM範圍以覆蓋部分選定的節點

我的javascript代碼需要從contentEditable div容器中包裝選定的節點。 我正在使用MDC中描述的方法。但因爲我需要到div容器的內容同步到我的XML DOM我想避免在w3c ranges描述部分選擇:

<BODY><H1>Title</H1><P>Blah xyz.</P></BODY

............^----------------^............

這裏面選擇H1開始,內部P結束,我希望它完全包含H1,P。

是否有一種簡單的方法可以將選擇擴展到完全覆蓋部分選定的孩子? 基本上我想使用range.surroundContents()而不會遇到異常。

(代碼不需要與歌劇/ IE工作)

回答

8

望着MDC的文檔,我設法做這樣的事情:

Selection.prototype.coverAll = function() { 
    var ranges = []; 
    for(var i=0; i<this.rangeCount; i++) { 
     var range = this.getRangeAt(i); 
     while(range.startContainer.nodeType == 3 
       || range.startContainer.childNodes.length == 1) 
      range.setStartBefore(range.startContainer); 
     while(range.endContainer.nodeType == 3 
       || range.endContainer.childNodes.length == 1) 
      range.setEndAfter(range.endContainer); 
     ranges.push(range); 
    } 
    this.removeAllRanges(); 
    for(var i=0; i<ranges.length; i++) { 
     this.addRange(ranges[i]); 
    } 
    return; 
}; 

你可以在這裏嘗試一下:http://jsfiddle.net/GFuX6/9/

編輯: 更新讓瀏覽器正確顯示增強選擇。即使選擇包含多個範圍(使用Ctrl),它也會按照您的要求進行操作。

要使多個部分節點大膽,這裏是一個解決辦法:我最後的代碼在http://jsfiddle.net/wesUV/21/上前

Selection.prototype.boldinize = function() { 
    this.coverAll(); 
    for(var i=0; i<this.rangeCount; i++) { 
     var range = this.getRangeAt(i); 
     var parent = range.commonAncestorContainer; 
     var b = document.createElement('b'); 
     if(parent.nodeType == 3) { 
      range.surroundContents(b); 
     } else { 
      var content = range.extractContents(); 
      b.appendChild(content); 
      range.insertNode(b); 
     } 
    } 
}; 
+0

確實,但我認爲這是正確的軌道。我會嘗試從具有這些屬性的原始選擇中創建一個自定義選擇。 – 2010-03-19 12:55:40

+0

我會延長我的問題,使其更清晰。 此外,我更新了http://jsfiddle.net/GFuX6/5/ – 2010-03-19 13:21:28

+0

的示例選擇一些文本,按下轉義,文本變爲粗體。在小提琴中有很長的一行:''window.getSelection()。getRangeAt(0).surroundContents(tag);' 當前小提琴擴展了文本節點的邊界,但我無法找到一種方法來部分覆蓋包括節點。 – 2010-03-19 13:30:50

0

如果你的意思是你要包括標籤H1和P(即有效的標記),不用擔心。你可以免費獲得。如果你的意思是你想要包含(部分)選擇內的所有內容,你需要訪問Selection對象。請閱讀Quirksmode's introduction to Range

+0

像怪異模式分析文章指出,瀏覽器將修復了「無效」 HTML:「瀏覽器添加HTML的最低量,使範圍內有效」。我寧願沒有無效的選擇開始;) – 2010-03-19 12:49:26

0

感謝Alsciende。 這種方法不像其他方法那麼貪婪。在coverAll()之後,surroundContents()應該始終工作。

Selection.prototype.coverAll = function() { 
    var ranges = []; 
    for(var i=0; i<this.rangeCount; i++) { 
    var range = this.getRangeAt(i); 
    var ancestor = range.commonAncestorContainer; 
    if (ancestor.nodeType == 1) {    
     if (range.startContainer.parentNode != ancestor && this.containsNode(range.startContainer.parentNode, true)) { 
      range.setStartBefore(range.startContainer.parentNode); 
     } 
     if (range.endContainer.parentNode != ancestor && this.containsNode(range.endContainer.parentNode, true)) { 
       range.setEndAfter(range.endContainer.parentNode); 
     } 
    } 
    ranges.push(range); 
    } 
    this.removeAllRanges(); 
    for(var i=0; i<ranges.length; i++) { 
    this.addRange(ranges[i]); 
    } 
    return; 
}; 

而且boldinize功能:

Selection.prototype.boldinize = function() { 
    for(var i=0; i<this.rangeCount; i++) {   
    var range = this.getRangeAt(i); 
    var b = document.createElement('b'); 
    try { 
     range.surroundContents(b); 
    } catch (e) { 
     alert(e); 
    } 
    } 
};