单击只能使用一次

时间:2016-04-25 11:22:41

标签: javascript jquery

我想允许用户通过单个鼠标单击删除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);

    });
});

2 个答案:

答案 0 :(得分:0)

这可能无法解决您的问题,但这是另一种方法。
此代码将每个单词包装在一个span中,并为每个单词创建一个事件监听器。


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();
        });
    }
});

答案 1 :(得分: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