为什么JQuery on()事件处理程序没有使用contenteditable从动态生成的元素中捕获事件?

时间:2016-09-05 20:48:58

标签: javascript jquery contenteditable

我在<p>内动态生成<div contenteditable=true>标记,但我设置的事件处理程序捕获来自<p>标记的keyup事件并没有捕获它们。

HTML

<!-- Non-dynamically generated paragraph -->
<div class="note">
    <p contenteditable="true"></p>
</div>

<!-- Contains dynamically generated paragraphs -->
<div class="note" contenteditable="true"></div>

<!-- Debug output -->
<div id="output"></div>

JS

$(document).ready(function() {
    $(".note").keyup(function(evt) {
        $("#output").append("<br/>note tag keyup");
        // Surround paragraphs with paragraph tag
        $(this).contents().filter(function() {
            return this.nodeType === 3;
        }).wrap('<p class="test"></p>');
    });

    $(".note").on("keyup", "p", function(evt) {
        $("#output").append("<br/>p tag keyup");
    });
});

小提琴:https://jsfiddle.net/mibacode/axgccwoq/3/

第一个div元素演示了我可以成功地从加载时生成的段落标记中捕获keyup事件。第二个div显示我的动态生成的段落没有触发(或JQuery无法捕获)keyup事件。

修改

问题/错误似乎是如何生成段落标记并将其添加到代码的这一部分中的DOM:

$(this).contents().filter(function() {
   return this.nodeType === 3;
}).wrap('<p class="test"></p>');

我相信有些<p>代码未正确添加,因此DOM无法识别它或者不知道它存在。

编辑2: 我取代了jQuery功能,它将新的段落标签与vanilla JS一起插入,希望可以解决我的问题,但事实并非如此。

新代码:

var textNode = null;
var nodes = this.childNodes;
for (var i = 0; i < nodes.length; i++)
{
    if (nodes[i].nodeType === 3)
    {
        textNode = nodes[i];
        break;
    }
}
if (textNode)
{
    var p = document.createElement("P");
    var attr = document.createAttribute("contenteditable");
    attr.value = "true";
    p.setAttributeNode(attr);
    p.addEventListener("keyup", function() {
        $("#output").append("<br/>Special paragraph click!");
    });
    p.innerHTML = textNode.nodeValue;
    var parent = $(this)[0];
    parent.insertBefore(p, textNode);
    parent.removeChild(textNode);
}

看起来它与JS处理从特定元素中的元素触发的事件的方式有关。

1 个答案:

答案 0 :(得分:0)

唯一的问题是您在动态contenteditable代码上没有<p>属性。仅仅因为它们包含在contenteditable元素中并不能使它们可编辑 - 它们需要明确地显示属性。

在我的updated fiddle中,我简化了它,只是为了表明动态代码有效。