我有一些IMG表情符号,可以将它们作为字符串表示形式插入到textarea中。下面的脚本必须位于插入记号的位置,并将其插入到正确的位置,但有时会触发错误,并将选择范围重置为0。
您可以看到它在玩耍,例如单击微笑并在文本区域内单击。在文本区域内容的末尾设置了插入符号后,我已立即重置为0。
window.onload = function() {
var doc = window.document;
var smiles = doc.getElementById('chat-smiles-panel').getElementsByTagName('IMG');
var el = doc.getElementById('chat-textarea');
for (var i = 0; i < smiles.length; i++) {
smiles[i].onclick = function(e) {
var elem, evt = e?e:event;
elem = (evt.target)?evt.target:evt.srcElement;
var newText = elem.getAttribute('data-smile');
console.log('before', el.selectionStart, el.selectionEnd);
var start = el.selectionStart;
var end = el.selectionEnd;
var text = el.value;
var before = text.substring(0, start);
var after = text.substring(end, text.length);
el.value = (before + newText + after);
start = end = start + newText.length;
el.setSelectionRange(start, end);
console.log('after', el.selectionStart, el.selectionEnd);
}
}
};
<div>
<div id="chat-smiles-panel">
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/slightly-smiling-face_1f642.png" alt="smiley" data-smile=":smiley:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/rolling-on-the-floor-laughing_1f923.png" alt="lol" data-smile=":lol:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/smiling-face-with-halo_1f607.png" alt="angel" data-smile=":angel:" />
</div>
<textarea id="chat-textarea"></textarea>
</div>
每次在控制台日志中都可以看到插入表情符号前后的牙齿位置。
答案 0 :(得分:3)
我想您知道,el.value = (before + newText + after);
会擦除该值并将其替换为新值,将光标移回该字段的开头。
我认为,为了使setSelectionRange
能够跨浏览器工作,该领域必须再次获得关注。无论如何,Chrome似乎都是这种情况,因为(使用el.focus()
)可以正常工作:
window.onload = function() {
var doc = window.document;
var smiles = doc.getElementById('chat-smiles-panel').getElementsByTagName('IMG');
var el = doc.getElementById('chat-textarea');
for (var i = 0; i < smiles.length; i++) {
smiles[i].onclick = function(e) {
var elem, evt = e?e:event;
elem = (evt.target)?evt.target:evt.srcElement;
var newText = elem.getAttribute('data-smile');
console.log('before', el.selectionStart, el.selectionEnd);
var start = el.selectionStart;
var end = el.selectionEnd;
var text = el.value;
var before = text.substring(0, start);
var after = text.substring(end, text.length);
el.value = (before + newText + after);
el.focus(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Added
start = end = start + newText.length;
el.setSelectionRange(start, end);
console.log('after', el.selectionStart, el.selectionEnd);
}
}
};
<div>
<div id="chat-smiles-panel">
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/slightly-smiling-face_1f642.png" alt="smiley" data-smile=":smiley:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/rolling-on-the-floor-laughing_1f923.png" alt="lol" data-smile=":lol:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/smiling-face-with-halo_1f607.png" alt="angel" data-smile=":angel:" />
</div>
<textarea id="chat-textarea"></textarea>
</div>
在评论中您已经询问:
如果我不想将重点放在文本区域上,还没有解决方案吗?我问原因是,当textarea获得焦点时,我试图使UI更友好地隐藏表情符号面板。因此,当脚本在插入表情符号后设置焦点时,表情符号面板会滑开,效果不好。
为解决这个问题,我尝试在使用focus
之前获取了活动元素:
// Didn't work
var active = document.activeElement;
el.focus();
el.setSelectionRange(start, end);
if (active) {
active.focus();
}
当那不起作用时,我猛击并使用了el.blur()
,它可以起作用(尽管我不太喜欢):
window.onload = function() {
var doc = window.document;
var smiles = doc.getElementById('chat-smiles-panel').getElementsByTagName('IMG');
var el = doc.getElementById('chat-textarea');
for (var i = 0; i < smiles.length; i++) {
smiles[i].onclick = function(e) {
var elem, evt = e?e:event;
elem = (evt.target)?evt.target:evt.srcElement;
var newText = elem.getAttribute('data-smile');
console.log('before', el.selectionStart, el.selectionEnd);
var start = el.selectionStart;
var end = el.selectionEnd;
var text = el.value;
var before = text.substring(0, start);
var after = text.substring(end, text.length);
el.value = (before + newText + after);
el.focus(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Added
start = end = start + newText.length;
el.setSelectionRange(start, end);
el.blur(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Added
console.log('after', el.selectionStart, el.selectionEnd);
}
}
};
<div>
<div id="chat-smiles-panel">
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/slightly-smiling-face_1f642.png" alt="smiley" data-smile=":smiley:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/rolling-on-the-floor-laughing_1f923.png" alt="lol" data-smile=":lol:" />
<img width="20" src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/apple/155/smiling-face-with-halo_1f607.png" alt="angel" data-smile=":angel:" />
</div>
<textarea id="chat-textarea">Testing 1 2 3</textarea>
</div>
我倾向于使表情面板在消失时更智能,例如,从上次使用开始增加一秒钟的延迟,这样,如果您想添加多个表情,可以,但是可以在最后一个之后第二秒消失。