UMIhelp

Разработка сайта на UMI.CMS => Шаблоны XSLT => Тема начата: Babajka от 20 Марта 2013, 11:48:29

Название: Position в выборке
Отправлено: Babajka от 20 Марта 2013, 11:48:29
Здравсвуйте. На сайте находится несколько меню.
Распределение их происходит с помощью выборки из content menu определенных пунктов меню с метками, в этом случае bottom_menu.
Мне необходимо первому тэгу li присвоить класс first.
Но он не присваевается.
Собственно код:

<xsl:apply-templates select="document('udata://content/menu/')/udata" mode="bottom_menu"/>
<xsl:template match="udata[@method = 'menu']" mode="bottom_menu">
<ul >
<xsl:apply-templates select="items/item" mode="bottom_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="bottom_menu">
<xsl:variable name="test" select="document(concat('upage://',@id, '.bottom_menu'))/udata/property/value" />
<xsl:if test="$test !=0">
<li>
<xsl:if test="position() = 1"><!-- тут и закрывается ошибка -->
<xsl:attribute name="class">first</xsl:attribute>
</xsl:if>
<a href="{@link}" >
<xsl:value-of select="." />
</a>
</li>
</xsl:if>
</xsl:template>

Собстенно, если заменить position()=1 на 6(т.к. это 6 пункт меню в админке). То все работает. Но это временная мера.
И сам вопрос: Как это сделать более красиво, что ли. Что бы, если в будущем добавлю еще пунктов меню, не расползлось все.
Название: Re:Position в выборке
Отправлено: Rodogor от 20 Марта 2013, 13:25:39
1. может быть заюзать css li:first-child ?
2. Так вроде всё достаточно красиво, причина не ясна.
Надо попробывать вывести position <xsl:value-of select="position()"/> и смотреть какие цифры, может =1 там не появляется. Такое может быть, если выше были ошибки с xslt
Название: Re:Position в выборке
Отправлено: admin от 20 Марта 2013, 17:26:07
class не присваивается, так как первый item, скорее всего, просто не прошел проверку
<xsl:if test="$test !=0">
, а остальные уже не первые...

Так что вижу тут 2 варианта

1. Добавляете информацию из поля bottom_menu в xml который возвращает макрос content menu и правильно формируете вызов при переборе item.
То есть вызов выглядит так:
<xsl:apply-templates select="document('udata://content/menu/?extProps=bottom_menu')/udata" mode="bottom_menu"/>

а шаблоны для вывода так:
<xsl:template match="udata[@method = 'menu']" mode="bottom_menu">
<ul >
<xsl:apply-templates select="items/item[not(//property[@name='bottom_menu']/value=0)]" mode="bottom_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="bottom_menu">
<li>
<xsl:if test="position() = 1"><!-- тут и закрывается ошибка -->
<xsl:attribute name="class">first</xsl:attribute>
</xsl:if>
<a href="{@link}" >
<xsl:value-of select="." />
</a>
</li>
</xsl:template>

Этот вариант, к тому же, немного сократить потребность в ресурсах, при выводе меню

2. Используете usel выборку вместо content menu макроса. И там прописываете условие, что вас интересуют страницы с отмеченной галочкой bottom_menu. Пример, создание альтернативного меню, используя usel описан в этой статье http://umihelp.ru/articles/usel-multilevel-menu/
Название: Re:Position в выборке
Отправлено: Babajka от 21 Марта 2013, 09:52:13
Воспользовался я первым вариантом. Но, результат оказался непредсказуемый. Класс first присвоился, но меню вывелось просто 6 первых меню. Т.е. даже не обращая внимания на флажок bottom_menu или top_menu.
Название: Re:Position в выборке
Отправлено: admin от 21 Марта 2013, 10:38:23
возможно, у меня в шаблоне есть неточности, писал сразу на форум без проверки синтаксиса. Так же, стоит проверить версию umi и работает ли у вас возможность получать extProps
Название: Re:Position в выборке
Отправлено: niakriss от 29 Марта 2013, 15:27:02
а нельзя просто 2 шаблона написать для 1го и для всех остальных?
На сколько я слышала, рекоммендуют лучше шаблонами обойтись, нежели операторами условия.

