/**
* @fileoverview The tui.Grid class for the external API.
* @author NHN Ent. FE Development Team
*/
'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=35] - 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 {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=27] - 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 {boolean} [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.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 {boolean} [options.virtualScrolling=true] - If set to true, use virtual-scrolling so that large
* amount of data can be processed performantly.
* @param {boolean} [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.component.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 {boolean} [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 {Array} [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 {Object.<string, Object>} [options.summary.columnContent]
* The object for configuring each column in the summary.
* Sub options below are keyed by each column name.
* @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 {Object} [options.footer] - Deprecated: The object for configuring summary area. This option is replaced by "summary" option.
* @param {number} [options.footer.height] - Deprecated: The height of the summary area.
* @param {Object.<string, Object>} [options.footer.columnContent]
* Deprecated: The object for configuring each column in the summary.
* Sub options below are keyed by each column name.
* @param {boolean} [options.footer.columnContent.useAutoSummary=true]
* Deprecated: 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.footer.columnContent.template] - Deprecated: 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'.
*/
var Grid = View.extend(/** @lends Grid.prototype */{
initialize: function(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);
}
},
/**
* 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);
},
/**
* Replace 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);
},
/**
* Replace 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);
},
/**
* 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);
},
/**
* Insert 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
*/
appendRow: function(row, options) {
this.modelManager.dataModel.append(row, options);
},
/**
* Insert 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.prepend(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 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
*/
setColumns: function(columns) {
this.modelManager.columnModel.set('columns', columns);
},
/**
* Create 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 {tui.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');
},
/**
* Get 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.component.Pagination.
* @returns {tui.component.Pagination}
*/
getPagination: function() {
return this.componentHolder.getInstance('pagination');
},
/**
* Set the width of the dimension.
* @param {number} width - The width of the dimension
*/
setWidth: function(width) {
this.modelManager.dimensionModel.setWidth(width);
},
/**
* Set the height of the dimension.
* @param {number} height - The height of the dimension
*/
setHeight: function(height) {
this.modelManager.dimensionModel.setHeight(height);
},
/**
* Refresh the layout view. Use this method when the view was rendered while hidden.
*/
refreshLayout: function() {
this.modelManager.dimensionModel.refreshLayout();
},
/**
* Reset the width of each column by using initial setting of column models.
*/
resetColumnWidths: function() {
this.modelManager.coordColumnModel.resetColumnWidths();
},
/**
* Show columns
* @param {...string} arguments - Column names to show
*/
showColumn: function() {
var args = snippet.toArray(arguments);
this.modelManager.columnModel.setHidden(args, false);
},
/**
* Hide 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.
* @param {string} columnName - column name
* @param {string} contents - HTML string
*/
setSummaryColumnContent: function(columnName, contents) {
this.modelManager.columnModel.setSummaryContent(columnName, contents);
},
/**
* 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();
},
/**
* Find rows by conditions
* @param {object} conditions - K-V object to find rows (K: column name, V: column value)
* @returns {array} Row list
*/
findRows: function(conditions) {
var rowList = this.modelManager.dataModel.getRows();
return _.where(rowList, 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');
}
},
/**
* Select 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);
},
/**
* 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 {tui.Grid} - Grid instance
* var Grid = tui.Grid; // or require('tui-grid')
*
* Grid.getInstanceById(id);
*/
Grid.getInstanceById = function(id) {
return instanceMap[id];
};
/**
* Apply theme to all grid instances with the preset options of a given name.
* @static
* @param {String} presetName - preset theme name. Available values are 'default', 'striped' and 'clean'.
* @param {Object} [extOptions] - if exist, extend preset options with this object.
* @param {Object} [extOptions.grid] - Styles for the grid (container)
* @param {String} [extOptions.grid.background] - Background color of the grid.
* @param {number} [extOptions.grid.border] - Border color of the grid
* @param {number} [extOptions.grid.text] - Text color of the grid.
* @param {Object} [extOptions.selection] - Styles for a selection layer.
* @param {String} [extOptions.selection.background] - Background color of a selection layer.
* @param {String} [extOptions.selection.border] - Border color of a selection layer.
* @param {Object} [extOptions.scrollbar] - Styles for scrollbars.
* @param {String} [extOptions.scrollbar.background] - Background color of scrollbars.
* @param {String} [extOptions.scrollbar.thumb] - Color of thumbs in scrollbars.
* @param {String} [extOptions.scrollbar.active] - Color of arrows(for IE) or
* thumb:hover(for other browsers) in scrollbars.
* @param {Object} [extOptions.cell] - Styles for the table cells.
* @param {Object} [extOptions.cell.normal] - Styles for normal cells.
* @param {String} [extOptions.cell.normal.background] - Background color of normal cells.
* @param {String} [extOptions.cell.normal.border] - Border color of normal cells.
* @param {String} [extOptions.cell.normal.text] - Text color of normal cells.
* @param {Boolean} [extOptions.cell.normal.showVerticalBorder] - Whether vertical borders of
* normal cells are visible.
* @param {Boolean} [extOptions.cell.normal.showHorizontalBorder] - Whether horizontal borders of
* normal cells are visible.
* @param {Object} [extOptions.cell.head] - Styles for the head cells.
* @param {String} [extOptions.cell.head.background] - Background color of head cells.
* @param {String} [extOptions.cell.head.border] - border color of head cells.
* @param {String} [extOptions.cell.head.text] - text color of head cells.
* @param {Boolean} [extOptions.cell.head.showVerticalBorder] - Whether vertical borders of
* head cells are visible.
* @param {Boolean} [extOptions.cell.head.showHorizontalBorder] - Whether horizontal borders of
* head cells are visible.
* @param {Object} [extOptions.cell.selectedHead] - Styles for selected head cells.
* @param {String} [extOptions.cell.selectedHead.background] - background color of selected haed cells.
* @param {String} [extOptions.cell.selectedHead.text] - text color of selected head cells.
* @param {Object} [extOptions.cell.focused] - Styles for a focused cell.
* @param {String} [extOptions.cell.focused.background] - background color of a focused cell.
* @param {String} [extOptions.cell.focused.border] - border color of a focused cell.
* @param {Object} [extOptions.cell.focusedInactive] - Styles for a inactive focus cell.
* @param {String} [extOptions.cell.focusedInactive.border] - border color of a inactive focus cell.
* @param {Object} [extOptions.cell.required] - Styles for required cells.
* @param {String} [extOptions.cell.required.background] - background color of required cells.
* @param {String} [extOptions.cell.required.text] - text color of required cells.
* @param {Object} [extOptions.cell.editable] - Styles for editable cells.
* @param {String} [extOptions.cell.editable.background] - background color of the editable cells.
* @param {String} [extOptions.cell.editable.text] - text color of the selected editable cells.
* @param {Object} [extOptions.cell.disabled] - Styles for disabled cells.
* @param {String} [extOptions.cell.disabled.background] - background color of disabled cells.
* @param {String} [extOptions.cell.disabled.text] - text color of disabled cells.
* @param {Object} [extOptions.cell.invalid] - Styles for invalid cells.
* @param {String} [extOptions.cell.invalid.background] - background color of invalid cells.
* @param {String} [extOptions.cell.invalid.text] - text color of invalid cells.
* @param {Object} [extOptions.cell.currentRow] - Styles for cells in a current row.
* @param {String} [extOptions.cell.currentRow.background] - background color of cells in a current row.
* @param {String} [extOptions.cell.currentRow.text] - text color of cells in a current row.
* @param {Object} [extOptions.cell.evenRow] - Styles for cells in even rows.
* @param {String} [extOptions.cell.evenRow.background] - background color of cells in even rows.
* @param {String} [extOptions.cell.evenRow.text] - text color of cells in even rows.
* @param {Object} [extOptions.cell.dummy] - Styles for dummy cells.
* @param {String} [extOptions.cell.dummy.background] - background color of dummy cells.
* @example
* var Grid = tui.Grid; // or require('tui-grid')
*
* Grid.applyTheme('striped', {
* grid: {
* border: '#aaa',
* text: '#333'
* },
* cell: {
* disabled: {
* text: '#999'
* }
* }
* });
*/
Grid.applyTheme = function(presetName, extOptions) {
themeManager.apply(presetName, extOptions);
};
/**
* Set language
* @static
* @param {string} localeCode - Code to set locale messages and
* this is the language or language-region combination (ex: en-US)
* @param {object} [data] - Messages using in Grid
* @example
* var Grid = tui.Grid; // or require('tui-grid')
*
* Grid.setLanguage('en'); // default and set English
* Grid.setLanguage('ko'); // set Korean
* Grid.setLanguage('en-US', { // set new language
* display: {
* noData: 'No data.',
* loadingData: 'Loading data.',
* resizeHandleGuide: 'You can change the width of the column by mouse drag, ' +
* 'and initialize the width by double-clicking.'
* },
* net: {
* confirmCreate: 'Are you sure you want to create {{count}} data?',
* confirmUpdate: 'Are you sure you want to update {{count}} data?',
* confirmDelete: 'Are you sure you want to delete {{count}} data?',
* confirmModify: 'Are you sure you want to modify {{count}} data?',
* noDataToCreate: 'No data to create.',
* noDataToUpdate: 'No data to update.',
* noDataToDelete: 'No data to delete.',
* noDataToModify: 'No data to modify.',
* failResponse: 'An error occurred while requesting data.\nPlease try again.'
* }
* });
*/
Grid.setLanguage = function(localeCode, data) {
i18n.setLanguage(localeCode, data);
};
module.exports = Grid;