Вообще говоря, как-либо программно модифицировать панель управления Битрикс достаточно сложно и единственный способ это сделать, не нарвавшись на то, что обновлять ядро будет невозможно, — это использовать события. Какое решение я могу предложить — напишу в этой статье.
Какие события использовать?
Есть 2 события, которые нам могут пригодится: OnBeforeProlog и OnAfterEpilog: первое выполняется перед началом вывода страницы, второе — по окончанию вывода страницы. Фактически с помощью этих двух мы можем перехватить вывод страницы, что-то добавить в код и затем вывести ее пользователю.
Делается это так:
RegisterModuleDependences("main", "OnBeforeProlog", "main", "ModifyContent", "StartBuffer", "100");
RegisterModuleDependences("main", "OnAfterEpilog", "main", "ModifyContent", "EndBuffer", "100");
class ModifyContent
{
function StartBuffer()
{
if (!defined("ADMIN_SECTION")) return;
define("MYBOT_IS_ACTIVE", true);
ob_start();
}
function EndBuffer()
{
if(defined("MYBOT_IS_ACTIVE"))
{
$content = ob_get_contents();
ob_end_clean();
echo $content . "еще чего-то";
}
}
}
В методе, который вызывается при событии OnBeforeProlog идет проверка на содержание константы ADMIN_SECTION и не для панели управления данный код не выполняется. Пара функций ob_start() и ob_get_contents() позволяет перенаправить вывод страницы в буфер, а потом отдать этот вывод в переменную.
Как что-то изменить в панели управления?
Я решил выбрать способ, при котором непосредственной модификации даже выходящего код страницы панели управления не происходит, — через изменение внешнего вида с помощью javascript, а точнее библиотеки jquery.
С недавнего времени jquery в битрикс можно подключить так: CJSCore::Init( ‘jquery’ ).
Чтобы понять какой скрипт нужно написать, нужно просто посмотреть код html после генерации страницы списка заказов. Список заказов представляет собой таблицу с id tbl_sale_order, причем те строки, где непосредственно находятся заказы (т.е. не заголовок и не футер таблицы) отмечены id odd и even. Этим мы и воспользуемся для обработки данных. К тому же нам нужен ID заказа. Его можно найти в первой ячейке в значении чекбокса. Таким образом получается нехитрый скрипт поиска всех ID заказов, которые используются на данной странице заказа:
var ordersAr = [];
$('#tbl_sale_order tr.odd, #tbl_sale_order tr.even').each(function(){
var orderid = $(this).children("td:first").children("input").attr('value');
ordersAr[ordersAr.length]=orderid;
});
Далее нужно получить данные по каждому ID заказа является ли он отмененным или нет. Это очевидно нужно делать через обращение через AJAX к серверному скрипту. В скрипт будем отправлять массив ID заказов, а назад будем принимать json-объект ассоциативный массив вида: ID заказа => Отменен или нет.
Скрипт на сервере будет выглядеть так:
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
CModule::IncludeModule('sale');
$CancelInfo = Array();
foreach($_REQUEST["orders"] as $order)
{
$arOrder = CSaleOrder::GetByID($order);
if ($arOrder["CANCELED"] == "Y")
$CancelInfo[$order] = true;
else
$CancelInfo[$order] = false;
}
echo json_encode(array('CancelInfo' => $CancelInfo));
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
?>
а обращение из ява-скрипта к этому скрипту и обработка данных — так:
$.getJSON("/bitrix/admin/dv/getorders.php", { orders: ordersAr },
function(data)
{
$('#tbl_sale_order tr.odd, #tbl_sale_order tr.even').each(function(){
var orderid = $(this).children("td:first").children("input").attr('value');
if (data.CancelInfo[orderid]) {
$(this).children("td").css("background-color", "#FFA7A7");
}
});
}
);
Ничего сложного в скрипте обработки нет — она просто по новой перебирает все заказы на страницы и, если в массиве, полученном с сервера, этот заказ помечен как отмененный, то скрипт перекрашивает все ячейки данной строки в другой цвет.
Серверный скрипт я привел полностью, а код вызываемый по событиям нет, исправим это:
if( ADMIN_SECTION ) {
CJSCore::Init( 'jquery' );
}
RegisterModuleDependences("main", "OnBeforeProlog", "main", "ModifyContent", "StartBuffer", "100");
RegisterModuleDependences("main", "OnAfterEpilog", "main", "ModifyContent", "EndBuffer", "100");
class ModifyContent
{
function StartBuffer()
{
if (!defined("ADMIN_SECTION")) return;
define("MYBOT_IS_ACTIVE", true);
ob_start();
}
function EndBuffer()
{
if(defined("MYBOT_IS_ACTIVE"))
{
$content = ob_get_contents();
ob_end_clean();
global $APPLICATION;
echo $content;
if ($APPLICATION->GetCurPage() == "/bitrix/admin/sale_order.php")
{
echo <<<EOL
<script>
$(function() {
var ordersAr = [];
$('#tbl_sale_order tr.odd, #tbl_sale_order tr.even').each(function(){
var orderid = $(this).children("td:first").children("input").attr('value');
ordersAr[ordersAr.length]=orderid;
});
$.getJSON("/bitrix/admin/dv/getorders.php", { orders: ordersAr },
function(data)
{
$('#tbl_sale_order tr.odd, #tbl_sale_order tr.even').each(function(){
var orderid = $(this).children("td:first").children("input").attr('value');
if (data.CancelInfo[orderid]) {
$(this).children("td").css("background-color", "#FFA7A7");
}
});
}
);
});
</script>
EOL;
}
}
}
}
Конечно же, данный код должен располагаться в файле /bitrix/php_interface/init.php, а код, который вызывается через AJAX в файле /bitrix/admin/dv/getorders.php . Удачного кодинга!
отлично работает!
в последних версиях битрикса ( в частности 17.0) нужно заменить
#tbl_sale_order tr.odd, #tbl_sale_order tr.even
на
#tbl_sale_order tr.adm-list-table-row
Спасибо за дополнение!
Еще можно влезть в список заказов без JS, тоже через событие:
AddEventHandler(«main», «OnAdminListDisplay», «MyOnAdminListDisplay»);
function MyOnAdminListDisplay(&$list)
{
if ($list->table_id==’tbl_sale_order’) {//если это страница списка заказов
….
}
}
Когда я этот код писал, я не знал о такой возможности. Возможно ее еще не было. Спасибо за информацию!