{"id":20390316,"url":"https://github.com/the-couch/richer","last_synced_at":"2025-04-12T11:21:27.541Z","repository":{"id":87761745,"uuid":"101497572","full_name":"the-couch/richer","owner":"the-couch","description":"jquery free ajax cart for shopify","archived":false,"fork":false,"pushed_at":"2017-09-04T17:30:26.000Z","size":1851,"stargazers_count":33,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T06:11:16.088Z","etag":null,"topics":["ajax","cart","shopify","slate"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/the-couch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-26T16:18:59.000Z","updated_at":"2024-02-14T07:04:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"bf1be9f4-fdc4-4268-92a1-1caae9ad5957","html_url":"https://github.com/the-couch/richer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-couch%2Fricher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-couch%2Fricher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-couch%2Fricher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-couch%2Fricher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/the-couch","download_url":"https://codeload.github.com/the-couch/richer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248558128,"owners_count":21124223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ajax","cart","shopify","slate"],"created_at":"2024-11-15T03:24:12.058Z","updated_at":"2025-04-12T11:21:27.535Z","avatar_url":"https://github.com/the-couch.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Richer\n\n\n\n[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](http://standardjs.com)\n\n## What is it?\nThis library is built on top of [slater](https://github.com/the-couch/slater) (which is a fork of shopify [slate](https://github.com/Shopify/slate)). It is based on the old implementation of the [Timber](https://github.com/Shopify/Timber) depreciated richcart. The idea behind this comes from Slate and Timber both being tied to jQuery and wanting to build something that could be used independent of that.\n\n\u003cimg src=\"https://raw.githubusercontent.com/the-couch/richer/master/richer.gif\" style=\"width: 620px; margin: 2em 0;\"/\u003e\n\n## Using It\nWe use richer to handle API requests to the shopify AJAX cart. How you implement it is entirely up to you. We expose a couple of common routes that allow you to easily handle updating/refreshing/generating your ajax cart.\n\nI'll outline a number of examples in YOYO below\n\n\n### Initialize a cart\n```javascript\nimport RicherAPI from 'richer'\n\n// Some DOM defaults\nconst defaults = {\n  addToCart: '.js-add-to-cart', // classname\n  addToCartForm: 'AddToCartForm', // id\n  cartContainer: 'CartContainer', // id\n  cartCounter: 'CartCounter', // id\n  items: []\n}\n\nconst config = Object.assign({}, defaults, options)\n\nconst dom = {\n  addToCartForm: document.getElementById(config.addToCartForm),\n  cartContainer: document.getElementById(config.cartContainer),\n  cartCounter: document.getElementById(config.cartCounter)\n}\n\nRicherAPI.getCart(cartUpdateCallback)\n\n// Updates a cart number and builds our cart\nconst cartUpdateCallback = (cart) =\u003e {\n  updateCount(cart)\n  buildCart(cart)\n}\n\nconst updateCount = (cart) =\u003e {\n  const counter = dom.cartCounter\n  counter.innerHTML = cart.item_count\n}\n\nconst buildCart = (cart) =\u003e {\n  const cartContainer = dom.cartContainer\n  cartContainer.innerHTML = null\n\n  if (cart.item_count === 0) {\n    cartContainer.innerHTML = `\u003cp\u003eWe're sorry your cart is empty\u003c/p\u003e`\n    return\n  }\n\n  var el = cartBlock(cart.items, cart, update)\n\n  function cartBlock (items, cart, qtyControl) {\n    return yo`\n      \u003cdiv class='r-cart'\u003e\n        ${items.map((item, index) =\u003e {\n          const product = cleanProduct(item, index, config)\n          return yo`\n            \u003cdiv class=\"r-cart__product f jcb\"\u003e\n              \u003cdiv\u003e\n                \u003cimg src='${product.image}' alt='${product.name}' /\u003e\n              \u003c/div\u003e\n              \u003cdiv class=\"r-cart__product_info\"\u003e\n                \u003ch5\u003e\u003ca href='${product.url}'\u003e${product.name}\u003c/a\u003e\u003c/h5\u003e\n                ${product.variation ? yo`\u003cspan\u003e${product.variation}\u003c/span\u003e` : null}\n                ${realPrice(product.discountsApplied, product.originalLinePrice, product.linePrice)}\n                ${yo`\n                  \u003cdiv class=\"r-cart__qty f jcb\"\u003e\n                    \u003cdiv class=\"r-cart__qty_control\" onclick=${() =\u003e qtyControl(product, product.itemMinus)}\u003e\n                      \u003csvg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"\u003e\u003cpath fill=\"#444\" d=\"M17.543 11.029H2.1A1.032 1.032 0 0 1 1.071 10c0-.566.463-1.029 1.029-1.029h15.443c.566 0 1.029.463 1.029 1.029 0 .566-.463 1.029-1.029 1.029z\"/\u003e\u003c/svg\u003e\n                    \u003c/div\u003e\n                    \u003cspan\u003e${product.itemQty}\u003c/span\u003e\n                    \u003cdiv class=\"r-cart__qty_control\" onclick=${() =\u003e qtyControl(product, product.itemAdd)}\u003e\n                      \u003csvg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" class=\"icon\"\u003e\u003cpath fill=\"#444\" d=\"M17.409 8.929h-6.695V2.258c0-.566-.506-1.029-1.071-1.029s-1.071.463-1.071 1.029v6.671H1.967C1.401 8.929.938 9.435.938 10s.463 1.071 1.029 1.071h6.605V17.7c0 .566.506 1.029 1.071 1.029s1.071-.463 1.071-1.029v-6.629h6.695c.566 0 1.029-.506 1.029-1.071s-.463-1.071-1.029-1.071z\"/\u003e\u003c/svg\u003e\n                    \u003c/div\u003e\n                  \u003c/div\u003e\n                `}\n              \u003c/div\u003e\n            \u003c/div\u003e\n          `\n        })}\n        ${subTotal(cart.total_price, cart.total_cart_discount)}\n      \u003c/div\u003e\n    `\n  }\n\n  function subTotal (total, discount) {\n    // TODO: handling discounts\n    const totalPrice = slate.Currency.formatMoney(total)  // eslint-disable-line\n    return yo`\n      \u003cdiv\u003e\n        \u003ch5\u003eSubtotal: ${totalPrice}\u003c/h5\u003e\n      \u003c/div\u003e\n    `\n  }\n\n  function realPrice (discountsApplied, originalLinePrice, linePrice) {\n    if (discountsApplied) {\n      return yo`\n        \u003cdiv\u003e\n          \u003csmall className='strike'\u003e${originalLinePrice}\u003c/small\u003e\n          \u003cbr /\u003e\u003cspan\u003e${linePrice}\u003c/span\u003e\n        \u003c/div\u003e\n      `\n    } else {\n      return yo`\n        \u003cspan\u003e${linePrice}\u003c/span\u003e\n      `\n    }\n  }\n\n  function update (item, quantity) {\n     RicherAPI.changeItem((item.index + 1), quantity, refreshCart)\n  }\n\n  function refreshCart (cart) {\n    let newCart = cartBlock(cart.items, cart, update)\n    yo.update(el, newCart)\n  }\n\n  cartContainer.appendChild(el)\n}\n\n```\n\n\n\n```javascript\nimport RicherAPI from 'richer'\n\nconst dom = {\n  addToCartForm: document.getElementById('AddToCartForm'),\n}\n\nconst AddToCart = () =\u003e {\n  const form = dom.addToCartForm\n\n  form.addEventListener('submit', (e) =\u003e {\n    e.preventDefault()\n    form.classList.remove('is-added')\n    form.classList.add('is-adding')\n\n    RicherAPI.addItemFromForm(e.target, itemAddedCallback, itemErrorCallback)\n  })\n\n  const itemAddedCallback = () =\u003e {\n    RicherAPI.getCart(cartUpdateCallback)\n  }\n\n  const itemErrorCallback = (XMLHttpRequest, textStatus) =\u003e {\n    console.log('error family')\n  }\n}\n\nconst cartUpdateCallback = (cart) =\u003e {\n  updateCount(cart)\n  buildCart(cart)\n  RicherAPI.onCartUpdate(cart)\n}\n```\n\n\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-couch%2Fricher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthe-couch%2Fricher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-couch%2Fricher/lists"}