Skip to content

Instantly share code, notes, and snippets.

@savchukoleksii
Last active August 13, 2021 11:17
Show Gist options
  • Save savchukoleksii/b9eec2872e11a80757ccbfd8d0efa9ce to your computer and use it in GitHub Desktop.
Save savchukoleksii/b9eec2872e11a80757ccbfd8d0efa9ce to your computer and use it in GitHub Desktop.
{
"name": "NOSTO",
"settings": [
{
"type": "header",
"content": "You May Also Like"
},
{
"type": "checkbox",
"id": "enable_nosto_recommendations",
"label": "Enable NOSTO You May Also Like",
"info": "If unchecked then default theme related products section will be enabled",
"default": true
},
{
"type": "text",
"id": "nosto_collection_recommendation_id",
"label": "[Collection Page] You May Also Like Id",
"default": "frontpage-nosto-4-copy"
},
{
"type": "text",
"id": "nosto_product_recommendation_id",
"label": "[Product Page] You May Also Like Id",
"default": "productpage-nosto-2"
},
{
"type": "header",
"content": "Recently Viewed"
},
{
"type": "checkbox",
"id": "enable_nosto_recently_viewed",
"label": "Enable NOSTO Recently Viewed",
"info": "If unchecked then default theme recently viewed section will be enabled",
"default": true
},
{
"type": "text",
"id": "nosto_collection_recently_viewed_id",
"label": "[Collection Page] Recently Viewed Id",
"default": "categorypage-nosto-2"
},
{
"type": "text",
"id": "nosto_product_recently_viewed_id",
"label": "[Product Page] Recently Viewed Id",
"default": "productpage-nosto-3"
}
]
}
import initVerticalFixOnSlider from './_fixVerticalDraggingFlickity';
import initHorizontalFixOnSlider from "./_fixHorizontalDraggingFlickity";
function initNostoRecommendations() {
let sections = document.querySelectorAll('.js-nosto-section');
if(!sections.length){
return null;
}
let placements = Array.from(sections).reduce((result, next) => {
let placement = next.dataset.nostoId;
if(placement){
result.push(placement);
}
return result;
}, []);
if(!placements.length){
return null;
}
nostojs(api => {
api.defaultSession()
.viewProduct('' + window.__st.rid || '')
.setPlacements(placements)
.load()
.then(data => {
renderSection(data)
})
});
function renderSection({ recommendations }){
sections.forEach((section) => {
let placement = section.dataset.nostoId;
if(!placement){
return null;
}
let sliderWrapper = section.querySelector('.js-nosto-products');
if(!sliderWrapper){
return null;
}
initProducts(recommendations, section, sliderWrapper, placement);
});
}
async function initProducts(recommendations, section, sliderWrapper, placement) {
if(!recommendations.hasOwnProperty(placement) || !recommendations[placement].products.length){
return null;
}
let promises = [];
recommendations[placement].products.forEach(product => {
promises.push(fetch(${product.url}?view=related-product-item).then(data => data.text()));
});
let productGridItems = await Promise.all(promises);
productGridItems = productGridItems.reduce((result, next) => {
let div = document.createElement('div');
div.classList.add('Carousel__Cell', 'js-slide');
div.innerHTML = next;
div.querySelectorAll('a[href]').forEach((item) => {
item.setAttribute('href', ${item.getAttribute('href')}?nosto=${placement});
});
result.push(div);
return result;
}, []);
let config = {};
try{
config = JSON.parse(sliderWrapper.dataset.flickityConfig);
} catch (e) {
return null;
}
let sliderObject = new window.Flickity(sliderWrapper, config);
['previous', 'next'].forEach(direction => {
let customSvg = sliderWrapper.querySelector(.js-custom-${direction}-arrow);
if(!customSvg){
return null;
}
let sliderArrow = sliderWrapper.querySelector(.flickity-prev-next-button.${direction});
if(!sliderArrow){
return null;
}
Alex Hodzitsky, [13.08.21 14:10]
sliderArrow.innerHTML = customSvg.innerHTML;
});
sliderObject.insert(productGridItems, 0);
removeLoading(section);
sliderObject.resize();
initVerticalFixOnSlider(sliderObject);
initHorizontalFixOnSlider(sliderObject, sliderWrapper);
}
function removeLoading(section){
section.classList.remove('d-none');
let parent = section.parentNode;
if(!parent){
return null;
}
parent.classList.remove('shopify-section--hidden')
}
}
export default initNostoRecommendations;
{%- capture flickity_options -%}
{
"prevNextButtons": false,
"pageDots": false,
"wrapAround": false,
"contain": true,
"cellAlign": "center",
"watchCSS": true,
"dragThreshold": 8,
"groupCells": true,
"arrowShape": {"x0": 20, "x1": 60, "y1": 40, "x2": 60, "y2": 35, "x3": 25}
}
{%- endcapture -%}
{% assign isNosto = false %}
{% assign nosto_id = '' %}
{% if settings.enable_nosto_recently_viewed %}
{% if template.name == 'product' %}
{% assign nosto_id = settings.nosto_product_recommendation_id %}
{% elsif template.name == 'collection' %}
{% assign nosto_id = settings.nosto_collection_recommendation_id %}
{% endif %}
{% if nosto_id != blank %}
{% assign isNosto = true %}
{% endif %}
{% endif %}
{%- if section.settings.show_section -%}
<section class="Section Section--spacingNormal {% if isNosto %}js-nosto-section d-none{% endif %}" data-section-id="{{ section.id }}" data-section-type="related-products" {% if isNosto %}data-nosto-id="{{ nosto_id }}"{% endif %}>
{%- if section.settings.title != blank -%}
<header class="SectionHeader SectionHeader--center">
<div class="Container">
<h3 class="SectionHeader__Heading Heading u-h3 rr-products-title">{{ section.settings.title | escape }}</h3>
<div class="subtitle_realted_product">{{section.settings.subtitle | escape}}</div>
</div>
</header>
{%- endif -%}
{%- comment -%}
If we are in the context of a collection, we use other products from the same collection. Otherwise we fallback to the first collection attached
to the product and, if none is found, the "all" collections
{%- endcomment -%}
{%- unless collection -%}
{%- assign collection = product.collections.first | default: collections.all -%}
{%- endunless -%}
{%- if collection.products_count == 1 -%}
{%- assign collection = collections.all -%}
{%- endif -%}
{%- assign products_count = collection.products.size -%}
{%- if product.metafields.sf_related_products.enabled == 1 -%}
{%- assign related_products_count = 0 -%}
{%- for i in (1..4) -%}
{%- assign related_product_option = 'product_' | append: i -%}
{%- assign related_product = all_products[product.metafields.sf_related_products[related_product_option]] -%}
{%- unless related_product.empty? -%}
{%- assign related_products_count = related_products_count | plus: 1 -%}
{%- endunless -%}
{%- endfor -%}
{%- else -%}
{%- if products_count >= 5 -%}
{%- assign related_products_count = 4 -%}
{%- else -%}
{%- assign related_products_count = products_count | minus: 1 -%}
{%- endif -%}
{%- endif -%}
<div class="ProductListWrapper ProductListWrapper--RelatedProduct container wrap">
{% if isNosto %}
<div class="nosto_element d-none" id="{{ nosto_id }}"></div>
{% endif %}
<div class="ProductList ProductList--RelatedProduct ProductList--carousel Carousel js-nosto-products" data-flickity-config='{{ flickity_options }}'>
{% unless isNosto %}
{%- if collection.products.size >= 5 -%}
{%- assign random_factor = collection.products.size | minus: related_products_count | abs -%}
{%- capture index -%}{{ 'now' | date: '%S' | times: random_factor | divided_by: 60 }}{%- endcapture -%}
{%- else -%}
{%- assign index = 0 -%}
{%- endif -%}
{%- comment -%}
All our themes come with a native integration with our SuperFields metafield app. If the product has the hand-picked choosen, then we display the
hand-picked products instead
{%- endcomment -%}
{%- if product.metafields.sf_related_products.enabled == 1 -%}
{%- for i in (1..related_products_count) -%}
{%- assign related_product_option = 'product_' | append: i -%}
{%- assign related_product = all_products[product.metafields.sf_related_products[related_product_option]] -%}
{%- unless related_product.empty? -%}
<div class="Carousel__Cell">
{% include 'product-item', product: related_product, show_product_info: section.settings.show_product_info, show_vendor: section.settings.show_vendor, show_labels: true, custom_aspect_ratio: true %}
</div>
{%- endunless -%}
{%- endfor -%}
{%- else -%}
{%- for related_product in collection.products offset: index limit: 5 -%}
{%- if related_product.id == product.id or processed_related_products >= related_products_count -%}
{%- continue -%}
{%- endif -%}
<div class="Carousel__Cell">
{% include 'product-item', product: related_product, show_product_info: section.settings.show_product_info, show_vendor: section.settings.show_vendor, show_color_swatch: section.settings.show_color_swatch, show_labels: true, custom_aspect_ratio: true %}
</div>
{%- assign processed_related_products = processed_related_products | plus: 1 -%}
{%- endfor -%}
{%- endif -%}
{% endunless %}
</div>
<button class="view-collection-btn d-none">view entire collection</button>
</div>
</section>
{%- endif -%}
{% schema %}
{
"name": "Related products",
"class": "shopify-section--bordered",
"settings": [
{
"type": "paragraph",
"content": "Are you looking for hand-picked related products? [Learn more](http://support.maestrooo.com/article/117-product-choosing-hand-picked-related-products)."
},
{
"type": "checkbox",
"id": "show_section",
"label": "Show section",
"default": true
},
{
"type": "text",
"id": "title",
"label": "Heading",
"default": "You May Also Like"
},
{
"type": "text",
"id": "subtitle",
"label": "Heading",
"default": "Other products that our customers have enjoyed"
},
{
"type": "checkbox",
"id": "show_product_info",
"label": "Show product info",
"default": true
},
{
"type": "checkbox",
"id": "show_vendor",
"label": "Show vendor",
"default": false
},
{
"type": "checkbox",
"id": "show_color_swatch",
"label": "Show color swatch",
"info": "Some colors appear white? [Learn more](http://support.maestrooo.com/article/80-product-uploading-custom-color-for-color-swatch).",
"default": false
}
]
}
{% endschema %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment