Объединение и группировка таблиц с использованием JSON и JQuery

Вы можете добавить свой собственный обработчик ошибок, который может предоставить дополнительную информацию об отладке. Кроме того, вы можете настроить его для отправки по электронной почте.

function ERR_HANDLER($errno ,$errstr, $errfile, $errline){
    $msg="<b>Someting bad happened.</b> [$errno] $errstr <br><br>
    <b>File:</b> $errfile <br>
    <b>Line:</b> $errline <br>
    <pre>".json_encode(debug_backtrace(), JSON_PRETTY_PRINT)."</pre> <br>";

    echo $msg;

    return false;
}

function EXC_HANDLER($exception){
    ERR_HANDLER(0,$exception->getMessage(),$exception->getFile(),$exception->getLine());
}

function shutDownFunction() {
    $error = error_get_last();
    if ($error["type"] == 1) {
        ERR_HANDLER($error["type"],$error["message"],$error["file"],$error["line"]);
    }
}

set_error_handler ("ERR_HANDLER", E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
register_shutdown_function("shutdownFunction");
set_exception_handler("EXC_HANDLER");
1
задан Bakti Wijaya 28 March 2019 в 04:38
поделиться

3 ответа

Я разбил это на два этапа: 1. сгенерировать древовидную структуру из входных данных, чтобы позволить подсчет числа строк; 2. Рисование строк и столбцов таблицы.

Весь код настолько универсален, насколько это возможно, чтобы избежать жестко закодированного количества столбцов.

Я также добавил динамический заголовок таблицы. Если вы добавите еще один столбец в структуру данных, заголовки таблицы HTML также будут обновлены. Например, можно использовать этот же код для добавления четвертого уровня, например, "LEVEL_4": "LEVEL 1.2.2.1" в один или несколько рядов.

var data = [
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.1",
        "LEVEL_3": "LEVEL 1.1.1"
    },
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.2",
        "LEVEL_3": "LEVEL 1.2.1"
    },
    {
        "LEVEL_1": "LEVEL 1",
        "LEVEL_2": "LEVEL 1.2",
        "LEVEL_3": "LEVEL 1.2.2"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.1",
        "LEVEL_3": "LEVEL 2.1.1"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.1",
        "LEVEL_3": "LEVEL 2.1.2"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.2",
        "LEVEL_3": "LEVEL 2.2.1"
    },
    {
        "LEVEL_1": "LEVEL 2",
        "LEVEL_2": "LEVEL 2.2",
        "LEVEL_3": "LEVEL 2.2.2"
    }
];

/**
 * Generate rows and columns for the table using the JSON data.
 *
 * @param {Object} data
 * @param {HTMLTableSectionElement} tableBody
 * @param {HTMLTableSectionElement} tableHead
 */
function setTableContent(data, tableBody, tableHead) {
    /* The rowspan is stored here depending on the label of each column */
    var columnRowspans = {};

    var columnHeadings = {};

    /**
     * Translate the data into a tree-like structure
     *
     * @param {JSON} data
     * @return {Array}
     */
    function translateData(data) {
        var rows = [];
        /* Iterate over each row in the dataset */
        data.forEach(function (row) {
            var columns = [],
                label;
            /* Find the individual columns */
            for (var key in row) {
                /* Store the columns header */
                columnHeadings[key] = true;

                label = row[key];
                /* Skip those columns that were already added */
                if (columnRowspans[label]) {
                    columnRowspans[label]++;
                    continue;
                }
                columns.push(label);
                columnRowspans[label] = 1;
            }
            rows.push(columns);
        });
        return rows;
    }

    /* Template string used for a single field in the table */
    var cellTemplate = '<td rowspan="{rowspan}">{content}</td>';

    /* Output */
    var html = '';
    translateData(data).forEach(function (row, index) {
        html += '<tr>';
        row.forEach(function (columnLabel) {
            /* Use the stored rowspans here to generate columns */
            html += cellTemplate
                .replace('{rowspan}', columnRowspans[columnLabel])
                .replace('{content}', columnLabel);
        });
        html += '</tr>';
    });

    if (tableBody instanceof HTMLTableSectionElement) {
        tableBody.innerHTML = html;
    }

    if (tableHead instanceof HTMLTableSectionElement) {
        var thead = '<tr>';
        Object.keys(columnHeadings).forEach(function (heading) {
            thead += '<th>' + heading.replace('_', ' ') + '</th>';
        });
        thead += '</tr>';
        tableHead.innerHTML = thead;
    }
}

