Pull to refresh

Как легко и быстро поставить свой прелоадер на стандартный AJAX Битрикса?

Reading time 3 min
Views 18K

Вступление


Посещаю Хабр уже давно, но на статью решился только сейчас. Да и то, не статья это вовсе, а так — скорее, заметка о том, как легко и без напряга, без правки ядра и заморочек с самим аяксом взять и заменить стандартное убогое окошко прелоадера битрикса на свой произвольный HTML/CSS код. Приступим?

Описание проблемы


Разработчики на 1С-Битрикс должны знать об этой проблеме, а для всех непосвящённых — поясню. Эта CMS использует в стандартных шаблонах и компонентах свой кастомный jquery и ajax. Документация имеется, но много ли кому охото её изучать, чтобы сделать какие то элементарные вещи?..
В принципе, если ничего в стандартных шаблонах не трогать, «родной» аякс битрикса работает не плохо. Но если попытаться что то серьёзно подправить, или вовсе — натягивать свою вёрстку в купе с родным аяксом — тут начинаются танцы с бубном, и такая элементарная вещь, как замена дефолтного убогого прелоадера, превращается в нудное гугление и изучение кода в ядре CMS.

Позиция ТП Битрикса на этот счёт вообще удивляет:
Сейчас, к сожалению, нет стандартного способа изменить стандартный прелоадер

Скрин сообщения техподдержки

Все самые наивные и доверчивые скажут «нельзя? ну ок...» и пойдут писать свои аякс-запросы. А мы возьмём и сделаем!

Реализация


Суть проста — у стандартного аякса есть две функции BX.showWait и BX.closeWait которые отвечают за действия на странице в момент ожидания ответа от аякса. Используем их чтобы подгрузить вместо дефолтного прелоадера, свой.

Для начала найдём сам прелоадер. Мне например, понравился на чистом HTML/CSS в стиле Windows 8. Затем открываем footer.php нашего шаблона и перед тегом вписываем наш код:

<div id="win8_wrapper">
	<div class="windows8">
		<div class="wBall" id="wBall_1">
			<div class="wInnerBall"></div>
		</div>
		<div class="wBall" id="wBall_2">
			<div class="wInnerBall"></div>
		</div>
		<div class="wBall" id="wBall_3">
			<div class="wInnerBall"></div>
		</div>
		<div class="wBall" id="wBall_4">
			<div class="wInnerBall"></div>
		</div>
		<div class="wBall" id="wBall_5">
			<div class="wInnerBall"></div>
		</div>
	</div>
</div>

Длинную CSS-простыню вставлять не буду (в конце будут все исходники). Далее вставляем скрипт с вызовом функций, которые подгрузят наш прелоадер вместо стандартного:

var lastWait = [];
	/* non-xhr loadings */
	BX.showWait = function (node, msg)
	{
		node = BX(node) || document.body || document.documentElement;
		msg = msg || BX.message('JS_CORE_LOADING');

		var container_id = node.id || Math.random();

		var obMsg = node.bxmsg = document.body.appendChild(BX.create('DIV', {
			props: {
				id: 'wait_' + container_id,
				className: 'bx-core-waitwindow'
			},
			text: msg
		}));

		setTimeout(BX.delegate(_adjustWait, node), 10);

		$('#win8_wrapper').show();
		lastWait[lastWait.length] = obMsg;
		return obMsg;
	};

	BX.closeWait = function (node, obMsg)
	{
		$('#win8_wrapper').hide();
		if (node && !obMsg)
			obMsg = node.bxmsg;
		if (node && !obMsg && BX.hasClass(node, 'bx-core-waitwindow'))
			obMsg = node;
		if (node && !obMsg)
			obMsg = BX('wait_' + node.id);
		if (!obMsg)
			obMsg = lastWait.pop();

		if (obMsg && obMsg.parentNode)
		{
			for (var i = 0, len = lastWait.length; i < len; i++)
			{
				if (obMsg == lastWait[i])
				{
					lastWait = BX.util.deleteFromArray(lastWait, i);
					break;
				}
			}

			obMsg.parentNode.removeChild(obMsg);
			if (node)
				node.bxmsg = null;
			BX.cleanNode(obMsg, true);
		}
	};

	function _adjustWait()
	{
		if (!this.bxmsg)
			return;

		var arContainerPos = BX.pos(this),
			div_top = arContainerPos.top;

		if (div_top < BX.GetDocElement().scrollTop)
			div_top = BX.GetDocElement().scrollTop + 5;

		this.bxmsg.style.top = (div_top + 5) + 'px';

		if (this == BX.GetDocElement())
		{
			this.bxmsg.style.right = '5px';
		}
		else
		{
			this.bxmsg.style.left = (arContainerPos.right - this.bxmsg.offsetWidth - 5) + 'px';
		}
	}

Ну и не забываем обязательно добавить CSS стили вашего прелоадера стандартным способом — скопировав в template_styles.css либо подключив в header.php отдельным файлом.

Пробуем что нибудь пощёлкать на сайте. Вуаля — прелоадер заменён. Для более «правильного» метода я бы советовал вынести подключение в футере в отдельную включаемую область.

Исходники на GitHub

Всем спасибо за внимание!
Tags:
Hubs:
-9
Comments 4
Comments Comments 4

Articles