Несколько изображений к товару средствами дополнительных полей — различия между версиями

Материал из Umicms
Перейти к:навигация, поиск
(Новая страница: «'''Актуально для версии 2.9.5''' == Задача == Вывести на сайте несколько изображений к товару, н…»)
 
 
(не показаны 23 промежуточные версии этого же участника)
Строка 15: Строка 15:
 
[[Файл:Fields_simple.png]]
 
[[Файл:Fields_simple.png]]
  
 +
2) Создадим товар с этим типом данных и заполним созданные поля в карточке товара:
  
 +
[[Файл:Fields_simple_page.png]]
 +
 +
3) Теперь осталось это вывести, вывод в tpl есть в статье [[Добавление_нескольких_фотографий_к_описанию_объекта_каталога]], первый вариант.
 +
В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:
 +
 +
<source lang="xml">
 +
<group id="5573" name="kartinki">
 +
<title>Картинки</title>
 +
<property id="971" name="kartinka_1" type="img_file">
 +
<title>Картинка 1</title>
 +
<value path="./images/cms/data/sovet/sovet-cv_tc21.jpg" folder="/images/cms/data/sovet" name="sovet-cv_tc21" ext="jpg" width="680" height="499">/images/cms/data/sovet/sovet-cv_tc21.jpg</value>
 +
</property>
 +
<property id="972" name="kartinka_2" type="img_file">
 +
<title>Картинка 2</title>
 +
<value path="./images/cms/data/sovet/sovet-tc3.jpg" folder="/images/cms/data/sovet" name="sovet-tc3" ext="jpg" width="350" height="350">/images/cms/data/sovet/sovet-tc3.jpg</value>
 +
</property>
 +
<property id="973" name="kartinka_3" type="img_file">
 +
<title>Картинка 3</title>
 +
<value path="./images/cms/data/sovet/sovet-tv-tc1.jpg" folder="/images/cms/data/sovet" name="sovet-tv-tc1" ext="jpg" width="500" height="412">/images/cms/data/sovet/sovet-tv-tc1.jpg</value>
 +
</property>
 +
<property id="974" name="kartinka_4" type="img_file">
 +
<title>Картинка 4</title>
 +
<value path="./images/cms/data/sovet/soviet-tv-b1.jpg" folder="/images/cms/data/sovet" name="soviet-tv-b1" ext="jpg" width="500" height="375">/images/cms/data/sovet/soviet-tv-b1.jpg</value>
 +
</property>
 +
<property id="975" name="kartinka_5" type="img_file">
 +
<title>Картинка 5</title>
 +
<value path="./images/cms/data/sovet/soviet-tv-ba.jpg" folder="/images/cms/data/sovet" name="soviet-tv-ba" ext="jpg" width="680" height="573">/images/cms/data/sovet/soviet-tv-ba.jpg</value>
 +
</property>
 +
<property id="977" name="kartinka_6" type="img_file">
 +
<title>Картинка 6</title>
 +
<value path="./images/cms/data/sovet/soviet-tv-t7.jpg" folder="/images/cms/data/sovet" name="soviet-tv-t7" ext="jpg" width="890" height="630">/images/cms/data/sovet/soviet-tv-t7.jpg</value>
 +
</property>
 +
</group>
 +
</source>
 +
 +
Обработать это дерево можно с помощью следующей конструкции:
 +
 +
<source lang="xml">
 +
<div style="max-width: 300; max-height: 300;">
 +
<ul class="bxslider">
 +
<xsl:for-each select="./page/properties/group[@name = 'kartinki']/property[@type = 'img_file']">
 +
<li>
 +
<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', ./value, ')/200/auto'))"/>
 +
</li>
 +
</xsl:for-each>
 +
</ul>
 +
</div>
 +
</source>
 +
 +
и шаблона, знакомого нам по статье [[Несколько_изображений_к_товару_средствами_протокола_ufs]] (bxslider мы берем оттуда же):
 +
 +
<source lang="xml">
 +
<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
 +
<img src="{src}"/>
 +
</xsl:template>
 +
</source>
 +
 +
=== Плюсы ===
 +
 +
<ul>
 +
<li>Легко реализовать в административном интерфейсе</li>
 +
<li>Легко вывести на сайте</li>
 +
<li>Легко менять изображения, в том числе и через eip</li>
 +
</ul>
 +
 +
=== Минусы ===
 +
 +
<ul>
 +
<li>Нельзя добавить дополнительное изображение ни через eip, ни через редактирование страницы</li>
 +
<li>Пользователю будет нужно редактировать типы данных, а это чревато [[Ошибка_(coreException):_Give_me_a_normal_type_to_create_;)]]</li>
 +
</ul>
  
 
== Вариант 2 ==
 
== Вариант 2 ==
  [[category:Модуль Каталог]]
+
 
 +
1) Создадим в типе данных, к которому относится товар составное поле и справочник к нему:
 +
 
 +
[[Файл:Fields_option.png]]
 +
 
 +
2) Создадим в типе данных этого справочника поле типа изображение:
 +
 
 +
[[Файл:Guid_options.png]]
 +
 
 +
3) Заполним справочник элементами:
 +
 
 +
[[Файл:Guid_options_add.png]]
 +
 
 +
4) Выберем на странице товара эти элементы:
 +
 
 +
[[Файл:Fields_option_page.png]]
 +
 
 +
5) Теперь осталось это вывести. В tpl для этого понадобится макрос %data getProperty()%, который выведет опцию,
 +
а в шаблоне для вывода опции понадобится макрос %data getPropertyOfObject()%, для вывода картинки.
 +
В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:
 +
 
 +
<source lang="xml">
 +
<property id="976" name="pictures" type="optioned">
 +
<title>Изображения</title>
 +
<value>
 +
<option int="1">
 +
<object id="5726" name="Картинка 1" type-id="620" ownerId="2" xlink:href="uobject://5726"/>
 +
</option>
 +
<option int="1">
 +
<object id="5727" name="Картинка 2" type-id="620" ownerId="2" xlink:href="uobject://5727"/>
 +
</option>
 +
<option int="1">
 +
<object id="5728" name="Картинка 3" type-id="620" ownerId="2" xlink:href="uobject://5728"/>
 +
</option>
 +
<option int="1">
 +
<object id="5729" name="Картинка 4" type-id="620" ownerId="2" xlink:href="uobject://5729"/>
 +
</option>
 +
<option int="1">
 +
<object id="5730" name="Картинка 5" type-id="620" ownerId="2" xlink:href="uobject://5730"/>
 +
</option>
 +
<option int="1">
 +
<object id="5731" name="Картинка 6" type-id="620" ownerId="2" xlink:href="uobject://5731"/>
 +
</option>
 +
</value>
 +
</property>
 +
</source>
 +
 
 +
Обработать это дерево можно с помощью следующей конструкции (снова используется bxslider):
 +
 
 +
<source lang="xml">
 +
<div style="max-width: 300; max-height: 300;">
 +
<ul class="bxslider">
 +
<xsl:for-each select="./page/properties/group[@name = 'kartinki']/property[@type = 'optioned']/value/option">
 +
<li>
 +
<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('uobject://', ./object/@id,  '.kartinka'))//value, ')/200/auto'))"/>
 +
</li>
 +
</xsl:for-each>
 +
</ul>
 +
</div>
 +
</source>
 +
 
 +
и уже знакомого темплейта:
 +
 
 +
<source lang="xml">
 +
<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
 +
<img src="{src}"/>
 +
</xsl:template>
 +
</source>
 +
 
 +
=== Плюсы ===
 +
 
 +
<ul>
 +
<li>Легко вывести на сайте</li>
 +
<li>Легко менять изображения, в том числе и через eip</li>
 +
<li>Можно добавить дополнительное изображение через редактирование страницы</li>
 +
</ul>
 +
 
 +
=== Минусы ===
 +
 
 +
<ul>
 +
<li>Нельзя добавить дополнительное изображение через eip</li>
 +
<li>В интерфейсе страницы не видны изображения выбранных элементов</li>
 +
<li>Муторно добавлять элементы в справочник, а потом еще и опции на страницу</li>
 +
</ul>
 +
 
 +
=== Кастомизация административного интерфейса ===
 +
 
 +
Попробуем решить два последних минуса и облегчить жизнь пользователю, то есть будет нужно:
 +
 
 +
<ul>
 +
<li>Сделать отображение картинок выбранных элементов.</li>
 +
<li>Дать возможность заполнить справочник прямо со страницы товар.</li>
 +
</ul>
 +
 
 +
Пример кастомизации даем ниже.
 +
 
 +
1) Создадим в директории /styles/skins/mac/data/modules/catalog файл form.modify.custom.xsl следующего содержания:
 +
 
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="utf-8"?>
 +
<!DOCTYPE xsl:stylesheet SYSTEM "ulang://common">
 +
<xsl:stylesheet version="1.0"
 +
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 +
xmlns:umi="http://www.umi-cms.ru/TR/umi"
 +
xmlns:php="http://php.net/xsl"
 +
>
 +
<xsl:template match="field[@type = 'optioned']" mode="form-modify">
 +
<div class="field text">
 +
<label for="{generate-id()}">
 +
