Как эффективно хранить (небольшие) обновления в 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>

Если вам нужна функция "Повторить", создайте еще один атрибут для хранения последнего значения отмены, чтобы можно было отменить отмену.

Другие вопросы по тегам