Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как реализовать отмена/вперёд через JS (https://javascript.ru/forum/misc/75758-kak-realizovat-otmena-vperjod-cherez-js.html)

MC-XOBAHCK 03.11.2018 23:59

Как реализовать отмена/вперёд через JS
 
Подскажите, как в js реализовуют кнопки отмена/вперёд для каких либо действий при редактировании?
Имею в виду тот же функционал что на клавиатуре делают комбинации клавиш Ctrl + Z / Ctrl + Shift + Z.

Для этого нужно писать кастомное событие с привязкой к этим кнопкам или есть какие то IP ?

j0hnik 04.11.2018 00:19

history.forward(); // эквивалентно кнопке вперед
history.back(); // эквивалентно кнопке назад

рони 04.11.2018 00:19

MC-XOBAHCK,
https://javascript.ru/forum/misc/699...tml#post460057

j0hnik 04.11.2018 00:20

так же можно использовать
history.go(-1); // страниц назад
history.go(1); // страниц вперед

j0hnik 04.11.2018 00:22

рони,
MC-XOBAHCK,
Цитата:

Сообщение от рони
https://javascript.ru/forum/misc/699...tml#post460057

так вот вы о чем..

MC-XOBAHCK 04.11.2018 00:29

Не, по истории посещённых страниц браузера гонять это не то. А я так обрадовался сначала....

Мне нужно тот же функционал что на клавиатуре делают комбинации клавиш Ctrl + Z / Ctrl + Shift + Z

Допустим в textarea (можно прям в этой форме комментариев) из текста вырезаю пару параграфов, потом вдруг осознаю что я болван и не то вырезал, нажимаю Ctrl + Z и удалённые параграфы возвращаются назад. Теперь я не болван а красавчег.

Вот эту же штуку хочу повесить на две кнопочки назад/вперёд.

рони 04.11.2018 01:02

MC-XOBAHCK,
массив значений textarea хранить

MC-XOBAHCK 04.11.2018 01:30

Цитата:

Сообщение от рони (Сообщение 497803)
MC-XOBAHCK,
массив значений textarea хранить

А не знаете, у браузера нет доступных для этого IP ?
По умолчанию ведь в нём где то это всё сохраняется. Если на странице поменять несколько инпутов, текстария, таблицу доступную для редактирования, то на клавиатуре Ctrl + Z / Ctrl + Shift + Z можно туда-сюда гонять по всей истории изменений на странице.

Если в браузере это всё уже хранится, при чём очень классно, то зачем создавать и хранить это всё в массиве?

Я вот думаю если нет для этого доступных IP, то наверное проще написать кастомное событие вызывающее комбинации этих клавишь.
По идее должно что то быть. Наверное это тоже что то из BOM.

j0hnik 04.11.2018 02:06

наверное API, а не IP
document.execCommand('undo'); // отменить последние действие
document.execCommand('redo'); // Повтор последнего действия

доступные команды можете посмотреть тут
https://developer.mozilla.org/ru/doc...nt/execCommand

j0hnik 04.11.2018 02:08

<textarea></textarea>
	<button id="zzz">ctrl+Z</button>
	<button id="yyy">ctrl+Y</button>
	<script>
		zzz.onclick = e => document.execCommand('undo');
		yyy.onclick = e => document.execCommand('redo');
	</script>


напишите что нибудь, пощелкайте кнопки

MC-XOBAHCK 04.11.2018 02:37

Цитата:

Сообщение от j0hnik (Сообщение 497807)
наверное API, а не IP

Да, API. Я в чужом тексте наверное увидел бы и заметил, а когда сам писал даже не задумывался и вряд ли когда обнаружил бы такой прокол.

Спасибо! Это именно то что мне нужно.

MC-XOBAHCK 04.11.2018 02:49

zzz.onclick = e => document.execCommand('undo');
yyy.onclick = e => document.execCommand('redo');

А можно спросить, часто здесь и в учебнике вижу в коде как дом-элементы по id пишут в короткой форме:
zzz.onclick и yyy.onclick

Так можно всегда писать или это примочки сайта, а в коде следует писать document.querySelector('#zzz')

j0hnik 04.11.2018 07:27

MC-XOBAHCK,
http://w3c.github.io/html/browsers.h...-window-object
браузеры поддерживают, но в боевом коде рекомендуют по старинке.

рони 04.11.2018 08:04

MC-XOBAHCK,
j0hnik,
ввожу четыре символа, как мне вернутся к состоянию, когда было 2 символа, а затем когда было 3?

j0hnik 04.11.2018 08:15

рони,
<textarea id="text"></textarea>
	<button id="zzz">ctrl+Z</button>
	<button id="yyy">ctrl+Y</button>
	<script>

		text.oninput = e => {
			text.blur();
			text.focus();
		};
		zzz.onclick = e =>document.execCommand('undo');
		yyy.onclick = e => document.execCommand('redo');
</script>

рони 04.11.2018 08:26

j0hnik,
:)

