Firefox双击带有下一个空格的选定文本。如何使用javascript删除屏幕上的结尾空间。
非常感谢。

最佳答案

以下解决方案确实删除了Windows浏览器中双击时选择的尾随空白字符,从而在某种程度上模拟了Firefox的about:config设置layout.word_select.eat_space_to_next_word设置为“false”。

是否“在屏幕上而不是变量中”。

已在Chrome 60.0.3112.113,Firefox 55.0.3,IE8和IE Edge(14)中进行测试。
它仍然有时可见从多余的空间,但没有选择收缩,可说来完成。

适用于任意文本和输入/文本区域(需要完全不同的方法)。

使用jQuery

(function() {
var lastSelEvent = null;
var lastSelInputEvent = null;
var lastDblClickEvent = null;
var selchangeModTs = null;

$(document).on('selectstart selectionchange', function (e) //not input/textarea case
{
    fixEventTS(e);
    lastSelEvent = e;

    if (( selchangeModTs != null) && (new Date().getTime() - selchangeModTs < 50)) //without this we get infinite loop in IE11+ as changing selection programmatically apparently generates event itself...
        return;

    handleSelEvent(e);
});

$(document).on('select', function (e) //input/textarea
{
    fixEventTS(e);
    lastSelInputEvent = e;
    handleSelEvent(e);
});

$(document).on('dblclick',function(e)
{
    fixEventTS(e);
    lastDblClickEvent = e;
    handleSelEvent(e);
});

function fixEventTS(e)
{
    if (typeof e.timeStamp == 'undefined') //IE 8 no timestamps for events...
    {
        e.timeStamp = new Date().getTime();
    }
}

function handleSelEvent(e)
{
    if (lastDblClickEvent===null)
        return;

    if ( ((e.type==='selectstart') || (e.type==='selectionchange') || (e.type==='dblclick')) && (lastSelEvent != null) && (Math.abs(lastDblClickEvent.timeStamp - lastSelEvent.timeStamp) < 1000) ) // different browsers have different event order so take abs to be safe...
    {
        switch (lastSelEvent.type)
        {
            case 'selectstart':
                setTimeout(handleSelChange,50); //IE8 etc fix, selectionchange is actually only change, not selection "creation"
            break;
            case 'selectionchange':
                handleSelChange();
            break;
        }
    }

    if ( ((e.type==='select') || (e.type==='dblclick')) && (lastSelInputEvent != null) && (Math.abs(lastDblClickEvent.timeStamp - lastSelInputEvent.timeStamp) < 1000) ){
        handleSel(lastSelInputEvent);
    }
}

function handleSel(e)
{
    //right whitespace
    while (/\s$/.test(e.target.value.substr(e.target.selectionEnd - 1, 1)) && e.target.selectionEnd > 0) {
        e.target.selectionEnd -= 1;
    }
    //left whitespace
    while (/\s$/.test(e.target.value.substr(e.target.selectionStart, 1)) && e.target.selectionStart > 0) {
        e.target.selectionStart += 1;
    }
}

function handleSelChange() {
    var sel = null;

    if (typeof window.getSelection == 'function') // modern browsers
        sel = window.getSelection();
    else if (typeof document.getSelection == 'function')
        sel = document.getSelection();

    if (sel && !sel.isCollapsed) {
        var range = sel.getRangeAt(0); //have to use range instead of more direct selection.expand/selection.modify as otherwise have to consider selection's direction in non-doubleclick cases
        if (range.endOffset > 0 && (range.endContainer.nodeType===3) && (range.endContainer.textContent != ''/*otherwise rightside pictures get deleted*/))
        {
            //right whitespaces
            while ( /[\s\S]+\s$/.test(range.endContainer.textContent.substr(0,range.endOffset)) ) { //have to use instead of range.toString() for IE11+ as it auto-trims whitespaces there and in selection.toString()
                selchangeModTs = new Date().getTime();
                range.setEnd(range.endContainer, range.endOffset - 1);
            }
        }

        if ((range.startContainer.nodeType===3) && (range.startContainer.textContent != '') && (range.startOffset < range.startContainer.textContent.length)) {
            //left whitespaces
            while (/^\s[\s\S]+/.test(range.startContainer.textContent.substr(range.startOffset))) {
                selchangeModTs = new Date().getTime();
                range.setStart(range.startContainer, range.startOffset + 1);
            }
        }
        selchangeModTs = new Date().getTime();
        sel.removeAllRanges(); //IE11+ fix, in Firefox/Chrome changes to range apply to selection automatically
        sel.addRange(range);
    }
    else if (typeof document.selection != 'undefined') //IE 10 and lower case
    {
        var range = document.selection.createRange();
        if (range && range.text && range.text.toString()) {
            while ((range.text != '') && /[\s\S]+\s$/.test(range.text.toString())) {
                selchangeModTs = new Date().getTime();
                range.moveEnd('character', -1);
                range.select();
            }
            while ((range.text != '') && /^\s[\s\S]+/.test(range.text.toString())) {
                selchangeModTs = new Date().getTime();
                range.moveStart('character', 1);
                range.select();
            }
        }
    }
}

})();

如果您不需要旧的IE支持和limitint即可仅删除doubleclick,则可以大大简化该操作,并且只需要处理selectchange和select相应函数的事件即可。(但实际上您无法使用键盘选择东西)

编辑:
使用Rangy lib(https://github.com/timdown/rangy)Core + TextRange进行非输入元素选择修整比我的基本尝试好得多,我的基本尝试只有在endContainer恰好是文本节点时才起作用。选择修整的基本 Action 是
rangy.getSelection().trim()

最少包含
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js
  • https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.min.js
  • https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.min.js

  • Rangy实现还支持三击式全行选择修整
    (function() {
    var lastSelEvent = null;
    var lastSelInputEvent = null;
    var lastDblClickEvent = null;
    var selchangeModTs = null;
    var tripleclickFixBound = false;
    var selStartTimout = null;
    
    $(document).on('selectstart selectionchange', function (e) //non-inputs
    {
        fixEventTS(e);
        lastSelEvent = e;
    
        if ( ( selchangeModTs != null) && (new Date().getTime() - selchangeModTs < 50) ) //ie11+ fix otherwise get self-loop with our selection changes generating this event
            return;
    
        handleSelEvent(e);
    });
    
    if ('onselect' in document.documentElement) {
        $(document).on('select', function (e) //input/textarea
        {
            fixEventTS(e);
            lastSelInputEvent = e;
            handleSelEvent(e);
        });
    }
    
    $(document).on('click',function(e){
        if (typeof e.originalEvent.detail !== 'undefined')
        {
            multiclickHandlerfunction(e);
        }
        else
        {
            fixEventTS(e);
            if (!tripleclickFixBound) {
    
                $(document).on('dblclick', function (e) {
                    fixEventTS(e);
                    selchangeModTs = null;
                    lastDblClickEvent = e;
                    handleSelEvent(e);
                });
                tripleclickFixBound=true;
            }
            if ( (lastDblClickEvent != null) && (e.timeStamp - lastDblClickEvent.timeStamp < 300))
            {
                lastDblClickEvent = e;
                selchangeModTs = null;
                handleSelEvent(e);
            }
        }
    
    });
    
    function multiclickHandlerfunction(e) {
        if (e.originalEvent.detail === 2 || e.originalEvent.detail === 3) {
            fixEventTS(e);
            selchangeModTs = null;
            lastDblClickEvent = e;
            handleSelEvent(e);
        }
    }
    
    function fixEventTS(e)
    {
        if (typeof e.timeStamp == 'undefined') //IE 8
        {
            e.timeStamp = new Date().getTime();
        }
    }
    
    function handleSelEvent(e)
    {
        if (lastDblClickEvent===null)
            return;
    
        if ( ((e.type==='selectstart') || (e.type==='selectionchange') || (e.type==='dblclick') || (e.type==='click')) && (lastSelEvent != null) && (Math.abs(lastDblClickEvent.timeStamp - lastSelEvent.timeStamp) < 1000) ) // different order of events in different browsers...
        {
            switch (lastSelEvent.type)
            {
                case 'selectstart':
                case 'selectionchange':
                    clearTimeout(selStartTimout);
                    selStartTimout = setTimeout(handleSelChange,(/msie\s|trident\/|edge\//i.test(window.navigator.userAgent)?150:0));
                break;
            }
        }
    
        if ( ((e.type==='select') || (e.type==='dblclick') || (e.type==='click')) && (lastSelInputEvent != null) && (Math.abs(lastDblClickEvent.timeStamp - lastSelInputEvent.timeStamp) < 1000) )
        {
            handleSel(lastSelInputEvent);
        }
    }
    
    function handleSel(e)
    {
        if (typeof(e.target.selectionEnd) != 'undefined') {
            //left whitespace
            while (/\s$/.test(e.target.value.substr(e.target.selectionEnd - 1, 1)) && e.target.selectionEnd > 0) {
                e.target.selectionEnd -= 1;
            }
            //right whitespace
            while (/^s/.test(e.target.value.substr(e.target.selectionStart - 1, 1)) && e.target.selectionStart > 0) {
                e.target.selectionStart += 1;
            }
        }
    }
    
    function handleSelChange() {
        var sel = rangy.getSelection();
        if (sel && !sel.isCollapsed) {
            selchangeModTs = new Date().getTime();
            sel.trim();
        }
        else if (typeof document.selection != 'undefined') //IE 10- input/textArea case
        {
            var range = document.selection.createRange();
    
            if (range && range.text && range.text.toString()) {
                while ((range.text != '') && /[\s\S]+\s$/.test(range.text.toString())) {
                    selchangeModTs = new Date().getTime();
                    range.moveEnd('character', -1);
                    range.select();
                }
                while ((range.text != '') && /^\s[\s\S]+/.test(range.text.toString())) {
                    selchangeModTs = new Date().getTime();
                    range.moveStart('character', 1);
                    range.select();
                }
            }
        }
    }
    
    })($,window);
    

    CodePen demo

    关于javascript - Firefox双击所选文本时如何删除末尾空间,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23306561/

    10-12 13:22