Вопрос:

контекстные события изменения

javascript jquery html5 contenteditable

179484 просмотра

18 ответа

12612 Репутация автора

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

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

Автор: Jourkey Источник Размещён: 07.09.2009 11:15

Ответы (18)


0 плюса

578528 Репутация автора

Событие onchange не срабатывает, когда элемент с атрибутом contentEditable изменяется, предлагаемым подходом может быть добавление кнопки, чтобы «сохранить» издание.

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

Автор: CMS Размещён: 07.09.2009 11:56

242 плюса

245205 Репутация автора

Решение

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

ОБНОВЛЕНИЕ 29 октября 2014 года

HTML5 inputсобытие является ответом в долгосрочной перспективе. На момент написания он поддерживается для contenteditableэлементов в современных браузерах Mozilla (от Firefox 14) и WebKit / Blink, но не в 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/

Автор: Tim Down Размещён: 11.09.2009 02:39

0 плюса

81 Репутация автора

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

Автор: joox Размещён: 09.05.2010 06:19

-1 плюса

1522 Репутация автора

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

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

Автор: Lawrence Whiteside Размещён: 17.08.2010 03:14

19 плюса

967 Репутация автора

Я так изменил ответ закона, и это работает для меня. Я использую событие 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')});
Автор: Dennkster Размещён: 13.09.2010 02:06

3 плюса

39 Репутация автора

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

   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);
            }
   });
Автор: gregory whiteside Размещён: 28.01.2011 09:09

2 плюса

29 Репутация автора

Вот решение, которое я в конечном итоге использовал и работает сказочно. Я использую $ (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!');
    }
});
Автор: user740433 Размещён: 05.05.2011 05:22

173 плюса

30705 Репутация автора

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

$('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

Автор: balupton Размещён: 07.06.2011 09:54

0 плюса

247 Репутация автора

Использование 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

Автор: janfabian Размещён: 28.02.2012 02:33

3 плюса

67 Репутация автора

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

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

https://gist.github.com/3410122

Обновить:

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

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

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

Автор: tracend Размещён: 21.08.2012 07:36

47 плюса

2194 Репутация автора

Рассмотрим использование MutationObserver . Эти наблюдатели предназначены для реагирования на изменения в DOM и в качестве замены исполнителей на Mutation Events .

Плюсы:

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

Минусы:

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

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

  • Я написал небольшой фрагмент, чтобы сравнить использование MutationObserers для обработки различных событий. Я использовал код балуптона, так как его ответ имеет самые высокие показатели.
  • Mozilla имеет отличную страницу в API
  • Взгляните на библиотеку MutationSummary
Автор: jrullmann Размещён: 26.12.2012 05:24

0 плюса

33857 Репутация автора

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

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

Автор: Blowsie Размещён: 04.06.2013 04:22

20 плюса

1512 Репутация автора

не 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);
});
Автор: Developia Размещён: 11.10.2015 12:10

0 плюса

390 Репутация автора

Простой ответ в 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
        }           
    });
Автор: sarath Размещён: 29.03.2016 09:44

-2 плюса

1734 Репутация автора

Нет ответа 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'))

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

Автор: DrMcCleod Размещён: 17.05.2016 09:09

-2 плюса

19016 Репутация автора

Основываясь на ответе @ 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>

Автор: Phillip Senn Размещён: 30.08.2017 06:25

0 плюса

848 Репутация автора

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

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/MutationObserver

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 });
Автор: bit-less Размещён: 14.03.2018 08:23

0 плюса

151 Репутация автора

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: 'textContent',
  subtree: true,
})
<p contenteditable>abc</p>
<div />

Автор: superwf Размещён: 07.11.2018 10:29
Вопросы из категории :
32x32