setTableContent(data, document.querySelector('#user tbody'), document.querySelector('#user thead'));
 table { 
      border-collapse: collapse;
    }

    td {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }

    th {
      padding: 20px; 
      border: 1px solid black; 
      text-align: center;
    }
<table id="user">
    <thead>
    </thead>
    <tbody> 
    </tbody>
</table>

0
ответ дан feeela 28 March 2019 в 04:38
поделиться

С помощью этого вопроса мне удалось объединить 1-й уровень.

var data = [{
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.1",
    "LEVEL_3": "LEVEL 1.1.1",
  },
  {
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.2",
    "LEVEL_3": "LEVEL 1.2.1",
  },
  {
    "LEVEL_1": "LEVEL 1",
    "LEVEL_2": "LEVEL 1.2",
    "LEVEL_3": "LEVEL 1.2.2",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.1",
    "LEVEL_3": "LEVEL 2.1.1",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.1",
    "LEVEL_3": "LEVEL 2.1.2",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.2",
    "LEVEL_3": "LEVEL 2.2.1",
  },
  {
    "LEVEL_1": "LEVEL 2",
    "LEVEL_2": "LEVEL 2.2",
    "LEVEL_3": "LEVEL 2.2.2",
  }
];

for (i = 0; i < data.length; i++) {
  var l1 = data[i].LEVEL_1;
  data[i].rowspan = 1;
  for (j = i + 1; j < data.length; j++) {
    var l2 = data[j].LEVEL_1;
    if (l1 == l2) {
      data[i].rowspan += 1;
    } else {
      break;
    }
  }
  i = j - 1;
}
var tableStr = '';
$.each(data, function(index, value) {
  if (value.rowspan > 1) {
    tableStr += '<tr>' +
      '<td rowspan="' + value.rowspan + '">' + value.LEVEL_1 + '</td>' +
      '<td>' + value.LEVEL_2 + '</td>' +
      '<td>' + value.LEVEL_3 + '</td>' +
      '</tr>';
  } else {
    tableStr += '<tr>' +
      '<td>' + value.LEVEL_2 + '</td>' +
      '<td>' + value.LEVEL_3 + '</td>' +
      '</tr>';
  }


});
$('#user tbody').html(tableStr);
table {
  border-collapse: collapse;
}

td {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="user">
  <thead>
    <tr>
      <th>LEVEL 1</th>
      <th>LEVEL 2</th>
      <th>LEVEL 3</th>
    </tr>
    <tr>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>

0
ответ дан Abhishek Pandey 28 March 2019 в 04:38
поделиться

У меня есть решение для вас. Возможно, он не самый элегантный, но он работает

Сначала я преобразую данные из JSON во вложенный объект, который считает появление элементов более низкого уровня .

Вторым этапом является прохождение этого вложенного объекта и создание таблицы, tr и td соответственно со значениями счетчика из шага 1, используемого в качестве значений атрибута rowspan.

Мне даже не нужен jQuery, только VanillaJS.

console.clear();

var data = [
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.1",
    LEVEL_3: "LEVEL 1.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.2"
  }
];

const transformData = (data) => {
  let t = {};

  data.forEach((item, index, source) => {
    let l1 = item.LEVEL_1,
        l2 = item.LEVEL_2,
        l3 = item.LEVEL_3;
    t[l1]                         = t[l1]                         || {text: l1, content: {}, count: 0};
    t[l1].content[l2]             = t[l1].content[l2]             || {text: l2, content: {}, count: 0};
    t[l1].content[l2].content[l3] = t[l1].content[l2].content[l3] || {text: l3, content: {}, count: 0};
    t[l1].count++
    t[l1].content[l2].count++
    t[l1].content[l2].content[l3].count++
  })
  return t;
}

