devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
632 lines (519 loc) • 20.5 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
Class = require("../../core/class"),
getPublicElement = require("../../core/utils/dom").getPublicElement,
extend = require("../../core/utils/extend").extend,
isDefined = require("../../core/utils/type").isDefined;
var PIVOTGRID_EXPAND_CLASS = "dx-expand";
var getRealElementWidth = function getRealElementWidth(element) {
var width = 0,
clientRect;
if (element.getBoundingClientRect) {
clientRect = element.getBoundingClientRect();
width = clientRect.width;
if (!width) {
width = clientRect.right - clientRect.left;
}
}
if (width > 0) {
return width;
} else {
return element.offsetWidth;
}
};
function getFakeTableOffset(scrollPos, elementOffset, tableSize, viewPortSize) {
var offset = 0,
halfTableCount = 0,
halfTableSize = tableSize / 2;
if (scrollPos + viewPortSize - (elementOffset + tableSize) > 1) {
if (scrollPos >= elementOffset + tableSize + halfTableSize) {
halfTableCount = parseInt((scrollPos - (elementOffset + tableSize)) / halfTableSize, 10);
}
offset = elementOffset + tableSize + halfTableSize * halfTableCount;
} else if (scrollPos < elementOffset) {
if (scrollPos <= elementOffset - halfTableSize) {
halfTableCount = parseInt((scrollPos - (elementOffset - halfTableSize)) / halfTableSize, 10);
}
offset = elementOffset - (tableSize - halfTableSize * halfTableCount);
} else {
offset = elementOffset;
}
return offset;
}
///#DEBUG
exports.getRealElementWidth = getRealElementWidth;
///#ENDDEBUG
exports.AreaItem = Class.inherit({
_getRowElement: function _getRowElement(index) {
var that = this;
if (that._tableElement && that._tableElement.length > 0) {
return that._tableElement[0].rows[index];
}
return null;
},
_createGroupElement: function _createGroupElement() {
return $('<div>');
},
_createTableElement: function _createTableElement() {
return $('<table>');
},
_getCellText: function _getCellText(cell, encodeHtml) {
var cellText = cell.isWhiteSpace ? " " : cell.text || " ";
if (encodeHtml && (cellText.indexOf("<") !== -1 || cellText.indexOf(">") !== -1)) {
cellText = $("<div>").text(cellText).html();
}
return cellText;
},
_getRowClassNames: function _getRowClassNames() {},
_applyCustomStyles: function _applyCustomStyles(options) {
if (options.cell.width) {
options.cssArray.push("min-width:" + options.cell.width + "px");
}
if (options.cell.sorted) {
options.classArray.push("dx-pivotgrid-sorted");
}
},
_getMainElementMarkup: function _getMainElementMarkup() {
return "<tbody>";
},
_getCloseMainElementMarkup: function _getCloseMainElementMarkup() {
return "</tbody>";
},
_renderTableContent: function _renderTableContent(tableElement, data) {
var that = this,
rowsCount = data.length,
row,
cell,
i,
j,
rowElement,
cellElement,
cellText,
rtlEnabled = that.option("rtlEnabled"),
markupArray = [],
encodeHtml = that.option("encodeHtml"),
rowClassNames,
colspan = "colspan='",
rowspan = "rowspan='";
tableElement.data("area", that._getAreaName());
tableElement.data("data", data);
tableElement.css("width", "");
markupArray.push(that._getMainElementMarkup());
for (i = 0; i < rowsCount; i++) {
row = data[i];
var columnMarkupArray = [];
rowClassNames = [];
markupArray.push("<tr ");
for (j = 0; j < row.length; j++) {
cell = row[j];
this._getRowClassNames(i, cell, rowClassNames);
columnMarkupArray.push("<td ");
if (cell) {
cell.rowspan && columnMarkupArray.push(rowspan + (cell.rowspan || 1) + "'");
cell.colspan && columnMarkupArray.push(colspan + (cell.colspan || 1) + "'");
var styleOptions = {
cellElement: cellElement,
cell: cell,
cellsCount: row.length,
cellIndex: j,
rowElement: rowElement,
rowIndex: i,
rowsCount: rowsCount,
rtlEnabled: rtlEnabled,
classArray: [],
cssArray: []
};
that._applyCustomStyles(styleOptions);
if (styleOptions.cssArray.length) {
columnMarkupArray.push("style='");
columnMarkupArray.push(styleOptions.cssArray.join(";"));
columnMarkupArray.push("'");
}
if (styleOptions.classArray.length) {
columnMarkupArray.push("class='");
columnMarkupArray.push(styleOptions.classArray.join(" "));
columnMarkupArray.push("'");
}
columnMarkupArray.push(">");
if (isDefined(cell.expanded)) {
columnMarkupArray.push("<div class='dx-expand-icon-container'><span class='" + PIVOTGRID_EXPAND_CLASS + "'></span></div>");
}
cellText = this._getCellText(cell, encodeHtml);
} else {
cellText = "";
}
columnMarkupArray.push("<span ");
if (isDefined(cell.wordWrapEnabled)) {
columnMarkupArray.push("style='white-space:", cell.wordWrapEnabled ? "normal" : "nowrap", ";'");
}
columnMarkupArray.push(">" + cellText + "</span>");
if (cell.sorted) {
columnMarkupArray.push("<span class='dx-icon-sorted'></span>");
}
columnMarkupArray.push("</td>");
}
if (rowClassNames.length) {
markupArray.push("class='");
markupArray.push(rowClassNames.join(" "));
markupArray.push("'");
}
markupArray.push(">");
markupArray.push(columnMarkupArray.join(""));
markupArray.push("</tr>");
}
markupArray.push(this._getCloseMainElementMarkup());
tableElement.append(markupArray.join(""));
this._triggerOnCellPrepared(tableElement, data);
},
_triggerOnCellPrepared: function _triggerOnCellPrepared(tableElement, data) {
var that = this,
rowElements = tableElement.find("tr"),
areaName = that._getAreaName(),
onCellPrepared = that.option("onCellPrepared"),
hasEvent = that.component.hasEvent("cellPrepared"),
rowElement,
$cellElement,
onCellPreparedArgs,
defaultActionArgs = this.component._defaultActionArgs(),
row,
cell,
rowIndex,
columnIndex;
if (onCellPrepared || hasEvent) {
for (rowIndex = 0; rowIndex < data.length; rowIndex++) {
row = data[rowIndex];
rowElement = rowElements.eq(rowIndex);
for (columnIndex = 0; columnIndex < row.length; columnIndex++) {
cell = row[columnIndex];
$cellElement = rowElement.children().eq(columnIndex);
onCellPreparedArgs = {
area: areaName,
rowIndex: rowIndex,
columnIndex: columnIndex,
cellElement: getPublicElement($cellElement),
cell: cell
};
if (hasEvent) {
that.component._trigger("onCellPrepared", onCellPreparedArgs);
} else {
onCellPrepared(extend(onCellPreparedArgs, defaultActionArgs));
}
}
}
}
},
_getRowHeight: function _getRowHeight(index) {
var row = this._getRowElement(index),
clientRect,
height = 0;
if (row && row.lastChild) {
if (row.getBoundingClientRect) {
clientRect = row.getBoundingClientRect();
height = clientRect.height;
}
if (height > 0) {
return height;
} else {
return row.offsetHeight;
}
}
return 0;
},
_setRowHeight: function _setRowHeight(index, value) {
var row = this._getRowElement(index);
if (row) {
row.style.height = value + 'px';
}
},
ctor: function ctor(component) {
this.component = component;
},
option: function option() {
return this.component.option.apply(this.component, arguments);
},
getRowsLength: function getRowsLength() {
var that = this;
if (that._tableElement && that._tableElement.length > 0) {
return that._tableElement[0].rows.length;
}
return 0;
},
getRowsHeight: function getRowsHeight() {
var that = this,
result = [],
rowsLength = that.getRowsLength(),
i;
for (i = 0; i < rowsLength; i++) {
result.push(that._getRowHeight(i));
}
return result;
},
setRowsHeight: function setRowsHeight(values) {
var that = this,
totalHeight = 0,
valuesLength = values.length,
i;
for (i = 0; i < valuesLength; i++) {
totalHeight += values[i];
that._setRowHeight(i, values[i]);
}
this._tableHeight = totalHeight;
this._tableElement[0].style.height = totalHeight + 'px';
},
getColumnsWidth: function getColumnsWidth() {
var rowsLength = this.getRowsLength(),
rowIndex,
row,
i,
columnIndex,
processedCells = [],
result = [],
fillCells = function fillCells(cells, rowIndex, columnIndex, rowSpan, colSpan) {
var rowOffset, columnOffset;
for (rowOffset = 0; rowOffset < rowSpan; rowOffset++) {
for (columnOffset = 0; columnOffset < colSpan; columnOffset++) {
cells[rowIndex + rowOffset] = cells[rowIndex + rowOffset] || [];
cells[rowIndex + rowOffset][columnIndex + columnOffset] = true;
}
}
};
if (rowsLength) {
for (rowIndex = 0; rowIndex < rowsLength; rowIndex++) {
processedCells[rowIndex] = processedCells[rowIndex] || [];
row = this._getRowElement(rowIndex);
for (i = 0; i < row.cells.length; i++) {
for (columnIndex = 0; processedCells[rowIndex][columnIndex]; columnIndex++) {}
fillCells(processedCells, rowIndex, columnIndex, row.cells[i].rowSpan, row.cells[i].colSpan);
if (row.cells[i].colSpan === 1) {
result[columnIndex] = result[columnIndex] || getRealElementWidth(row.cells[i]);
}
}
}
}
return result;
},
setColumnsWidth: function setColumnsWidth(values) {
var i,
totalWidth = 0,
tableElement = this._tableElement[0],
colgroupElementHTML = '',
columnsCount = this.getColumnsCount(),
columnWidth = [];
for (i = 0; i < columnsCount; i++) {
columnWidth.push(values[i] || 0);
}
for (i = columnsCount; i < values.length && values; i++) {
columnWidth[columnsCount - 1] += values[i];
}
for (i = 0; i < columnsCount; i++) {
totalWidth += columnWidth[i];
colgroupElementHTML += '<col style="width: ' + columnWidth[i] + 'px">';
}
this._colgroupElement.html(colgroupElementHTML);
this._tableWidth = totalWidth;
tableElement.style.width = totalWidth + 'px';
tableElement.style.tableLayout = 'fixed';
},
resetColumnsWidth: function resetColumnsWidth() {
this._colgroupElement.find('col').width('auto');
this._tableElement.css({
width: '',
tableLayout: ''
});
},
groupWidth: function groupWidth(value) {
if (value === undefined) {
return this._groupElement.width();
} else if (value >= 0) {
this._groupWidth = value;
return this._groupElement[0].style.width = value + 'px';
} else {
return this._groupElement[0].style.width = value;
}
},
groupHeight: function groupHeight(value) {
if (value === undefined) {
return this._groupElement.height();
}
this._groupHeight = null;
if (value >= 0) {
this._groupHeight = value;
this._groupElement[0].style.height = value + 'px';
} else {
this._groupElement[0].style.height = value;
}
},
groupElement: function groupElement() {
return this._groupElement;
},
tableElement: function tableElement() {
return this._tableElement;
},
element: function element() {
return this._rootElement;
},
headElement: function headElement() {
return this._tableElement.find('thead');
},
_setTableCss: function _setTableCss(styles) {
if (this.option("rtlEnabled")) {
styles.right = styles.left;
delete styles.left;
}
this.tableElement().css(styles);
},
setVirtualContentParams: function setVirtualContentParams(params) {
this._virtualContent.css({
width: params.width,
height: params.height
});
this.groupElement().addClass("dx-virtual-mode");
},
disableVirtualMode: function disableVirtualMode() {
this.groupElement().removeClass("dx-virtual-mode");
},
_renderVirtualContent: function _renderVirtualContent() {
var that = this;
if (!that._virtualContent && that.option("scrolling.mode") === "virtual") {
that._virtualContent = $("<div>").addClass("dx-virtual-content").insertBefore(that._tableElement);
}
},
reset: function reset() {
var that = this,
tableElement = that._tableElement[0];
that._fakeTable && that._fakeTable.detach();
that._fakeTable = null;
that.disableVirtualMode();
that.groupWidth("100%");
that.groupHeight("auto");
that.resetColumnsWidth();
if (tableElement) {
for (var i = 0; i < tableElement.rows.length; i++) {
tableElement.rows[i].style.height = "";
}
tableElement.style.height = "";
tableElement.style.width = "100%";
}
},
_updateFakeTableVisibility: function _updateFakeTableVisibility() {
var that = this,
tableElement = that.tableElement()[0],
horizontalOffsetName = that.option("rtlEnabled") ? "right" : "left",
fakeTableElement = that._fakeTable[0];
if (tableElement.style.top === fakeTableElement.style.top && fakeTableElement.style[horizontalOffsetName] === tableElement.style[horizontalOffsetName]) {
that._fakeTable.addClass("dx-hidden");
} else {
that._fakeTable.removeClass("dx-hidden");
}
},
_moveFakeTableHorizontally: function _moveFakeTableHorizontally(scrollPos) {
var that = this,
rtlEnabled = that.option("rtlEnabled"),
offsetStyleName = rtlEnabled ? "right" : "left",
tableElementOffset = parseFloat(that.tableElement()[0].style[offsetStyleName]),
offset = getFakeTableOffset(scrollPos, tableElementOffset, that._tableWidth, that._groupWidth);
if (parseFloat(that._fakeTable[0].style[offsetStyleName]) !== offset) {
that._fakeTable[0].style[offsetStyleName] = offset + "px";
}
},
_moveFakeTableTop: function _moveFakeTableTop(scrollPos) {
var that = this,
tableElementOffsetTop = parseFloat(that.tableElement()[0].style.top),
offsetTop = getFakeTableOffset(scrollPos, tableElementOffsetTop, that._tableHeight, that._groupHeight);
if (parseFloat(that._fakeTable[0].style.top) !== offsetTop) {
that._fakeTable[0].style.top = offsetTop + "px";
}
},
_moveFakeTable: function _moveFakeTable() {
this._updateFakeTableVisibility();
},
_createFakeTable: function _createFakeTable() {
var that = this;
if (!that._fakeTable) {
that._fakeTable = that.tableElement().clone().addClass("dx-pivot-grid-fake-table").appendTo(that._virtualContent);
}
},
render: function render(rootElement, data) {
var that = this;
if (that._tableElement) {
try {
that._tableElement[0].innerHTML = '';
} catch (e) {
that._tableElement.empty();
}
that._tableElement.attr('style', '');
} else {
that._groupElement = that._createGroupElement();
that._tableElement = that._createTableElement();
that._tableElement.appendTo(that._groupElement);
that._groupElement.appendTo(rootElement);
that._rootElement = rootElement;
}
that._colgroupElement = $('<colgroup>').appendTo(that._tableElement);
that._renderTableContent(that._tableElement, data);
that._renderVirtualContent();
},
_getScrollable: function _getScrollable() {
return this.groupElement().data('dxScrollable');
},
on: function on(eventName, handler) {
var that = this,
scrollable = that._getScrollable();
if (scrollable) {
scrollable.on(eventName, function (e) {
if (that.option("rtlEnabled")) {
e.scrollOffset.left = scrollable.$content().width() - scrollable._container().width() - e.scrollOffset.left;
}
handler(e);
});
}
return this;
},
off: function off(eventName) {
var scrollable = this._getScrollable();
if (scrollable) {
scrollable.off(eventName);
}
return this;
},
scrollTo: function scrollTo(pos) {
var scrollable = this._getScrollable(),
scrollablePos = pos;
if (scrollable) {
if (this.option("rtlEnabled")) {
if (this._getAreaName() === "column") {
scrollablePos = scrollable.$content().width() - scrollable._container().width() - pos;
} else if (this._getAreaName() === "data") {
scrollablePos = { x: scrollable.$content().width() - scrollable._container().width() - pos.x, y: pos.y };
}
}
scrollable.scrollTo(scrollablePos);
if (this._virtualContent) {
this._createFakeTable();
this._moveFakeTable(pos);
}
}
},
updateScrollable: function updateScrollable() {
var scrollable = this._getScrollable();
if (scrollable) {
return scrollable.update();
}
},
getColumnsCount: function getColumnsCount() {
var columnCount = 0,
row = this._getRowElement(0),
cells;
if (row) {
cells = row.cells;
for (var i = 0, len = cells.length; i < len; ++i) {
columnCount += cells[i].colSpan;
}
}
return columnCount;
},
getData: function getData() {
var tableElement = this._tableElement;
return tableElement ? tableElement.data("data") : [];
}
});