Вопрос

Я хочу запустить функцию, когда пользователь редактирует содержание div с contenteditable атрибут. Что такое эквивалент onchange мероприятие?

Я использую jQuery, поэтому любые решения, которые используют jQuery, предпочтительнее. Спасибо!

Это было полезно?

Решение

Я бы посоветовал прикрепить слушателей к ключевым событиям, запущенным редактируемым элементом, хотя вам нужно знать, что keydown а также keypress События запущены до того, как сам контент будет изменен. Это не будет охватывать все возможные средства изменения контента: пользователь также может использовать вырезание, копирование и вставку из меню браузера редактирования или контекста, чтобы вы могли обработать cut copy а также paste События тоже. Кроме того, пользователь может сбросить текст или другой контент, поэтому там больше событий (mouseup, Например). Вы можете захотеть опросить содержимое элемента как запасную сторону.

Обновление 29 октября 2014 г.

А HTML5 input мероприятие это ответ в долгосрочной перспективе. На момент написания он поддерживается contenteditable Элементы в нынешних мозилле (из Firefox 14) и Webkit/Blink Browsers, но не IE.

Демонстрация:

document.getElementById("editor").addEventListener("input", function() {
    console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>

Демонстрация: http://jsfiddle.net/ch6yn/2691/

Другие советы

Вот более эффективная версия, которая использует on для всех довольных. Он основан на верхних ответах здесь.

$('body').on('focus', '[contenteditable]', function() {
    const $this = $(this);
    $this.data('before', $this.html());
}).on('blur keyup paste input', '[contenteditable]', function() {
    const $this = $(this);
    if ($this.data('before') !== $this.html()) {
        $this.data('before', $this.html());
        $this.trigger('change');
    }
});

Проект здесь: https://github.com/balupton/html5edit

Рассмотрим использование MutationObserver. Анкет Эти наблюдатели предназначены для реагирования на изменения в DOM и в качестве эффективности замены на Мутационные события.

Плюсы:

  • Пожары, когда Любые Происходит изменения, чего трудно достичь, прослушивая ключевые события, как предложено другими ответами. Например, все они работают хорошо: перетаскивание, курсивы, копировать/вырезать/вставить через контекстное меню.
  • Разработан с учетом производительности.
  • Простой, простой код. Гораздо легче понять и отлаживать код, который прислушивается к одному событию, а не код, который слушает 10 событий.
  • Google имеет отличный Сводная библиотека мутации что делает использование MutationObservers очень простым.

Минусы:

  • Требуется самая недавняя версия Firefox (14,0+), Chrome (18+) или IE (11+).
  • Новый API, чтобы понять
  • Еще много информации о лучших практиках или тематических исследованиях

Учить больше:

  • Я написал немного фрагмент Сравнить использование MutationObserers для обработки различных событий. Я использовал код Балуптона с его отвечать Имеет наиболее подъем.
  • Мозилла имеет отличную страницу на API
  • Взглянуть на Mutationsummary библиотека

не jquery быстро и грязный отвечать:

function setChangeListener (div, listener) {

    div.addEventListener("blur", listener);
    div.addEventListener("keyup", listener);
    div.addEventListener("paste", listener);
    div.addEventListener("copy", listener);
    div.addEventListener("cut", listener);
    div.addEventListener("delete", listener);
    div.addEventListener("mouseup", listener);

}

var div = document.querySelector("someDiv");

setChangeListener(div, function(event){
    console.log(event);
});

Я изменил ответ Lawwantsin, как и так, и это работает для меня. Я использую событие Keyup вместо Keypress, которое отлично работает.

$('#editor').on('focus', function() {
  before = $(this).html();
}).on('blur keyup paste', function() { 
  if (before != $(this).html()) { $(this).trigger('change'); }
});

$('#editor').on('change', function() {alert('changed')});

const p = document.querySelector('p')
const result = document.querySelector('div')
const observer = new MutationObserver((mutationRecords) => {
  result.textContent = mutationRecords[0].target.data
  // result.textContent = p.textContent
})
observer.observe(p, {
  characterData: true,
  subtree: true,
})
<p contenteditable>abc</p>
<div />

Два варианта:

1) Для современных (вечнозеленых) браузеров:Событие «Вход» будет действовать как альтернативное событие «Изменение».

https://developer.mozilla.org/en-us/docs/web/events/input

document.querySelector('div').addEventListener('input', (e) => {
    // Do something with the "change"-like event
});

или же

<div oninput="someFunc(event)"></div>

или (с jQuery)

$('div').on('click', function(e) {
    // Do something with the "change"-like event
});

2) Обучать IE11 и современные (вечнозеленые) браузеры:Эти часы изменений элемента и их содержимое внутри Div.

