← back to Dw Theme Boost Fix

assets/dw-grid-control.js

136 lines

/**
 * DW Grid Control — Inline grid column selector for collection pages
 * Positioned at top-left directly above the product grid
 * Only appears on pages with a product image grid
 */
(function() {
  'use strict';
  /* === DW 2026-06-25 CONSOLIDATION: this control is SUPERSEDED, hard-disabled ===
     dw-boost-overrides.liquid now owns the single density slider that targets
     Boost's real grid. This legacy control injected a SECOND control on the same
     .boost-sd__product-list (already CSS-hidden via `.dw-gc{display:none}` in the
     overrides) and was a competing localStorage('dw-grid-cols') writer. Returning
     early stops the two layers fighting. Reversible: remove this return to restore. */
  return;
  /* eslint-disable no-unreachable */
  var path = window.location.pathname;
  if (!path.startsWith('/collections/')) return;
  if (path.indexOf('/products/') !== -1) return;

  var STORAGE_KEY = 'dw-grid-cols';
  var DEFAULT = 3;
  var MIN = 1;
  var MAX = 8;
  var saved = parseInt(localStorage.getItem(STORAGE_KEY)) || DEFAULT;
  var attempts = 0;

  function findGrid() {
    var selectors = [
      '.boost-pfs-filter-products',
      '.boost-sd__product-list',
      '[data-boost-products]',
      '.product-grid',
      '.collection-products',
      '.product-loop',
      '.collection-grid',
      '#product-loop',
      '.product-list--collection'
    ];
    for (var i = 0; i < selectors.length; i++) {
      var el = document.querySelector(selectors[i]);
      if (el && el.children.length > 2) return el;
    }
    // Fallback: container with 4+ product links
    var containers = document.querySelectorAll('[class*="product"]');
    for (var j = 0; j < containers.length; j++) {
      if (containers[j].querySelectorAll('a[href*="/products/"]').length >= 4 && containers[j].children.length >= 4)
        return containers[j];
    }
    return null;
  }

  function applyGrid(container, cols) {
    container.style.display = 'grid';
    container.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';
    container.style.gap = '4px';
    var imgWidth = container.offsetWidth / cols;
    container.style.paddingRight = imgWidth + 'px';
    var ch = container.children;
    for (var i = 0; i < ch.length; i++) {
      ch[i].style.width = '100%';
      ch[i].style.maxWidth = '100%';
      ch[i].style.flex = 'none';
      ch[i].style.float = 'none';
      // Hide product names when grid > 4 columns
      var nameEls = ch[i].querySelectorAll('[class*="title"] a, [class*="product-title"], [class*="product-name"]');
      for (var j = 0; j < nameEls.length; j++) {
        nameEls[j].style.display = cols > 4 ? 'none' : '';
      }
    }
  }

  function createControl(container) {
    var style = document.createElement('style');
    style.textContent = [
      '.dw-gc{display:inline-flex;align-items:center;gap:8px;padding:6px 16px;margin:0 0 6px;font-family:-apple-system,BlinkMacSystemFont,sans-serif;font-size:11px;user-select:none;background:#fff;border:1.5px solid #000;border-radius:999px}',
      '.dw-gc-lbl{color:#000;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px}',
      '.dw-gc-slider{-webkit-appearance:none;width:140px;height:3px;background:#ccc;border-radius:2px;outline:none;cursor:pointer}',
      '.dw-gc-slider::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;background:#000;border-radius:50%;cursor:pointer}',
      '.dw-gc-slider::-moz-range-thumb{width:16px;height:16px;background:#000;border-radius:50%;cursor:pointer;border:none}',
      '.dw-gc-val{color:#000;font-weight:700;font-size:14px;min-width:16px;text-align:center}',
    ].join('');
    document.head.appendChild(style);

    var bar = document.createElement('div');
    bar.className = 'dw-gc';

    var label = document.createElement('span');
    label.className = 'dw-gc-lbl';
    label.textContent = 'Grid';
    bar.appendChild(label);

    var slider = document.createElement('input');
    slider.type = 'range';
    slider.className = 'dw-gc-slider';
    slider.min = MIN;
    slider.max = MAX;
    slider.value = saved;
    bar.appendChild(slider);

    var val = document.createElement('span');
    val.className = 'dw-gc-val';
    val.textContent = saved;
    bar.appendChild(val);

    slider.addEventListener('input', function() {
      var v = parseInt(this.value);
      saved = v;
      val.textContent = v;
      localStorage.setItem(STORAGE_KEY, v);
      applyGrid(container, v);
    });

    // Insert directly above the grid, top-left
    container.parentNode.insertBefore(bar, container);
    applyGrid(container, saved);
  }

  function init() {
    var grid = findGrid();
    if (grid) {
      createControl(grid);
      new MutationObserver(function() {
        applyGrid(grid, parseInt(localStorage.getItem(STORAGE_KEY)) || DEFAULT);
      }).observe(grid, { childList: true });
    } else if (++attempts < 50) {
      setTimeout(init, 200);
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function() { setTimeout(init, 500); });
  } else {
    setTimeout(init, 500);
  }
})();