tui-grid
Version:
TOAST UI Grid : Powerful data grid control supported by TOAST UI
226 lines (191 loc) • 7.29 kB
JavaScript
/**
* @fileoverview ResizeHandle for the Header
* @author NHN. FE Development Lab <dl_javascript@nhn.com>
*/
'use strict';
var $ = require('jquery');
var _ = require('underscore');
var snippet = require('tui-code-snippet');
var View = require('../../base/view');
var constMap = require('../../common/constMap');
var classNameConst = require('../../common/classNameConst');
var DragEventEmitter = require('../../event/dragEventEmitter');
var i18n = require('../../common/i18n');
var attrNameConst = constMap.attrName;
var frameConst = constMap.frame;
var CELL_BORDER_WIDTH = constMap.dimension.CELL_BORDER_WIDTH;
var RESIZE_HANDLE_WIDTH = constMap.dimension.RESIZE_HANDLE_WIDTH;
var EXTRA_WIDTH = 3;
var DEFAULT_WIDTH = 7;
/**
* Resize Handler class
* @module view/layout/resizeHandle
* @extends module:base/view
* @param {Object} options - Options
* @ignore
*/
var ResizeHandle = View.extend(/** @lends module:view/layout/resizeHandle.prototype */ {
initialize: function(options) {
_.assign(this, {
columnModel: options.columnModel,
coordColumnModel: options.coordColumnModel,
dimensionModel: options.dimensionModel,
domEventBus: options.domEventBus,
handleHeights: options.handleHeights,
whichSide: options.whichSide || frameConst.R,
frozenBorder: options.frozenBorder || false
});
this.dragEmitter = new DragEventEmitter({
type: 'resizeColumn',
cursor: 'col-resize',
domEventBus: this.domEventBus,
onDragMove: _.bind(this._onDragMove, this)
});
this.listenTo(this.coordColumnModel, 'columnWidthChanged', this._refreshHandlerPosition);
},
className: classNameConst.COLUMN_RESIZE_CONTAINER,
events: function() {
var eventHash = {};
eventHash['mousedown .' + classNameConst.COLUMN_RESIZE_HANDLE] = '_onMouseDown';
eventHash['dblclick .' + classNameConst.COLUMN_RESIZE_HANDLE] = '_onDblClick';
return eventHash;
},
template: _.template(
'<div ' +
attrNameConst.COLUMN_INDEX + '="<%=columnIndex%>" ' +
attrNameConst.COLUMN_NAME + '="<%=columnName%>" ' +
'class="' + classNameConst.COLUMN_RESIZE_HANDLE + ' <%=lastClass%>" ' +
'title="<%=title%>"' +
'style="width:<%=width%>;height:<%=height%>;display:<%=displayType%>">' +
'</div>'
),
/**
* Return an object that contains an array of column width and an array of column model.
* @returns {{widths: (Array|*), columns: (Array|*)}} Column Data
* @private
*/
_getColumnData: function() {
var columnWidths = this.coordColumnModel.getWidths(this.whichSide);
var columns = this.columnModel.getVisibleColumns(this.whichSide, true);
return {
widths: columnWidths,
columns: columns
};
},
/**
* Returns the HTML string of all handler.
* @returns {String}
* @private
*/
_getResizeHandlerMarkup: function() {
var frozenBorder = this.frozenBorder;
var columns = this._getColumnData().columns;
var length = columns.length;
var width = frozenBorder ? this.dimensionModel.get('frozenBorderWidth') + EXTRA_WIDTH : DEFAULT_WIDTH;
var resizeHandleMarkupList = _.map(frozenBorder ? [_.last(columns)] : columns, function(column, index) {
var columnName = column.name;
return this.template({
lastClass: (index + 1 === length) ? classNameConst.COLUMN_RESIZE_HANDLE_LAST : '',
columnIndex: frozenBorder ? length - 1 : index,
columnName: columnName,
width: width + 'px',
height: this.handleHeights[index] + 'px',
title: i18n.get('resizeHandleGuide'),
displayType: (column.resizable === false) ? 'none' : 'block'
});
}, this);
return resizeHandleMarkupList.join('');
},
/**
* Render
* @returns {module:view/layout/resizeHandle} This object
*/
render: function() {
var headerHeight = this.dimensionModel.get('headerHeight');
var htmlStr = this._getResizeHandlerMarkup();
var styles = {
display: 'block'
};
if (this.frozenBorder) {
this.$el.addClass(classNameConst.FROZEN_BORDER_TOP);
} else {
_.extend(styles, {
marginTop: -headerHeight,
height: headerHeight
});
}
this.$el.empty().html(htmlStr).css(styles);
this._refreshHandlerPosition();
return this;
},
/**
* Refresh the position of every handler.
* @private
*/
_refreshHandlerPosition: function() {
var columnData = this._getColumnData();
var columnWidths = columnData.widths;
var $resizeHandleList = this.$el.find('.' + classNameConst.COLUMN_RESIZE_HANDLE);
var handlerWidthHalf = Math.floor(RESIZE_HANDLE_WIDTH / 2);
var curPos = 0;
var left = 0;
snippet.forEachArray($resizeHandleList, function(item, index) {
var $handler = $resizeHandleList.eq(index);
if (!this.frozenBorder) {
curPos += columnWidths[index] + CELL_BORDER_WIDTH;
left = curPos - handlerWidthHalf;
}
$handler.css('left', left);
}, this);
},
/**
* Event handler for the 'mousedown' event
* @param {MouseEvent} ev - mouse event
* @private
*/
_onMouseDown: function(ev) {
var $target = $(ev.target);
var columnWidths = this.coordColumnModel.getWidths(this.whichSide);
var columnIndex = parseInt($target.attr(attrNameConst.COLUMN_INDEX), 10);
this.dragEmitter.start(ev, {
width: columnWidths[columnIndex],
columnIndex: this._getHandlerColumnIndex(columnIndex),
pageX: ev.pageX
});
},
/**
* Event handler for dragmove event
* @param {module:event/gridEvent} ev - GridEvent
* @private
*/
_onDragMove: function(ev) {
var startData = ev.startData;
var diff = ev.pageX - startData.pageX;
ev.setData({
columnIndex: startData.columnIndex,
width: startData.width + diff
});
},
/**
* Event handler for the 'dblclick' event
* @param {MouseEvent} mouseEvent - mouse event
* @private
*/
_onDblClick: function(mouseEvent) {
var $target = $(mouseEvent.target);
var columnIndex = parseInt($target.attr(attrNameConst.COLUMN_INDEX), 10);
this.domEventBus.trigger('dblclick:resizeColumn', {
columnIndex: this._getHandlerColumnIndex(columnIndex)
});
},
/**
* Find the real index (based on visibility) of the column using index value of the handler and returns it.
* @param {number} index - index value of the handler
* @returns {number}
* @private
*/
_getHandlerColumnIndex: function(index) {
return (this.whichSide === frameConst.R) ? (index + this.columnModel.getVisibleFrozenCount(true)) : index;
}
});
module.exports = ResizeHandle;