Лирическое отступление
Когда только начинаешь работать с чем-нибудь новым программным средством, то, зачастую, от недостаточного понимания, складывается негативное впечатление - все не так, как мне хочется и тут ограничены возможности и тут поставленная задача не реализуема. Но со временем приходит понимание, узнаешь больше о системе и все встает на свои места. Все больше осваиваешь и привыкаешь и задачи решаются быстрее и в рамках используемого в системе подхода.Ближе к делу
В рамках одного проекта на Битриксе понадобилось иметь свое необычное пользовательское свойство, ни числовое, ни строковое, ни какое-либо другое стандартное не подходило. Сначала задача казалась не выполнимой в системе, но поиск решения в Интернете принес свои плоды и мы стали реализовывать требуемый функционал.
Чтобы не быть голословным далее рассмотрим простой пример реализации пользовательского свойства для элементов и разделов инфоблоков.
Процесс разработки был не простой, но нет ничего невозможного для специалиста, это всего лишь вопрос времени. К сожалению, пользовательские свойства элементов инфоблоков и разделов относятся к разным модулям (инфоблоки и главный модуль соответственно), отсюда и разный подход в их реализации. К тому же, поиск в Интернете выдал только простой пример и за дополнительной информацией пришлось обращаться к исходным кодам Битрикса, к счастью, они местами хорошо документированы.
Осветим поподробней эту полезную тему
Для примера попробуем реализовать свойство для выбора цвета с помощью jQuery UI. Свойствао можно будет использовать как для элемента так и для раздела инфоблока. Сразу замечу, что код примера нужно доводить до ума для использования на реальном проекте. По уму, нужно выделить общий класс с методами для представления и редактирования свойства, затем унаследовать от него еще два класса - на каждую отличающуюся реализацию.
Общий алгоритм примерно следующий:
- прописываем обработчики событий для OnIBlockPropertyBuildList (из инфоблока) и OnUserTypeBuildList (из главного модуля);
- реализуем методы описывающие свойства, отдельные для каждого из двух модулей;
- реализуем общие методы представления и редактирования свойства.
Собственно, сам код с небольшими комментариями
<?
// расширим свой класс от числового типа
class UserDataColor extends CUserTypeInteger
{
// инициализация пользовательского свойства для главного модуля
function GetUserTypeDescription()
{
return array(
"USER_TYPE_ID" => "color",
"CLASS_NAME" => "UserDataColor",
"DESCRIPTION" => "Цвет",
"BASE_TYPE" => "int",
);
}
// инициализация пользовательского свойства для инфоблока
function GetIBlockPropertyDescription()
{
return array(
"PROPERTY_TYPE" => "S",
"USER_TYPE" => "color",
"DESCRIPTION" => "Цвет",
'GetPropertyFieldHtml' => array('UserDataColor', 'GetPropertyFieldHtml'),
'GetAdminListViewHTML' => array('UserDataColor', 'GetAdminListViewHTML'),
);
}
// представление свойства
function getViewHTML($name, $value)
{
return '<div style="display: block; width: 16px; height: 16px; background-color: #'.str_pad(dechex($value), 6, '0', STR_PAD_LEFT).';"> </div>';
}
// редактирование свойства
function getEditHTML($name, $value, $is_ajax = false)
{
$uid = 'x'.uniqid();
$dom_id = $uid;
$colorHex = str_pad(dechex($value), 6, '0', STR_PAD_LEFT);
$colorRGB = array();
$colorRGB[0] = hexdec(substr($colorHex, -6, 2));
$colorRGB[1] = hexdec(substr($colorHex, -4, 2));
$colorRGB[2] = hexdec(substr($colorHex, -2, 2));
$init = $is_ajax ? 'init();' : '$(init);';
return <<<SSS
<input type="hidden" id="{$dom_id}" name="{$name}" value="{$value}">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<style>
#red{$uid}, #green{$uid}, #blue{$uid} {float: left; clear: left; width: 300px; margin: 15px;}
#swatch{$uid} {width: 120px; height: 100px; margin-top: 18px; margin-left: 350px; background-image: none;}
#red{$uid} .ui-slider-range, #red{$uid} .ui-slider-handle { background: #ef2929; }
#green{$uid} .ui-slider-range, #green{$uid} .ui-slider-handle { background: #8ae234; }
#blue{$uid} .ui-slider-range, #blue{$uid} .ui-slider-handle { background: #729fcf; }
</style>
<div>
<div id="red{$uid}"></div>
<div id="green{$uid}"></div>
<div id="blue{$uid}"></div>
<div id="swatch{$uid}" class="ui-widget-content ui-corner-all"></div>
</div>
<script>
(function(){
function hexFromRGB(r, g, b) {
var hex = [
r.toString( 16 ),
g.toString( 16 ),
b.toString( 16 )
];
$.each( hex, function( nr, val ) {
if ( val.length === 1 ) {
hex[ nr ] = "0" + val;
}
});
return hex.join( "" ).toUpperCase();
}
function refreshSwatch() {
var red = $( "#red{$uid}" ).slider( "value" ),
green = $( "#green{$uid}" ).slider( "value" ),
blue = $( "#blue{$uid}" ).slider( "value" ),
hex = hexFromRGB( red, green, blue );
$( "#{$dom_id}" ).val(red*256*256+green*256+blue);
$( "#swatch{$uid}" ).css( "background-color", "#" + hex );
}
var init = function() {
$( "#red{$uid}, #green{$uid}, #blue{$uid}" ).slider({
orientation: "horizontal",
range: "min",
max: 255,
value: 0,
slide: refreshSwatch,
change: refreshSwatch
});
$( "#red{$uid}" ).slider( "value", {$colorRGB[0]} );
$( "#green{$uid}" ).slider( "value", {$colorRGB[1]} );
$( "#blue{$uid}" ).slider( "value", {$colorRGB[2]} );
};
{$init}
})();
</script>
SSS;
}
// редактирование свойства в форме (главный модуль)
function GetEditFormHTML($arUserField, $arHtmlControl)
{
return self::getEditHTML($arHtmlControl['NAME'], $arHtmlControl['VALUE'], false);
}
// редактирование свойства в списке (главный модуль)
function GetAdminListEditHTML($arUserField, $arHtmlControl)
{
return self::getViewHTML($arHtmlControl['NAME'], $arHtmlControl['VALUE'], true);
}
// представление свойства в списке (главный модуль, инфоблок)
function GetAdminListViewHTML($arProperty, $value, $strHTMLControlName)
{
return self::getViewHTML($strHTMLControlName['VALUE'], $value['VALUE']);
}
// редактирование свойства в форме и списке (инфоблок)
function GetPropertyFieldHtml($arProperty, $value, $strHTMLControlName)
{
return $strHTMLControlName['MODE'] == 'FORM_FILL'
? self::getEditHTML($strHTMLControlName['VALUE'], $value['VALUE'], false)
: self::getViewHTML($strHTMLControlName['VALUE'], $value['VALUE'])
;
}
}
// добавляем тип для инфоблока
AddEventHandler("iblock", "OnIBlockPropertyBuildList", array("UserDataColor", "GetIBlockPropertyDescription"));
// добавляем тип для главного модуля
AddEventHandler("main", "OnUserTypeBuildList", array("UserDataColor", "GetUserTypeDescription"));
?>
с битрикс работаю недавно ;) самому нужно создать новый тип свойства (для инфоблока) в какой файл идет весь этот код?
ОтветитьУдалитьмаленькое дополнение:
ОтветитьУдалитьчтобы потом воспользоваться значением из данного свойства, его нужно преобразовать обратно:
$colorHex = str_pad(dechex($value), 6, '0', STR_PAD_LEFT);
$colorRGB = array();
$colorRGB[0] = hexdec(substr($colorHex, -6, 2));
$colorRGB[1] = hexdec(substr($colorHex, -4, 2));
$colorRGB[2] = hexdec(substr($colorHex, -2, 2));