Malleys 04.11.2018 08:30

Если использовать стандартное сочетание Command-Z, то оно откатит вас к состоянию, когда вы сфокусировались на элементе. Command-Shift-Z возвратит к исходному. Чтобы это происходило по одному символу, нужно потерять и сразу возвратить фокус. Но действительно ли это нужно? Я считаю, что это усложнение. Мне показалось, что по словам лучше, наверное для разных целей подойдёт разный откат.

<button onclick="document.execCommand('undo')">Отменить</button>
<button onclick="document.execCommand('redo')">Возвратить</button>
<p>
  <textarea oninput="" placeholder="Стандартный откат"></textarea>
  <textarea oninput="this.blur();this.focus();" placeholder="по одному символу"></textarea>
  <textarea oninput="if(/[\s,.!?]/.test(event.data)) { this.blur();this.focus(); }" placeholder="по слову"></textarea>
</p>


Кнопки должны быть рядом с текстовым полем, или более точней они должны быть в поле видимости, ведь во время отката, фокус может переместиться с кнопки на элемент, а на планшете или телефоне нет возможности нажать Command-Z. Я к тому, что на сенсорных устройствах может не быть возможности совершить такой откат, кроме того, чтобы нажать на нашу придуманную кнопку.

Цитата:

Сообщение от MC-XOBAHCK
часто здесь и в учебнике вижу в коде как дом-элементы по id пишут в короткой форме

В стандарте HTML 5.2 о поимённом доступе к элементам сказано:

Цитата:

Возвращает указанный элемент или коллекцию элементов.
Как правило, полагаясь на это, вы получите ломающийся код. То, какие идентификаторы перестанут подходить к этому API, может меняться со временем, так как, например, новые функции добавляются к веб-платформе. Вместо этого используйте document.getElementById() или document.querySelector ().
Например, если у вашего элемента идентификатор alert, то он не может быть получен при помощи этого API, поскольку функция с соответствующим именем уже определена в глобальном контексте. (alert-у присвоена именно функция)

Важно понимать, что это происходит именно из-за того, что идентификаторы в глобальном контексте используются, где может произойти конфликт с другими, уже назначенными свойствами объекта window.

Конечно это можно исправить...
for(const element of document.querySelectorAll("[id]")) {
	window[element.id] = element;
}

Но лучше поимённый доступ к элементам сделать не через глобальный объект, а через свой. И даже гарантированно будет работать
Цитата:

Сообщение от j0hnik
в боевом коде

const $ = {};

for(const element of document.querySelectorAll("[id]")) {
	$[element.id] = element;
}

// пример
$.zzz.onclick = e => document.execCommand('undo');
$.yyy.onclick = e => document.execCommand('redo');
Правда, классно?

Или даже так...
const $ = new Proxy({}, { get(_, id) { return document.getElementById(id) } });

// пример
$.zzz.onclick = e => document.execCommand('undo');
$.yyy.onclick = e => document.execCommand('redo');

Вообще супер, правда?

MC-XOBAHCK 04.11.2018 17:36

Цитата:

Сообщение от Malleys
Кнопки должны быть рядом с текстовым полем, или более точней они должны быть в поле видимости

У меня при фокусе на элементе сделана подсветка через стили, поэтому я потерю фокуса сразу увидел и осознал. Кнопки сделал так как вы говорите - в поле видимости и в кастомном контекстном меню на элементе.

Цитата:

Сообщение от Malleys
Правда, классно?

Да
Цитата:

Сообщение от Malleys
Вообще супер, правда?

Правда.

Я так смотрю на этот код и если правильно понимаю, то во всём этом есть своя определённая выгода, пока непонятная мне. Прописать querySelector('#') меня не обременяет.
Наверное это очень удобно применять на элементы сгенерированные приложением.

После вашего решения с объединением ячеек, я как по щелчку внезапно для себя перешёл с функционального стиля написания кода на объектно-ориентированный. Теперь у меня всё по полочкам. Внедрить в приложение данное решение теперь для меня сущий пустяк. Буду пробовать и осознавать в чём выгода.


Часовой пояс GMT +3, время: 19:14.