← back to Interiordesignershowroom

public/js/grid.js

50 lines

// Client-side sort + density for any product grid. Reads data-* attributes off the
// server-rendered cards (so the initial paint is SEO-clean) and re-orders in place.
// Both choices persist in localStorage per Steve's standing grid rule.
(function () {
  var grid = document.getElementById('grid');
  var sortSel = document.getElementById('sortSel');
  var densitySel = document.getElementById('densitySel');
  var densityVal = document.getElementById('densityVal');
  if (!grid) return;

  var LS_SORT = 'ids.sort', LS_COLS = 'ids.cols';
  var COL_MIN = 2, COL_MAX = 6, COL_DEFAULT = 4;

  // The slider now sets an explicit COLUMN COUNT (2–6, default 4) on --gcols,
  // which #grid consumes as `repeat(var(--gcols), 1fr)`. Grid starts at 4 across.
  function applyCols(n) {
    n = Math.min(COL_MAX, Math.max(COL_MIN, parseInt(n, 10) || COL_DEFAULT));
    document.documentElement.style.setProperty('--gcols', n);
    if (densitySel) densitySel.value = n;
    if (densityVal) densityVal.textContent = n;
    localStorage.setItem(LS_COLS, n);
  }

  function num(el, a) { return parseFloat(el.getAttribute(a)) || 0; }
  function str(el, a) { return (el.getAttribute(a) || '').toLowerCase(); }

  function sortBy(mode) {
    var cards = Array.prototype.slice.call(grid.children);
    var cmp = {
      'newest':     function () { return 0; }, // server order = newest first
      'price-asc':  function (a, b) { return num(a, 'data-price') - num(b, 'data-price'); },
      'price-desc': function (a, b) { return num(b, 'data-price') - num(a, 'data-price'); },
      'color':      function (a, b) { return str(a, 'data-color').localeCompare(str(b, 'data-color')); },
      'style':      function (a, b) { return str(a, 'data-style').localeCompare(str(b, 'data-style')); },
      'brand':      function (a, b) { return str(a, 'data-title').localeCompare(str(b, 'data-title')); },
      'title':      function (a, b) { return str(a, 'data-title').localeCompare(str(b, 'data-title')); },
    }[mode];
    if (cmp && mode !== 'newest') cards.sort(cmp);
    cards.forEach(function (c) { grid.appendChild(c); });
    if (sortSel) sortSel.value = mode;
    localStorage.setItem(LS_SORT, mode);
  }

  if (sortSel) sortSel.addEventListener('change', function () { sortBy(sortSel.value); });
  if (densitySel) densitySel.addEventListener('input', function () { applyCols(densitySel.value); });

  applyCols(localStorage.getItem(LS_COLS) || COL_DEFAULT);
  sortBy(localStorage.getItem(LS_SORT) || 'newest');
})();