Выделение стилем CSS в массиве JS-Script - динамическая таблица

Рейтинг: -1Ответов: 2Опубликовано: 28.07.2025

Имеется таблица: Всё работает прекрасно. Но хотел бы применить стиль css в данных массива "data", к примеру - выделить название отделов ("Руководство" в примере) стилями. Как такое можно внедрить в данную конструкцию?

let data = [
                "► Руководство;;;;",
                "Директор;Пупкин Василий Васильевич;223-322;8 900-000-00-00;director@e-mail.ru",
                    
                "Зам. директора;Тигренко Лев Леопардович;322-223;8 900-000-00-01;zamdirectora@e-mail.ru"];
        
        
function clearTable(table) {
  for (var i = table.rows.length - 1; i > 0; i--) {
    table.deleteRow(i);
  }
}

function buildCell(row, entry, searchQuery) {
  var cell = row.insertCell(-1);
  highlight = new RegExp(searchQuery, "i");

  if (searchQuery) {
    cell.innerHTML = entry.replace(highlight, "<mark style='background-color:#0078d7; color:#ffffff;'>" + "$&" + "</mark>");
  } else {
    cell.appendChild(document.createTextNode(entry));
  }
}

function buildTable(tableID, data, searchQuery) {
  var table = document.getElementById(tableID);
  clearTable(table)
  for (i = 0; i < data.length; i++) {
    var row = table.insertRow(-1);
    slots = data[i].split(";");
    for (j = 0; j < 5; j++) {
      buildCell(row, slots[j], searchQuery);
    }
  }
}

buildTable("dataTable", data, "")

var keyupStack = [];
var keyword = document.getElementById('keyword');
keyword.addEventListener('keyup', function() {
  keyupStack.push(1);

  setTimeout(function() {
    keyupStack.pop();
    if (keyupStack.length === 0) {
      var buf = '.*?' + this.value.replace(/(.)/g, "$1");
      var reg = new RegExp(buf, 'i');

      var filteredLists = data.filter(function(d) {
        return reg.test(d);
      });

      buildTable("dataTable", filteredLists, this.value);
    }
  }.bind(this), 300);
});
 tr:nth-child(2n+1) {
    background: #f9f9f9; /* Цвет фона */
   } 
   tr:nth-child(1) {
    background: #cccccc; /* Цвет фона */
    
   }
            
            
            
        td{padding-left: 4px; padding-right: 4px;
        border: solid;
        border-color: #cccccc;
        border-width: 1px;}
            
            th {border: solid;
        border-color: #b1b1b1;
        border-width: 1px;} 
            
            
            #foundation{padding: 4px 4px 4px 4px;

                color:#121c4b;

                width:fit-content;
                margin-left: auto;
                margin-right: auto;
                margin-bottom: 20pt;
                line-height: 13px;
                top:14pt;
    
                text-align: left;

                font-family: 'PT Sans', 'Roboto', 'Helvetica Nue', sans-serif;
                font-size: 8pt;
                position:relative;}
<div id="foundation">
                
<div style="position:fixed; text-align: center; min-width:228pt; max-width:600pt; width: 22vw; left:50%; right:50%; transform: translate(-50%, -50%); margin-top: -12px; margin-bottom: 24px; background-color:rgba(255,255,255,0.80); padding-top: 8pt;">
<span style="font-size: 10pt; font-weight: bold;">Поиск:</span> <input type="text" id="keyword" style="height: 12pt">
<ul id="list">
</ul>
</div>
 
<table id="dataTable" border="0" cellspacing="0" cellpadding="0" style="margin-left: auto; margin-right: auto; margin-top: 12pt; margin-bottom: 16px; border-collapse: collapse;">
  <tr>
      <th style="padding-left: 6px; padding-right: 6px;">Должность</th>
    <th style="padding-left: 6px; padding-right: 6px;">ФИО</th>
    <th style="padding-left: 6px; padding-right: 6px;">телефон отдела</th>
    <th style="padding-left: 6px; padding-right: 6px;">телефон сотрудника</th>
    <th style="padding-left: 6px; padding-right: 6px;">e-mail</th>
  </tr>
