diff --git a/src/js/templates/tableEditor.html b/src/js/templates/tableEditor.html index c954e086a..c514d303d 100644 --- a/src/js/templates/tableEditor.html +++ b/src/js/templates/tableEditor.html @@ -22,7 +22,7 @@ - + Clear & reset table diff --git a/src/js/views/TableEditorView.js b/src/js/views/TableEditorView.js index c261b1c6d..17924cf1a 100644 --- a/src/js/views/TableEditorView.js +++ b/src/js/views/TableEditorView.js @@ -15,6 +15,14 @@ define([ PapaParse, Template, ) => { + // Classes used for elements we will manipulate + const CLASS_NAMES = { + button: "dropbtn", + controls: "spreadsheet-controls", + colOption: "col-dropdown-option", + sortButton: "col-sort", + rowHeader: "row-header", + }; // a utility function to check if a value is empty for sorting const valIsEmpty = (x) => x === "" || x === undefined || x === null || Number.isNaN(x); @@ -102,15 +110,16 @@ define([ * @constructs TableEditorView * @param {object} options - A literal object with options to pass to the * view - * @param {string} options.markdown - A markdown table to edit. - * @param {string} options.csv - A CSV table to edit. - * @param {string} options.tableData - The table data as a stringified + * @param {string} [options.markdown] - A markdown table to edit. + * @param {string} [options.csv] - A CSV table to edit. + * @param {string} [options.tableData] - The table data as a stringified * JSON in the form of an array of arrays. Only used if markdown is not * provided. + * @param {boolean} [options.viewMode] - Set this to true to inactivate + * editing of the table. */ initialize(options = {}) { const mergedOptions = { ...this.defaults, ...options }; - Object.keys(mergedOptions).forEach((key) => { this[key] = mergedOptions[key]; }); @@ -125,6 +134,7 @@ define([ .html( this.template({ cid: this.cid, + controlsClass: CLASS_NAMES.controls, }), ) .data("view", this); @@ -197,6 +207,39 @@ define([ this.createTableBody(tableBody, this.rowCount, this.colCount); this.populateTable(); + + // If in view mode, remove editing functionality + if (this.viewMode) { + this.deactivateEditing(); + } + }, + + /** + * Turn off functionality that allows the user to edit the table values, + * add or remove rows or columns. + */ + deactivateEditing() { + const tableCells = this.el.querySelectorAll("td, th > span"); + const controls = this.el.querySelectorAll(`.${CLASS_NAMES.controls}`); + + tableCells.forEach((td) => td.setAttribute("contentEditable", "false")); + controls.forEach((control) => + control.style.setProperty("display", "none"), + ); + + // Hide every button except the sort button in the columns + this.el + .querySelectorAll( + `.${CLASS_NAMES.colOption}:not(.${CLASS_NAMES.sortButton})`, + ) + .forEach((btn) => { + btn.style.setProperty("display", "none"); + }); + + // Hide row controls + this.$el + .find(`.${CLASS_NAMES.rowHeader} .${CLASS_NAMES.button}`) + .hide(); }, /** @@ -324,14 +367,14 @@ define([ const dropDownDiv = document.createElement("div"); dropDownDiv.setAttribute("class", "dropdown"); dropDownDiv.innerHTML = ` - + - Insert 1 column left - Insert 1 column right - Sort column - Delete column + Insert 1 column left + Insert 1 column right + Sort column + Delete column `; th.appendChild(span); @@ -372,7 +415,7 @@ define([ `; cell.appendChild(span); cell.appendChild(dropDownDiv); - cell.setAttribute("class", "row-header"); + cell.setAttribute("class", CLASS_NAMES.rowHeader); } else { cell.contentEditable = true; } @@ -665,14 +708,14 @@ define([ document .getElementById(`col-dropdown-${idArr[2]}`) .classList.toggle("show"); - } else if (classes.contains("col-dropdown-option")) { + } else if (classes.contains(CLASS_NAMES.colOption)) { const index = e.target.parentNode.id.split("-")[2]; if (classes.contains("col-insert-left")) { view.addColumn(index, "left"); } else if (classes.contains("col-insert-right")) { view.addColumn(index, "right"); - } else if (classes.contains("col-sort")) { + } else if (classes.contains(CLASS_NAMES.sortButton)) { view.sortColumn(index); } else if (classes.contains("col-delete")) { view.deleteColumn(index);