这个问题已经被问过了,但是直到现在还没有工作的答案,所以我很想再次打开它,希望我们可以找到它。
我有一个contentEditable段落和一个文本输入,当我选择一些文本并单击输入时,选择就消失了。
所以我尝试保存输入mousedown上的选择并将其恢复为mouseup ,是的它可以(正如预期的那样)在Firefox中)但是......在chrome 输入失去焦点 :(
查看实际操作(使用chrome ):https://jsfiddle.net/mody5/noygdhdu/
这是我用过的代码:
HTML
select yr, mo, count(*) as numusers, minminv, maxmaxv,
sum(case when minv = minminv then 1 else 0 end) as numAtMin,
sum(case when maxv = maxmaxv then 1 else 0 end) as numAtMax
from (select yr, mo, [user], min(visits) as minv, max(visits) as maxv,
min(min(visits)) over (partition by yr, mo) as minminv,
max(max(visits)) over (partition by yr, mo) as maxmaxv
from t
group by yr, mo, [user]
) ymu
group by yr, mo, minminv, maxmaxv;
的javascript
<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">
答案 0 :(得分:6)
我无法对maioman发表评论(需要一些声望:)),这里有一点点他的aswer:
它在firefox中不起作用的原因是将焦点放在输入字段上会删除选择。
如果你在p上放置一个mouseup事件而不是输入字段上的焦点事件,这一切都可以正常工作:
p.addEventListener('mouseup', () => { highlight(select()); // save the selection })
答案 1 :(得分:3)
我在这个上做了一点......这是一个非常有趣和有益的练习
我主要是从Maioman的回答开始的
我这样做是为了使所选文本最终成为一个锚点,并在输入字段中提供href ...并且在输入链接时所选文本保持选中状态。这是我对你的问题的理解。
看我的工作小提琴:https://jsfiddle.net/Bes7weB/rLmfb043/
在FF 46,Chrome 50,Safari 5.1和Explorer 11上经过测试可以正常工作
请注意,仅在IE10及更高版本中支持classList
此外,由于鼠标事件,链接不是“可点击的”
但是你可以在mouseover上看到title属性
我假设您将保存段落的innerHTML以将其输出到其他地方
;)
的 CSS:强>
a.highlighted {
background: blue;
color:white;
}
<强> HTML 强>
<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">
<强> JavaScript的:强>
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;
}
答案 2 :(得分:2)
将焦点添加到超时功能中,这应该可以解决您的问题。
setTimeout(function(){
document.getElementById("textToInsert").focus();
}, 1);
答案 3 :(得分:2)
用span元素替换所选区域(并着色)可能是一种解决方法:
var p = document.querySelector('p');
var old = p.innerHTML;
var input = document.querySelector('input');
p.addEventListener('blur', () => {
highlight(select()); // save the selection
})
p.addEventListener('focus', () => {
restore(); // restore the selection
})
function highlight(r) {
if (!r) return;
var extracted = r.extractContents();
el = document.createElement('span');
el.appendChild(extracted);
r.insertNode(el)
}
function select() {
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 restore() {
p.innerHTML = old;
}
&#13;
span {
background: tomato;
color:white;
}
&#13;
<p contenteditable="true" tabindex="0">
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">
&#13;
适用于chrome,但不适用于FF
正如Eric在mouseup
使用blur
事件(我实际使用p
)来调用highlight(select())
来建议解决FF上的问题。
答案 4 :(得分:2)
用<span>
替换选择可能是最简单的方法。您还可以使用谷歌文档中谷歌使用的<iframe>
来维护文档内部文本的选择,同时点击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)
.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>
答案 5 :(得分:1)
这是我很久以前在其他名单上发布的一个非常古老的片段。它可能有助于您重新考虑当前的策略,并完全避免黑客攻击自然预期的焦点行为。
function createLink(e){
if(e.target){
var a = window.getSelection().getRangeAt(0);
var b = a.toString();
var z = document.createElement("span");
var l2 = prompt("Enter URL:", "http://");
b = b.link(l2);
z.innerHTML=b;
a.deleteContents();
a.insertNode(z) }
else{
document.execCommand("CreateLink") }
}
<!DOCTYPE html>
<html>
<head>
<title>Text to Hyperlink</title>
</head>
<body>
<h1>Create a link</h1>
Select some text and click the button. On the presented toolbox provide the url and confirm. The selected text will become a hyperlink<br>
My Homepage<br>
My Favorite<br>
My Search Page<br><br>
<button onclick="createLink(event)">Make it a link</button>
<script>
</script>
</body>
</html>
答案 6 :(得分:1)
我会给你一个提示,让你自己弄清楚。您需要检测是否正在使用铬。在您的jsfiddle中,在console.log(sel);
之后添加sel = window.getSelection();
。请注意,在日志中,不同浏览器的选择是不同的。说实话,我不确定为什么,但这可以帮助你找出问题所在。
如果您注释掉sel.removeAllRanges();
,也会发现同样的问题,如上所述,您会收到错误消息,告诉您它们不同。
答案 7 :(得分:0)
我想它不会回答你的问题,但为了你的目的,我强烈建议你使用Angular.js或React.js。 如果你没有和他们一起玩,那么你将有一个学习曲线,但从长远来看,这将是非常值得的! (你也会发现更容易“选择”化妆品)
希望有帮助......:)
答案 8 :(得分:0)
在选择后进行编辑操作的UI部件上尝试此操作。它为我工作时没有困难的解决方法,将当前选择保持为标记有此选项的元素是无法选择的,并且可以更改或删除当前选择。
答案 9 :(得分:0)
在我的用例中,我能够在 MutationObserver
的帮助下解决在使用输入字段时丢失选择的问题。
在我的组件中,我获得了连接时初始化的范围的状态:
private range: Range | undefined;
componentWillLoad() {
const selection: Selection | undefined = getSelection();
this.range = selection?.getRangeAt(0);
}
<块引用>
getSelection
是一个实用程序,它根据浏览器返回 Selection
。
然后应用颜色的函数如下所示:
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);
发生了什么:我得到了选择,删除了所有范围并添加了我作为状态保留的范围。
然后我在选择锚节点上附加一个变异观察者。为此,我使用了一个实用程序,该实用程序在选择 text
或 comment
的情况下返回锚节点或其父节点。
然后我调用 execCommand
。
一旦观察者启动,我就会查询新范围的选择(此时是文档的修改节点,而不是输入)并将其保存到我的状态。