Javascript 焦点输入时保持文本处于选中状态

Javascript 焦点输入时保持文本处于选中状态,javascript,range,selection,contenteditable,Javascript,Range,Selection,Contenteditable,这个问题已经被问过了,但直到现在还没有有效的答案,所以我很想再次打开它,希望我们能找到一个破解方法 我有一个内容可编辑的段落和一个文本输入,当我选择一些文本并单击输入时,选择就消失了 所以我试着在输入mousedown上保存所选内容并在mouseup上还原它,是的它可以工作(正如firefox中所期望的那样),但是。。。在chrome中,输入失去焦点:( 查看它的实际操作(使用chrome): 这是我使用的代码: HTML 在超时函数中添加焦点,这将解决您的问题 setTimeout(funct

这个问题已经被问过了,但直到现在还没有有效的答案,所以我很想再次打开它,希望我们能找到一个破解方法

我有一个内容可编辑的段落和一个文本输入,当我选择一些文本并单击输入时,选择就消失了

所以我试着在输入mousedown上保存所选内容在mouseup上还原它,是的它可以工作(正如firefox中所期望的那样),但是。。。在chrome中,输入失去焦点:(

查看它的实际操作(使用chrome):

这是我使用的代码:

HTML


在超时函数中添加焦点,这将解决您的问题

setTimeout(function(){
  document.getElementById("textToInsert").focus();
    }, 1);

jshiddle:

这是我很久以前在其他一些列表中作为答案发布的一个非常古老的片段。它可能会帮助您重新思考当前的策略,完全避免攻击focus的自然预期行为

函数createLink(e){
如果(e.target){
var a=window.getSelection().getRangeAt(0);
var b=a.toString();
var z=document.createElement(“span”);
var l2=提示符(“输入URL:,“http://”);
b=b.link(l2);
z、 innerHTML=b;
a、 删除内容();
a、 插入节点(z)}
否则{
document.execCommand(“CreateLink”)}
}

文本到超链接
创建链接
选择一些文本并单击按钮。在显示的工具箱上提供url并确认。所选文本将成为超链接
我的主页
我最喜欢的
我的搜索页面

让它成为一个链接
用span元素替换所选区域(以及该元素的颜色)可能是一种解决方法:

var p=document.querySelector('p');
var old=p.innerHTML;
var input=document.querySelector('input');
p、 addEventListener('blur',()=>{
高亮显示(select());//保存所选内容
})
p、 addEventListener('焦点',()=>{
restore();//还原所选内容
})
功能突出显示(r){
如果(!r)返回;
var extracted=r.extractContents();
el=document.createElement('span');
el.appendChild(提取);
r、 插入节点(el)
}
函数选择(){
if(window.getSelection){
sel=window.getSelection();
if(sel.getRangeAt&&sel.rangeCount){
返回sel.getRangeAt(0);
}
}else if(document.selection&&document.selection.createRange){
return document.selection.createRange();
}
返回null;
}
函数还原(){
p、 innerHTML=旧的;
}
span{
背景:番茄;
颜色:白色;
}

在这里选择一些内容,然后单击下面的输入
在firefox上,输入获得焦点,文本仍处于选中状态。
在chrome上,文本仍处于选中状态,但输入失去焦点


由于我无法对maioman(需要一些声誉:)发表评论,下面是对他的回答的一点补充:

它在firefox中不起作用的原因是将焦点放在输入字段上会删除选择

如果将mouseup事件放在p上,而不是将焦点事件放在inputfield上,则一切正常:

p.addEventListener('mouseup', () => { highlight(select()); // save the selection }) p、 addEventListener('mouseup',()=>{ 高亮显示(select());//保存所选内容 })
我给你一个提示,让你自己去弄清楚。您需要检测是否正在使用chrome。在JSFIDLE中,添加
console.log(sel)
after
sel=window.getSelection()。请注意,在日志中,不同浏览器上的选择不同。老实说,我不知道为什么,但这可能会帮助你找出问题所在


如果注释掉
sel.removeAllRanges(),也会注意到同样的问题您将得到一个错误,告诉您它们是不同的,如上所述。

我对此做了一些工作。。。这是一个非常有趣和有教育意义的练习。
我主要从Maioman的回答开始。

我这样做是为了让选定的文本最终在输入字段中提供href的锚中。。。输入链接时,所选文本保持选中状态。这就是我对你问题的理解。

看我的工作小提琴:
测试在FF 46、Chrome 50、Safari 5.1和Explorer 11上运行。

请注意,
classList
仅在IE10及更高版本中受支持。
此外,由于鼠标点击事件,链接不可“点击”。
但是您可以在鼠标上方看到title属性。
我假设您将保存段落的innerHTML以将其输出到其他地方。
;)


CSS:

a.highlighted {
  background: blue;
  color:white;
}
<h1>Select some text below and click GO!</h1>
<br>
<p contenteditable="true" tabindex="0">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris nec risus turpis. Donec nisi urna, semper nec ex ac, mollis egestas risus. Donec congue metus massa, nec lacinia tortor ornare ac. Nulla porttitor feugiat lectus ut iaculis. In sagittis tortor et diam feugiat fermentum. Nunc justo ligula, feugiat dignissim consectetur non, tristique vitae enim. Curabitur et cursus velit. Etiam et aliquam urna. Duis pharetra fermentum lectus et fermentum. Phasellus eget nunc ultricies, ornare libero quis, porta justo. Sed euismod, arcu sed tempor venenatis, urna ipsum lacinia eros, ac iaculis leo risus ac est. In hac habitasse platea dictumst. Sed tincidunt rutrum elit, ornare posuere lorem tempor quis. Proin tincidunt, lorem ac luctus dictum, dui mi molestie neque, a sagittis purus leo a nunc.
</p><br>
<br>
<b>Add a link to selected text:</b> <input type="text" id="hrefInput" style="border: solid blue 1px" value="http://www.test.com"> <input type="button" id="gobutton" value="GO!"><br>
<span id="errorMsg" style="display:none;">No selected text!</span><br>
<input type="button" id="undoButton" value="Undo">
var p = document.querySelector('p');
var old = p.innerHTML;
var HrefInput = document.getElementById("hrefInput");
var GoButton = document.getElementById("gobutton");
var UndoButton = document.getElementById("undoButton");
var errorMsg = document.getElementById("errorMsg");
var idCounter=0;
var textSelected=false;

UndoButton.addEventListener('focus', function() {
    console.log("Undo button clicked. Default text reloaded.");
    restore();
})

GoButton.addEventListener('click', function() {
    if(!textSelected){
        errorMsg.style.display="inline";
        errorMsg.style.color="rgb(166, 0, 0)";
        errorMsg.style.fontWeight="bold";
        return;
    }
    console.log("GO button clicked: Link id=a-"+idCounter+" created.");
    targetId="a-"+idCounter;
    document.getElementById(targetId).setAttribute("href",HrefInput.value);
    document.getElementById(targetId).classList.add("createdlink");
    document.getElementById(targetId).setAttribute("title",HrefInput.value);
    document.getElementById(targetId).classList.remove("highlighted");
    textSelected=false;
    idCounter++
})

p.addEventListener('focus', function() {
    errorMsg.style.display="none";
});

p.addEventListener('mouseup', function() {
    textSelected=true;
    console.log("Mouseup event in p : Text selected.");
    appendanchor(selectText()); // extract the selection
    HrefInput.focus();  // FireFox 
    HrefInput.blur();   // Needs it. Try without, you'll see.
})

function appendanchor(r) {  // onmouseup
    if (!r) return;
    extracted = r.extractContents();
    el = document.createElement('a');
    el.setAttribute("id", "a-"+idCounter);
    el.setAttribute("class", "highlighted");
    el.appendChild(extracted);
    r.insertNode(el)
}

function selectText() { // onmouseup
    if (window.getSelection) {
        console.log("window.getSelection");
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) { // Chrome, FF
            console.log(sel.getRangeAt(0));
            return sel.getRangeAt(0);
        }
        else{console.log(sel);}
    } else if (document.selection && document.selection.createRange) {
        console.log("elseif");
        return document.selection.createRange();
    }
    return null;
}

function restore() {
    p.innerHTML = old;
    textSelected=false;
}
HTML:

a.highlighted {
  background: blue;
  color:white;
}
<h1>Select some text below and click GO!</h1>
<br>
<p contenteditable="true" tabindex="0">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris nec risus turpis. Donec nisi urna, semper nec ex ac, mollis egestas risus. Donec congue metus massa, nec lacinia tortor ornare ac. Nulla porttitor feugiat lectus ut iaculis. In sagittis tortor et diam feugiat fermentum. Nunc justo ligula, feugiat dignissim consectetur non, tristique vitae enim. Curabitur et cursus velit. Etiam et aliquam urna. Duis pharetra fermentum lectus et fermentum. Phasellus eget nunc ultricies, ornare libero quis, porta justo. Sed euismod, arcu sed tempor venenatis, urna ipsum lacinia eros, ac iaculis leo risus ac est. In hac habitasse platea dictumst. Sed tincidunt rutrum elit, ornare posuere lorem tempor quis. Proin tincidunt, lorem ac luctus dictum, dui mi molestie neque, a sagittis purus leo a nunc.
</p><br>
<br>
<b>Add a link to selected text:</b> <input type="text" id="hrefInput" style="border: solid blue 1px" value="http://www.test.com"> <input type="button" id="gobutton" value="GO!"><br>
<span id="errorMsg" style="display:none;">No selected text!</span><br>
<input type="button" id="undoButton" value="Undo">
var p = document.querySelector('p');
var old = p.innerHTML;
var HrefInput = document.getElementById("hrefInput");
var GoButton = document.getElementById("gobutton");
var UndoButton = document.getElementById("undoButton");
var errorMsg = document.getElementById("errorMsg");
var idCounter=0;
var textSelected=false;

UndoButton.addEventListener('focus', function() {
    console.log("Undo button clicked. Default text reloaded.");
    restore();
})

GoButton.addEventListener('click', function() {
    if(!textSelected){
        errorMsg.style.display="inline";
        errorMsg.style.color="rgb(166, 0, 0)";
        errorMsg.style.fontWeight="bold";
        return;
    }
    console.log("GO button clicked: Link id=a-"+idCounter+" created.");
    targetId="a-"+idCounter;
    document.getElementById(targetId).setAttribute("href",HrefInput.value);
    document.getElementById(targetId).classList.add("createdlink");
    document.getElementById(targetId).setAttribute("title",HrefInput.value);
    document.getElementById(targetId).classList.remove("highlighted");
    textSelected=false;
    idCounter++
})

p.addEventListener('focus', function() {
    errorMsg.style.display="none";
});

p.addEventListener('mouseup', function() {
    textSelected=true;
    console.log("Mouseup event in p : Text selected.");
    appendanchor(selectText()); // extract the selection
    HrefInput.focus();  // FireFox 
    HrefInput.blur();   // Needs it. Try without, you'll see.
})

function appendanchor(r) {  // onmouseup
    if (!r) return;
    extracted = r.extractContents();
    el = document.createElement('a');
    el.setAttribute("id", "a-"+idCounter);
    el.setAttribute("class", "highlighted");
    el.appendChild(extracted);
    r.insertNode(el)
}

function selectText() { // onmouseup
    if (window.getSelection) {
        console.log("window.getSelection");
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) { // Chrome, FF
            console.log(sel.getRangeAt(0));
            return sel.getRangeAt(0);
        }
        else{console.log(sel);}
    } else if (document.selection && document.selection.createRange) {
        console.log("elseif");
        return document.selection.createRange();
    }
    return null;
}

function restore() {
    p.innerHTML = old;
    textSelected=false;
}

替换选择可能是最简单的方法。您还可以使用,这是google在google文档中使用的,用于在单击UI元素时维护文档中文本的选择

使用
,解决方案可能是这样的(此解决方案基于您的原始代码和其他人的想法,尤其是@Bekim Bacaj)

!功能(doc,win){
var input=doc.getElementById('special'))
,可编辑=doc.getElementById('可编辑')
,button=doc.getElementById('button'))
,fragment=null
,range=null;
函数saveSelection(){
if(win.getSelection){
sel=win.getSelection();
if(sel.getRangeAt&&sel.rangeCount){
返回sel.getRangeAt(0);
}
}else if(doc.selection&&doc.selection.createRange){
return doc.selection.createRange();
}
返回null;
}
/*不需要,除非您还希望恢复选择
函数restoreSelection(){
如果(范围){
if(win.getSelection){
sel=win.getSelection();
选择removeAllRanges();
选择添加范围(范围);
}else if(doc.selection&&range.select){
range.select();
}
}
}
*/
函数saveRangeEvent(事件){
范围=保存选择();
如果(范围&&!范围.折叠){
fragment=range.cloneContents();
切换
private selectColor($event: CustomEvent) {
    const selection: Selection | undefined = getSelection();

    if (!selection || !$event || !$event.detail) {
      return;
    }

    selection?.removeAllRanges();
    selection?.addRange(this.range);

    const observer: MutationObserver = 
      new MutationObserver( (_mutations: MutationRecord[]) => {
      observer.disconnect();

      this.range = selection?.getRangeAt(0);
    });

    const anchorNode: HTMLElement | undefined = getAnchorNode(selection);

    observer.observe(anchorNode, {childList: true});

    document.execCommand('foreColor', false, $event.detail.value);