2010-02-01 857 views
4

有這個網站:如何使用屬性contentEditable刪除div內的HTML元素?

<div id="editable" contentEditable="true" > 
    <span contentEditable="false" >Text to delete</span> 
</div> 

需要的跨度(以及所有文本中)與單個退格鍵刪除,這可能嗎?

+0

請您提供有關在用戶按下退格鍵時會發生什麼的更多信息,例如,脫字符位於文本節點的中間位置或可編輯區域的起始位置。 – 2010-02-01 18:18:23

回答

9

事實證明,這比我想象的要複雜得多。或者我已經做得比它需要更復雜。無論如何,這應該在所有的瀏覽器大工作:

function getLastTextNodeIn(node) { 
    while (node) { 
     if (node.nodeType == 3) { 
      return node; 
     } else { 
      node = node.lastChild; 
     } 
    } 
} 

function isRangeAfterNode(range, node) { 
    var nodeRange, lastTextNode; 
    if (range.compareBoundaryPoints) { 
     nodeRange = document.createRange(); 
     lastTextNode = getLastTextNodeIn(node); 
     nodeRange.selectNodeContents(lastTextNode); 
     nodeRange.collapse(false); 
     return range.compareBoundaryPoints(range.START_TO_END, nodeRange) > -1; 
    } else if (range.compareEndPoints) { 
     if (node.nodeType == 1) { 
      nodeRange = document.body.createTextRange(); 
      nodeRange.moveToElementText(node); 
      nodeRange.collapse(false); 
      return range.compareEndPoints("StartToEnd", nodeRange) > -1; 
     } else { 
      return false; 
     } 
    } 
} 

document.getElementById("editable").onkeydown = function(evt) { 
    var sel, range, node, nodeToDelete, nextNode, nodeRange; 
    evt = evt || window.event; 
    if (evt.keyCode == 8) { 
     // Get the DOM node containing the start of the selection 
     if (window.getSelection && window.getSelection().getRangeAt) { 
      range = window.getSelection().getRangeAt(0); 
     } else if (document.selection && document.selection.createRange) { 
      range = document.selection.createRange(); 
     } 

     if (range) { 
      node = this.lastChild; 
      while (node) { 
       if (isRangeAfterNode(range, node)) { 
        nodeToDelete = node; 
        break; 
       } else { 
        node = node.previousSibling; 
       } 
      } 

      if (nodeToDelete) { 
       this.removeChild(nodeToDelete); 
      } 
     } 
     return false; 
    } 
}; 
+0

不,我需要刪除文本光標左側的元素| – byterussian 2010-02-01 16:27:25

+0

我怎樣才能使這個代碼更加動態通過添加span usnig輸入KeyDown按下並刪除跨度使用退格幫助我,如果可以的話。 – Basbous 2011-07-25 15:14:28

+0

這工作在克羅姆,但不是在Firefox。在Firefox瀏覽器中是否有與節點相關的問題?我需要幫助,請[見附件鏈接](http://jsfiddle.net/C5R8M/7)。 – 2014-06-23 12:00:46

2

因爲要刪除整個元素,這是更好地使contenteditable="false",使瀏覽器不會讓一元素的內容被刪除。

然後你就可以按如下方式使用該屬性在事件處理測試:在最新的Chrome版本

$('#editable').on('keydown', function (event) { 
    if (window.getSelection && event.which == 8) { // backspace 
     // fix backspace bug in FF 
     // https://bugzilla.mozilla.org/show_bug.cgi?id=685445 
     var selection = window.getSelection(); 
     if (!selection.isCollapsed || !selection.rangeCount) { 
      return; 
     } 

     var curRange = selection.getRangeAt(selection.rangeCount - 1); 
     if (curRange.commonAncestorContainer.nodeType == 3 && curRange.startOffset > 0) { 
      // we are in child selection. The characters of the text node is being deleted 
      return; 
     } 

     var range = document.createRange(); 
     if (selection.anchorNode != this) { 
      // selection is in character mode. expand it to the whole editable field 
      range.selectNodeContents(this); 
      range.setEndBefore(selection.anchorNode); 
     } else if (selection.anchorOffset > 0) { 
      range.setEnd(this, selection.anchorOffset); 
     } else { 
      // reached the beginning of editable field 
      return; 
     } 
     range.setStart(this, range.endOffset - 1); 


     var previousNode = range.cloneContents().lastChild; 
     if (previousNode && previousNode.contentEditable == 'false') { 
      // this is some rich content, e.g. smile. We should help the user to delete it 
      range.deleteContents(); 
      event.preventDefault(); 
     } 
    } 
}); 

demo on jsfiddle

+0

確切地解決了我的問題 – Saravanan 2016-09-23 05:14:53

0

似乎在默認情況下工作(沒有任何JavaScript)(我已經與測試61.0.3163.100)。