Несколько изображений к товару средствами дополнительных полей — различия между версиями
Mad grant (обсуждение | вклад) |
Mad grant (обсуждение | вклад) |
||
(не показаны 22 промежуточные версии этого же участника) | |||
Строка 18: | Строка 18: | ||
[[Файл:Fields_simple_page.png]] | [[Файл: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) Создадим в типе данных, к которому относится товар, столько полей типа изображение, сколько будет изображений у товара:
2) Создадим товар с этим типом данных и заполним созданные поля в карточке товара:
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) Создадим в типе данных, к которому относится товар составное поле и справочник к нему:
2) Создадим в типе данных этого справочника поле типа изображение:
3) Заполним справочник элементами:
4) Выберем на странице товара эти элементы:
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) Теперь в карточке товара мы увидим следующее:
Дополнительно
Также, есть и другие способы вывода нескольких картинок для товара: