JavaScript

General rules

  • All JS for a component should live within an .js file in that component’s directory. JS within these files should not affect any other component. If multiple components must communicate with each other, refer to “Events” below.
  • Any HTML elements that are targeted by JS should have a class prefixed by js-. This reduces the chances of breaking JavaScript by otherwise changing or removing classes or elements without updating the corresponding JS.
  • All components should listen for the 'component-init' event (more details below).
  • jQuery was not included in the library for performance purposes and because it was not needed. Unfortunately it still got included within the Hybris implementation because a lot of out-of-the-box Hybris JS relies on jQuery. That said, it should be kept out of the component library.
  • Any external JS libraries needed within the component library should be added to package.json and added to app.js by listing it within gulpfile.js.

Events

By default, all component JS is limited in scope to affect only that component and runs on document ready. There are multiple use cases when this becomes an issue:

  • when something implementing the component library adds a component to the page after the initial page load, that component’s JS will not get executed again.
  • when one component needs to be aware of and/or react to what another component has done.

Custom events using the ev-emitter package and built upon the global window.componentEvents variable were implemented to solve this.

Events can be emitted with the following:

window.componentEvents.emitEvent('event-name', [{data: value}]);

They can be handled with the following:

window.componentEvents.on('event-name', functionToHandle);

Reference the comments within /src/assets/js/app.js, or other component code (by searching the codebase for componentEvents), for more examples. The rest of this documentation will outline what events currently exist in the component library and what purpose they serve.

Event Data Purpose
'component-init' N/A This is to be emitted by an implementation’s code any time HTML is added to the page after the initial page load. All components will then initialize themselves if they haven’t already (they track their status by use of a class on the element).
'open-modal' id: The ID of the modal. Triggers the opening of the given modal. Reduces duplication of the JS needed to open a modal.
'close-modal' id: The ID of the modal., formReset: Whether or not any forms within the modal should be reset. Triggers the closing of the given modal. Reduces duplication of the JS needed to close a modal.
'modal-change' id: The ID of the modal., action: What the modal is doing (open or close) Allows implementation JS to react to these actions, such as removing validation errors from a form that is getting reset as the modal closes.
'product-compare-open' N/A Triggers the opening of the @product-compare interface.
'product-compare-close' N/A Triggers the closing of the @product-compare interface.
'flyout-change' id: The ID of the header flyout., action: What the flyout is doing (open or close) Allows implementation JS to react to these actions.
'open-search-flyout' N/A Allows implementation JS to open the header’s search flyout.
'open-cart-flyout' N/A Allows implementation JS to open the header’s cart flyout (such as when a product is added to the user’s cart).
'close-search-flyout' N/A Allows implementation JS to close the header’s search flyout.
'close-cart-flyout' N/A Allows implementation JS to close the header’s cart flyout.
'change-cart-icon' action: Whether the cart now has something in it (full) or not (empty) Allows implementation JS to easily update the cart icon in the header as products are added/removed in the cart, changing its state.
'product-control-change' See the @product-controls README for more information. Emitted as the product controls (Wishlist, Compare, etc.) are used so the icons can be updated.
'active-product-variant' N/A Emitted any time the variant in the @product-detail component is updated, allowing other components on the page to update content accordingly.
'pdp-magnification-change' magnification: The magnification being changed to. Emitted any time the magnification for the @product-detail component is updated, allowing it to update its content accordingly.
'customization-options-notify' customizations: An object of customization data. See that component’s README for more information. Used by the @customize component to communicate across that page as different customization options are selected by the user.

File organization/implementation

All JavaScript is aggregated and minified into app.js, which should then get added to every page. It does not differ between brands.