<xsl:template match="udata[@method = 'menu']" mode="bottom_menu">
<ul >
<xsl:apply-templates select="items/item[not(//property[@name='bottom_menu']/value=0)]" mode="bottom_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="bottom_menu">
<li>
<a href="{@link}" >
<xsl:value-of select="." />
</a>
</li>
</xsl:template>
<xsl:template match="item[1]" mode="bottom_menu">
<li class="fist">
<a href="{@link}" >
<xsl:value-of select="." />
</a>
</li>
</xsl:template>
Название: Re:Position в выборке
Отправлено: Babajka от 03 Апреля 2013, 14:44:22
niakriss
Попробовал ваш пример. Не вышло, выводит просто основное меню и ничего больше.
И еще вопрос
<xsl:apply-templates select="items/item[not(//property[@name='bottom_menu']/value=0)]" mode="bottom_menu" />
Чем нибудь отличается от
<xsl:apply-templates select="items/item[(//property[@name='bottom_menu']/value=1)]" mode="bottom_menu" />
?
Название: Re:Position в выборке
Отправлено: admin от 04 Апреля 2013, 07:35:14
перепроверил еще раз уже на рабочем варианте. вместо вашей галочки bottom_menu использовал галочку  robots_deny ("Запретить индексацию поисковиками"), то есть к двум из пунктам меню я добавил данную галочку и в итоге получал список из этих двух пунктов при том что position() возвращал в их случае 1 и 2 (то есть вопрос с выводом класса first тоже решался)

Привожу копию шаблонов

Вызов:
<xsl:apply-templates select="document('udata://content/menu/?extProps=robots_deny')" mode="new_menu" />

шаблоны меню:
<xsl:template match="udata[@method = 'menu']" mode="new_menu">
<ul umi:element-id="0" umi:module="content" umi:region="list" umi:sortable="sortable" umi:add-method="popup">
<xsl:apply-templates select="items/item[.//property[@name='robots_deny']/value=1]" mode="new_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="new_menu">
<li>
<a href="{@link}" umi:element-id="{@id}" umi:region="row" umi:field-name="name" umi:empty="&empty-section-name;" umi:delete="delete">
~<xsl:value-of select="position()" />~
<xsl:value-of select="text()" />
</a>
</li>
</xsl:template>


P.S. едиственное что поменялось в шаблоне, это синтаксис условия выборки item
items/item[.//property[@name='robots_deny']/value=1]
видимо в нем и была ошибка
Название: Re:Position в выборке
Отправлено: admin от 04 Апреля 2013, 07:42:58
niakriss
а нельзя просто 2 шаблона написать для 1го и для всех остальных?
На сколько я слышала, рекоммендуют лучше шаблонами обойтись, нежели операторами условия.

Можно и в большинстве случаев именно так я и делаю и рекомендую делать слушателям курсов, но <xsl:if /> все равно продолжаю использовать.Например, в ситуации, когда мне надо добавить класс в верстку в зависимости от позиции элемента в xml документе (особенно если их несколько, например класс для первого, для последнего, для четного). В этом случае удобнее делать это в одном шаблоне иначе сэкономив на быстроте выполнении той или иной организации шаблона, вы можете потерять в скорости обработки из-за возрастания количества шаблонов.
Название: Re:Position в выборке
Отправлено: Babajka от 05 Апреля 2013, 17:49:01
Если я ничего не "навертел" в коде
	<xsl:template match="udata[@method = 'menu']" mode="bottom_menu">
<ul umi:element-id="0" umi:module="content" umi:region="list" umi:sortable="sortable" umi:add-method="popup">
<xsl:apply-templates select="items/item[.//property[@name='bottom_menu']/value=1]" mode="bottom_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="bottom_menu">
<li>
<xsl:if test="position() = 1">
<xsl:attribute name="class">first</xsl:attribute>
</xsl:if>
<a href="{@link}" >
<xsl:value-of select="." />
</a>
</li>
</xsl:template>
то у меня непобедимый сайт. Все равно не выводит.
Название: Re:Position в выборке
Отправлено: admin от 05 Апреля 2013, 20:14:29
шаблон вроде верный, а вы проверяли срабатывает ли у вас параметр ?extProps. то есть пробовали посмотреть через <xsl:copy-of select="document('udata://content/menu/?extProps=robots_deny')" mode="new_menu" /> выводит ли система доп поля?
Название: Re:Position в выборке
Отправлено: Babajka от 08 Апреля 2013, 16:27:26
шаблон вроде верный, а вы проверяли срабатывает ли у вас параметр ?extProps. то есть пробовали посмотреть через <xsl:copy-of select="document('udata://content/menu/?extProps=robots_deny')" mode="new_menu" /> выводит ли система доп поля?
Все выяснил, версия не дотягивает.

Из размышлений
<xsl:apply-templates select="items/item[not(//property[@name='bottom_menu']/value=0)]" mode="bottom_menu" />
У bottom_menu нет значения 0. Если он вообще присутствует то value=1, при отсутствии самого property нет.
Название: Re:Position в выборке
Отправлено: e.ioffe от 08 Апреля 2013, 17:15:16
Можно и в большинстве случаев именно так я и делаю и рекомендую делать слушателям курсов, но <xsl:if /> все равно продолжаю использовать.Например, в ситуации, когда мне надо добавить класс в верстку в зависимости от позиции элемента в xml документе (особенно если их несколько, например класс для первого, для последнего, для четного). В этом случае удобнее делать это в одном шаблоне иначе сэкономив на быстроте выполнении той или иной организации шаблона, вы можете потерять в скорости обработки из-за возрастания количества шаблонов.

Вставлю свои 5 копеек :) If использую в редких случаях, когда, например, нужно проверить, есть ли в корзине товары, но при этом не хочется городить дополнительные template.

