Вход

Просмотр полной версии : Сделать историю?


makar3000
07.01.2015, 01:30
Доброй ночи! Мои мозги закипают уже :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++;
}
}

bes
07.01.2015, 11:28
 if( history.length > 11 ) { // на 10 раз
     h_i = 1;
     history = [];
   }

то есть ты каждый раз обнуляешь после 11 сохранений
копируй или смещай элементы массива вперед, в конец добавляй последний результат сохранения

makar3000
07.01.2015, 14:37
Делал вместо очистки .pop() все работало! Но если по второму кругу нажимать back() то в массиве были данные из первого круга и возвращалось то что было в первом круге а не во втором

bes
07.01.2015, 15:22
Делал вместо очистки .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>

bes
07.01.2015, 17:15
опиши логику переходов по истории


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

Яростный Меч
07.01.2015, 17:51
опиши логику переходов по истории
Обычно логика такая (если по уму делать):

есть массив (очередь), и есть указатель на текущий пункт в нем. Всё что перед указателем - "область повторов", прочее - "область отмен" (обе области могут быть пустые).

Функция undo - если есть команды в "области отмен", отменяем команду, на которой стоит указатель, перемещаем оный на шаг назад.

Функция redo - если есть команды в "области повторов", перемещаем указатель на шаг вперед и выполняем команду под ним.

Функция action (юзер хочет что-то сделать) - удаляем всё из "области повторов", формируем команду, ставим перед указателем, делаем redo. Если в очереди стало больше 10 элементов, удаляем самый старый.


Каждый элемент в очереди - команда, которую можно выполнить или отменить.

bes
07.01.2015, 18:46
Обычно логика такая (если по уму делать):

есть массив (очередь), и есть указатель на текущий пункт в нем. Всё что перед указателем - "область повторов", прочее - "область отмен" (обе области могут быть пустые).

Функция undo - если есть команды в "области отмен", отменяем команду, на которой стоит указатель, перемещаем оный на шаг назад.

Функция redo - если есть команды в "области повторов", перемещаем указатель на шаг вперед и выполняем команду под ним.

Функция action (юзер хочет что-то сделать) - удаляем всё из "области повторов", формируем команду, ставим перед указателем, делаем redo. Если в очереди стало больше 10 элементов, удаляем самый старый.


Каждый элемент в очереди - команда, которую можно выполнить или отменить.

отобрази на мой пример с тремя кнопками
save - action - удаляем все предыдущие элементы массива перед текущим, добавляем элемент в конец массива
back - undo - переходим на предыдущий элемент массива, если он есть
forward - redo - переходим на последующий элемент массива, если он есть
так?

makar3000
07.01.2015, 21:13
Обычно логика такая (если по уму делать):

есть массив (очередь), и есть указатель на текущий пункт в нем. Всё что перед указателем - "область повторов", прочее - "область отмен" (обе области могут быть пустые).

Функция undo - если есть команды в "области отмен", отменяем команду, на которой стоит указатель, перемещаем оный на шаг назад.

Функция redo - если есть команды в "области повторов", перемещаем указатель на шаг вперед и выполняем команду под ним.

Функция action (юзер хочет что-то сделать) - удаляем всё из "области повторов", формируем команду, ставим перед указателем, делаем redo. Если в очереди стало больше 10 элементов, удаляем самый старый.


Каждый элемент в очереди - команда, которую можно выполнить или отменить.

Что-то я не понял, так что-ли?:

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(); // Удаляем последний элемент
}
}

Яростный Меч
07.01.2015, 21:38
Вот набросок очереди команд:

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() {...}
});

makar3000
07.01.2015, 23:22
Спасибо, вы очень помогли. Разобрался. Вопрос решен