2016-04-25 129 views
0

我想允許用戶刪除一個div中的單詞單個鼠標單擊。它工作正常,請參閱jsFiddle單擊一次只能工作一次

唯一的問題是,單擊功能只適用於第一個點擊。之後,你需要雙擊。

我無法理解爲什麼它的行爲如此。也許你可以?可能是問題jQuery(document).ready() ...

的jQuery:

// highlight a word/term quicker and smarter: so.com/a/35103840/1185126 
jQuery(document).ready(function(e){ 

    (function(els){ 

     // variable declaration for previous range info 
     // and function for finding the sibling 
     var prevRangeInfo = {}, 
      findSibling = function(thisNode, direction){ 
       // get the child node list of the parent node 
       var childNodeList = thisNode.parentNode.childNodes, 
        children = []; 

       // convert the child node list to an array 
       for(var i=0, l=childNodeList.length; i<l; i++) children.push(childNodeList[i]); 

       return children[children.indexOf(thisNode) + direction]; 
      }; 

     for(var i=0;i<els.length;i++){ 
      var el = els[i]; 

      el.addEventListener('mouseup',function(evt){ 
       if (document.createRange) { // Works on all browsers, including IE 9+ 

        var selected = window.getSelection(); 
        // Removing the following line from comments will make the function drag-only 
        /* if(selected.toString().length){ */ 
        var d = document, 
         nA = selected.anchorNode, 
         oA = selected.anchorOffset, 
         nF = selected.focusNode, 
         oF = selected.focusOffset, 
         range = d.createRange(), 
         rangeLength = 0; 

        range.setStart(nA,oA); 
        range.setEnd(nF,oF); 

        // Check if direction of selection is right to left 
        if(range.startContainer !== nA || (nA === nF && oF < oA)){ 
         range.setStart(nF,oF); 
         range.setEnd(nA,oA); 
        } 

        // Extend range to the next space or end of node 
        while(range.endOffset < range.endContainer.textContent.length && !/\s$/.test(range.toString())){ 
         range.setEnd(range.endContainer, range.endOffset + 1); 
        } 
        // Extend range to the previous space or start of node 
        while(range.startOffset > 0 && !/^\s/.test(range.toString())){ 
         range.setStart(range.startContainer, range.startOffset - 1); 
        } 

        // Remove spaces 
        if(/\s$/.test(range.toString()) && range.endOffset > 0) 
         range.setEnd(range.endContainer, range.endOffset - 1); 
        if(/^\s/.test(range.toString())) 
         range.setStart(range.startContainer, range.startOffset + 1); 

        // Store the length of the range 
        rangeLength = range.toString().length; 

        // Check if another range was previously selected 
        if(prevRangeInfo.startContainer && nA === nF && oA === oF){ 
         var rangeTryContain = d.createRange(), 
          rangeTryLeft = d.createRange(), 
          rangeTryRight = d.createRange(), 
          nAp = prevRangeInfo.startContainer; 
         oAp = prevRangeInfo.startOffset; 
         nFp = prevRangeInfo.endContainer; 
         oFp = prevRangeInfo.endOffset; 

         rangeTryContain.setStart(nAp, oAp); 
         rangeTryContain.setEnd(nFp, oFp); 
         rangeTryLeft.setStart(nFp, oFp-1); 
         rangeTryLeft.setEnd(range.endContainer, range.endOffset); 
         rangeTryRight.setStart(range.startContainer, range.startOffset); 
         rangeTryRight.setEnd(nAp, oAp+1); 

         // Store range boundary comparisons 
         // & inner nodes close to the range boundary --> stores null if none 
         var compareStartPoints = range.compareBoundaryPoints(0, rangeTryContain) === 0, 
          compareEndPoints = range.compareBoundaryPoints(2, rangeTryContain) === 0, 
          leftInnerNode = range.endContainer.previousSibling, 
          rightInnerNode = range.startContainer.nextSibling; 

         // Do nothing if clicked on the right end of a word 
         if(range.toString().length < 1){ 
          range.setStart(nAp,oAp); 
          range.setEnd(nFp,oFp); 
         } 

         // Collapse the range if clicked on last highlighted word 
         else if(compareStartPoints && compareEndPoints) 
          range.collapse(); 

         // Remove a highlighted word from left side if clicked on 
         // This part is quite tricky! 
         else if(compareStartPoints){ 
          range.setEnd(nFp,oFp); 

          if(range.startOffset + rangeLength + 1 >= range.startContainer.length){ 
           if(rightInnerNode) 
           // there is a right inner node, set its start point as range start 
            range.setStart(rightInnerNode.firstChild, 0); 

           else { 
            // there is no right inner node 
            // there must be a text node on the right side of the clicked word 

            // set start of the next text node as start point of the range 
            var rightTextNode = findSibling(range.startContainer.parentNode, 1), 
             rightTextContent = rightTextNode.textContent, 
             level=1; 

            // if beginning of paragraph, find the first child of the paragraph 
            if(/^(?:\r\n|[\r\n])|\s{2,}$/.test(rightTextContent)){ 
             rightTextNode = findSibling(rightTextNode, 1).firstChild; 
             level--; 
            } 

            range.setStart(rightTextNode, level); 

           } 
          } 
          else 
           range.setStart(range.startContainer, range.startOffset + rangeLength + 1); 
         } 

         // Remove a hightlighted word from right side if clicked on 
         // This part is also tricky! 
         else if (compareEndPoints){ 
          range.setStart(nAp,oAp); 

          if(range.endOffset - rangeLength - 1 <= 0){ 
           if(leftInnerNode) 
           // there is a right inner node, set its start point as range start 
            range.setEnd(leftInnerNode.lastChild, leftInnerNode.lastChild.textContent.length); 

           else { 
            // there is no left inner node 
            // there must be a text node on the left side of the clicked word 

            // set start of the previous text node as start point of the range 
            var leftTextNode = findSibling(range.endContainer.parentNode, -1), 
             leftTextContent = leftTextNode.textContent, 
             level = 1; 

            // if end of paragraph, find the last child of the paragraph 
            if(/^(?:\r\n|[\r\n])|\s{2,}$/.test(leftTextContent)){ 
             leftTextNode = findSibling(leftTextNode, -1).lastChild; 
             level--; 
            } 

            range.setEnd(leftTextNode, leftTextNode.length - level); 
           } 
          } 
          else 
           range.setEnd(range.endContainer, range.endOffset - rangeLength - 1); 
         } 

         // Add previously selected range if adjacent 
         // Upgraded to include previous/next word even in a different paragraph 
         else if(/^[^\s]*((?:\r\n|[\r\n])|\s{1,})[^\s]*$/.test(rangeTryLeft.toString())) 
          range.setStart(nAp,oAp); 
         else if(/^[^\s]*((?:\r\n|[\r\n])|\s{1,})[^\s]*$/.test(rangeTryRight.toString())) 
          range.setEnd(nFp,oFp); 

         // Detach the range objects we are done with, clear memory 
         rangeTryContain.detach(); 
         rangeTryRight.detach(); 
         rangeTryLeft.detach(); 
        } 

        // Save the current range --> not the whole Range object but what is neccessary 
        prevRangeInfo = { 
         startContainer: range.startContainer, 
         startOffset: range.startOffset, 
         endContainer: range.endContainer, 
         endOffset: range.endOffset 
        }; 

        // Clear the saved range info if clicked on last highlighted word 
        if(compareStartPoints && compareEndPoints) 
         prevRangeInfo = {}; 

        // Remove all ranges from selection --> necessary due to potential removals 
        selected.removeAllRanges(); 

        // Assign the current range as selection 
        selected.addRange(range); 

        // Detach the range object we are done with, clear memory 
        range.detach(); 

        el.style.MozUserSelect = '-moz-none'; 

        // Removing the following line from comments will make the function drag-only 
        /* } */ 

       } else { 
        // Fallback for Internet Explorer 8 and earlier 
        // (if you think it still is worth the effort of course) 
       } 
      }); 

      /* This part is necessary to eliminate a FF specific dragging behavior */ 
      el.addEventListener('mousedown',function(e){ 
       if (window.getSelection) { // Works on all browsers, including IE 9+ 
        var selection = window.getSelection(); 
        selection.collapse (selection.anchorNode, selection.anchorOffset); 
       } else { 
        // Fallback for Internet Explorer 8 and earlier 
        // (if you think it still is worth the effort of course) 
       } 
       el.style.MozUserSelect = 'text'; 
      }); 

     } 
    })(document.getElementsByClassName('taggable')); 

}); 




