Гайды

liquid

Как измерить скорость рендеринга liquid кода

Для измерения скорости используйте фильтр date.

См. пример ниже.

Liquid
        
          

{% capture start_time %}{{'now' | date: '%s.%L' }}{% endcapture %}

{% include 'head' %}

<!-- Render time: {{ 'now' | date: '%s.%L' | minus: start_time }} -->

Создание простого меню на платформе InSales

Меню это список, поэтому мы можем построить меню из любых массивов которые доступны в liquid.
Например массив категорий на сайте, массив блогов, массив статей, массив блоков и конечно массив ссылок из раздела «Меню и статьи».

Для вывода ссылок из конкретных каталогов или меню необходимо использовать пермалинки.


Для такого меню пермалинком является main-nav, значит для вывода пунктов нужно использовать linklists.main-nav.links.

Далее простые реализации меню:

 

 

 

Виджеты

Чтобы создать виджет в шаблоне нужно указать следующие данные в setup.json:

widget_types

theme_widgets -> widget_lists

 

widget_types

widget_types отвечает за создание виджета. 

widget_types имеет следующие свойства:

"block_template": шаблон блокок которые будут добавляться в виджете

"name": заголовок виджета

"handle": уникальный пермалинк для типов виджетов

"type": "block_list_widget_type"

"snippet": название сниппета который будет привязан к виджету, например - "widget_shippet.liquid". Сниппет должен присутствовать в теме.

 

widget_lists

widget_lists содержит в себе виджет листы, которые содержат в себе массивы виджетов.

В ликвид доступна переменна widget_lists в которой по ключу можно получить массив виджетов.

widget_lists.index-list.widgets

widget_lists содержит массив объектов с полями:

"name": имя виджет листа (указать уникальное имя на латинице)

"handle": пермалинк виджет листа, используется для доступа в виджетам в ликвид

"widgets" массив виджетов

 

widgets

В массиве виджетов находятся с объекты с указанным типом виджета и пермалинком панели блоков

"widget_type": тут указывается handle из widget_types

"data_handle": тут пермалинк из block_lists

 

Liquid js
        
          

{% for widgetDrop in widget_lists.index-list.widgets %}
  {% widget widgetDrop %}
{% endfor %}

        
          

{
"block_lists": {
 "mainblock": {
  "block_template": "system-image-and-content",
  "title": "Наша тестовая панель блоков",
  "blocks": [
   "image-text-1"
  ]
 }
},
"blocks": {
 "image-text-1": {
  "block_template": "system-image-and-content",
  "title": "Блок внутри тестового виджета",
  "content": "Контент внутри тестового виджета",
  "image": "empty.jpg"
 }
},
"theme_widgets": {
 "widget_lists": [{
  "name": "index",
  "handle": "index-list",
  "widgets": [{
   "widget_type": "test_handle",
   "data_handle": "mainblock"
  }]
 }],
 "widget_types": [{
  "block_template": "system-image-and-content",
  "name": "Заголовок тестового виджета",
  "handle": "test_handle",
  "type": "block_list_widget_type",
  "snippet": "widget_test_snippet.liquid"
 }]
}
}

Особенности шаблонов на InSales

Темы InSales состоят из liquid-файлов, каждый из которых служит для определенных задач. Например, collection.liquid используется для отображения товаров внутри категории, а product.liquid - для отображения информации о конкретном товаре.

Структура папок:

root/
    |-- config/
    |-- media/
    |-- snippets/
    |-- templates/

media

Эта директория содержит ассеты, используемые в теме, в том числе изображения, стили, скрипты, svg-файлы (css, js и svg-файлы из директории media можно править с помощью редактора шаблонов в бек-офисе магазина). Для обращения к файлам из этой директории из шаблонов используйте фильтр asset_url (важно! css и картинки лежат в одном месте потому в таких случаях как background-image: url('./images/main.jpg') ссылка на файл указывается от корневой директории background-image: url('main.jpg'), папки на платформе создавать нельзя)

snippets

Директория содержит Liquid-снипеты с кусочками кода, используемого в разных шаблонах / в разных частях сайта. Используйте include для включения снипета в шаблон.

