Вообще говоря, как-либо программно модифицировать панель управления Битрикс достаточно сложно и единственный способ это сделать, не нарвавшись на то, что обновлять ядро будет невозможно, — это использовать события. Какое решение я могу предложить — напишу в этой статье.
Какие события использовать?
Есть 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’) {//если это страница списка заказов
….
}
}
Когда я этот код писал, я не знал о такой возможности. Возможно ее еще не было. Спасибо за информацию!