【问题标题】:trigger an event when contenteditable is changed当 contenteditable 改变时触发事件
【发布时间】:2011-09-09 12:35:52
【问题描述】:

当一个div的值发生变化时,如何触发事件?

<div class="changeable" contenteditable="true"> Click this div to edit it <div>

所以当它的内容发生变化时,我想创建一个警报和/或做其他事情:

$('.changeable').text().change(function() {
  alert('Handler for .change() called.');
});

【问题讨论】:

标签: jquery contenteditable


【解决方案1】:

只需将内容存储到一个变量中,并在blur() 事件之后检查它是否不同。如果不同,则存储新内容。

var contents = $('.changeable').html();
$('.changeable').blur(function() {
    if (contents!=$(this).html()){
        alert('Handler for .change() called.');
        contents = $(this).html();
    }
});

示例:http://jsfiddle.net/niklasvh/a4QNB/

【讨论】:

  • 非常感谢@Niklas!
  • 这是一个肮脏的hack,不应该使用。
  • 修改@Niklas 代码并添加新答案here
  • 不适用于我的 Chrome 65 - 仅在“模糊”(聚焦)时。
【解决方案2】:

这是一个 jquery 版本:

function fix_contenteditableOnchange(obj)
{
     div=$(obj);
     var contents = div.html();
     var onchange = div.attr('onchange');
     div.blur(function() {
      if (contents!=$(this).html()){
        eval(onchange);
        fix_contenteditableOnchange(obj);
      }
     });
}

试试这个。

【讨论】:

  • 为什么是递归调用?你能做contents = $(this).html()吗?
【解决方案3】:

这是我的方法...

$('.changeable').focusout(function() {
  alert('Handler for .change() called.');
});

