Создаем адаптивную сводную таблицу

Создаем адаптивную сводную таблицу

От автора: не так давно твит Smashing Magazine привлек внимание к моей статье по созданию элегантной таблицы с помощью OpenType. Спасибо, Smashing Magazine. Один комментатор справедливо заметил, что таблица была неадаптивной: при сужении окна браузера данные отсекались. Я не мог изменить таблицу, как в предыдущих примерах: порядок и направление данных в ней важны и не должны обрезаться. Однако есть другое решение.

В Microsoft Excel и других табличных приложениях есть функция под названием «сводные таблицы», которая меняет строки и столбцы местами. Подобный эффект можно реализовать на веб-страницах с помощью JavaScript для таблиц определенного вида. Например, для таблицы сверху.

Начинаем с разметки

Разметка таблицы похожа на таблицу из примера с OpenType, только здесь добавляются id и класс (необязательные закрывающие теги были удалены для упрощения кода).

<table id="gg" class="large">
    <caption>2014 Greenhouse gas emissions, per country</caption>
    <thead>
        <tr>
            <td>&nbsp;
            <th scope="col">China
            <th scope="col"><abbr title="United States of America">USA</abbr>
            <th scope="col"><abbr title="European Union">EU</abbr>
            <th scope="col">India
            <th scope="col">Russia
    </thead>
    <tbody>
        <tr>
            <th scope="row">CO<sub>2</sub> (mt)
            <td>10,540
            <td>5,334
            <td>3,415
            <td>2,341
            <td>1,766
        <tr>
            <th scope="row">Emission per capita (t)
            <td>7.6
            <td>16.5
            <td>6.7
            <td>1.8
            <td>12.4
    </tbody>
</table>

CSS тоже очень похож. Я написал этот пример на Sass:

table {
    margin: 2rem auto;
    font-size: 1.6rem;
    border-collapse: collapse;
    @media all and (max-width: 636px) {
        font-size: 1.4rem; 
    }
@media all and (max-width: 522px) {
        font-size: 1.2rem; 
    }
table td {
    text-align: right;
    padding: .5rem;
    width: 5rem;
}
table thead th {
    border-bottom: 1px solid #777;
    font-weight: 400;
}
table tbody th {
    font-weight: 400;
    text-align: right;
    padding-right: 1rem;
}
table caption {
  font-weight: 600;
  margin-bottom: 1rem;
}
table tbody td {
  color: #444;
}

Поворот строк и столбцов

Текущая структура таблицы записана в JS в переменную fulltable. Без JS таблица будет отображаться, но не будет поворачиваться.

var fullTable = document.querySelector(".large").innerHTML,
caption = gg.getElementsByTagName("caption"),
ggHead = gg.querySelector("thead tr"),
ggBody = gg.querySelector("tbody"),
ggColHeaders = ggHead.querySelectorAll("th"),
ggDataHeaders = ggBody.querySelectorAll("tr th"),
ggDataRows = ggBody.querySelectorAll("tr"),
matchPoint = window.matchMedia("(max-width: 600px)"),
slimTable;

Во всех переменных хранится часть таблицы.

function pivotTable() {
  if (matchPoint.matches && gg.matches(".large")) {
  if (typeof slimTable === 'undefined') {
    ggHead.innerHTML = "<td>&nbsp;</td>";
    for (var i = 0; i < ggDataHeaders.length; i++) {
      var scoped = ggDataHeaders;
      scoped.scope = "col";
      ggHead.appendChild(scoped);
    }

    var totalCols = ggDataRows[0].getElementsByTagName("td").length;
    ggBody.innerHTML = "";       

    for (var j = 0; j < totalCols; j++) { 
      var newRow = document.createElement("tr");
      var newRowHeader = document.createElement("th");
      newRowHeader.scope = "row";
      newRowHeader.innerHTML = ggColHeaders[j].innerText;
      newRow.appendChild(newRowHeader);
      for (var k = 0; k < ggDataRows.length; k++) { 
        var currentRowData = ggDataRows[k].getElementsByTagName("td");
        var newCell = document.createElement("td");
        newCell.innerHTML = currentRowData[j].innerText;
        newRow.appendChild(newCell);
      }
      ggBody.appendChild(newRow);
    }
  } else {
    gg.innerHTML = slimTable;
  }
    gg.classList.remove("large");
    gg.classList.add("small");
    slimTable = document.querySelector(".small").innerHTML;
  } 
  if (gg.matches(".small") && !matchPoint.matches) {
    console.log("Upsize");
    gg.innerHTML = fullTable;
    gg.classList.remove("small");
    gg.classList.add("large");
  } 
}

Функция pivotTable меняет строки и колонки местами. Ячейки заголовков, которые были слева, перемещаются наверх. Чисто семантически (и с точки зрения перспективы) ничего не меняется, меняется только вид.

После переворота таблицы класс меняется с large на small. Перевернутая версия структуры таблицы записывается в переменную slimTable, чтобы таблица еще раз не перевернулась при изменении размера вьюпорта.

Функция pivotTable запускается после загрузки страницы:

pivotTable();

Нам не нужно проверять вызов функции pivotTable каждый раз при изменении размера вьюпорта (это сильно ударит по производительности), поэтому я принудительно понизил время повторного запуска до 200 миллисекунд при срабатывании события resize:

window.addEventListener("resize", throttle( pivotTable, 200 )); 

Замедление делается через функцию:

function throttle (callback, limit) {
  var wait = false; 
  return function () {
    if (!wait) {  
      callback.call(); 
      wait = true; 
      setTimeout(function () { 
        wait = false;   
        }, limit);
     }
   }
}

Заключение

Техника не подходит для всех таблиц (в которых слишком много столбцов и строк), но может пригодиться для таблиц, как в нашем примере.

Источник: http://thenewcode.com/

Редакция: Команда webformyself.

Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Фреймворк Bootstrap: практика адаптивной верстки от А до Я

Научись верстать сайты, используя все возможности фреймворка Bootstrap.

Научиться

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree