[英]How can I know if an user deleted an element in a contenteditable div?
I am using jQuery to detect if an @ symbol has been inserted into a contenteditable div.我正在使用 jQuery 来检测 @ 符号是否已插入内容可编辑的 div 中。 When this is detected an ajax request is fired to the server to retrieve a list of users.
当检测到此情况时,会向服务器发出 ajax 请求以检索用户列表。 A user would then click on the username (the function adduser will fire) and it will create a disabled textarea in the div.
然后用户将单击用户名(函数 adduser 将触发),它将在 div 中创建一个禁用的文本区域。 Then I create an input dynamically with the id of the user selected as value (to notify them)
然后我动态创建一个输入,将用户的 id 选为值(通知他们)
The problem I have is that if the users delete a textarea (a username) with the keyboard or even the mouse from the contenteditable div, How do I know which textarea it is and so remove too the input which has the user id as value?我遇到的问题是,如果用户使用键盘甚至鼠标从 contenteditable div 中删除文本区域(用户名),我怎么知道它是哪个文本区域,因此也删除了以用户 ID 作为值的输入?
My script:我的脚本:
function adduser(fname, lname, id, q)
{
var fname = fname;
var lname = lname;
var id = id;
var word = '@' + q;
var iid = 'id' + id;
var old=$("#contentbox").html();
var content=old.replace(word,"");
$("#contentbox").html(content);
var E="<textarea class='textareamention' name="+id+" id="+iid+" disabled >"+fname+"</textarea>";
$("#contentbox").append(E);
$('<input/>').attr({ type: 'text', name: 'mention[]', id: id, value: id}).appendTo('#post');
}
OK, here goes ...好的,这就...
A way ahead - maybe not the only one - is to use Mutation Observers, more particularly the Mutation-summary , library - to watch your #contentbox
for changes.一种前进的方式 - 也许不是唯一的 - 是使用 Mutation Observers,尤其是Mutation-summary库 - 来观察你的
#contentbox
的变化。 The Mutation-summary documentation even mentions this particular usage case - see last bullet point under What is it useful for? Mutation-summary 文档甚至提到了这个特殊的使用案例 - 请参阅它有什么用处下的最后一个要点? .
.
The advantage over event handling is that you don't need to predict every type of event that might cause deletion of a textarea.与事件处理相比的优势在于您不需要预测可能导致文本区域删除的每种类型的事件。
A few warnings though :不过有几个警告:
Once a mutation is observed, there must be a number of ways to handle removal of a corresponding element.一旦观察到突变,必须有多种方法来处理相应元素的移除。
One way, as I suggested in the comments above, would be to loop through all the inputs and remove any of them for which its corresponding textarea no longer exists.正如我在上面的评论中所建议的那样,一种方法是遍历所有输入并删除其相应的 textarea 不再存在的任何输入。
However, I think there's a cleaner way.但是,我认为有一种更清洁的方法。
First, install the Mutation-summary , library on the page (a <script src="...">
tag, like jQuery).首先,在页面上安装Mutation-summary库(一个
<script src="...">
标签,如 jQuery)。
Then, modify adduser()
to include a custom EventListener, removeRelatedElements
, attached to your <textarea>
elements :然后,修改
adduser()
以包含附加到您的<textarea>
元素的自定义事件侦听器removeRelatedElements
:
function adduser(fname, lname, id, q) {
$('<textarea class="textareamention" name=' + id + ' id=id' + id + ' disabled>' + fname + '</textarea>')
.on('removeRelatedElements', function() {
$input.remove(); // $input is held in a closure
})
.appendTo($("#contentbox").html($("#contentbox").html().replace('@' + q, '')));
var $input = $('<input/>')
.attr({
'type': 'text',
'name': 'mention[]',
'id': id,
'value': id
})
.appendTo('#post');
}
Now, you should be able to use Mutation-summary to observe changes to #contentbox
and, when a textArea is removed, trigger its custom removeRelatedElements
event, causing the corresponding <input>
element also to be removed.现在,您应该能够使用 Mutation-summary 来观察对
#contentbox
更改,并且当删除 textArea 时,触发其自定义removeRelatedElements
事件,从而导致相应的<input>
元素也被删除。
var observer = new MutationSummary({
queries: [
{ element: '#contentbox' } // jQuery-like selector
],
callback: function(summaries) {
summaries[0].removed.forEach(function(removedEl) {
// Here, you should be able to write POJS or jQuery, or a mixture
if(removedEl.tagName.toUpperCase() === 'TEXTAREA') {
$(removedEl).trigger('removeRelatedElements').off('removeRelatedElements'); // remove the corresponding input element and detatch the custom handler to keep things clean
}
});
}
});
That's the gist of it anyway.无论如何,这就是它的要点。 You may well need to do some debugging.
您可能需要进行一些调试。
EDIT:编辑:
OK, the above attempt doesn't work due to $("#contentbox").html().replace('@' + q, '')
, which replaces the DOM hierarchy within #contentbox.好的,由于
$("#contentbox").html().replace('@' + q, '')
替换了 #contentbox 中的 DOM 层次结构,上述尝试不起作用。 In the process, our .on('removeRelatedElements', ...)
event handlers get irrevocably blitzed and thereafter .trigger('removeRelatedElements')
fails silently.在此过程中,我们的
.on('removeRelatedElements', ...)
事件处理程序不可撤销地快速启动,此后.trigger('removeRelatedElements')
静默失败。
We have to revert to "plan A".我们必须回到“A计划”。 At each mutation of
.textareamention
, you need to find and remove any input for which there is no corresponding textarea.在
.textareamention
每次.textareamention
,您需要查找并删除任何没有对应 textarea 的输入。
It's tempting to think you can simply work with summaries[0].removed
as before, but no.很容易认为您可以像以前一样简单地使用
summaries[0].removed
,但summaries[0].removed
并非如此。 The problem there is that summaries[0].removed
includes references to the textareas that were removed during the replace('@' + q, '')
process.问题在于
summaries[0].removed
包含对在replace('@' + q, '')
过程中删除的 textareas 的引用。 Consequently all corresponding input elements get removed, including the one that was just added!因此,所有相应的输入元素都会被删除,包括刚刚添加的元素! The nett effect is that the expected input never appears.
净效应是预期的输入永远不会出现。
Fortunately, the workaround is simple.幸运的是,解决方法很简单。 We can completely ignore
summaries
and work with $("#contentbox textarea.textareamention")
as a start point at each observed mutation.我们可以完全忽略
summaries
并使用$("#contentbox textarea.textareamention")
作为每个观察到的突变的起点。 Don't worry if you can't grasp this point - it's not obvious.如果您无法掌握这一点,请不要担心 - 这并不明显。 I discovered it by trial and error.
我通过反复试验发现了它。
Here's the code :这是代码:
jQuery(function($) {
var counter = 0; // integer, for associating each <textarea> with its <input>
$('#button').click(function() {
var q = " ";
$('<textarea class="textareamention ' + counter + '" disabled></textarea>') // include `counter` as a className
.text(counter) // for demo purposes
.appendTo($("#contentbox").html($("#contentbox").html().replace('@' + q, '')));
var $input = $('<input/>').attr({
'type': 'text',
'name': 'mention[]',
'value': counter // for demo purposes
})
.data('counter', counter) // bind the current counter value to this <input>
.appendTo('#post');
counter++;
});
var observer = new MutationSummary({
'queries': [
{ element: '.textareamention' }
],
'callback': function(summaries) {
// Remove all inputs for which there is no corresponding textarea.
var $textareas = $("#contentbox textarea.textareamention"); // all textareas
$("#post input").filter(function(index, element) {
return $textareas.filter('.' + $(element).data('counter')).length === 0;
}) // filter to find any input for which there is no corresponding textarea ...
.remove(); // ... and remove it/them.
}
});
});
DEMO .演示。 Note: in the fiddle, all the above code appears at the bottom of the javascript frame.
注意:在小提琴中,以上所有代码都出现在 javascript 框架的底部。
Try to register a callback function while deleting the textarea, like this:尝试在删除textarea时注册一个回调函数,如下所示:
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
function del(id) {
if (event.keyCode == 8) {
alert(id);
$("#id"+id).remove();
}
}
function adduser(fname, lname, id, q) {
var fname = fname;
var lname = lname;
var id = id;
var word = '@' + q;
var iid = 'id' + id;
var old=$("#contentbox").html();
var content=old.replace(word,"");
$("#contentbox").html(content);
var E="<textarea onkeydown='del("+id+")' class='textareamention' name="+id+" id="+iid+" >"+fname+"</textarea>";
$("#contentbox").append(E);
$('<input/>').attr({ type: 'text', name: 'mention[]', id: id, value: id}).appendTo('#post');
}
</script>
<body>
<div id='contentbox'></div>
<button onclick="adduser(123, 123, 123, 123)">Click me</button>
</body>
</html>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.