const transformDataTable = (tdata) => {

  const table = document.createElement('table');

  for (l1 in tdata) {
    const td1 = document.createElement('th')
    td1.textContent = tdata[l1].text;
    td1.setAttribute('rowspan', tdata[l1].count)
    let done1 = false;

    for (l2 in tdata[l1].content) {
      const td2 = document.createElement('td')
      td2.textContent = tdata[l1].content[l2].text;
      td2.setAttribute('rowspan', tdata[l1].content[l2].count)
      let done2 = false;
      
      for (l3 in tdata[l1].content[l2].content) {
        const td3 = document.createElement('td')
        td3.textContent = tdata[l1].content[l2].content[l3].text;
        td3.setAttribute('rowspan', tdata[l1].content[l2].content[l3].count)
        const tr = document.createElement('tr')
        !done1 && tr.appendChild(td1) && (done1 = true);
        !done2 && tr.appendChild(td2) && (done2 = true);
        tr.appendChild(td3);
        table.appendChild(tr);
      }
    }
  }
  return table;
}


const tdata = transformData(data);
const table = transformDataTable(tdata);


document.body.appendChild(table)
table {
  border-collapse: collapse;
}

td,
th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

С некоторыми изменениями вы можете отсортировать каждый столбец по своему усмотрению

console.clear();

var data = [
  {
    LEVEL_1: "LEVEL 3",
    LEVEL_2: "LEVEL 3.1",
    LEVEL_3: "LEVEL 3.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.1",
    LEVEL_3: "LEVEL 1.1.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.1"
  },
  {
    LEVEL_1: "LEVEL 1",
    LEVEL_2: "LEVEL 1.2",
    LEVEL_3: "LEVEL 1.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.1"
  },
  {
    LEVEL_1: "LEVEL 3",
    LEVEL_2: "LEVEL 3.1",
    LEVEL_3: "LEVEL 3.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.1",
    LEVEL_3: "LEVEL 2.1.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.1"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.2"
  },
  {
    LEVEL_1: "LEVEL 2",
    LEVEL_2: "LEVEL 2.2",
    LEVEL_3: "LEVEL 2.2.3"
  }
  
];

const transformData = (data) => {
  let t = {};

  data.forEach((item, index, source) => {
    let l1 = item.LEVEL_1,
        l2 = item.LEVEL_2,
        l3 = item.LEVEL_3;
    t[l1]                         = t[l1]                         || {text: l1, content: {}, count: 0};
    t[l1].content[l2]             = t[l1].content[l2]             || {text: l2, content: {}, count: 0};
    t[l1].content[l2].content[l3] = t[l1].content[l2].content[l3] || {text: l3, content: {}, count: 0};
    t[l1].count++
    t[l1].content[l2].count++
    t[l1].content[l2].content[l3].count++
  })
  return t;
}

const transformDataTable = (tdata, sort = (a,b) => b-a, sort1 = sort, sort2 = sort1) => {

  const table = document.createElement('table');

  for (l1 of Object.keys(tdata).sort(sort)) {
    const td1 = document.createElement('th')
    td1.textContent = tdata[l1].text;
    td1.setAttribute('rowspan', tdata[l1].count)
    let done1 = false;

    for (l2 of Object.keys(tdata[l1].content).sort(sort1)) {
      const td2 = document.createElement('td')
      td2.textContent = tdata[l1].content[l2].text;
      td2.setAttribute('rowspan', tdata[l1].content[l2].count)
      let done2 = false;
      
      for (l3 of Object.keys(tdata[l1].content[l2].content).sort(sort2)) {
        const td3 = document.createElement('td')
        td3.textContent = tdata[l1].content[l2].content[l3].text;
        td3.setAttribute('rowspan', tdata[l1].content[l2].content[l3].count)
        const tr = document.createElement('tr')
        !done1 && tr.appendChild(td1) && (done1 = true);
        !done2 && tr.appendChild(td2) && (done2 = true);
        tr.appendChild(td3);
        table.appendChild(tr);
      }
    }
  }
  return table;
}

const asc = (a,b) => b-a
const desc = (a,b) => a-b

const tdata = transformData(data);
const table = transformDataTable(tdata, desc, asc);


document.body.appendChild(table)
table {
  border-collapse: collapse;
}

td,
th {
  padding: 20px;
  border: 1px solid black;
  text-align: center;
}

0
ответ дан yunzen 28 March 2019 в 04:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: