@Anton_98

Как присвоить стиль через JS?

ДОбрый день!

Подскажите, пытаюсь сделать стиль для карточки лида если стоит метка что лид повторный. В консоле браузера все работает, а вот если задаю в файле Битрикс ошибка

файл положил в init.php

Сам пример кода:

var divContent = document.querySelector('.crm-kanban-item-repeated').closest('.crm-kanban-item')
var StyleContents = divContent.style.background = '#000'
console.log(StyleContents)


Ошибка в Консоле если файл:
Uncaught TypeError: Cannot read properties of null (reading 'closest')

С js только начинаю дружить, подскажите как правильно
  • Вопрос задан
  • 206 просмотров
Решения вопроса 1
gromdron
@gromdron Куратор тега Битрикс24
Работаю с Bitrix24
В вашем коде сразу несколько ошибок.

Во-первых, вы предполагаете что поведение браузера эквивалентно коду на странице. Т.е. одно и то же действие в браузере и в коде дают одинаковый результат, но это не так. Браузер отрисовывает страницу по частям и нет никаких гарантий что в момент выполнения вашего кода (фрагмент document.querySelector('.crm-kanban-item-repeated')) на странице существует хотя бы один элемент с подобным селектором. Более того скажу сразу - этот элемент не существует, так как он добавляется позже через javascript.
Вам нужно почитать больше про js и про то как браузер рисует страницу - без этого вы далеко не уйдете.

Во-вторых, вы полагаете что у вас всего 1 элемент (querySelector - вернет первый(!) элемент подходящий под условия), а у вас их может быть много. Т.е. нужно использовать как минимум querySelectorAll. Вы так же полагаете что наличие ноды автоматически делает элемент "повторным", что совершенно не так. Ноду можно вывести у любого элемента, но повторным он от этого не станет.

В-третьих, даже если вы окрасите элементы, то после перезагрузки данных (не страницы), например при применении фильтра, ваш код не выполнится еще раз и не будет иметь силы.

Предположим наша задача - покрасить элементы в красный если они повторные.

Для начала определимся как мы будем красить: я полагаю что проще всего будет создать какой-нибудь css-класс, который будет отрабатывать, если карточка подходит под указанные условия.
Я буду использовать кастомный класс flah_repeated и для этого я создам css правило:

.crm-kanban-item.flah_repeated {
	background-color: red !important;
}


Затем я поищу событие, которое отрабатывает при отрисовке карточки канбана. Используя события я могу сразу гарантировать следующие вещи:
1. Скрипт будет отрабатывать только там где есть канбан. То есть мы не будем искать элементы на других страницах чтобы не повредить их в случае ошибки.
2. Скрипт будет отрабатывать только когда канбан уже отрисован. То есть все элементы уже есть на странице и мы можем не боятся их отсутствия
3. Скрипт будет отрабатывать при повторной отрисовке. Т.е. примнение фильтра так же вызовет событие и мы еще раз сможет сделать то что нужно.

Затем, когда я найду событие, скорее всего оно может быть использовано и в других сущностях, где выполнять подобное мне не нужно, поэтому мне нужно подумать как ограничить действие только нужными элементами

BX.addCustomEvent("Kanban.Grid:onRender", function(kanbanGrid){

	if ( kanbanGrid.getData().entityType != 'LEAD' )
	{
		return;
	}

	let kanbanItems = kanbanGrid.getItems();

	for (let key in kanbanItems)
	{
		if ( key < 1 ) continue;

		let kanbanItem = kanbanItems[key];

		if ( kanbanItem.getDataKey('return') )
		{
			BX.addClass(kanbanItem.container, "flah_repeated");
		}
	}
});


Ну и когда все будет готово, я сделаю расширение (extension) и подключу его на событии пролога, чтобы добавлять к каждой странице.

Таким образом я не изменю публичную часть и добьюсь того что требовалось в изначальной задаче.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
ValeriuCutebov
@ValeriuCutebov
Проблема заключается в том, что скрипт выполняется раньше, чем элементы страницы загружены и доступны для манипуляций. Попробуйте обернуть ваш скрипт в обработчик события DOMContentLoaded, чтобы выполнение скрипта началось только после полной загрузки документа:

document.addEventListener('DOMContentLoaded', function() {
  var divContent = document.querySelector('.crm-kanban-item-repeated').closest('.crm-kanban-item')
  var StyleContents = divContent.style.background = '#000'
  console.log(StyleContents)
});

Также убедитесь, что элемент с классом crm-kanban-item-repeated существует на странице в момент выполнения скрипта, иначе querySelector вернет null.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы