TL; DR вопрос:
Как некоторый javascript может сообщить окну, что кнопка мыши отпущена? Событие mouseup теряется из-за междоменного iframe. Я могу обнаружить, что проблема произошла, но я не знаю, что делать, чтобы вылечить ее. Если бы я мог заставить положение указателя мыши, проблема исчезла бы; но javascript не может изменять положение указателя мыши. Если бы я мог «выстрелить мышью», то проблема исчезла бы, потому что она заменила бы потерянное мышиное событие; но использование dispatchEvent для нового события mouseup ничего не дает.
Положение:
- Любая последняя версия Chrome, любая операционная система.
- Внешний документ, содержащий iframe, расположенный внутри. Никакого JavaScript не требуется вообще.
- Внешний документ и внутренний документ iframe, размещенные на разных доменах, оба https. Не разные субдомены одного базового домена, но фактически разные домены. В моих примерах используются www.pressero.com и client-prototype.dev2.edocbuilder.com. Проблема все еще возникает, действительны ли сертификаты (у меня есть).
- Текстовое поле ввода в iframe, расположенное на левом краю или близко к нему. Стандартное направление текста LTR.
- Пример почти минимальный: Демо1 . У этого есть один маленький кусочек javascript во внешнем документе, для удобства при изменении источника iframe. Удаление этого javascript не имеет никакого эффекта.
Важные ограничения:
- Бывает только с браузерами на базе Chrome и Chromium; не Firefox, Safari, Edge или IE.
- Существует некоторая неоднозначность того, происходит ли это одинаково для всех клиентов Chrome. Я лично воспроизвел идентичное поведение примерно на пяти разных компьютерах с Windows, работающих под управлением Chrome 68 или 69. Один коллега получил немного разные результаты на Mac под управлением Chrome 69 и на Chrome 69 в виртуальной машине Windows, работающей на том же Mac.
Возникновение проблемы:
- Пользователь пытается выделить весь текст в поле ввода текста, используя мышь, перемещая мышь от конца текстового поля к началу.
- Случайно пользователь перемещает указатель мыши за левый край и, следовательно, выходит из iframe во внешний документ.
- Пользователь отпускает левую кнопку мыши после того, как указатель мыши покинул фрейм.
- происходит только , когда мышь используется для выделения текста, и только когда указатель оказывается за пределами iframe во время отпускания левой кнопки. Другие методы выделения текста не вызывают симптом:
- Ctrl-A, чтобы выбрать все
- вкладка в поле
- с помощью стрелок для выбора текста
- с помощью мыши для выбора текста, но слева направо
- с помощью мыши выбирайте текст, но будьте осторожны, чтобы указатель находился внутри фрейма при отпускании кнопки мыши
Еще один способ сделать вставленный обратно текст:
- Поместите указатель мыши в верхнем левом углу текстового поля.
- Удерживайте левую кнопку мыши нажатой.
- Введите текст. Он вставляется в обратном порядке, потому что после каждого нажатия клавиши точка вставки перемещается в положение до ввода только что введенного символа.
- Это подразумевается только как иллюстрация нежелательного поведения. Это явно не ошибка, так как это искусственный способ показать это.
Воспринимаемый симптом:
- Текст, набранный после отпускания левой кнопки, вставляется в обратном порядке: т.е. ввод «abcde» будет выглядеть как «edcba», а точка вставки будет слева от первого символа.
Сопутствующие симптомы:
- Если используется javascript, например, функция изменения размера объекта или перетаскивания его по холсту, то перетаскивание будет продолжаться даже после отпускания левой кнопки за пределами iframe. Даже после перемещения указателя обратно в iframe, перетаскивание продолжается.
- Тот факт, что это действительно событие
mouseup
, теряется, подтверждается присоединением alert()
к mouseup к body
в документе iframe. Предупреждение появляется, если кнопка мыши отпущена, когда указатель находится внутри iframe; это не происходит, если кнопка мыши отпущена, когда указатель находится за пределами фрейма.
Опять же, я подчеркиваю, что ТОЛЬКО ХРОМ имеет такое поведение. Делая то же самое в Firefox, Edge или IE, освобождение кнопки мыши обнаруживается немедленно, независимо от того, где находится указатель мыши.
Обойдены обходные пути:
- Посоветуйте пользователям быть осторожнее с положением мыши. Не популярное решение.
- Javascript применяется к текстовому полю, чтобы выбрать все, когда текстовое поле находится в фокусе. Это делает ненужным использование мыши для выбора и, следовательно, не позволяет пользователям столкнуться с проблемой. Однако это делает невозможным выделение небольших частей текста вместо всего этого.
- Перемещение текстового поля, чтобы оно не касалось левого края. Это снижает вероятность того, что пользователь отпустит, когда указатель находится за пределами iframe.
Поймать потерянное событие mouseup:
Прикрепив обработчик событий к <body>
во внешнем документе, я могу поймать мышиную подсказку. Затем я могу использовать стандартную технику postMessage, чтобы сообщить внутреннему окну iframe, что произошла наведенная мышка. Внутренний iframe знает, какой элемент был активен во время перетаскивания, так что это хорошо. Тем не менее, мне не повезло в том, чтобы на самом деле симулировать событие mouseup. Я попробовал triggerMouseEvent
технику здесь . Он работает без ошибок, но, очевидно, ничего не делает.
Демонстрация здесь имеет минимальный пример сверху, плюс слесарное дело для захвата указателя мыши во внешнем документе, отправки сообщения внутреннему и вызова triggerMouseEvent
: Demo2
Еще одна странная возможность
Пытаясь создать минимальные примеры, я обнаружил, что, возможно, блочная модель как-то задействована. Demo1a идентичен demo1 выше, за исключением того, что элемент iframe имеет высоту 710px вместо 700px. На моих тестовых машинах это устраняет ошибку. На тестовой машине моего коллеги ошибка остается.
Возможная связанная отслеживаемая проблема с хромом:
РЕДАКТИРОВАТЬ 2018-09-25
Я отправил Номер хрома # 882491 . Он еще не видел никакой реальной активности.