templates

Эта директория содержит файлы Liquid-шаблонов для основных типов страниц сайта, а также шаблоны лэйаутов, определяющий общую часть оформления и вёрстки страниц. По умолчанию в теме присутствует 2 лэйаута - layouts.layout.liquid (для всех страниц сайта, кроме личного кабинета и шаго оформления заказа) и layouts.checkout.liquid (для страниц оформления заказа).

config

тут файлы конфигурации темы

Нейминг шаблонов:

  • Главный лэйаут - layouts.layout.liquid (Все остальные шаблоны не являющиеся лэйаутами наследуют содержимое данного файла. Контент шаблонов будет вставлен на место тега {{ content_for_layout }})
  • Главная - index.liquid
  • Категория - collection.liquid
  • Товар - product.liquid
  • Корзина - cart.iquid
  • Страница page.liquid
  • Поиск search.liquid
  • Блог blog.liquid
  • Статья article.liquid

Кастомные шаблоны для любой страницы можно сделать, со следующим неймингом:

Сначала идет имя лэйаута, потом кастомное имя.

  • product.hits.liquid
  • product.new.liquid
  • blog.news.liquid
  • page.contacts.liquid

Подключение стилей и скриптов

Для подключения стоит использовать внутренний функционал платформы для склеивания файлов.

Для стилей нужно пользоваться директивой препроцессора sass — @import или внутренней директивой #= require

Пример plugins.css:

#= require jquery.min
#= require magiczoomplus.min
#= require normalize.min
#= require swiper.min
#= require alertify.min
#= require magnific-popup.min

Пример main.scss:

@import 'header';
@import 'footer';
@import 'slider';

Важно! Файлы header, footer, slider могут быть как scss так и css.

Используя @import и #= require можно игнорировать расширение.

Для удобности в файлы относящиеся к main.scss именуют с префиксом _, при импорте префикс игнорируется.

main.scss компилируется в main.css, в тему подключается скомпилированный или склеенный main.scss.

Подключение js происходит аналогично, только используется директива #= require.

Js файлы так же разделяются на два файла plugins и main.

Пример main.js:

#= require cart
#= require product
#= require collection

Подключение скриптов и стилей разделяется сниппетами, сниппет для стилей styles.liquid для скриптов scripts.liquid.

Сниппеты подключаются в главный лэйаут layouts.layout.liquid.

Пример layouts.layout.liquid:


<!DOCTYPE html>
<html>

<head>

  {% include 'head' %}

  {% include 'styles' %}

</head>
<body class="adaptive">

<div class="page-wrapper">

  <div class="page-inner container">

    {% include 'header' %}

    {{ content_for_layout }}

  </div>

  {% include 'footer' %}

</div>

  {% include 'modals' %}

  {% include 'scripts' %}

</body>
</html>

Содержимое styles.liquid:

<link rel="stylesheet" href="{{ 'plugins.css' | asset_url }}">
<link rel="stylesheet" href="{{ 'main.css' | asset_url }}">

Содержимое scripts.liquid:

<script type="text/javascript" src="{{ 'plugins.js' | asset_url }}"></script>
<script type="text/javascript" src="{{ 'main.js' | asset_url }}"></script>

Как пользоваться сниппетами

Сниппеты в программировании — это небольшие фрагменты кода которые обычно повторно используются в коде программы (Статья на википедии).

Сниппеты на платформе InSales хранят в себе html код разметки и код написанный на шаблонизаторе liquid.

Сниппеты включаются в шаблоны через директиву include.

Пример:

Пример включения сниппета без передачи параметров.
{% include 'header' %}
Пример включения сниппета с передачей строки в виде параметра
{% include 'header' with "index" %}
При таком включении внутри сниппета header, параметр будет доступен в одноименной переменной {{ header }}

Пример кода сниппета header
{% if header == 'index' %}
# код для включения с параметром - index
{% else %}
# код обычного включения
{% endif %}
Пример включения сниппета с передачей нескольких параметров:
{% assign logo_text = 'Моя компания' %}
{% include 'logo', use_image: false, logo_text: logo_text %}
При таком виде включения, все передаваемые переменные стоит обнулять в конце кода сниппета, так как значения параметров кэшируется в переменные и можут быть использованы в следующих по коду сниппетах которые используют эти переменные. 

Пример кода сниппета logo
{% if use_image %}
  <img src="{{ 'logo.svg' | asset_url }}" />
{% else %}
  {{ logo_text }}
{% endif %}
{% assign use_image = null %}
{% assign logo_text = null %}

Сниппеты могут содержать в себе включение других сниппетов.

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

<div class="container">
  <div class="row">
    <div class="cell-2">
      {% include "logo", modificator: 'in-header', use_image: true %}
    </div>
    <div class="cell-6">
      {% include "menu", modificator: 'in-header', menu_class: 'main-menu', source_type: 'collection', source_handle: 'all', show_icon: true %}
    </div>
    <div class="cell-2">
      {% include "search", modificator: 'in-header' %}
    </div>
    <div class="cell-2">
      {% include "cart_widget", modificator: 'in-header' %}
    </div>
  </div>
</div>

Javascript

Выбор изображения по варианту

Чтобы переключать изображения вариантов нужно привязаться к событию смены модификации.

Модификация содержит id привязанного изображения (image_id).

По image_id нужно искать картинку варианта в массиве изображений товара.

Далее искать изображение в галерее товара и переключаться на него

Но в common.v2 в событии update_variant:insales:product возвращается объект со свойством first_image, в котором уже определено изображение варианта!

 

js
        
          

// для swiper
EventBus.subscribe('update_variant:insales:product', function (data) {
​​​​​​​  if (variant.action.quantityState.change) {
    return;
  }
  // определяем что смена варианта произошла у основного товара
  var $productForm = $('#product-order[data-product-id="'+data.product_id+'"]');
  // если нужна смена изображений для вариантов без фото нужно убрать проверку на data.image_id
  if ($productForm.length && data.image_id) {
    var sliderClass = '.js-product-gallery'; // селектор слайдера
    var slideClass = '.swiper-slide';
    var imageSize = 'original_url'; // Важно указать правильный размер original_url, large_url, medium_url
    var imagePath = slideClass + ' [src="'+data.first_image[imageSize]+'"]';
    var index = $(imagePath).parents(slideClass + ':first').index();
    if ($(sliderClass)[0].swiper) {
      $(sliderClass)[0].swiper.slideTo(index);
    }
  }
});

// для owl
EventBus.subscribe('update_variant:insales:product', function (data) {
  if (variant.action.quantityState.change) {
    return;
  }
  // определяем что смена варианта произошла у основного товара
  var $productForm = $('#product-order[data-product-id="'+data.product_id+'"]');
  // если нужна смена изображений для вариантов без фото нужно убрать проверку на data.image_id
  if ($productForm.length && data.image_id) {
    var sliderClass = '.js-slider-product';
    var slideClass = '.owl-item';
    var imageSize = 'original_url'; // original_url, large_url, medium_url
    var imagePath = slideClass + ' [src="'+data.first_image[imageSize]+'"]';
    var index = $(imagePath).parents(slideClass + ':first').index();
    $(sliderClass).trigger('to.owl.carousel', index);
  }
});

Как работать с API магазина на платформе InSales

Разрабатывая сайт на платформе InSales самым важным аспектом является знание всех возможностей которые предоставляет платформа.

API магазина это набор готовых контроллеров со стороны backend для работы с корзиной, получением информации о товаре, добавлением отзывов, фильтрации товаров в категории и т.д.

Обращение к API может быть как через отправки форм, так и через AJAX-запросы.

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

<form action="{{ cart_url }}" method="post">

  <input type="hidden" name="variant_id" value="{{ product.variants.first.id }}" />

  <input type="number" name="quantity" value="1" />

  <button type="submit">Купить</button>

</form>

Пример AJAX-запроса для получения информации о товаре:

$.post('/products_by_id/62898073.json')
  .done(function (product) {
    console.log(product);
  })

Для успешной разработки тем необходимо знать максимум возможностей API.

Описание AJAX-запросов можно почитать на тут.

Полезные видео