четверг, 5 ноября 2015 г.

Seample Search - простой поиск на modx revo

Спонсор блога Магазин детской одежды Dress

Официальная документация

1. Создаем новый ресурс в корне дерева. Заголовок: Результаты поиска, ставим галочку "Не показывать в меню". Нажимаем на вкладку "Настройки" и убираем галочки с "Доступен для поиска", "Использовать HTML-редактор". Не забываем сохранить ресурс.

2. Далее заходим в новосозданный ресурс и в поле "Содержимое ресурса" вписываем
[[!SimpleSearch]]

3. Запоминаем id этого ресурса, это страница вывода результатов поиска. В шаблон где находится сама форма поиска вставляем следующий код:

[[!SimpleSearchForm? &landing=`1` &tpl=`search`]]
где вместо 1 вставляем ID страницы вывода результатов поиска

4. Затем копируем следующий код (это содержимое файла core/components/simplesearch/elements/chunks/searchform.chunk.tpl):
в новый чанк с названием search и создаем тот шаблон отображения окна поиска, который нам необходим.

<form action="[[~[[+landing]]]]" method="[[+method]]">
              <input type="text" name="[[+searchIndex]]" id="[[+searchIndex]]" value="[[+searchValue]]" placeholder="Поиск по сайту">
 <input type="hidden" name="id" value="[[+landing]]" />
              <button type="submit"></button>
            </form>

FormIt - отправка форм в modx revo

Спонсор блога Магазин детской одежды Dress

очень мощный плагин для работы с формами
Официальная документация 

Пример вызова:

[[!FormIt@custom?
&hooks=`email,redirect`
&submitVar=`FeedbackMes`
&emailTpl=`FeedbackMes`
&emailSubject=`Обратная связь`
&redirectTo=`48`
]]


<form id="callBackMes" action="[[~[[*id]]]]" method="post">
  <input type="hidden" name="FeedbackMes" value="1">
            <div class="bInputWrap">
              <input type="text" name="feedbackFio" placeholder="ФИО" required value="[[!+fi.feedbackFio]]" class="bTextInputFeedback height50">
 <input type="text" name="feedbackPhone" placeholder="Телефон" required value="[[!+fi.feedbackPhone]]" class="bTextInputFeedback height50">
 <input type="text" name="feedbackEmail" placeholder="E-mail" required value="[[!+fi.feedbackEmail]]" class="bTextInputFeedback height50">
 <textarea class="bTextInputFeedback height150" name="feedbackMessage" placeholder="Сообщение"></textarea>
            </div>
            <button type="submit" class="bBtn">Отправить</button>
          </form>

Код чанка FeedbackMes (отвечает за формат письма) E-mail внес в настройки
 
 <h3>Сообщение с сайта ***. Форма обратной связи</h3>
<p>ФИО: [[+feedbackFio]]</p>
<p>Телефон: [[+feedbackPhone]]</p>
<p>E-mail: [[+feedbackEmail]]</p>
<p>Сообщение: [[+feedbackMessage]]</p>


Quip - простая система комментирования в modx revo

Спонсор блога Магазин детской одежды Dress

Официальная документация 
Пример вызова:

<div id="comment">
          <h3>Отзывы</h3>
  [[!QuipReply?
&thread=`item_comment[[*id]]`
&requireAuth=`1`
&tplAddComment=`new-comment`
&moderate=`1`]]
<ul class="commentlist">
[[!Quip? &thread=`item_comment[[*id]]` &threading=`0` &tplComment=`comment`]]
        </ul>

,где QuipReply - выводит форму добавления комментария
Quip - вывод комментарий

Пример чанка new-comment:

<div id="commentform">
     <span class="quip-success" id="quip-success-[[+idprefix]]">[[+successMsg]]</span>
    <form id="quip-add-comment-[[+idprefix]]" action="[[+url]]#quip-comment-preview-box-      [[+idprefix]]" method="post">
<div class="input fl">
        <input type="text" name="name" id="quip-comment-name-[[+idprefix]]" value="[[+name]]" placeholder="Ваше имя"/>
</div>
<div class="input fl">
<input type="email" placeholder="Эл. почта" name="email" id="quip-comment-email-[[+idprefix]]" value="[[+email]]">
</div>

<textarea name="comment" id="commenttext" placeholder="Комментарий"></textarea>
        <button type="submit" name="[[+post_action]]" value="1">Написать</button>
<input type="hidden" name="nospam" value="" />
    <input type="hidden" name="thread" value="[[+thread]]" />
    <input type="hidden" name="parent" value="[[+parent]]" />
    <input type="hidden" name="auth_nonce" value="[[+auth_nonce]]" />
    <input type="hidden" name="preview_mode" value="[[+preview_mode]]" />
</form>

</div>

Важно! submit формы должен иметь имя  и значение name="[[+post_action]]" value="1"

Пример чанка comment:

<li class="comment">
        <div class="author">
           <div class="authorname">[[+name]]</div>

</div>
<div class="commenttext">
[[+body]]
</div>

</li>

AjaxForm - Отправка форм через ajax


Спонсор блога Магазин детской одежды Dress


Cниппет для отправки любых форм через ajax. По умолчанию рассчитан на работу с FormIt, но можно использовать и собственный сниппет.

1. Создаем чанк "callBack" (ну или любой другой, по смыслу)
2. Добавляем форму в чанк
3. вызываем сниппет [[!AjaxForm?form=`myForm`&snippet=`FormIt`]]

Параметры сниппета:

&form - чанк с формой ( по умолчанию - tpl.AjaxForm.example)
&snippet - сниппет для обработки формы (FormIt)
&frontend_css - Стили оформления формы и полей с ошибками ([[+assetsUrl]]css/default.css)
&frontend_js - Javascript для отправки формы через ajax ([[+assetsUrl]]js/default.js)
&actionUrl - Адрес коннектора, на который отправляется форма ([[+assetsUrl]]action.php)

Пример вызова сниппета:

[[!AjaxForm?form=`callBack`
&snippet=`FormIt` 
&hooks=`email` 
&emailTo=`myemail@gmail.com`
&submitVar=`callBackMes`
&emailTpl=`callBackMes`
&emailSubject=`Обратный звонок с сайта xiaomi-mi.ru`
&validate=`name:required,phone:required`
&validationErrorMessage=`Пожалуйста, заполните поля корректно`
&successMessage=`Ваше сообщение отправлено, в ближайшее время мы свяжемся с Вами`
]]

Пример чанка callBack:

<div class="popup" id="call">
<div class="close_order popup_close"></div>
<form id="callback_form" action="" method="post" class="ajax_form">
<input type="hidden" name="callBackMes" value="1">
<div class="input">
<input type="text" id="af_name" name="name" value="[[+fi.name]]" placeholder="Ваше Имя" required>
<span class="error_name">[[+fi.error.name]]</span>
</div>
<div class="input">
<input type="tel" id="af_phone" name="phone" value="[[+fi.phone]]" placeholder="Ваш Телефон">
<span class="error_phone">[[+fi.error.phone]]</span>
</div>
<input type="submit" value="Отправить">
[[+fi.success:is=`1`:then=`
<div class="alert alert-success">[[+fi.successMessage]]</div>
`]]
[[+fi.validation_error:is=`1`:then=`
<div class="alert alert-danger">[[+fi.validation_error_message]]</div>
`]]
</form>
</div>

Пример чанка callBackMes (отвечает за формат письма) E-mail

<h3>Сообщение с сайта xiaomi-mi.ru Форма обратного звонка</h3>
<p>Имя: [[+name]]</p>

<p>Телефон: [[+phone]]</p>

Если необходимо после отправки формы скрыть всплывающее окно:

$(document).on('af_complete', function(event, response) {
var form = response.form;
// Если у формы определённый id
if (form.attr('id') == 'callback_form') {
$('#call .close_order').click(); // кнопка закрытия всплывающего окна
}

});

PS при работе с этим сниппетом ajaxForm столкнулся с проблемой,что письмо не приходит на email, хотя выскакивает оповещение, что сообщение отправлено. А причина была вот в чем: в файле документации 
\core\components\ajaxform\docs\readme.txt
Ошибка в вызове сниппета:

You can specify any parameters for end snippet:
[[!AjaxForm?
&form=`myForm`
&snippet=`FormIt`
&hooks=`email`
&emailto=`info@mysite.com`
&etc=`...`

]]

строка &emailto=`info@mysite.com` регистрозависима. Нужно 
&emailTo=`info@mysite.com` тогда все работает как нужно.







Документация на сайте разработчика

пятница, 30 октября 2015 г.

modx revo api

Спонсор блога Магазин детской одежды Dress

Пример выборки страниц:

$c = $modx->newQuery('modResource');
 $c->where(array(
'parent:IN' => array($pageId),
'deleted' => false,
'published' => true,
  ));
  $c->limit(30);
  $resources = $modx->getCollection('modResource',$c);

  $variantPageArray = array();
  foreach ($resources as $k => $res) {
  $tempArr = array();
$tempArr['pagetitle'] = $res->get('pagetitle');
$tempArr['page_id'] = $res->get('id');
$tempArr['price'] = $res->getTVValue('price');
$tempArr['color'] = trim((string)$res->getTVValue('color'));
$tempArr['memory'] = trim((string)$res->getTVValue('memory'));
$tempArr['image'] = $res->getTVValue('image');
$variantPageArray[]=$tempArr;
  }

Выборка страниц по ид шаблона

$pages = $modx->getCollection('modResource', array('template' =>5));

Пример установки tv параметра

$pages = $modx->getCollection('modResource', array('template' => 5));
$count_item = 0;
foreach ($pages as $page)
{
$price_dollar = $page->getTVValue('price_dollar');
$old_price_dollar = $page->getTVValue('old_price_dollar');
if(!empty($price_dollar) && (float)$price_dollar>0)
{
$page->setTVValue('price', round($price_dollar*$kurs));
}
if(!empty($old_price_dollar) && (float)$old_price_dollar>0)
{
$page->setTVValue('old_price', round($old_price_dollar*$kurs));
}
$count_item++;

}

Выполнение другого сниппета

$output = $modx->runSnippet('Welcome',array(
   'name' => 'John'
));
echo $output; // prints 'Welcome John!'


вторник, 27 октября 2015 г.

Shopkeeper 3.0 - создание интернет магазина на modx revo


Спонсор блога Магазин детской одежды Dress

Столкнулся с такой проблемой: при добавлении товара в корзину через ajax js нормально отрабатывает, товар якобы добавляется визуально, никаких ошибок в консоле, сервер отдает ответ... НО! стоит перегрузить страницу, товара в корзине нет!!! Бился с этим пару часов. В докумментации нет на эту тему ничего! Нашел ток ответ в "Часто задаваемых вопросах". После этого ток проблема рассосалась.

Почему не сохраняются товары в корзине?

Если при нажатии на кнопку "В корзину" товары не попадают в корзину или попадают через раз, надо открыть "Настройки системы" и очистить (сделать пустым) значение параметры "session_handler_class" (Имя класса-обработчика сессий) в разделе "Сессии и куки". Это включит стандартное поведение для сессий PHP.

Со следующими проблемами пока что не сталкивался, но лучше продублирую их здесь:

2. На странице оформления заказа выводится только сокращенная корзина в шапке сайта. Как вывести подробную корзину в центре страницы?

Сниппет можно вызывать на странице несколько раз, но корзина выводится только в месте первого вызова. Второй и последующие вызовы игнорируются. Если у Вас корзина на страницах каталога товаров находится в правой колонке шаблона, а на странице оформления заказа вызов сниппета вставлен в контент страницы, то на этой странице корзина будет выведена только в ценральной колонке (в правой вызов сниппета можно не убирать). Если есть вызов сниппета Shopkeeper в шапке сайта и в центральной части, то корзина будет выводиться только в шапке.
Чтобы убрать сокращенную корзину на странице оформления заказа, используйте параметр hideOn (указать ID страницы оформления заказа, можно несколько через запятую). Тогда вызов сниппета сокращенной корзины будт проигнорирован и будет выводиться подробный вид корзины (второй вызов сниппета).

