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);

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);
Was this article helpful to you?