Обычно класс для элемента вставляю с помощью конструкции (если уверен, что класс будет в любом случае)

<li>
<xsl:attribute name="class"><xsl:apply-templates select="." mode="additional-class" /></xsl:attribute>
</li>

<xsl:template macth="item[first()]" mode="additional-class">first</xsl:template>

<xsl:template macth="item[last()]" mode="additional-class">last</xsl:template>

Или, если в некоторых случаях класс не нужен, то:

<li>
<xsl:apply-templates select="." mode="additional-class" />
</li>

<xsl:template macth="item" mode="additional-class" />

<xsl:template macth="item[first()]" mode="additional-class">
<xsl:attribute name="class">first</xsl:attribute>
</xsl:template>
Название: Re:Position в выборке
Отправлено: Babajka от 21 Мая 2013, 12:12:38
e.ioffe
Ничего более здравого не придумал, в прменении твоего примера. Хотя сам понимаю, что код бредовый.
Кто нибудь может подсказать, что именно не так и как сделать чтобы было так?
 	<xsl:template match="udata[@method = 'menu']" mode="bottom_menu">
<ul >
<xsl:apply-templates select="items/item" mode="bottom_menu" />
</ul>
</xsl:template>

<xsl:template match="item" mode="bottom_menu">
<xsl:variable name="test" select="document(concat('upage://',@id, '.bottom_menu'))/udata/property/value" />
<xsl:if test="$test !=0">
<xsl:apply-templates select="." mode="additional-class" />
</xsl:if>
</xsl:template>

<xsl:template macth="item" mode="additional-class" >
<li>
<a href="{@link}" ><xsl:value-of select="." /></a>
</li>
</xsl:template>

<xsl:template macth="item[first()]" mode="additional-class">
<li>
<xsl:attribute name="class">first</xsl:attribute>
<a href="{@link}" ><xsl:value-of select="." /></a>
</li>
</xsl:template>
Название: Re:Position в выборке
Отправлено: admin от 21 Мая 2013, 12:23:35
может уже ну его, через макрос menu, может через usel попробовать? там при выборке сразу можно будет поставить проверку на это поле bottom_menu

P.S. Кстати, этот то вариант работает?
Название: Re:Position в выборке
Отправлено: e.ioffe от 21 Мая 2013, 14:49:26
может уже ну его, через макрос menu, может через usel попробовать? там при выборке сразу можно будет поставить проверку на это поле bottom_menu

P.S. Кстати, этот то вариант работает?

Не сторонник использовать usel там, где можно обойтись стандартными udata :)

Именно для этого случая я бы использовал следующий код:

<xsl:apply-templates select="document('udata://content/menu/?extProps=bottom_menu')/udata" mode="bottom_menu" />

<xsl:template match="udata[@method = 'menu']" mode="bottom_menu" />

<xsl:template match="udata[@method = 'menu'][items/item]" mode="bottom_menu">
<ul>
<xsl:apply-templates select="items/item" mode="bottom_menu" />
</u>
</xsl:template>

<xsl:template match="item" mode="bottom_menu" />

