Как сделать редактируемую таблицу (CRUD) c редактируемыми полями (в т.ч. списки) и вычислениями?
Нужна помощь! Суть вопроса в том, что нужна таблица, где в колонках "Фамилия..." и "Марка...", можно было выбрать в выпадающем списке. В других колонка, ручной ввод. В идеале, в последней колонке подсчитывался пробег, после ввода начального и конечного километража.

table {
position: absolute;
width: 100px;/* сделает ширину таблицы равной ширине блока контейнера, в котором она находится */
border-collapse: collapse;
border: 1px solid black;/* границы ячеек первого ряда таблицы */
empty-cells: show;
}
th {
border: 2px solid black;/* границы ячеек тела таблицы */
background-color: rgb(160, 221, 222);
}
td {
border: 1px solid black;
background-color: rgb(176, 222, 161);
}
table {/* задаст фиксированную ширину для таблицы */
width: 900px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<script src="http://code.jquery.com/jquery-latest.js"></script>
<title>КПП</title>
</head>
<h1>Журнал КПП</h1>
<div id="current_date_time_block"></div>
<script type="text/javascript">
/* функция добавления ведущих нулей */
/* (если число меньше десяти, перед числом добавляем ноль) */
function zero_first_format(value)
{
if (value < 10)
{
value='0'+value;
}
return value;
}
/* функция получения текущей даты и времени */
function date_time()
{
var current_datetime = new Date();
var day = zero_first_format(current_datetime.getDate());
var month = zero_first_format(current_datetime.getMonth()+1);
var year = current_datetime.getFullYear();
var hours = zero_first_format(current_datetime.getHours());
var minutes = zero_first_format(current_datetime.getMinutes());
var seconds = zero_first_format(current_datetime.getSeconds());
return day+"."+month+"."+year+" "+hours+":"+minutes+":"+seconds;
}
/* выводим текущую дату и время на сайт в блок с id "current_date_time_block" */
setInterval(function () {
document.getElementById('current_date_time_block2').innerHTML = date_time();
}, 1000);
</script>
<div id="current_date_time_block2"></div>
<script type="text/javascript">
/* каждую секунду получаем текущую дату и время */
/* и вставляем значение в блок с id "current_date_time_block2" */
setInterval(function () {
document.getElementById('current_date_time_block2').innerHTML = date_time();
}, 1000);
</script>
<body>
<table class="table">
<tr> <!--ряд с ячейками заголовков-->
<th>№ п/п</th>
<th>Фамилия водителя</th>
<th>Марка/Модель машины</th>
<th>№ путевого листа</th>
<th>Начальный километраж</th>
<th>Конечный километраж</th>
<th>Пройдено км</th>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
<tr>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
<td>данные</td>
</tr>
</table>
<!--Нумерация п/п-->
<script>
$('.table tr').each(function(i) {
i && $(this).find('td:first').text(i);});
</script>
</body>
</html>
Ответы (1 шт):
Автор решения: Daniil Loban
→ Ссылка
Реализация CRUD*
*без D - удаления
const tableHeader = document.getElementById('tableHeader');
const tableBody = document.getElementById('tableBody');
const NO_DATA = "нет данных";
// блок данных
const jurnalRows = [
[1, 'Иванов', 'Волга', '1076-B2', 0, 10, 10]
]
const lastNames =[
NO_DATA,
"Иванов",
"Петров",
"Cидоров"
];
const models =[
NO_DATA,
"Жигули",
"Волга",
"Лада"
];
const columns = [
{name: "№ п/п", source:null, className:"number"},
{name: "Фамилия водителя", source:createSelect(lastNames), dataSource: lastNames, className: "lastName"},
{name: "Марка/Модель машины", source:createSelect(models), dataSource: models, className: "model"},
{name: "№ путевого листа", source:createInput('text'), dataSource: "", className:"listNumber"},
{name: "Начальный километраж", source:createInput('number'), dataSource: 0, className: "begin"},
{name: "Конечный километраж", source:createInput('number'), dataSource: 0, className: "end"},
{name: "Пройдено км", source:null, className: "sum"}
]
// конец блока данных
// блок переменных
let currentRow = -1;
let currentCol = -1;
let currentCell = null;
const indexOfSum = columns.indexOf(columns.find( e => e.className === "sum"));
const indexOfBegin = columns.indexOf(columns.find( e => e.className === "begin"));
const indexOfEnd = columns.indexOf(columns.find( e => e.className === "end"));
// конец блока переменных
// подсчет колонки "Пройдено км"
function calulate(event) {
const cell = event.target;
if (cell.parentNode.className === "begin") {
jurnalRows[currentRow][indexOfSum] = jurnalRows[currentRow][indexOfEnd] - cell.value;
} else if (cell.parentNode.className === "end") {
jurnalRows[currentRow][indexOfSum] = cell.value - jurnalRows[currentRow][indexOfBegin];
}
tableBody.children[currentRow].children[indexOfSum].textContent = jurnalRows[currentRow][indexOfSum]
}
function createInput(type) {
const input = document.createElement('input');
input.setAttribute('type', type);
input.addEventListener('change', calulate, false);
return input;
}
function createSelect(list) {
const select = document.createElement('select');
select.cla
for (let i = 0; i < list.length; i++){
const option = document.createElement('option');
option.value=i;
option.textContent=list[i];
select.appendChild(option);
}
return select;
}
const createCell = (text, className) => {
const cell = document.createElement('td');
cell.textContent=text
if(className) cell.className = className;
return cell;
}
const createHeader = () => {
const row = document.createDocumentFragment();
for (i = 0; i< columns.length; i++){
const cell = createCell(columns[i].name, columns[i].className);
row.appendChild(cell);
}
return row;
}
const createRow = (rowData) => {
const row = document.createElement('tr');
for (i = 0; i< columns.length; i++){
const cell= createCell(rowData[i], columns[i].className);
row.appendChild(cell);
}
return row
}
function addNewRow() {
const rowData = [jurnalRows.length +1, ...Array(columns.length-1).fill(NO_DATA)];
jurnalRows.push(rowData)
tableBody.appendChild(createRow(rowData))
}
function addRow(rowData) {
tableBody.appendChild(createRow(rowData))
}
const fillTable = () => {
tableHeader.appendChild(createHeader())
for (let i = 0; i < jurnalRows.length; i++){
addRow(jurnalRows[i])
}
//addNewRow()
}
fillTable()
const showEditField = () => {
if (event.target.tagName !== 'TD') return;
const cell = event.target;
const column = columns.find(e => e.className === cell.className);
const index = columns.indexOf(column);
// запоминаем последний выбор в данных
if (currentCell && currentCol !== -1 && currentRow !== -1){
if (Array.isArray(columns[currentCol].dataSource)){
jurnalRows[currentRow][currentCol] = columns[currentCol].dataSource[+columns[currentCol].source.value];
currentCell.textContent = jurnalRows[currentRow][currentCol];
} else {
jurnalRows[currentRow][currentCol] = columns[currentCol].source.value;
currentCell.textContent = jurnalRows[currentRow][currentCol];
}
}
// переносим ячейку выбора
if (column.source) {
oldData = cell.innerHTML;
cell.innerHTML = "";
if (Array.isArray(column.dataSource)){
column.source.value = `${column.dataSource.indexOf(oldData)}`;
} else {
column.source.value = oldData !== NO_DATA ? oldData : column.dataSource;
}
cell.appendChild(column.source)
currentCol = index;
currentRow = Array.prototype.indexOf.call(tableBody.children, cell.parentNode);
currentCell = cell;
// console.table(jurnalRows);
}
}
tableBody.addEventListener('click',showEditField, false)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--<link rel="stylesheet" href="css/style.css">-->
<style type="text/css">
table {
/*position: absolute; убрано для примера*/
width: 100px;/* сделает ширину таблицы равной ширине блока контейнера, в котором она находится */
border-collapse: collapse;
border: 1px solid black;/* границы ячеек первого ряда таблицы */
empty-cells: show;
}
th {
border: 2px solid black;/* границы ячеек тела таблицы */
background-color: rgb(160, 221, 222);
}
td {
border: 1px solid black;
background-color: rgb(176, 222, 161);
}
table {/* задаст фиксированную ширину для таблицы */
width: 900px;
}
select {
width: 100%;
height: 20px;
font-size: 10px;
}
input {
width: 90%;
height: 20px;
font-size: 10px;
}
</style>
<title>КПП</title>
</head>
<h1>Журнал КПП</h1>
<div id="current_date_time_block"></div>
<div id="current_date_time_block2"></div>
<script type="text/javascript">
/* функция добавления ведущих нулей */
/* (если число меньше десяти, перед числом добавляем ноль) */
function zero_first_format(value) {
return (value < 10) ? value='0'+value : value;
}
/* функция получения текущей даты и времени */
function date_time(){
const current_datetime = new Date();
const day = zero_first_format(current_datetime.getDate());
const month = zero_first_format(current_datetime.getMonth()+1);
const year = current_datetime.getFullYear();
const hours = zero_first_format(current_datetime.getHours());
const minutes = zero_first_format(current_datetime.getMinutes());
const seconds = zero_first_format(current_datetime.getSeconds());
return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`;
}
/* выводим текущую дату и время на сайт в блок с id "current_date_time_block" */
setInterval(function () {
document.getElementById('current_date_time_block2').innerHTML = date_time();
}, 1000);
</script>
<body>
<table class="table">
<thead id="tableHeader"><!--ряд с ячейками заголовков-->
</thead>
<tbody id="tableBody"></tbody>
</table>
<button type="button" onclick="addNewRow()">Добавить строку</button>
</body>
</html>
Пример использования:
- выносим добавленные стили в файл
css/style.css - два скрипта (
для времниидля таблицы) выносим в файлjs/index.jsи подлючаем:
так перед закрытием тега </body>
<script src="js/index.js"></script>
либо там же где и стили с аттрибутом defer
<script defer src="js/index.js"></script>