<span>
 +
<xsl:call-template name="std-optioned-control_cus" />
 +
</span>
 +
</label>
 +
</div>
 +
</xsl:template>
 +
 
 +
<xsl:template match="field[@type = 'optioned' and @name = 'stores_state']" mode="form-modify">
 +
<div class="field text">
 +
<label for="{generate-id()}">
 +
<span>
 +
<xsl:call-template name="std-optioned-control_cus">
 +
<xsl:with-param name="type" select="'int'" />
 +
</xsl:call-template>
 +
</span>
 +
</label>
 +
</div>
 +
</xsl:template>
 +
 +
<xsl:template name="std-optioned-control_cus">
 +
<xsl:param name="guide-id" select="@guide-id" />
 +
<xsl:param name="input-name" select="@input_name" />
 +
<xsl:param name="title" select="@title" />
 +
<xsl:param name="tip" select="@tip" />
 +
<xsl:param name="type"><xsl:text>float</xsl:text></xsl:param>
 +
<xsl:choose>
 +
<xsl:when test="@name = 'pictures'">
 +
<h3>Добавить изображение:</h3>
 +
 +
<xsl:variable name="filemanager">
 +
<xsl:text>elfinder</xsl:text>
 +
</xsl:variable>
 +
<span>
 +
<strong>Выберите изображение:</strong>
 +
</span>
 +
<div class="field file" id="{generate-id()}" umi:input-name="photo"
 +
umi:field-type="img_file"
 +
umi:name="photo"
 +
umi:folder="{@destination-folder}"
 +
umi:file="{@relative-path}"
 +
umi:folder-hash="{php:function('elfinder_get_hash', string(@destination-folder))}"
 +
umi:file-hash="{php:function('elfinder_get_hash', string(@relative-path))}"
 +
umi:lang="{/result/@interface-lang}"
 +
umi:filemanager="{$filemanager}"
 +
>
 +
<label for="symlinkInput{generate-id()}">
 +
<span id="fileControlContainer_{generate-id()}">
 +
</span>
 +
</label>
 +
</div>
 +
 +
<xsl:variable name="gen_id" select="string(concat('fileControlContainer_', generate-id()))"/>
 +
<xsl:variable name="guid_id" select="number(./@guide-id)"/>
 +
<xsl:variable name="rel_id" select="string(concat('relationSelect', generate-id()))"/>
 +
 +
<script type="text/javascript">
 +
$(document).ready(function(){
 +
$('#make_element').click(function(){
 +
 +
$('#make_element').attr('src', "/images/cms/loading.gif");
 +
 +
$photo_name = $('#option_name').val();
 +
$photo_path = $('#<xsl:value-of select="$gen_id"/> option:selected').val();
 +
 +
if($photo_name == '' || $photo_path == ''){
 +
$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
 +
return jQuery.jGrowl('Выберите изображение и укажите его имя', {
 +
'header': 'Поля не заполнены',
 +
'life': 1500
 +
});
 +
}
 +
 +
$.ajax({
 +
  type: "POST",
 +
  url: "/udata://custom/makeElement/.json",
 +
  dataType: "json",
 +
  data: { photo_name: $photo_name,
 +
          photo_path: $photo_path,
 +
  guid: '<xsl:value-of select="$guid_id"/>'
 +
  }
 +
}).done(function(json) {
 +
$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
 +
$object_id = json.result;
 +
$option = "<option value=" + $object_id + ">" + $photo_name + "</option>";
 +
$('#<xsl:value-of select="$rel_id"/>').append($option);
 +
return jQuery.jGrowl('Элемент успешно добавлен, теперь можно добавить еще', {
 +
'header': 'Элемент успешно добавлен',
 +
'life': 1500
 +
});
 +
  })
 +
  .fail(function() {
 +
$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
 +
return jQuery.jGrowl('При добавлении элемента произошла ошибка', {
 +
'header': 'Ошибка',
 +
'life': 1000
 +
});
 +
  })
 +
});
 +
});
 +
</script>
 +
<span style="width: 47%;">
 +
<strong>Укажите имя изображения:</strong>
 +
<input id="option_name" type="text"/>
 +
<img id="make_element" src="/images/cms/admin/mac/table/ico_add.gif"/>
 +
</span>
 +
 +
<h3>Выбрать изображение:</h3>
 +
<table id="{generate-id()}" class="tableContent optioned">
 +
<thead>
 +
<th umi:type="rel">
 +
<acronym>
 +
<xsl:if test="$tip">
 +
<xsl:attribute name="title"><xsl:value-of select="$tip" /></xsl:attribute>
 +
</xsl:if>
 +
<strong><xsl:value-of select="$title" />:</strong>
 +
</acronym>
 +
</th>
 +
<th umi:type="{$type}" class="center" />
 +
<th class="center narrow" />
 +
</thead>
 +
<tbody>
 +
<xsl:apply-templates mode="field-optioned_cus">
 +
<xsl:with-param name="input-name" select="$input-name" />
 +
<xsl:with-param name="type" select="$type" />
 +
</xsl:apply-templates>
 +
</tbody>
 +
<tfoot>
 +
<tr>
 +
<td style="padding-left:0;">
 +
<select id="relationSelect{generate-id()}" umi:guide="{$guide-id}" umi:name="{$input-name}" class="relation-add"></select>
 +
<input type="text" id="relationInput{generate-id()}" />
 +
<input type="hidden"  id="relationButton{generate-id()}" />
 +
</td>
 +
<td class="center"><input type="text" umi:type="{$type}" /></td>
 +
<td class="center narrow">
 +
<a href="#" class="add"><img src="/images/cms/admin/mac/table/ico_add.gif" /></a>
 +
</td>
 +
</tr>
 +
</tfoot>
 +
</table>
 +
<div>
 +
<a href="{$lang-prefix}/admin/data/guide_items/{$guide-id}/"><xsl:text>&label-edit-guide-items;</xsl:text></a>
 +
</div>
 +
</xsl:when>
 +
<xsl:otherwise>
 +
<table id="{generate-id()}" class="tableContent optioned">
 +
<thead>
 +
<th umi:type="rel">
 +
<acronym>
 +
<xsl:if test="$tip">
 +
<xsl:attribute name="title"><xsl:value-of select="$tip" /></xsl:attribute>
 +
</xsl:if>
 +
<xsl:value-of select="$title" />
 +
</acronym>
 +
</th>
 +
<th umi:type="{$type}" class="center" />
 +
<th class="center narrow" />
 +
</thead>
 +
<tbody>
 +
<xsl:apply-templates mode="field-optioned">
 +
<xsl:with-param name="input-name" select="$input-name" />
 +
<xsl:with-param name="type" select="$type" />
 +
</xsl:apply-templates>
 +
</tbody>
 +
<tfoot>
 +
<tr>
 +
<td style="padding-left:0;">
 +
<select id="relationSelect{generate-id()}" umi:guide="{$guide-id}" umi:name="{$input-name}" class="relation-add"></select>
 +
<input type="text" id="relationInput{generate-id()}" />
 +
<input type="hidden"  id="relationButton{generate-id()}" />
 +
</td>
 +
<td class="center"><input type="text" umi:type="{$type}" /></td>
 +
<td class="center narrow">
 +
<a href="#" class="add"><img src="/images/cms/admin/mac/table/ico_add.gif" /></a>
 +
</td>
 +
</tr>
 +
</tfoot>
 +
</table>
 +
<div>
 +
<a href="{$lang-prefix}/admin/data/guide_items/{$guide-id}/"><xsl:text>&label-edit-guide-items;</xsl:text></a>
 +
</div>
 +
</xsl:otherwise>
 +
</xsl:choose>
 +
</xsl:template>
 +
 
 +
<xsl:template match="field/values/value" mode="field-optioned_cus">
 +
<xsl:param name="input-name" />
 +
<xsl:param name="type"><xsl:text>float</xsl:text></xsl:param>
 +
<xsl:variable name="position" select="position()" />
 +
<tr>
 +
<td>
 +
<span><xsl:value-of select="object/@name" /></span>
 +
<span><xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('uobject://', object/@id))/udata/object/properties/group[@name='kartinki']/property[@name='kartinka']/value, ')/50/auto'))" mode="optioned_pic"/></span>
 +
<input type="hidden" name="{$input-name}[{$position}][rel]" value="{object/@id}" />
 +
</td>
 +
<td class="center">
 +
<xsl:choose>
 +
<xsl:when test="$type = 'int'">
 +
<input type="text" umi:type="{$type}" name="{$input-name}[{$position}][{$type}]" value="{@int}" />
 +
<input type="hidden" umi:type="float" name="{$input-name}[{$position}][float]" value="1" />
 +
</xsl:when>
 +
<xsl:when test="$type = 'varchar'">
 +
<input type="text" umi:type="{$type}" name="{$input-name}[{$position}][{$type}]" value="{@varchar}" />
 +
<input type="hidden" umi:type="int" name="{$input-name}[{$position}][int]" value="1" />
 +
</xsl:when>
 +
<xsl:otherwise>
 +
<input type="text" umi:type="float" name="{$input-name}[{$position}][float]" value="{@float}" />
 +
