grid-apps-cmms/src/kiri/ui.js

780 lines
23 KiB
JavaScript
Raw Normal View History

2020-06-05 23:21:53 -04:00
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
"use strict";
2022-02-22 11:32:35 -05:00
// use: kiri.init
// use: kiri.main
gapp.register("kiri.ui", [], (root, exports) => {
2020-06-05 23:21:53 -04:00
const { kiri } = root;
2020-06-05 23:21:53 -04:00
let DOC = self.document,
inputAction = null,
2020-06-05 23:21:53 -04:00
lastGroup = null,
lastDiv = null,
addTo = null,
2020-12-23 14:27:18 -05:00
bindTo = null,
2020-06-05 23:21:53 -04:00
groups = {},
groupSticky = false,
2020-06-05 23:21:53 -04:00
groupName = undefined,
hasModes = [],
2020-11-05 11:00:34 -05:00
setters = [],
2024-05-29 17:55:34 -04:00
lastMode = null,
lastExpert = true,
prefix = "tab",
units = 1,
2021-02-10 16:10:18 -05:00
lastChange = null,
lastBtn = null,
lastTxt = null,
lastPop = null;
2020-06-05 23:21:53 -04:00
self.$ = function (id) { return DOC.getElementById(id) };
2020-06-05 23:21:53 -04:00
kiri.ui = {
2020-06-05 23:21:53 -04:00
prefix: function(pre) { prefix = pre; return kiri.ui },
inputAction: function(fn) { inputAction = fn; return kiri.ui },
2021-02-10 16:10:18 -05:00
lastChange: function() { return lastChange },
2020-06-05 23:21:53 -04:00
checkpoint,
restore,
refresh,
setMode,
bound,
toInt,
toFloat,
2020-12-23 14:27:18 -05:00
isSticky,
setSticky,
newElement,
newBoolean,
newButton,
newBlank,
newDiv,
newGCode,
newGroup,
newLabel,
newInput,
newRange,
newRow,
newSelect,
newTable,
newTableRow,
newText,
setGroup,
addUnits,
setUnits,
confirm,
prompt,
alert,
2024-05-20 13:12:49 -04:00
onBlur,
setVisible(el, bool) {
2024-05-22 22:58:10 -04:00
kiri.ui.setClass(el, 'hide', !bool);
2024-05-22 18:20:02 -04:00
},
setClass(el, clazz, bool) {
2024-05-20 13:12:49 -04:00
if (bool) {
2024-05-22 18:20:02 -04:00
el.classList.add(clazz);
2024-05-22 21:16:55 -04:00
} else {
el.classList.remove(clazz);
2024-05-20 13:12:49 -04:00
}
}
2020-06-05 23:21:53 -04:00
};
function onBlur(obj, fn) {
if (Array.isArray(obj)) {
for (let o of obj) onBlur(o, fn);
return;
}
obj.addEventListener('blur', fn);
}
function alert(message) {
return confirm(message, {ok:true});
}
function prompt(message, value) {
return confirm(message, {ok:true, cancel:false}, value);
}
2020-11-16 09:17:02 -05:00
function confirm(message, buttons, input, opt = {}) {
return new Promise((resolve, reject) => {
let btns = buttons || {
"yes": true,
"no": false
};
let rnd = Date.now().toString(36);
let any = $('mod-any');
let html = [
`<div class="confirm f-col a-stretch">`
];
if (message) {
html.push(`<label style="user-select:text">${message}</label>`);
}
2020-11-16 09:17:02 -05:00
if (opt.pre) {
html = opt.pre.appendAll(html);
}
let iid;
if (typeof(input) === 'string') {
iid = `confirm-input-${rnd}`;
html.append(`<div><input class="grow" type="text" spellcheck="false" id="${iid}"/></div>`);
} else if (Array.isArray(input)) {
iid = `confirm-input-${rnd}`;
html.append(`<div><textarea rows="15" cols="40" class="grow" type="text" spellcheck="false" id="${iid}"></textarea></div>`);
}
2020-07-05 15:39:52 -04:00
html.append(`<div class="f-row j-end">`);
Object.entries(btns).forEach((row,i) => {
html.append(`<button id="confirm-${i}-${rnd}">${row[0]}</button>`);
});
2020-11-16 09:17:02 -05:00
html.append(`</div></div>`);
if (opt.post) {
html.appendAll(opt.post);
}
$('mod-any').innerHTML = html.join('');
function done(value) {
kiri.api.modal.hide();
setTimeout(() => { resolve(value) }, 150);
}
if (iid) {
let array = Array.isArray(input);
iid = $(iid);
iid.value = array ? input.join('\n') : input;
if (!array)
iid.onkeypress = (ev) => {
if (ev.key === 'Enter' || ev.charCode === 13) {
done(ev.target.value);
}
};
}
Object.entries(btns).forEach((row,i) => {
$(`confirm-${i}-${rnd}`).onclick = (ev) => {
let value = iid && row[1] ? iid.value : row[1];
ev.preventDefault();
ev.stopPropagation();
done(value);
}
});
setTimeout(() => {
kiri.api.modal.show('any');
if (iid) {
iid.focus();
iid.selectionStart = iid.value.length;
}
}, 150);
});
}
function refresh() {
setMode(lastMode);
2020-11-05 11:00:34 -05:00
setters.forEach(input => {
if (input.setv) {
input.setv(input.real);
}
});
}
function setMode(mode) {
2024-05-29 17:55:34 -04:00
lastMode = mode;
hasModes.forEach(div => div.setMode(mode));
}
function checkpoint(at) {
return { addTo: at || addTo, lastDiv: at || lastDiv, lastGroup, groupName };
2020-06-05 23:21:53 -04:00
}
2020-12-23 14:27:18 -05:00
function restore(opt = {}) {
addTo = opt.addTo || addTo;
bindTo = opt.bindTo || null;
lastDiv = opt.lastDiv || lastDiv;
lastGroup = opt.lastGroup || lastGroup;
groupName = opt.groupName || groupName;
2020-06-05 23:21:53 -04:00
}
// at present only used by the layers popup menu
function setGroup(div) {
addTo = lastDiv = div;
groupName = undefined;
lastGroup = [];
return div;
}
2020-12-23 14:27:18 -05:00
function newElement(type, opt = {}) {
let el = DOC.createElement(type);
if (opt.id) {
el.setAttribute("id", opt.id);
}
if (opt.class) {
for (let cl of opt.class.split(' ')) {
el.classList.add(cl);
}
}
if (opt.attr) {
for (let [key, val] of Object.entries(opt.attr)) {
el.setAttribute(key, val);
}
}
return el;
}
2024-05-26 22:51:44 -04:00
function newGroup(label, div, opt = {}) {
2024-05-27 13:53:16 -04:00
lastDiv = div = (div || lastDiv);
2020-12-23 14:27:18 -05:00
2024-05-29 17:55:34 -04:00
let group = opt.group || label,
row = DOC.createElement('div'),
2020-06-05 23:21:53 -04:00
dbkey = `beta-${prefix}-show-${group}`,
link;
2024-05-26 22:51:44 -04:00
if (opt.class) {
opt.class.split(' ').forEach(ce => {
row.classList.add(ce);
});
} else {
row.setAttribute("class", "set-header");
}
if (div && opt.driven) {
addModeControls(div, opt);
}
addTo = lastDiv;
2020-06-05 23:21:53 -04:00
div.appendChild(row);
if (label) {
link = DOC.createElement('a');
link.appendChild(DOC.createTextNode(label));
row.appendChild(link);
}
2024-05-23 00:38:38 -04:00
2020-06-05 23:21:53 -04:00
addModeControls(row, opt);
lastGroup = groups[group] = [];
lastGroup.key = dbkey;
groupName = group;
return row;
}
function addCollapsableElement(parent) {
let row = newDiv();
if (parent) parent.appendChild(row);
if (lastGroup) lastGroup.push(row);
return row;
}
2020-11-05 11:00:34 -05:00
function bound(low,high) {
return function(v) {
if (isNaN(v)) return low;
return v < low ? low : v > high ? high : v;
};
}
2020-06-05 23:21:53 -04:00
function toInt() {
let nv = this.value !== '' ? parseInt(this.value) : null;
if (isNaN(nv)) nv = 0;
if (nv !== null && this.bound) nv = this.bound(nv);
this.value = nv;
2020-11-05 11:00:34 -05:00
if (this.setv) {
return this.real = Math.round(nv * units);
};
2020-06-05 23:21:53 -04:00
return nv;
}
function toFloat() {
let nv = this.value !== '' ? parseFloat(this.value) : null;
if (nv !== null && this.bound) nv = this.bound(nv);
2020-11-05 11:00:34 -05:00
if (this.setv) {
return this.setv(nv * units);
} else {
this.value = nv;
}
2020-11-05 11:00:34 -05:00
return nv;
2020-06-05 23:21:53 -04:00
}
function raw() {
return this.value !== '' ? this.value : null;
}
2020-11-05 11:00:34 -05:00
function setUnits(v) {
if (v !== units) {
units = v;
refresh();
}
}
function newLabel(text, opt = {}) {
2020-06-05 23:21:53 -04:00
let label = DOC.createElement('label');
label.appendChild(DOC.createTextNode(text));
label.setAttribute("class", "noselect");
if (opt.class) opt.class.split(' ').forEach(cl => {
label.classList.add(cl);
})
2020-06-05 23:21:53 -04:00
return label;
}
2024-05-29 17:55:34 -04:00
function addId(el, opt = {}) {
if (opt.id) {
el.setAttribute("id", opt.id);
2020-06-05 23:21:53 -04:00
}
}
function safecall(fn) {
try {
return fn();
} catch (e) {
// console.log({ safecall_error: e });
return false;
}
}
2020-12-23 14:27:18 -05:00
function addModeControls(el, opt = {}) {
el.__opt = opt;
2020-06-05 23:21:53 -04:00
el.showMe = function() {
if (opt.trace) console.log({ showMe: el });
2024-05-29 17:55:34 -04:00
el.classList.remove('hide');
2020-06-05 23:21:53 -04:00
};
el.hideMe = function() {
if (opt.trace) console.log({ hideMe: el });
2024-05-29 17:55:34 -04:00
el.classList.add('hide');
2020-06-05 23:21:53 -04:00
};
el.setVisible = function(show) {
if (opt.trace) console.log({ setVisible: show });
2020-06-05 23:21:53 -04:00
if (show) el.showMe();
else el.hideMe();
};
el.setMode = function(mode) {
2024-05-29 17:55:34 -04:00
let xprt = opt.expert === undefined || (opt.expert === lastExpert);
let show = opt.show ? safecall(opt.show) : true;
let disp = opt.visible ? opt.visible() : true;
let hmod = el.hasMode(mode);
if (opt.trace) console.log({ setMode: mode, xprt, show, disp, hmod, modes:el.modes });
2024-05-31 23:35:42 -04:00
if (opt.manual) return;
el.setVisible(hmod && show && xprt && disp);
2020-06-05 23:21:53 -04:00
}
el.hasMode = function(mode) {
return (el.modes.length === 0) ||
(el.modes.contains && el.modes.contains(mode)) ||
(el.modes === mode);
2020-06-05 23:21:53 -04:00
}
el.modes = opt.modes || [];
hasModes.push(el);
2020-06-05 23:21:53 -04:00
}
2024-05-29 17:55:34 -04:00
function newDiv(opt = {}) {
2020-06-05 23:21:53 -04:00
let div = DOC.createElement('div');
2024-05-29 17:55:34 -04:00
addModeControls(div, opt);
(opt.addto || addTo).appendChild(div);
if (opt.addto) lastDiv = addTo = div;
if (opt.addto && opt.class) div.setAttribute('class', opt.class);
lastGroup?.push(div);
2020-06-05 23:21:53 -04:00
div._group = groupName;
return div;
}
2020-12-23 14:27:18 -05:00
function isSticky() {
return groupSticky;
}
function setSticky(bool) {
groupSticky = bool;
}
2020-06-20 22:07:35 -04:00
function newGCode(label, options) {
let opt = options || {},
btn = DOC.createElement("button"),
txt = DOC.createElement("textarea"),
area = opt.area;
txt.setAttribute("wrap", "off");
txt.setAttribute("spellcheck", "false");
txt.setAttribute("style", "resize: none");
2020-12-23 14:27:18 -05:00
txt.onblur = bindTo || inputAction;
2020-06-20 22:07:35 -04:00
btn.setAttribute("class", "basis-50");
2020-06-20 22:07:35 -04:00
btn.appendChild(DOC.createTextNode(label));
btn.onclick = function(ev) {
ev.stopPropagation();
if (ev.target === txt) {
// drop clicks on TextArea
ev.target.focus();
} else {
let fc = area.firstChild;
if (fc) area.removeChild(fc);
area.appendChild(txt);
txt.scrollTop = 0;
txt.scrollLeft = 0;
txt.selectionEnd = 0;
let rows = txt.value.split('\n');
let cols = 0;
rows.forEach(row => {
cols = Math.max(cols, row.length);
});
txt.setAttribute("cols", Math.max(30, cols + 1));
2024-06-01 01:27:43 -04:00
txt.setAttribute("rows", 6);
2020-06-20 22:07:35 -04:00
let showing = btn === lastBtn;
if (lastTxt) {
lastTxt.classList.remove('txt-sel');
}
if (lastBtn) {
lastBtn.classList.remove('btn-sel');
}
if (!showing) {
btn.classList.add('btn-sel');
lastTxt = btn;
lastBtn = btn;
txt.focus();
} else {
inputAction();
}
}
};
addModeControls(btn, opt);
if (opt.title) {
2020-11-29 19:45:35 -05:00
btn.setAttribute("title", options.title);
}
2020-06-20 22:07:35 -04:00
txt.button = btn;
return txt;
}
function newText(label, options) {
2020-06-05 23:21:53 -04:00
let opt = options || {},
2020-06-20 22:07:35 -04:00
inline = opt.row,
row = inline ? lastDiv : newDiv(options),
2020-06-05 23:21:53 -04:00
btn = DOC.createElement("button"),
pop = DOC.createElement("div"),
2020-06-06 23:21:42 -04:00
txt = DOC.createElement("textarea"),
area = opt.area;
2020-06-05 23:21:53 -04:00
txt.setAttribute("wrap", "off");
2020-06-06 23:21:42 -04:00
txt.setAttribute("spellcheck", "false");
txt.setAttribute("style", "resize: none");
2020-06-10 19:59:07 -04:00
txt.onblur = inputAction;
2020-06-05 23:21:53 -04:00
2020-06-20 22:07:35 -04:00
btn.appendChild(DOC.createTextNode(inline ? label : "edit"));
2020-06-06 23:21:42 -04:00
2020-06-05 23:21:53 -04:00
btn.onclick = function(ev) {
ev.stopPropagation();
if (ev.target === txt) {
// drop clicks on TextArea
ev.target.focus();
} else {
2020-06-06 23:21:42 -04:00
let fc = area.firstChild;
if (fc) area.removeChild(fc);
area.appendChild(txt);
2020-06-05 23:21:53 -04:00
// first time, button click / show
btn.parentNode.onclick = btn.onclick;
txt.scrollTop = 0;
txt.scrollLeft = 0;
txt.selectionEnd = 0;
let rows = txt.value.split('\n');
let cols = 0;
rows.forEach(row => {
cols = Math.max(cols, row.length);
});
txt.setAttribute("cols", Math.max(30, cols + 1));
let showing = pop === lastPop;
2020-06-20 22:07:35 -04:00
if (lastBtn) {
lastBtn.classList.remove('btn-sel');
}
if (lastTxt) {
lastTxt.classList.remove('txt-sel');
}
2020-06-05 23:21:53 -04:00
if (!showing) {
2020-06-07 10:43:07 -04:00
row.classList.add('txt-sel');
2020-06-05 23:21:53 -04:00
pop.style.display = "flex";
lastPop = pop;
2020-06-07 10:43:07 -04:00
lastTxt = row;
2020-06-05 23:21:53 -04:00
txt.focus();
} else {
inputAction();
}
}
};
addModeControls(btn, opt);
addId(btn, opt);
2020-06-20 22:07:35 -04:00
if (!inline) {
row.appendChild(newLabel(label));
row.setAttribute("class", "var-row");
}
2020-06-05 23:21:53 -04:00
row.appendChild(btn);
if (opt.title) row.setAttribute("title", options.title);
2020-06-20 22:07:35 -04:00
if (row.setVisible) {
btn.setVisible = row.setVisible;
}
2020-06-05 23:21:53 -04:00
return txt;
}
2024-05-29 17:55:34 -04:00
function newInput(label, opt = {}) {
let row = newDiv(opt),
hide = opt.hide,
size = opt.size || 5,
height = opt.height || 0,
2020-06-05 23:21:53 -04:00
ip = height > 1 ? DOC.createElement('textarea') : DOC.createElement('input'),
2020-12-23 14:27:18 -05:00
action = opt.action || bindTo || inputAction;
2020-06-05 23:21:53 -04:00
row.appendChild(newLabel(label));
row.appendChild(ip);
row.setAttribute("class", opt.class || "var-row");
2020-06-05 23:21:53 -04:00
if (height > 1) {
ip.setAttribute("cols", size);
ip.setAttribute("rows", height);
ip.setAttribute("wrap", "off");
} else {
if (Number.isInteger(size)) {
ip.setAttribute("size", size);
} else {
ip.setAttribute("style", `width:${size}`);
}
}
ip.setAttribute("type", "text");
2020-06-06 23:21:42 -04:00
ip.setAttribute("spellcheck", "false");
2020-06-05 23:21:53 -04:00
row.style.display = hide ? 'none' : '';
2024-05-29 17:55:34 -04:00
if (opt.disabled) ip.setAttribute("disabled", "true");
if (opt.title) row.setAttribute("title", opt.title);
if (opt.convert) ip.convert = opt.convert.bind(ip);
if (opt.bound) ip.bound = opt.bound;
if (opt.action) action = opt.action;
2020-06-05 23:21:53 -04:00
ip.addEventListener('focus', function(event) {
2021-04-27 09:18:14 -04:00
setSticky(true);
2020-06-05 23:21:53 -04:00
});
if (action) {
ip.addEventListener('keydown', function(event) {
let key = event.key;
if (
opt.text ||
(key >= '0' && key <= '9') ||
key === '.' ||
key === '-' ||
key === 'Backspace' ||
key === 'Delete' ||
key === 'ArrowLeft' ||
key === 'ArrowRight' ||
key === 'Tab' ||
event.metaKey ||
event.ctrlKey ||
(key === ',' && options.comma)
) {
return;
}
event.preventDefault();
event.stopPropagation();
});
ip.addEventListener('keyup', function(event) {
if (event.keyCode === 13) {
ip.blur();
}
});
ip.addEventListener('blur', function(event) {
2021-04-27 09:18:14 -04:00
setSticky(false);
2021-02-10 16:10:18 -05:00
lastChange = ip;
2020-06-05 23:21:53 -04:00
action(event);
if (opt.trigger) {
2022-10-18 10:27:41 -04:00
refresh(opt.trigger === 1);
}
2020-06-05 23:21:53 -04:00
});
2020-11-05 11:00:34 -05:00
if (opt.units) {
addUnits(ip, opt.round || 3);
2020-11-05 11:00:34 -05:00
}
2020-06-05 23:21:53 -04:00
}
if (!ip.convert) ip.convert = raw.bind(ip);
ip.setVisible = row.setVisible;
return ip;
}
function addUnits(input, round) {
2020-11-05 11:00:34 -05:00
setters.push(input);
input.setv = function(value) {
if (typeof(value) === 'number') {
input.real = value;
input.value = (value / units).round(round);
2020-11-05 11:00:34 -05:00
} else {
input.value = value;
}
return input.real;
2020-11-05 11:00:34 -05:00
};
return input;
}
2020-06-05 23:21:53 -04:00
function newRange(label, options) {
let row = newDiv(options),
ip = DOC.createElement('input'),
hide = options && options.hide,
2020-12-23 14:27:18 -05:00
action = bindTo || inputAction;
2020-06-05 23:21:53 -04:00
if (label) row.appendChild(newLabel(label));
row.appendChild(ip);
row.setAttribute("class", "var-row");
2020-06-05 23:21:53 -04:00
ip.setAttribute("type", "range");
ip.setAttribute("min", (options && options.min ? options.min : 0));
ip.setAttribute("max", (options && options.max ? options.max : 100));
ip.setAttribute("value", 0);
row.style.display = hide ? 'none' : '';
if (options) {
if (options.title) {
ip.setAttribute("title", options.title);
row.setAttribute("title", options.title);
}
if (options.action) action = options.action;
}
ip.setVisible = row.setVisible;
return ip;
}
function newSelect(label, options, source) {
let row = newDiv(options),
ip = DOC.createElement('select'),
hide = options && options.hide,
2020-12-23 14:27:18 -05:00
action = bindTo || inputAction;
2020-06-05 23:21:53 -04:00
row.appendChild(newLabel(label));
row.appendChild(ip);
if (Array.isArray(source)) {
ip._source = source;
} else {
row.setAttribute("source", source || "tools");
}
row.setAttribute("class", "var-row");
2020-06-05 23:21:53 -04:00
row.style.display = hide ? 'none' : '';
if (options) {
if (options.convert) ip.convert = options.convert.bind(ip);
if (options.disabled) ip.setAttribute("disabled", "true");
if (options.title) row.setAttribute("title", options.title);
if (options.action) action = options.action;
}
2020-11-18 21:54:40 -05:00
ip.setVisible = row.setVisible;
2020-12-23 14:27:18 -05:00
ip.onchange = function(ev) {
2021-02-10 16:10:18 -05:00
lastChange = ip;
action();
};
ip.onclick = (ev) => {
groupSticky = true;
};
2020-11-18 21:54:40 -05:00
// because firefox
ip.onmouseenter = (ev) => {
groupSticky = true;
};
2020-06-05 23:21:53 -04:00
return ip;
}
2024-05-29 17:55:34 -04:00
function newBoolean(label, action = bindTo, opt = {}) {
let row = newDiv(opt),
2020-06-05 23:21:53 -04:00
ip = DOC.createElement('input'),
2024-05-29 17:55:34 -04:00
hide = opt.hide;
2020-06-05 23:21:53 -04:00
if (label) {
row.appendChild(newLabel(label));
}
row.appendChild(ip);
row.setAttribute("class", "var-row");
2020-06-05 23:21:53 -04:00
row.style.display = hide ? 'none' : '';
ip.setAttribute("type", "checkbox");
ip.checked = false;
2024-05-29 17:55:34 -04:00
if (opt.disabled) {
ip.setAttribute("disabled", "true");
}
if (opt.title) {
ip.setAttribute("title", opt.title);
row.setAttribute("title", opt.title);
2020-06-05 23:21:53 -04:00
}
if (action) {
2024-05-29 17:55:34 -04:00
ip.onclick = function(ev) {
action(ip);
if (opt.trigger) {
refresh();
}
};
}
2020-06-05 23:21:53 -04:00
ip.setVisible = row.setVisible;
return ip;
}
function newBlank(options) {
2020-06-12 19:46:39 -04:00
let opt = options || {},
row = newDiv(opt),
hide = opt.hide;
2020-06-05 23:21:53 -04:00
row.isBlank = true;
2020-06-05 23:21:53 -04:00
row.style.display = hide ? 'none' : '';
2024-05-26 23:11:11 -04:00
if (!opt.driven) {
row.setAttribute("class", "var-row");
}
2020-06-12 19:46:39 -04:00
if (opt.class) {
opt.class.split(' ').forEach(ce => {
row.classList.add(ce);
});
}
return row;
2020-06-05 23:21:53 -04:00
}
// unlike other elements, does not auto-add to a row
function newButton(label, action, opt = {}) {
let b = DOC.createElement('button');
2020-06-05 23:21:53 -04:00
b.onclick = function() {
2020-06-13 18:27:31 -04:00
if (action) action(...arguments);
2020-06-05 23:21:53 -04:00
};
2020-06-07 10:43:07 -04:00
if (opt.class) {
opt.class.split(' ').forEach(ce => {
b.classList.add(ce);
});
}
if (opt.icon) {
let d = DOC.createElement('div');
d.innerHTML = opt.icon;
b.appendChild(d);
}
if (opt.title) {
b.setAttribute('title', opt.title);
}
2020-06-07 10:43:07 -04:00
if (label) {
b.appendChild(DOC.createTextNode(label));
2020-06-05 23:21:53 -04:00
}
addModeControls(b, opt);
addId(b, opt);
2020-06-05 23:21:53 -04:00
return b;
}
function newRow(children, options) {
let row = addCollapsableElement((options && options.noadd) ? null : addTo);
if (children) children.forEach(function (c) { row.appendChild(c) });
addModeControls(row, options);
if (options && options.class) {
options.class.split(' ').forEach(ce => {
row.classList.add(ce);
});
2020-06-05 23:21:53 -04:00
}
return row;
2020-06-05 23:21:53 -04:00
}
function newRowTable(array) {
let div = newDiv();
2020-06-06 23:21:42 -04:00
div.setAttribute("class", "table-row");
2020-06-05 23:21:53 -04:00
array.forEach(function(c) {
div.appendChild(c);
});
return div;
}
function newTableRow(arrayOfArrays, options) {
return newRow(newTable(arrayOfArrays), options);
2020-06-05 23:21:53 -04:00
}
function newTable(arrayOfArrays) {
let array = [];
for (let i=0; i<arrayOfArrays.length; i++) {
array.push(newRowTable(arrayOfArrays[i]));
}
return array;
2020-06-05 23:21:53 -04:00
}
});