Customizing JavaScript

Plan: Stencil Developer

Lesson 12 of 28 · 30 min

Cornerstone Theme Pages

Most Cornerstone theme page template files located in templates/pages/ have a corresponding .js file in assets/js/theme/. These JavaScript files contain event handlers and logic for managing page-specific elements and actions.

For example, assets/js/theme/product.js corresponds to templates/pages/product.html and contains a productReviewHandler() and bulkPricingHandler(). These functions are implemented within a derived Product class which extends the PageManager class. This same pattern is repeated in all assets/js/theme/*.js files.

By default, all derived PageManager classes contain an onReady method functionally similar to JQuery.ready(). Additionally, certain pages have unique event handlers. For example, the setApplePaySupport function in assets/js/cart.js is executed and variables like this.$cartContent are populated when the DOM is ready.

Developers can customize and enhance page behavior and functionality by editing code within these event handlers or by creating their own event handlers.

Modifying a page’s JavaScript

In this example, we will add some “Hello World!” text to the product page’s onReady event. We’ll first add a call to the function. Then, we will implement the function itself.

First, implement the helloWorld() function by adding it to the Product class just after the closing onReady() bracket.

export default class Product extends PageManager {
constructor(context) {
super(context);
this.url = window.location.href;
this.$reviewLink = $('[data-reveal-id="modal-review-form"]');
this.$bulkPricingLink = $('[data-reveal-id="modal-bulk-pricing"]');
}
onReady() {
// ...
// Example Code
this.helloWorld();
}
// Example Code
helloWorld() {
console.log("[assets/js/theme/product.js]: Hello World!");
}
// ...
}

Next, in assets/js/theme/product.js file, add a call to this.helloWorld() to the bottom of the onReady() method, which we’ll implement in the step below.

export default class Product extends PageManager {
constructor(context) {
super(context);
this.url = window.location.href;
this.$reviewLink = $('[data-reveal-id="modal-review-form"]');
this.$bulkPricingLink = $('[data-reveal-id="modal-bulk-pricing"]');
}
onReady() {
// ...
// Example Code
this.helloWorld();
}
// ...
}

In your browser, refresh any product details pop-up or page to see your new “Hello World” message.

Handlebars Context

Bringing in Handlebars context

You can inject any variables from the Handlebars context into your client-side JavaScript by using the {{inject…}} expression.

{{inject 'productThumbSize' theme_settings.productthumb_size}}

To inject theme settings.productthumb_size_into the product page’s context, add {{inject 'productThumbSize' theme_settings.productthumb_size}} just under {{#partial "page"}} in templates/pages/product.html:

product:
videos:
limit: {{theme_settings.productpage_videos_count}}
reviews:
limit: {{theme_settings.productpage_reviews_count}}
related_products:
limit: {{theme_settings.productpage_related_products_count}}
similar_by_views:
limit: {{theme_settings.productpage_similar_by_views_count}}
{{#partial "page"}}
<!-- Context Injection Example: -->
{{inject 'productThumbSize' theme_settings.productthumb_size}}
<!-- End Context Injection Example -->
<!-- ... -->
{{/partial}}
{{> layout/base}}

The injected productThumbSize property can then be accessed from product.js by calling this.context.productThumbSize.

export default class Product extends PageManager {
constructor(context) {
super(context);
this.url = window.location.href;
this.$reviewLink = $('[data-reveal-id="modal-review-form"]');
this.$bulkPricingLink = $('[data-reveal-id="modal-bulk-pricing"]');
}
onReady() {
//...
// Example Code
this.helloWorld();
}
// Example Code
helloWorld() {
console.log("[assets/js/theme/product.js]: Hello World!");
console.log("[assets/js/theme/product.js]: " + this.context.productThumbSize);
}
// ...
}

Note: That the console.log(this.context.themeImageSizes); statement will report the configured image size, following the “Hello World!” message previously defined in the Customizing JavaScript for Individual Pages above.

[/assets/js/theme/product.js]: Hello World!
product.js:63 [/assets/js/theme/product.js]: 100x100

Installing Libraries

Once you have installed the default Stencil theme, you can add custom JavaScript libraries with npm. The code examples below show how to install the moment.js library:

npm install moment

Next you can import modules from the library into the theme’s JavaScript files. For instance, you can add the following import statement to assets/js/theme/product.js to load moment on the product page:

import moment from 'moment'

After importing the module, you can access it later in the file. Add the following to the onReady method in assets/js/theme/product.js to display an alert with the current time when the page is ready.

window.alert('Hello world, it is now ' + moment().format('LTS'))

The resulting alert will look like:

Alert with current time