comindware.ui
Version:
Comindware Core UI provides the basic components like editors, lists, dropdowns, popups that we so desperately need while creating Marionette-based single-page applications.
275 lines (222 loc) • 9.22 kB
JavaScript
/**
* Developer: Grigory Kuznetsov
* Date: 17.08.2015
* Copyright: 2009-2016 Comindware®
* All Rights Reserved
* Published under the MIT license
*/
'use strict';
import template from '../templates/header.hbs';
import { Handlebars } from 'lib';
import GridHeaderView from '../../list/views/GridHeaderView';
import GlobalEventService from '../../services/GlobalEventService';
/**
* @name HeaderView
* @memberof module:core.nativeGrid.views
* @class HeaderView
* @description View заголовка списка
* @extends module:core.list.views.GridHeaderView {@link module:core.list.views.GridHeaderView}
* @param {Object} options Constructor options
* @param {Array} options.columns Массив колонок
* @param {Object} options.gridEventAggregator ?
* @param {Backbone.View} options.gridColumnHeaderView View Используемый для отображения заголовка (шапки) списка
* */
const HeaderView = GridHeaderView.extend({
initialize(options) {
GridHeaderView.prototype.initialize.apply(this, arguments);
_.bindAll(this, '__draggerMouseUp', '__draggerMouseMove', '__handleResizeInternal', '__handleColumnSort');
this.listenTo(GlobalEventService, 'window:resize', this.__handleResizeInternal);
},
template: Handlebars.compile(template),
onRender() {
const self = this;
this.ui.gridHeaderColumnContent.each((i, el) => {
const column = self.columns[i];
const view = new self.gridColumnHeaderView(_.extend(self.gridColumnHeaderViewOptions || {}, {
model: column.viewModel,
column,
gridEventAggregator: self.gridEventAggregator
}));
self.listenTo(view, 'columnSort', self.__handleColumnSort);
const childEl = view.render().el;
el.appendChild(childEl);
});
},
constants: {
MIN_COLUMN_WIDTH: 100
},
__getAvailableWidth() {
return this.$el.parent().width() - 1;
},
__getElementOuterWidth(el) {
return $(el)[0].getBoundingClientRect().width;
},
setFitToView() {
let availableWidth = this.__getAvailableWidth(),
viewWidth = this.__getTableWidth(),
columnsL = this.ui.gridHeaderColumn.length,
fullWidth = 0,
sumDelta = 0,
sumGap = 0;
this.ui.gridHeaderColumn.each((i, el) => {
if (availableWidth !== viewWidth) {
var columnWidth = this.__getElementOuterWidth(el) * availableWidth / viewWidth;
if (columnWidth < this.constants.MIN_COLUMN_WIDTH) {
sumDelta += this.constants.MIN_COLUMN_WIDTH - columnWidth;
columnWidth = this.constants.MIN_COLUMN_WIDTH;
} else {
sumGap += columnWidth - this.constants.MIN_COLUMN_WIDTH;
}
}
this.columns[i].width = columnWidth;
});
this.ui.gridHeaderColumn.each((i, el) => {
if (availableWidth !== viewWidth) {
if (this.columns[i].width > this.constants.MIN_COLUMN_WIDTH) {
const delta = (this.columns[i].width - this.constants.MIN_COLUMN_WIDTH) * sumDelta / sumGap;
this.columns[i].width -= delta;
}
}
if (i === columnsL - 1 && fullWidth + this.columns[i].width < availableWidth) {
this.columns[i].width = availableWidth - fullWidth;
}
$(el).outerWidth(this.columns[i].width);
fullWidth += this.columns[i].width;
});
this.$el.width(Math.ceil(fullWidth));
},
__setInitialWidth(availableWidth) {
const columnsL = this.ui.gridHeaderColumn.length;
const columnWidthData = this.__getColumnsWidthData(availableWidth, this.columns);
let fullWidth = 0;
this.ui.gridHeaderColumn.each((i, el) => {
const columnWidth = columnWidthData[i];
if (i === columnsL - 1 && fullWidth + this.columns[i].width < availableWidth) {
this.columns[i].width = availableWidth - fullWidth;
}
$(el).outerWidth(columnWidth);
this.columns[i].width = columnWidth;
fullWidth += columnWidth;
});
this.$el.width(Math.ceil(fullWidth));
},
__getColumnsWidthData(availableWidth, columns) {
const columnWidthData = [];
let availableDynamicWidth = availableWidth;
let nonStaticColumnsCount = columns.length;
this.ui.gridHeaderColumn.each((i, el) => {
let columnWidth;
if (columns[i].width) {
columnWidth = columns[i].width;
--nonStaticColumnsCount;
} else {
columnWidth = Math.max($(el).outerWidth(), this.constants.MIN_COLUMN_WIDTH);
}
availableDynamicWidth -= columnWidth;
columnWidthData.push(columnWidth);
});
if (availableDynamicWidth > 0) {
const columnAdditionalWidth = availableDynamicWidth / nonStaticColumnsCount;
columns.forEach((column, i) => {
if (!column.width) {
columnWidthData[i] += columnAdditionalWidth;
}
});
}
return columnWidthData;
},
onShow() {
this.headerMinWidth = this.__getAvailableWidth();
this.__setInitialWidth(this.headerMinWidth);
this.__handleResizeInternal();
},
__startDrag(e) {
const $dragger = $(e.target);
const $column = $dragger.parent();
this.updateDragContext($column, e.pageX);
this.dragContext.tableInitialWidth = this.__getTableWidth();
this.dragContext.$dragger = $dragger;
$dragger.addClass('active');
this.$document.mousemove(this.__draggerMouseMove).mouseup(this.__draggerMouseUp);
},
__stopDrag() {
if (!this.dragContext) {
return;
}
this.dragContext.$dragger.removeClass('active');
this.dragContext = null;
this.$document.unbind('mousemove', this.__draggerMouseMove);
this.$document.unbind('mouseup', this.__draggerMouseUp);
this.gridEventAggregator.trigger('columnStopDrag');
},
__draggerMouseMove(e) {
if (!this.dragContext) {
return;
}
const ctx = this.dragContext;
const delta = e.pageX - ctx.pageOffsetX;
if (delta !== 0) {
const index = ctx.draggedColumn.index;
this.updateColumnAndNeighbourWidths(index, delta);
}
return false;
},
updateColumnAndNeighbourWidths(index, delta) {
let $current = $(this.ui.gridHeaderColumn[index]),
newColumnWidth = this.dragContext.draggedColumn.initialWidth + delta;
if (this.dragContext.draggedColumn.initialWidth + delta < this.constants.MIN_COLUMN_WIDTH) {
return;
}
$current.outerWidth(newColumnWidth);
this.gridEventAggregator.trigger('singleColumnResize', this, {
index,
delta
});
this.__changeTableWidth(this.dragContext.tableInitialWidth, delta);
this.columns[index].width = newColumnWidth;
},
__changeTableWidth(initialWidth, delta) {
this.$el.width(initialWidth + delta + 1);
},
updateDragContext($column, offset) {
this.dragContext = this.dragContext || {};
const draggedColumn = {
$el: $column,
initialWidth: this.__getElementOuterWidth($column),
index: $column.index()
};
this.dragContext.tableInitialWidth = this.__getTableWidth();
this.gridEventAggregator.trigger('columnStartDrag', this, draggedColumn.index);
this.dragContext.fullWidth = this.headerMinWidth;
this.dragContext.draggedColumn = draggedColumn;
this.dragContext.pageOffsetX = offset;
},
__getTableWidth() {
return this.$el.width() - 1;
},
__handleResizeInternal() {
let fullWidth = this.__getAvailableWidth(),
currentWidth = this.__getTableWidth();
if (fullWidth > currentWidth) {
this.$el.width(fullWidth);
}
this.headerMinWidth = fullWidth;
this.__updateColumnsWidth();
},
__updateColumnsWidth() {
let columns = this.columns,
needUpdate = false,
fullWidth = 0;
this.ui.gridHeaderColumn.each((i, el) => {
const child = $(el);
const col = columns[i];
if (col.width) {
needUpdate = true;
child.outerWidth(col.width);
fullWidth += col.width;
}
});
needUpdate && this.$el.width(fullWidth);
}
});
export default HeaderView;