Browser API
  • Browser API
    • Getting Started
    • Examples
      • Combos
      • Bundles
      • Bundle builders
      • Kits
      • Looks
      • Common
    • API Reference
    • API Events
    • Release history
    • Why PickyStory
    • License
Powered by GitBook
On this page
  • Combos
  • Bundles
  • Bundle builders
  • Kits
  • Looks
  • Common

Was this helpful?

  1. Browser API

Examples

These examples show how Browser API can be leveraged to create custom widget implementations to display combos, bundles, and bundle builders.

Combos

const renderCombo = (containerSelector) => {
  // Grab the API client, a location and a combo
  const { client } = window.pickystory
  const location = client.getLocations('combos').shift()
  const combo = location.deals.shift()

  // Find the designated slot in the page and add a title and product cards
  const container = document.querySelector(containerSelector)
  const header = document.createElement('h2')
  header.textContent = 'COMBO'
  container.append(header)
  for (let product of combo.products) {
    renderProductCard(product, container)
  }

  // Render the ATC button and specify its action
  renderAddToCart(container, async (selections) => {
    const variants = combo.getVariantsForSelections(selections)
    await combo.addVariantsToCart(variants, 1)
  })
}

Bundles

const renderBundle = (containerSelector) => {
  // Grab the API client, a location and a bundle
  const { client } = window.pickystory
  const location = client.getLocations('bundles').shift()
  const bundle = location.deals.shift()

  // Find the designated slot in the page and add a title and product cards
  const container = document.querySelector(containerSelector)
  const header = document.createElement('h2')
  header.textContent = 'BUNDLE'
  container.append(header)
  for (let product of bundle.products) {
    renderProductCard(product, container)
  }

  // Render the ATC button and specify its action
  renderAddToCart(container, async (selections) => {
    const variants = bundle.getVariantsForSelections(selections)
    await bundle.addVariantsToCart(variants, 1)
  })
}

Bundle builders

const renderBuilder = (containerSelector) => {
  // Grab the API client, a location and a builder
  const { client } = window.pickystory
  const location = client.getLocations('builders').shift()
  const builder = location.deals.shift()

  // Find the designated slot in the page and add a title and product cards
  const container = document.querySelector(containerSelector)
  const header = document.createElement('h2')
  header.textContent = 'BUILDER'
  container.append(header)
  for (let product of builder.products) {
    renderProductCard(product, container)
  }

  // Render the ATC button and specify its action
  renderAddToCart(container, async (selections) => {
    const variants = builder.getVariantsForSelections(selections)
    await builder.addVariantsToCart(variants, 1)
  })
}

Kits

Coming soon!

Looks

Coming soon!

Common

For the purpose of this demo, we assume widget slots have been added to the store HTML as below:

<div id="api-combo-container"></div>
<div id="api-bundle-container"></div>
<div id="api-builder-container"></div>
<div id="api-kit-container"></div>
<div id="api-look-container"></div>
/**
 * Render a card containing product title, image and options
 */
const renderProductCard = (product, container) => {
  // Show the title and the product image using simple <div>, <h3> and <img> tags
  const productDiv = document.createElement('div')
  container.append(productDiv)
  const title = document.createElement('h3')
  productDiv.append(title)
  title.textContent = product.title
  const image = document.createElement('img')
  productDiv.append(image)
  image.height = 100
  image.width = 100
  image.src = product.images[0].src

  // Show product options and their values as dropdowns using <select>
  for (let option of product.options) {
    const select = document.createElement('select')
    productDiv.append(select)
    select.name = option.name
    select.setAttribute('product-position', product.position)
    select.setAttribute('option-position', option.position)
    select.classList.add('picky-option')
    for (let value of option.values) {
      const option = document.createElement('option')
      select.append(option)
      option.value = value
      option.textContent = value
    }
  }
}

/**
 * Render a sample Add To Cart button
 */
const renderAddToCart = (container, onAddSelections, callToAction = 'ADD') => {
  // Create a simple button and style it a bit
  const button = document.createElement('button')
  container.append(button)
  button.type = 'button'
  button.textContent = callToAction
  Object.entries({
    width: '100%', 'text-align': 'center', background: 'black', color: 'white', height: '40px'
  }).forEach(([key, value]) => button.style.setProperty(key, value))

  // Collect product option values from the relevant <select> elements
  button.onclick = async () => {
    const selections = [...container.querySelectorAll('.picky-option')]
      .reduce((result, node) => {
        const productPosition = parseInt(node.getAttribute('product-position'), 10)
        const optionPosition = parseInt(node.getAttribute('option-position'), 10)
        let product = result.find(({ position }) => position === productPosition)
        if (!product) {
          product = { position: productPosition }
          result.push(product)
        }
        const optionAlias = 'option' + optionPosition
        product[optionAlias] = node.value
        return result
      }, [])

    // Use a naive opacity effect while cart addition is in progress
    button.disabled = true
    button.style.setProperty('opacity', '0.4')

    // An async click handler must be provided
    if (typeof onAddSelections === 'function') {
      await onAddSelections(selections)
    }

    button.disabled = false
    button.style.setProperty('opacity', '1')
  }
}

(() => {
// A simple way of activating the widget once the API becomes available
  let apiWaitCount = 0
  const interval = window.setInterval(() => {
    ++apiWaitCount
    if (window?.pickystory?.client) {
      clearInterval(interval)
      renderCombo('#api-combo-container')
      renderBundle('#api-bundle-container')
      renderBuilder('#api-builder-container')
    } else if (apiWaitCount > 50) clearInterval(interval)
  }, 50)
})()
PreviousGetting StartedNextAPI Reference

Last updated 3 years ago

Was this helpful?