Table responsive

J’ai repris ici le principe des tables responsives de l’admin de Dotclear, qui, je sais, est un pis-aller quand on a des tables avec des contenus bien copieux.

Un peu de javascript :

/**
 * Add headers on each cells (responsive tables)
 *
 * @param      DOM elt   table         The table
 * @param      string    selector      The selector
 * @param      number    [offset=0]    The offset = number of firsts columns to ignore
 * @param      boolean   [thead=false] True if titles are in thead rather than in the first tr of the body
 */
const responsiveCellHeaders = (table, selector, offset = 0, thead = false) => {
  try {
    const THarray = [];
    const ths = table.getElementsByTagName('th');
    for (const th of ths) {
      for (let colspan = th.colSpan; colspan > 0; colspan--) {
        THarray.push(th.innerText);
      }
    }
    const tds = table.getElementsByTagName('td');
    for (const td of tds) {
      const div = document.createElement('div');
      div.innerHTML = td.innerHTML;
      td.innerHTML = '';
      td.appendChild(div);
    }
    const styleElm = document.createElement('style');
    let styleSheet;
    document.head.appendChild(styleElm);
    styleSheet = styleElm.sheet;
    for (let i = offset; i < THarray.length; i++) {
      styleSheet.insertRule(
        `${selector} td:nth-child(${i + 1})::before {content:"${THarray[i]} ";}`,
        styleSheet.cssRules.length,
      );
    }
    table.className += `${table.className === '' ? '' : ' '}rch${thead ? ' rch-thead' : ''}`;
  } catch (e) {
    console.log(`responsiveCellHeaders(): ${e}`);
  }
};
const generateSelector = function (context) {
  let index, pathSelector, localName;

  if (context == 'null') throw 'not an dom reference';
  // call getIndex function
  index = getIndex(context);

  while (context.tagName) {
    // selector path
    pathSelector = context.localName + (pathSelector ? '>' + pathSelector : '');
    context = context.parentNode;
  }
  // selector path for nth of type
  pathSelector = pathSelector + `:nth-of-type(${index})`;
  return pathSelector;
};
const getIndex = function (node) {
  // get index for nth of type element
  let i = 1;
  let tagName = node.tagName;

  while (node.previousSibling) {
    node = node.previousSibling;
    if (node.nodeType === 1 && tagName.toLowerCase() == node.tagName.toLowerCase()) {
      i++;
    }
  }
  return i;
};

document.querySelectorAll('#content table').forEach(function (element) {
  const selector = generateSelector(element);
  const thead = element.tHead ? true : false;
  if (element && selector) responsiveCellHeaders(element, selector, 0, thead);
});

Et un peu de CSS :

/* Responsive Cell Header */
.rch td::before {
  display: none;
}

@media screen and (max-width: 60em), print and (max-width: 5in) {
  table.rch {
    display: block;
  }
  table.rch caption,
  table.rch tbody,
  table.rch tr,
  table.rch td {
    display: block;
  }
  table.rch th,
  table.rch tr:first-of-type {
    display: none;
  }
  table.rch td:first-of-type {
    border-top: 1px solid;
  }
  table.rch td::before {
    display: inline;
    font-weight: bold;
  }
  table.rch td {
    display: grid;
    grid-template-columns: 10em auto;
    grid-gap: 1em 0.5em;
    text-align: left;
    border: none;
  }
  table.rch input,
  table.rch select {
    align-self: center;
  }
  table.rch-thead thead {
    display: none;
  }
  table.rch-thead tr:first-of-type {
    display: block;
  }
}

Et le tour est joué (a priori).

À tester avec le billet précédent.

Ajouter un commentaire

Les champs suivis d'un * sont obligatoires

Les commentaires peuvent être formatés en utilisant la syntaxe Markdown Extra.

Ajouter un rétrolien

URL de rétrolien : https://open-time.net/trackback/15750

Haut de page