{"_id":"5859b025941f6d2d00e9b899","user":"55a6caa022cfa321008e01d6","parentDoc":null,"project":"55a6e72e8cc73e0d00096635","version":{"_id":"55a6e72f8cc73e0d00096638","project":"55a6e72e8cc73e0d00096635","hasReference":false,"__v":29,"hasDoc":true,"createdAt":"2015-07-15T23:05:19.125Z","releaseDate":"2015-07-15T23:05:19.125Z","categories":["55a6e7308cc73e0d00096639","55b7ed07aea7c8190058badb","5604567c0c78b00d0039b191","5605e6f23a93940d002b3e4a","5605f2bba4574a0d00811365","5605f309a4574a0d00811366","5608e3b98aedf50d0004cf8f","5608e4318aedf50d0004cf90","5608e6b5a7cc2f0d00d9754d","5608e6d331beb60d001b6560","5608f879a7cc2f0d00d97580","560b097887b71d0d000d3bd9","560b13cbafa0990d00979545","560b5cbec341310d00de2a01","560b5cd0c341310d00de2a02","566a35b81e08750d00a0c49b","566a3e8503b4b20d00d02a4a","567889d307bf6a0d0083edc8","569c8b7c15bb390d00db6f9d","56b254dc65ddf50d0076ba8f","57a8ebc4cdeea20e001d2a63","57e48a4000c8680e00fae6e7","5808216773557d0f00a1e428","58105ad54a8aa50f00aa4cba","58105bf298aea40f00afa3ba","58105f548a4aed0f00d67536","581061b898aea40f00afa3be","584b3de7e5f3a42300df6ef7","596839a75965d400155bb750"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"category":{"_id":"584b3de7e5f3a42300df6ef7","project":"55a6e72e8cc73e0d00096635","__v":0,"version":"55a6e72f8cc73e0d00096638","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-12-09T23:27:35.491Z","from_sync":false,"order":16,"slug":"javascript-api","title":"JavaScript Customization"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-12-20T22:26:45.225Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":1,"body":"Stencil themes use several common techniques to manage and deliver JavaScript assets to a shopper's Web browser. This page provides a very brief overview of these concepts for context, then outlines specific options for adding JavaScript to your theme. It covers:\n\n* [Bundling and Minification](#bunmin)\n* [Development Options](#devopt)\n* [Using npm (Node Package Manager)](#npm)\n* [Place Modules in /assets/js/](#assetsjsdir)\n* [Theme-Specific JavaScript Modules](#themedir)\n* [Mapping Page Types to JavaScript Modules](#map)\n* [Summary](#qed)\n\n## <span id=\"bunmin\"> Bundling and Minification </span>\n\nA small Web application, such as an ecommerce theme, can include rich user interactions that depend on many small JavaScript and CSS modules. If we were to embed each of the JavaScript modules in a template file with a separate `<script>` tag, the shopper's browser would need to make separate HTTP requests to retrieve each module.\n\nIn some cases, it would take longer to set up the HTTP request than to download the small JavaScript module – leading to slower load times. On mobile devices, slow load times can be especially frustrating. \n\n### <span id=\"\"> Bundling </span>\n\nTo solve this problem, modern front-end frameworks will bundle all the JavaScript modules into a single file (a _bundle_), so that the shopper's browser only needs to make a single HTTP request. After the browser has downloaded the bundle of JavaScript modules, the browser will cache them, speeding up the rest of the shopper's session.\n\n### <span id=\"\"> Minification </span>\n\nBeyond reducing the number of HTTP calls required to fetch all the required JavaScript modules, we can reduce the size of the individual JavaScript modules through _minification_. JavaScript minification removes white space and comments, shortens variable and function names, removes dead code, and more. The goal, in all cases, is to reduce the amount of bandwidth necessary to transmit the JavaScript module to the browser. \n\n## <span id=\"devopt\"> Development Options </span>\n\nWhen you add JavaScript to a theme, use one of the following techniques, so that Stencil will automatically bundle and minify your modules:\n\n* **Using npm:** Add third-party JavaScript modules to your theme with <a href=\"https://www.npmjs.com/\" target=\"_blank\">npm</a>, where possible.\n\n* **Place Modules in /assets/js/:** For a JavaScript module that is not distributed via npm, add this module to your theme by creating a subdirectory in `/assets/js/` that contains your module.\n\n* **Theme-Specific JavaScript Modules:** Stencil themes include their own custom JavaScript modules for most page types. You can alter these page-type–specific modules by editing the files in `/assets/js/theme/*.js`.\n\nThese techniques are outlined in the following sections. \n\n## <span id=\"npm\"> Using npm (Node Package Manager) </span>\n\nMany third-party JavaScript components are distributed with <a href=\"https://www.npmjs.com/\" target=\"_blank\">npm</a> (Node Package Manager). When you use the npm command-line utility to add a JavaScript component to your theme, Stencil will automatically bundle and minify the component. To enable this, run each module's `npm install` command from the root directory of your theme.\n\n### <span id=\"\"> Taking Over from npm </span>\n\nnpm facilitates managing third-party JavaScript components by placing each JavaScript component – and any of its dependencies – in the correct directories. However, as a developer, you will still need to edit your theme files to wire up the JavaScript component to expose it on your storefront. You will find several examples of this on the following pages.\n\n## <span id=\"assetsjsdir\"> Place Modules in /assets/js/ </span>\n\nYou can freely create subdirectories within `/assets/js/`, to contain new JavaScript modules. The constraint is that all JavaScript files in each module must use the `.js` file extension.\n\n## <span id=\"themedir\"> Theme-Specific JavaScript Modules </span>\n\nIn your theme's `/assets/js/theme/` subdirectory, you will find a tree of JavaScript files. Each file is a JavaScript module. Some modules are for specific page types. Others are common modules that can be used in other modules. Still others are global modules that are available on every page. \n\n## <span id=\"map\"> Mapping Page Types to JavaScript Modules </span>\n\nTo find the mapping from page types to modules in `/assets/js/theme/`, examine the `PageClasses` object in the file: `/assets/js/app.js`. Each key in this class is a page type, and its value is the entry module for that page type. For example: When the `cart` page type is loaded in the browser, the JavaScript module named `cart` will be loaded. At the top of the `/assets/js/app.js` file, the `cart` module is mapped to `./theme/cart`, which corresponds to `/assets/js/theme/cart.js`.\n\n### <span id=\"\"> Mapping Example in app.js </span>\n\nHere is an excerpt of mappings from `/assets/js/app.js`:\n\n```\nimport 'babel-polyfill';\nimport $ from 'jquery';\nimport async from 'async';\nimport account from './theme/account';\nimport auth from './theme/auth';\nimport blog from './theme/blog';\nimport brand from './theme/brand';\nimport cart from './theme/cart';\nimport category from './theme/category';\nimport contactUs from './theme/contact-us';\nimport compare from './theme/compare';\nimport errors from './theme/errors';\nimport errors404 from './theme/404-error';\nimport giftCertificate from './theme/gift-certificate';\nimport global from './theme/global';\nimport home from './theme/home';\nimport orderComplete from './theme/order-complete';\nimport rss from './theme/rss';\nimport page from './theme/page';\nimport product from './theme/product';\nimport search from './theme/search';\nimport sitemap from './theme/sitemap';\nimport subscribe from './theme/subscribe';\nimport wishlist from './theme/wishlist';\n\nconst PageClasses = {\n    mapping: {\n        'pages/account/orders/all': account,\n...\n        'pages/cart': cart,\n...\n```\n\n### <span id=\"\"> Mapping Example in cart.js </span>\n\nInside the `cart` module (`/assets/js/theme/cart.js`), other modules are imported, and custom JavaScript methods for the cart module are created in the `Cart` class.\n\nHere is an excerpt from the `/assets/js/theme/cart.js` file:\n\n```\nimport PageManager from '../page-manager';\nimport $ from 'jquery';\nimport _ from 'lodash';\nimport giftCertCheck from './common/gift-certificate-validator';\nimport utils from ':::at:::bigcommerce/stencil-utils';\nimport ShippingEstimator from './cart/shipping-estimator';\nimport { defaultModal } from './global/modal';\n\nexport default class Cart extends PageManager {\n\n    loaded(next) {\n        this.$cartContent = $('[data-cart-content]');\n        this.$cartMessages = $('[data-cart-status]');\n        this.$cartTotals = $('[data-cart-totals]');\n        this.$overlay = $('[data-cart] .loadingOverlay')\n        .hide(); \n        this.bindEvents();\n        next();\n    }\n\n    cartUpdate($target) {\n        const itemId = $target.data('cart-itemid');\n        const $el = $(`#qty-${itemId}`);\n        const oldQty = parseInt($el.val(), 10);\n...\n```\n\n## <span id=\"qed\"> Summary </span>\n\nTo review the basics of using JavaScript in your Stencil theme:\n\n* Stencil automatically bundles and minifies JavaScript modules to optimize page performance.\n\n* To insert custom JavaScript on a particular page in your theme, edit the JavaScript module that corresponds to the page's type.\n\n* To add files from third-party JavaScript modules to a theme, use npm, where possible.\n\n* To add JavaScript modules not distributed via npm, you can  create new subdirectories within `/assets/js/`.\n\n* Theme-Specific JavaScript modules are provided in the theme's `/assets/js/theme/` subdirectory.\n\n* To find the mapping between modules in `/assets/js/theme/` and page types, examine the `PageClasses` object contained in `/assets/js/app.js`.","excerpt":"Custom JavaScript","slug":"js-101","type":"basic","title":"Adding JavaScript to Your Theme"}

Adding JavaScript to Your Theme

Custom JavaScript

Stencil themes use several common techniques to manage and deliver JavaScript assets to a shopper's Web browser. This page provides a very brief overview of these concepts for context, then outlines specific options for adding JavaScript to your theme. It covers: * [Bundling and Minification](#bunmin) * [Development Options](#devopt) * [Using npm (Node Package Manager)](#npm) * [Place Modules in /assets/js/](#assetsjsdir) * [Theme-Specific JavaScript Modules](#themedir) * [Mapping Page Types to JavaScript Modules](#map) * [Summary](#qed) ## <span id="bunmin"> Bundling and Minification </span> A small Web application, such as an ecommerce theme, can include rich user interactions that depend on many small JavaScript and CSS modules. If we were to embed each of the JavaScript modules in a template file with a separate `<script>` tag, the shopper's browser would need to make separate HTTP requests to retrieve each module. In some cases, it would take longer to set up the HTTP request than to download the small JavaScript module – leading to slower load times. On mobile devices, slow load times can be especially frustrating. ### <span id=""> Bundling </span> To solve this problem, modern front-end frameworks will bundle all the JavaScript modules into a single file (a _bundle_), so that the shopper's browser only needs to make a single HTTP request. After the browser has downloaded the bundle of JavaScript modules, the browser will cache them, speeding up the rest of the shopper's session. ### <span id=""> Minification </span> Beyond reducing the number of HTTP calls required to fetch all the required JavaScript modules, we can reduce the size of the individual JavaScript modules through _minification_. JavaScript minification removes white space and comments, shortens variable and function names, removes dead code, and more. The goal, in all cases, is to reduce the amount of bandwidth necessary to transmit the JavaScript module to the browser. ## <span id="devopt"> Development Options </span> When you add JavaScript to a theme, use one of the following techniques, so that Stencil will automatically bundle and minify your modules: * **Using npm:** Add third-party JavaScript modules to your theme with <a href="https://www.npmjs.com/" target="_blank">npm</a>, where possible. * **Place Modules in /assets/js/:** For a JavaScript module that is not distributed via npm, add this module to your theme by creating a subdirectory in `/assets/js/` that contains your module. * **Theme-Specific JavaScript Modules:** Stencil themes include their own custom JavaScript modules for most page types. You can alter these page-type–specific modules by editing the files in `/assets/js/theme/*.js`. These techniques are outlined in the following sections. ## <span id="npm"> Using npm (Node Package Manager) </span> Many third-party JavaScript components are distributed with <a href="https://www.npmjs.com/" target="_blank">npm</a> (Node Package Manager). When you use the npm command-line utility to add a JavaScript component to your theme, Stencil will automatically bundle and minify the component. To enable this, run each module's `npm install` command from the root directory of your theme. ### <span id=""> Taking Over from npm </span> npm facilitates managing third-party JavaScript components by placing each JavaScript component – and any of its dependencies – in the correct directories. However, as a developer, you will still need to edit your theme files to wire up the JavaScript component to expose it on your storefront. You will find several examples of this on the following pages. ## <span id="assetsjsdir"> Place Modules in /assets/js/ </span> You can freely create subdirectories within `/assets/js/`, to contain new JavaScript modules. The constraint is that all JavaScript files in each module must use the `.js` file extension. ## <span id="themedir"> Theme-Specific JavaScript Modules </span> In your theme's `/assets/js/theme/` subdirectory, you will find a tree of JavaScript files. Each file is a JavaScript module. Some modules are for specific page types. Others are common modules that can be used in other modules. Still others are global modules that are available on every page. ## <span id="map"> Mapping Page Types to JavaScript Modules </span> To find the mapping from page types to modules in `/assets/js/theme/`, examine the `PageClasses` object in the file: `/assets/js/app.js`. Each key in this class is a page type, and its value is the entry module for that page type. For example: When the `cart` page type is loaded in the browser, the JavaScript module named `cart` will be loaded. At the top of the `/assets/js/app.js` file, the `cart` module is mapped to `./theme/cart`, which corresponds to `/assets/js/theme/cart.js`. ### <span id=""> Mapping Example in app.js </span> Here is an excerpt of mappings from `/assets/js/app.js`: ``` import 'babel-polyfill'; import $ from 'jquery'; import async from 'async'; import account from './theme/account'; import auth from './theme/auth'; import blog from './theme/blog'; import brand from './theme/brand'; import cart from './theme/cart'; import category from './theme/category'; import contactUs from './theme/contact-us'; import compare from './theme/compare'; import errors from './theme/errors'; import errors404 from './theme/404-error'; import giftCertificate from './theme/gift-certificate'; import global from './theme/global'; import home from './theme/home'; import orderComplete from './theme/order-complete'; import rss from './theme/rss'; import page from './theme/page'; import product from './theme/product'; import search from './theme/search'; import sitemap from './theme/sitemap'; import subscribe from './theme/subscribe'; import wishlist from './theme/wishlist'; const PageClasses = { mapping: { 'pages/account/orders/all': account, ... 'pages/cart': cart, ... ``` ### <span id=""> Mapping Example in cart.js </span> Inside the `cart` module (`/assets/js/theme/cart.js`), other modules are imported, and custom JavaScript methods for the cart module are created in the `Cart` class. Here is an excerpt from the `/assets/js/theme/cart.js` file: ``` import PageManager from '../page-manager'; import $ from 'jquery'; import _ from 'lodash'; import giftCertCheck from './common/gift-certificate-validator'; import utils from '@bigcommerce/stencil-utils'; import ShippingEstimator from './cart/shipping-estimator'; import { defaultModal } from './global/modal'; export default class Cart extends PageManager { loaded(next) { this.$cartContent = $('[data-cart-content]'); this.$cartMessages = $('[data-cart-status]'); this.$cartTotals = $('[data-cart-totals]'); this.$overlay = $('[data-cart] .loadingOverlay') .hide(); this.bindEvents(); next(); } cartUpdate($target) { const itemId = $target.data('cart-itemid'); const $el = $(`#qty-${itemId}`); const oldQty = parseInt($el.val(), 10); ... ``` ## <span id="qed"> Summary </span> To review the basics of using JavaScript in your Stencil theme: * Stencil automatically bundles and minifies JavaScript modules to optimize page performance. * To insert custom JavaScript on a particular page in your theme, edit the JavaScript module that corresponds to the page's type. * To add files from third-party JavaScript modules to a theme, use npm, where possible. * To add JavaScript modules not distributed via npm, you can create new subdirectories within `/assets/js/`. * Theme-Specific JavaScript modules are provided in the theme's `/assets/js/theme/` subdirectory. * To find the mapping between modules in `/assets/js/theme/` and page types, examine the `PageClasses` object contained in `/assets/js/app.js`.