Product Image in Cart Page

Description

  • fix cart page: product shows a random image, not the primary image
  • buy me a coffee

07.26c16v2 Product Image in Cart Page

#1. Install Code

You can use this code to Code Injection > Footer

<!-- 07.26c16v2 Product Image in Cart Page -->
<script>
(function () {
  var productCache = {};

  function slug(s){ return String(s).toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,''); }

  function getProductData(url) {
    var key = url.split('?')[0];
    if (productCache[key]) return productCache[key];
    productCache[key] = fetch(key + '?format=json&noredirect', { headers: { 'Accept': 'application/json' } })
      .then(function (r) { return r.json(); })
      .then(function (j) { return j.item || null; })
      .catch(function () { return null; });
    return productCache[key];
  }

  function findRow(imgEl) {
    var el = imgEl;
    for (var i = 0; i < 8 && el; i++) {
      if (el.querySelector && el.querySelector('a[href*="/p/"]')) return el;
      el = el.parentElement;
    }
    return null;
  }
  function parseVariantText(row) {
    var vEl = row.querySelector('.cart-row-variants');
    if (!vEl) return null;
    var txt = (vEl.textContent || '').trim();
    if (!txt) return null;
    var attrs = {};
    txt.split(/[\n\u2022|]/).forEach(function (part) {
      var idx = part.indexOf(':');
      if (idx > -1) attrs[slug(part.slice(0, idx))] = slug(part.slice(idx + 1));
      else if (part.trim()) attrs['_' + Object.keys(attrs).length] = slug(part);
    });
    return Object.keys(attrs).length ? attrs : null;
  }

  function assetBase(im) {
    return (im && im.assetUrl) ? im.assetUrl.split('?')[0] : null;
  }
  function pickAsset(item, wantAttrs) {
    var gallery = item.items || [];
    var mainBase = item.assetUrl ? item.assetUrl.split('?')[0] : null;
    if (!wantAttrs) return mainBase;

    var wantVals = Object.keys(wantAttrs).map(function (k) { return wantAttrs[k]; });
    for (var i = 0; i < gallery.length; i++) {
      var base = assetBase(gallery[i]);
      if (!base) continue;
      var fn = slug(base.split('/').pop());
      if (wantVals.every(function (v) { return v && fn.indexOf(v) > -1; })) return base;
    }
    var variants = item.variants || [];
    for (var k = 0; k < variants.length; k++) {
      var va = variants[k].attributes || {};
      var vSlugs = Object.keys(va).map(function (kk) { return slug(va[kk]); });
      if (wantVals.every(function (v) { return vSlugs.indexOf(v) > -1; })) {
        if (variants[k].image && variants[k].image.assetUrl) return variants[k].image.assetUrl.split('?')[0];
        if (gallery[k]) return assetBase(gallery[k]);
      }
    }
    return mainBase;
  }

  function fixCart() {
    document.querySelectorAll('.cart-row-img').forEach(function (imgDiv) {
      var row = findRow(imgDiv);
      var link = row && row.querySelector('a[href*="/p/"]');
      if (!link) return;
      var wantAttrs = parseVariantText(row);
      getProductData(link.getAttribute('href')).then(function (item) {
        if (!item) return;
        var newBase = pickAsset(item, wantAttrs);
        if (!newBase) return;
        var cur = imgDiv.getAttribute('style') || '';
        var m = cur.match(/url\(["']?([^"')]+)/);
        var curBase = m ? m[1].split('?')[0] : '';
        if (curBase === newBase) return;
        var fmt = (m && /[?&]format=[^&]+/.test(m[1]))
          ? m[1].match(/[?&]format=[^&]+/)[0].replace('&', '?')
          : '?format=300w';
        imgDiv.style.backgroundImage = 'url("' + newBase + fmt + '")';
      });
    });
  }

  fixCart();
  new MutationObserver(fixCart).observe(document.body, { childList: true, subtree: true });
})();
</script>

07.26c16v2 Product Image in Cart Page

#2. Customize

nothing now

Buy me a coffee