Как эффективно хранить (небольшие) обновления в html для пользовательского стека отмены в javascript?
Я строю CMS с помощью contenteditable
(сравнимо с алоха например). Я чиню патчи ctrl+z / ctrl+y (отменить / повторить), так как некоторые команды не могут быть выполнены с нативным document.execCommand
и поэтому не попадайте в нативный стек отмены.
Поэтому я хочу сам реализовать эффективный откат стека. Поскольку записи в таком стеке будут иметь небольшие отличия в html (по крайней мере, в большинстве случаев), кажется логичным использовать для хранения какое-то кодирование delta / diff.
Есть ли там что-нибудь (javascript), которое бы хорошо покрывало этот сценарий? В качестве альтернативы, другие / лучшие способы сделать это?
1 ответ
Некоторые моменты, которые необходимо учитывать в вашей реализации:
- сохранить очки
- место хранения
- поиск
В целях иллюстрации я собираюсь использовать кнопку "Отменить", кнопку "Сохранить" и текстовое поле.
Вы можете использовать интервал / таймер для автоматического сохранения изменений при каждом изменении текстового поля; или вы можете положиться на кнопку "Сохранить", чтобы явно создать точки сохранения.
Реализация таймера сравнивает текущий текст с предыдущим снимком. Если текст изменяется и прошло достаточно времени, создается точка сохранения. Вы можете использовать событие onkeyup для запуска автосохранения.
Следующим пунктом является хранение. Если прерывистые изменения не должны сохраняться, вы можете использовать память в памяти; или просто функции JavaScript. Присоедините объект "history" к элементу DOM. В этом случае объект textarea.
<button onclick="undo();">Undo</button>
<textarea id="text" onkeyup="autosave()"></textarea>
<script>
function autosave(){
var text=document.getElementById('text');
var date=new Date(); var now=date.getTime();
if (text.lastsaved==null) text.lastsaved=now;
if (now-text.lastsaved<5000) return; //ignore changes within 5 seconds
if (text.savetimer) clearTimeout(text.savetimer);
text.savetimer=setTimeout(function(){
if (!text.undohist) text.undohist=[];
text.undohist.push(text.value); //save a snapshot
text.lastsaved=now;
}, 300); //if keys are continuously pressed, wait until it "settles down"
}
function undo(){
var text=document.getElementById('text');
var date=new Date(); var now=date.getTime();
if (!text.undohist) return; //cannot undo any more
if (text.undohist.length==0) return;
text.value=text.undohist.pop();
text.lastupdated=now;
}
</script>
Если вам нужна функция "Повторить", создайте еще один атрибут для хранения последнего значения отмены, чтобы можно было отменить отмену.