UNPKG

@syncfusion/ej2-spreadsheet

Version:

Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel

533 lines (532 loc) 26.8 kB
import { removeDesignChart, clearChartBorder } from '../index'; import { getCellPosition, refreshImgCellObj, refreshChartCellObj, insertDesignChart, refreshOverlayElem } from '../common/index'; import { getRowIdxFromClientY, getColIdxFromClientX, overlayEleSize, getStartEvent, getMoveEvent, selectionStatus } from '../common/index'; import { getEndEvent, getClientX, getClientY, spreadsheetDestroyed, getPageX, getPageY, isTouchMove } from '../common/index'; import { getRangeIndexes, refreshChartSize, focusChartBorder, getRowsHeight, getCellIndexes, addDPRValue } from '../../workbook/index'; import { getColumnsWidth } from '../../workbook/index'; import { EventHandler, removeClass, closest, isNullOrUndefined, Browser } from '@syncfusion/ej2-base'; import { focus } from '../common/index'; /** * Specifes to create or modify overlay. * * @hidden */ var Overlay = /** @class */ (function () { /** * Constructor for initializing Overlay service. * * @param {Spreadsheet} parent - Specifies the Spreadsheet instance. */ function Overlay(parent) { this.minHeight = '300px'; this.minWidth = '400px'; this.isOverlayClicked = false; this.isResizerClicked = false; this.currentWidth = 400; this.currenHeight = 300; this.parent = parent; this.parent.on(selectionStatus, this.isOverlaySelected, this); this.parent.on(refreshOverlayElem, this.refreshOverlayElem, this); this.parent.on(spreadsheetDestroyed, this.destroy, this); } /** * To insert a shape. * * @param {string} id - Specifies the id. * @param {string} range - Specifies the range. * @param {number} sheetIndex - Specifies the sheet index. * @returns {HTMLElement} - Returns div element * @hidden */ Overlay.prototype.insertOverlayElement = function (id, range, sheetIndex) { var div = this.parent.createElement('div', { id: id, attrs: { 'class': 'e-ss-overlay' }, styles: 'width: ' + this.minWidth + '; height: ' + this.minHeight }); if (this.parent.allowEditing) { var actOverlayElem = this.parent.element.getElementsByClassName('e-ss-overlay-active')[0]; if (actOverlayElem) { removeClass([actOverlayElem], 'e-ss-overlay-active'); this.parent.notify(removeDesignChart, {}); } div.classList.add('e-ss-overlay-active'); } var indexes = getRangeIndexes(range); var sheet = this.parent.sheets[sheetIndex]; var frozenRow = this.parent.frozenRowCount(sheet); var frozenCol = this.parent.frozenColCount(sheet); var pos = getCellPosition(sheet, indexes, frozenRow, frozenCol, this.parent.viewport.beforeFreezeHeight, this.parent.viewport.beforeFreezeWidth, this.parent.sheetModule.colGroupWidth, true); if (indexes[0] >= frozenRow && indexes[1] < frozenCol) { var mainPanel = this.parent.sheetModule.contentPanel; if (mainPanel.scrollTop) { pos.top -= mainPanel.scrollTop; pos.top += this.parent.getColumnHeaderContent().parentElement.getBoundingClientRect().height; } } if (indexes[1] >= frozenCol && indexes[0] < frozenRow) { var scrollPanel = this.parent.getScrollElement(); if (scrollPanel.scrollLeft) { pos.left -= scrollPanel.scrollLeft; pos.left += this.parent.sheetModule.getRowHeaderWidth(sheet); } } var parent; if (indexes[0] < frozenRow || indexes[1] < frozenCol) { parent = this.parent.element.querySelector('#' + this.parent.element.id + '_sheet'); if (frozenRow) { if (indexes[0] >= frozenRow) { pos.top += (sheet.showHeaders ? 31 : 0) + getRowsHeight(sheet, getCellIndexes(sheet.topLeftCell)[0], frozenRow - 1); } else if (!frozenCol) { pos.left += this.parent.sheetModule.getRowHeaderWidth(sheet, true); } } if (frozenCol) { if (indexes[1] >= frozenCol) { pos.left += this.parent.sheetModule.getRowHeaderWidth(sheet); } else if (!frozenRow) { pos.left += (sheet.showHeaders ? 31 : 0); } } } else { parent = this.parent.getMainContent(); } div.style.top = Number(addDPRValue(pos.top).toFixed(2)) + 'px'; div.style.left = Number(addDPRValue(pos.left).toFixed(2)) + 'px'; if (sheetIndex === this.parent.activeSheetIndex) { parent.appendChild(div); this.renderResizeHandler(div); this.addEventListener(div); } else if (this.parent.isPrintingProcessing) { div.style.visibility = 'hidden'; document.body.append(div); } this.originalWidth = parseFloat(getComputedStyle(div, null).getPropertyValue('width').replace('px', '')); this.originalHeight = parseFloat(getComputedStyle(div, null).getPropertyValue('height').replace('px', '')); return { element: div, top: pos.top, left: pos.left }; }; /** * To adjust the layout inside freeze pane. * * @hidden * @param {ChartModel} model - Specifies the id. * @param {HTMLElement} element - Specifies the range. * @param {string} range - Specifies the sheet index. * @returns {void} */ Overlay.prototype.adjustFreezePaneSize = function (model, element, range) { var indexes = getRangeIndexes(range); var sheet = this.parent.getActiveSheet(); var frozenRow = this.parent.frozenRowCount(sheet); var frozenCol = this.parent.frozenColCount(sheet); if (indexes[0] < frozenRow || indexes[1] < frozenCol) { if (!isNullOrUndefined(model.top)) { element.style.top = model.top + (sheet.showHeaders ? 31 : 0) - this.parent.viewport.beforeFreezeHeight + 'px'; } if (!isNullOrUndefined(model.left)) { element.style.left = model.left + this.parent.sheetModule.getRowHeaderWidth(sheet, true) - this.parent.viewport.beforeFreezeWidth + 'px'; } } else { if (!isNullOrUndefined(model.top)) { element.style.top = model.top - this.parent.viewport.beforeFreezeHeight - (frozenRow ? getRowsHeight(sheet, getCellIndexes(sheet.topLeftCell)[0], frozenRow - 1) : 0) + 'px'; } if (!isNullOrUndefined(model.left)) { element.style.left = model.left - this.parent.viewport.beforeFreezeWidth - (frozenCol ? getColumnsWidth(sheet, getCellIndexes(sheet.topLeftCell)[1], frozenCol - 1) : 0) + 'px'; } } if (isNullOrUndefined(model.top)) { var startTop = getCellIndexes(sheet.topLeftCell)[0]; model.top = this.parent.viewport.beforeFreezeHeight + (frozenRow && startTop === indexes[0] ? 0 : getRowsHeight(sheet, frozenRow ? startTop : 0, indexes[0] - 1)); } if (isNullOrUndefined(model.left)) { var startLeft = getCellIndexes(sheet.topLeftCell)[1]; model.left = this.parent.viewport.beforeFreezeWidth + (frozenCol && startLeft === indexes[1] ? 0 : getColumnsWidth(sheet, frozenCol ? startLeft : 0, indexes[1] - 1)); } }; Overlay.prototype.addEventListener = function (div) { var overlayElem = div; EventHandler.add(overlayElem, getStartEvent(), this.overlayClickHandler, this); EventHandler.add(overlayElem, getMoveEvent(), this.overlayMouseMoveHandler, this); EventHandler.add(this.parent.element.querySelector('#' + this.parent.element.id + '_sheet'), getMoveEvent(), this.overlayMouseMoveHandler, this); if (!this.mouseUpHandler) { this.mouseUpHandler = this.overlayMouseUpHandler; EventHandler.add(document, getEndEvent(), this.mouseUpHandler, this); } this.parent.on(overlayEleSize, this.setOriginalSize, this); }; Overlay.prototype.setOriginalSize = function (args) { this.originalHeight = args.height; this.originalWidth = args.width; }; Overlay.prototype.overlayMouseMoveHandler = function (e) { var target = e.target; var overlayElem = document.getElementsByClassName('e-ss-overlay-active')[0]; var sheet = this.parent.getActiveSheet(); var checkOffset = sheet.frozenRows || sheet.frozenColumns ? [29, this.parent.sheetModule.getRowHeaderWidth(sheet, true)] : [-1, -1]; var height1; var top; var width1; var height2; var width2; var left; if (this.isOverlayClicked && this.isResizerClicked) { if (isTouchMove(e)) { e.preventDefault(); } switch (this.resizer) { case 'e-ss-overlay-t': height1 = Math.max(this.originalMouseY - getClientY(e) + this.originalHeight, 20); top = getClientY(e) - (this.originalMouseY - this.originalResizeTop); if (height1 > 20 && top > checkOffset[0]) { overlayElem.style.height = height1 + 'px'; overlayElem.style.top = top + 'px'; this.resizedReorderTop = top; // resized divTop this.currenHeight = height1; this.parent.notify(refreshChartSize, { height: overlayElem.style.height, width: overlayElem.style.width, overlayEle: overlayElem }); } break; case 'e-ss-overlay-r': width1 = this.originalWidth + (getPageX(e) - this.originalMouseX); if (width1 > 20) { overlayElem.style.width = width1 + 'px'; this.currentWidth = width1; this.parent.notify(refreshChartSize, { height: overlayElem.style.height, width: overlayElem.style.width, overlayEle: overlayElem }); } break; case 'e-ss-overlay-b': height2 = this.originalHeight + (getPageY(e) - this.originalMouseY); if (height2 > 20) { overlayElem.style.height = height2 + 'px'; this.currenHeight = height2; this.parent.notify(refreshChartSize, { height: overlayElem.style.height, width: overlayElem.style.width, overlayEle: overlayElem }); } break; case 'e-ss-overlay-l': width2 = Math.max(this.originalMouseX - getClientX(e) + this.originalWidth, 20); left = getClientX(e) - (this.originalMouseX - this.originalResizeLeft); if (width2 > 20 && left > checkOffset[1]) { overlayElem.style.width = width2 + 'px'; overlayElem.style.left = left + 'px'; this.resizedReorderLeft = left; //resized divLeft this.currentWidth = width2; this.parent.notify(refreshChartSize, { height: overlayElem.style.height, width: overlayElem.style.width, overlayEle: overlayElem }); } break; } } else if (this.isOverlayClicked) { if (isTouchMove(e)) { e.preventDefault(); } if ((closest(target, '.e-sheet') && !target.classList.contains('e-sheet-content')) || target.classList.contains('e-cell')) { if (!overlayElem) { return; } var aX = getClientX(e) - this.diffX; var aY = getClientY(e) - this.diffY; if (aX > checkOffset[1]) { overlayElem.style.left = aX + 'px'; } if (aY > checkOffset[0]) { overlayElem.style.top = aY + 'px'; } this.resizedReorderLeft = aX < 0 ? 0 : aX; //resized divLeft this.resizedReorderTop = aY < 0 ? 0 : aY; // resized divTop } else { this.overlayMouseUpHandler(e, true); } } }; Overlay.prototype.overlayMouseUpHandler = function (e, isMouseUp) { if (!this.parent || this.parent.getActiveSheet().isProtected || !this.parent.allowEditing) { return; } this.isResizerClicked = false; var elem = e.target; var overlayElems = document.getElementsByClassName('e-datavisualization-chart e-ss-overlay-active'); if (!elem.classList.contains('e-ss-overlay')) { elem = closest(e.target, '.e-datavisualization-chart') ? closest(e.target, '.e-datavisualization-chart') : elem; } var sheet = this.parent.getActiveSheet(); var eventArgs = { prevTop: sheet.frozenRows || sheet.frozenColumns ? this.prevY : this.originalReorderTop, prevLeft: sheet.frozenRows || sheet.frozenColumns ? this.prevX : this.originalReorderLeft, currentTop: this.resizedReorderTop >= 0 ? parseInt(this.resizedReorderTop.toString(), 10) : this.originalReorderTop, currentLeft: this.resizedReorderLeft >= 0 ? parseInt(this.resizedReorderLeft.toString(), 10) : this.originalReorderLeft, id: elem.id, currentHeight: this.currenHeight, currentWidth: this.currentWidth, requestType: 'imageRefresh', prevHeight: this.originalHeight, prevWidth: this.originalWidth }; if (this.isOverlayClicked || isMouseUp) { var currRowIdx = void 0; var currColIdx = void 0; var prevRowIdx = { clientY: eventArgs.prevTop, isImage: true }; var prevColIdx = { clientX: eventArgs.prevLeft, isImage: true }; var overlayEle = this.parent.element.getElementsByClassName('e-ss-overlay-active')[0]; if (sheet.frozenRows || sheet.frozenColumns) { if (!overlayEle) { return; } prevRowIdx.isImage = false; prevColIdx.isImage = false; prevRowIdx.target = overlayEle; prevColIdx.target = overlayEle; if (eventArgs.prevTop < this.parent.getColumnHeaderContent().getBoundingClientRect().bottom) { prevRowIdx.target = this.parent.getColumnHeaderContent(); prevRowIdx.isOverlay = true; } if (eventArgs.prevLeft < this.parent.getRowHeaderContent().getBoundingClientRect().right) { prevColIdx.target = this.parent.getRowHeaderTable(); } var clientRect = overlayEle.getBoundingClientRect(); currRowIdx = { clientY: clientRect.top }; currColIdx = { clientX: clientRect.left }; if (clientRect.top < this.parent.getColumnHeaderContent().getBoundingClientRect().bottom) { currRowIdx.target = this.parent.getColumnHeaderContent(); currRowIdx.isOverlay = true; } if (clientRect.left < this.parent.getRowHeaderContent().getBoundingClientRect().right) { currColIdx.target = this.parent.getRowHeaderTable(); } } else { currRowIdx = { clientY: eventArgs.currentTop, isImage: true }; currColIdx = { clientX: eventArgs.currentLeft, isImage: true }; } this.parent.notify(getRowIdxFromClientY, prevRowIdx); this.parent.notify(getRowIdxFromClientY, currRowIdx); this.parent.notify(getColIdxFromClientX, prevColIdx); this.parent.notify(getColIdxFromClientX, currColIdx); if (currRowIdx.size) { eventArgs.currentTop = currRowIdx.size; } if (currColIdx.size) { eventArgs.currentLeft = currColIdx.size; } eventArgs.prevRowIdx = prevRowIdx.clientY; eventArgs.prevColIdx = prevColIdx.clientX; eventArgs.currentRowIdx = currRowIdx.clientY; eventArgs.currentColIdx = currColIdx.clientX; if ((sheet.frozenColumns || sheet.frozenRows) && !closest(overlayEle, '.e-sheet-content')) { var frozenCol = this.parent.frozenColCount(sheet); var frozenRow = this.parent.frozenRowCount(sheet); if (eventArgs.currentRowIdx >= frozenRow && eventArgs.currentColIdx >= frozenCol) { var top_1 = parseFloat(overlayEle.style.top); var left = parseFloat(overlayEle.style.left); var mainPanel = this.parent.sheetModule.contentPanel; top_1 += mainPanel.scrollTop; top_1 -= this.parent.getColumnHeaderContent().parentElement.getBoundingClientRect().height; var scrollPanel = this.parent.getScrollElement(); left += scrollPanel.scrollLeft; left -= this.parent.sheetModule.getRowHeaderWidth(sheet); overlayEle.style.top = top_1 + 'px'; overlayEle.style.left = left + 'px'; this.parent.getMainContent().appendChild(overlayEle); if (overlayEle.classList.contains('e-datavisualization-chart')) { var chartEle = overlayEle.querySelector('.e-chart'); if (chartEle) { focus(chartEle); } } } } if (overlayElems && overlayElems[0]) { if (overlayElems[0].querySelector('.e-control')) { eventArgs.id = overlayElems[0].id; } } if (this.originalReorderTop !== this.resizedReorderTop || this.originalReorderLeft !== this.resizedReorderLeft) { eventArgs.id = overlayEle.id; if (overlayElems && overlayElems[0]) { eventArgs.requestType = 'chartRefresh'; this.parent.notify(refreshChartCellObj, eventArgs); } else { this.parent.notify(refreshImgCellObj, eventArgs); } this.resizedReorderTop = this.originalReorderTop; this.resizedReorderLeft = this.originalReorderLeft; } else if (this.currenHeight !== this.originalHeight || this.originalWidth !== this.currentWidth) { eventArgs.id = elem.id.indexOf('overlay') > 0 ? elem.id : elem.parentElement && elem.parentElement.classList.contains('e-ss-overlay') ? elem.parentElement.id : overlayEle.id; if (overlayElems && overlayElems[0]) { eventArgs.requestType = 'chartRefresh'; this.parent.notify(refreshChartCellObj, eventArgs); } else { this.parent.notify(refreshImgCellObj, eventArgs); } this.originalHeight = this.currenHeight; this.originalWidth = this.currentWidth; } } this.isOverlayClicked = false; }; Overlay.prototype.isOverlaySelected = function (args) { args.isOverlayClicked = this.isOverlayClicked; }; Overlay.prototype.refreshOverlayElem = function (args) { if (args) { var selector = '.e-ss-overlay-active' + ((args && args.selector) || ''); var overlayElem = this.parent.element.querySelector(selector); if (overlayElem) { removeClass([overlayElem], 'e-ss-overlay-active'); this.parent.notify(removeDesignChart, {}); } } else { var selector = 'e-ss-overlay-active'; var overlayElems = Array.from(this.parent.element.getElementsByClassName(selector)); for (var i = 0; i < overlayElems.length; i++) { var element = overlayElems[i]; if (element) { removeClass([element], 'e-ss-overlay-active'); this.parent.notify(removeDesignChart, {}); } } } this.parent.notify(clearChartBorder, null); }; Overlay.prototype.overlayClickHandler = function (e) { if (this.parent.getActiveSheet().isProtected || !this.parent.allowEditing) { return; } this.isOverlayClicked = true; var target = e.target; var overlayElem = e.target; if (!target.classList.contains('e-ss-overlay')) { overlayElem = target.parentElement; if (closest(e.target, '.e-datavisualization-chart')) { overlayElem = closest(e.target, '.e-datavisualization-chart'); } } var sheet = this.parent.getActiveSheet(); if ((sheet.frozenColumns || sheet.frozenRows) && closest(overlayElem, '.e-sheet-content')) { var top_2 = parseInt(overlayElem.style.top, 10); var left = parseInt(overlayElem.style.left, 10); var mainPanel = this.parent.sheetModule.contentPanel; top_2 -= mainPanel.scrollTop; top_2 += this.parent.getColumnHeaderContent().parentElement.getBoundingClientRect().height; var scrollPanel = this.parent.getScrollElement(); left -= scrollPanel.scrollLeft; left += this.parent.sheetModule.getRowHeaderWidth(sheet); overlayElem.style.top = top_2 + 'px'; overlayElem.style.left = left + 'px'; this.parent.element.querySelector('#' + this.parent.element.id + '_sheet').appendChild(overlayElem); } this.originalWidth = this.currentWidth = parseFloat(overlayElem.style.width); this.originalHeight = this.currenHeight = parseFloat(overlayElem.style.height); this.originalReorderLeft = parseFloat(overlayElem.style.left); //divLeft this.originalReorderTop = parseFloat(overlayElem.style.top); // divTop this.resizedReorderLeft = parseFloat(overlayElem.style.left); //resized divLeft this.resizedReorderTop = parseFloat(overlayElem.style.top); // resized divTop this.originalResizeTop = this.originalReorderTop; this.originalResizeLeft = this.originalReorderLeft; this.originalMouseX = getClientX(e); // posX this.originalMouseY = getClientY(e); // posY this.diffX = this.originalMouseX - this.originalReorderLeft; this.diffY = this.originalMouseY - this.originalReorderTop; var actOverlayElem = document.getElementsByClassName('e-ss-overlay-active')[0]; if (actOverlayElem) { removeClass([actOverlayElem], 'e-ss-overlay-active'); } this.parent.element.querySelector('#' + overlayElem.id).classList.add('e-ss-overlay-active'); if (target.classList.contains('e-ss-resizer')) { this.resizer = target.classList[0]; this.isResizerClicked = true; } if (overlayElem.classList.contains('e-datavisualization-chart')) { this.parent.notify(focusChartBorder, { id: overlayElem.id }); if (!actOverlayElem) { this.parent.notify(insertDesignChart, { id: overlayElem.id }); } else if (actOverlayElem.id !== overlayElem.id) { this.parent.notify(insertDesignChart, { refreshChartTheme: true }); } } var clientRect = overlayElem.getBoundingClientRect(); this.prevX = clientRect.left; this.prevY = clientRect.top; }; Overlay.prototype.renderResizeHandler = function (overlay) { var handles = ['e-ss-overlay-t', 'e-ss-overlay-r', 'e-ss-overlay-b', 'e-ss-overlay-l']; var idx = 0; var handleElem; while (idx < handles.length) { handleElem = this.parent.createElement('div', { className: handles[idx] + ' ' + 'e-ss-resizer' + (Browser.isDevice ? ' e-ss-resizer-touch' : ''), styles: 'width: 8px; height: 8px; border-radius: 4px;' }); overlay.appendChild(handleElem); idx++; } }; Overlay.prototype.removeEventListener = function () { var overlays = this.parent.element.querySelectorAll('.e-ss-overlay'); if (overlays.length) { // Added this condition temporarly to handle chart destroy from spec file. for (var idx = 0; idx < overlays.length; idx++) { EventHandler.remove(overlays[idx], getStartEvent(), this.overlayClickHandler); EventHandler.remove(overlays[idx], getMoveEvent(), this.overlayMouseMoveHandler); } } var ele = this.parent.element.querySelector('#' + this.parent.element.id + '_sheet'); if (ele) { EventHandler.remove(ele, getMoveEvent(), this.overlayMouseMoveHandler); } if (document && this.mouseUpHandler) { EventHandler.remove(document, getEndEvent(), this.mouseUpHandler); this.mouseUpHandler = null; } if (!this.parent.isDestroyed) { this.parent.off(overlayEleSize, this.setOriginalSize); this.parent.off(selectionStatus, this.isOverlaySelected); this.parent.off(refreshOverlayElem, this.refreshOverlayElem); this.parent.off(spreadsheetDestroyed, this.destroy); } }; /** * To clear private variables. * * @returns {void} */ Overlay.prototype.destroy = function () { this.removeEventListener(); if (this.currentWidth) { this.currentWidth = null; } if (this.currenHeight) { this.currenHeight = null; } if (this.minHeight) { this.minHeight = null; } if (this.minWidth) { this.minWidth = null; } if (this.isOverlayClicked) { this.isOverlayClicked = null; } if (this.isResizerClicked) { this.isResizerClicked = null; } this.parent = null; }; return Overlay; }()); export { Overlay };