Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions 2-ui/4-forms-controls/3-events-change-input/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
```smart header="Нельзя ничего предотвратить в `oninput`"
Событие `input` происходит после изменения значения.

Поэтому мы не можем использовать `event.preventDefault()` там - будет уже слишком поздно, никакого эффекта не будет.
Поэтому мы не можем использовать `event.preventDefault()` там -- уже слишком поздно, никакого эффекта не будет.
```

## События: cut, copy, paste
Expand All @@ -61,25 +61,46 @@

Мы также можем использовать `event.preventDefault()` для предотвращения действия по умолчанию, и в итоге ничего не скопируется/не вставится.

Например, код, приведённый ниже, предотвращает все подобные события и показывает, что мы пытаемся вырезать/копировать/вставить:
Например, код, приведённый ниже, предотвращает все `cut/copy/paste` события и показывает текст, который мы пытаемся вырезать/копировать/вставить:

```html autorun height=40 run
<input type="text" id="input">
<script>
input.oncut = input.oncopy = input.onpaste = function(event) {
alert(event.type + ' - ' + event.clipboardData.getData('text/plain'));
return false;
input.onpaste = function(event) {
alert("paste: " + event.clipboardData.getData('text/plain'));
event.preventDefault();
};

input.oncut = input.oncopy = function(event) {
alert(event.type + '-' + document.getSelection());
event.preventDefault();
};
</script>
```

Технически, мы можем скопировать/вставить всё. Например, мы можем скопировать файл из файловой системы и вставить его.
Обратите внимание: внутри обработчиков событий `cut` и `copy` вызов `event.clipboardData.getData(...)` возвращает пустую строку. Это потому, что технически данные ещё не находятся в буфере обмена. Если мы используем `event.preventDefault()` они вообще не будут скопированы.

Поэтому в приведённом выше примере используется `document.getSelection()` для получения выделенного текста. Более подробную информацию о выделении в документе можно найти в главе <info:selection-range>.

Возможно копирование/вставка не только текста, но и любых данных. Например, мы можем скопировать файл в файловом менеджере ОС и вставить его.

Это потому, что `clipboardData` реализует интерфейс `DataTransfer`, обычно используемый для перетаскивания и копирования/вставки. Сейчас это немного выходит за рамки нашего рассмотрения, но вы можете найти его методы в [спецификации DataTransfer](https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface).

Кроме того, существует дополнительный асинхронный API для доступа к буферу обмена: `navigator.clipboard`. Подробнее -- в спецификации [Clipboard API and events](https://www.w3.org/TR/clipboard-apis/), [не поддерживается в Firefox](https://caniuse.com/async-clipboard).

## Ограничения безопасности

Буфер обмена работает глобально, на уровне ОС. Пользователь может переключаться между приложениями, копировать/вставлять различные данные, и страница браузера не должна всё это видеть.

Поэтому большинство браузеров разрешают беспрепятственный доступ к буферу обмена для чтения/записи только в рамках определённых действий пользователя, таких как копирование/вставка и т.д.

Запрещено генерировать "пользовательские" события буфера обмена с помощью `dispatchEvent` во всех браузерах, кроме Firefox. И даже если нам удастся создать такое событие, спецификация чётко указывает, что такие "синтетические" события не должны предоставлять доступ к буферу обмена.

Существует список методов [в спецификации](https://www.w3.org/TR/clipboard-apis/#dfn-datatransfer) для работы с различными типами данных, чтения/записи в буфер обмена.
Даже если кто-то решит сохранить `event.clipboardData` в обработчике событий, а затем обратиться к нему позже -- это не сработает.

Но обратите внимание, что буфер обмена работает глобально, на уровне ОС. Большинство браузеров в целях безопасности разрешают доступ на чтение/запись в буфер обмена только в рамках определённых действий пользователя, к примеру, в обработчиках событий `onclick`.
Повторим: [event.clipboardData](https://www.w3.org/TR/clipboard-apis/#clipboardevent-clipboarddata) работает исключительно в контексте обработчиков событий, инициированных пользователем.

Также запрещается генерировать "пользовательские" события буфера обмена при помощи `dispatchEvent` во всех браузерах, кроме Firefox.
С другой стороны, [navigator.clipboard](https://www.w3.org/TR/clipboard-apis/#h-navigator-clipboard) -- более современный API, предназначенный для использования в любых сценариях. Он запрашивает разрешение пользователя, если это необходимо.

## Итого

Expand All @@ -89,4 +110,4 @@
|---------|----------|-------------|
| `change`| Значение было изменено. | Для текстовых полей срабатывает при потере фокуса. |
| `input` | Срабатывает при каждом изменении значения. | Запускается немедленно, в отличие от `change`. |
| `cut/copy/paste` | Действия по вырезанию/копированию/вставке. | Действие можно предотвратить. Свойство `event.clipboardData` предоставляет доступ на чтение/запись в буфер обмена.. |
| `cut/copy/paste` | Действия по вырезанию/копированию/вставке. | Действие можно предотвратить. Свойство `event.clipboardData` предоставляет доступ на чтение/запись в буфер обмена. Все браузеры, кроме Firefox, также поддерживают `navigator.clipboard`. |