<input type="hidden" umi:type="int" name="{$input-name}[{$position}][int]" value="1" />
 +
</xsl:otherwise>
 +
</xsl:choose>
 +
</td>
 +
<td class="center narrow">
 +
<a href="#" class="remove">
 +
<img src="/images/cms/admin/mac/table/ico_del.gif" />
 +
</a>
 +
</td>
 +
</tr>
 +
</xsl:template>
 +
 +
<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']" mode="optioned_pic">
 +
<img src="{src}"/>
 +
</xsl:template>
 +
 
 +
<xsl:include href="udata://core/importSkinXsl/form.modify.xsl"/>
 +
</xsl:stylesheet>
 +
</source>
 +
 
 +
2) Добавим в файл /classes/modules/custom.php следующий кастомный метод:
 +
 
 +
<source lang="php">
 +
public function makeElement(){
 +
$name = urldecode($_POST['photo_name']);
 +
$name = htmlspecialchars($name);
 +
 +
$guid = intval($_POST['guid']);
 +
$path = $_POST['photo_path'];
 +
 
 +
$objectsCollection = umiObjectsCollection::getInstance();
 +
$id = $objectsCollection->addObject($name, $guid);
 +
if($id){
 +
$object = $objectsCollection->getObject($id);
 +
$object->setValue('kartinka', $path);
 +
$object->commit();
 +
return $id;
 +
}else{
 +
return 'Не удалось создать объект';
 +
}
 +
}
 +
</source>
 +
 
 +
3) Теперь в карточке товара мы увидим следующее:
 +
 
 +
[[Файл:Custom_adm_option.png]]
 +
 
 +
== Дополнительно ==
 +
 
 +
Также, есть и другие способы вывода нескольких картинок для товара:
 +
 
 +
<ul>
 +
<li>[[Несколько_изображений_к_товару_средствами_протокола_ufs]]</li>
 +
<li>[[Несколько_изображений_к_товару_средствами_модуля_Фотогалереи]]</li>
 +
</ul>
 +
  [[category:Модуль Каталог]][[Категория: Верстка в XSLT]][[Категория:Написание кастомных макросов]]

Текущая версия на 15:16, 25 марта 2014

Актуально для версии 2.9.5

Задача

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

Решение

Задачу можно решить средствами модуля "Шаблоны данных", ниже дан пример.

Вариант 1

1) Создадим в типе данных, к которому относится товар, столько полей типа изображение, сколько будет изображений у товара:

Fields simple.png

2) Создадим товар с этим типом данных и заполним созданные поля в карточке товара:

Fields simple page.png

3) Теперь осталось это вывести, вывод в tpl есть в статье Добавление_нескольких_фотографий_к_описанию_объекта_каталога, первый вариант. В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:

<group id="5573" name="kartinki">
	<title>Картинки</title>
	<property id="971" name="kartinka_1" type="img_file">
		<title>Картинка 1</title>
		<value path="./images/cms/data/sovet/sovet-cv_tc21.jpg" folder="/images/cms/data/sovet" name="sovet-cv_tc21" ext="jpg" width="680" height="499">/images/cms/data/sovet/sovet-cv_tc21.jpg</value>
	</property>
	<property id="972" name="kartinka_2" type="img_file">
		<title>Картинка 2</title>
		<value path="./images/cms/data/sovet/sovet-tc3.jpg" folder="/images/cms/data/sovet" name="sovet-tc3" ext="jpg" width="350" height="350">/images/cms/data/sovet/sovet-tc3.jpg</value>
	</property>
	<property id="973" name="kartinka_3" type="img_file">
		<title>Картинка 3</title>
		<value path="./images/cms/data/sovet/sovet-tv-tc1.jpg" folder="/images/cms/data/sovet" name="sovet-tv-tc1" ext="jpg" width="500" height="412">/images/cms/data/sovet/sovet-tv-tc1.jpg</value>
	</property>
	<property id="974" name="kartinka_4" type="img_file">
		<title>Картинка 4</title>
		<value path="./images/cms/data/sovet/soviet-tv-b1.jpg" folder="/images/cms/data/sovet" name="soviet-tv-b1" ext="jpg" width="500" height="375">/images/cms/data/sovet/soviet-tv-b1.jpg</value>
	</property>
	<property id="975" name="kartinka_5" type="img_file">
		<title>Картинка 5</title>
		<value path="./images/cms/data/sovet/soviet-tv-ba.jpg" folder="/images/cms/data/sovet" name="soviet-tv-ba" ext="jpg" width="680" height="573">/images/cms/data/sovet/soviet-tv-ba.jpg</value>
	</property>
	<property id="977" name="kartinka_6" type="img_file">
		<title>Картинка 6</title>
		<value path="./images/cms/data/sovet/soviet-tv-t7.jpg" folder="/images/cms/data/sovet" name="soviet-tv-t7" ext="jpg" width="890" height="630">/images/cms/data/sovet/soviet-tv-t7.jpg</value>
	</property>
