tui-grid
Version:
TOAST UI Grid : Powerful data grid control supported by TOAST UI
244 lines (210 loc) • 7.72 kB
JavaScript
/**
* @fileoverview Painter class for cell(TD) views
* @author NHN. FE Development Lab <dl_javascript@nhn.com>
*/
'use strict';
var _ = require('underscore');
var snippet = require('tui-code-snippet');
var Painter = require('../base/painter');
var util = require('../common/util');
var attrNameConst = require('../common/constMap').attrName;
var classNameConst = require('../common/classNameConst');
/**
* Painter class for cell(TD) views
* @module painter/cell
* @extends module:base/painter
* @param {Object} options - options
* @ignore
*/
var Cell = snippet.defineClass(Painter, /** @lends module:painter/cell.prototype */{
init: function(options) {
Painter.apply(this, arguments);
this.editType = options.editType;
this.fixedRowHeight = options.fixedRowHeight;
this.inputPainter = options.inputPainter;
this.selector = 'td[' + attrNameConst.EDIT_TYPE + '="' + this.editType + '"]';
},
/**
* template for TD
* @returns {string} template
*/
template: _.template(
'<td <%=attributeString%> style="<%=style%>"><%=contentHtml%></td>'
),
/**
* template for DIV (inner content of TD)
*/
contentTemplate: _.template(
'<div class="<%=className%>" style="<%=style%>"><%=content%></div>'
),
/**
* Returns whether the instance is editable type.
* @returns {Boolean}
*/
_isEditableType: function() {
return !_.contains(['normal', 'mainButton'], this.editType);
},
/**
* Returns css style string for given cellData
* @param {Object} cellData - cell data
* @returns {string}
*/
_getContentStyle: function(cellData) {
var whiteSpace = cellData.columnModel.whiteSpace || 'nowrap';
var styles = [];
if (whiteSpace) {
styles.push('white-space:' + whiteSpace);
}
if (this.fixedRowHeight) {
styles.push('max-height:' + cellData.height + 'px');
}
return styles.join(';');
},
/**
* Returns the HTML string of the contents containg the value of the 'prefix' and 'postfix'.
* @param {Object} cellData - cell data
* @returns {String}
* @private
*/
_getContentHtml: function(cellData) {
var customTemplate = cellData.columnModel.template;
var content = cellData.formattedValue;
var prefix = cellData.prefix;
var postfix = cellData.postfix;
var fullContent, template;
if (this.inputPainter) {
content = this.inputPainter.generateHtml(cellData);
if (this._shouldContentBeWrapped() && !this._isUsingViewMode(cellData)) {
prefix = this._getSpanWrapContent(prefix, classNameConst.CELL_CONTENT_BEFORE);
postfix = this._getSpanWrapContent(postfix, classNameConst.CELL_CONTENT_AFTER);
content = this._getSpanWrapContent(content, classNameConst.CELL_CONTENT_INPUT);
// notice the order of concatenation
fullContent = prefix + postfix + content;
}
}
if (!fullContent) {
fullContent = prefix + content + postfix;
}
if (cellData.columnName === '_number' && _.isFunction(customTemplate)) {
template = customTemplate({
content: fullContent
});
} else {
template = this.contentTemplate({
content: fullContent,
className: classNameConst.CELL_CONTENT,
style: this._getContentStyle(cellData)
});
}
return template;
},
/**
* Returns whether the cell has view mode.
* @param {Object} cellData - cell data
* @returns {Boolean}
* @private
*/
_isUsingViewMode: function(cellData) {
return snippet.pick(cellData, 'columnModel', 'editOptions', 'useViewMode') !== false;
},
/**
* Returns whether the contents should be wrapped with span tags to display them correctly.
* @returns {Boolean}
* @private
*/
_shouldContentBeWrapped: function() {
return _.contains(['text', 'password', 'select'], this.editType);
},
/**
* 주어진 문자열을 span 태그로 감싼 HTML 코드를 반환한다.
* @param {string} content - 감싸질 문자열
* @param {string} className - span 태그의 클래스명
* @returns {string} span 태그로 감싼 HTML 코드
* @private
*/
_getSpanWrapContent: function(content, className) {
if (snippet.isFalsy(content)) {
content = '';
}
return '<span class="' + className + '">' + content + '</span>';
},
/**
* Returns the object contains attributes of a TD element.
* @param {Object} cellData - cell data
* @returns {Object}
* @private
*/
_getAttributes: function(cellData) {
var classNames = [
cellData.className,
classNameConst.CELL
];
var attrs = {
'align': cellData.columnModel.align || 'left'
};
attrs['class'] = classNames.join(' ');
attrs[attrNameConst.EDIT_TYPE] = this.editType;
attrs[attrNameConst.ROW_KEY] = cellData.rowKey;
attrs[attrNameConst.COLUMN_NAME] = cellData.columnName;
if (cellData.rowSpan) {
attrs.rowspan = cellData.rowSpan;
}
return attrs;
},
/**
* Attaches all event handlers to the $target element.
* @param {jquery} $target - target element
* @param {String} parentSelector - selector of a parent element
* @override
*/
attachEventHandlers: function($target, parentSelector) {
Painter.prototype.attachEventHandlers.call(this, $target, parentSelector);
if (this.inputPainter) {
this.inputPainter.attachEventHandlers($target, parentSelector + ' ' + this.selector);
}
},
/**
* Generates a HTML string from given data, and returns it.
* @param {object} cellData - cell data
* @returns {string} HTML string of the cell (TD)
* @implements {module:base/painter}
*/
generateHtml: function(cellData) {
var attributeString = util.getAttributesString(this._getAttributes(cellData));
var contentHtml = this._getContentHtml(cellData);
var valign = cellData.columnModel.valign;
var styles = [];
if (valign) {
styles.push('vertical-align:' + valign);
}
return this.template({
attributeString: attributeString,
style: styles.join(';'),
contentHtml: contentHtml
});
},
/**
* Refreshes the cell(td) element.
* @param {object} cellData - cell data
* @param {jQuery} $td - cell element
*/
refresh: function(cellData, $td) {
var contentProps = ['value', 'editing', 'disabled', 'listItems'];
var editingChangedToTrue = _.contains(cellData.changed, 'editing') && cellData.editing;
var shouldUpdateContent = _.intersection(contentProps, cellData.changed).length > 0;
var mainButton = this.editType === 'mainButton';
$td.attr(this._getAttributes(cellData));
if (editingChangedToTrue && !this._isUsingViewMode(cellData)) {
this.inputPainter.focus($td);
} else if (mainButton) {
$td.find(this.inputPainter.selector).prop({
checked: cellData.value,
disabled: cellData.disabled
});
} else if (shouldUpdateContent) {
$td.html(this._getContentHtml(cellData));
$td.scrollLeft(0);
}
}
});
module.exports = Cell;