4. После обновления через аякс списка товаров или корзины не работает вызов сниппета в чанке.

Нужно убрать "!" в вызове сниппета, если он вызывается в чанке getProducts.
Вместо [[!mySnippet?... будет [[mySnippet?...
============================================

Shopkeeper 3.x

http://modx-shopkeeper.ru/


Параметры:

lang - язык. По умолчанию - ru.

prodCont - CSS-селектор элемента, внутри которого находится информация о товаре (по умолчанию `div.shk-item`);

cartTpl - Чанк корзины (в нём содержатся две части: пстая корзина и корзина с товарами). По умолчанию - shopCart.

cartRowTpl - Чанк строки товара в корзине. По умолчанию - shopCartRow.

packageName - Имя пакета таблицы БД товаровe: "shop". По умолчанию пусто (modResource).

className - Имя класса таблицы БД товаров. Пример: "ShopContent". По умолчанию пусто (modResource).

fieldPrice - Имя поля или TV с ценой товара. По умолчанию - price.

fieldName - Имя поля или TV с названием товара. По умолчанию - pagetitle.

getUnpublished - Разрешить добавлять в корзину неопубликованные товары. По умолчанию - false.

allowFloatCount - Разрешить числа с плавающей точкой для кол-ва товара. По умолчанию - false.

excepDigitGroup - Делать разрядность больших чисев в ценах.

orderFormPageId - ID страницы оформления заказа.

currency - Валюта. По умолчанию - руб.

processParams - Просчитывать дополнительные параметры перед добавлением товара в корзину.

savePurchasesFields - Список полей (или имен TV) товаров, которые нужно выводить в корзине и сохранять при заказе (через запятую).

orderDataRowTpl - чанк строки товара в списке в письме, которое отправляется при заказе ([[+orderOutputData]]). По умолчанию orderDataRow.

flyToCart - Эффект добавления товара в корзину - helper | image | nofly (по умолчанию `helper`);

noJavaScript - Работать без JavaScript (по умолчанию `0`);

noJQuery - Не подгружать jquery.js (по умолчанию `0`);

style - Стиль корзины (по умолчанию `default`);

pluralWords - Слова через запятую, которые нужно склонять по количеству. По умолчанию слова берутся из языкового файла (товар,товара,товаров).

groupBy - Название поля, по которому нужно группировать товары в корзине. Пример: &groupBy=`parent`

Пример использования:

[[!Shopkeeper3@cart_catalog]]

cart_catalog - Имя набора параметров.

Рекомендуется все параметры указывать в наборе параметров, т.к. нужно синхронизировать эти параметры при аякс-запросе.

Можно выводить две и более корзины на одной странице.

Пример чанка корзины товаров:

<div class="shop-cart" data-shopcart="1">
    <div class="shop-cart-head"><b>Корзина</b></div>
    <div class="empty">
        <div class="shop-cart-empty">Пусто</div>
    </div>
</div>
<!--tpl_separator-->
<div class="shop-cart" data-shopcart="1">
    <div class="shop-cart-head"><b>Корзина</b></div>
    <div class="full">
        <div  style="text-align:right;">
            <a href="[[+empty_url]]" id="shk_butEmptyCart">Очистить корзину</a>
        </div>
        <div class="shop-cart-body">Выбрано: <b>[[+items_total]]</b> [[+plural]]</div>
        <div style="text-align:right;">Общая сумма: <b>[[+price_total]]</b> [[+currency]]
        </div>
        <div class="cart-order">
            <a href="[[+order_page_url]]" id="shk_butOrder">Оформить заказ</a>
        </div>
    </div>
</div>

Чанк состоит из двух частей, разделенных специальным разделителем <!--tpl_separator-->

Первая часть - чанк пустой корзины товаров.
Вторая часть - чанк корзины с товарами.

data-shopcart="1" - это метка, по которой определяется набор параметров при аякс-обновлении корзины.

В настройках системы (Настройки системы -> shopkeeper3) в параметре "shk3.property_sets" нужно указать имена наборов параметров (можно несколько через запятую), которые используются на вашем сайте для сниппета Shopkeeper. Это нужно для синхронизации при аякс-обновлении корзины.

Например shk3.property_sets = cart_catalog,cart_order_page

В этом случае в чанке (cartTpl), который указан в  наборе параметров "cart_catalog" нужно поставить метку data-shopcart="1".

А в чанке , который указан в наборе параметров "cart_order_page" поставить метку data-shopcart="2" (порядковый номер набора параметров).

--------------------------------------------

Параметры в настройках системы

В админке перейти "Настройки системы" -> "shopkeeper3" (фильтр).

shk3.property_sets - Список используемых наборов параметров сниппета Shopkeeper3. Подробнее в разделе "Пример чанка корзины товаров". По умолчанию "cart_catalog,cart_order_page".

shk3.currency - Название основной валюты сайта. По умолчанию "руб.".

shk3.currency_default - Номер валюты в списке по умолчанию. Подробнее в разделе "Мультивалютность". По умолчанию "1".

shk3.mail_order_data_tpl - Чанк шаблона данных заказа (для письма заказа). По умолчанию "orderDataOuter".

shk3.mail_order_data_row_tpl - Чанк шаблона одного товара в письме заказа. По умолчанию "orderDataRow".

shk3.mail_contacts_row_tpl - Чанк шаблона строки контактных данных в письме заказа. По умолчанию "mailContactsRow".

shk3.first_status - Номер первого статуса заказа от еденицы. Этот статус присваивается при создании заказа. По умолчанию "1" (Новый).

--------------------------------------------

Плейсхолдеры, доступные в чанке  "cartTpl":

[[+inner]] - список товаров (по шаблону cartRowTpl);
[[+price_total]] - общая цена товаров в корзине;
[[+items_total]] - общее число товаров в корзине;
[[+items_unique_total]] - общее число уникальных товаров в корзине;
[[+plural]] - слово "товар" во множественном числе в зависимости от числа выбранных товаров;
[[+this_page_url]] - адрес текущей страницы;
[[+empty_url]] - ссылка для очистки корзины;
[[+order_page_url]] - ссылка на страницу оформления заказа;
[[+currency]] - валюта товаров;
[[+delivery_name]] - Название выбранной доставки.
[[+delivery_price]] - Цена выбранной доставки.

Плейсхолдеры, доступные в чанке "cartRowTpl":

[[+name]] - название товара;
[[+id]] - ID товара;
[[+url]] - ссылка на страницу товара;
[[+price]] - цена товара;
[[+price_total]] - общая цена товара, включая доп. параметры;
[[+price_count]] - цена товара, умнженная на кол-во;
[[+price_count_total]] - общая цена товара с параметрами, умноженная на кол-во;
[[+currency]] - валюта товара;
[[+count]] - количество товара;
[[+index]] - порядковый номер товара в корзине от нуля;
[[+num]] - порядковый номер товара в корзине от единицы;
[[+even]] - четный или нечетный товар (выводит 1 или 0);
[[+comma]] - запятая (выводится между товарами);
[[+url_del_item]] - ссылка на удаление товара из корзины;
[[+addit_data]] - дополнительные параметры товара;
[[+любой TV]] - любой TV-параметр, например [[+image]];

Лично у меня не вышло так вытянуть картинку в мини корзине. Пришлось это делать вот так:
<img src="[[pdoField? &id=`[[+id]]` &field=`image` &processTV=`1`]]">
При чем, если делать ресайз через сниппет
[[phpthumbof? &input=`[[pdoField? &id=`[[+id]]` &field=`image` &processTV=`1`]]` &options=`&w=56&h=56`]]
, то обновление корзины при ajax добавлении товара вообще подвисает.

[[+shk_любой TV]] - любой доп. параметр, выбранный при добавлении товара в корзину (из [[+addit_data]]), например [[+shk_param1]].

    Если параметры сделаны в виде чекбоксов, то чтобы вывести отдельно каждый из них, нужно добавлять индекс (номер от нуля) для параметров следующих за первым. Пример: [[+shk_param1]], [[+shk_param1_1]], [[+shk_param1_2]] ...

--------------------------------------

События для плагинов:

OnSHKaddProduct - Добавление товара в корзину. $purchaseArray
OnSHKAfterAddProduct - После добавления товара в корзину. $purchaseArray, $index, $id
OnSHKgetProductPrice - Выбор цены товара при добавлении в корзину. $price, $id, $purchaseArray
OnSHKgetDeliveryPrice - Выбор цены досавки. $price
OnSHKgetProductAdditParamPrice - Выбор цены доп. параметра товара при добавлении в корзину. $price, $id
OnSHKcalcTotalPrice - Рассчет полной цены товаров в корзине. $price_total, $purchases
OnSHKbeforeCartLoad - Вызывается до начала формирования HTML-кода корзины.
OnSHKcartLoad - Вывод корзины. $items_total, $price_total
OnSHKChangeStatus - Изменение статуса заказа. Доступны: $order_ids, $status.
OnSHKsaveOrder - Отправка заказа. $order_id
OnSHKAfterRemoveProduct - После удаления товара из корзины. $index, $id
OnSHKAfterClearCart - После очистки корзины (удаления всех товаров).

============================================

Виджет

Для добавления виджета "Статистика заказов" на панель перейти
"Панели" -> "Панели" -> "Default" -> "Редактировать" -> "Добавить виджет" -> "Статистика заказов".
Перетащить в списке виджет вверх.

============================================

Плагин "shk_updateInventory" - Учет товара на складе

Плагин меняет число (значение поля или TV) кол-ва товара на складе, при переводе заказа в нужный статус.
По умолчанию плагин отключен, нужно его включить и настроить параметры:

inventory_fieldname - Имя поля или TV, где записано число товара на складе. По умолчанию - inventory.
plugin_status - номер статуса (от 1) при котором нужно уменьшать число товаров на складе. По умолчанию - 2.
context - имя контекста, кэш которого нужно очистить после пересчета товара на складе.

============================================

Автоматические псевдонимы для MIGXDB

Создать плагин на событие "OnDocFormSave" с кодом из файла:
"/core/components/shopkeeper3/elements/plugins/migx_autoalias.php"

Открыть файл "/core/components/migx/processors/mgr/default/update.php" и сразу после "$object->save()"
точнее в актуальной версии версии это после

if ($object->save() == false) {
    $updateerror = true;
    $errormsg = $modx->lexicon('quip.thread_err_save');
    return;
}

Добавить вызов плагина так:

$modx->invokeEvent( 'OnDocFormSave', array( 'id' => $object->get('id'), 'resource' => &$object ) );

============================================

Сниппет shkOptions

Сниппет для вывода конфигурации Shopkeeper. Например можно выводить список способов доставки и оплаты.

Параметры:

get - Названия параметров, которые нужно достать из БД. Можно несколько через запятую.
post_name  - Названия полей в форме. Например вывод при оформлении заказа. Нужно для работы плейсхолдера [[+selected]] - выбранное значение.
tpl - Названия чанка для одной строки параметра.
toPlaceholders - отправить вывод в плейсхолдеры (разделенные по названию параметров). По умолчанию 0 (выкл.).
pl_prefix - Префикс названия плейсхолдера. По умолчанию: shkopt_.

Пример чанка (tpl):
<option value="[[+value]]" [[+selected]]>[[+label]]</option>

Пример использования:

[[!shkOptions?
&get=`delivery,payments`
&post_name=`shk_delivery,payment`
&toPlaceholders=`1`
&pl_prefix=`shkopt_`
&tpl=`select_option`
]]

Способ доставки:
<select name="shk_delivery">
    <option value=""></option>
    [[!+shkopt_delivery]]
</select>

Способ оплаты:
<select name="payment">
    <option value=""></option>
    [[!+shkopt_payments]]
</select>

Для динамического обновления цены доставки в корзине можно использовать такой скрипт:

<script type="text/javascript">
$(document).bind('ready',function(){
    if ( SHK.data.delivery_name ) {
        $('select[name="shk_delivery"]','#shopOrderForm').val( SHK.data.delivery_name );
    }
    $('select[name="shk_delivery"]','#shopOrderForm').bind('change',function(){
        SHK.selectDelivery( $(this).val() );
    });
});
</script>

============================================

Мультивалютность

Для мультивалютности используется плагин "shk_multicurrency". Проверьте чтобы он был активирован (по умолчанию выключен).

В настройках системы используются параметры:
shk3.currency - название валюты по умолчанию.
shk3.currency_default - номер валюты в списке по умолчанию.

Курсы вылют задаются в конфигурации компонента Shopkeeper3. "Управление заказами" -> "Настройки" -> "Курсы валют".

Если все цены интернет-магазина заданы в долларах (USD), в параметре "shk3.currency_default" нужно указать значение "3" (без кавычек),
если в списке валют USD под номером 3.

В шаблоне в нужном месте разместить выпадающий список с выбором валют:

<select id="site_currency" name="curency">
    <option value="1">руб.</option>
    <option value="2">грн.</option>
    <option value="3">USD</option>
    <option value="4">euro</option>
</select>

Также список валют можно выводить с помощью сниппета "shkOptions".

При выборе валюты все цены будут пересчитаны по соответствующему курсу.

Для пересчета цены в шаблоне страницы товара использовать модификатор "shk_curr_rate":

[[!*price:shk_curr_rate]] [[!+shk_currency]]

shk_currency - плейсхолдер наименования валюты.

Пример вывода цены в чанке сниппета getProducts при выводе списка товаров:

[[+tv.price:shk_curr_rate]] [[+shk_currency]]

-------------------------------

Если на сайте только одна валюта, но цены товаров указаны в другой валюте,
нужно добавить в настройках системы параметр "shk3.currency_selected" (Пространство имен "shopkeeper3") со значением - номер валюты (от еденицы),
в которую нужно переводить.
Например, если у товаров указана цена в долларах, а нужно выводить в рублях:
shk3.currency_default = 3 (USD)
shk3.currency_selected = 1 (руб.)
3 - номер валюты USD в списке курсов валют.

============================================

Дополнительные параметры товаров:

Товарам можно назначать параметры, которые покупатель сможет выбрать перед добавлением товара в корзину.
Параметры выводятся в виде выпадающего списка - shk_select, радио кнопок - shk_radio или флажков (чекбоксов) - shk_checkbox.
Выбрать тип вывода можно в настройках TV-параметра на вкладке "Параметры вывода".

Значения параметров (на странице редактирования ресурса (товара)) вводятся по такому принципу:
название параметра 1==цена 1||название параметра 2==цена 2||...

Можно ввести цену параметра со знаком умножения: Вес==*0.5||Вес==*1
В этом случае цена товара будет умножена на цену параметра.

В чанке сниппета getResources или getProducts параметры выводятся как плейсхолдеры: [[+tv.param1]].

На странице товара (в шаблоне товара) нужно изменить ID параметра. Сделать это можно с помощью фильтра replace:
[[*param1:replace=`[[+id]]==[[*id]]`]]

Контроллер параметров вывода: core/model/modx/processors/element/tv/renders/mgr/properties/
Параметры вывода: manager/templates/default/element/tv/renders/properties/
Контроллеры вывода: core/model/modx/processors/element/tv/renders/web/output/

============================================

Две и более цены для одного товара

Для этого нужно создать две или более формы (<form>) и в поле name=«shk-id» после ID написать имя TV с ценой.

Пример:

<input type="hidden" name="shk-id" value="[[*id]]__price2" />

При submit формы в корзину добавится цена из TV-параметра (или поля) с именем «price2».

============================================

Добавление в корзину данных без создания TV-параметров

Пример:

<input type="text" name="test__[[*id]]__add" value="дополнительные данные" />

В корзину добавится параметр, который можно выводить в месте вставки плейсхолдера [[+shk_test]] (выведется «дополнительные данные»).

============================================

Сниппет "shk_sitemap" - создание sitemap.xml

Автор - slaad

1. Создать документ с именем и псевдонимом "sitemap".

2. Установить пустой шаблон и отметить флажки "Публиковать" и "Не показывать в меню".
   Тип содержимого - XML.

3. В поле "Содержимое ресурса" вставить вызов сниппета.

Параметры сниппета:

packageNames - Имя пакета объектов которые нужно вывдить (можно несколько через запятую).
classNames - Имя класса объектов которые нужно вывдить (можно несколько через запятую).
contexts - Контекст, в котором находятся объекты (можно несколько через запятую). Внимаение! Нужно сохранять порядок контекстов и классов, если их несколько, см. пример ниже.

Примеры:

1. Только ресурсы (Один или больше контекстов):

[[shk_sitemap?
&packageNames=`modResource`
&classNames=`modResource`
]]

2. Ресурсы и товары из отдельной таблицы, два контекста:

[[shk_sitemap?
&packageNames=`modResource,shop`
&classNames=`modResource,ShopContent`
&contexts=`web,catalog`
]]

В данном случае родители товаров (категории каталога) находятся в контексте "catalog".

============================================

Пример чанка товара при выводе списка товаров:

<div class="product shk-item">
    <div class="product-b">
        <div class="product-descr">
            <a href="[[~[[+id]]? &scheme=`abs`]]">
                <img class="shk-image" src="[[+tv.image]]" alt="" height="130" width="130" />
            </a>
            <h3>[[+pagetitle]]</h3>
            [[+introtext]]<br />
            <a href="[[~[[+id]]? &scheme=`abs`]]">Details &rsaquo;</a>
            <div style="clear:both;"></div>
        </div>
        <form action="[[~[[*id]]? &scheme=`abs`]]" method="post">
            <fieldset>
                <input type="hidden" name="shk-id" value="[[+id]]" />
                <input type="hidden" name="shk-count" value="1" />
                <div class="product-price">
                    <button type="submit" class="shk-but">Add to cart</button>
                    <div>Price: <span class="shk-price">[[+tv.price:num_format]]</span> руб.</div>
                </div>
            </fieldset>
        </form>
    </div>
</div>

============================================

Вывод списка товаров с помощью сниппетов "getPage" и "getProducts":

[[!getPage?
&elementClass=`modSnippet`
&element=`getProducts`
&className=`shopContent`
&packageName=`shop`
&limit=`10`
&tpl=`product`
&where=`{"template":15}`
]]
<br clear="all" />
<ul class="pages">
[[!+page.nav]]
</ul>

============================================

Оформление заказа с помощью сниппета "FormIt" и хука "shk_fihook"

[[!FormIt?
&hooks=`spam,shk_fihook,email,FormItAutoResponder,redirect`
&submitVar=`order`
&emailTpl=`shopOrderReport`
&fiarTpl=`shopOrderReport`
&emailSubject=`В интернет-магазине "[[++site_name]]" сделан новый заказ`
&fiarSubject=`Вы сделали заказ в интернет-магазине "[[++site_name]]"`
&emailTo=`[[++emailsender]]`
&fiarReplyTo=`[[++emailsender]]`
&fiarToField=`email`
&redirectTo=`10`
&validate=`address:required,fullname:required,email:email:required,phone:required`
&errTpl=`<br /><span class="error">[[+error]]</span>`
]]

[[$shopOrderForm]]

В чанке shopOrderReport доступны плейсхолдеры:

orderID - ID заказа.
orderDate - Дата заказа.
orderPrice - Цена заказа.
orderOutputData - Состав заказа (чанк "orderDataOuter"). Включает список товаров, контактные данные, доставку.
orderCurrency - Валюта заказа.


tagManager ( создание фильтров, сортировки) на modx revo

Спонсор блога Магазин детской одежды Dress

Компонент для фильтрации товаров в каталоге и управления фильтрами.

Функции:

- Управление фильтрами. Изменение порядка сортировки, переименование названий групп фильтров и др.
- Групповое изменение значений доп. параметров товаров.
- Простая фильтрация товаров в каталоге (без ajax).
- Ajax-фильтрация товаров в каталоге с выводом количества найденных товаров по каждому фильтру.
- Динамическое изменение вида вывода товаров (изменение шаблонов).
- Поддержка мультивалютности.

==================================================================

tmFilters - сниппет выводит фильтры. Вызывать кэшированным (без "!").

tmCatalog - сниппет выводит товары каталога и фильтрует. Вызывать не кэшированным (с "!").

tmRefresh - плагин для обновления значений фильтров при сохранении документа.

Необходимо установить сниппет getProducts (http://modx.com/extras/package/getproducts).

==================================================================

Сниппет tmFilters

Параметры сниппета:

filterOuterTpl - Чанк блоки с фильтрами. По умолчанию - tm2_filterOuterTpl.
filterTpl - Чанк одного фильтра. По умолчанию - tm2_filterTpl.
filterNumericOuterTpl - Чанк блока с фильтрами с числовыми значениями. По умолчанию - tm2_filterOuterTpl.
filterNumericTpl - Чанк фильтра с числовыми значениями. По умолчанию - tm2_filterNumericTpl.
jsMap - Генерация JS-карты данных товаров для возможности вывода количества найденных товаров по каждому фильтру ( 1 - да, 0 - нет). По умолчанию: 0.
toPlaceholder - Имя плейсхолдера для вывода. Если не задано, выводится в месте вызова сниппета.
style - Подключить CSS-файл стилей ( 1 - да, 0 - нет). По умолчанию: 1.
jsScript - Подключить все необходимые JS-скрипты ( 1 - да, 0 - нет). По умолчанию: 1.
filtersType - Тип фильтрации. Возможные значения: filters, filters_simple. По умолчанию: filters.
categoryId - ID документа откуда нужно брать сохраненные фильтры. По умолчанию - текущий.

Используется библиотека jQuery.
Если у вас на сайте уже используется jQuery, повторно она подключаться не будет (сделана автоматическая проверка).

Для тонкой настройки открыть в текстовом редакторе файл
/assets/components/tag_manager2/js/web/filters.js
или
/assets/components/tag_manager2/js/web/filters_simple.js
Настройки вверху, в коде есть комментарии.

Если используется ajax-фильтрация (filtersType = filters), в форму фильтрации добавить скрытое поле (см. пример 3):

<input type="hidden" name="page_id" value="[[*id]]" disabled="disabled" />

Параметр "filters_type" в filters.js
Для "filters_type" = "default" (показ числа товаров по каждому фильтру и блокирование пустых вариантов)
или "only_block" (только блокирование пустых париантов) необходимо включить параметр "jsMap" у сниппета "tmFilters".
Если "filters_type" = "none", "jsMap" рекомендуется выключить.

Внимание!
При аякс-фильтрации все параметры для getProducts (через getPage) должны указываться в наборе параметров.
Имя используемого набора параметров нужно указать в настройках системы - tag_mgr2.propertySetName.
Этот набор параметров должен быть привязан к сниппету getPage. Сниппет getPage должен использовать getProducts (element=getProducts).
Так же имя набора параметров можно указать в параметрах шаблона категории товаров (см. ниже).

==================================================================

Сниппет tmCatalog

Сниппет не имеет параметров, т.к. является оберточным сниппетом для "getPage" и "getProducts".
Используются параметры из набора параметров для сниппета "getPage", указанного в настройках системы - tag_mgr2.propertySetName.
Можно указывать параметры для "getPage" и "getProducts".

Пример:

[[!tmCatalog?
&parents=`-1`
&resources=`110,111,112`
&tpl=`product`
]]

В данном случае будут выводиться только товары с ID = 110,111,112.
Можно использовать для поиска, выводить найденные ID товаров с помощью отдельного сниппета и фильтровать найденные товары.

==================================================================

Вывод товаров из таблицы, созданной в MIGXDB (http://modx.com/extras/package/migx)

Если для хранения товаров импользуется отдельная таблица в БД, созданная с помощью MIGXDB,
в настройках компонента "tagManager2" в параметрах "tag_mgr2.className" и "tag_mgr2.packageName" указать
название класса и название компонента вашей таблицы в БД.

Настройки "className" и "packageName" можно указать в параметрах шаблона категории товаров:

1. Открыть шаблон категории товаров.
2. Перейти на вкладку "Параметры".
3. Разблокировать параметры по умолчанию и добавить параметры:
    prodClassName - Имя класса таблицы БД (например "ShopContent").
    prodPackageName - Имя пакета таблицы БД (например "shop").
    prodPropertySetName - имя набора параметров для сниппета getPage, который нужно использовать для фильтрации для текущего шаблона (не обязателный параметр).
4. Сохранить изменения.

==================================================================
==================================================================

Множественные значения фильтров

Если нужно сделать возможность задавать множественные значения для параметра, нужно создать TV параметр с типом ввода "Флажки (checkbox)" или "Список (множественный выбор)".
Поле "Возможные значения" заполнить по такому принципу:

акция==#акция#||лидер продаж==#лидер продаж#||новинка==#новинка#

Разделитель "#" можно изменить в конфигурации компонента - tag_mgr2.guard_key.

Имена таких TV нужно указать в скрипте filters.js в массиве
'multitags': ['tag']

А также имена полей с множественными значениями нужно указать в настройках системы в параметре "tag_mgr2.multitags" (можно несколько через запятую).

==================================================================
==================================================================

Динамическое изменение шаблона вывода списка товаров

На данный момент сделана готовая возможность изменения шаблона с помошью JS-скрипта /assets/components/tag_manager/js/web/view_switch.js.
Скрипт ставит куку и обновляет вывод.

1. Добавить скрипт на страницу

<script type="text/javascript" src="/assets/components/tag_manager2/js/web/view_switch.js"></script>

2. В набор параметров "getPage", который используется для вывода товаров, добавить параметр "tpl_list" со списком шаблонов (чанков) через запятую.
Например: "product,product_list".

3. В тело страницы вставить ссылки для изменения вида. У элемента-контейнера должен быть id="viewSwitch".

Пример:

<span id="viewSwitch">
    Показывать:
    &nbsp;
    <a rel="nofollow" href="#" class="active">картинками</a>
    &nbsp;
    <a rel="nofollow" href="#">списком</a>
</span>

==================================================================
==================================================================

Мультивалютность

Поддерживается мультивалютность, используемая Shopkeeper. По настройке мультивалютности читать документацию Shopkeeper.

Для работы tagManager с мультивалютностью необходимо выполнить:

1. Если используется аякс-фильтрация, открыть в текстовом редакторе /assets/components/tag_manager2/js/web/filters.js
   и включить мультивалютность - multi_currency = true.
2. В этом же файле указать правильное название TV параметра или поля с ценой - price_field.
3. В настройках системы в параметре tag_mgr2.priceName нужно указать название TV параметра или поля с ценой (по умолчанию "price").
4. Версия Shopkeeper должна быть не меньше 2.3.4.

==================================================================
==================================================================

Стилизация селектов

Для стилизации селектов рекомендуется использовать jQuery-плагин SelectBoxIt - http://gregfranko.com/jquery.selectBoxIt.js/index.html.
Данный плагин поддерживается tagManager.

Пример подключение стиля и скриптов SelectBoxIt:

<link href="/assets/template/js/jquery.selectBoxIt.js/src/stylesheets/jquery.selectBoxIt.css" type="text/css" rel="stylesheet" />
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js" type="text/javascript"></script>
<script src="/assets/template/js/jquery.selectBoxIt.js/src/javascripts/jquery.selectBoxIt.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).bind('ready',function(){
    $("select").selectBoxIt();
});
</script>

==================================================================
==================================================================

Автоматическое обновление списков значений фильтров

tmRefresh - плагин для обновления фильтров.

События: OnDocFormSave, OnCacheUpdate

По умолчанию данный плагин отключен. Для активации найти плагин в списке и нажать "Активировать плагин".
Если для плагина включено событие "OnCacheUpdate", при активации в админке "Сайт" -> "Обновить сайт", автоматически обновятся
все списки значений фильтров. Если товаров очень много (больше 3000), это действие может занимать продолжительное время. В этом случае
рекомендуется отключить событие "OnCacheUpdate" и использовать cron - скрипт /assets/components/tag_manager2/cron_updatefilters.php.

Основной файл конфигурации cron обычно находится по адресу: /etc/crontab

Пример для запуска ежедневно в 02:00 ч.:

00 02 * * * php -f '/var/www/modxsite/assets/components/tag_manager2/cron_updatefilters.php' > /dev/null

Внимание!
Если используестся плагин "tmRefresh" с включенным событием "OnCacheUpdate", то удаление значений тегов работать не будет, т.к. при обновлении они снова будут появляться.
Если нужно удалять, то данное событие плагина нужно отключить или просто вместо удаления делать деативанцию значения фильтра.

==================================================================
==================================================================

JS-callback функции в filters.js

При использовании аякс-фильтрации (filter.js) есть возможность использовать callback функции:

tm_onFilterBefore( state_data ) - перед отправкой запроса на фильтраци. state_data - данные активных фильтров.
tm_onFilterAfter( total, pageCount, onPageLimit ) - после фильтрации. total - общее число товаров; pageCount - число страниц; onPageLimit - число тоаров на одной странице.

Просто создайте функцию и она будет вызвана в нужный момент.

Пример:
<script type="text/javascript">
function tm_onFilterAfter( total, pageCount, onPageLimit ){
 
    $('#total').text(total);
 
}
</script>

В данном примере в элементе с id="total" при фильтрации будет обновляться число найденных товаров.

==================================================================
==================================================================

Подключение JS-скриптов вручную.

[[tmFilters?
&jsScript=`0`
...

Необходимые JS-скрипты и CSS-файлы:

<link type="text/css" href="/assets/components/tag_manager2/css/web/tm-style.css" rel="stylesheet">
<script type="text/javascript" src="/assets/components/tag_manager2/js/web/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="/assets/components/tag_manager2/js/web/jquery-ui-1.10.3.custom.min.js"></script>
<script type="text/javascript" src="/assets/components/tag_manager2/js/web/jquery.history.js"></script>
<script type="text/javascript" src="/assets/components/tag_manager2/js/web/filters.js"></script>

<script type="text/javascript">
//Filters initialization
$(document).bind( 'ready', function(){ tmFilters.init(); } );
</script>

==================================================================
==================================================================

Пример 1. Простая фильтрация с чекбоксами (множественный выбор).

[[tmFilters?
&filterOuterTpl=`tm2_filterOuterTpl`
&filterTpl=`tm2_filterTpl`
&filterNumericOuterTpl=`tm2_filterOuterTpl`
&filterNumericTpl=`tm2_filterNumericTpl`
&filtersType=`filters_simple`
&toPlaceholder=`filters`
]]

<div id="filters">
    <form action="[[~[[*id]]]]" method="get">
   
        <table>
            <tr>
                <td>
                    Сортировать по:
                </td>
                <td>
                    <select class="f_sortby" name="sortby" style="width:100px;">
                        <option value="pagetitle">названию</option>
                        <option value="price">цене</option>
                        <option value="publishedon">дате</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>
                    В порядке:
                </td>
                <td>
                    <select class="f_sortdir" name="sortdir" style="width:100px;">
                        <option value="asc">возрастания</option>
                        <option value="desc">убывания</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>
                    Выводить по:
                </td>
                <td>
                    <select class="f_limit" name="limit" style="width:100px;">
                        <option value="10">10</option>
                        <option value="20">20</option>
                        <option value="40">40</option>
                    </select>
                </td>
            </tr>
        </table>
     
        [[+filters]]
     
        <button type="submit">Подобрать</button>
        <button type="button" onclick="window.location.href = window.location.pathname; return false;">Сбросить</button>
    </form>
</div>

==================================================================

<div id="products">
    [[!tmCatalog]]
    <div class="clearfix"></div>
</div>

<ul class="pages" id="pages">
    [[!+page.nav]]
</ul>

==================================================================
==================================================================

Пример 2. Сортировка отдельно от формы фильтров. Простая фильтрация с фильтрами в виде выпадающих списков (одиночный выбор).

<div id="filters">
    <form action="[[~[[*id]]]]" method="get">
     
        <input type="hidden" name="sortby" value="pagetitle" />
        <input type="hidden" name="sortdir" value="asc" />
        <input type="hidden" name="limit" value="10" />
     
        [[tmFilters?
        &filterOuterTpl=`tm2_filterOuterTpl_select`
        &filterTpl=`tm2_filterTpl_select`
        &filterNumericOuterTpl=`tm2_filterOuterTpl`
        &filterNumericTpl=`tm2_filterNumericTpl`
&filtersType=`filters_simple`
        ]]
     
        <button type="submit">Подобрать</button>
        <button type="button" onclick="window.location.href = window.location.pathname; return false;">Сбросить</button>
    </form>
</div>

==================================================================

<div class="sorting">
 
    <select class="f_sortby" name="sortby">
        <option value="pagetitle">по названию</option>
        <option value="price">по цене</option>
        <option value="publishedon">по дате</option>
    </select>
    &nbsp;
    <select class="f_sortdir" name="sortdir">
        <option value="asc">по возростанию</option>
        <option value="desc">по убыванию</option>
    </select>
    &nbsp;
    <select class="f_limit" name="limit">
        <option value="10">10</option>
        <option value="20">20</option>
        <option value="40">40</option>
    </select>
 
    <div class="clearfix"></div>
</div>

<div id="products">
    [[!tmCatalog]]
    <div class="clearfix"></div>
</div>

<ul class="pages" id="pages">
    [[!+page.nav]]
</ul>

==================================================================
==================================================================

Пример 3. Ajax-фильтрация, сортировка отдельно от формы фильтров.

[[tmFilters?
&filterOuterTpl=`tm2_filterOuterTpl`
&filterTpl=`tm2_filterTpl`
&filterNumericOuterTpl=`tm2_filterOuterTpl`
&filterNumericTpl=`tm2_filterNumericTpl`
&jsMap=`1`
&toPlaceholder=`filters`
]]

<div id="filters">
    <form action="[[~[[*id]]]]" method="get">
   
<input type="hidden" name="page_id" value="[[*id]]" disabled="disabled" />
     
        [[+filters]]
     
        <button type="button" onclick="tmFilters.resetFilters(); return false;">Сбросить</button>
    </form>
</div>

==================================================================

<div class="sorting">
 
    <select class="f_sortby" name="sortby" onchange="tmFilters.changeOrder(this);">
        <option value="pagetitle">по названию</option>
        <option value="price">по цене</option>
        <option value="publishedon">по дате</option>
    </select>
    &nbsp;
    <select class="f_sortdir" name="sortdir" onchange="tmFilters.changeOrder(this);">
        <option value="asc">по возростанию</option>
        <option value="desc">по убыванию</option>
    </select>
    &nbsp;
    <select class="f_limit" name="limit" onchange="tmFilters.changeOrder(this);">
<option value="4" selected="selected">4</option>
        <option value="10">10</option>
        <option value="20">20</option>
        <option value="40">40</option>
    </select>
 
    <div class="clearfix"></div>
</div>

<div id="products">
    [[!tmCatalog]]
    <div class="clearfix"></div>
</div>

<ul class="pages" id="pages">
    [[!+page.nav]]
</ul>