</group>

Обработать это дерево можно с помощью следующей конструкции:

<div style="max-width: 300; max-height: 300;">
	<ul class="bxslider">
		<xsl:for-each select="./page/properties/group[@name = 'kartinki']/property[@type = 'img_file']">
			<li>
				<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', ./value, ')/200/auto'))"/>
			</li>
		</xsl:for-each>
	</ul>
</div>

и шаблона, знакомого нам по статье Несколько_изображений_к_товару_средствами_протокола_ufs (bxslider мы берем оттуда же):

<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
	<img src="{src}"/>
</xsl:template>

Плюсы

  • Легко реализовать в административном интерфейсе
  • Легко вывести на сайте
  • Легко менять изображения, в том числе и через eip

Минусы

  • Нельзя добавить дополнительное изображение ни через eip, ни через редактирование страницы
  • Пользователю будет нужно редактировать типы данных, а это чревато Ошибка_(coreException):_Give_me_a_normal_type_to_create_;)

Вариант 2

1) Создадим в типе данных, к которому относится товар составное поле и справочник к нему:

Fields option.png

2) Создадим в типе данных этого справочника поле типа изображение:

Guid options.png

3) Заполним справочник элементами:

Guid options add.png

4) Выберем на странице товара эти элементы:

Fields option page.png

5) Теперь осталось это вывести. В tpl для этого понадобится макрос %data getProperty()%, который выведет опцию, а в шаблоне для вывода опции понадобится макрос %data getPropertyOfObject()%, для вывода картинки. В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:

<property id="976" name="pictures" type="optioned">
	<title>Изображения</title>
	<value>
		<option int="1">
			<object id="5726" name="Картинка 1" type-id="620" ownerId="2" xlink:href="uobject://5726"/>
		</option>
		<option int="1">
			<object id="5727" name="Картинка 2" type-id="620" ownerId="2" xlink:href="uobject://5727"/>
		</option>
		<option int="1">
			<object id="5728" name="Картинка 3" type-id="620" ownerId="2" xlink:href="uobject://5728"/>
		</option>
		<option int="1">
			<object id="5729" name="Картинка 4" type-id="620" ownerId="2" xlink:href="uobject://5729"/>
		</option>
		<option int="1">
			<object id="5730" name="Картинка 5" type-id="620" ownerId="2" xlink:href="uobject://5730"/>
		</option>
		<option int="1">
			<object id="5731" name="Картинка 6" type-id="620" ownerId="2" xlink:href="uobject://5731"/>
		</option>
	</value>
</property>

Обработать это дерево можно с помощью следующей конструкции (снова используется bxslider):

<div style="max-width: 300; max-height: 300;">
	<ul class="bxslider">
		<xsl:for-each select="./page/properties/group[@name = 'kartinki']/property[@type = 'optioned']/value/option">
			<li>
				<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('uobject://', ./object/@id,  '.kartinka'))//value, ')/200/auto'))"/>
			</li>
		</xsl:for-each>
	</ul>
</div>

и уже знакомого темплейта:

<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
	<img src="{src}"/>
</xsl:template>

Плюсы

  • Легко вывести на сайте
  • Легко менять изображения, в том числе и через eip
  • Можно добавить дополнительное изображение через редактирование страницы

Минусы

  • Нельзя добавить дополнительное изображение через eip
  • В интерфейсе страницы не видны изображения выбранных элементов
  • Муторно добавлять элементы в справочник, а потом еще и опции на страницу

Кастомизация административного интерфейса

Попробуем решить два последних минуса и облегчить жизнь пользователю, то есть будет нужно:

  • Сделать отображение картинок выбранных элементов.
  • Дать возможность заполнить справочник прямо со страницы товар.

Пример кастомизации даем ниже.

