如何在不改变焦点的情况下输入

How to input without change focus

构建如下所示的编辑器——我需要用户能够 select 一些文本,然后使用输入做一些事情而不丢失 selection。

function doReplace(){
  const s = document.getSelection()
  if(s?.anchorNode.parentElement.id != "out")return;
  
  console.log('replace')
  out.innerText = out.innerText.substring(0,s.anchorOffset)+(inp.value||'FALLBACK')+out.innerText.substring(s.extentOffset)
  
}
<input id="inp" placeholder="replace selection to" >
<button onclick="doReplace()">replace</button>
<p id="out">select some here and replace</p>

此演示重现了该问题:无法在不丢失文本的情况下使用输入 selection。

如何在不改变焦点的情况下输入?

真实世界的用例类似于为 selection 设置字体大小。

编辑

也许缓存 selection 是可行的方法,但会失去视觉指示,尝试恢复 selection 将再次失去焦点。

let s

function doReplace() {
  if (s?.anchorNode?.parentElement.id != "out") return;

  console.log('replace')
  out.innerText = out.innerText.substring(0, s.anchorOffset) + (inp.value || 'FALLBACK') + out.innerText.substring(s.extentOffset)

}

function doRestore() {
  if (s?.anchorNode?.parentElement.id != "out") return;
  const sel = document.getSelection();
  sel.setBaseAndExtent(s.anchorNode, s.anchorOffset, s.anchorNode, s.extentOffset);
}
out.addEventListener('mouseup', () => {
  const sel = document.getSelection()
  if(!sel)return;
  const {
    anchorNode,
    anchorOffset,
    extentOffset
  } = sel || {}
  s = {
    text: sel.toString(),
    anchorNode,
    anchorOffset,
    extentOffset
  }
  console.log(`sel`, s.anchorOffset, s.extentOffset, s.text)
}, false);
<input id="inp" placeholder="replace selection to" autocomplete="false" onfocus="doRestore()">
<button onclick="doReplace()">replace</button>
<p id="out">select some here and replace</p>

如果我错了请纠正我,但我看不出有什么可能。 input/textarea 标签需要焦点,以便用户能够输入。

我建议您使用 EventListener 而不是输入标签:

function doReplace(){
  const s = document.getSelection()
  if(s?.anchorNode.parentElement.id != "out")return;
  
  console.log('replace')
  out.innerText = out.innerText.substring(0,s.anchorOffset)+(inp.value||'FALLBACK')+out.innerText.substring(s.extentOffset)
  
}

window.addEventListener("keydown", event => {
  document.getElementById("field").innerHTML += event.key 
});
<div id="field"></div>
<button onclick="doReplace()">replace</button>
<p id="out">select some here and replace</p>