// remove selected text 
jQuery(document).ready(function() { 
    jQuery('.taggable').bind("mouseup", function() { 
    var text1; 
     if (window.getSelection().toString() != "") { 
      selectedText = window.getSelection().toString() 
      text1 = jQuery(".taggable").text().split("") 
      pointStart = window.getSelection().anchorOffset 
      pointEnd = window.getSelection().focusOffset 

      if (pointEnd < pointStart) { 
       pointStart = pointEnd 
      } 
      text1.splice(pointStart, selectedText.length); 
      text1 = text1.join("") 
     } else { 
      selectedText = jQuery(".taggable").text() 
      text1 = selectedText; 
     } 
    jQuery(".taggable").text(text1); 

    }); 
}); 
+1

鑑於這一問題的相對複雜性,我將與50點一次合格賞金它。 –

+0

控制檯中的錯誤怎麼樣?你有調查嗎? '未捕獲的WrongDocumentError:未能在'Range'上執行'compareBoundaryPoints':源範圍與此範圍不在同一個文檔中。' –

+0

我得到的'argument'不是第一次單擊後的對象。你知道如何解決這個問題嗎? –

回答

0

這可能不是解決您的問題,但它的另一種方法。
此代碼將每個單詞包含在一個範圍內併爲每個單詞創建一個事件偵聽器。


