Online Store 2.1 standard browser events
For Online Store 2.1 themes, SHOPLINE uses standard browser events to manage interactions between the theme template and JavaScript. Refer to standard browser events to listen for and handle theme-related events.
For Online Store 2.0 or 1.0 themes, refer to Online Store 2.0 & 1.0 events for event handling.
Use case examples
Variant selection
The following example demonstrates the variant selection HTML within a theme:
<variant-selects>
<label>
<input type="checkbox" value="blue" name="variant-input-blue" />
blue
</label>
<label>
<input type="checkbox" value="red" name="variant-input-red" />
red
</label>
</variant-selects>
The following sample shows how to bind events to variant selection HTML using JavaScript. When a shopper selects a variant, the system records the choice and prints the current list of selected variants to the browser's console.
class VariantSelects extends HTMLElement {
constructor() {
super();
this.variantInputs = this.querySelectorAll('input[name^="variant-input"]');
this.variantStore = new Set();
this.variantInputs.forEach((variantInput) => {
variantInput.addEventListener('change', (event) => {
const elem = event.target;
if (elem.checked) {
this.variantStore.add(elem.value);
} else {
this.variantStore.delete(elem.value);
}
console.log('variant changed: ', Array.from(this.variantStore));
});
});
}
}
customElements.define('variant-selects', VariantSelects);
Product addition
The following example demonstrates an HTML snippet that uses Handlebars to create a button for adding products to a cart.
<product-form class="product-form" data-default-error-message="{{t 'products.general.no_product_data_found'}}">
{{#form "product" product id=product_form_id}}
<div class="product-form__buttons">
<button
id="{{product_form_id}}-submit"
type="submit"
name="add"
class="product-form__submit button button--full-width button--secondary"
{{#unless product.selected_or_first_available_variant.available}}
disabled
{{/unless}}
>
<span>
{{#if product.selected_or_first_available_variant.available}}
{{t "products.product_list.add_to_cart"}}
{{else}}
{{t "products.general.sold_out"}}
{{/if}}
</span>
{{snippet "loading-overlay-spinner"}}
</button>
{{payment_button}}
</div>
{{/form}}
</product-form>
The following sample shows how to bind events to the add-to-cart button HTML using JavaScript. When a shopper clicks the add-to-cart button, a request is triggered to add a product to the shopping cart.
class ProductForm extends HTMLElement {
constructor() {
super();
this.submitButton = this.querySelector('[type="submit"]');
this.submitButton.addEventListener('click', this.submitButtonClickHandler.bind(this));
}
// Because the editor hijack the a tag click event, the click event needs to be bound to prevent bubbling
submitButtonClickHandler(e) {
e.preventDefault();
e.stopPropagation();
this.onSubmitHandler();
}
onSubmitHandler() {
if (this.submitButton.classList.contains('disabled') || this.submitButton.classList.contains('loading')) return;
const config = {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
Accept: `application/json`,
},
};
const formData = new FormData(this.form);
config.body = formData;
fetch(`${window.routes.cart_add_url}`, config)
.then((response) => response.json())
.then((response) => {
// The logic after adding an item to the cart
})
.finally(() => {
this.submitButton.classList.remove('loading');
});
}
};
customElements.define('product-form', ProductForm);
Product search
The following example demonstrates an HTML snippet that uses Handlebars to implement a search box with a predictive function.
<predictive-search class="main-search__content">
<form action="{{ routes.search_url }}" method="get" class="main-search__form search">
<div class="main-search__field field">
<input
id="main-search-input"
class="main-search__input field__input body3"
type="search"
name="keyword"
value="{{ search.terms }}"
placeholder="{{ t 'general.search.search' }}"
maxlength="255"
autocorrect="off"
autocomplete="off"
autocapitalize="off"
spellcheck="false"
>
<label class="main-search__field-label field__label body3" for="main-search-input">{{ t 'general.search.search' }}</label>
<button class="main-search__submit-button">
{{snippet 'icon-search'}}
</button>
</div>
<div class="predictive-search global-modal-border-shadow" tabindex="-1">
<div class="predictive-search__results" data-predictive-search></div>
<div class="predictive-search__loading-state">
<span class="predictive-search__spinner">
{{ snippet 'icon-loading' }}
</span>
</div>
</div>
</form>
</predictive-search>
The following sample shows how to bind events to the product search HTML using JavaScript.
- Bind the
submit
event to the form: The event is triggered when a shopper clicks the submit button. - Bind the following events to the search input box:
input
event: Triggered when a shopper enters a text into the input box.focus
event: Triggered when a shopper's mouse focuses the input box.
- Bind the following events to the
predictive-search
component:focusout
event: Triggered when a shopper's mouse leaves the component.keyup
event: Triggered when a keyboard key is released after a shopper enters text.keydown
event: Triggered when a keyboard key is pressed to enter text.
class PredictiveSearch extends BaseElement {
constructor() {
super();
this.input = this.querySelector('input[type="search"]');
this.setupEventListeners();
}
get query() {
return this.input.value.trim();
}
setupEventListeners() {
const form = this.querySelector('form.search');
form.addEventListener('submit', this.onFormSubmit.bind(this));
this.input.addEventListener('input', window.debounce(this.onChange.bind(this), 300));
this.input.addEventListener('focus', this.onFocus.bind(this));
this.addEventListener('focusout', this.onFocusOut.bind(this));
this.addEventListener('keyup', this.onKeyup.bind(this));
this.addEventListener('keydown', this.onKeydown.bind(this));
}
onFormSubmit(event) {
if (!this.query.length || this.querySelector('[selected="true"]')) event.preventDefault();
}
onChange() {
// Use this.query to retrieve the search keyword for searching products.
}
onFocus() {
// When the mouse cursor enters the input field
}
onFocusOut() {
// When the mouse cursor leaves the input field
}
onKeyup() {
// Listen for and handle keyboard key events
}
onKeydown(event) {
if (event.code === 'ArrowUp' || event.code === 'ArrowDown') {
event.preventDefault();
}
}
}
customElements.define('predictive-search', PredictiveSearch);