Skip to content

Instantly share code, notes, and snippets.

@panoply
Last active February 18, 2020 15:03
Show Gist options
  • Save panoply/05da67ac0fba758eccfe83408110c99e to your computer and use it in GitHub Desktop.
Save panoply/05da67ac0fba758eccfe83408110c99e to your computer and use it in GitHub Desktop.
Shopify Search Filter using Mithril
/* Modules */
import m from 'mithril'
import url from 'urljs'
export default () => {
const products = document.querySelector('#product-collection')
const results = document.querySelector('#search-collection')
const items = data => {
return [
m('.row.justify-content-start.align-content-center.p-2', [
data.map(item => {
return [
m('.col-6.col-sm-4.col-md-4.col-lg-4.col-xl-3.p-2', [
m('.product', [
m('.product__item', [
item.quantity < 4 && item.quantity !== 0 && [
m('.badge.limited-stock.d-block', `${item.quantity} IN STOCK`)
],
item.sale && m('.badge.sale', item.sale),
m(`a[href="${item.url}"][data-turbolinks-preload="true"]`, [
m('picture', [
m(`source[media="(min-width: 540px)"][srcset="${item.image}"]`),
m(`img.img-fluid[src="${item.image}"]`)
]),
m('.product__info.d-flex.justify-content-between.px-0.px-md-3', [
m('.align-self-center.d-block', [
m('.title.d-block', `${item.title}`),
item.color && m('.color.d-block.pt-1', `${item.color}`)
]),
m('.price.align-self-center', [
m('span.d-block', m.trust(item.price)),
item.compare && m('span.old.d-block', m.trust(item.compare))
])
])
])
])
])
])
]
})
])
]
}
const visible = char => {
if (char < 2) {
url.updateSearchParam('search')
!results.classList.contains('d-none') && results.classList.add('d-none')
products.classList.contains('d-none') && products.classList.remove('d-none')
} else {
url.updateSearchParam('search', `${state.value}`)
results.classList.contains('d-none') && results.classList.remove('d-none')
!products.classList.contains('d-none') && products.classList.add('d-none')
}
}
const state = {
gender: window.location.pathname.split('/').slice(1)[1],
data: [],
value: '',
setValue (v) {
state.value = v
setTimeout(() => {
return m.request({
url: `/search?type=product&q=${state.gender}%20${state.value}*&view=json`,
background: true
}).then(data => {
m.render(results, items(data.results))
}).then(() => {
visible(state.value.length)
})
}, 250)
}
}
const Input = {
oninit () {
if (url.queryString('search')) {
state.value = url.queryString('search')
state.setValue(state.value)
}
},
view () {
return [
m('.search__products', [
m('input', {
placeholder: 'SEARCH',
oninput: m.withAttr('value', state.setValue),
value: state.value
})
])
]
}
}
m.mount(document.querySelector('#search-filter'), Input)
}
{%comment%}
Add this to the template folder in the customize code page.
{%endcomment%}
{%- layout none -%}
{%- capture results -%}
{%- for item in search.results -%}
{%- unless item.title contains 'Re-waxing' -%}
{%- comment -%}
Set `product` variable
{%- endcomment -%}
{%- assign product = item -%}
{%- comment -%}
Check if the product is sold out and set a variable to be used below.
{%- endcomment -%}
{%- assign sold_out = true -%}
{%- if product.available -%}
{%- assign sold_out = false -%}
{%- endif -%}
{%- comment -%}
Check if the product is on sale and set a variable to be used below.
{%- endcomment -%}
{%- assign on_sale = false -%}
{%- if product.compare_at_price > product.price -%}
{%- assign on_sale = true -%}
{%- endif -%}
{%- comment -%}
Acquire the items quantity amount.
{%- endcomment -%}
{%- assign qty = 0 -%}
{%- for variant in product.variants -%}
{%- if variant.inventory_quantity > 0 -%}
{%- assign qty = qty | plus: variant.inventory_quantity -%}
{%- endif -%}
{%- endfor -%}
{%- comment -%}
Set Product title name
{%- endcomment -%}
{%- if product.metafields.global.short_name -%}
{%- assign product_title = product.metafields.global.short_name -%}
{%- else -%}
{%- assign product_title = product.title -%}
{%- endif -%}
{%- comment -%}
Set Product color name
{% endcomment %}
{%- if product.metafields.global.product_color -%}
{%- assign color = product.metafields.global.product_color -%}
{%- endif -%}
{%- if on_sale -%}
{%- if product.price_varies -%}
{%- assign sale_price = product.price | money -%}
{%- else -%}
{%- assign price = product.price | money -%}
{%- assign compare = product.compare_at_price | money %}
{%- endif -%}
{% else %}
{%- if product.price_varies -%}
{%- assign price = product.price | money -%}
{%- else -%}
{%- assign price = product.price | money -%}
{%- endif -%}
{%- endif -%}
{%- comment -%}
Set sale property value
{%- endcomment -%}
{%- if on_sale -%}
{%- unless sold_out -%}
{% if product.compare_at_price > product.price %}
{%- assign sale = product.compare_at_price
| minus: product.price
| times: 100.0
| divided_by: product.compare_at_price
| times: 100
| divided_by: 100
| floor
| append: '% OFF' %}
{% endif %}
{%- endunless -%}
{%- endif -%}
{%- comment -%}
Applies different stock badge texts based on season.
{%- endcomment -%}
{%- if product.vendor == 'Autumn / Winter 18' -%}
{%- assign status = 'COMING SOON' -%}
{%- else -%}
{%- assign status = 'OUT OF STOCK' -%}
{%- endif -%}
{%- comment -%}
Build JSON response
{%- endcomment -%}
{
"id": {{ product.id | json }},
"title": {{ product_title | json }},
"color": {%- if color -%}{{ color | json }}{%- else -%}false{%- endif -%},
"url": {{ product.url | within: product.collections.last | json }},
"image": {{ product.featured_image.src | product_img_url: 'x560' | json }},
"price": {{ price | json }},
"compare": {%- if compare -%}{{ compare | json }}{%- else -%}false{%- endif -%},
"sale": {%- if sale -%}{{ sale | json }}{%- else -%}false{%- endif -%},
"quantity": {{ qty | strip }},
"status": {%- if status -%}{{ status | json }}{%- else -%}false{%- endif -%}
}
{%- unless forloop.last -%},{%- endunless -%}
{%- endunless -%}
{%- endfor -%}
{%- endcapture -%}
{%- comment -%}
Return response array
{%- endcomment -%}
{
"results_count": {{ search.results_count | strip }},
"results": [{{ results | strip }}]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment