UNPKG

tui-grid

Version:

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

266 lines (223 loc) 7.91 kB
/** * @fileoverview Class for the body layout * @author NHN. FE Development Lab <dl_javascript@nhn.com> */ 'use strict'; var $ = require('jquery'); var _ = require('underscore'); var View = require('../../base/view'); var DragEventEmitter = require('../../event/dragEventEmitter'); var GridEvent = require('../../event/gridEvent'); var util = require('../../common/util'); var constMap = require('../../common/constMap'); var classNameConst = require('../../common/classNameConst'); var frameConst = constMap.frame; // Minimum time (ms) to detect if an alert or confirm dialog has been displayed. var MIN_INTERVAL_FOR_PAUSED = 200; // Minimum distance (pixel) to detect if user wants to drag when moving mouse with button pressed. var MIN_DISATNCE_FOR_DRAG = 10; /** * Class for the body layout * @module view/layout/body * @extends module:base/view * @param {Object} options - Options * @param {String} [options.whichSide=R] L or R (which side) * @ignore */ var Body = View.extend(/** @lends module:view/layout/body.prototype */{ initialize: function(options) { View.prototype.initialize.call(this); _.assign(this, { dimensionModel: options.dimensionModel, renderModel: options.renderModel, viewFactory: options.viewFactory, domEventBus: options.domEventBus, // DIV for setting rendering position of entire child-nodes of $el. $container: null, whichSide: (options && options.whichSide) || frameConst.R }); this.listenTo(this.dimensionModel, 'change:bodyHeight', this._onBodyHeightChange) .listenTo(this.dimensionModel, 'change:totalRowHeight', this._resetContainerHeight) .listenTo(this.renderModel, 'change:scrollTop', this._onScrollTopChange) .listenTo(this.renderModel, 'change:scrollLeft', this._onScrollLeftChange); this.dragEmitter = new DragEventEmitter({ type: 'body', domEventBus: this.domEventBus, onDragMove: _.bind(this._onDragMove, this) }); }, className: classNameConst.BODY_AREA, events: function() { var hash = {}; hash.scroll = '_onScroll'; hash['mousedown .' + classNameConst.BODY_CONTAINER] = '_onMouseDown'; return hash; }, /** * Event handler for 'change:bodyHeight' event on module:model/dimension * @param {Object} model - changed model * @param {Number} value - new height value * @private */ _onBodyHeightChange: function(model, value) { this.$el.css('height', value + 'px'); }, /** * Resets the height of a container DIV * @private */ _resetContainerHeight: function() { this.$container.css({ height: this.dimensionModel.get('totalRowHeight') }); }, /** * Event handler for 'scroll' event on DOM * @param {UIEvent} event - event object * @private */ _onScroll: function(event) { var attrs = { scrollTop: event.target.scrollTop }; if (this.whichSide === frameConst.R) { attrs.scrollLeft = event.target.scrollLeft; } this.renderModel.set(attrs); }, /** * Event handler for 'change:scrollLeft' event on module:model/renderer * @param {Object} model - changed model * @param {Number} value - new scrollLeft value * @private */ _onScrollLeftChange: function(model, value) { if (this.whichSide === frameConst.R) { this.el.scrollLeft = value; } }, /** * Event handler for 'chage:scrollTop' event on module:model/renderer * @param {Object} model - changed model instance * @param {Number} value - new scrollTop value * @private */ _onScrollTopChange: function(model, value) { this.el.scrollTop = value; }, /** * Mousedown event handler * @param {MouseEvent} ev - MouseEvent * @private */ _onMouseDown: function(ev) { var $target = $(ev.target); var isTargetInput = $target.is('input, teaxarea'); if (!this._triggerPublicMousedown(ev)) { return; } this._triggerBodyMousedown(ev); if (isTargetInput && ev.shiftKey) { ev.preventDefault(); } if (util.isRightClickEvent(ev)) { return; } if (!isTargetInput || ev.shiftKey) { this.dragEmitter.start(ev, { pageX: ev.pageX, pageY: ev.pageY }); } }, /** * Trigger mousedown event on domEventBus and returns the result * @param {MouseEvent} ev - MouseEvent * @returns {module:event/gridEvent} * @private */ _triggerPublicMousedown: function(ev) { var startTime, endTime; var gridEvent = new GridEvent(ev, GridEvent.getTargetInfo($(ev.target))); var result = true; if (gridEvent.targetType === GridEvent.targetTypeConst.DUMMY) { result = false; } else { startTime = (new Date()).getTime(); this.domEventBus.trigger('mousedown', gridEvent); if (gridEvent.isStopped()) { result = false; } else { // check if the model window (alert or confirm) was popped up endTime = (new Date()).getTime(); result = (endTime - startTime) <= MIN_INTERVAL_FOR_PAUSED; } } return result; }, /** * Trigger mousedown:body event on domEventBus * @param {MouseEvent} ev - MouseEvent * @private */ _triggerBodyMousedown: function(ev) { var gridEvent = new GridEvent(ev, { pageX: ev.pageX, pageY: ev.pageY, shiftKey: ev.shiftKey }); this.domEventBus.trigger('mousedown:body', gridEvent); }, /** * Event handler for dragmove * @param {event:module/gridEvent} gridEvent - GridEvent */ _onDragMove: function(gridEvent) { var startData = gridEvent.startData; var currentData = { pageX: gridEvent.pageX, pageY: gridEvent.pageY }; if (this._getMouseMoveDistance(startData, currentData) < MIN_DISATNCE_FOR_DRAG) { gridEvent.stop(); } }, /** * Returns the distance between start position and current position. * @param {{pageX:number, pageY:number}} start - start position * @param {{pageX:number, pageY:number}} current - current position * @returns {number} * @private */ _getMouseMoveDistance: function(start, current) { var dx = Math.abs(start.pageX - current.pageX); var dy = Math.abs(start.pageY - current.pageY); return Math.round(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2))); }, /** * renders * @returns {module:view/layout/body} */ render: function() { var whichSide = this.whichSide; this._destroyChildren(); if (!this.dimensionModel.get('scrollX')) { this.$el.css('overflow-x', 'hidden'); } if (!this.dimensionModel.get('scrollY') && whichSide === frameConst.R) { this.$el.css('overflow-y', 'hidden'); } this.$el.css('height', this.dimensionModel.get('bodyHeight')); this.$container = $('<div>').addClass(classNameConst.BODY_CONTAINER); this.$el.append(this.$container); this._addChildren([ this.viewFactory.createBodyTable(whichSide), this.viewFactory.createSelectionLayer(whichSide), this.viewFactory.createFocusLayer(whichSide) ]); this.$container.append(this._renderChildren()); this._resetContainerHeight(); return this; } }); module.exports = Body;