<xsl:template match="item[extended//property[@name = 'bottom_menu']/value]" mode="bottom_menu">
<li>
<xsl:apply-templates select="." mode="additional-class" />
<a href="{@link}" ><xsl:value-of select="." /></a>
</li>
</xsl:template>

<xsl:template match="item" mode="additional-class" />

<xsl:template match="item[first()]" mode="additional-class">
<xsl:attribute name="class">first</xsl:attribute>
</xsl:template>

Во-первых, при вызове content/menu указываем, что нам нужно дополнительно получить параметр bottom_menu. Затем фильтруем в зависимости от того, есть ли у элемента этот параметр или нет.

Если есть - показываем элемент и дальше определяем, какой у него должен быть класс. Если не первый, то класс не добавляем. Если первый, то добавляем.

Как-то так :)
Название: Re:Position в выборке
Отправлено: e.ioffe от 21 Мая 2013, 14:50:41
Да, забыл дописать проверку, есть ли вообще в выборке элементы интересные нам. Вместо

<xsl:template match="udata[@method = 'menu'][items/item]" mode="bottom_menu">

нужно указать

<xsl:template match="udata[@method = 'menu'][items/item[extended//property[@name = 'bottom_menu']/value]]" mode="bottom_menu">
Название: Re:Position в выборке
Отправлено: Babajka от 21 Мая 2013, 17:22:25
e.ioffe
У меня не держит extProps. Так что не подходит.

admin
Через usel она изначально была сделана, пытался отойти от этого. Но судя по всему придется обратно вернуться.
Но за варианты еще буду благодарен. )
Название: Re:Position в выборке
Отправлено: e.ioffe от 21 Мая 2013, 17:55:46
Жаль. А можно адрес сайта в личку? Может, что-то еще в голову придет.
Название: Re:Position в выборке
Отправлено: admin от 22 Мая 2013, 09:37:29
Не сторонник использовать usel там, где можно обойтись стандартными udata :)

Именно для этого случая я бы использовал следующий код:

уже пробовали этот вариант смотрите сообщения выше, версия не позволяет.
Название: Re:Position в выборке
Отправлено: e.ioffe от 22 Мая 2013, 12:51:53
уже пробовали этот вариант смотрите сообщения выше, версия не позволяет.

Ага, видел.

Тогда попробуйте так:

<xsl:template match="item" mode="bottom_menu">
<xsl:apply-templates select="document(concat('upage://', @id, '.bottom_menu'))//value" mode="select_bottom_menu">
<xsl:with-param name="item" select="." />
</xsl:apply-templates>
</xsl:template>

<xsl:template match="value" mode="select_bottom_menu">
<xsl:param name="item" />

<li>
<xsl:if test="first()"><xsl:attribute name="class">first</xsl:attribute></xsl:if>
<a href="{$item/@link}"><xsl:value-of select="$item" /></a>
</li>
</xsl:template>

Основная мысль:
если мы проверяем item используя <xsl:if test="$test !=0">, то в дальнейшем мы не можем проверить position, так как он будет равен position данного item в items без учета if-a.

Грубо говоря:
1-й элемент - не подходит
2-й элемент - не подходит
3-й элемент - подходит, однако его position для шаблона будет 3, а не 1.

Мне кажется, что если использовать <xsl:apply-templates select="document(concat('upage://', @id, '.bottom_menu'))//value" mode="select_bottom_menu">
      <xsl:with-param name="item" select="." />
   </xsl:apply-templates>
, то position будет рассчитываться только для тех элементов, у которых есть value (остальные отбрасываются на уровне условия).

Возможно, что это не так - под рукой нет тестовой базы, не могу проверить.
Название: Re:Position в выборке
Отправлено: Babajka от 22 Мая 2013, 14:31:26
e.ioffe
Именно на этот пример, он выругался на "umiTemplaterXSLT.php on line 50". И не выдал мне меню. Вот.
Но для моего понимания код оказался, как то замудрен, по этому мыслей по его "доработке" не нашел.
Название: Re:Position в выборке
Отправлено: admin от 22 Мая 2013, 15:14:32
в общем в итоге у нас рабочий вариант с usel (если я правильно понял Babajka), Вариант с extProps (очень хороший но версия umi не позволяет им воспользоваться) и пляски с xslt чтобы делая доп запросы через upage выводить нужный нам список.

Может, разумнее уже написать свой экономичный кастом, который будет выводить то что надо)