我在实现建议文本的游戏的聊天栏中制作用户标记方法。当玩家键入“@”后跟字母/数字时,建议的用户名将突出显示并选中,如Google搜索栏那样排序。 我在下面有一个简单的演示。
我的问题是事件监听器的时间。我想使用“按键”事件,以便只有可打印的字符提示建议,但是在按下的按键呈现之前插入并选择了建议,导致建议立即被删除。在我的演示中,我默认返回“keyup”,但现在有一个明显的滞后和不可打印的键触发事件(使用箭头进行退格/删除和导航不可能)。
如何同时获得正确的时间并阻止不可打印的字符?
var users = ["benjamin", "nick", "joe", "tyler"];
$input = $("#input");
$input.focus();
$input.on("keyup", function() {
var message = $input.text();
var pattern = /^[@]([a-zA-Z0-9]{1,16})$/;
if(pattern.test(message)) {
var username = pattern.exec(message);
var matches = [];
users.forEach(function(element) {
if(element.indexOf(username[1]) == 0) matches.push(element);
});
if(matches.length) {
$input.text("@" + matches[0]);
var textNode = $input.get(0).childNodes[0];
var range = document.createRange();
range.setStart(textNode, message.length);
range.setEnd(textNode, matches[0].length + 1);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
}
});
#input {
border: 2px solid black;
padding: 2px 4px;
width: 200px;
box-sizing: border-box;
}
#input:focus {
outline: none;
box-shadow: 5px 5px 5px #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="input" contenteditable="true"></div>
答案 0 :(得分:0)
我发现了一些可以顺利运作的内容,但它只适用于内容可编辑<div>
而不是<input>
。
var users = ["benjamin", "nick", "joe", "tyler"];
$input = $("#input");
$input.focus();
$input.on("keypress", function(event) {
var highlight = window.getSelection().toString();
var message = $input.text();
message = message.replace(highlight, "");
message += event.key;
var pattern = /^[@]([a-zA-Z0-9]{1,16})$/;
if(pattern.test(message)) {
var username = pattern.exec(message);
var matches = [];
users.forEach(function(element) {
if(element.indexOf(username[1]) == 0) matches.push(element);
});
if(matches.length) {
event.preventDefault();
$input.text("@" + matches[0]);
var textNode = $input.get(0).childNodes[0];
var range = document.createRange();
range.setStart(textNode, message.length);
range.setEnd(textNode, matches[0].length + 1);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
}
});
#input {
border: 2px solid black;
padding: 2px 4px;
width: 200px;
box-sizing: border-box;
}
#input:focus {
outline: none;
box-shadow: 5px 5px 5px #aaa;
}
#input::selection {
background-color: #d8d8d8;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="input" contenteditable="true"></div>