HTML

<p>This is an example text</p> 


的Javascript

jQuery(document).ready(function($) { 
    var text = $('p').text(); 
    var arr = text.split(' '); 

    $('p').html(''); 

    for (var i = 0; i < arr.length; i++) { 
     $('<span />').html(arr[i] + ' ').appendTo('p'); 

     $('p').on('click', 'span:nth-of-type(' + (i + 1) + ')', function() { 
      $(this).remove(); 
     }); 
    } 
}); 
+0

這是一個小提琴https:// jsfiddle。net/e1mvekpx/8/ –

0

我已經想通了,主要問題是因爲如果anchorOffset等於focusOffset,這是行不通的,那麼,可能的解決方案是在相等時添加+1,然後代碼將按需要工作,因爲子字符串時至少會找到一個字母。從

var selected = window.getSelection(); 
        // Removing the following line from comments will make the function drag-only 
        /* if(selected.toString().length){ */ 
        var d = document, 
         nA = selected.anchorNode, 
         oA = selected.anchorOffset, 
         nF = selected.focusNode, 
         oF = selected.focusOffset, 
         range = d.createRange(), 
         rangeLength = 0; 

var selected = window.getSelection(); 
        var offset = selected.focusOffset; 
        if(selected.anchorOffset == selected.focusOffset) 
          offset++; 
        // Removing the following line from comments will make the function drag-only 
        /* if(selected.toString().length){ */ 
        var d = document, 
         nA = selected.anchorNode, 
         oA = selected.anchorOffset, 
         nF = selected.focusNode, 
         oF = offset, 
         range = d.createRange(), 
         rangeLength = 0; 

我在這裏JFiddle多次測試和它的工作不錯,但 我還是擔心這會導致:更改代碼一些其他問題。

如果您遇到問題,請通知我,我會幫忙。

編輯:

jsFiddle

+0

你能否提供一個jsFiddle與你的修復程序,以便我可以測試這個?謝謝。 –

+0

它有效嗎? – Rickedb