在焦点输入时保持选择文本

med*_*zid 11 javascript range selection contenteditable

这个问题已经被问到,但是直到现在还没有工作的答案,所以我很想再次打开它,希望我们可以找到它.

我有一个contentEditable段落和一个文本输入,当我选择一些文本并单击输入时,选择就消失了.

所以我试图在输入mousedown上保存选择在mouseup上恢复它,是的可行(如预期在firefox中)但是...在chrome 中输入失去焦点 :(

看到它在行动(使用铬):https://jsfiddle.net/mody5/noygdhdu/

这是我用过的代码:

HTML

<p contenteditable="true">
    Select something up here and click the input below
    <br> on firefox the input get the focus and the text still selected.
    <br> on chrome the text still selected but the input lose focus
</p>

    <input type="text" id="special" style="border: solid blue 1px">
Run Code Online (Sandbox Code Playgroud)

JavaScript的

function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}


var specialDiv = document.getElementById("special");
var savedSel = null;

specialDiv.onmousedown = function() {

    savedSel = saveSelection(); // save the selection

};

specialDiv.onmouseup = function() {

    restoreSelection(savedSel); // restore the selection

};
Run Code Online (Sandbox Code Playgroud)

小智 7

由于我不能评论maioman(需要一些声誉:)),这里有一点他的aswer:

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

如果你在p上放置一个mouseup事件而不是inputfield上的焦点事件,这一切都可以正常工作:


    p.addEventListener('mouseup', () => {
      highlight(select()); // save the selection
    })


Vac*_*tny 7

用 a 替换 selection<span>可能是最简单的方法。您还可以使用<iframe>,这是 google 在 Google Docs 中用来在单击 UI 元素时维护文档内文本选择的方法。

使用<span>,解决方案可能是这样的(这个解决方案建立在你的原始代码和这里其他人的想法上,尤其是@Bekim Bacaj)。

!function(doc, win) {
  var input = doc.getElementById('special')
  	, editable = doc.getElementById('editable')
    , button = doc.getElementById('button')
    , fragment = null
    , range = null;

	function saveSelection() {  
    if (win.getSelection) {
      sel = win.getSelection();
      if (sel.getRangeAt && sel.rangeCount) {
        return sel.getRangeAt(0);
      }
    } else if (doc.selection && doc.selection.createRange) {
      return doc.selection.createRange();
    }
    return null;
  }
  
  /* Not needed, unless you want also restore selection
  function restoreSelection() {
    if (range) {
      if (win.getSelection) {
        sel = win.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
      } else if (doc.selection && range.select) {
        range.select();
      }
    }
  }
  */
    
  function saveRangeEvent(event) {
    range = saveSelection();
    if (range && !range.collapsed) {
    	fragment = range.cloneContents();
      toggleButton();
    }
  } 
   
  function toggleButton() {
      button.disabled = !fragment || !input.value.match(/^https?:.*/);
  }
  toggleButton();
  
  editable.addEventListener('mouseup', saveRangeEvent);
  editable.addEventListener('keyup', saveRangeEvent);
  button.addEventListener('click', function(event) {
    // insert link
  	var link = doc.createElement('a');
    link.href = input.value;
    input.value = '';
    range.surroundContents(link);
    toggleButton();
  });
  input.addEventListener('keyup', toggleButton);
  input.addEventListener('change', toggleButton);
  input.addEventListener('mousedown', function(event) {
    // create fake selection
    if (fragment) {
      var span = doc.createElement('span');
      span.className = 'selected';
      range.surroundContents(span);
    }
  });
  input.addEventListener('blur', function(event) {
    // remove fake selection
  	if (fragment) {
      range.deleteContents();
      range.insertNode(fragment);  
      //restoreSelection();
    }
    fragment = null;
  }, true);
  
}(document, window)
    
    
Run Code Online (Sandbox Code Playgroud)
.selected {
  background-color: dodgerblue;
  color: white;
}
Run Code Online (Sandbox Code Playgroud)
<p id="editable" contenteditable="true">
  Select something up here and click the input below
  <br>on firefox the input get the focus and the text still selected.
  <br>on chrome the text still selected but the input lose focus
</p>

<table>
  <tr>
    <td>
      <input type="text" id="special" style="border: solid blue 1px" placeholder="insert valid link incl. http://">
    </td>
    <td>
      <button id="button">Add link</button>
    </td>
  </tr>
</table>
Run Code Online (Sandbox Code Playgroud)


链接到 jsFiddle


Par*_*ari 2

将焦点添加到超时函数中,这应该可以解决您的问题。

setTimeout(function(){
  document.getElementById("textToInsert").focus();
    }, 1);
Run Code Online (Sandbox Code Playgroud)

jsfiddle: http: //jsfiddle.net/mody5/L5hx9h3k/1/