焦点输入时保持选中文本
这个问题已经被问过了,但直到现在还没有有效的答案,所以我很想再次打开它,希望我们能找到破解它的方法.
This question has already been asked but until now there is no working answer so I am tempting to open it again hopefully we can find a hack to it.
我有一个 contentEditable 段落和一个文本输入,当我选择一些文本并单击输入时,选择消失了.
I have a contentEditable paragraph and a text input, when I select some text and click the input, the selection is gone.
所以我尝试在输入 mousedown 时保存选择并在 mouseup 时恢复它,是的 它可以工作(正如预期的那样在 Firefox 中)但是......在 chrome 输入失去焦点 :(
So I've tried to save the selection on input mousedown and to restore it back on mouseup and yeah it works ( as expected in firefox) But... in chrome the input lose focus :(
查看实际操作(使用 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">
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
};
推荐答案
用 <span>
替换选择可能是最简单的方法.您还可以使用 <iframe>
,这是 google 在 Google Docs 中使用的,用于在单击 UI 元素时保持对文档内文本的选择.
Replacing selection with a <span>
is probably the simplest way. You can also use an <iframe>
, which is what google uses in Google Docs to maintain selection of text inside document while clicking UI elements.
使用 <span>
,解决方案可能是这样的(此解决方案基于您的原始代码和这里其他人的想法,尤其是 @Bekim Bacaj).
With <span>
, the solution might be like this (this solution build on your original code and the ideas of the other people here, especially @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)
.selected {
background-color: dodgerblue;
color: white;
}
<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>
链接到 jsFiddle
相关文章