JS examples

Trap focus

It’s important to consider keyboard users when using dynamic modules, such as a modal or popover. If they take over the full screen then it’s best to limit the user’s keyboard access to that module so they don’t end up tabbing through hidden elements on the page.

Here’s an example of a modal that traps the keyboard focus inside the element when open, and removes the trap when closed.

slate.a11y.trapFocus({ options });
slate.a11y.removeTrapFocus({ options });
Parameters Type Description
$container jQuery object Container to trap focus within
namespace string Namespace used for new focus event handler
$elementToFocus jQuery object (optional) Set an element to be selected after the focus is trapped. Only used in trapFocus.
var $modal = $('#Modal');

$('#TriggerModal').on('click', function() {
  $modal.addClass('is-active');

  slate.a11y.trapFocus({
    $container: $modal,
    namespace: 'modal',
    $elementToFocus: $modal.find('input[type="text"]')
  });
});

$('#CloseModal').on('click', function() {
  $modal.removeClass('is-active');

  slate.a11y.removeTrapFocus({
    $container: $modal,
    namespace: 'modal'
  });
});

Responsive tables and videos

Tables and video embeds do not natively scale well on smaller screens. Slate adds a wrapper class to tables and video embeds that are loaded in from a rich text editor.

Parameters Type Description
$tables jQuery object <table> elements to be made responsive
tableWrapperClass string CSS class to apply on the <div> that will wrap each targeted <table> element
$iframes jQuery object <iframe> elements to be made responsive
iframeWrapperClass string CSS class to apply on the <div> that will wrap each targeted <iframe> element
// Wrap RTE tables to make them scrollable
var tableSelectors = '.rte table';

slate.rte.wrapTable({
  $tables: $(tableSelectors),
  tableWrapperClass: 'rte__table-wrapper',
});

// Wrap RTE videos to make them responsive
var videoSelectors =
  '.rte iframe[src*="youtube.com/embed"],' +
  '.rte iframe[src*="player.vimeo"]';

slate.rte.wrapIframe({
  $iframes: $(videoSelectors),
  iframeWrapperClass: 'rte__video-wrapper'
});

Format currency

Slate ships JavaScript to mimic Shopify money formats. This makes handling product prices and cart items in JS simple. (View currency.js source).

Slate maps the shop’s money format — defined in Liquid — to a JavaScript variable in layouts/theme.liquid so it can be used regardless of file type.

In layouts/theme.liquid:

window.theme.moneyFormat: {{ shop.money_format | json }};
Parameters Type Description
cents string Price in cents
format string shop.money_format setting

In this example, shop.money_format is ${{amount}} so 1999 cents would be formatted as $19.99.

var itemPrice = 1999; // cents
slate.Currency.formatMoney(itemPrice, theme.moneyFormat);

// Returns string
'$19.99'

Image helpers

Command Usage
preload slate.Images.preload(images, size)
imageSize slate.Images.imageSize(src)
getSizedImageUrl slate.Images.getSizedImageUrl(src, size)
removeProtocol slate.Images.removeProtocol(path)

preload

Preload a single image or an array of images at a given size. A common use for preloading is reducing the loading delay when enlarging a thumbnail.

Parameters Type Description
images array or string Single image URL or list of image URLs
size string Size of image to request
slate.Image.preload(['image-url-1.jpg', 'image-url-2.jpg'], '1024x1024');

imageSize

Get the size of an image based on the URL.

Parameters Type Description
src string Image URL
slate.Image.imageSize('https://cdn.shopify.com/s/files/big-ol-image_480x480.jpeg');

// Returns string
'480x480'

getSizedImageUrl

Adds a Shopify size attribute to a URL

Parameters Type Description
src string Image URL
size string Custom size
slate.Image.getSizedImageUrl('https://cdn.shopify.com/s/files/big-ol-image.jpeg', '250x250');

// Returns string
'https://cdn.shopify.com/s/files/big-ol-image_250x250.jpeg'

removeProtocol

Parameters Type Description
path string Image URL
slate.Image.removeProtocol('https://cdn.shopify.com/s/files/big-ol-image_480x480.jpeg')

// Returns string
'//cdn.shopify.com/s/files/big-ol-image_480x480.jpeg'

Product variants

The Slate theme has two script files to manage the display of product variants:

Script Location Description
variant.js scripts/slate Handles variant change events in any forms that add to cart
product.js scripts/sections Behaviour coupled to the theme code of product-based sections

variant.js

Slate separates product variant options into multiple <select> elements. When a variant changes, variant.js updates the master select. The master select is the default <select> element that contains all variant IDs needed to properly submit the form.

Slate’s variant.js also triggers a number of custom events to handle various state changes:

Events Trigger condition
variantChange When a variant option’s <select> element is changed.
variantImageChange When the selected variant has a featured image which is not currently displayed.
variantPriceChange When the selected variant has a price or compare_at_price which is different than what is currently displayed.

product.js

The theme-specific script of product.js has a number of methods that listen for the above custom events. Each function has access to the newly selected variant object in evt.variant. Customize these functions to fit your theme’s desired behaviour.

Methods Description
updateAddToCartState() Update the add to cart button text and enabled/disabled/sold out state
updateProductImage() Replace the main product image src with the associated variant image if it exists
updateProductPrices() Updates the product price and compare_at_price when necessary

Cart helpers

In order for customers to build a cart, their browsers must support cookies.

Methods Description
cookiesEnabled() Returns true if the browser supports cookies.

In the theme scaffolding, classes for supports-cookies and supports-no-cookies are toggled on the html element so theme developers can show/hide different content based on browser support.

if (slate.cart.cookiesEnabled()) {
  document.documentElement.className = document.documentElement.className.replace('supports-no-cookies', 'supports-cookies');
}

Section events

Slate comes with a section.js file to help Sections communicate with Shopify’s Theme editor JavaScript API.

Methods Description
onUnload() A section has been deleted or is being re-rendered.
onSelect() User has selected the section in the editor’s sidebar.
onDeselect() User has deselected the section in the editor’s sidebar.
onReorder() User has changed the section’s order in the editor’s sidebar.
onBlockSelect() User has selected the block in the editor’s sidebar.
onBlockDeselect() User has deselected the block in the editor’s sidebar.

As an example, product.js uses the onUnload method to remove all namespaced events when the section is deleted or re-rendered.

Product.prototype = $.extend({}, Product.prototype, {
  onUnload: function() {
    this.$container.off(this.settings.eventNamespace);
  }
});

Register sections

Slate provides a register method to properly scope the various Sections used in a theme.

sections.register(type, constructor);
Parameters Type Description
type string Unique section type defined by theme developer
constructor function Section constructor run in Theme editor and on storefront

Slate follows a convention of wrapping the content of a Section file in an element with a data-section-type attribute. The type is taken from this attribute’s value.

// From sections/product.liquid
<div data-section-id="{{ section.id }}" data-section-type="product">
  ...
</div>

In the theme.js file, you must import the Section specific JavaScript with the // =require helper, more information here, as it will contain your constructor.

// =require sections/product.js

$(document).ready(function() {
  var sections = new slate.Sections();
  sections.register('product', theme.Product);
});