Javascript 当插入符号进入特定的div/span/a标记时以及当插入符号离开标记时触发事件
这个想法是-Javascript 当插入符号进入特定的div/span/a标记时以及当插入符号离开标记时触发事件,javascript,jquery,angularjs,frontend,jquery-events,Javascript,Jquery,Angularjs,Frontend,Jquery Events,这个想法是- 有一个contenteditable元素,其中包含一些文本。我正在尝试建立一种标记机制(有点像推特的人在你输入@时标记)。每当用户键入“@”,当他们继续键入时,它就会显示一个带有建议和过滤器的弹出窗口。在这之前,一切都很简单,我已经弄明白了。当/仅当插入符号位于包含标记的元素上方时,当我需要显示popover时,就会出现问题 <div contenteditable=""> <p>Some random text before
有一个
contenteditable
元素,其中包含一些文本。我正在尝试建立一种标记机制(有点像推特的人在你输入@时标记)。每当用户键入“@”,当他们继续键入时,它就会显示一个带有建议和过滤器的弹出窗口。在这之前,一切都很简单,我已经弄明白了。当/仅当插入符号位于包含标记的元素上方时,当我需要显示popover时,就会出现问题
<div contenteditable="">
<p>Some random text before
<a href="javascript:;"
class="name-suggest"
style="color:inherit !important;text-decoration:inherit !important">@samadams</a>
Some random text after</p>
</div>
之前的一些随机文本
后面有一些随机文本
现在,每当用户将插入符号移动到a标记上/单击它时,我想触发一个显示popover的事件,并在插入符号离开a标记时将其删除。(有点像聚焦/模糊,但它们似乎不起作用)onmousedown
起作用,但无法判断光标是否已用键盘移动到锚定标记中
此外,我在angularjs中这样做,因此,任何针对这一点的解决方案都是可取的,但不是必需的
一天来,我们一直在努力使其发挥作用,非常感谢您的帮助。这将让您知道插入符号位置何时位于包含
@
$('#content')。在('mouseup keydown keydup',函数(事件){
var sel=getSelection();
如果(选择类型==“插入符号”){
var anchorNodeVal=sel.anchorNode.nodeValue;
if(anchorNodeVal.indexOf('@')>=0){
$('pop').show()
}否则{
$('#pop').hide()
}
}
})
之前的一些随机文本
后面有一些随机文本
Twitter节点发现
下面的代码中有一个奇怪的regexp和偏移量计算,但让我解释一下为什么它是一个更好的解决方案
大约一年前,我一直在使用contenteditable构建一个复杂的编辑器。这不仅仅是一场灾难。那是一场他妈的灾难。没有覆盖所有案例的规范。浏览器在每一个可能的细节上表现不同,并且经常变化。在@
字符前面加上插入符号,您将看到这是壁虎:
<a href="#">|@name
而不是
$el = $('#content');
var showTip = function (nickname) {
// ...
console.log('Show: ' + nickname);
};
var dismissTip = function () {
// ...
console.log('Hide');
};
// I'm sure there is a better RegExp for this :)
var nicknameRegexp = /(^|\b|\s)\@(\w+)(\s|\b|$)/g;
var trackSelection = function () {
var selection = window.getSelection(),
range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
if (range == null || $el[0].contains(range.commonAncestorContainer) == false) {
return dismissTip();
}
var comparer = range.cloneRange();
comparer.setStart($el[0], 0);
var offset = comparer.toString().length;
var match, from, to;
while (match = nicknameRegexp.exec($el[0].textContent)) {
from = match.index + match[1].length;
to = match.index + match[1].length + match[2].length + 1;
if (offset >= from && offset <= to) {
// Force rewind, otherwise next time result might be incorrect
nicknameRegexp.lastIndex = 0;
return showTip(match[2]);
}
}
return dismissTip();
};
$el.on({
// `mousedown` can happen outside #content
'mousedown': function (e) {
$(document).one('mouseup', function (e) {
// Calling function without a tiny delay will lead to a wrong selection info
setTimeout(trackSelection, 5);
});
},
'keyup': trackSelection
});
$el=$(“#内容”);
var showTip=函数(昵称){
// ...
log('Show:'+昵称);
};
var dismissTip=函数(){
// ...
console.log('Hide');
};
//我相信有一个更好的RegExp用于此:)
变量昵称regexp=/(^ |\b |\s)\@(\w+)(\s |\b |$)/g;
var trackSelection=函数(){
var selection=window.getSelection(),
range=selection.rangeCount>0?selection.getRangeAt(0):空;
if(range==null | |$el[0]。包含(range.commonAncestorContainer)==false){
返回dismissTip();
}
var comparer=range.cloneRange();
comparer.setStart($el[0],0);
var offset=comparer.toString().length;
var匹配,从,到;
而(match=昵称regexp.exec($el[0].textContent)){
from=match.index+match[1]。长度;
to=match.index+match[1]。长度+match[2]。长度+1;
如果(offset>=from&&offset刚刚看了我来这里的原因,假装你的情况非常相似,只是发现当前单词是否特别以@
开头,以便模态显示
您需要的是一种方法,可以在移动或键入时获取我们正在使用的单词,然后检查第一个字符并相应地隐藏/显示模式窗格将非常简单
function getSelectedWord(grab=document.getSelection()) {
var i = grab.focusOffset, node = grab.focusNode, // find cursor
text = node.data || node.innerText, // get focus-node text
a = text.substr(0, i), p = text.substr(i); // split on caret
return a.split(/\s/).pop() + p.split(/\s/)[0]} // cut-out at spaces
现在,您可以收听keydown
或selectionchange
事件,并显示您的窗格,了解当前/所选单词已写入的内容
editor.addEventListener('keydown', ev => {
if (ev.key.substr(0, 5) != 'Arrow') // react when we move caret or
if (ev.key != '@') return; // react when we type an '@' or quit
var word = getSelectedWord(); // <-- checking value
if (word[0] == '@') showModal(word.substr(1)); // pass without '@'
});
editor.addEventListener('keydown',ev=>{
if(ev.key.substr(0,5)!=“箭头”)//移动插入符号或
if(ev.key!='@')return;//在键入'@'或退出时做出反应
var word=getSelectedWord();//很酷。谢谢。这很有效,为实现我需要的东西提供了一些好主意。Selection.type
不是在Gecko中实现的。很好的一点。您可以实际删除if块,它的功能很好,性能差异可能可以忽略
editor.addEventListener('keydown', ev => {
if (ev.key.substr(0, 5) != 'Arrow') // react when we move caret or
if (ev.key != '@') return; // react when we type an '@' or quit
var word = getSelectedWord(); // <-- checking value
if (word[0] == '@') showModal(word.substr(1)); // pass without '@'
});