Есть в body тег select, содержащий список тем сайта, этот select я сделал блоком. При событие change у select, нужно менять значение href у тега link, содержащий url текущей темы. Для этого решил сделать link тем же блоком, что и select, используя параметр id, в общем вот, в head:
<link class="theme i-bem" data-bem='{"theme": {"id": "main"}}' rel="stylesheet" href="">
и в body
<select class="theme i-bem" data-bem='{"theme": {"id": "main"}}'>
<option value="default" selected>Default</option>
<option value="rock">Rock</option>
</select>
в декларации блока есть вот такой код, вызываемый при событие change у select:
this.domElem.filter('link').attr({'href': this.params.themeFullFileUrl});
Но не работает. А не работает потому, что, если вывести в консоль или алертом кол-во элементов this.domElem - возвращает 1, а не 2, хотя в документации сказано, что обе DOM ноды будут добавлены в this.domElem. В чем причина? Спасибо.
а link в head прописан я так понимаю? надо посмотреть насколько это поддерживается.
да, link в head
автоматическая инициализация делается только по document.body. в качестве хака при инициализации можно попробовать добавить link в domElem при инициализации
this.domElem = this.domElem.add($('link.theme'))
. Призовём @tadatuta чтобы он сказал на сколько это правильно использовать. По крайней мере мне в одном месте пришлось воспользоваться таким подходом - пока работает.а вместо
this.domElem.filter('link')
на link правильнее намиксовать элементlink
и получать его с помощьюthis.elem('link')
Ещё один способ - переопределить аттрибут BEMDOM.scope на уровне проекта:
Вероятно этот способ правильнее.
Итого:
@Guria, спасибо, попробую. Но хотелось бы узнать у разработчиков, на сколько это правильно и почему в BEMDOM.scope изначально юзается document.body, а не document?
Есть ещё вот такой PR который попадёт в следующую версию bem-core. Из комментариев видно, что разработчики считают нормальным переопределение
BEMDOM.scope
.Сейчас, при использовании
bem-core@2.5.1
, получается два определенияBEMDOM.scope
по наступлению событияDOM ready
:Могу предположить, что при определённых обстоятельствах, код из библиотеки может выполнится позже пользовательского и тогда трюк не сработает. На сколько я понимаю, мой сниппет в новой продолжит работать и уже гарантировано устанавливать значение
BEMDOM.scope
. Можно уточнить у самого @dfilatov@Guria, работает, но при условии, что код вашего снипеета будет выше кода моего модуля theme, если же ниже - то не работает, оно-то и понятно почему. В общем выглядит, как хак. @dfilatov, скажите, пожалуйста, почему в scope по-умолчанию используется document.body, а не document? Спасибо.
Вопрос положения решается с помощью зависимостей. В css и js почти везде результат от порядка зависит это не значит, что это хак.
@pavel06081991 Вполне ок, имхо :-) Лишь бы поддержка была в
bem-core
, чтобы ничего завтра не сломалось. Благо,bem-core
выглядит сейчас стабильной.Нашёл место, которое зависит от BEMDOM.scope. Правда я склонен считать ошибкой, т.к. для popup лучше использовать document.body, а не полагаться на его наличие в BEMDOM.scope. cc // @tadatuta
BEMDOM.scope
был введен, когда решалась задача поддержки нескольких версий i-bem.js в одном рантайме. Подробности может рассказать @veged@pavel06081991 Плохие новости:
BEMDOM.scope
нельзя назначитьdocument
. Ждём подробности в документации.@pavel06081991 @Guria
Кажется, исходная задача (правильно) решается переопределением
i-bem__dom_init_auto
на уровне проекта, вызовомBEMDOM.int($(document))
(по умолчанию, как заметили выше, инициализация происходит только в пределахscope
).Пока документация на блоки bem-core находится в разработке, можно посмотреть код
i-bem__dom_init
.Относительно
BEMDOM.scope
: как написал @tadatuta, главная задача, которую он должен был решать, это возможность разграничения страницы на несколько изолированных рантаймов, в каждом из которых будут работать блоки разной версии i-bem.js.