</table>

        
        
        
        </div>
        </div>

Ответы

▲ 2

Убрана зависимость от html и написано с помощью JS класса. Добавлена возможность добавления CSS свойств/CSS классов для ячеек данных. Изменён формат данных для таблицы - без ;. Если принципиально нужно с ; - нужно будет отдельно написать функцию, которая будет форматировать массив со строками с ; в массив, который тут используется.

class DirectoryTable {
  #container;
  #data;
  #headers;
  #highlightColor;
  #highlightTextColor;
  #debounce;
  #keyupStack = [];
  #table;
  #keywordInput;

  constructor({
    container,
    data,
    headers = [],
    highlightColor = '#0078d7',
    highlightTextColor = '#ffffff',
    debounce = 300
  }) {
    this.#container = container;
    this.#data = data;
    this.#headers = headers;
    this.#highlightColor = highlightColor;
    this.#highlightTextColor = highlightTextColor;
    this.#debounce = debounce;

    this.#createLayout();
    this.#buildTable(this.#data, "");
    this.#keywordInput.addEventListener("keyup", this.#onKeyUp);
  }

  #createLayout() {
    this.#container.innerHTML = "";

    const searchPanel = document.createElement("div");
    searchPanel.className = "search-panel";
    searchPanel.innerHTML = `
      <span class="search-label">Поиск:</span>
      <input type="text" class="search-input">
      <ul class="search-suggestions"></ul>
    `;
    this.#container.appendChild(searchPanel);
    this.#keywordInput = searchPanel.querySelector("input");

    this.#table = document.createElement("table");
    this.#table.className = "data-table";

    const headerRow = this.#table.insertRow(-1);
    headerRow.className = "header-row";
    this.#headers.forEach(text => {
      const th = document.createElement("th");
      th.className = "th-cell";
      th.textContent = text;
      headerRow.appendChild(th);
    });

    this.#container.appendChild(this.#table);
  }

  #clearTable() {
    while (this.#table.rows.length > 1) {
      this.#table.deleteRow(-1);
    }
  }

  #buildCell(row, cellData, searchQuery) {
    const td = row.insertCell(-1);
    const value = (cellData && typeof cellData.value !== "undefined") ? String(cellData.value) : "";

    // Добавление классов
    if (Array.isArray(cellData?.className)) {
      td.classList.add(...cellData.className);
    }

    // Добавление стилей (не перезаписывает существующие)
    if (cellData?.style && typeof cellData.style === "object") {
      for (const [key, val] of Object.entries(cellData.style)) {
        td.style[key] = val;
      }
    }

    // Подсветка совпадений
    const regex = new RegExp(searchQuery, "i");
    if (searchQuery && regex.test(value)) {
      td.innerHTML = value.replace(
        regex,
        `<mark style="background-color:${this.#highlightColor}; color:${this.#highlightTextColor};">$&</mark>`
      );
    } else {
      td.textContent = value;
    }
  }

  #buildTable(data, searchQuery) {
    this.#clearTable();

    data.forEach(rowData => {
      const row = this.#table.insertRow(-1);
      for (let i = 0; i < this.#headers.length; i++) {
        this.#buildCell(row, rowData[i] || {}, searchQuery);
      }
    });
  }

  #onKeyUp = () => {
    this.#keyupStack.push(1);

    setTimeout(() => {
      this.#keyupStack.pop();
      if (this.#keyupStack.length === 0) {
        const query = this.#keywordInput.value.trim();
        const regex = new RegExp(".*?" + query.replace(/(.)/g, "$1"), "i");

        const filtered = this.#data.filter(row =>
          row.some(cell => cell?.value && regex.test(String(cell.value)))
        );

        this.#buildTable(filtered, query);
      }
    }, this.#debounce);
  }
}

const headers = ["Должность", "ФИО", "телефон отдела", "телефон сотрудника", "e-mail"];

