Хобрук: Ваш путь к мастерству в программировании

Как проверить, доступен ли элемент HTML для редактирования содержимого из расширения Chrome

Я пишу расширение для Chrome, которое должно обнаруживать contenteditable HTML-элементы (или элементы, в которые пользователь может вводить текст) на странице, куда вставляется мой контекстный скрипт.

Я сейчас делаю это:

var objAll = document.getElementsByTagName("*");
for(var i = 0; i < objAll.length; i++)
{
    obj = objAll[i];

    if(obj.contentEditable &&
        obj.contentEditable != 'inherit' &&
        obj.contentEditable != 'false')
    {
        //Yes, this is a content editable element!
    }
}

Но мой метод работает не на всех сайтах, на которых я его тестировал.

Мне интересно, что я там упускаю?

PS. Поскольку это скрипт контента, я не использую jQuery, чтобы сделать его более надежным.


  • Пробовали ли вы одновременно выделять все нужные элементы с помощью чего-то вроде document.querySelectorAll('[contenteditable]')? 10.09.2014

Ответы:


1

contentEditable — это свойство, которое подразумевается атрибутом contenteditable. Что вам действительно нужно проверить, так это свойство isContentEditable, которое является логическим значением и сообщает, имеет ли элемент редактируемое содержимое или нет:

if (obj.isContentEditable) {
    // do stuff
}

Но вместо того, чтобы получать все элементы и фильтровать их, просто выберите все contenteditable элементов:

var contEditables = document.querySelectorAll('[contenteditable]');
for (var i = 0; i < contEditables.length; i++) {
    // do stuff
}

На самом деле элемент имеет редактируемое содержимое тогда и только тогда, когда он имеет атрибут contenteditable, независимо от того, является ли он пустой строкой или нет.

Демо

10.09.2014
  • Спасибо. Знаете, почему-то document.querySelectorAll('[contenteditable]') этого не делает. Только когда я делаю if (obj.isContentEditable) вместо того, что у меня было, и сохраняю document.getElementsByTagName("*"), это работает для моей конкретной тестовой страницы. Есть идеи, почему? 10.09.2014
  • @ c00000fd На самом деле нет. Этот запрос должен и работает, и хотя я не проверял его в расширении, я не понять, почему он должен вести себя по-другому. 10.09.2014
  • Спасибо за демонстрацию. Я это вижу. Но я тестирую его на гораздо более сложном примере на активной странице (из расширения Chrome), и то, что я сказал выше, действительно имеет значение. И я был бы признателен, если бы кто-нибудь мог объяснить, почему? 10.09.2014
  • Почему? Может быть, элементы создаются динамически? Когда вы запускаете этот код? 10.09.2014
  • @ c00000fd Трудно сказать без реального случая. Единственное, что я могу сказать, это то, что getElementsByTagName возвращает живую коллекцию, поэтому она изменяется при добавлении новых элементов, а querySelectorAll — это моментальный снимок запроса в DOM. Таким образом, вы должны вызвать его снова, если за это время были добавлены некоторые элементы. 10.09.2014
  • @Xan: Вполне возможно, они могли быть созданы динамически. Я не автор страницы, на которой работает скрипт. Итак, вы говорите, что если элементы были созданы динамически, то мне нужно будет вызвать document.getElementsByTagName("*"), верно? 10.09.2014
  • @ c00000fd Я направляю вас к этому вопросу: stackoverflow.com/questions/2844565/ 10.09.2014
  • @Xan: Да, я знаю о наблюдателе мутаций. Все-таки это другая тема. 10.09.2014
  • К вашему сведению, вот страница, на которой я это тестирую: music.msn.com/ music/article.aspx?news=888163 Элемент contenteditable — это поле Write a comment... в нижней части страницы. Трудно сказать, создается ли он динамически. 10.09.2014
  • @ c00000fd Ах, осторожно, это нечто другое! Это весь документ (в виде <iframe>), который доступен для редактирования. Это зависит не от атрибута contenteditable, а скорее от свойства designMode, для которого установлено значение "on" в документе, а не в отдельном элементе. Вот почему селектор не работает. 10.09.2014
  • Спасибо за информацию. Итак, вы говорите, что мне нужно проверить obj.designMode в извлеченных элементах DOM? 10.09.2014
  • @ c00000fd Нет, не для элементов: это свойство определено для объектов документа. Итак, если у вас есть iframe, вы должны получить его contentDocument. 10.09.2014
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..