Сделать историю?
Доброй ночи! Мои мозги закипают уже :help:
Имеется набор функций моего редактора, перед выполнением каждой фукции я сохраняю прошлый результат всего редактора в массив. Есть кнопка "Вернуть" при нажатии возвращается преведущий результат... Дело в том что такой способ полностью работает, но так как я в массив заношу каждый раз огромный код сжатый код, хотелось бы ограничить "Возвращение" до 10 этапов Как реализовано у меня: Заход1: Меняем данные в редакторе и пытаемся вернутся back(); => удивительно но работает сколько бы раз не возвращались (до 10) Заход2: Пытаемся после возвращений что-то изменить данные редактора и пытаемся вернутся back(); => не хочет возвращаться вообще h_i = 1; // указал единицу так как в массиве первый ключ 1 history = []; addhistory(); // Запускаю первый раз что бы добавить данные "как есть" function addhistory() { content = '';//тут я загоняю сгенерированный код редактором в JSON if( history.length > 11 ) { // на 10 раз h_i = 1; history = []; } history.unshift(content); } function back() { if( history.length > h_i ) { //смотрим что-бы хватало истории readcontent( history[ h_i ] ); // возвращаем предыдущие данные h_i++; } } |
Цитата:
копируй или смещай элементы массива вперед, в конец добавляй последний результат сохранения |
Делал вместо очистки .pop() все работало! Но если по второму кругу нажимать back() то в массиве были данные из первого круга и возвращалось то что было в первом круге а не во втором
|
Цитата:
<input> <button>save</button> <script> document.querySelector("button").addEventListener("click", function () { if (!this.mas) this.mas = []; if (this.mas.length > 9) this.mas.shift(); this.mas.push(this.previousElementSibling.value); console.log(this.mas); }); </script> |
опиши логику переходов по истории
<input> <button class="save">save</button> <button class="back">back</button> <button class="forward">forward</button> <script> function addElement(element, mas, limit) { if (mas.length > limit - 1) mas.shift(); mas.push(element); } document.querySelector(".save").addEventListener("click", function () { var backBut = document.querySelector(".back"); delete backBut.n; if (!this.mas) this.mas = []; var input = document.querySelector("input"); addElement(input.value, this.mas, 10); input.select(); console.log(this.mas); }); document.querySelector(".back").addEventListener("click", function () { var saveBut = document.querySelector(".save"); if (!saveBut.mas) saveBut.mas = []; mas = saveBut.mas; if (this.n == undefined) { (!mas.length) ? this.n = 0 : this.n = mas.length - 1; } (this.n <= 0) ? this.n = 0 : this.n--; document.querySelector("input").value = mas[this.n]; console.log("n=" + this.n + "; mas[n]=" + mas[this.n]); }); </script> |
Цитата:
есть массив (очередь), и есть указатель на текущий пункт в нем. Всё что перед указателем - "область повторов", прочее - "область отмен" (обе области могут быть пустые). Функция undo - если есть команды в "области отмен", отменяем команду, на которой стоит указатель, перемещаем оный на шаг назад. Функция redo - если есть команды в "области повторов", перемещаем указатель на шаг вперед и выполняем команду под ним. Функция action (юзер хочет что-то сделать) - удаляем всё из "области повторов", формируем команду, ставим перед указателем, делаем redo. Если в очереди стало больше 10 элементов, удаляем самый старый. Каждый элемент в очереди - команда, которую можно выполнить или отменить. |
Цитата:
save - action - удаляем все предыдущие элементы массива перед текущим, добавляем элемент в конец массива back - undo - переходим на предыдущий элемент массива, если он есть forward - redo - переходим на последующий элемент массива, если он есть так? |
Цитата:
action и redo у меня не зависимы, action происходит в редакторе, а redo конкретно по кнопке исполняется var history = []; var ukazatel; function redo() { if( ! history[ ukazatel + 1 ] ) { return false; //Нет в области повторов } ukazatel++; command = history[ ukazatel ]; //Выполняем } function undo() { if( ! history[ ukazatel - 1 ] ) { return false; //Нет в области отмен } command = history[ ukazatel ]; //Отмена ukazatel--; } function action() { if( ukazatel == undefined ) ukazatel = 1; else ukazatel++; history[ ukazatel-1 ] = COMMAND; // Добавляем команду if( history.length > 10 ) { history.pop(); // Удаляем последний элемент } } |
Вот набросок очереди команд:
function CommandQueue(limit) { this._limit = limit || 10; this._arr = []; this._pointer = -1; } CommandQueue.prototype.undoCount = function() { return this._pointer + 1; }; CommandQueue.prototype.redoCount = function() { return this._arr.length - this._pointer - 1; }; CommandQueue.prototype.undo = function() { if (!this.undoCount()) { return false; } this._arr[this._pointer].undo(); this._pointer--; return true; }; CommandQueue.prototype.redo = function() { if (!this.redoCount()) { return false; } this._pointer++; this._arr[this._pointer].redo(); return true; }; CommandQueue.prototype.action = function(command) { this._arr.splice(this._pointer + 1, this.redoCount(), command); this.redo(); if (this._arr.length > this._limit) { this._arr.shift(); this._pointer--; } }; использование: var q = new CommandQueue(10); q.action({ undo: function() {...}, redo: function() {...} }); |
Спасибо, вы очень помогли. Разобрался. Вопрос решен
|
Часовой пояс GMT +3, время: 19:56. |