https://developer.mozilla.org/en-us/docs/web/api/mutebserver

var div = document.querySelector('div');
var divMO = new window.MutationObserver(function(e) {
    // Do something on change
});
divMO.observe(div, { childList: true, subtree: true, characterData: true });

Вот что сработало для меня:

   var clicked = {} 
   $("[contenteditable='true']").each(function(){       
        var id = $(this).attr("id");
        $(this).bind('focus', function() {
            // store the original value of element first time it gets focus
            if(!(id in clicked)){
                clicked[id] = $(this).html()
            }
        });
   });

   // then once the user clicks on save
   $("#save").click(function(){
            for(var id in clicked){
                var original = clicked[id];
                var current = $("#"+id).html();
                // check if value changed
                if(original != current) save(id,current);
            }
   });

Эта ветка была очень полезна, когда я расследовал эту тему.

Я изменил часть кода, доступного здесь, в плагин jQuery, так что он находится в повторной форме, в первую очередь для удовлетворения моих потребностей, но другие могут оценить более простой интерфейс для Jumpstart с использованием довольных тегов.

https://gist.github.com/3410122

Обновлять:

Из -за растущей популярности плагин был принят Makeites.org

Развитие будет продолжаться отсюда:

https://github.com/makesites/jquery-pantentaintaiting

Вот решение, которое я в итоге использовал и работает сказочно. Я использую $ (this) .text () вместо этого, потому что я просто использую один линейный Div, который является редактируемым контентом. Но вы также можете использовать .html () Таким образом, вам не нужно беспокоиться о объеме глобальной/неглобальной переменной, и до того, как до редактора Div на самом деле прикреплено к редактору.

$('body').delegate('#editor', 'focus', function(){
    $(this).data('before', $(this).html());
});
$('#client_tasks').delegate('.task_text', 'blur', function(){
    if($(this).data('before') != $(this).html()){
        /* do your stuff here - like ajax save */
        alert('I promise, I have changed!');
    }
});

Без jQuery ответ ...

function makeEditable(elem){
    elem.setAttribute('contenteditable', 'true');
    elem.addEventListener('blur', function (evt) {
        elem.removeAttribute('contenteditable');
        elem.removeEventListener('blur', evt.target);
    });
    elem.focus();
}

Чтобы использовать его, вызовите (скажем) элемент заголовка с id = "myheader"

makeEditable(document.getElementById('myHeader'))

Этот элемент теперь будет редактирован пользователем, пока не потеряет фокус.

Событие OnChange не стреляет, когда изменяется элемент с атрибутом с довольным, предложенным подходом может быть добавление кнопки, в "спасти" издание.

Проверьте этот плагин, который решает проблему таким образом:

Чтобы избежать таймеров и кнопок «Сохранить», вы можете использовать размытое событие, когда стреляет, когда элемент теряет фокус. Но чтобы быть уверенным, что элемент был фактически изменен (не только сфокусирован и дефокус), его содержание следует сравнить с его последней версией. Или используйте событие Keydown, чтобы установить «грязный» флаг на этом элементе.

С использованием DomCharacterDatamodified в рамках MutationEvents приведет к тому же. Тайм -аут установлен для предотвращения отправки неправильных значений (например, в Chrome у меня были некоторые проблемы с космическим ключом)

var timeoutID;
$('[contenteditable]').bind('DOMCharacterDataModified', function() {
    clearTimeout(timeoutID);
    $that = $(this);
    timeoutID = setTimeout(function() {
        $that.trigger('change')
    }, 50)
});
$('[contentEditable]').bind('change', function() {
    console.log($(this).text());
})

Пример JSFiddle

Я построил плагин 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();

Вы также можете удалить / добавить события, если хотите

Простой ответ в jQuery, я только что создал этот код и подумал, что он будет полезен и для других

    var cont;

    $("div [contenteditable=true]").focus(function() {
        cont=$(this).html();
    });

    $("div [contenteditable=true]").blur(function() {
        if ($(this).html()!=cont) {
           //Here you can write the code to run when the content change
        }           
    });

Проверьте эту идею.http://pastie.org/1096892

Я думаю, что это близко. HTML 5 действительно должен добавить событие изменения в спецификацию. Единственная проблема заключается в том, что функция обратного вызова оценивает if (до == $ (this) .html ()) до того, как контент фактически обновляется в $ (this) .html (). Settimeout не работает, и это грустно. Дайте мне знать, что вы думаете.

Основано на ответе @Balupton:

$(document).on('focus', '[contenteditable]', e => {
	const self = $(e.target)
	self.data('before', self.html())
})
$(document).on('blur', '[contenteditable]', e => {
	const self = $(e.target)
	if (self.data('before') !== self.html()) {
	  self.trigger('change')
	}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top