UNPKG

solid-ui

Version:

UI library for Solid applications

217 lines • 8.33 kB
// Build a 2D matrix of values // // dom AKA document // query a Query object of rdflib.js with a valid pattern // vx A variable object, the one to be used for the X variable (horiz) // vy A variable object, the one to be used for the Y variable (vertical) // vvalue A variable object, the one to be used for the cell value // returns A DOM element with the matrix in it, which has a .refresh() function. // // Options: // cellFunction(td, x, y, value) fill the TD element of a single cell // xDecreasing set true for x axis to be in decreasing order. // yDecreasing set true for y axis to be in decreasing order. // set_x array of X values to be define initial rows (order irrelevant) // set_y array of Y values to be define initial columns // // Features: // Header row at top (x axis) and left (y-axis) generated automatically. // Extra rows and columns are inserted as needed to hold new data points // matrix.refresh() will re-run the query and adjust the display import * as utils from '../utils'; import * as $rdf from 'rdflib'; import { solidLogicSingleton } from 'solid-logic'; const kb = solidLogicSingleton.store; export function matrixForQuery(dom, query, vx, vy, vvalue, options, whenDone) { // @@ TODO Remove need to cast to any const matrix = dom.createElement('table'); const header = dom.createElement('tr'); const corner = header.appendChild(dom.createElement('td')); corner.setAttribute('class', 'MatrixCorner'); matrix.appendChild(header); // just one for now matrix.lastHeader = header; // Element before data let columns = []; // Vector const rows = []; // Associative array const setCell = function (cell, x, y, value) { while (cell.firstChild) { // Empty any previous cell.removeChild(cell.firstChild); } cell.setAttribute('style', ''); cell.style.textAlign = 'center'; if (options.cellFunction) { options.cellFunction(cell, x, y, value); } else { cell.textContent = utils.label(value); cell.setAttribute('style', 'padding: 0.3em'); } delete cell.old; }; const rowFor = function (y1) { const y = y1.toNT(); if (rows[y]) return rows[y]; // @@ TODO Remove need for casting to any const tr = dom.createElement('tr'); const header = tr.appendChild(dom.createElement('td')); header.setAttribute('style', 'padding: 0.3em;'); header.textContent = utils.label(y1); // first approximation if (y1.termType === 'NamedNode') { kb.fetcher.nowOrWhenFetched(y1.uri.split('#')[0], undefined, function (ok, _body, _response) { if (ok) header.textContent = utils.label(y1); }); } for (let i = 0; i < columns.length; i++) { setCell(tr.appendChild(dom.createElement('td')), $rdf.fromNT(columns[i]), y1, null); } tr.dataValueNT = y; rows[y] = tr; for (let ele = matrix.lastHeader.nextSibling; ele; ele = ele.nextSibling) { // skip header if ((y > ele.dataValueNT && options && options.yDecreasing) || (y < ele.dataValueNT && !(options && options.yDecreasing))) { return matrix.insertBefore(tr, ele); // return the tr } } return matrix.appendChild(tr); // return the tr }; const columnNumberFor = function (x1) { const xNT = x1.toNT(); // xNT is a NT string let col = null; // These are data columns (not headings) for (let i = 0; i < columns.length; i++) { if (columns[i] === xNT) { return i; } if ((xNT > columns[i] && options.xDecreasing) || (xNT < columns[i] && !options.xDecreasing)) { columns = columns .slice(0, i) .concat([xNT]) .concat(columns.slice(i)); col = i; break; } } if (col === null) { col = columns.length; columns.push(xNT); } // col is the number of the new column, starting from 0 for (let row = matrix.firstChild; row; row = row.nextSibling) { // For every row header or not const y = row.dataValueNT; const td = dom.createElement('td'); // Add a new cell td.style.textAlign = 'center'; if (row === matrix.firstChild) { td.textContent = utils.label(x1); } else { setCell(td, x1, $rdf.fromNT(y), null); } if (col === columns.length - 1) { row.appendChild(td); } else { let t = row.firstChild; for (let j = 0; j < col + 1; j++) { // Skip header col too t = t.nextSibling; } row.insertBefore(td, t); } } return col; }; const markOldCells = function () { for (let i = 1; i < matrix.children.length; i++) { const row = matrix.children[i]; for (let j = 1; j < row.children.length; j++) { row.children[j].old = true; } } }; const clearOldCells = function () { let row, cell; const colsUsed = []; const rowsUsed = []; if (options.set_y) { // Knows y values create rows for (let k = 0; k < options.set_y.length; k++) { rowsUsed[options.set_y[k]] = true; } } if (options.set_x) { for (let k = 0; k < options.set_x.length; k++) { colsUsed[columnNumberFor(options.set_x[k]) + 1] = true; } } for (let i = 1; i < matrix.children.length; i++) { row = matrix.children[i]; for (let j = 1; j < row.children.length; j++) { cell = row.children[j]; if (cell.old) { const y = $rdf.fromNT(row.dataValueNT); const x = $rdf.fromNT(columns[j - 1]); setCell(cell, x, y, null); } else { rowsUsed[row.dataValueNT] = true; colsUsed[j] = true; } } } for (let i = 0; i < matrix.children.length; i++) { row = matrix.children[i]; if (i > 0 && !rowsUsed[row.dataValueNT]) { delete rows[row.dataValueNT]; matrix.removeChild(row); } else { for (let j = row.children.length - 1; j > 0; j--) { // backwards const cell = row.children[j]; if (!colsUsed[j]) { row.removeChild(cell); } } } } const newcolumns = []; for (let j = 0; j < columns.length; j++) { if (colsUsed[j + 1]) { newcolumns.push(columns[j]); } } columns = newcolumns; }; matrix.refresh = function () { markOldCells(); kb.query(query, addCellFromBindings, undefined, clearOldCells); }; const addCellFromBindings = function (bindings) { const x = bindings[vx.toString()]; const y = bindings[vy.toString()]; const value = bindings[(vvalue.toString())]; const row = rowFor(y); const colNo = columnNumberFor(x); const cell = row.children[colNo + 1]; // number of Y axis headings setCell(cell, x, y, value); }; if (options.set_y) { // Knows y values create rows for (let k = 0; k < options.set_y.length; k++) { rowFor(options.set_y[k]); } } if (options.set_x) { for (let k = 0; k < options.set_x.length; k++) { columnNumberFor(options.set_x[k]); } } kb.query(query, addCellFromBindings, undefined, whenDone); // Populate the matrix return matrix; } //# sourceMappingURL=matrix.js.map