UNPKG

equation-admin-template

Version:

Booststrap 4 admin template made by equation

296 lines (241 loc) 10.5 kB
/** * Abstract cell renderer * @constructor * @class Base class for all cell renderers * @param {Object} config */ function CellRenderer(config) { this.init(config); } CellRenderer.prototype.init = function(config) { // override default properties with the ones given for (var p in config) this[p] = config[p]; }; CellRenderer.prototype._render = function(rowIndex, columnIndex, element, value) { // remember all the things we need element.rowIndex = rowIndex; element.columnIndex = columnIndex; // remove existing content while (element.hasChildNodes()) element.removeChild(element.firstChild); // clear isEditing (in case a currently editeed is being re-rendered by some external call) element.isEditing = false; // always apply the number class to numerical cells and column headers if (this.column.isNumerical()) EditableGrid.prototype.addClassName(element, "number"); // always apply the boolean class to boolean column headers if (this.column.datatype == 'boolean') EditableGrid.prototype.addClassName(element, "boolean"); // apply a css class corresponding to the column name EditableGrid.prototype.addClassName(element, "editablegrid-" + this.column.name); // add a data-title attribute used for responsiveness element.setAttribute('data-title', this.column.label); // call the specialized render method return this.render(element, typeof value == 'string' && this.column.datatype != "html" ? (value === null ? null : htmlspecialchars(value, 'ENT_NOQUOTES').replace(/ /g, ' &nbsp;')) : value); }; CellRenderer.prototype.render = function(element, value, escapehtml) { var _value = escapehtml ? (typeof value == 'string' && this.column.datatype != "html" ? (value === null ? null : htmlspecialchars(value, 'ENT_NOQUOTES').replace(/ /g, ' &nbsp;')) : value) : value; element.innerHTML = _value ? _value : ""; }; CellRenderer.prototype.getDisplayValue = function(rowIndex, value) { // for html data type, sort and filter after replacing html entities if (this.column.datatype == 'html') return html_entity_decode(value); return value; }; /** * Enum cell renderer * @constructor * @class Class to render a cell with enum values */ function EnumCellRenderer(config) { this.init(config); } EnumCellRenderer.prototype = new CellRenderer(); EnumCellRenderer.prototype.getLabel = function(rowIndex, value) { var label = null; if (typeof value != 'undefined') { value = value ? value : ''; var optionValues = this.column.getOptionValuesForRender(rowIndex); if (optionValues && value in optionValues) label = optionValues[value]; if (label === null) { var isNAN = typeof value == 'number' && isNaN(value); label = isNAN ? "" : value; } } return label ? label : ''; }; EnumCellRenderer.prototype.render = function(element, value) { var label = this.getLabel(element.rowIndex, value); element.innerHTML = label ? (this.column.datatype != "html" ? htmlspecialchars(label, 'ENT_NOQUOTES').replace(/\s\s/g, '&nbsp; ') : label) : ''; }; EnumCellRenderer.prototype.getDisplayValue = function(rowIndex, value) { // if the column has enumerated values, sort and filter on the value label return value === null ? null : this.getLabel(rowIndex, value); }; /** * Number cell renderer * @constructor * @class Class to render a cell with numerical values */ function NumberCellRenderer(config) { this.init(config); } NumberCellRenderer.prototype = new CellRenderer(); NumberCellRenderer.prototype.render = function(element, value) { var column = this.column || {}; // in case somebody calls new NumberCellRenderer().render(..) var isNAN = value === null || (typeof value == 'number' && isNaN(value)); var displayValue = isNAN ? (column.nansymbol || "") : value; if (typeof displayValue == 'number') { if (column.precision !== null) { // displayValue = displayValue.toFixed(column.precision); displayValue = number_format(displayValue, column.precision, column.decimal_point, column.thousands_separator); } if (column.unit !== null) { if (column.unit_before_number) displayValue = column.unit + ' ' + displayValue; else displayValue = displayValue + ' ' + column.unit; } } element.innerHTML = displayValue; if (isNAN) EditableGrid.prototype.addClassName(element, "nan"); else EditableGrid.prototype.removeClassName(element, "nan"); }; /** * Checkbox cell renderer * @constructor * @class Class to render a cell with an HTML checkbox */ function CheckboxCellRenderer(config) { this.init(config); } CheckboxCellRenderer.prototype = new CellRenderer(); CheckboxCellRenderer.prototype._render = function(rowIndex, columnIndex, element, value) { // if a checkbox already exists keep it, otherwise clear current content if (element.firstChild && (typeof element.firstChild.getAttribute != "function" || element.firstChild.getAttribute("type") != "checkbox")) while (element.hasChildNodes()) element.removeChild(element.firstChild); // remember all the things we need element.rowIndex = rowIndex; element.columnIndex = columnIndex; // apply a css class corresponding to the column name EditableGrid.prototype.addClassName(element, "editablegrid-" + this.column.name); // add a data-title attribute used for responsiveness element.setAttribute('data-title', this.column.label); // call the specialized render method return this.render(element, value); }; CheckboxCellRenderer.prototype.render = function(element, value) { // convert value to boolean just in case value = (value && value != 0 && value != "false") ? true : false; // if check box already created, just update its state if (element.firstChild) { element.firstChild.checked = value; return; } // create and initialize checkbox var htmlInput = document.createElement("input"); htmlInput.setAttribute("type", "checkbox"); // give access to the cell editor and element from the editor field htmlInput.element = element; htmlInput.cellrenderer = this; // this renderer is a little special because it allows direct edition var cellEditor = new CellEditor(); cellEditor.editablegrid = this.editablegrid; cellEditor.column = this.column; htmlInput.onclick = function(event) { element.rowIndex = this.cellrenderer.editablegrid.getRowIndex(element.parentNode); // in case it has changed due to sorting or remove element.isEditing = true; cellEditor.applyEditing(element, htmlInput.checked ? true : false); }; element.appendChild(htmlInput); htmlInput.checked = value; htmlInput.disabled = (!this.column.editable || !this.editablegrid.isEditable(element.rowIndex, element.columnIndex)); EditableGrid.prototype.addClassName(element, "boolean"); }; /** * Email cell renderer * @constructor * @class Class to render a cell with emails */ function EmailCellRenderer(config) { this.init(config); } EmailCellRenderer.prototype = new CellRenderer(); EmailCellRenderer.prototype.render = function(element, value) { element.innerHTML = value ? "<a href='mailto:" + value + "'>" + value + "</a>" : ""; }; /** * Website cell renderer * @constructor * @class Class to render a cell with websites */ function WebsiteCellRenderer(config) { this.init(config); } WebsiteCellRenderer.prototype = new CellRenderer(); WebsiteCellRenderer.prototype.render = function(element, value) { element.innerHTML = value ? "<a href='" + (value.indexOf("//") == -1 ? "http://" + value : value) + "'>" + value + "</a>" : ""; }; /** * Date cell renderer * @constructor * @class Class to render a cell containing a date */ function DateCellRenderer(config) { this.init(config); } DateCellRenderer.prototype = new CellRenderer; DateCellRenderer.prototype.render = function(cell, value) { var date = this.editablegrid.checkDate(value); if (typeof date == "object") cell.innerHTML = date.formattedDate; else cell.innerHTML = value ? value : ""; cell.style.whiteSpace = 'nowrap'; }; /** * Sort header renderer * @constructor * @class Class to add sorting functionalities to headers */ function SortHeaderRenderer(columnName, cellRenderer) { this.columnName = columnName; this.cellRenderer = cellRenderer; }; SortHeaderRenderer.prototype = new CellRenderer(); SortHeaderRenderer.prototype.render = function(cell, value) { if (!value) { if (this.cellRenderer) this.cellRenderer.render(cell, value); } else { // create a link that will sort (alternatively ascending/descending) var link = document.createElement("a"); cell.appendChild(link); link.columnName = this.columnName; link.style.cursor = "pointer"; link.innerHTML = value; link.editablegrid = this.editablegrid; link.renderer = this; link.onclick = function() { with (this.editablegrid) { var cols = tHead.rows[0].cells; var clearPrevious = -1; var backOnFirstPage = false; if (sortedColumnName != this.columnName) { clearPrevious = sortedColumnName; sortedColumnName = this.columnName; sortDescending = false; backOnFirstPage = true; } else { if (!sortDescending) sortDescending = true; else { clearPrevious = sortedColumnName; sortedColumnName = -1; sortDescending = false; backOnFirstPage = true; } } // render header for previous sort column (not needed anymore since the grid is now fully refreshed after a sort - cf. possible pagination) // var j = getColumnIndex(clearPrevious); // if (j >= 0) columns[j].headerRenderer._render(-1, j, cols[j], columns[j].label); sort(sortedColumnName, sortDescending, backOnFirstPage); // render header for new sort column (not needed anymore since the grid is now fully refreshed after a sort - cf. possible pagination) // var j = getColumnIndex(sortedColumnName); // if (j >= 0) columns[j].headerRenderer._render(-1, j, cols[j], columns[j].label); } }; // add an arrow to indicate if sort is ascending or descending if (this.editablegrid.sortedColumnName == this.columnName) { cell.appendChild(document.createTextNode("\u00a0")); cell.appendChild(this.editablegrid.sortDescending ? this.editablegrid.sortDownElement: this.editablegrid.sortUpElement); } // call user renderer if any if (this.cellRenderer) this.cellRenderer.render(cell, value); } };