1) Создадим в директории /styles/skins/mac/data/modules/catalog файл form.modify.custom.xsl следующего содержания:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet SYSTEM "ulang://common">
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:umi="http://www.umi-cms.ru/TR/umi"
	xmlns:php="http://php.net/xsl"
	>
	<xsl:template match="field[@type = 'optioned']" mode="form-modify">
		<div class="field text">
			<label for="{generate-id()}">
				<span>
					<xsl:call-template name="std-optioned-control_cus" />
				</span>
			</label>
		</div>
	</xsl:template>

	<xsl:template match="field[@type = 'optioned' and @name = 'stores_state']" mode="form-modify">
		<div class="field text">
			<label for="{generate-id()}">
				<span>
					<xsl:call-template name="std-optioned-control_cus">
						<xsl:with-param name="type" select="'int'" />
					</xsl:call-template>
				</span>
			</label>
		</div>
	</xsl:template>
	
	<xsl:template name="std-optioned-control_cus">
		<xsl:param name="guide-id" select="@guide-id" />
		<xsl:param name="input-name" select="@input_name" />
		<xsl:param name="title" select="@title" />
		<xsl:param name="tip" select="@tip" />
		<xsl:param name="type"><xsl:text>float</xsl:text></xsl:param>
		<xsl:choose>
			<xsl:when test="@name = 'pictures'">
				<h3>Добавить изображение:</h3>
				
				<xsl:variable name="filemanager">
					<xsl:text>elfinder</xsl:text>
				</xsl:variable>
				<span>
					<strong>Выберите изображение:</strong>
				</span>
				<div class="field file" id="{generate-id()}" umi:input-name="photo"
					umi:field-type="img_file"
					umi:name="photo"
					umi:folder="{@destination-folder}"
					umi:file="{@relative-path}"
					umi:folder-hash="{php:function('elfinder_get_hash', string(@destination-folder))}"
					umi:file-hash="{php:function('elfinder_get_hash', string(@relative-path))}"
					umi:lang="{/result/@interface-lang}"
					umi:filemanager="{$filemanager}"
					>
					<label for="symlinkInput{generate-id()}">
						<span id="fileControlContainer_{generate-id()}">
						</span>
					</label>
				</div>
				
				<xsl:variable name="gen_id" select="string(concat('fileControlContainer_', generate-id()))"/>
				<xsl:variable name="guid_id" select="number(./@guide-id)"/>
				<xsl:variable name="rel_id" select="string(concat('relationSelect', generate-id()))"/>
				
				<script type="text/javascript">
					$(document).ready(function(){
						$('#make_element').click(function(){
							
							$('#make_element').attr('src', "/images/cms/loading.gif");
							
							$photo_name = $('#option_name').val();
							$photo_path = $('#<xsl:value-of select="$gen_id"/> option:selected').val();
							
							if($photo_name == '' || $photo_path == ''){
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								return jQuery.jGrowl('Выберите изображение и укажите его имя', {
													 'header': 'Поля не заполнены',
													 'life': 1500
													});
							}
							
							$.ajax({
								  type: "POST",
								  url: "/udata://custom/makeElement/.json",
								  dataType: "json",
								  data: { photo_name: $photo_name,
								          photo_path: $photo_path,
										  guid: '<xsl:value-of select="$guid_id"/>'
								  }
							}).done(function(json) {
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								$object_id = json.result;								
								$option = "<option value=" + $object_id + ">" + $photo_name + "</option>";								
								$('#<xsl:value-of select="$rel_id"/>').append($option);					
								return jQuery.jGrowl('Элемент успешно добавлен, теперь можно добавить еще', {
													 'header': 'Элемент успешно добавлен',
													 'life': 1500
													});
							  })
							  .fail(function() {
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								return jQuery.jGrowl('При добавлении элемента произошла ошибка', {
													 'header': 'Ошибка',
													 'life': 1000
													});
							  })
						});
					});
				</script>
				<span style="width: 47%;">
					<strong>Укажите имя изображения:</strong>
					<input id="option_name" type="text"/>
					<img id="make_element" src="/images/cms/admin/mac/table/ico_add.gif"/>
				</span>
				
				<h3>Выбрать изображение:</h3>
				<table id="{generate-id()}" class="tableContent optioned">
					<thead>
						<th umi:type="rel">
							<acronym>
								<xsl:if test="$tip">
									<xsl:attribute name="title"><xsl:value-of select="$tip" /></xsl:attribute>
								</xsl:if>
								<strong><xsl:value-of select="$title" />:</strong>
							</acronym>
						</th>
						<th umi:type="{$type}" class="center" />
						<th class="center narrow" />
					</thead>
					<tbody>
						<xsl:apply-templates mode="field-optioned_cus">
							<xsl:with-param name="input-name" select="$input-name" />
							<xsl:with-param name="type" select="$type" />
						</xsl:apply-templates>
					</tbody>
					<tfoot>
						<tr>
							<td style="padding-left:0;">
								<select id="relationSelect{generate-id()}" umi:guide="{$guide-id}" umi:name="{$input-name}" class="relation-add"></select>
								<input type="text" id="relationInput{generate-id()}" />
								<input type="hidden"  id="relationButton{generate-id()}" />
							</td>
							<td class="center"><input type="text" umi:type="{$type}" /></td>
							<td class="center narrow">
								<a href="#" class="add"><img src="/images/cms/admin/mac/table/ico_add.gif" /></a>
							</td>
						</tr>
					</tfoot>
				</table>
				<div>
					<a href="{$lang-prefix}/admin/data/guide_items/{$guide-id}/"><xsl:text>&label-edit-guide-items;</xsl:text></a>
				</div>			
			</xsl:when>
			<xsl:otherwise>
				<table id="{generate-id()}" class="tableContent optioned">
					<thead>
						<th umi:type="rel">
							<acronym>
								<xsl:if test="$tip">
									<xsl:attribute name="title"><xsl:value-of select="$tip" /></xsl:attribute>
								</xsl:if>
								<xsl:value-of select="$title" />
							</acronym>
						</th>
						<th umi:type="{$type}" class="center" />
						<th class="center narrow" />
					</thead>
					<tbody>
						<xsl:apply-templates mode="field-optioned">
							<xsl:with-param name="input-name" select="$input-name" />
							<xsl:with-param name="type" select="$type" />
						</xsl:apply-templates>
					</tbody>
					<tfoot>
						<tr>
							<td style="padding-left:0;">
								<select id="relationSelect{generate-id()}" umi:guide="{$guide-id}" umi:name="{$input-name}" class="relation-add"></select>
								<input type="text" id="relationInput{generate-id()}" />
								<input type="hidden"  id="relationButton{generate-id()}" />
							</td>
							<td class="center"><input type="text" umi:type="{$type}" /></td>
							<td class="center narrow">
								<a href="#" class="add"><img src="/images/cms/admin/mac/table/ico_add.gif" /></a>
							</td>
						</tr>
					</tfoot>
				</table>
				<div>
					<a href="{$lang-prefix}/admin/data/guide_items/{$guide-id}/"><xsl:text>&label-edit-guide-items;</xsl:text></a>
				</div>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template match="field/values/value" mode="field-optioned_cus">
		<xsl:param name="input-name" />
		<xsl:param name="type"><xsl:text>float</xsl:text></xsl:param>
		<xsl:variable name="position" select="position()" />
		<tr>
			<td>
				<span><xsl:value-of select="object/@name" /></span>
				<span><xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('uobject://', object/@id))/udata/object/properties/group[@name='kartinki']/property[@name='kartinka']/value, ')/50/auto'))" mode="optioned_pic"/></span>
				<input type="hidden" name="{$input-name}[{$position}][rel]" value="{object/@id}" />
			</td>
			<td class="center">
				<xsl:choose>
					<xsl:when test="$type = 'int'">
						<input type="text" umi:type="{$type}" name="{$input-name}[{$position}][{$type}]" value="{@int}" />
						<input type="hidden" umi:type="float" name="{$input-name}[{$position}][float]" value="1" />
					</xsl:when>
					<xsl:when test="$type = 'varchar'">
						<input type="text" umi:type="{$type}" name="{$input-name}[{$position}][{$type}]" value="{@varchar}" />
						<input type="hidden" umi:type="int" name="{$input-name}[{$position}][int]" value="1" />
					</xsl:when>
					<xsl:otherwise>
						<input type="text" umi:type="float" name="{$input-name}[{$position}][float]" value="{@float}" />
						<input type="hidden" umi:type="int" name="{$input-name}[{$position}][int]" value="1" />
					</xsl:otherwise>
				</xsl:choose>
			</td>
			<td class="center narrow">
				<a href="#" class="remove">
					<img src="/images/cms/admin/mac/table/ico_del.gif" />
				</a>
			</td>
		</tr>
	</xsl:template>
	
	<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']" mode="optioned_pic">
		<img src="{src}"/>
	</xsl:template>

	<xsl:include href="udata://core/importSkinXsl/form.modify.xsl"/>
</xsl:stylesheet>

2) Добавим в файл /classes/modules/custom.php следующий кастомный метод:

public function makeElement(){
	$name = urldecode($_POST['photo_name']);
	$name = htmlspecialchars($name);
	
	$guid = intval($_POST['guid']);
	$path = $_POST['photo_path'];

	$objectsCollection = umiObjectsCollection::getInstance();
	$id = $objectsCollection->addObject($name, $guid);
	if($id){
		$object = $objectsCollection->getObject($id);
		$object->setValue('kartinka', $path);
		$object->commit();
		return $id;
	}else{
		return 'Не удалось создать объект';
	}			
}

3) Теперь в карточке товара мы увидим следующее:

Custom adm option.png

Дополнительно

Также, есть и другие способы вывода нескольких картинок для товара: