如何修改从左到右的选择白色 space

how to modify selection from left to right white space

在下面的示例中,请将光标放在 story 内,例如在字母 b.

之后

单击按钮时,我需要向左和向右扩展选择,直到出现白色 space - 或 start/end 行。
所以应该选择 https://tumblr.com 并在控制台中写入。

我的尝试有问题​​ - 只选择了 tumblr

$(btngo).on('click', function(){
    var sel = window.getSelection();
    sel.modify("move", "backward", "word");
    sel.modify("extend", "right", "word");
    console.log(sel.toString()); // tumblr - I need - https://tumblr.com
});
.story{outline:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='story' id='story' contenteditable>
lorem - https://tumblr.com
</div>
<br>
<button id='btngo'>GO</button>

使用 Javascript Selection, Range and split()

此解决方案将整个文本块拆分为行,然后将行拆分为单词。它首先逐行搜索光标位置,然后,一旦找到该行,就在该行中搜索包含光标的单词。文本块越大,查找和突出显示目标词所需的处理就越多。 请参阅我的其他答案。

将光标放在任何单词中,然后单击“开始”。该词被返回以供进一步处理,并突出显示。如果光标未放在单词中,或者文本已被选中,则不会搜索文本块并返回消息“无光标位置”。

要查找包含光标的单词(一串没有空格的连续字符),整个文本块按空格或行 returns 拆分。该数组循环搜索光标位置。一旦找到,返回数组中对应的词,然后用于在文本块中定位该词,然后突出显示。

// document.getElementById("btngo").addEventListener('click', function () { // vanilla

$(btngo).on('click', function(){
    var sel = window.getSelection();

    // get beginning and end of selection
    let ao = sel.anchorOffset;
    let fo = sel.focusOffset;

    // make sure there is a cursor position but not a selected range
    if ( 1 < fo && ao === fo ) {

        // get node containing cursor
        let fn = sel.focusNode;
        // trim whitespace at beginning and end of block of text, 
        // then split on spaces into an array
        let fn_arr = fn.textContent.trim().split(/\r?\n|\s/);

        // loop array and search for cursor position
        // when found use position to determine word in array containing cursor
        let [strt,end,wrd] = fn_arr.reduce(function (acc, txt) {

            return (fo > acc[1]) // have we reached the cursor position?
              ? [acc[1] + 1, acc[1] + txt.length + 1, txt] // if not keep track of location
              : acc; // if so, keep returning location information
        }, [0,0,""]);

        console.log(wrd); // display word containing cursor

        // select word containing cursor
        let range = new Range();
        range.setStart(fn, strt);
        range.setEnd(fn, end);
        sel.addRange(range);
    }
    else { console.log('no cursor position') }
});
.story{outline:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='story' id='story' contenteditable>
lorem - https://tumblr.com
more text to@select from
</div>
<br>
<button id='btngo'>GO</button>


对于LONG的文本块,可以逐行查找,然后只查找光标所在的行:

document.getElementById("btngo").addEventListener('click', function () {
    var sel = window.getSelection();
    // get beginning and end of selection
    let [ao, fo] = [sel.anchorOffset, sel.focusOffset];
    // make sure there is a cursor position but not a selected range
    if ( 1 < fo && ao === fo ) {
        // get node containing cursor
        let fn = sel.focusNode;

// FIND LINE
        // split on *line returns* into an array
        let fn_arr = fn.textContent.trim().split(/\r?\n/);
        // when found use position to determine *line* in array containing cursor
        let [strt,end,wrd] = fn_arr.reduce(findCursor(fo), [0,0,""]);

// FIND WORD IN LINE
        // split on *spaces* into an array
        fn_arr = wrd.trim().split(' ');    
        // when found use position to determine *word* in array containing cursor
        [strt,end,wrd] = fn_arr.reduce(findCursor(fo), [strt,strt-1,""]);

        console.log(wrd); // display word containing cursor
        // select word containing cursor
        let range = new Range();
        range.setStart(fn, strt);
        range.setEnd(fn, end);
        sel.addRange(range);
    }
    else { console.log('no cursor position')}
});

const findCursor = function (fo) {
    return function (acc, txt) {
        return (fo > acc[1]) // have we reached the cursor position?
            ? [acc[1] + 1, acc[1] + txt.length + 1, txt] // if not keep track of location
            : acc; // if so, keep returning location information
    }
}

您可以使用范围将光标定位在您需要的位置,然后从那里 select,在这种情况下,selection 将从第 9 个位置到行尾。

$(btngo).on('click', function(){
    var range = document.createRange()
    var sel = window.getSelection()
    
    //place the cursor to 9th position
    range.setStart($("#story")[0].childNodes[0], 9)
    range.collapse(true)
    
    sel.removeAllRanges()
    sel.addRange(range)  
 
    sel.modify("extend", "right", "lineboundary");
    console.log(sel.toString());
});
.story{outline:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='story' id='story' contenteditable>
lorem - https://tumblr.com
</div>
<br>
<button id='btngo'>GO</div>

使用 Javascript Selection and Selection.setBaseAndExtent():

这个解决方案从anchorNode and focusNode to locate the cursor, then Selection.setBaseAndExtent()开始逐渐扩大选区,直到找到白色space。这种方法的好处是速度和性能不受光标所在文本块大小的影响。

将光标放在任何单词中,然后单击“开始”。

选区的前端,通常是 anchorNode(起始)位置,逐渐向后移动,直到找到 space 或行 return。选择的后侧,通常是 focusNode(结束)位置,逐渐向前移动,直到找到 space 或行 return。该选择文本现在可以作为 sel.toString().

进行进一步处理

Actually, the anchorNode and anchorOffset are where the users start their cursor selection, and the focusNode and focusOffset is where they end their selection. So the anchor... is typically before, and the focus... after, but not necessarily. So these are sorted in order to move them in the corresponding direction they were selected.

document.getElementById("btngo").addEventListener('click', function () { // vanilla...why not?
    const sel = window.getSelection();

    let [bws,aws] = [false,false]; // before whitespace, after whitespace

    // sort because direction user makes selection determines node/offset order
    let [[bn,bo],[an,ao]] // before node/offset (backward), and after node/offset (forward)
        = [[sel.anchorNode, sel.anchorOffset],[sel.focusNode, sel.focusOffset]]
            .sort(function (aa,bb) { return aa[1] - bb[1]; }); // sort by offset

    // move BEFORE position backward until whitespace or beginning of node
    while ( !bws && 0 < bo ) {
        sel.setBaseAndExtent(bn,--bo,an,ao); // move backward 1 character

        // don't include whitespace, and assign result to bws
        if ( (bws = (-1 !== sel.toString().search(/\r?\n| /))) ) {
            ++bo; // prepare to move forward 1 to remove space
        }
    }

    // move AFTER position forward until whitespace or end of node
    while ( !aws && an.length >= ao + 1 ) {
        sel.setBaseAndExtent(bn,bo,an,++ao); // move forward 1 character
        if ( (aws = (-1 !== sel.toString().search(/\r?\n| /))) ) { // don't include whitespace, and assign result to aws
            --ao; // prepare to move backward to remove space
        }
    }
    sel.setBaseAndExtent(bn,bo,an,ao); // remove whitespace
    console.log(sel.toString());
});
.story{outline:none;}
<div class="story" id="story" contenteditable>
lorem - https://tumblr.com
more text to@select from
</div>
<br>
<button id="btngo">GO</button>