UNPKG

frappe-datatable

Version:

A modern datatable library for the web

297 lines (249 loc) 8.16 kB
import $ from './dom'; import DataManager from './datamanager'; import CellManager from './cellmanager'; import ColumnManager from './columnmanager'; import RowManager from './rowmanager'; import BodyRenderer from './body-renderer'; import Style from './style'; import Keyboard from './keyboard'; import TranslationManager from './translationmanager'; import getDefaultOptions from './defaults'; let defaultComponents = { DataManager, CellManager, ColumnManager, RowManager, BodyRenderer, Style, Keyboard }; class DataTable { constructor(wrapper, options) { DataTable.instances++; if (typeof wrapper === 'string') { // css selector wrapper = document.querySelector(wrapper); } this.wrapper = wrapper; if (!(this.wrapper instanceof HTMLElement)) { throw new Error('Invalid argument given for `wrapper`'); } this.initializeTranslations(options); this.setDefaultOptions(); this.buildOptions(options); this.prepare(); this.initializeComponents(); if (this.options.data) { this.refresh(); this.columnmanager.applyDefaultSortOrder(); if (this.options.saveSorting) { this.setupSaveSorting(); this.columnmanager.applySavedSortOrder(); } } } initializeTranslations(options) { this.language = options.language || 'en'; this.translationManager = new TranslationManager(this.language); if (options.translations) { this.translationManager.addTranslations(options.translations); } } setDefaultOptions() { this.DEFAULT_OPTIONS = getDefaultOptions(this); } buildOptions(options) { this.options = this.options || {}; this.options = Object.assign( {}, this.DEFAULT_OPTIONS, this.options || {}, options ); options.headerDropdown = options.headerDropdown || []; this.options.headerDropdown = [ ...this.DEFAULT_OPTIONS.headerDropdown, ...options.headerDropdown ]; // custom user events this.events = Object.assign( {}, this.DEFAULT_OPTIONS.events, this.options.events || {}, options.events || {} ); this.fireEvent = this.fireEvent.bind(this); } prepare() { this.prepareDom(); this.unfreeze(); } initializeComponents() { let components = Object.assign({}, defaultComponents, this.options.overrideComponents); let { Style, Keyboard, DataManager, RowManager, ColumnManager, CellManager, BodyRenderer } = components; this.style = new Style(this); this.keyboard = new Keyboard(this.wrapper); this.datamanager = new DataManager(this.options); this.rowmanager = new RowManager(this); this.columnmanager = new ColumnManager(this); this.cellmanager = new CellManager(this); this.bodyRenderer = new BodyRenderer(this); } prepareDom() { this.wrapper.innerHTML = ` <div class="datatable" dir="${this.options.direction}"> <div class="dt-header"></div> <div class="dt-scrollable"></div> <div class="dt-footer"></div> <div class="dt-freeze"> <span class="dt-freeze__message"> ${this.options.freezeMessage} </span> </div> <div class="dt-toast"></div> <div class="dt-dropdown-container"></div> <textarea class="dt-paste-target"></textarea> </div> `; this.datatableWrapper = $('.datatable', this.wrapper); this.header = $('.dt-header', this.wrapper); this.footer = $('.dt-footer', this.wrapper); this.bodyScrollable = $('.dt-scrollable', this.wrapper); this.freezeContainer = $('.dt-freeze', this.wrapper); this.toastMessage = $('.dt-toast', this.wrapper); this.pasteTarget = $('.dt-paste-target', this.wrapper); this.dropdownContainer = $('.dt-dropdown-container', this.wrapper); } refresh(data, columns) { this.datamanager.init(data, columns); this.render(); this.setDimensions(); } destroy() { this.wrapper.innerHTML = ''; this.style.destroy(); this.fireEvent('onDestroy'); } appendRows(rows) { this.datamanager.appendRows(rows); this.rowmanager.refreshRows(); } refreshRow(row, rowIndex) { this.rowmanager.refreshRow(row, rowIndex); } render() { this.renderHeader(); this.renderBody(); } renderHeader() { this.columnmanager.renderHeader(); } renderBody() { this.bodyRenderer.render(); } setDimensions() { this.style.setDimensions(); } showToastMessage(message, hideAfter) { this.bodyRenderer.showToastMessage(message, hideAfter); } clearToastMessage() { this.bodyRenderer.clearToastMessage(); } getColumn(colIndex) { return this.datamanager.getColumn(colIndex); } getColumns() { return this.datamanager.getColumns(); } getRows() { return this.datamanager.getRows(); } getCell(colIndex, rowIndex) { return this.datamanager.getCell(colIndex, rowIndex); } getColumnHeaderElement(colIndex) { return this.columnmanager.getColumnHeaderElement(colIndex); } getViewportHeight() { if (!this.viewportHeight) { this.viewportHeight = $.style(this.bodyScrollable, 'height'); } return this.viewportHeight; } sortColumn(colIndex, sortOrder) { this.columnmanager.sortColumn(colIndex, sortOrder); } saveSorting(colIndex, nextSortOrder) { this.columnmanager.saveSorting(colIndex, nextSortOrder); } removeColumn(colIndex) { this.columnmanager.removeColumn(colIndex); } scrollToLastColumn() { this.datatableWrapper.scrollLeft = 9999; } freeze() { $.style(this.freezeContainer, { display: '' }); } unfreeze() { $.style(this.freezeContainer, { display: 'none' }); } updateOptions(options) { this.buildOptions(options); } fireEvent(eventName, ...args) { // fire internalEventHandlers if any // and then user events const handlers = [ ...(this._internalEventHandlers[eventName] || []), this.events[eventName] ].filter(Boolean); for (let handler of handlers) { handler.apply(this, args); } } on(event, handler) { this._internalEventHandlers = this._internalEventHandlers || {}; this._internalEventHandlers[event] = this._internalEventHandlers[event] || []; this._internalEventHandlers[event].push(handler); } log() { if (this.options.logs) { console.log.apply(console, arguments); } } translate(str, args) { return this.translationManager.translate(str, args); } setupSaveSorting() { // add options in default headerdropdown let action = { label: this.translate('Save Sorting'), action: function (column) { this.saveSorting(column.colIndex, column.sotOrder); }, display: 'hidden' }; this.options.headerDropdown.push(action); this.columnmanager.bindDropdown(); // add events for onSortColumn this.on('onSortColumn', function (column) { this.columnmanager.toggleDropdownItem(4); if (column.sortOrder === 'none') { localStorage.removeItem(this.columnmanager.sortingKey); } }); } } DataTable.instances = 0; export default DataTable;