【讨论】:

    【解决方案4】:

    使用 EventListener(不是 jQuery 方法)更简单:

    document.getElementById("editor").addEventListener("input", function() { alert("输入事件触发"); }, 错误的);

    【讨论】:

    • 这适用于最近的 Mozilla 和 WebKit 浏览器,但遗憾的是,IE 或 Opera 的任何版本都不支持 contenteditable
    • 这也可以与 jquery 一起使用,以便更容易地附加到类,$('.class').on('input', function(){})
    【解决方案5】:

    为此我构建了一个 jQuery 插件。

    (function ($) {
        $.fn.wysiwygEvt = function () {
            return this.each(function () {
                var $this = $(this);
                var htmlold = $this.html();
                $this.bind('blur keyup paste copy cut mouseup', function () {
                    var htmlnew = $this.html();
                    if (htmlold !== htmlnew) {
                        $this.trigger('change')
                    }
                })
            })
        }
    })(jQuery);
    

    您可以直接拨打$('.wysiwyg').wysiwygEvt();

    如果您愿意,您还可以删除/添加事件

    【讨论】:

    • that.bind(...) 中的that 是什么?
    • blur keyup paste copy cut mouseup 是所有潜在的变化事件
    • that.bind(...) 应该是$this.bind(...)
    • 这很好,除了 htmlold 需要更新更改。否则,如果它变回原来的 htmlold,则该事件不会触发。
    【解决方案6】:

    另一种解决方案,它对以前的版本稍作修改,但对你们中的某些人来说使用起来可能更舒服。

    想法是保存原始值并将其与“模糊”事件中的当前值进行比较。我将原始值保存为可编辑 div 标签的属性(而不是为原始值创建变量)。当表格中有大量可编辑的 div(作为单元格)时,使用属性作为原始值的容器会更舒服。因为不需要创建很多变量,所以很容易获得原始值。

    查看我的完整示例代码:

    可编辑的 div

    <td><div contenteditable="true" class="cell" origin="originValue">originValue</div></td>
    

    检测模糊的变化

    var cells = $("#table").find('td>div[contenteditable=true]');
    
    cells.each(function () {    
    
            $(this).blur(function() {
    
                        if ($(this).text() != $(this).attr("origin")) {
                            console.log('changed');
                        }
            });    
    });
    

    【讨论】:

    • 这不是一个好方法。您的 originalValue 可能包含无效的 html,但浏览器将始终尝试在可编辑的 div 中修复它,因此即使内容实际上没有更改,您的测试条件也会失败,因为浏览器已将您的
      转换为
      跨度>
    • 未来我会为此使用数据标签,而且效果很好!
    【解决方案7】:

    您可以简单地将焦点/模糊事件与 jQuery 的 data() 函数一起使用:

    // Find all editable content.
    $('[contenteditable=true]')
        // When you click on item, record into data("initialText") content of this item.
        .focus(function() {
            $(this).data("initialText", $(this).html());
        });
        // When you leave an item...
        .blur(function() {
            // ...if content is different...
            if ($(this).data("initialText") !== $(this).html()) {
                // ... do something.
                console.log('New data when content change.');
                console.log($(this).html());
            }
        });
    });
    

    更新:使用 Vanilla JS

    // Find all editable content.
    var contents = document.querySelectorAll("[contenteditable=true]");
    [].forEach.call(contents, function (content) {
        // When you click on item, record into `data-initial-text` content of this item.
        content.addEventListener("focus", function () {
            content.setAttribute("data-initial-text", content.innerHTML);
        });
        // When you leave an item...
        content.addEventListener("blur", function () {
            // ...if content is different...
            if (content.getAttribute("data-initial-text") !== content.innerHTML) {
                // ... do something.
                console.log("New data when content change.");
                console.log(content.innerHTML);
            }
        });
    });
    

    【讨论】:

    • +1 是我(未发布的)问题的唯一解决方案“您如何检测编辑何时开始?”...因此您可以显示保存按钮等...所有相关问题都集中在在检测更改时,而不是在编辑会话开始时...
    • +1 用于展示如何处理所有可编辑元素,而无需专门引用 id。非常适合使用 html 表格创建简单的可编辑网格。
    【解决方案8】:

    在 chrome 和其他浏览器中可能存在错误,当用户按下选项卡时,它将创建空间并附加 apple-be span 或类似的东西.. 以删除该用户

    var contents = $('.changeable').html();
    $('.changeable').blur(function() {
       if (contents!=$(this).html()){
     alert('Handler for .change() called.');
          $(".Apple-tab-span").remove();
           contents = $(this).html();
           contentsTx = $(this).text();
           alert(contentsTx);
    
       }
    });
    

    这将删除跨度.. 和上面的代码一样,只是稍微修改了一下,或者你可以添加

    .Apple-tab-span
    {
      Display:None;
    }
    

    这也将解决问题.. http://jsfiddle.net/a4QNB/312/

    刚刚修改了@Nikals 的答案...

    【讨论】:

      【解决方案9】:

      jquery 中的另一个版本。在 jsFiddle here 中查看。

      var $editableContent = $("#mycontent");
      
      //  Implement on text change
      $editableContent.on("focus", function(event) {$(this).data("currentText", $(this).text());});
      
      $editableContent.on("blur", function (event) {
              if ($(this).text() != $(this).data("currentText")) {
                      $(this).trigger('change');}});
      
      
      //  Wire onchange event
      $editableContent.on("change", function(){alert("Text changed to: " + $(this).text())});
      

      【讨论】:

        【解决方案10】:

        目前最好的解决方案是 HTML5 input event

        &lt;div contenteditable="true" id="content"&gt;&lt;/div&gt;

        在你的 jquery 中。

        $('#content').on('input', (e) => {
            // your code here
            alert('changed')
        });
        

        【讨论】:

        • 效果很好! ?
        • 这应该是公认的答案——我认为它是最直接也是最好的答案。
        • 唯一的问题是每次按键都会触发input,而在输入所有输入后最后会触发change - 对于我的情况,我需要一个不输入的更改事件跨度>
        【解决方案11】:

        您需要做的是在您的 contenteditable 元素上组合 blurDOMSubtreeModified 事件。

        var contentEdited = false;
        
        function fn($el) {
          if (contentEdited) {
            var text = $el[0].innerText.trim();
            console.log(text);
            contentEdited = false;
          }
        }
        $("div.editable").on("blur", function() {
          fn($(this));
        }).on("DOMSubtreeModified", function() {
          contentEdited = true;
        });
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        
        <div class="editable" contenteditable="true">Click this div to edit it<div>

        【讨论】:

        【解决方案12】:

        function myFunction(){
          alert('Handler for .change() called.');
        }
        &lt;div class="changeable" contenteditable="true" onfocusout="myFunction()" &gt; Click this div to edit it &lt;div&gt;

        【讨论】:

        • 谢谢伙计。你的解决方案帮助了我
        • 当我在表格单元格上使用您的代码时,我想修改一个特定的列值,警报会无限持续。我使用了 onfocus 和 onfocusout,同样的事情发生了。我想要的只是当我移动到上方或下方的新单元格时捕获新值。 onchange 也不起作用。
        猜你喜欢
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 2016-11-21
        • 1970-01-01
        • 1970-01-01
        • 2013-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多