UNPKG

tui-grid

Version:

TOAST UI Grid : Powerful data grid control supported by TOAST UI

1,185 lines (1,067 loc) 60.6 kB
/** * @fileoverview The Grid class for the external API. * @author NHN. FE Development Lab <dl_javascript@nhn.com> */ 'use strict'; var _ = require('underscore'); var snippet = require('tui-code-snippet'); var View = require('./base/view'); var ModelManager = require('./model/manager'); var ViewFactory = require('./view/factory'); var DomEventBus = require('./event/domEventBus'); var DomState = require('./domState'); var PublicEventEmitter = require('./publicEventEmitter'); var PainterManager = require('./painter/manager'); var PainterController = require('./painter/controller'); var NetAddOn = require('./addon/net'); var ComponentHolder = require('./componentHolder'); var util = require('./common/util'); var i18n = require('./common/i18n'); var themeManager = require('./theme/manager'); var themeNameConst = require('./common/constMap').themeName; var instanceMap = {}; /** * Grid public API * @class Grid * @param {Object} options * @param {Array} [options.data] - Grid data for making rows. * @param {Object} [options.header] - Options object for header. * @param {number} [options.header.height=40] - The height of the header area. * @param {Array} [options.header.complexColumns] - This options creates new parent headers of the multiple columns * which includes the headers of spcified columns, and sets up the hierarchy. * @param {boolean} [options.virtualScrolling=false] - If set to true, use virtual-scrolling so that large * amount of data can be processed performantly. When using this option that sets true, the rowHeight option * must set value. * @param {string|number} [options.rowHeight] - The height of each rows. The default value is 'auto', * the height of each rows expands to dom's height. If set to number, the height is fixed. * @param {number} [options.minRowHeight=40] - The minimum height of each rows. When this value is larger than * the row's height, it set to the row's height. * @param {string|number} [options.bodyHeight] - The height of body area. The default value is 'auto', * the height of body area expands to total height of rows. If set to 'fitToParent', the height of the grid * will expand to fit the height of parent element. If set to number, the height is fixed. * @param {number} [options.minBodyHeight=minRowHeight] - The minimum height of body area. When this value * is larger than the body's height, it set to the body's height. * @param {Object} [options.columnOptions] - Option object for all columns * @param {number} [options.columnOptions.minWidth=50] - Minimum width of each columns * @param {boolean} [options.columnOptions.resizable=true] - If set to true, resize-handles of each columns * will be shown. * @param {number} [options.columnOptions.frozenCount=0] - The number of frozen columns. * The columns indexed from 0 to this value will always be shown on the left side. * {@link Grid#setFrozenColumnCount} can be used for setting this value dynamically. * @param {number} [options.columnOptions.frozenBorderWidth=1] - The value of frozen border width. * When the frozen columns are created by "frozenCount" option, the frozen border width set. * @param {Object} [options.treeColumnOptions] - Option object for the tree column. * @param {string} [options.treeColumnOptions.name] - The name of column that makes tree column. * @param {boolean} [options.treeColumnOptions.useIcon=true] - If set to true, the folder or file icon is created on * the left side of the tree cell data. * @param {boolean} [options.treeColumnOptions.useCascadingCheckbox] - If set to true, a cascading relationship is * created in the checkbox between parent and child rows. * @param {Object} [options.copyOptions] - Option object for clipboard copying * @param {boolean} [options.copyOptions.useFormattedValue] - Whether to use formatted values or original values * as a string to be copied to the clipboard * @param {boolean} [options.useClientSort=true] - If set to true, sorting will be executed by client itself * without server. * @param {string} [options.editingEvent='dblclick'] - If set to 'click', editable cell in the view-mode will be * changed to edit-mode by a single click. * @param {boolean} [options.scrollX=true] - Specifies whether to show horizontal scrollbar. * @param {boolean} [options.scrollY=true] - Specifies whether to show vertical scrollbar. * @param {boolean} [options.showDummyRows=false] - If set to true, empty area will be filled with dummy rows. * @param {?string} [options.keyColumnName=null] - The name of the column to be used to identify each rows. * If not specified, unique value for each rows will be created internally. * @param {boolean} [options.heightResizable=false] - If set to true, a handle for resizing height will be shown. * @param {Object} [options.pagination=null] - Options for tui.Pagination. * If set to null or false, pagination will not be used. * @param {string} [options.selectionUnit='cell'] - The unit of selection on Grid. ('cell', 'row') * @param {Array} [options.rowHeaders] - Options for making the row header. The row header content is number of * each row or input element. The value of each item is enable to set string type. (ex: ['rowNum', 'checkbox']) * @param {string} [options.rowHeaders.type] - The type of the row header. ('rowNum', 'checkbox', 'radio') * @param {string} [options.rowHeaders.title] - The title of the row header on the grid header area. * @param {number} [options.rowHeaders.width] - The width of the row header. * @param {function} [options.rowHeaders.template] - Template function which returns the content(HTML) of * the row header. This function takes a parameter an K-V object as a parameter to match template values. * @param {Array} options.columns - The configuration of the grid columns. * @param {string} options.columns.name - The name of the column. * @param {boolean} [options.columns.ellipsis=false] - If set to true, ellipsis will be used * for overflowing content. * @param {string} [options.columns.align=left] - Horizontal alignment of the column content. * Available values are 'left', 'center', 'right'. * @param {string} [options.columns.valign=middle] - Vertical alignment of the column content. * Available values are 'top', 'middle', 'bottom'. * @param {string} [options.columns.className] - The name of the class to be used for all cells of * the column. * @param {string} [options.columns.title] - The title of the column to be shown on the header. * @param {number} [options.columns.width] - The width of the column. The unit is pixel. If this value * isn't set, the column's width is automatically resized. * @param {number} [options.columns.minWidth=50] - The minimum width of the column. The unit is pixel. * @param {boolean} [options.columns.hidden] - If set to true, the column will not be shown. * @param {boolean} [options.columns.resizable] - If set to false, the width of the column * will not be changed. * @param {Object} [options.columns.validation] - The options to be used for validation. * Validation is executed whenever data is changed or the {@link Grid#validate} is called. * @param {boolean} [options.columns.validation.required=false] - If set to true, the data of the column * will be checked to be not empty. * @param {string} [options.columns.validation.dataType='string'] - Specifies the type of the cell value. * Avilable types are 'string' and 'number'. * @param {string} [options.columns.defaultValue] - The default value to be shown when the column * doesn't have a value. * @param {function} [options.columns.formatter] - The function that formats the value of the cell. * The retrurn value of the function will be shown as the value of the cell. * @param {boolean} [options.columns.useHtmlEntity=true] - If set to true, the value of the cell * will be encoded as HTML entities. * @param {boolean} [options.columns.ignored=false] - If set to true, the value of the column will be * ignored when setting up the list of modified rows. * @param {boolean} [options.columns.sortable=false] - If set to true, sort button will be shown on * the right side of the column header, which executes the sort action when clicked. * @param {function} [options.columns.onBeforeChange] - The function that will be * called before changing the value of the cell. If stop() method in event object is called, * the changing will be canceled. * @param {function} [options.columns.onAfterChange] - The function that will be * called after changing the value of the cell. * @param {Object} [options.columns.editOptions] - The object for configuring editing UI. * @param {string} [options.columns.editOptions.type='text'] - The string value that specifies * the type of the editing UI. * Available values are 'text', 'password', 'select', 'radio', 'checkbox'. * @param {boolean} [options.columns.editOptions.useViewMode=true] - If set to true, default mode * of the cell will be the 'view-mode'. The mode will be switched to 'edit-mode' only when user * double click or press 'ENTER' key on the cell. If set to false, the cell will always show the * input elements as a default. * @param {Array} [options.columns.editOptions.listItems] - Specifies the option items for the * 'select', 'radio', 'checkbox' type. The item of the array must contain properties named * 'text' and 'value'. (e.g. [{text: 'option1', value: 1}, {...}]) * @param {function} [options.columns.editOptions.onFocus] - The function that will be * called when a 'focus' event occurred on an input element * @param {function} [options.columns.editOptions.onBlur] - The function that will be * called when a 'blur' event occurred on an input element * @param {function} [options.columns.editOptions.onKeyDown] - The function that will be * called when a 'keydown' event occurred on an input element * @param {(string|function)} [options.columns.editOptions.prefix] - The HTML string to be * shown left to the input element. If it's a function, the return value will be used. * @param {(string|function)} [options.columns.editOptions.postfix] - The HTML string to be * shown right to the input element. If it's a function, the return value will be used. * @param {function} [options.columns.editOptions.converter] - The function whose * return value (HTML) represents the UI of the cell. If the return value is * falsy(null|undefined|false), default UI will be shown. * @param {Object} [options.columns.copyOptions] - Option object for clipboard copying. * This option is column specific, and overrides the global copyOptions. * @param {boolean} [options.columns.copyOptions.useFormattedValue] - Whether to use * formatted values or original values as a string to be copied to the clipboard * @param {boolean} [options.columns.copyOptions.useListItemText] - Whether to use * concatenated text or original values as a string to be copied to the clipboard * @param {function} [options.columns.copyOptions.customValue] - Whether to use * customized value from "customValue" callback or original values as a string to be copied to the clipboard * @param {Array} [options.columns.relations] - Specifies relation between this and other column. * @param {Array} [options.columns.relations.targetNames] - Array of the names of target columns. * @param {function} [options.columns.relations.disabled] - If returns true, target columns * will be disabled. * @param {function} [options.columns.relations.editable] - If returns true, target columns * will be editable. * @param {function} [options.columns.relations.listItems] - The function whose return * value specifies the option list for the 'select', 'radio', 'checkbox' type. * The options list of target columns will be replaced with the return value of this function. * @param {string} [options.columns.whiteSpace='nowrap'] - If set to 'normal', the text line is broken * by fitting to the column's width. If set to 'pre', spaces are preserved and the text is braken by * new line characters. If set to 'pre-wrap', spaces are preserved, the text line is broken by * fitting to the column's width and new line characters. If set to 'pre-line', spaces are merged, * the text line is broken by fitting to the column's width and new line characters. * @param {Object} [options.columns.component] - Option for using tui-component * @param {string} [options.columns.component.name] - The name of the compnent to use * for this column * @param {Object} [options.columns.component.options] - The options object to be used for * creating the component * @param {Object} [options.summary] - The object for configuring summary area. * @param {number} [options.summary.height] - The height of the summary area. * @param {string} [options.summary.position='bottom'] - The position of the summary area. ('bottom', 'top') * @param {(string|Object)} [options.summary.defaultContent] * The configuring of summary cell for every column. * This options can be overriden for each column by columnContent options. * If type is string, the value is used as HTML of summary cell for every columns * without auto-calculation. * @param {boolean} [options.summary.defaultContent.useAutoSummary=true] * If set to true, the summary value of every column is served as a paramater to the template * function whenever data is changed. * @param {function} [options.summary.defaultContent.template] - Template function which returns the * content(HTML) of the column of the summary. This function takes an K-V object as a parameter * which contains a summary values keyed by 'sum', 'avg', 'min', 'max' and 'cnt'. * @param {Object} [options.summary.columnContent] * The configuring of summary cell for each column. * Sub options below are keyed by each column name. * If type of value of this object is string, the value is used as HTML of summary cell for * the column without auto-calculation. * @param {boolean} [options.summary.columnContent.useAutoSummary=true] * If set to true, the summary value of each column is served as a paramater to the template * function whenever data is changed. * @param {function} [options.summary.columnContent.template] - Template function which returns the * content(HTML) of the column of the summary. This function takes an K-V object as a parameter * which contains a summary values keyed by 'sum', 'avg', 'min', 'max' and 'cnt'. * @param {boolean} [options.usageStatistics=true] Send the hostname to google analytics. * If you do not want to send the hostname, this option set to false. */ var Grid = View.extend(/** @lends Grid.prototype */{ initialize: function(options) { options = snippet.extend({ usageStatistics: true }, options); if (options.footer) { util.warning('The "footer" option is deprecated since 2.5.0 and replaced by "summary" option.'); options.summary = options.footer; } this.id = util.getUniqueKey(); this.domState = new DomState(this.$el); this.domEventBus = DomEventBus.create(); this.modelManager = this._createModelManager(options); this.painterManager = this._createPainterManager(); this.componentHolder = this._createComponentHolder(options.pagination); this.viewFactory = this._createViewFactory(options); this.container = this.viewFactory.createContainer(); this.publicEventEmitter = this._createPublicEventEmitter(); this.container.render(); this.refreshLayout(); if (!themeManager.isApplied()) { themeManager.apply(themeNameConst.DEFAULT); } this.addOn = {}; instanceMap[this.id] = this; if (options.data) { this.setData(options.data); } if (options.usageStatistics) { snippet.sendHostname('grid', 'UA-129951906-1'); } }, /** * Creates core model and returns it. * @param {Object} options - Options set by user * @returns {module:model/manager} - New model manager object * @private */ _createModelManager: function(options) { var modelOptions = _.assign({}, options, { gridId: this.id, publicObject: this }); _.omit(modelOptions, 'el'); return new ModelManager(modelOptions, this.domState, this.domEventBus); }, /** * Creates painter manager and returns it * @returns {module:painter/manager} * @private */ _createPainterManager: function() { var controller = new PainterController({ focusModel: this.modelManager.focusModel, dataModel: this.modelManager.dataModel, columnModel: this.modelManager.columnModel, selectionModel: this.modelManager.selectionModel }); return new PainterManager({ gridId: this.id, selectType: this.modelManager.columnModel.get('selectType'), fixedRowHeight: this.modelManager.dimensionModel.get('fixedRowHeight'), domEventBus: this.domEventBus, controller: controller }); }, /** * Creates a view factory. * @param {options} options - options * @returns {module:view/factory} * @private */ _createViewFactory: function(options) { var viewOptions = _.pick(options, [ 'heightResizable', 'summary' ]); var dependencies = { modelManager: this.modelManager, painterManager: this.painterManager, componentHolder: this.componentHolder, domEventBus: this.domEventBus, domState: this.domState }; return new ViewFactory(_.assign(dependencies, viewOptions)); }, /** * Creates a pagination component. * @param {Object} pgOptions - pagination options * @returns {module:component/pagination} * @private */ _createComponentHolder: function(pgOptions) { return new ComponentHolder({ pagination: pgOptions }); }, /** * Creates public event emitter and returns it. * @returns {module:publicEventEmitter} - New public event emitter * @private */ _createPublicEventEmitter: function() { var emitter = new PublicEventEmitter(this); emitter.listenToFocusModel(this.modelManager.focusModel); emitter.listenToDomEventBus(this.domEventBus); emitter.listenToDataModel(this.modelManager.dataModel); emitter.listenToSelectionModel(this.modelManager.selectionModel); return emitter; }, /** * Disables all rows. */ disable: function() { this.modelManager.dataModel.setDisabled(true); }, /** * Enables all rows. */ enable: function() { this.modelManager.dataModel.setDisabled(false); }, /** * Disables the row identified by the rowkey. * @param {number|string} rowKey - The unique key of the target row */ disableRow: function(rowKey) { this.modelManager.dataModel.disableRow(rowKey); }, /** * Enables the row identified by the rowKey. * @param {number|string} rowKey - The unique key of the target row */ enableRow: function(rowKey) { this.modelManager.dataModel.enableRow(rowKey); }, /** * Returns the value of the cell identified by the rowKey and columnName. * @param {number|string} rowKey - The unique key of the target row. * @param {string} columnName - The name of the column * @param {boolean} [isOriginal] - It set to true, the original value will be return. * @returns {number|string} - The value of the cell */ getValue: function(rowKey, columnName, isOriginal) { return this.modelManager.dataModel.getValue(rowKey, columnName, isOriginal); }, /** * Returns a list of all values in the specified column. * @param {string} columnName - The name of the column * @param {boolean} [isJsonString=false] - It set to true, return value will be converted to JSON string. * @returns {(Array|string)} - A List of all values in the specified column. (or JSON string of the list) */ getColumnValues: function(columnName, isJsonString) { return this.modelManager.dataModel.getColumnValues(columnName, isJsonString); }, /** * Returns the object that contains all values in the specified row. * @param {number|string} rowKey - The unique key of the target row * @param {boolean} [isJsonString=false] - If set to true, return value will be converted to JSON string. * @returns {Object|string} - The object that contains all values in the row. (or JSON string of the object) */ getRow: function(rowKey, isJsonString) { return this.modelManager.dataModel.getRowData(rowKey, isJsonString); }, /** * Returns the object that contains all values in the row at specified index. * @param {number} index - The index of the row * @param {boolean} [isJsonString=false] - If set to true, return value will be converted to JSON string. * @returns {Object|string} - The object that contains all values in the row. (or JSON string of the object) */ getRowAt: function(index, isJsonString) { return this.modelManager.dataModel.getRowDataAt(index, isJsonString); }, /** * Returns the total number of the rows. * @returns {number} - The total number of the rows */ getRowCount: function() { return this.modelManager.dataModel.length; }, /** * Returns data of currently focused cell * @returns {number} rowKey - The unique key of the row * @returns {string} columnName - The name of the column * @returns {string} value - The value of the cell */ getFocusedCell: function() { var addr = this.modelManager.focusModel.which(); var value = this.getValue(addr.rowKey, addr.columnName); return { rowKey: addr.rowKey, columnName: addr.columnName, value: value }; }, /** * Returns the jquery object of the cell identified by the rowKey and columnName. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @returns {jQuery} - The jquery object of the cell element */ getElement: function(rowKey, columnName) { return this.modelManager.dataModel.getElement(rowKey, columnName); }, /** * Sets the value of the cell identified by the specified rowKey and columnName. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @param {number|string} columnValue - The value to be set */ setValue: function(rowKey, columnName, columnValue) { this.modelManager.dataModel.setValue(rowKey, columnName, columnValue); }, /** * Sets the all values in the specified column. * @param {string} columnName - The name of the column * @param {number|string} columnValue - The value to be set * @param {boolean} [isCheckCellState=true] - If set to true, only editable and not disabled cells will be affected. */ setColumnValues: function(columnName, columnValue, isCheckCellState) { this.modelManager.dataModel.setColumnValues(columnName, columnValue, isCheckCellState); }, /** * Replaces all rows with the specified list. This will not change the original data. * @param {Array} data - A list of new rows */ resetData: function(data) { this.modelManager.dataModel.resetData(data); }, /** * Replaces all rows with the specified list. This will change the original data. * @param {Array} data - A list of new rows * @param {function} callback - The function that will be called when done. */ setData: function(data, callback) { this.modelManager.dataModel.setData(data, true, callback); }, /** * Sets the height of body-area. * @param {number} value - The number of pixel */ setBodyHeight: function(value) { this.modelManager.dimensionModel.set({ bodyHeight: value, fixedHeight: value !== 'auto' }); }, /** * Sets focus on the cell identified by the specified rowKey and columnName. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @param {boolean} [isScrollable=false] - If set to true, the view will scroll to the cell element. */ focus: function(rowKey, columnName, isScrollable) { this.modelManager.focusModel.focusClipboard(); this.modelManager.focusModel.focus(rowKey, columnName, isScrollable); }, /** * Sets focus on the cell at the specified index of row and column. * @param {number|string} rowIndex - The index of the row * @param {string} columnIndex - The index of the column * @param {boolean} [isScrollable=false] - If set to true, the view will scroll to the cell element. */ focusAt: function(rowIndex, columnIndex, isScrollable) { this.modelManager.focusModel.focusAt(rowIndex, columnIndex, isScrollable); }, /** * Sets focus on the cell at the specified index of row and column and starts to edit. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @param {boolean} [isScrollable=false] - If set to true, the view will scroll to the cell element. */ focusIn: function(rowKey, columnName, isScrollable) { this.modelManager.focusModel.focusIn(rowKey, columnName, isScrollable); }, /** * Sets focus on the cell at the specified index of row and column and starts to edit. * @param {number|string} rowIndex - The index of the row * @param {string} columnIndex - The index of the column * @param {boolean} [isScrollable=false] - If set to true, the view will scroll to the cell element. */ focusInAt: function(rowIndex, columnIndex, isScrollable) { this.modelManager.focusModel.focusInAt(rowIndex, columnIndex, isScrollable); }, /** * Makes view ready to get keyboard input. */ activateFocus: function() { this.modelManager.focusModel.focusClipboard(); }, /** * Removes focus from the focused cell. */ blur: function() { this.modelManager.focusModel.blur(); }, /** * Checks all rows. */ checkAll: function() { this.modelManager.dataModel.checkAll(); }, /** * Checks the row identified by the specified rowKey. * @param {number|string} rowKey - The unique key of the row */ check: function(rowKey) { this.modelManager.dataModel.check(rowKey); }, /** * Unchecks all rows. */ uncheckAll: function() { this.modelManager.dataModel.uncheckAll(); }, /** * Unchecks the row identified by the specified rowKey. * @param {number|string} rowKey - The unique key of the row */ uncheck: function(rowKey) { this.modelManager.dataModel.uncheck(rowKey); }, /** * Removes all rows. */ clear: function() { this.modelManager.dataModel.setData([]); }, /** * Removes the row identified by the specified rowKey. * @param {number|string} rowKey - The unique key of the row * @param {boolean|object} [options] - Options. If the type is boolean, this value is equivalent to * options.removeOriginalData. * @param {boolean} [options.removeOriginalData] - If set to true, the original data will be removed. * @param {boolean} [options.keepRowSpanData] - If set to true, the value of the merged cells will not be * removed although the target is first cell of them. */ removeRow: function(rowKey, options) { if (snippet.isBoolean(options) && options) { options = { removeOriginalData: true }; } this.modelManager.dataModel.removeRow(rowKey, options); }, /** * Removes all checked rows. * @param {boolean} showConfirm - If set to true, confirm message will be shown before remove. * @returns {boolean} - True if there's at least one row removed. */ removeCheckedRows: function(showConfirm) { var rowKeys = this.getCheckedRowKeys(); var confirmMessage = i18n.get('net.confirmDelete', { count: rowKeys.length }); if (rowKeys.length > 0 && (!showConfirm || confirm(confirmMessage))) { _.each(rowKeys, function(rowKey) { this.modelManager.dataModel.removeRow(rowKey); }, this); return true; } return false; }, /** * Enables the row identified by the rowKey to be able to check. * @param {number|string} rowKey - The unique key of the row */ enableCheck: function(rowKey) { this.modelManager.dataModel.enableCheck(rowKey); }, /** * Disables the row identified by the spcified rowKey to not be abled to check. * @param {number|string} rowKey - The unique keyof the row. */ disableCheck: function(rowKey) { this.modelManager.dataModel.disableCheck(rowKey); }, /** * Returns a list of the rowKey of checked rows. * @param {boolean} [isJsonString=false] - If set to true, return value will be converted to JSON string. * @returns {Array|string} - A list of the rowKey. (or JSON string of the list) */ getCheckedRowKeys: function(isJsonString) { var checkedRowList = this.modelManager.dataModel.getRows(true); var checkedRowKeyList = _.pluck(checkedRowList, 'rowKey'); return isJsonString ? JSON.stringify(checkedRowKeyList) : checkedRowKeyList; }, /** * Returns a list of the checked rows. * @param {boolean} [useJson=false] - If set to true, return value will be converted to JSON string. * @returns {Array|string} - A list of the checked rows. (or JSON string of the list) */ getCheckedRows: function(useJson) { var checkedRowList = this.modelManager.dataModel.getRows(true); return useJson ? JSON.stringify(checkedRowList) : checkedRowList; }, /** * Returns a list of the column model. * @returns {Array} - A list of the column model. */ getColumns: function() { return this.modelManager.columnModel.get('dataColumns'); }, /** * Returns the object that contains the lists of changed data compared to the original data. * The object has properties 'createdRows', 'updatedRows', 'deletedRows'. * @param {Object} [options] Options * @param {boolean} [options.checkedOnly=false] - If set to true, only checked rows will be considered. * @param {boolean} [options.withRawData=false] - If set to true, the data will contains * the row data for internal use. * @param {boolean} [options.rowKeyOnly=false] - If set to true, only keys of the changed * rows will be returned. * @param {Array} [options.ignoredColumns] - A list of column name to be excluded. * @returns {{createdRows: Array, updatedRows: Array, deletedRows: Array}} - Object that contains the result list. */ getModifiedRows: function(options) { return this.modelManager.dataModel.getModifiedRows(options); }, /** * Inserts the new row with specified data to the end of table. * @param {Object} [row] - The data for the new row * @param {Object} [options] - Options * @param {number} [options.at] - The index at which new row will be inserted * @param {boolean} [options.extendPrevRowSpan] - If set to true and the previous row at target index * has a rowspan data, the new row will extend the existing rowspan data. * @param {boolean} [options.focus] - If set to true, move focus to the new row after appending * @param {(Number|String)} [options.parentRowKey] - Tree row key of the parent which appends given rows * @param {number} [options.offset] - Tree offset from first sibling */ appendRow: function(row, options) { this.modelManager.dataModel.appendRow(row, options); }, /** * Inserts the new row with specified data to the beginning of table. * @param {Object} [row] - The data for the new row * @param {Object} [options] - Options * @param {boolean} [options.focus] - If set to true, move focus to the new row after appending */ prependRow: function(row, options) { this.modelManager.dataModel.prependRow(row, options); }, /** * Returns true if there are at least one row modified. * @returns {boolean} - True if there are at least one row modified. */ isModified: function() { return this.modelManager.dataModel.isModified(); }, /** * Returns the instance of specified AddOn. * @param {string} name - The name of the AddOn * @returns {instance} addOn - The instance of the AddOn */ getAddOn: function(name) { return name ? this.addOn[name] : this.addOn; }, /** * Restores the data to the original data. * (Original data is set by {@link Grid#setData|setData} */ restore: function() { this.modelManager.dataModel.restore(); }, /** * Sets options for header. * @param {Object} options - Options for header * @param {number} [options.height] - The height value * @param {Array} [options.complexColumns] - The complex columns info */ setHeader: function(options) { if (options.height) { this.modelManager.dimensionModel.set('headerHeight', options.height); } if (options.complexColumns) { this.modelManager.columnModel.set({ complexHeaderColumns: options.complexColumns }); } }, /** * Sets the count of frozen columns. * @param {number} count - The count of columns to be frozen */ setFrozenColumnCount: function(count) { this.modelManager.columnModel.set('frozenCount', count); }, /** * Sets the list of column model. * @param {Array} columns - A new list of column model * @example * { * columnName1: 'title1', * columnName2: 'title2', * columnName3: 'title3' * } */ setColumns: function(columns) { this.modelManager.columnModel.set('columns', columns); }, /** * Set columns title * @param {string} columnsMap - columns map to be change */ setColumnTitles: function(columnsMap) { this.modelManager.columnModel.setColumnTitles(columnsMap); }, /** * Creates an specified AddOn and use it on this instance. * @param {string} name - The name of the AddOn to use. * @param {Object} options - The option objects for configuring the AddON. * @returns {Grid} - This instance. */ use: function(name, options) { if (name === 'Net') { options = _.assign({ domEventBus: this.domEventBus, renderModel: this.modelManager.renderModel, dataModel: this.modelManager.dataModel, pagination: this.componentHolder.getInstance('pagination') }, options); this.addOn.Net = new NetAddOn(options); this.publicEventEmitter.listenToNetAddon(this.addOn.Net); } return this; }, /** * Returns a list of all rows. * @returns {Array} - A list of all rows */ getRows: function() { return this.modelManager.dataModel.getRows(); }, /** * Sorts all rows by the specified column. * @param {string} columnName - The name of the column to be used to compare the rows * @param {boolean} [ascending] - Whether the sort order is ascending. * If not specified, use the negative value of the current order. */ sort: function(columnName, ascending) { this.modelManager.dataModel.sortByField(columnName, ascending); }, /** * Unsorts all rows. (Sorts by rowKey). */ unSort: function() { this.sort('rowKey'); }, /** * Gets state of the sorted column in rows * @returns {{columnName: string, ascending: boolean, useClient: boolean}} Sorted column's state */ getSortState: function() { return this.modelManager.dataModel.sortOptions; }, /** * Adds the specified css class to cell element identified by the rowKey and className * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @param {string} className - The css class name to add */ addCellClassName: function(rowKey, columnName, className) { this.modelManager.dataModel.get(rowKey).addCellClassName(columnName, className); }, /** * Adds the specified css class to all cell elements in the row identified by the rowKey * @param {number|string} rowKey - The unique key of the row * @param {string} className - The css class name to add */ addRowClassName: function(rowKey, className) { this.modelManager.dataModel.get(rowKey).addClassName(className); }, /** * Removes the specified css class from the cell element indentified by the rowKey and columnName. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @param {string} className - The css class name to be removed */ removeCellClassName: function(rowKey, columnName, className) { this.modelManager.dataModel.get(rowKey).removeCellClassName(columnName, className); }, /** * Removes the specified css class from all cell elements in the row identified by the rowKey. * @param {number|string} rowKey - The unique key of the row * @param {string} className - The css class name to be removed */ removeRowClassName: function(rowKey, className) { this.modelManager.dataModel.get(rowKey).removeClassName(className); }, /** * Returns the rowspan data of the cell identified by the rowKey and columnName. * @param {number|string} rowKey - The unique key of the row * @param {string} columnName - The name of the column * @returns {Object} - Row span data */ getRowSpanData: function(rowKey, columnName) { return this.modelManager.dataModel.getRowSpanData(rowKey, columnName); }, /** * Returns the index of the row indentified by the rowKey. * @param {number|string} rowKey - The unique key of the row * @returns {number} - The index of the row */ getIndexOfRow: function(rowKey) { return this.modelManager.dataModel.indexOfRowKey(rowKey); }, /** * Returns the index of the column indentified by the column name. * @param {string} columnName - The unique key of the column * @returns {number} - The index of the column */ getIndexOfColumn: function(columnName) { return this.modelManager.columnModel.indexOfColumnName(columnName); }, /** * Returns an instance of tui.Pagination. * @returns {tui.Pagination} */ getPagination: function() { return this.componentHolder.getInstance('pagination'); }, /** * Sets the width of the dimension. * @param {number} width - The width of the dimension */ setWidth: function(width) { this.modelManager.dimensionModel.setWidth(width); }, /** * Sets the height of the dimension. * @param {number} height - The height of the dimension */ setHeight: function(height) { this.modelManager.dimensionModel.setHeight(height); }, /** * Refreshs the layout view. Use this method when the view was rendered while hidden. */ refreshLayout: function() { this.modelManager.dimensionModel.refreshLayout(); }, /** * Resets the width of each column by using initial setting of column models. */ resetColumnWidths: function() { this.modelManager.coordColumnModel.resetColumnWidths(); }, /** * Shows columns * @param {...string} arguments - Column names to show */ showColumn: function() { var args = snippet.toArray(arguments); this.modelManager.columnModel.setHidden(args, false); }, /** * Hides columns * @param {...string} arguments - Column names to hide */ hideColumn: function() { var args = snippet.toArray(arguments); this.modelManager.columnModel.setHidden(args, true); }, /** * Sets the HTML string of given column summary. * The type of content is the same as the options.summary.columnContent of the constructor. * @param {string} columnName - column name * @param {string|object} content - HTML string or options object. */ setSummaryColumnContent: function(columnName, content) { this.modelManager.summaryModel.setColumnContent(columnName, content, true); }, /** * Returns the values of given column summary. * If the column name is not specified, all values of available columns are returned. * The shape of returning object looks like the example below. * @param {string} [columnName] - column name * @returns {Object} * @example * { * column1: { * sum: 1000, * avg: 200, * max: 300, * min: 50, * cnt: 5 * }, * column2: { * sum: 2000, * avg: 300, * max: 600, * min: 80, * cnt: 5 * } * } */ getSummaryValues: function(columnName) { if (this.modelManager.summaryModel) { return this.modelManager.summaryModel.getValues(columnName); } return null; }, /** * Sets the HTML string of given column summary. * @deprecated since version 2.5.0 and is replaced by "setSummaryColumnContent" API * @param {string} columnName - column name * @param {string} contents - HTML string */ setFooterColumnContent: function(columnName, contents) { this.modelManager.columnModel.setSummaryContent(columnName, contents); }, /** * Validates all data and returns the result. * Return value is an array which contains only rows which have invalid cell data. * @returns {Array.<Object>} An array of error object * @example * // return value example * [ * { * rowKey: 1, * errors: [ * { * columnName: 'c1', * errorCode: 'REQUIRED' * }, * { * columnName: 'c2', * errorCode: 'REQUIRED' * } * ] * }, * { * rowKey: 3, * errors: [ * { * columnName: 'c2', * errorCode: 'REQUIRED' * } * ] * } * ] */ validate: function() { return this.modelManager.dataModel.validate(); }, /** * Finds rows by conditions * @param {Object|Function} conditions - object (key: column name, value: column value) or * function that check the value and returns true/false result to find rows * @returns {Array} Row list * @example <caption>Conditions type is object.</caption> * grid.findRows({ * artist: 'Birdy', * price: 10000 * }); * @example <caption>Conditions type is function.</caption> * grid.findRows(function(row) { * return (/b/ig.test(row.artist) && row.price > 10000); * }); */ findRows: function(conditions) { return this.modelManager.dataModel.findRows(conditions); }, /** * Copy to clipboard */ copyToClipboard: function() { this.modelManager.clipboardModel.setClipboardText(); if (!window.clipboardData) { // Accessing the clipboard is a security concern on chrome document.execCommand('copy'); } }, /** * Selects cells or rows by range * @param {Object} range - Selection range * @param {Array} [range.start] - Index info of start selection (ex: [rowIndex, columnIndex]) * @param {Array} [range.end] - Index info of end selection (ex: [rowIndex, columnIndex]) */ selection: function(range) { var selectionModel = this.modelManager.selectionModel; var start = range.start; var end = range.end; var unit = selectionModel.getSelectionUnit(); selectionModel.start(start[0], start[1], unit); selectionModel.update(end[0], end[1], unit); }, /** * Expands tree row * @param {number|string} rowKey - row key * @param {boolean} recursive - true for recursively expand all descendant * @returns {Array.<number|string>} - children or descendant of given row */ expand: function(rowKey, recursive) { return this.modelManager.dataModel.treeExpand(rowKey, recursive); }, /** * Expands all tree row */ expandAll: function() { this.modelManager.dataModel.treeExpandAll(); }, /** * Expands tree row * @param {number|string} rowKey - row key * @param {boolean} recursive - true for recursively expand all descendant * @returns {Array.<number|string>} - children or descendant of given row */ collapse: function(rowKey, recursive) { return this.modelManager.dataModel.treeCollapse(rowKey, recursive); }, /** * Collapses all tree row */ collapseAll: function() { this.modelManager.dataModel.treeCollapseAll(); }, /** * Gets the ancestors of the row which has the given row key * @param {number|string} rowKey - row key * @returns {Array.<TreeRow>} - the ancestor rows */ getAncestors: function(rowKey) { return this.modelManager.dataModel.getTreeAncestors(rowKey); }, /** * Gets the descendants of the row which has the given row key * @param {number|string} rowKey - row key * @returns {Array.<TreeRow>} - the descendant rows */ getDescendants: function(rowKey) { return this.modelManager.dataModel.getTreeDescendants(rowKey); }, /** * Gets the parent of the row which has the given row key * @param {number|string} rowKey - row key * @returns {TreeRow} - the parent row */ getParent: function(rowKey) { return this.modelManager.dataModel.getTreeParent(rowKey); }, /** * Gets the children of the row which has the given row key * @param {number|string} rowKey - row key * @returns {Array.<TreeRow>} - the children rows */ getChildren: function(rowKey) { return this.modelManager.dataModel.getTreeChildren(rowKey); }, /** * Gets the depth of the row which has the given row key * @param {number|string} rowKey - row key to test * @returns {number} - the depth */ getDepth: function(rowKey) { return this.modelManager.dataModel.getTreeDepth(rowKey); }, /** * Destroys the instance. */ destroy: function() { this.modelManager.destroy(); this.container.destroy(); this.modelManager = this.container = null; } }); /** * Returns an instance of the grid associated to the id. * @static * @param {number} id - ID of the target grid * @returns {Grid} - Grid instance * var Grid = tui.Grid; // or re