UPD 12.10.2015
Сделал модуль свойства инфоблоков - привязка к сущностям CRM.
Скачать можно
Была поставлена задача: в пользовательских списках сделать возможность выбирать компанию и товар из модуля CRM.
Игорь Карпович писал про это
Для удобного поиска и выбора товара/компании необходимо использовать стандартный компонент (crm.entity.selector), который используется в модуле CRM.
Создаем пользовательские свойства для привязки к компании и товару. Создаем файлы usertype_company_crm.php и usertype_product_crm.php, инклудим их в init.php . Ознакомиться с кодом можно скачав файлы, я лишь остановлюсь на некоторых моментах.
Мое пользовательское свойство условно делится на 3 составляющих: отображение в карточке элемента, отображение в списке элементов и отображение в фильтре.
Итак по порядку
1. GetEditForm - функция, которая подключает всплывающее окошко на страницу редактирования (карточки) элемента в админке и в публичной части. Для записи и отправки свойства сделан скрытый инпут
<input type="hidden" id='<?=$fieldIdentifier?>' name="<?=$strHTMLControlName["VALUE"]?>" value="<?=$value['VALUE']?>" |
<sc ript> $(window).load(function() { ... $('#crm-<?=$userIdentifier?>-box').live('DOMSubtreeModified', function() { try{ var product=$('#crm-<?=$userIdentifier?>-box').find('a').attr('href'); $('#<?=$userIdentifier?>').val(product.replace(/[^\d]/gi, '')); } catch(e){ $('#<?=$userIdentifier?>').val(''); } ... }); }); </sc ript> |
Следующий фрагмент кода решает задачу сильного подтормаживания при поиске товаров. (именно товаров, т.к. с компаниями такого не наблюдалось).
На ввод символов стоит обработчик события "keyup", что означает, что после каждого введенного символа происходит post запрос к компоненту crm.product.list, а именно к файлу list.ajax.php, который и осуществляет поиск по товарам. И если пользователь вводит слово "мотопомпа", то происходит 9 обращений (!) к этому фалу, что при количестве товаров более 20к выдает сильные тормоза (на скрине apache не загружен, в рабочие часы запросы могут исполнятся по 2-3 минуты!)
Для решения этой проблемы написал небольшую функцию, которая ставит таймер и выполняет отложенный поиск, что позволяет выполнять всего 1 запрос вместо нескольких и в разы сэкономить время. Поясню "тонкое место" при загрузке скрипта на страницу происходит отложенная смена обработчика события для поля ввода (у меня она установлена в 1500 миллисекунд). Сделано это потому, что форма выбора товара подгружается отложено и не сразу присутствует на странице.
<sc ript> $(window).load(function() { ... setTimeout(function(){ BX.unbindAll(BX('crm-crm-form-<?=str_replace('_','-',$strHTMLControlName['FORM_NAME'])?>-product-id-open_<?=$fieldIdentifier?>-search-input')); BX.bind(BX('crm-crm-form-<?=str_replace('_','-',$strHTMLControlName['FORM_NAME'])?>-product-id-open_<?=$fieldIdentifier?>-search-input'), "keyup", function(event){ switchTimer();}); },1500); function switchTimer() { timeHandlerId=getCookie('timeHandlerId'); if(timeHandlerId!=0) clearTimeout(timeHandlerId); var crmID="crm-form-<?=str_replace('_','-',$strHTMLControlName['FORM_NAME'])?>-product-id-open"; timeHandlerId=setTimeout(function(){ CRM.SearchChange(crmID) },2000); document.cookie='timeHandlerId='+timeHandlerId; } // возвращает cookie с именем name, если есть, если нет, то undefined function getCookie(name) { var matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } ... }); </sc ript> |
И последнее, что было необходимо - отображение списка товаров списком, а не таблицей. За это отвечает код
<st yle type="text/css"> #crm-crm-form-<?=str_replace('_','-',$strHTMLControlName['FORM_NAME'])?>-product-id-open_<?=$fieldIdentifier?>-block-product .crm-block-cont-contact-info { width: 330px!important; } #crm-crm-form-<?=str_replace('_','-',$strHTMLControlName['FORM_NAME'])?>-product-id-open_<?=$fieldIdentifier?>-block-search .crm-block-cont-contact-info { width: 330px!important; } </style> |
2. Функция, отвечающая за отображение в списке элементов - выводит название товара с ссылкой на карточку товара в crm
function GetPublicViewHTML($arProperty, $value, $strHTMLControlName) { if($value['VALUE']!=''){ $rsGroup=CCrmProduct::GetList(array(), array("ID"=>$value['VALUE'])); $arGroup=$rsGroup->Fetch(); if($arGroup) return '<a target="blank" href="/crm/product/show/'.$arGroup["ID"].'/">'.$arGroup["NAME"].'</a>'; else return ""; } else return ""; } |
При отображении в фильтре используется crm.field.filter , тогда как не в фильтре подключается system.field.edit. За это отвечает флаг 'FILTER'=>'Y', компонента crm.entity.selector. Плюс при показе в фильтре изменяются некоторые стили.
Приведенный мною пример кода создает свойство для привязке к товару.
Для того, чтобы создать привязку к компании необходимо в параметрах компонента crm.entity.selector указать
'ENTITY_TYPE' => 'COMPANY' |
Порядок действий для подключения свойства привязка к товару в ваш проект (аналогично для свойства привязка к компании):
- Скачиваем файл usertype_product_crm.php
- Если не подключен JQuery - добавляем в файл строчку CJSCore::Init(‘jquery’); (спасибо Денис Диденко )
- Кладем его в /bitrix/php_interface/include/
- В /bitrix/php_interface/init.php пишем
include($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/include/usertype_product_crm.php");
- Заходим в свойства инфоблока, выбираем тип свойства "Привязка к товару CRM"