Vivaldi и Redactor: выводим скрипт из рекурсии

При использовании Redactor от Imperavi в браузере Vivaldi наблюдается баг, из-за которого в редакторе нельзя применять картинки — иначе скрипт уходит в рекурсию.

Причина кроется в реализации пространственной навигации, в ходе которой браузер вмешивается в DOM страницы и автоматически навешивает на кликабельные элементы атрибут data-vivaldi-spatnav-clickable. Я и раньше подозревал, что такое решение где-нибудь да вылезет боком, но обнаружил первую проблему из-за этого атрибута только сейчас.

Что происходит?

Redactor использует MutationObserver для наблюдения за изменениями в DOM. Наблюдатель вызывается каждый раз, когда Vivaldi добавляет соответствующий атрибут. Редактор при этом реинициализирует обработчики, заставляя браузер снова добавить атрибут — таким образом, всё заходит в рекурсию и вкладка повисает.

Разработчикам Redactor о проблеме и способе её решения я уже сообщил. Отозвались они достаточно быстро и пообещали включить фикс в следующее обновление. Ну, а пока обновление не вышло, пользователи Redactor могут исправить проблему самостоятельно.

Как починить?

Открываем не минифицированную версию скрипта редактора. Поиском находим строку «iterateObserver:» (без кавычек и с двоеточием). В версии 2.6 это линия № 4278. Находим в методе блок if такого вида:

if (
(
  (
       this.opts.type === 'textarea'
    || this.opts.type === 'div'
  )
  &&
  (
       !this.detect.isFirefox()
    && mutation.target === this.core.editor()[0]
  )
)
|| (
     mutation.attributeName === 'class'
  && mutation.target === this.core.editor()[0])
)
{
 stop = true;
}

Как видно, некоторые исключения уже прописаны авторами скрипта. Добавляем условие и для атрибута Vivaldi. Таким образом блок принимает следующий вид:

if (
(
  (
       this.opts.type === 'textarea'
    || this.opts.type === 'div'
  )
  &&
  (
       !this.detect.isFirefox()
    && mutation.target === this.core.editor()[0]
  )
)
|| (
     mutation.attributeName === 'class'
  && mutation.target === this.core.editor()[0]
 )
|| (mutation.attributeName == 'data-vivaldi-spatnav-clickable')
)
{
 stop = true;
}

И проверяем. Всё должно заработать.

Загрузка...