2016-04-25 144 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