Ответ 1
Я предполагаю, что вы имеете в виду большую ячейку в Gmail, где вы вводите тело сообщения, когда вы составляете электронное письмо.
"Если это случай;
Причина:
Это редактирование элемента управления в Gmail не является текстовым элементом управления (input или textarea). Это редактор WYSIWYG, реализованный с <iframe>
, который сделан editable, установив document.designMode = "on"
(или document.body.contentEditable = true
в зависимости от поддержки браузера).
Итак, при нажатии; вы не всегда получаете нужный элемент с тем, как вы запрашиваете document.activeElement
, в этом случае. Вы получаете оберточный (основной) документ body
(даже не iframe
body
).
Например; Я полагаю, в этой строке вашего кода; вы добавляете прослушиватель событий click
в основной документ. Но вы также должны добавить его в редактируемые iframes на странице; потому что страница и iframe имеют разные объекты document
(и iframe не будет устанавливать себя как активные). Итак, вы получите неправильный document.activeElement
.
Обход проблемы:
Добавьте в фреймы также необходимые прослушиватели событий; так как вы хотите получать уведомления о них.
// Add mouseup event listener to the main document
document.addEventListener('mouseup', logActiveElement, false);
// Get all the iframes on the main document.
var iframeElems = document.getElementsByTagName('iframe');
// Add mouseup event listener to the document of the iframe elements
for (var i = 0; i < iframeElems.length; ++i) {
addIframeEvent(iframeElems[i], true, 'mouseup', logActiveElement);
}
Вот вспомогательные функции:
(Обратите внимание, как мы добавляем прослушиватели событий к iframe (документу) из основного документа и как мы проверяем, может ли iframe в настоящее время редактироваться.)
// Adds the specified event listener to the iframe element.
function addIframeEvent(iframeElem, editableOnly, eventName, callback) {
// Get the document of the iframe element.
var iframeDocument = iframeElem.contentDocument ||
iframeElem.contentWindow.document;
// Watch for editableOnly argument.
if ( (editableOnly && isDocEditable(iframeDocument)) || !editableOnly) {
// Add the event listener to the document of the iframe element.
iframeDocument.addEventListener(eventName, callback, false);
}
}
// Checks whether the specified document is content-editable or in design mode.
function isDocEditable(doc) {
return ( ('contentEditable' in doc.body) && (doc.body.contentEditable === true) ) ||
('designMode' in doc) && (doc.designMode == "on") );
}
// Handler function
function logActiveElement() {
console.log("Active Element:", document.activeElement);
}
Теперь обработчик события зарегистрирует правильный activeElement
на консоли.
Осложнения:
В результате; такие вещи, как выбор текста и проверки в вашем существующем коде, не будут работать так же, как с обычными элементами управления редактированием (ввод, текстовое поле и т.д.).
Например; ваша функция getWordUnderCaret(editor)
получает insertionPoint
от editor.
selectionStart
, которая не существует в document.body
(цели iframe
). Для такого рода отбора/инспекции; вы должны переключаться между DOM Selections, Диапазоны DOM; вместо выбора текста и диапазонов в текстовом редактировании.
Примечание. Библиотека jQuery выбора текста/диапазона (Rangy), которую вы используете, promises для обработки такого вида редактируемого контента в браузере (iframes, divs и т.д.). Вы пробовали это для iframes (например, в Gmail)?
Дополнительная информация:
- См. документация ActiveElement в Mozilla Developer
Сеть. В Aditinonally это означает: "Не путайте фокус с помощью
выбор по документу. Когда выбор отсутствует,
activeElement
- это страница<body>
. "
UPDATE:
Проверить элементы управления текстом в Gmail; Я также играл с вашим примером кода;
- Добавлены опции
attachTo: ["existing", "top", "frame"]
в PageMod. - Изменено значение
contentScriptWhen
на'end'
(вместо'ready'
) в параметрах PageMod; чтобы убедиться, что все, включая DOM, CSS, JS, загружено. Некоторое содержимое может быть изменено через JS на странице ready/load, после чего "end" будет выполняться после него. - Применяет контекст селектора к пунктам меню; чтобы убедитесь, что элемент отображается только во время контекста селектора.
Протестировано в Gmail (поле поиска, окно чата и т.д.) и другие сайты; это, похоже, работает.
См./Проверьте рабочий пример здесь в конструкторе аддонов.