const data = [
  [{
      value: "► Административно-управленческий персонал",
      className: ["group-row", "text-bold"],
      style: {
        color: "red",
        border: "2px solid currentColor"
      }
    },
    {}, {}, {}, {}
  ],
  [{
      value: "Директор",
      className: ["title"]
    },
    {
      value: "Пупкин Василий Васильевич"
    },
    {
      value: "223-322"
    },
    {
      value: "8 900-000-00-00",
      className: ["phone"]
    },
    {
      value: "director@e-mail.ru"
    }
  ],
  [{
      value: "Зам. директора"
    },
    {
      value: "Тигренко Лев Леопардович"
    },
    {
      value: "322-223"
    },
    {
      value: "8 900-000-00-01",
      className: ["phone"],
      style: {
        fontStyle: "italic"
      }
    },
    {
      value: "zamdirectora@e-mail.ru"
    }
  ]
];

new DirectoryTable({
  container: document.getElementById("foundation"),
  data: data,
  headers: headers
});
html {
  font-size: 24px;
}

.foundation {
  padding: 4px;
  color: #121c4b;
  width: fit-content;
  margin: 0 auto 1.25rem auto;
  /* 20pt ≈ 26.67px ≈ 1.25rem */
  line-height: 1.1rem;
  top: 1rem;
  /* 14pt ≈ 18.67px ≈ 1rem */
  text-align: left;
  font-family: 'PT Sans', 'Roboto', 'Helvetica Neue', sans-serif;
  font-size: 0.5rem;
  /* 8pt ≈ 10.67px ≈ 0.5rem */
  position: relative;
}

.search-panel {
  position: fixed;
  text-align: center;
  min-width: 304px;
  /* 228pt ≈ 304px */
  max-width: 800px;
  /* 600pt ≈ 800px */
  width: 22vw;
  left: 50%;
  right: 50%;
  transform: translate(-50%, -50%);
  margin-top: -12px;
  margin-bottom: 24px;
  background-color: rgba(255, 255, 255, 0.8);
  padding-top: 0.5rem;
  /* 8pt ≈ 10.67px ≈ 0.5rem */
}

.search-label {
  font-size: 0.625rem;
  /* 10pt ≈ 13.3px ≈ 0.625rem */
  font-weight: bold;
}

.search-input {
  height: 0.75rem;
  /* 12pt ≈ 16px ≈ 1rem, but slightly smaller */
}

.data-table {
  margin: 0.75rem auto 1rem auto;
  /* 12pt ≈ 16px, 16px ≈ 1rem */
  border-collapse: collapse;
}

.header-row {
  background: #cccccc;
}

.data-table tr:nth-child(2n+1):not(.header-row) {
  background: #f9f9f9;
}

.th-cell {
  padding: 0 0.375rem;
  /* 6px ≈ 0.375rem */
  border: 1px solid #b1b1b1;
}

.data-table td {
  padding: 0 0.25rem;
  /* 4px ≈ 0.25rem */
  border: 1px solid #cccccc;
}
<div id="foundation" class="foundation">

</div>

▲ 1

Немного учим конструктор в функции buildTable отмечать строки таблицы по ключевому знаку. Код легко обучается проверкой всей ячейки или всей строки. Цвет во вкусу...

function buildTable(tableID, data, searchQuery) {
  let table = document.getElementById(tableID);
  clearTable(table);
  for (i = 0; i < data.length; i++) {
    let row = table.insertRow(-1);
    // row должна начинаться с ключа из примера
    if (data[i]?.slice(0, 1) === '►') row.style.backgroundColor='#fcc';
    // или содержит ключ где угодно в row
    // if (data[i]?.includes('►')) row.style.backgroundColor='#fcc';
    slots = data[i]?.split(";");
    // или можно по тексту первой ячейки красить
    // if (slots[0] === '► Руководство') row.style.backgroundColor='#fcc';
    for (j = 0; j < 5; j++) {
      buildCell(row, slots[j], searchQuery);
    }; // этот цикл можно заменить на динамический
    // и строить таблицу по полностью по 'data'
    // slots.forEach(e => buildCell(row, e, searchQuery));
    // но тогда весь код переписывать надо
  };
};