|
50 | 50 | ```smart header="Нельзя ничего предотвратить в `oninput`" |
51 | 51 | Событие `input` происходит после изменения значения. |
52 | 52 |
|
53 | | -Поэтому мы не можем использовать `event.preventDefault()` там - будет уже слишком поздно, никакого эффекта не будет. |
| 53 | +Поэтому мы не можем использовать `event.preventDefault()` там -- уже слишком поздно, никакого эффекта не будет. |
54 | 54 | ``` |
55 | 55 |
|
56 | 56 | ## События: cut, copy, paste |
|
61 | 61 |
|
62 | 62 | Мы также можем использовать `event.preventDefault()` для предотвращения действия по умолчанию, и в итоге ничего не скопируется/не вставится. |
63 | 63 |
|
64 | | -Например, код, приведённый ниже, предотвращает все подобные события и показывает, что мы пытаемся вырезать/копировать/вставить: |
| 64 | +Например, код, приведённый ниже, предотвращает все `cut/copy/paste` события и показывает текст, который мы пытаемся вырезать/копировать/вставить: |
65 | 65 |
|
66 | 66 | ```html autorun height=40 run |
67 | 67 | <input type="text" id="input"> |
68 | 68 | <script> |
69 | | - input.oncut = input.oncopy = input.onpaste = function(event) { |
70 | | - alert(event.type + ' - ' + event.clipboardData.getData('text/plain')); |
71 | | - return false; |
| 69 | + input.onpaste = function(event) { |
| 70 | + alert("paste: " + event.clipboardData.getData('text/plain')); |
| 71 | + event.preventDefault(); |
| 72 | + }; |
| 73 | +
|
| 74 | + input.oncut = input.oncopy = function(event) { |
| 75 | + alert(event.type + '-' + document.getSelection()); |
| 76 | + event.preventDefault(); |
72 | 77 | }; |
73 | 78 | </script> |
74 | 79 | ``` |
75 | 80 |
|
76 | | -Технически, мы можем скопировать/вставить всё. Например, мы можем скопировать файл из файловой системы и вставить его. |
| 81 | +Обратите внимание: внутри обработчиков событий `cut` и `copy` вызов `event.clipboardData.getData(...)` возвращает пустую строку. Это потому, что технически данные ещё не находятся в буфере обмена. Если мы используем `event.preventDefault()` они вообще не будут скопированы. |
| 82 | + |
| 83 | +Поэтому в приведённом выше примере используется `document.getSelection()` для получения выделенного текста. Более подробную информацию о выделении в документе можно найти в главе <info:selection-range>. |
| 84 | + |
| 85 | +Возможно копирование/вставка не только текста, но и любых данных. Например, мы можем скопировать файл в файловом менеджере ОС и вставить его. |
| 86 | + |
| 87 | +Это потому, что `clipboardData` реализует интерфейс `DataTransfer`, обычно используемый для перетаскивания и копирования/вставки. Сейчас это немного выходит за рамки нашего рассмотрения, но вы можете найти его методы в [спецификации DataTransfer](https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface). |
| 88 | + |
| 89 | +Кроме того, существует дополнительный асинхронный API для доступа к буферу обмена: `navigator.clipboard`. Подробнее -- в спецификации [Clipboard API and events](https://www.w3.org/TR/clipboard-apis/), [не поддерживается в Firefox](https://caniuse.com/async-clipboard). |
| 90 | + |
| 91 | +## Ограничения безопасности |
| 92 | + |
| 93 | +Буфер обмена работает глобально, на уровне ОС. Пользователь может переключаться между приложениями, копировать/вставлять различные данные, и страница браузера не должна всё это видеть. |
| 94 | + |
| 95 | +Поэтому большинство браузеров разрешают беспрепятственный доступ к буферу обмена для чтения/записи только в рамках определённых действий пользователя, таких как копирование/вставка и т.д. |
| 96 | + |
| 97 | +Запрещено генерировать "пользовательские" события буфера обмена с помощью `dispatchEvent` во всех браузерах, кроме Firefox. И даже если нам удастся создать такое событие, спецификация чётко указывает, что такие "синтетические" события не должны предоставлять доступ к буферу обмена. |
77 | 98 |
|
78 | | -Существует список методов [в спецификации](https://www.w3.org/TR/clipboard-apis/#dfn-datatransfer) для работы с различными типами данных, чтения/записи в буфер обмена. |
| 99 | +Даже если кто-то решит сохранить `event.clipboardData` в обработчике событий, а затем обратиться к нему позже -- это не сработает. |
79 | 100 |
|
80 | | -Но обратите внимание, что буфер обмена работает глобально, на уровне ОС. Большинство браузеров в целях безопасности разрешают доступ на чтение/запись в буфер обмена только в рамках определённых действий пользователя, к примеру, в обработчиках событий `onclick`. |
| 101 | +Повторим: [event.clipboardData](https://www.w3.org/TR/clipboard-apis/#clipboardevent-clipboarddata) работает исключительно в контексте обработчиков событий, инициированных пользователем. |
81 | 102 |
|
82 | | -Также запрещается генерировать "пользовательские" события буфера обмена при помощи `dispatchEvent` во всех браузерах, кроме Firefox. |
| 103 | +С другой стороны, [navigator.clipboard](https://www.w3.org/TR/clipboard-apis/#h-navigator-clipboard) -- более современный API, предназначенный для использования в любых сценариях. Он запрашивает разрешение пользователя, если это необходимо. |
83 | 104 |
|
84 | 105 | ## Итого |
85 | 106 |
|
|
88 | 109 | | Событие | Описание | Особенности | |
89 | 110 | |---------|----------|-------------| |
90 | 111 | | `change`| Значение было изменено. | Для текстовых полей срабатывает при потере фокуса. | |
91 | | -| `input` | Срабатывает при каждом изменении значения. | Запускается немедленно, в отличие от `change`. | |
92 | | -| `cut/copy/paste` | Действия по вырезанию/копированию/вставке. | Действие можно предотвратить. Свойство `event.clipboardData` предоставляет доступ на чтение/запись в буфер обмена.. | |
| 112 | +| `input` | Для текстовых полей при каждом изменении значения. | Запускается немедленно, в отличие от `change`. | |
| 113 | +| `cut/copy/paste` | Действия по вырезанию/копированию/вставке. | Действие можно предотвратить. Свойство `event.clipboardData` предоставляет доступ на чтение/запись в буфер обмена. Все браузеры, кроме Firefox, также поддерживают `navigator.clipboard`. | |
0 commit comments