@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
1,001 lines • 111 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { activeCellChanged, beginAction, getCell, getCellAddress, getCellIndexes, getRowHeight, getSheetName, importModelUpdate, setCell } from '../../workbook/index';
import { initiateComment, completeAction, createCommentIndicator, deleteComment, removeCommentContainer, locale, replyToComment, showCommentsPane, refreshCommentsPane, commentUndoRedo, getDPRValue, processSheetComments } from '../index';
import { Browser, closest, detach, enableRipple, EventHandler, getComponent, getUniqueID, isNullOrUndefined } from '@syncfusion/ej2-base';
import { getUpdateUsingRaf, navigateNextPrevComment, updateNoteContainer } from './../common/index';
import { getRangeAddress, updateCell } from '../../workbook/index';
import { Button } from '@syncfusion/ej2-buttons';
import { DropDownButton } from '@syncfusion/ej2-splitbuttons';
import { ListView, Virtualization } from '@syncfusion/ej2-lists';
ListView.Inject(Virtualization);
/**
* Comment module.
*/
var SpreadsheetComment = /** @class */ (function () {
/**
* Initializes a new instance of the `SpreadsheetComment` class
*
* @param {Spreadsheet} parent - Constructor for SpreadsheetComment module.
*/
function SpreadsheetComment(parent) {
/** @hidden */
this.isCommentVisible = false;
/** @hidden */
this.isCommentVisibleOnTouch = false;
/** @hidden */
this.isReviewPaneVisible = false;
this.isEditing = false;
this.reviewInstances = [];
this.reviewFilter = 'all';
this.scheduleMountId = 0;
this.parent = parent;
this.addEventListener();
}
SpreadsheetComment.prototype.addEventListener = function () {
this.parent.on(initiateComment, this.initiateComment, this);
this.parent.on(deleteComment, this.deleteComment, this);
this.parent.on(createCommentIndicator, this.createCommentIndicator, this);
this.parent.on(removeCommentContainer, this.removeCommentContainer, this);
this.parent.on(replyToComment, this.replyToComment, this);
this.parent.on(importModelUpdate, this.updateCommentsFromSheet, this);
this.parent.on(showCommentsPane, this.showCommentPane, this);
this.parent.on(navigateNextPrevComment, this.navigateNextPrevComment, this);
this.parent.on(refreshCommentsPane, this.refreshCommentsPane, this);
this.parent.on(processSheetComments, this.processSheetComments, this);
this.parent.on(commentUndoRedo, this.onCommentUndoRedo, this);
this.parent.on(activeCellChanged, this.commentHandler, this);
};
SpreadsheetComment.prototype.removeEventListener = function () {
if (!this.parent.isDestroyed) {
this.parent.off(initiateComment, this.initiateComment);
this.parent.off(deleteComment, this.deleteComment);
this.parent.off(createCommentIndicator, this.createCommentIndicator);
this.parent.off(removeCommentContainer, this.removeCommentContainer);
this.parent.off(replyToComment, this.replyToComment);
this.parent.off(importModelUpdate, this.updateCommentsFromSheet);
this.parent.off(showCommentsPane, this.showCommentPane);
this.parent.off(navigateNextPrevComment, this.navigateNextPrevComment);
this.parent.off(refreshCommentsPane, this.refreshCommentsPane);
this.parent.off(processSheetComments, this.processSheetComments);
this.parent.off(commentUndoRedo, this.onCommentUndoRedo);
this.parent.off(activeCellChanged, this.commentHandler);
}
};
SpreadsheetComment.prototype.initiateComment = function (args) {
var cellIndexes = (args && !isNullOrUndefined(args.rowIndex) && !isNullOrUndefined(args.columnIndex)) ?
[args.rowIndex, args.columnIndex] : getCellIndexes(this.parent.getActiveSheet().activeCell);
var targetElement = this.parent.getCell(cellIndexes[0], cellIndexes[1]);
if (!isNullOrUndefined(targetElement)) {
if (!targetElement.querySelector('.e-comment-indicator')) {
this.createCommentIndicator({ targetEle: targetElement, rIdx: cellIndexes[0], cIdx: cellIndexes[1] });
}
if (args && args.isMouseOver) {
this.createCommentContainer(targetElement, cellIndexes[0], cellIndexes[1]);
this.activeCommentCell = [cellIndexes[0], cellIndexes[1]];
return;
}
if (this.isReviewPaneVisible) {
var sheet = this.parent.getActiveSheet();
var existing = (sheet.comments || []).find(function (t) { return t.address && t.address[0] === cellIndexes[0] && t.address[1] === cellIndexes[1]; });
if (existing && existing.id) {
this.scrollToThreadInPanel(existing.id, args && args.isSelection);
}
else {
this.renderNewCommentForPanel(cellIndexes[0], cellIndexes[1]);
}
}
else {
this.createCommentContainer(targetElement, cellIndexes[0], cellIndexes[1]);
this.activeCommentCell = [cellIndexes[0], cellIndexes[1]];
}
}
};
SpreadsheetComment.prototype.createCommentIndicator = function (args) {
var commentIndicator = this.parent.createElement('div', { className: 'e-comment-indicator' });
if (args.targetEle.children.length > 0) {
var rowHeight = getRowHeight(this.parent.getActiveSheet(), args.rIdx);
var defaultFilterButtonHeight = 20;
for (var i = 0; i < args.targetEle.childElementCount; i++) {
var children = args.targetEle.children[i];
if (children.className.indexOf('e-filter-btn') > -1) {
if (this.parent.enableRtl) {
commentIndicator.style.left = (rowHeight < (defaultFilterButtonHeight + 10) ?
(children.getBoundingClientRect().width <= 0 ? defaultFilterButtonHeight :
children.getBoundingClientRect().width + 1) : 2) + 'px';
}
else {
commentIndicator.style.right = (rowHeight < (defaultFilterButtonHeight + 10) ?
(children.getBoundingClientRect().width <= 0 ? defaultFilterButtonHeight :
children.getBoundingClientRect().width + 1) : 2) + 'px';
}
}
if (children.className.indexOf('e-validation-list') > -1) {
if (this.parent.enableRtl) {
commentIndicator.style.left = (children.getBoundingClientRect().width || 20) + 2 + "px";
}
else {
commentIndicator.style.right = (children.getBoundingClientRect().width || 20) + 2 + "px";
}
}
}
}
if (!commentIndicator.dataset.commentListenersAdded && !args.skipEvent) {
commentIndicator.dataset.commentRowIndex = args.rIdx.toString();
commentIndicator.dataset.commentColIndex = args.cIdx.toString();
EventHandler.add(commentIndicator, 'mouseover', this.mouseOver, this);
EventHandler.add(commentIndicator, 'mouseout', this.mouseOut, this);
commentIndicator.dataset.commentListenersAdded = 'true';
}
args.targetEle.appendChild(commentIndicator);
};
SpreadsheetComment.prototype.mouseOver = function (event) {
var cell = event.currentTarget;
var row = parseInt(cell.dataset.commentRowIndex, 10);
var col = parseInt(cell.dataset.commentColIndex, 10);
if (!isNaN(row) && !isNaN(col)) {
var containerInDOM = document.getElementsByClassName('e-comment-container')[0];
if ((this.isCommentVisibleOnTouch && !isNullOrUndefined(containerInDOM)) || isNullOrUndefined(containerInDOM)) {
if (!isNullOrUndefined(containerInDOM)) {
this.removeCommentContainer();
}
this.initiateComment({ rowIndex: row, columnIndex: col, isMouseOver: true });
this.isCommentVisible = true;
}
}
};
SpreadsheetComment.prototype.mouseOut = function (e) {
var commentContainer = this.getCommentContainer();
var relatedTarget = e.relatedTarget;
if (this.isCommentVisible && (!this.isCommentVisibleOnTouch && commentContainer)) {
if (relatedTarget) {
var isInsideContainer = commentContainer.contains(relatedTarget);
var isInsideIndicator = closest(relatedTarget, '.e-comment-indicator');
var isInsideDropDownPopup = closest(relatedTarget, '.e-dropdown-popup');
var isCommentCell = this.parent.getCell(this.activeCommentCell[0], this.activeCommentCell[1]);
if (!isInsideContainer && !isInsideIndicator && !isInsideDropDownPopup &&
isCommentCell && !isCommentCell.contains(relatedTarget) &&
document.activeElement !== commentContainer &&
document.activeElement !== commentContainer.querySelector('.e-comment-input')) {
this.removeCommentContainer();
this.isCommentVisible = false;
this.activeCommentCell = null;
}
}
}
};
SpreadsheetComment.prototype.createCommentContainer = function (targetEle, rIdx, cIdx) {
var commentContainer = this.parent.createElement('div', { className: 'e-comment-container' });
commentContainer.tabIndex = -1;
this.renderCommentUI(commentContainer, rIdx, cIdx, false);
commentContainer.style.visibility = 'hidden';
this.parent.element.appendChild(commentContainer);
this.setCommentContainerPosition(commentContainer, targetEle.getBoundingClientRect());
commentContainer.style.visibility = '';
var cell = getCell(rIdx, cIdx, this.parent.getActiveSheet());
var thread = cell && cell.comment;
if (thread && thread.isResolved) {
this.handleResolvedThread(commentContainer, rIdx, cIdx, thread);
}
var textArea = commentContainer.querySelector('.e-comment-footer .e-comment-input');
if (textArea && (!cell || (cell && !cell.comment))) {
textArea.focus();
textArea.select();
if (!commentContainer.classList.contains('active')) {
commentContainer.classList.add('active');
}
}
this.bindContainerEvents(commentContainer);
EventHandler.add(commentContainer, 'mouseout', this.mouseOut, this);
EventHandler.add(targetEle, 'mouseout', this.mouseOut, this);
this.isCommentVisible = true;
};
SpreadsheetComment.prototype.handleResolvedThread = function (container, rIdx, cIdx, thread) {
var headerEl = container.querySelector('.e-comment-header');
if (headerEl) {
headerEl.replaceWith(this.createheaderContent(false, getCellAddress(rIdx, cIdx), thread));
}
var footerEl = container.querySelector('.e-comment-footer');
if (footerEl) {
this.unwireFooterEvents(footerEl);
this.removeFooterButtons(footerEl);
footerEl.remove();
}
container.classList.add('e-thread-resolved');
this.removeReplyButtons(container.querySelector('.e-comment-body'));
this.setTextAreaState(container, true);
this.renderResolvedWrap(container, rIdx, cIdx, thread.author || (this.parent.author || 'Guest User'));
};
SpreadsheetComment.prototype.renderCommentUI = function (container, rIdx, cIdx, inPane, containerId) {
var sheet = this.parent.getActiveSheet();
var cell = getCell(rIdx, cIdx, sheet);
var header;
var body;
var footer;
if (cell && cell.comment) {
var cellAddress = getCellAddress(rIdx, cIdx);
header = this.createheaderContent(false, cellAddress, cell.comment);
body = this.createBodyContent(cell.comment, true, inPane, containerId);
footer = this.createFooterContent(rIdx, cIdx, false);
}
else {
header = this.createheaderContent(true);
footer = this.createFooterContent(rIdx, cIdx, true);
}
if (!inPane) {
container.dataset.commentRowIndex = rIdx.toString();
container.dataset.commentColIndex = cIdx.toString();
}
container.appendChild(header);
if (body) {
container.appendChild(body);
}
container.appendChild(footer);
};
SpreadsheetComment.prototype.createheaderContent = function (initial, cellAddress, comment) {
var header = this.parent.createElement('div', { className: 'e-comment-header' });
var headerwrap = this.parent.createElement('div', { className: 'e-comment-header-wrap' });
var titleWrap = this.parent.createElement('div', { className: 'e-comment-title-wrap' });
var thread = comment;
if (!initial && thread && thread.isResolved) {
var l10n = this.parent.serviceLocator.getService(locale);
var resolvedWrap = this.parent.createElement('div', { className: 'e-comment-resolved' });
var tick = this.parent.createElement('span', { className: 'e-icons e-check' });
var label = this.parent.createElement('div', { className: 'e-resolve-text' });
label.textContent = l10n.getConstant('Resolved');
resolvedWrap.appendChild(tick);
resolvedWrap.appendChild(label);
headerwrap.appendChild(resolvedWrap);
this.renderHeaderActions(headerwrap, false, '', thread);
header.appendChild(headerwrap);
return header;
}
var authorName = initial ? (this.parent.author || 'Guest User') : (thread && thread.author);
var avatar = this.getAvatar(authorName);
var title = this.parent.createElement('div', { className: 'e-comment-title' });
title.textContent = authorName;
titleWrap.appendChild(title);
headerwrap.appendChild(titleWrap);
this.renderHeaderActions(headerwrap, initial, cellAddress, thread);
header.appendChild(avatar);
header.appendChild(headerwrap);
return header;
};
SpreadsheetComment.prototype.getAvatar = function (author) {
var avatar = this.parent.createElement('div', { className: 'e-comment-avatar' });
avatar.textContent = this.getAvatarInitials(author);
var currentUser = this.parent.author || 'Guest User';
if (author === currentUser) {
avatar.style.backgroundColor = '#b5082e';
}
else {
avatar.style.backgroundColor = this.getAuthorColor(author);
}
return avatar;
};
SpreadsheetComment.prototype.getAuthorColor = function (author) {
var colors = ['#b5082e', '#2e97d3', '#bb00ff', '#f37e43', '#03a60b', '#881824', '#e09a2b', '#50565e', '#1f7a8c',
'#7b5ea7', '#2db36c', '#d9480f', '#0a58ca', '#a83279', '#00897b'];
var authorStr = (author ? author : 'Guest User').trim().toLowerCase();
var hash = 5381;
for (var i = 0; i < authorStr.length; i++) {
var code = authorStr.charCodeAt(i);
hash = (hash * 33 + code) % 4294967296;
}
var idx = Math.abs(hash) % colors.length;
return colors[idx];
};
SpreadsheetComment.prototype.getAvatarInitials = function (name) {
var parts = (name ? name : 'Guest User').trim().split(' ');
if (parts && parts.length === 1) {
return parts[0].charAt(0).toUpperCase();
}
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
};
SpreadsheetComment.prototype.renderHeaderActions = function (headerWrap, initial, address, thread) {
var _this = this;
var l10n = this.parent.serviceLocator.getService(locale);
var parentHeader = headerWrap.closest('.e-comment-header');
var existingActions = headerWrap.querySelector('.e-comment-actions');
if (existingActions) {
existingActions.remove();
}
if (initial) {
if (parentHeader) {
var existingCloseBtn = parentHeader.querySelector('.e-comment-cancel');
if (existingCloseBtn) {
existingCloseBtn.remove();
}
}
var cancelBtn_1 = this.parent.createElement('button', {
className: 'e-comment-cancel',
attrs: { 'aria-label': 'Cancel', title: l10n.getConstant('Cancel') }
});
var button = new Button({ cssClass: 'e-flat', iconCss: 'e-icons e-close' }, cancelBtn_1);
button.createElement = this.parent.createElement;
EventHandler.add(button.element, 'click', function () { return _this.handleInitialCancel(cancelBtn_1); }, this);
headerWrap.appendChild(cancelBtn_1);
return;
}
if (parentHeader) {
var existingCloseBtn = parentHeader.querySelector('.e-comment-cancel');
if (existingCloseBtn) {
existingCloseBtn.remove();
}
}
var actionsWrap = this.parent.createElement('div', { className: 'e-comment-actions' });
if (this.isEditing) {
headerWrap.appendChild(actionsWrap);
return;
}
if (thread && thread.isResolved === true) {
var reopenBtnEl_1 = this.parent.createElement('button', {
className: 'e-comment-reopen-btn',
attrs: { type: 'button', title: l10n.getConstant('Reopen') }
});
var reopenBtn = new Button({ cssClass: 'e-flat', iconCss: 'e-icons e-undo' }, reopenBtnEl_1);
reopenBtn.createElement = this.parent.createElement;
EventHandler.add(reopenBtn.element, 'click', function () { return _this.setThreadResolved(false, reopenBtnEl_1); }, this);
var deleteBtnEl_1 = this.parent.createElement('button', {
className: 'e-comment-delete',
attrs: { type: 'button', title: l10n.getConstant('DeleteThread') }
});
var deleteBtn = new Button({ cssClass: 'e-flat', iconCss: 'e-icons e-trash' }, deleteBtnEl_1);
deleteBtn.createElement = this.parent.createElement;
EventHandler.add(deleteBtn.element, 'click', function () { return _this.deleteComment({ sourceEl: deleteBtnEl_1 }); }, this);
actionsWrap.appendChild(reopenBtnEl_1);
actionsWrap.appendChild(deleteBtnEl_1);
headerWrap.appendChild(actionsWrap);
return;
}
var cellRef = this.parent.createElement('span', { className: 'e-comment-cellref' });
cellRef.textContent = address;
actionsWrap.appendChild(cellRef);
var menuBar = this.parent.createElement('button', {
className: 'e-comment-menu e-flat', attrs: { type: 'button', title: l10n.getConstant('ThreadAction') }
});
var userOption = [
{ text: l10n.getConstant('EditComment'), iconCss: 'e-icons e-edit' },
{ text: l10n.getConstant('ResolveThread'), iconCss: 'e-icons e-check' },
{ text: l10n.getConstant('DeleteThread'), iconCss: 'e-icons e-trash' }
];
var menuItem = new DropDownButton({
items: userOption,
iconCss: 'e-icons e-more-horizontal-1',
cssClass: 'e-caret-hide e-menu-popup',
enableRtl: this.parent.enableRtl,
select: function (e) { return _this.onThreadMenuSelect(e, menuBar); },
open: function () { return _this.setPopupPosition(menuItem, menuBar); }
});
menuItem.createElement = this.parent.createElement;
menuItem.appendTo(menuBar);
actionsWrap.appendChild(menuBar);
headerWrap.appendChild(actionsWrap);
};
SpreadsheetComment.prototype.setPopupPosition = function (ddb, triggerEl) {
if (ddb && ddb.dropDown) {
var popupEl = ddb.dropDown.element;
if (popupEl) {
var btnRect = triggerEl.getBoundingClientRect();
var popupRect = popupEl.getBoundingClientRect();
popupEl.style.left = (this.parent.enableRtl ? btnRect.left : btnRect.right - popupRect.width) + "px";
}
}
};
SpreadsheetComment.prototype.handleInitialCancel = function (ele) {
if (ele) {
var container = this.getContainer(ele);
var indices = this.getIndexesFromContainer(container);
var sheet = this.parent.getActiveSheet();
if (indices) {
var rowIndex = indices[0], columnIndex = indices[1];
var cell = getCell(rowIndex, columnIndex, sheet);
if (!cell || !cell.comment) {
this.detachCommentIndicator(rowIndex, columnIndex);
}
}
if (container) {
EventHandler.remove(container, 'mouseout', this.mouseOut);
this.unbindContainerEvents(container);
var host = this.getBodyHost(container);
if (host) {
this.unbindReplyHover(host);
}
detach(container);
if (this.isReviewPaneVisible && container.classList.contains('e-thread-draft')) {
if (!sheet.comments || !sheet.comments.length) {
this.renderReviewBody();
}
}
}
if (this.activeReplyDdb) {
this.activeReplyDdb.destroy();
this.activeReplyDdb = null;
}
this.isCommentVisible = false;
this.activeCommentCell = null;
this.isEditing = false;
}
};
SpreadsheetComment.prototype.onThreadMenuSelect = function (event, sourceEl) {
var l10n = this.parent.serviceLocator.getService(locale);
var text = event.item.text;
if (text === l10n.getConstant('EditComment')) {
this.beginEdit(false, undefined, sourceEl);
}
else if (text === l10n.getConstant('ResolveThread')) {
this.setThreadResolved(true, sourceEl);
}
else {
this.deleteComment({ sourceEl: sourceEl });
}
};
SpreadsheetComment.prototype.createBodyContent = function (thread, rebuild, inPane, cId) {
var dataSource = thread ? this.convertThreadToListItems(thread) : [];
if (inPane) {
var host = this.parent.createElement('div', { className: 'e-comment-body' });
if (Browser.isDevice) {
host.classList.add('e-device-comment');
}
this.initListView(host, dataSource, true);
if (!thread.isResolved && !Browser.isDevice) {
this.bindReplyHover(host, cId);
}
return host;
}
if (!this.bodyHost) {
this.bodyHost = this.parent.createElement('div', { className: 'e-comment-body' });
}
if (!this.commentListView) {
this.commentListView = this.initListView(this.bodyHost, dataSource, false);
}
else if (rebuild) {
this.commentListView.setProperties({ dataSource: dataSource }, true);
this.commentListView.refresh();
}
if (!thread.isResolved && !Browser.isDevice) {
this.bindReplyHover(this.bodyHost);
}
return this.bodyHost;
};
SpreadsheetComment.prototype.initListView = function (host, dataSource, registerForCleanup) {
var _this = this;
var itemTemplate = function (data) {
var l10n = _this.parent.serviceLocator.getService(locale);
var actionText = l10n.getConstant('CommentAction');
var root = _this.parent.createElement('div', {
className: "e-comment-item " + data.type,
attrs: __assign({ 'data-id': data.id }, (data.type === 'reply' ? { 'data-reply-id': data.id } : {}))
});
var renderTextAndTimestamp = function (text, createdTime, parent) {
var textEl = _this.parent.createElement('div', { className: 'e-comment-text' });
textEl.textContent = text;
var tsEl = _this.parent.createElement('span', { className: 'e-comment-timestamp' });
tsEl.textContent = createdTime;
parent.appendChild(textEl);
parent.appendChild(tsEl);
};
if (data.type === 'initial') {
renderTextAndTimestamp(data.text, data.createdTime, root);
return [root];
}
var row = _this.parent.createElement('div', { className: 'e-comment-reply-row' });
var avatarWrap = _this.parent.createElement('div', { className: 'e-comment-avatar-wrap' });
var authorName = data.author;
var avatarEl = _this.getAvatar(authorName);
avatarWrap.appendChild(avatarEl);
var col = _this.parent.createElement('div', { className: 'e-comment-reply-col' });
var header = _this.parent.createElement('div', { className: 'e-comment-header-wrap' });
var titleWrap = _this.parent.createElement('div', { className: 'e-comment-title-wrap' });
var title = _this.parent.createElement('div', { className: 'e-comment-title' });
title.textContent = authorName;
titleWrap.appendChild(title);
var menuBtn = _this.parent.createElement('button', {
className: 'e-reply-ddb e-flat',
attrs: { type: 'button', 'data-reply-id': data.id, 'aria-label': actionText }
});
if (Browser.isDevice) {
_this.renderReplyDdb(menuBtn);
}
header.appendChild(titleWrap);
header.appendChild(menuBtn);
var content = _this.parent.createElement('div', { className: 'e-comment-reply-content' });
renderTextAndTimestamp(data.text, data.createdTime, content);
col.appendChild(header);
col.appendChild(content);
row.appendChild(avatarWrap);
row.appendChild(col);
root.appendChild(row);
return [root];
};
enableRipple(false);
var listView = new ListView({
dataSource: dataSource,
template: itemTemplate,
cssClass: 'e-comment-listview',
enableRtl: this.parent.enableRtl,
enableVirtualization: true,
height: '100%',
select: function (args) {
if (_this.isReviewPaneVisible) {
_this.updateCellSelction(args);
}
}
});
listView.createElement = this.parent.createElement;
/* eslint-disable */
listView.isInternalTemplate = true;
/* eslint-enable */
listView.appendTo(host);
if (registerForCleanup) {
this.reviewInstances.push({ destroy: function () { listView.destroy(); } });
}
return listView;
};
SpreadsheetComment.prototype.renderReplyDdb = function (btn) {
var _this = this;
if (this.isEditing) {
btn.style.visibility = 'hidden';
return;
}
if (btn.dataset.ddbMounted === 'true') {
return;
}
var l10n = this.parent.serviceLocator.getService(locale);
var items = [
{ id: 'edit-reply', text: l10n.getConstant('EditComment'), iconCss: 'e-icons e-edit' },
{ id: 'delete-reply', text: l10n.getConstant('DeleteComment'), iconCss: 'e-icons e-trash' }
];
var ddb = new DropDownButton({
items: items,
iconCss: 'e-icons e-more-horizontal-1',
cssClass: 'e-caret-hide e-menu-popup',
enableRtl: this.parent.enableRtl,
select: function (args) {
var replyId = btn.getAttribute('data-reply-id') || '';
_this.onReplyMenuSelect(args, replyId, btn);
},
open: function () { return _this.setPopupPosition(ddb, btn); }
});
ddb.createElement = this.parent.createElement;
ddb.appendTo(btn);
btn.dataset.ddbMounted = 'true';
this.activeReplyDdb = ddb;
};
SpreadsheetComment.prototype.onReplyMenuSelect = function (args, replyId, sourceEl) {
var l10n = this.parent.serviceLocator.getService(locale);
var text = args.item.text;
if (text === l10n.getConstant('EditComment')) {
this.beginEdit(true, replyId, sourceEl);
}
else {
this.deleteReplyById(replyId, sourceEl);
}
};
SpreadsheetComment.prototype.createFooterContent = function (rowIdx, colIdx, initial) {
var l10n = this.parent.serviceLocator.getService(locale);
var footer = this.parent.createElement('div', { className: 'e-comment-footer' });
var cell = getCell(rowIdx, colIdx, this.parent.getActiveSheet());
if (cell && cell.comment && cell.comment.isResolved === true) {
return footer;
}
footer.setAttribute('data-mode', initial ? 'initial' : 'reply');
var textArea = this.parent.createElement('textarea', {
className: 'e-comment-input',
attrs: { placeholder: initial ? l10n.getConstant('AddComment') : l10n.getConstant('Reply'), rows: '1', name: 'footerTextArea' }
});
textArea.style.height = '32px';
var btnBar = this.parent.createElement('div', { className: 'e-comment-btn' });
footer.appendChild(textArea);
footer.appendChild(btnBar);
if (initial) {
this.ensureFooterButtons(footer, initial);
this.syncFooterPostState(footer, textArea);
}
this.wireFooterEvents(footer);
return footer;
};
SpreadsheetComment.prototype.convertThreadToListItems = function (thread) {
var items = [];
items.push({
id: thread.id, type: 'initial', author: thread.author || 'Guest User',
text: thread.text, createdTime: thread.createdTime
});
var replies = thread.replies || [];
if (replies.length > 0) {
replies.forEach(function (reply) {
items.push({
id: reply.id || getUniqueID('e_spreadsheet_reply'), type: 'reply',
author: reply.author || 'Guest User', text: reply.text, createdTime: reply.createdTime
});
});
}
return items;
};
SpreadsheetComment.prototype.postComment = function (rowIdx, colIdx, commentText, container) {
if (!commentText) {
return;
}
var timeStampValue = this.timeStamp();
var actionFromPanel = container && container.classList.contains('e-pane-container');
var cell = getCell(rowIdx, colIdx, this.parent.getActiveSheet());
if (cell && cell.comment) {
var thread = JSON.parse(JSON.stringify(cell.comment));
if (!Array.isArray(thread.replies)) {
thread.replies = [];
}
var reply = {
id: getUniqueID('e_spreadsheet_reply'),
author: this.parent.author || 'Guest User',
text: commentText,
createdTime: timeStampValue
};
thread.replies.push(reply);
this.saveComment(rowIdx, colIdx, thread, 'addReply', actionFromPanel);
var body = container.querySelector('.e-comment-body');
var targetListView = void 0;
if (body) {
targetListView = getComponent(body, 'listview');
}
else {
targetListView = this.commentListView;
}
if (targetListView) {
var avatarEl = this.getAvatar(reply.author);
targetListView.addItem([{
id: reply.id,
type: 'reply',
author: reply.author,
text: reply.text,
createdTime: reply.createdTime,
avatarHtml: avatarEl.outerHTML
}]);
if (body) {
body.scrollTop = body.scrollHeight;
}
}
return;
}
var id = getUniqueID('e_spreadsheet_comment');
var newThread = {
id: id,
author: this.parent.author || 'Guest User',
text: commentText,
createdTime: timeStampValue,
isResolved: false,
replies: []
};
this.saveComment(rowIdx, colIdx, newThread, 'addComment', actionFromPanel);
var header = container.querySelector('.e-comment-header');
if (header && !header.querySelector('.e-comment-actions')) {
var headerWrap = header.querySelector('.e-comment-header-wrap');
if (headerWrap) {
this.renderHeaderActions(headerWrap, false, getCellAddress(rowIdx, colIdx));
}
}
if (container) {
var body = this.createBodyContent(newThread, true, this.isReviewPaneVisible);
var footer = container.querySelector('.e-comment-footer');
if (footer && body && body.parentElement !== container) {
container.insertBefore(body, footer);
}
else if (footer && body && footer.previousElementSibling !== body) {
container.insertBefore(body, footer);
}
}
if (this.isReviewPaneVisible) {
if (container && container.classList.contains('e-thread-draft')) {
container.remove();
}
}
};
SpreadsheetComment.prototype.beginEdit = function (isReply, replyId, sourceEl) {
var _this = this;
var container = this.getContainer(sourceEl);
var localBodyHost = this.getBodyHost(container);
if (this.isEditing || !container || !localBodyHost) {
return;
}
var idx = this.getIndexesFromContainer(container);
if (idx) {
var cell = getCell(idx[0], idx[1], this.parent.getActiveSheet());
var th = cell && cell.comment;
if (th && th.isResolved) {
return;
}
}
var itemSelector = isReply ? ".e-comment-item.reply[data-reply-id=\"" + replyId + "\"]" : '.e-comment-item.initial';
var itemEl = localBodyHost.querySelector(itemSelector);
if (!itemEl) {
return;
}
var textEl = itemEl.querySelector('.e-comment-text');
if (!textEl) {
return;
}
var originalText = textEl.textContent || '';
var l10n = this.parent.serviceLocator.getService(locale);
var editorWrap = this.parent.createElement('div', { className: 'e-comment-edit-wrap' });
var textArea = this.parent.createElement('textarea', {
className: 'e-comment-input e-comment-edit-input',
attrs: { rows: '1', name: 'editTextArea' }
});
EventHandler.add(textArea, 'focus', function () { textArea.classList.add('active'); }, this);
EventHandler.add(textArea, 'blur', function () { textArea.classList.remove('active'); }, this);
textArea.value = originalText;
this.adjustTextareaHeight(textArea, true);
var tsEle = itemEl.querySelector('.e-comment-timestamp');
var tsValue = '';
if (tsEle) {
tsValue = tsEle.style.display;
tsEle.style.display = 'none';
}
var btnBar = this.parent.createElement('div', { className: 'e-comment-btn' });
var postBtnEl = this.parent.createElement('button', {
className: 'e-comment-post',
attrs: { type: 'button', 'aria-label': 'Post', title: l10n.getConstant('EditComment') }
});
var postBtn = new Button({ iconCss: 'e-icons e-send', isPrimary: true }, postBtnEl);
postBtn.createElement = this.parent.createElement;
var cancelBtnEl = this.parent.createElement('button', {
className: 'e-comment-cancel',
attrs: { type: 'button', 'aria-label': 'Cancel', title: l10n.getConstant('Cancel') }
});
var cancelBtn = new Button({ cssClass: 'e-flat', iconCss: 'e-icons e-close' }, cancelBtnEl);
cancelBtn.createElement = this.parent.createElement;
EventHandler.add(textArea, 'input', function () { return _this.adjustTextareaHeight(textArea, true); }, this);
EventHandler.add(postBtn.element, 'click', function () {
_this.applyInlineEdit(isReply, textArea.value, textEl, editorWrap, originalText, replyId, container);
}, this);
EventHandler.add(cancelBtn.element, 'click', function () {
textEl.textContent = originalText;
textEl.style.display = '';
editorWrap.remove();
_this.endEdit(container);
}, this);
btnBar.appendChild(postBtnEl);
btnBar.appendChild(cancelBtnEl);
editorWrap.appendChild(textArea);
editorWrap.appendChild(btnBar);
textEl.style.display = 'none';
if (textEl.parentElement) {
textEl.parentElement.insertBefore(editorWrap, textEl.nextSibling);
}
this.editingState = {
isReply: isReply, replyId: replyId, textEl: textEl, editorWrap: editorWrap, originalText: originalText, tsEle: tsEle, tsValue: tsValue,
container: container, textHost: localBodyHost, addrIdx: idx
};
this.isEditing = true;
this.setTextAreaState(container, true);
container.classList.add('e-comment-editing');
var header = container.querySelector('.e-comment-header');
if (header) {
var headerWrap = header.querySelector('.e-comment-header-wrap');
if (headerWrap) {
if (idx && idx.length === 2) {
this.renderHeaderActions(headerWrap, false, getCellAddress(idx[0], idx[1]));
}
}
}
var replyBtns = localBodyHost.querySelectorAll('.e-reply-ddb');
if (replyBtns) {
replyBtns.forEach(function (btn) {
btn.style.visibility = 'hidden';
});
}
getUpdateUsingRaf(function () {
_this.adjustTextareaHeight(textArea, true);
textArea.focus();
var len = textArea.value.length;
textArea.setSelectionRange(len, len);
});
};
SpreadsheetComment.prototype.applyInlineEdit = function (isReply, newText, textEl, editorWrap, originalText, replyId, container) {
var finalText = newText || originalText;
textEl.textContent = finalText;
textEl.style.display = '';
editorWrap.remove();
var indices = this.getIndexesFromContainer(container || null);
if (indices && indices.length === 2) {
var row = indices[0], col = indices[1];
var cell = getCell(row, col, this.parent.getActiveSheet());
var actionFromPanel = container && container.classList.contains('e-pane-container');
if (cell && cell.comment) {
var thread = JSON.parse(JSON.stringify(cell.comment));
if (isReply) {
if (!replyId || !thread.replies) {
this.endEdit(container);
return;
}
var idx = thread.replies.findIndex(function (r) { return r.id === replyId; });
if (idx > -1) {
thread.replies[idx] = __assign({}, thread.replies[idx], { text: finalText });
this.saveComment(row, col, thread, 'editReply', actionFromPanel);
}
}
else {
var updatedThread = __assign({}, thread, { text: finalText });
this.saveComment(row, col, updatedThread, 'editComment', actionFromPanel);
}
}
}
this.endEdit(container);
};
SpreadsheetComment.prototype.endEdit = function (container) {
if (this.editingState && this.editingState.tsEle) {
this.editingState.tsEle.style.display = isNullOrUndefined(this.editingState.tsValue) ? '' : this.editingState.tsValue;
}
var targetContainer = container || (this.editingState && this.editingState.container);
if (targetContainer) {
targetContainer.classList.remove('e-comment-editing');
this.setTextAreaState(targetContainer, false);
var header = targetContainer.querySelector('.e-comment-header');
if (header) {
var headerWrap = header.querySelector('.e-comment-header-wrap');
if (headerWrap) {
var indices = this.getIndexesFromContainer(targetContainer);
if (indices && indices.length === 2) {
var prev = this.isEditing;
this.isEditing = false;
this.renderHeaderActions(headerWrap, false, getCellAddress(indices[0], indices[1]));
this.isEditing = prev;
}
}
}
var localBodyHost = this.getBodyHost(targetContainer);
if (localBodyHost) {
var replyBtns = localBodyHost.querySelectorAll('.e-reply-ddb');
replyBtns.forEach(function (btn) {
btn.style.visibility = '';
});
}
}
this.isEditing = false;
this.editingState = null;
};
SpreadsheetComment.prototype.deleteReplyById = function (replyId, sourceEl) {
if (replyId && sourceEl) {
var container = this.getContainer(sourceEl);
var host = this.getBodyHost(container);
if (container && host) {
var indexes = this.getIndexesFromContainer(container);
if (indexes && indexes.length === 2) {
var row = indexes[0], col = indexes[1];
var cell = getCell(row, col, this.parent.getActiveSheet());
if (cell && cell.comment) {
var thread = JSON.parse(JSON.stringify(cell.comment));
if (thread.replies) {
var idx = thread.replies.findIndex(function (r) { return r.id === replyId; });
if (idx > -1) {
thread.replies.splice(idx, 1);
this.saveComment(row, col, thread, 'deleteReply', container.classList.contains('e-pane-container'));
var targetListView = getComponent(host, 'listview');
if (targetListView) {
targetListView.removeItem({ id: replyId });
}
}
}
}
}
}
}
};
SpreadsheetComment.prototype.setTextAreaState = function (container, disabled) {
if (container) {
var l10n = this.parent.serviceLocator.getService(locale);
var textArea = container.querySelector('.e-comment-footer .e-comment-input');
if (textArea) {
if (disabled) {
textArea.disabled = true;
textArea.placeholder = l10n.getConstant('CommentEditingInProgress');
}
else {
textArea.disabled = false;
textArea.placeholder = l10n.getConstant('Reply');
this.adjustTextareaHeight(textArea, false);
}
}
}
};
SpreadsheetComment.prototype.adjustTextareaHeight = function (textArea, isEdit) {
if (textArea) {
var cs = getComputedStyle(textArea);
var linePx = parseFloat(cs.lineHeight);
if (isNaN(linePx)) {
var fontSize = parseFloat(cs.fontSize) || 14;
linePx = Math.round(fontSize * 1.2);
}
var padTB = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
var borderTB = (parseFloat(cs.borderTopWidth) || 0) + (parseFloat(cs.borderBottomWidth) || 0);
var minLines = 1;
var maxLines = 5;
if (!isEdit && textArea.value.trim().length === 0) {
textArea.style.height = (minLines * linePx) + padTB + borderTB + "px";
textArea.style.overflowY = 'hidden';
return;
}
textArea.style.height = 'auto';
var contentHeight = Math.max(0, textArea.scrollHeight - padTB);
var neededLines = Math.max(1, Math.ceil(contentHeight / Math.max(1, linePx)));
var clampedLines = Math.max(minLines, Math.min(maxLines, neededLines));
var finalHeight = (clampedLines * linePx) + padTB + borderTB;
textArea.style.height = finalHeight + "px";
textArea.style.overflowY = 'hidden';
}
};
SpreadsheetComment.prototype.saveComment = function (rIdx, cIdx, comment, actionName, isPanel) {
if (comment && !comment.address) {
comment.address = [rIdx, cIdx];
}
var sheet = this.parent.getActiveSheet();
var address = getSheetName(this.parent, this.parent.activeSheetIndex) + '!' + getRangeAddress([rIdx, cIdx]);
var eventArgs = { comment: JSON.parse(JSON.stringify(comment)), address: address, cancel: false };
this.parent.notify(beginAction, { eventArgs: eventArgs, action: actionName });
if (eventArgs.cancel) {
return;
}
comment = JSON.parse(JSON.stringify(eventArgs.comment));
this.processSheetComments({ sheet: sheet, comment: comment, isDelete: false });
updateCell(this.parent, sheet, { rowIdx: rIdx, colIdx: cIdx, preventEvt: true, cell: { comment: comment } });
var td = this.parent.getCell(rIdx, cIdx);
if (td && !td.querySelector('.e-comment-indicator')) {
this.createCommentIndicator({ targetEle: td, rIdx: rIdx, cIdx: cIdx });
}
if (this.isReviewPaneVisible) {
if (actionName === 'addComment') {
this.insertThreadIntoPanel(comment);
this.scrollToThreadInPanel(comment.id);
}
else if (!isPanel && actionName !== 'addComment') {
this.syncThreadInPanel(comment);
}
}
this.parent.notify(completeAction, { eventArgs: eventArgs, action: actionName });
};
SpreadsheetComment.prototype.detachCommentIndicator = function (rowIdx, colIdx) {
var cellElement = this.parent.getCell(rowIdx, colIdx);
if (cellElement) {
var indicator = cellElement.querySelector('.e-comment-indicator');
if (indicator) {
EventHandler.remove(indicator, 'mouseover', this.mouseOver);
EventHandler.remove(indicator, 'mouseout', this.mouseOut);
delete indicator.dataset.commentListenersAdded;
delete indicator.dataset.commentRowIndex;
delete indicator.dataset.commentColIndex;
detach(indicator);
}
}
};
SpreadsheetComment.prototype.setCommentContainerPosition = function (commentContainer, cellRect) {
var selectAllCell = this.parent.element.getElementsByClassName('e-select-all-cell')[0];
var scroller = this.parent.element.getElementsByClassName('e-scroller')[0];
var sheetClientRect = this.parent.element.getElementsByClassName('e-sheet')[0].getBoundingClientRect();
var elementClientRect = this.parent.element.getBoundingClientRect();
var elementPosition = this.parent.element.style.getPropertyValue('position');
var offsetTop = (elementPosition === 'absolute' ? 0 : this.parent.element.offsetTop);
var offsetLeft = (elementPosition === 'absolute' ? 0 : this.parent.element.offsetLeft);
commentContainer.style.position = 'absolute';
var containerTop = cellRect.top - (elementClientRect.top - offsetTop);
if (!isNullOrUndefined(selectAllCell) && !isNullOrUndefined(scroller) &&
cellRect.top < selectAllCell.getBoundingClientRect().bottom) {
containerTop = selectAllCell.getBoundingClientRect().bottom - (elementClientRect.top - offsetTop) + 5;
}
else if (containerTop < 0) {
containerTop = 5;
}
commentContainer.style.top = containerTop + "px";
var leftPos;
var preferredWidth = 244;
var actualWidth = preferredWidth;
var spaceToRight = sheetClientRect.width - (cellRect.left + cellRect.width - sheetClientRect.left);
if (spaceToRight > preferredWidth + 5) {
leftPos = cellRect.left + cellRect.width - (elementClientRect.le