UNPKG

@daypilot/modal

Version:

Build a modal dialog dynamically from code.

392 lines (312 loc) 9.42 kB
/** * Created on 2020-08-14. */ const local = {}; (function (DayPilot) { 'use strict'; if (DayPilot.Table) { return; } var Table = function(options) { this.form = null; // Form instance this.item = null; // table def from form this.data = null; this.name = null; this.theme = "edit_table_default"; this.onInput = null; this.nav = {}; this._activeEdit = null; this._rows = []; options = options || {}; for (var name in options) { this[name] = options[name]; } }; Table.prototype.create = function() { var table = this; var div = document.createElement("div"); div.className = this.theme + "_main"; div.style.position = "relative"; var hidden = document.createElement("input"); hidden.type = "hidden"; hidden.name = table.name; hidden.table = this; div.appendChild(hidden); var tableElement = document.createElement("div"); tableElement.className = this.theme + "_table"; var header = this._createHeader(); tableElement.appendChild(header); var spacerRow = table._createRowState({}); spacerRow.spacer = true; var spacer = this._renderRow(spacerRow); // spacer.style.visibility = "hidden"; spacer.classList.add(table.theme + "_spacer"); tableElement.appendChild(spacer); var body = document.createElement("div"); body.className = table.theme + "_tbody"; tableElement.appendChild(body); div.appendChild(tableElement); var after = document.createElement("div"); div.appendChild(after); this.nav.body = body; this.nav.table = tableElement; this.nav.main = div; this.nav.after = after; var add = document.createElement("div"); var plus = document.createElement("span"); plus.className = this.theme + "_plus"; plus.addEventListener("click", function(ev) { if (table.disabled) { return; } var generate = table.item.onNewRow; var value = {}; if (typeof generate === "function") { var args = {}; args.result = table.form.serialize(); args.value = {}; generate(args); value = args.value; } var row = table._createRowState(value); table._rows.push(row); table._render(); table._doOnInput(); }); this.nav.plus = plus; add.appendChild(plus); div.appendChild(add); return div; }; Table.prototype._createHeader = function() { var table = this; var row = document.createElement("div"); row.classList.add(this.theme + "_row"); row.classList.add(this.theme + "_header"); this.item.columns.forEach(function(item) { var cell = document.createElement("div"); cell.classList.add(table.theme + "_cell"); cell.innerText = item.name; row.appendChild(cell); }); return row; }; Table.prototype._maxRowsReached = function() { var max = this.item.max || 0; if (max && this._rows.length >= max) { return true; } return false; }; Table.prototype.save = function() { var table = this; var data = []; table._rows.forEach(function(row) { var item = {}; row.cells.forEach(function(cell) { item[cell.id] = cell.value; }); data.push(item); }); return data; }; Table.prototype.load = function(data) { var table = this; var isArray = Object.prototype.toString.call(data) === '[object Array]'; if (!isArray) { throw new Error("Array expected"); } this.data = data; this._createState(); this._render(); }; Table.prototype._updateCss = function() { if (this.disabled) { this.nav.main.classList.add(this.theme + "_disabled"); } else { this.nav.main.classList.remove(this.theme + "_disabled"); } var maxReached = this._maxRowsReached(); if (maxReached) { this.nav.plus.classList.add(this.theme + "_plus_max"); } else { this.nav.plus.classList.remove(this.theme + "_plus_max"); } }; Table.prototype._createState = function() { var table = this; this._rows = []; this.data.forEach(function(dataRow) { var row = table._createRowState(dataRow); table._rows.push(row); }); }; Table.prototype._removeRow = function(row) { var table = this; var index = table._rows.indexOf(row); table._rows.splice(index, 1); }; Table.prototype._createRowState = function(dataRow) { var table = this; var row = {}; row.data = dataRow; row.cells = []; table.item.columns.forEach(function(formItem) { var id = formItem.id; var value = dataRow[id]; var type = table._formItemType(formItem); if (typeof value === "undefined") { if (type === "text") { value = ""; } else if (type === "number") { value = 0; } else if (type === "select") { var options = formItem.options; value = options && options[0].id; } } var cell = {}; cell.id = id; cell.value = value; cell.type = type; cell.data = formItem; row.cells.push(cell); }); return row; }; Table.prototype._formItemType = function(formItem) { var type = formItem.type; if (!type) { if (formItem.options) { type = "select"; } else { type = "text"; } } return type; }; Table.prototype._render = function() { var table = this; this.nav.body.innerHTML = ""; this.nav.after.innerHTML = ""; this._rows.forEach(function(row) { var el = table._renderRow(row); table.nav.body.appendChild(el); }); if (this._rows.length === 0) { var el = table._renderEmpty(); table.nav.after.appendChild(el); } this._updateCss(); }; Table.prototype._renderEmpty = function() { var div = document.createElement("div"); div.className = this.theme + "_empty"; return div; }; Table.prototype._renderRow = function(row) { var table = this; var el = document.createElement("div"); el.className = table.theme + "_row"; row.cells.forEach(function(cell) { var cellEl = document.createElement("div"); cellEl.className = table.theme + "_cell"; var interactive = table._renderCell(cell); if (row.spacer) { var wrap = document.createElement("div"); wrap.style.height = "0px"; wrap.style.overflow = "hidden"; wrap.appendChild(interactive); cellEl.appendChild(wrap); } else { cellEl.appendChild(interactive); } el.appendChild(cellEl); }); var cell = document.createElement("div"); cell.classList.add(table.theme + "_cell"); cell.classList.add(table.theme + "_rowaction"); var span = document.createElement("span"); span.className = this.theme + "_delete"; span.addEventListener("click", function(ev) { if (table.disabled) { return; } table._removeRow(row); table._render(); table._doOnInput(); }); if (!row.spacer) { cell.appendChild(span); } el.appendChild(cell); return el; }; Table.prototype._doOnInput = function() { var table = this; if (typeof table.onInput === "function") { var args = {} table.onInput(args); } }; Table.prototype._renderCell = function(cell) { var table = this; var type = cell.type; if (type === "text" || type === "number") { var input = document.createElement("input"); input.type = type; if (table.disabled) { input.disabled = true; } if (cell.value) { input.value = cell.value; } input.addEventListener("keyup", function(ev) { if (type === "number") { cell.value = Number(this.value); } else { cell.value = this.value; } table._doOnInput(); }); return input; } else if (type === "select") { var select = document.createElement("select"); if (table.disabled) { select.disabled = true; } cell.data.options.forEach(function(item) { var option = document.createElement("option"); option.innerText = item.name; option.value = item.id; option._originalValue = item.id; select.appendChild(option); if (cell.value === item.id) { option.setAttribute("selected", true); } }); select.addEventListener("change", function(ev) { var option = select.options[select.selectedIndex]; if (option && typeof option._originalValue !== "undefined") { cell.value = option._originalValue; } table._doOnInput(); }); return select; } throw new Error("Unsupported item type: " + type); }; Table.prototype.focus = function() { }; DayPilot.Table = Table; })(local); const {Table} = local; export {Table};