单击仅工作一次

Single-click only works once

本文关键字:一次 工作 单击      更新时间:2023-09-26

我想允许用户通过单击鼠标来删除div中的单词。它工作正常,请参阅 jsFiddle

唯一的问题是单击功能仅在第一次单击时有效。之后,您需要双击。

我无法理解为什么它会这样。也许你可以?可能是jQuery(document).ready()的问题...

j查询:

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

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


.HTML

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


爪哇语

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

发现主要问题是因为如果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 上测试了很多次,它工作正常,但是我仍然担心这会导致其他一些问题。

如果您遇到问题,请通知我,我会提供帮助。

编辑:

js小提琴