1322 lines
54 KiB
JavaScript
1322 lines
54 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* This program is a free software product. You can redistribute it and/or
|
||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||
* version 3 as published by the Free Software Foundation. In accordance with
|
||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||
* of any third-party rights.
|
||
*
|
||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||
*
|
||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||
* street, Riga, Latvia, EU, LV-1050.
|
||
*
|
||
* The interactive user interfaces in modified source and object code versions
|
||
* of the Program must display Appropriate Legal Notices, as required under
|
||
* Section 5 of the GNU AGPL version 3.
|
||
*
|
||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||
* grant you any rights under trademark law for use of our trademarks.
|
||
*
|
||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||
* well as technical writing content are licensed under the terms of the
|
||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||
*
|
||
*/
|
||
|
||
"use strict";
|
||
|
||
(function (window, undefined) {
|
||
/*
|
||
* Import
|
||
* -----------------------------------------------------------------------------
|
||
*/
|
||
var asc_applyFunction = AscCommonExcel.applyFunction;
|
||
|
||
var c_oAscLockTypes = AscCommon.c_oAscLockTypes;
|
||
|
||
var c_oAscRecalcIndexTypes = AscCommonExcel.c_oAscRecalcIndexTypes;
|
||
var c_oAscLockTypeElemSubType = AscCommonExcel.c_oAscLockTypeElemSubType;
|
||
var c_oAscLockTypeElem = AscCommonExcel.c_oAscLockTypeElem;
|
||
|
||
/**
|
||
* Отвечает за совместное редактирование
|
||
* -----------------------------------------------------------------------------
|
||
*
|
||
* @constructor
|
||
* @memberOf AscCommonExcel
|
||
*/
|
||
function CCollaborativeEditing(handlers, isViewerMode) {
|
||
if (!(this instanceof CCollaborativeEditing)) {
|
||
return new CCollaborativeEditing();
|
||
}
|
||
AscCommon.CCollaborativeEditingBase.call(this);
|
||
|
||
this.m_nUseType = 1; // 1 - 1 клиент и мы сохраняем историю, -1 - несколько клиентов, 0 - переход из -1 в 1
|
||
|
||
this.handlers = new AscCommonExcel.asc_CHandlersList(handlers);
|
||
this.m_bIsViewerMode = !!isViewerMode; // Режим Viewer-а
|
||
this.m_bGlobalLock = 0; // Глобальный lock
|
||
this.m_bGlobalLockEditCell = false; // Глобальный lock (для редактирования ячейки) - отключаем смену select-а, но разрешаем сразу вводить
|
||
this.m_arrCheckLocks = []; // Массив для проверки залоченности объектов, которые мы собираемся изменять
|
||
|
||
this.m_arrNeedUnlock = []; // Массив со списком залоченных объектов(которые были залочены другими пользователями)
|
||
this.m_arrNeedUnlock2 = []; // Массив со списком залоченных объектов(которые были залочены на данном клиенте)
|
||
|
||
this.m_arrChanges = []; // Массив с изменениями других пользователей
|
||
|
||
this.m_oRecalcIndexColumns = {};
|
||
this.m_oRecalcIndexRows = {};
|
||
|
||
this.m_oInsertColumns = {}; // Массив листов с массивами списков добавленных колонок
|
||
this.m_oInsertRows = {}; // Массив листов с массивами списков добавленных строк
|
||
|
||
this.m_bFast = false;
|
||
|
||
this.m_aForeignCursorsData = {};
|
||
this.WaitImages = {};//cell/model/DrawingObjects/GlobalCounters.js
|
||
|
||
this.init();
|
||
|
||
return this;
|
||
}
|
||
|
||
CCollaborativeEditing.prototype = Object.create(AscCommon.CCollaborativeEditingBase.prototype);
|
||
CCollaborativeEditing.prototype.init = function () {
|
||
};
|
||
|
||
// Очищаем индексы пересчета (при открытии это необходимо)
|
||
CCollaborativeEditing.prototype.clearRecalcIndex = function () {
|
||
this.m_oRecalcIndexColumns = {};
|
||
this.m_oRecalcIndexRows = {};
|
||
};
|
||
|
||
// Начало совместного редактирования
|
||
CCollaborativeEditing.prototype.startCollaborationEditing = function () {
|
||
this.m_nUseType = -1;
|
||
};
|
||
|
||
// Временное окончание совместного редактирования
|
||
CCollaborativeEditing.prototype.endCollaborationEditing = function () {
|
||
if (this.m_nUseType <= 0)
|
||
this.m_nUseType = 0;
|
||
};
|
||
|
||
// Выставление режима view
|
||
CCollaborativeEditing.prototype.setViewerMode = function (isViewerMode) {
|
||
this.m_bIsViewerMode = isViewerMode;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.setFast = function (bFast) {
|
||
if (false === bFast) {
|
||
this.Remove_AllForeignCursors();
|
||
}
|
||
return this.m_bFast = bFast;
|
||
};
|
||
CCollaborativeEditing.prototype.getFast = function () {
|
||
return this.m_bFast;
|
||
};
|
||
CCollaborativeEditing.prototype.Is_SingleUser = function () {
|
||
return !this.getCollaborativeEditing();
|
||
};
|
||
CCollaborativeEditing.prototype.getCollaborativeEditing = function () {
|
||
if (this.m_bIsViewerMode)
|
||
return false;
|
||
return 1 !== this.m_nUseType;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.haveOtherChanges = function () {
|
||
return 0 < this.m_arrChanges.length;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getOwnLocksLength = function () {
|
||
return this.m_arrNeedUnlock2.length;
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------------
|
||
// Функции для проверки залоченности объектов
|
||
//-----------------------------------------------------------------------------------
|
||
CCollaborativeEditing.prototype.getGlobalLock = function () {
|
||
return this.m_bGlobalLock;
|
||
};
|
||
CCollaborativeEditing.prototype.getGlobalLockEditCell = function () {
|
||
return this.m_bGlobalLockEditCell;
|
||
};
|
||
CCollaborativeEditing.prototype.onStartEditCell = function () {
|
||
// Вызывать эту функцию только в случае редактирования ячейки и если мы не одни редактируем!!!
|
||
if (this.getCollaborativeEditing())
|
||
this.m_bGlobalLockEditCell = true;
|
||
};
|
||
CCollaborativeEditing.prototype.onStopEditCell = function () {
|
||
// Вызывать эту функцию только в случае окончания редактирования ячейки!!!
|
||
this.m_bGlobalLockEditCell = false;
|
||
};
|
||
CCollaborativeEditing.prototype.lock = function (arrLocks, callback) {
|
||
var type;
|
||
callback = this._checkCollaborative(callback);
|
||
|
||
this.onStartCheckLock();
|
||
for (var i = 0; i < arrLocks.length; ++i) {
|
||
type = this._addCheckLock(arrLocks[i], callback);
|
||
if (c_oAscLockTypes.kLockTypeNone !== type) {
|
||
// Снимаем глобальный лок (для редактирования ячейки)
|
||
this.m_bGlobalLockEditCell = false;
|
||
return c_oAscLockTypes.kLockTypeMine === type;
|
||
}
|
||
}
|
||
this.onEndCheckLock(callback);
|
||
return true;
|
||
};
|
||
CCollaborativeEditing.prototype._checkCollaborative = function (callback) {
|
||
if (false === this.getCollaborativeEditing()) {
|
||
// Пользователь редактирует один: не ждем ответа, а сразу продолжаем редактирование
|
||
AscCommonExcel.applyFunction(callback, true);
|
||
callback = undefined;
|
||
}
|
||
return callback;
|
||
};
|
||
CCollaborativeEditing.prototype._addCheckLock = function (lockInfo, callback) {
|
||
if (false !== this.getLockIntersection(lockInfo, c_oAscLockTypes.kLockTypeMine, false)) {
|
||
// Редактируем сами
|
||
AscCommonExcel.applyFunction(callback, true);
|
||
return c_oAscLockTypes.kLockTypeMine;
|
||
} else if (false !== this.getLockIntersection(lockInfo, c_oAscLockTypes.kLockTypeOther, false)) {
|
||
// Уже ячейку кто-то редактирует
|
||
AscCommonExcel.applyFunction(callback, false);
|
||
return c_oAscLockTypes.kLockTypeOther;
|
||
}
|
||
|
||
this.m_arrCheckLocks.push(lockInfo);
|
||
return c_oAscLockTypes.kLockTypeNone;
|
||
};
|
||
CCollaborativeEditing.prototype.onStartCheckLock = function () {
|
||
this.m_arrCheckLocks.length = 0;
|
||
};
|
||
CCollaborativeEditing.prototype.addCheckLock = function (oItem) {
|
||
this.m_arrCheckLocks.push(oItem);
|
||
};
|
||
CCollaborativeEditing.prototype.onEndCheckLock = function (callback) {
|
||
var t = this;
|
||
if (this.m_arrCheckLocks.length > 0) {
|
||
// Отправляем запрос на сервер со списком элементов
|
||
this.handlers.trigger("askLock", this.m_arrCheckLocks, function (result) {
|
||
t.onCallbackAskLock(result, callback);
|
||
});
|
||
|
||
if (undefined !== callback) {
|
||
// Ставим глобальный лок (только если мы не одни и ждем ответа!)
|
||
this.Set_GlobalLock(true);
|
||
}
|
||
} else {
|
||
asc_applyFunction(callback, true);
|
||
|
||
// Снимаем глобальный лок (для редактирования ячейки)
|
||
this.m_bGlobalLockEditCell = false;
|
||
}
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.onCallbackAskLock = function (result, callback) {
|
||
// Снимаем глобальный лок
|
||
this.Set_GlobalLock(false);
|
||
// Снимаем глобальный лок (для редактирования ячейки)
|
||
this.m_bGlobalLockEditCell = false;
|
||
|
||
if (result["lock"]) {
|
||
// Пробегаемся по массиву и проставляем, что залочено нами
|
||
var count = this.m_arrCheckLocks.length;
|
||
for (var i = 0; i < count; ++i) {
|
||
var oItem = this.m_arrCheckLocks[i];
|
||
|
||
if (true !== oItem && false !== oItem) // сравниваем по значению и типу обязательно
|
||
{
|
||
var oNewLock = new CLock(oItem);
|
||
oNewLock.setType(c_oAscLockTypes.kLockTypeMine);
|
||
this.addUnlock2(oNewLock);
|
||
}
|
||
}
|
||
|
||
asc_applyFunction(callback, true);
|
||
} else if (result["error"]) {
|
||
if (Asc.editor.frameManager.isLoadingOleEditor) {
|
||
Asc.editor.sync_closeOleEditor();
|
||
}
|
||
|
||
asc_applyFunction(callback, false);
|
||
}
|
||
|
||
Asc.editor.frameManager.endLoadOleEditor();
|
||
};
|
||
CCollaborativeEditing.prototype.addUnlock = function (LockClass) {
|
||
this.m_arrNeedUnlock.push(LockClass);
|
||
};
|
||
CCollaborativeEditing.prototype.addUnlock2 = function (Lock) {
|
||
this.m_arrNeedUnlock2.push(Lock);
|
||
this.handlers.trigger("updateDocumentCanSave");
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.removeUnlock = function (Lock) {
|
||
for (var i = 0; i < this.m_arrNeedUnlock.length; ++i)
|
||
if (Lock.Element["guid"] === this.m_arrNeedUnlock[i].Element["guid"]) {
|
||
this.m_arrNeedUnlock.splice(i, 1);
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.addChanges = function (oChanges) {
|
||
this.m_arrChanges.push(oChanges);
|
||
};
|
||
|
||
// Возвращает - нужно ли отправлять end action
|
||
CCollaborativeEditing.prototype.applyChanges = function (oColor) {
|
||
var t = this;
|
||
var length = this.m_arrChanges.length;
|
||
var oApi = Asc.editor;
|
||
// Принимаем изменения
|
||
if (0 < length) {
|
||
//splice to prevent double apply other changes in case of load fonts
|
||
oApi.sendEvent("asc_onBeforeApplyChanges");
|
||
var changes = t.m_arrChanges.splice(0, length);
|
||
this.handlers.trigger("applyChanges", changes, function () {
|
||
t.handlers.trigger("updateAfterApplyChanges");
|
||
}, oColor);
|
||
oApi.sendEvent("asc_onApplyChanges");
|
||
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.sendChanges = function (IsUserSave, isAfterAskSave, changesToSend) {
|
||
// Когда не совместное редактирование чистить ничего не нужно, но отправлять нужно.
|
||
var bIsCollaborative = this.getCollaborativeEditing();
|
||
|
||
var bCheckRedraw = false, bRedrawGraphicObjects = false, bUnlockDefName = false;
|
||
var oLock = null;
|
||
if (bIsCollaborative) {
|
||
if (0 < this.m_arrNeedUnlock.length || 0 < this.m_arrNeedUnlock2.length) {
|
||
bCheckRedraw = true;
|
||
this.handlers.trigger("cleanSelection");
|
||
}
|
||
|
||
// Очищаем свои изменения
|
||
while (0 < this.m_arrNeedUnlock2.length) {
|
||
oLock = this.m_arrNeedUnlock2.shift();
|
||
oLock.setType(c_oAscLockTypes.kLockTypeNone, false);
|
||
|
||
var drawing = AscCommon.g_oTableId.Get_ById(oLock.Element["rangeOrObjectId"]);
|
||
if (drawing && drawing.lockType !== c_oAscLockTypes.kLockTypeNone) {
|
||
var bLocked = drawing.lockType !== c_oAscLockTypes.kLockTypeNone && drawing.lockType !== c_oAscLockTypes.kLockTypeMine;
|
||
drawing.lockType = c_oAscLockTypes.kLockTypeNone;
|
||
bRedrawGraphicObjects = true;
|
||
if (drawing instanceof AscCommon.CCore) {
|
||
if (bLocked) {
|
||
Asc.editor && Asc.editor.sendEvent("asc_onLockCore", false);
|
||
}
|
||
}
|
||
}
|
||
if (!bUnlockDefName) {
|
||
bUnlockDefName = this.handlers.trigger("checkDefNameLock", oLock);
|
||
}
|
||
|
||
this.handlers.trigger("releaseLocks", oLock.Element["guid"]);
|
||
}
|
||
|
||
// Очищаем примененные чужие изменения
|
||
var nIndex = 0;
|
||
var nCount = this.m_arrNeedUnlock.length;
|
||
for (; nIndex < nCount; ++nIndex) {
|
||
oLock = this.m_arrNeedUnlock[nIndex];
|
||
if (c_oAscLockTypes.kLockTypeOther2 === oLock.getType()) {
|
||
if (!this.handlers.trigger("checkCommentRemoveLock", oLock.Element)
|
||
&& !this.handlers.trigger("checkCFRemoveLock", oLock.Element) &&
|
||
!this.handlers.trigger("checkProtectedRangeRemoveLock", oLock.Element)) {
|
||
drawing = AscCommon.g_oTableId.Get_ById(oLock.Element["rangeOrObjectId"]);
|
||
if (drawing && drawing.lockType !== c_oAscLockTypes.kLockTypeNone) {
|
||
var bLocked = drawing.lockType !== c_oAscLockTypes.kLockTypeNone && drawing.lockType !== c_oAscLockTypes.kLockTypeMine;
|
||
drawing.lockType = c_oAscLockTypes.kLockTypeNone;
|
||
bRedrawGraphicObjects = true;
|
||
if (drawing instanceof AscCommon.CCore) {
|
||
if (bLocked) {
|
||
Asc.editor && Asc.editor.sendEvent("asc_onLockCore", false);
|
||
}
|
||
}
|
||
}
|
||
if (!bUnlockDefName) {
|
||
bUnlockDefName = this.handlers.trigger("checkDefNameLock", oLock);
|
||
}
|
||
}
|
||
|
||
this.m_arrNeedUnlock.splice(nIndex, 1);
|
||
--nIndex;
|
||
--nCount;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Отправляем на сервер изменения
|
||
this.handlers.trigger("sendChanges", this.getRecalcIndexSave(this.m_oRecalcIndexColumns), this.getRecalcIndexSave(this.m_oRecalcIndexRows), isAfterAskSave, changesToSend);
|
||
|
||
if (bIsCollaborative) {
|
||
// Пересчитываем lock-и от чужих пользователей
|
||
this._recalcLockArrayOthers();
|
||
|
||
// Очищаем свои изменения (удаляем массив добавленных строк/столбцов)
|
||
delete this.m_oInsertColumns;
|
||
delete this.m_oInsertRows;
|
||
this.m_oInsertColumns = {};
|
||
this.m_oInsertRows = {};
|
||
// Очищаем свои пересчетные индексы
|
||
this.clearRecalcIndex();
|
||
|
||
// Чистим Undo/Redo
|
||
AscCommon.History.Clear_Redo();
|
||
AscCommon.History.Clear();
|
||
|
||
// Перерисовываем
|
||
if (bCheckRedraw) {
|
||
this.handlers.trigger("drawSelection");
|
||
this.handlers.trigger("drawFrozenPaneLines");
|
||
this.handlers.trigger("updateAllSheetsLock");
|
||
this.handlers.trigger("showComments");
|
||
}
|
||
|
||
if (bCheckRedraw || bRedrawGraphicObjects)
|
||
this.handlers.trigger("showDrawingObjects");
|
||
|
||
// if(bUnlockDefName){
|
||
this.handlers.trigger("unlockDefName");
|
||
// }
|
||
|
||
this.handlers.trigger("updateAllLayoutsLock");
|
||
this.handlers.trigger("asc_onLockPrintArea");
|
||
this.handlers.trigger("updateAllHeaderFooterLock");
|
||
this.handlers.trigger("onUpdateAllPrintScaleLock");
|
||
this.handlers.trigger("updateAllSheetViewLock");
|
||
|
||
this.handlers.trigger("unlockCF");
|
||
this.handlers.trigger("unlockProtectedRange");
|
||
|
||
this.handlers.trigger("unlockUserProtectedRanges");
|
||
|
||
if (0 === this.m_nUseType)
|
||
this.m_nUseType = 1;
|
||
} else {
|
||
// Обновляем точку последнего сохранения в истории
|
||
AscCommon.History.Reset_SavedIndex(IsUserSave);
|
||
}
|
||
|
||
Asc.editor.wb.Document_UpdateUndoRedoState();
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getRecalcIndexSave = function (oRecalcIndex) {
|
||
var bHasIndex = false;
|
||
var result = {};
|
||
var element = null;
|
||
for (var sheetId in oRecalcIndex) {
|
||
if (!oRecalcIndex.hasOwnProperty(sheetId))
|
||
continue;
|
||
result[sheetId] = {"_arrElements": []};
|
||
for (var i = 0, length = oRecalcIndex[sheetId]._arrElements.length; i < length; ++i) {
|
||
bHasIndex = true;
|
||
element = oRecalcIndex[sheetId]._arrElements[i];
|
||
result[sheetId]["_arrElements"].push({
|
||
"_recalcType": element._recalcType,
|
||
"_position": element._position, "_count": element._count,
|
||
"m_bIsSaveIndex": element.m_bIsSaveIndex
|
||
});
|
||
}
|
||
}
|
||
|
||
return bHasIndex ? result : null;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.S4 = function () {
|
||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||
};
|
||
CCollaborativeEditing.prototype.createGUID = function () {
|
||
return (this.S4() + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + this.S4() + this.S4());
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getLockInfo = function (typeElem, subType, sheetId, info) {
|
||
var oLockInfo = new AscCommonExcel.asc_CLockInfo();
|
||
oLockInfo["sheetId"] = sheetId;
|
||
oLockInfo["type"] = typeElem;
|
||
oLockInfo["subType"] = subType;
|
||
oLockInfo["guid"] = this.createGUID();
|
||
oLockInfo["rangeOrObjectId"] = info;
|
||
return oLockInfo;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getLockByElem = function (element, type) {
|
||
var arrayElements = (c_oAscLockTypes.kLockTypeMine === type) ? this.m_arrNeedUnlock2 : this.m_arrNeedUnlock;
|
||
for (var i = 0; i < arrayElements.length; ++i)
|
||
if (element["guid"] === arrayElements[i].Element["guid"])
|
||
return arrayElements[i];
|
||
return null;
|
||
};
|
||
|
||
/**
|
||
* Проверка lock для элемента
|
||
* @param {asc_CLockInfo} element элемент для проверки lock
|
||
* @param {c_oAscLockTypes} type сами(kLockTypeMine) или кто-то другой
|
||
* @param {Boolean} bCheckOnlyLockAll проверять только lock для свойств всего листа (либо только проверять удален ли лист, а не просто залочен)
|
||
*/
|
||
CCollaborativeEditing.prototype.getLockIntersection = function (element, type, bCheckOnlyLockAll) {
|
||
var arrayElements = (c_oAscLockTypes.kLockTypeMine === type) ? this.m_arrNeedUnlock2 : this.m_arrNeedUnlock;
|
||
var oUnlockElement = null, rangeTmp1, rangeTmp2;
|
||
for (var i = 0; i < arrayElements.length; ++i) {
|
||
oUnlockElement = arrayElements[i].Element;
|
||
if (c_oAscLockTypeElem.Sheet === element["type"] && element["type"] === oUnlockElement["type"]) {
|
||
// Проверка только на удаление листа (если проверка для себя, то выходим не сразу, т.к. нужно проверить lock от других элементов)
|
||
if ((c_oAscLockTypes.kLockTypeMine !== type && false === bCheckOnlyLockAll) ||
|
||
element["sheetId"] === oUnlockElement["sheetId"]) {
|
||
// Если кто-то залочил sheet, то больше никто не может лочить sheet-ы (иначе можно удалить все листы)
|
||
return arrayElements[i];
|
||
}
|
||
}
|
||
if (element["sheetId"] !== oUnlockElement["sheetId"])
|
||
continue;
|
||
|
||
if (null !== element["subType"] && null !== oUnlockElement["subType"])
|
||
return arrayElements[i];
|
||
|
||
// Не учитываем lock от ChangeProperties (только если это не lock листа)
|
||
if (true === bCheckOnlyLockAll ||
|
||
(c_oAscLockTypeElemSubType.ChangeProperties === oUnlockElement["subType"]
|
||
&& c_oAscLockTypeElem.Sheet !== element["type"]))
|
||
continue;
|
||
|
||
if (element["type"] === oUnlockElement["type"]) {
|
||
if (element["type"] === c_oAscLockTypeElem.Object) {
|
||
if (element["rangeOrObjectId"] === oUnlockElement["rangeOrObjectId"])
|
||
return arrayElements[i];
|
||
} else if (element["type"] === c_oAscLockTypeElem.Range) {
|
||
// Не учитываем lock от Insert
|
||
if (c_oAscLockTypes.kLockTypeMine === type || c_oAscLockTypeElemSubType.InsertRows === oUnlockElement["subType"] || c_oAscLockTypeElemSubType.InsertColumns === oUnlockElement["subType"])
|
||
continue;
|
||
rangeTmp1 = oUnlockElement["rangeOrObjectId"];
|
||
rangeTmp2 = element["rangeOrObjectId"];
|
||
if (rangeTmp2["c1"] > rangeTmp1["c2"] || rangeTmp2["c2"] < rangeTmp1["c1"] || rangeTmp2["r1"] > rangeTmp1["r2"] || rangeTmp2["r2"] < rangeTmp1["r1"])
|
||
continue;
|
||
return arrayElements[i];
|
||
}
|
||
} else if (oUnlockElement["type"] === c_oAscLockTypeElem.Sheet ||
|
||
(element["type"] === c_oAscLockTypeElem.Sheet && c_oAscLockTypes.kLockTypeMine !== type)) {
|
||
// Если кто-то уже залочил лист или мы пытаемся сами залочить и проверяем на чужие lock
|
||
return arrayElements[i];
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getLockElem = function (typeElem, type, sheetId) {
|
||
var arrayElements = (c_oAscLockTypes.kLockTypeMine === type) ? this.m_arrNeedUnlock2 : this.m_arrNeedUnlock;
|
||
var count = arrayElements.length;
|
||
var element = null, oRangeOrObjectId = null;
|
||
var result = [];
|
||
var c1, c2, r1, r2;
|
||
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexColumns[sheetId] = new CRecalcIndex();
|
||
}
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexRows[sheetId] = new CRecalcIndex();
|
||
}
|
||
|
||
for (var i = 0; i < count; ++i) {
|
||
element = arrayElements[i].Element;
|
||
if (element["sheetId"] !== sheetId || element["type"] !== typeElem)
|
||
continue;
|
||
|
||
// Отображать залоченность удаленных текущим пользователем строк/столбцов не нужно (уже нечего отображать)
|
||
if (c_oAscLockTypes.kLockTypeMine === type && c_oAscLockTypeElem.Range === typeElem &&
|
||
(c_oAscLockTypeElemSubType.DeleteColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.DeleteRows === element["subType"]))
|
||
continue;
|
||
// Отображать залоченность добавленных другим пользователем строк/столбцов не нужно (еще нечего отображать)
|
||
if (c_oAscLockTypeElem.Range === typeElem &&
|
||
(c_oAscLockTypeElemSubType.InsertColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.InsertRows === element["subType"]))
|
||
continue;
|
||
// Отображать lock-диапазон для lockAll(всего листа) не нужно
|
||
if (c_oAscLockTypeElemSubType.ChangeProperties === element["subType"])
|
||
continue;
|
||
|
||
oRangeOrObjectId = element["rangeOrObjectId"];
|
||
// Для диапазона нужно сделать пересчет с учетом удаленных или добавленных строк/столбцов
|
||
if (c_oAscLockTypeElem.Range === typeElem) {
|
||
// Пересчитывать для удаленных строк/столбцов у другого пользователя не нужно
|
||
if (c_oAscLockTypes.kLockTypeMine !== type && c_oAscLockTypeElem.Range === typeElem &&
|
||
(c_oAscLockTypeElemSubType.DeleteColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.DeleteRows === element["subType"])) {
|
||
c1 = oRangeOrObjectId["c1"];
|
||
c2 = oRangeOrObjectId["c2"];
|
||
r1 = oRangeOrObjectId["r1"];
|
||
r2 = oRangeOrObjectId["r2"];
|
||
} else {
|
||
c1 = this.m_oRecalcIndexColumns[sheetId].getLockOther(oRangeOrObjectId["c1"], type);
|
||
c2 = this.m_oRecalcIndexColumns[sheetId].getLockOther(oRangeOrObjectId["c2"], type);
|
||
r1 = this.m_oRecalcIndexRows[sheetId].getLockOther(oRangeOrObjectId["r1"], type);
|
||
r2 = this.m_oRecalcIndexRows[sheetId].getLockOther(oRangeOrObjectId["r2"], type);
|
||
}
|
||
if (null === c1 || null === c2 || null === r1 || null === r2)
|
||
continue;
|
||
|
||
oRangeOrObjectId = new Asc.Range(c1, r1, c2, r2);
|
||
}
|
||
|
||
result.push(oRangeOrObjectId);
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.getLockCellsMe = function (sheetId) {
|
||
return this.getLockElem(c_oAscLockTypeElem.Range, c_oAscLockTypes.kLockTypeMine, sheetId);
|
||
};
|
||
CCollaborativeEditing.prototype.getLockCellsOther = function (sheetId) {
|
||
return this.getLockElem(c_oAscLockTypeElem.Range, c_oAscLockTypes.kLockTypeOther, sheetId);
|
||
};
|
||
CCollaborativeEditing.prototype.getLockObjectsMe = function (sheetId) {
|
||
return this.getLockElem(c_oAscLockTypeElem.Object, c_oAscLockTypes.kLockTypeMine, sheetId);
|
||
};
|
||
CCollaborativeEditing.prototype.getLockObjectsOther = function (sheetId) {
|
||
return this.getLockElem(c_oAscLockTypeElem.Object, c_oAscLockTypes.kLockTypeOther, sheetId);
|
||
};
|
||
/**
|
||
* Проверка lock для всего листа
|
||
* @param {Number} sheetId элемент для проверки lock
|
||
* @return {Asc.c_oAscMouseMoveLockedObjectType} oLockedObjectType
|
||
*/
|
||
CCollaborativeEditing.prototype.isLockAllOther = function (sheetId) {
|
||
var arrayElements = this.m_arrNeedUnlock;
|
||
var count = arrayElements.length;
|
||
var element = null;
|
||
var oLockedObjectType = Asc.c_oAscMouseMoveLockedObjectType.None;
|
||
|
||
for (var i = 0; i < count; ++i) {
|
||
element = arrayElements[i].Element;
|
||
if (element["sheetId"] === sheetId) {
|
||
if (element["type"] === c_oAscLockTypeElem.Sheet) {
|
||
oLockedObjectType = Asc.c_oAscMouseMoveLockedObjectType.Sheet;
|
||
break;
|
||
} else if (element["type"] === c_oAscLockTypeElem.Range && null !== element["subType"])
|
||
oLockedObjectType = Asc.c_oAscMouseMoveLockedObjectType.TableProperties;
|
||
}
|
||
}
|
||
return oLockedObjectType;
|
||
};
|
||
|
||
CCollaborativeEditing.prototype._recalcLockArray = function (typeLock, oRecalcIndexColumns, oRecalcIndexRows) {
|
||
var arrayElements = (c_oAscLockTypes.kLockTypeMine === typeLock) ? this.m_arrNeedUnlock2 : this.m_arrNeedUnlock;
|
||
var count = arrayElements.length;
|
||
var element = null, oRangeOrObjectId = null;
|
||
var i;
|
||
var sheetId = -1;
|
||
|
||
for (i = 0; i < count; ++i) {
|
||
element = arrayElements[i].Element;
|
||
// Для удаления пересчитывать индексы не нужно
|
||
if (c_oAscLockTypeElem.Range !== element["type"] ||
|
||
c_oAscLockTypeElemSubType.InsertColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.InsertRows === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.DeleteColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.DeleteRows === element["subType"])
|
||
continue;
|
||
sheetId = element["sheetId"];
|
||
|
||
oRangeOrObjectId = element["rangeOrObjectId"];
|
||
|
||
if (oRecalcIndexColumns && oRecalcIndexColumns.hasOwnProperty(sheetId)) {
|
||
// Пересчет колонок
|
||
oRangeOrObjectId["c1"] = oRecalcIndexColumns[sheetId].getLockMe(oRangeOrObjectId["c1"]);
|
||
oRangeOrObjectId["c2"] = oRecalcIndexColumns[sheetId].getLockMe(oRangeOrObjectId["c2"]);
|
||
}
|
||
if (oRecalcIndexRows && oRecalcIndexRows.hasOwnProperty(sheetId)) {
|
||
// Пересчет строк
|
||
oRangeOrObjectId["r1"] = oRecalcIndexRows[sheetId].getLockMe(oRangeOrObjectId["r1"]);
|
||
oRangeOrObjectId["r2"] = oRecalcIndexRows[sheetId].getLockMe(oRangeOrObjectId["r2"]);
|
||
}
|
||
}
|
||
};
|
||
// Пересчет только для чужих Lock при сохранении на клиенте, который добавлял/удалял строки или столбцы
|
||
CCollaborativeEditing.prototype._recalcLockArrayOthers = function () {
|
||
var typeLock = c_oAscLockTypes.kLockTypeOther;
|
||
var arrayElements = (c_oAscLockTypes.kLockTypeMine === typeLock) ? this.m_arrNeedUnlock2 : this.m_arrNeedUnlock;
|
||
var count = arrayElements.length;
|
||
var element = null, oRangeOrObjectId = null;
|
||
var i;
|
||
var sheetId = -1;
|
||
|
||
for (i = 0; i < count; ++i) {
|
||
element = arrayElements[i].Element;
|
||
if (c_oAscLockTypeElem.Range !== element["type"] ||
|
||
c_oAscLockTypeElemSubType.InsertColumns === element["subType"] ||
|
||
c_oAscLockTypeElemSubType.InsertRows === element["subType"])
|
||
continue;
|
||
sheetId = element["sheetId"];
|
||
|
||
oRangeOrObjectId = element["rangeOrObjectId"];
|
||
|
||
if (this.m_oRecalcIndexColumns.hasOwnProperty(sheetId)) {
|
||
// Пересчет колонок
|
||
oRangeOrObjectId["c1"] = this.m_oRecalcIndexColumns[sheetId].getLockOther(oRangeOrObjectId["c1"]);
|
||
oRangeOrObjectId["c2"] = this.m_oRecalcIndexColumns[sheetId].getLockOther(oRangeOrObjectId["c2"]);
|
||
}
|
||
if (this.m_oRecalcIndexRows.hasOwnProperty(sheetId)) {
|
||
// Пересчет строк
|
||
oRangeOrObjectId["r1"] = this.m_oRecalcIndexRows[sheetId].getLockOther(oRangeOrObjectId["r1"]);
|
||
oRangeOrObjectId["r2"] = this.m_oRecalcIndexRows[sheetId].getLockOther(oRangeOrObjectId["r2"]);
|
||
}
|
||
}
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.addRecalcIndex = function (type, oRecalcIndex) {
|
||
if (null == oRecalcIndex)
|
||
return null;
|
||
var nIndex = 0;
|
||
var nRecalcType = c_oAscRecalcIndexTypes.RecalcIndexAdd;
|
||
var oRecalcIndexElement = null;
|
||
var oRecalcIndexResult = {};
|
||
|
||
var oRecalcIndexTmp = ("0" === type) ? this.m_oRecalcIndexColumns : this.m_oRecalcIndexRows;
|
||
for (var sheetId in oRecalcIndex) {
|
||
if (oRecalcIndex.hasOwnProperty(sheetId)) {
|
||
if (!oRecalcIndexTmp.hasOwnProperty(sheetId)) {
|
||
oRecalcIndexTmp[sheetId] = new CRecalcIndex();
|
||
}
|
||
if (!oRecalcIndexResult.hasOwnProperty(sheetId)) {
|
||
oRecalcIndexResult[sheetId] = new CRecalcIndex();
|
||
}
|
||
for (; nIndex < oRecalcIndex[sheetId]["_arrElements"].length; ++nIndex) {
|
||
oRecalcIndexElement = oRecalcIndex[sheetId]["_arrElements"][nIndex];
|
||
if (true === oRecalcIndexElement["m_bIsSaveIndex"])
|
||
continue;
|
||
nRecalcType = (c_oAscRecalcIndexTypes.RecalcIndexAdd === oRecalcIndexElement["_recalcType"]) ?
|
||
c_oAscRecalcIndexTypes.RecalcIndexRemove : c_oAscRecalcIndexTypes.RecalcIndexAdd;
|
||
oRecalcIndexTmp[sheetId].add(nRecalcType, oRecalcIndexElement["_position"],
|
||
oRecalcIndexElement["_count"], /*bIsSaveIndex*/true);
|
||
// Дублируем для возврата результата (нам нужно пересчитать только по последнему индексу
|
||
oRecalcIndexResult[sheetId].add(nRecalcType, oRecalcIndexElement["_position"],
|
||
oRecalcIndexElement["_count"], /*bIsSaveIndex*/true);
|
||
}
|
||
}
|
||
}
|
||
|
||
return oRecalcIndexResult;
|
||
};
|
||
|
||
// Undo для добавления/удаления столбцов
|
||
CCollaborativeEditing.prototype.undoCols = function (sheetId, count) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId))
|
||
return;
|
||
this.m_oRecalcIndexColumns[sheetId].remove(count);
|
||
};
|
||
// Undo для добавления/удаления строк
|
||
CCollaborativeEditing.prototype.undoRows = function (sheetId, count) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId))
|
||
return;
|
||
this.m_oRecalcIndexRows[sheetId].remove(count);
|
||
};
|
||
|
||
CCollaborativeEditing.prototype.removeCols = function (sheetId, position, count) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexColumns[sheetId] = new CRecalcIndex();
|
||
}
|
||
this.m_oRecalcIndexColumns[sheetId].add(c_oAscRecalcIndexTypes.RecalcIndexRemove, position,
|
||
count, /*bIsSaveIndex*/false);
|
||
};
|
||
CCollaborativeEditing.prototype.addCols = function (sheetId, position, count) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexColumns[sheetId] = new CRecalcIndex();
|
||
}
|
||
this.m_oRecalcIndexColumns[sheetId].add(c_oAscRecalcIndexTypes.RecalcIndexAdd, position,
|
||
count, /*bIsSaveIndex*/false);
|
||
};
|
||
CCollaborativeEditing.prototype.removeRows = function (sheetId, position, count) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexRows[sheetId] = new CRecalcIndex();
|
||
}
|
||
this.m_oRecalcIndexRows[sheetId].add(c_oAscRecalcIndexTypes.RecalcIndexRemove, position,
|
||
count, /*bIsSaveIndex*/false);
|
||
};
|
||
CCollaborativeEditing.prototype.addRows = function (sheetId, position, count) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId)) {
|
||
this.m_oRecalcIndexRows[sheetId] = new CRecalcIndex();
|
||
}
|
||
this.m_oRecalcIndexRows[sheetId].add(c_oAscRecalcIndexTypes.RecalcIndexAdd, position,
|
||
count, /*bIsSaveIndex*/false);
|
||
};
|
||
CCollaborativeEditing.prototype.addColsRange = function (sheetId, range) {
|
||
if (!this.m_oInsertColumns.hasOwnProperty(sheetId)) {
|
||
this.m_oInsertColumns[sheetId] = [];
|
||
}
|
||
var arrInsertColumns = this.m_oInsertColumns[sheetId];
|
||
// Перед добавлением нужно передвинуть имеющиеся
|
||
var countCols = range.c2 - range.c1 + 1;
|
||
var isAddNewRange = true;
|
||
for (var i = 0; i < arrInsertColumns.length; ++i) {
|
||
if (arrInsertColumns[i].c1 > range.c1) {
|
||
arrInsertColumns[i].c1 += countCols;
|
||
arrInsertColumns[i].c2 += countCols;
|
||
} else if (arrInsertColumns[i].c1 <= range.c1 && arrInsertColumns[i].c2 >= range.c1) {
|
||
arrInsertColumns[i].c2 += countCols;
|
||
isAddNewRange = false;
|
||
}
|
||
}
|
||
if (isAddNewRange)
|
||
arrInsertColumns.push(range);
|
||
};
|
||
CCollaborativeEditing.prototype.addRowsRange = function (sheetId, range) {
|
||
if (!this.m_oInsertRows.hasOwnProperty(sheetId)) {
|
||
this.m_oInsertRows[sheetId] = [];
|
||
}
|
||
var arrInsertRows = this.m_oInsertRows[sheetId];
|
||
// Перед добавлением нужно передвинуть имеющиеся
|
||
var countRows = range.r2 - range.r1 + 1;
|
||
var isAddNewRange = true;
|
||
for (var i = 0; i < arrInsertRows.length; ++i) {
|
||
if (arrInsertRows[i].r1 > range.r1) {
|
||
arrInsertRows[i].r1 += countRows;
|
||
arrInsertRows[i].r2 += countRows;
|
||
} else if (arrInsertRows[i].r1 <= range.r1 && arrInsertRows[i].r2 >= range.r1) {
|
||
arrInsertRows[i].r2 += countRows;
|
||
isAddNewRange = false;
|
||
}
|
||
}
|
||
if (isAddNewRange)
|
||
arrInsertRows.push(range);
|
||
};
|
||
CCollaborativeEditing.prototype.removeColsRange = function (sheetId, range) {
|
||
if (!this.m_oInsertColumns.hasOwnProperty(sheetId))
|
||
return;
|
||
var arrInsertColumns = this.m_oInsertColumns[sheetId];
|
||
// Нужно убрать те колонки, которые входят в диапазон
|
||
var countCols = range.c2 - range.c1 + 1;
|
||
for (var i = 0; i < arrInsertColumns.length; ++i) {
|
||
if (arrInsertColumns[i].c1 > range.c2) {
|
||
// Справа от удаляемого диапазона
|
||
arrInsertColumns[i].c1 -= countCols;
|
||
arrInsertColumns[i].c2 -= countCols;
|
||
} else if (arrInsertColumns[i].c1 >= range.c1 && arrInsertColumns[i].c2 <= range.c2) {
|
||
// Полностью включение в удаляемый диапазон
|
||
arrInsertColumns.splice(i, 1);
|
||
i -= 1;
|
||
} else if (arrInsertColumns[i].c1 >= range.c1 && arrInsertColumns[i].c1 <= range.c2 && arrInsertColumns[i].c2 > range.c2) {
|
||
// Частичное включение начала диапазона
|
||
arrInsertColumns[i].c1 = range.c2 + 1;
|
||
arrInsertColumns[i].c1 -= countCols;
|
||
arrInsertColumns[i].c2 -= countCols;
|
||
} else if (arrInsertColumns[i].c1 < range.c1 && arrInsertColumns[i].c2 >= range.c1 && arrInsertColumns[i].c2 <= range.c2) {
|
||
// Частичное включение окончания диапазона
|
||
arrInsertColumns[i].c2 = range.c1 - 1;
|
||
} else if (arrInsertColumns[i].c1 < range.c1 && arrInsertColumns[i].c2 > range.c2) {
|
||
// Удаляемый диапазон внутри нашего диапазона
|
||
arrInsertColumns[i].c2 -= countCols;
|
||
}
|
||
}
|
||
};
|
||
CCollaborativeEditing.prototype.removeRowsRange = function (sheetId, range) {
|
||
if (!this.m_oInsertRows.hasOwnProperty(sheetId))
|
||
return;
|
||
var arrInsertRows = this.m_oInsertRows[sheetId];
|
||
// Нужно убрать те строки, которые входят в диапазон
|
||
var countRows = range.r2 - range.r1 + 1;
|
||
for (var i = 0; i < arrInsertRows.length; ++i) {
|
||
if (arrInsertRows[i].r1 > range.r2) {
|
||
// Снизу от удаляемого диапазона
|
||
arrInsertRows[i].r1 -= countRows;
|
||
arrInsertRows[i].r2 -= countRows;
|
||
} else if (arrInsertRows[i].r1 >= range.r1 && arrInsertRows[i].r2 <= range.r2) {
|
||
// Полностью включение в удаляемый диапазон
|
||
arrInsertRows.splice(i, 1);
|
||
i -= 1;
|
||
} else if (arrInsertRows[i].r1 >= range.r1 && arrInsertRows[i].r1 <= range.r2 && arrInsertRows[i].r2 > range.r2) {
|
||
// Частичное включение начала диапазона
|
||
arrInsertRows[i].r1 = range.r2 + 1;
|
||
arrInsertRows[i].r1 -= countRows;
|
||
arrInsertRows[i].r2 -= countRows;
|
||
} else if (arrInsertRows[i].r1 < range.r1 && arrInsertRows[i].r2 >= range.r1 && arrInsertRows[i].r2 <= range.r2) {
|
||
// Частичное включение окончания диапазона
|
||
arrInsertRows[i].r2 = range.r1 - 1;
|
||
} else if (arrInsertRows[i].r1 < range.r1 && arrInsertRows[i].r2 > range.r2) {
|
||
// Удаляемый диапазон внутри нашего диапазона
|
||
arrInsertRows[i].r2 -= countRows;
|
||
}
|
||
}
|
||
};
|
||
CCollaborativeEditing.prototype.isIntersectionInCols = function (sheetId, col) {
|
||
if (!this.m_oInsertColumns.hasOwnProperty(sheetId))
|
||
return false;
|
||
var arrInsertColumns = this.m_oInsertColumns[sheetId];
|
||
for (var i = 0; i < arrInsertColumns.length; ++i) {
|
||
if (arrInsertColumns[i].c1 <= col && col <= arrInsertColumns[i].c2)
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
CCollaborativeEditing.prototype.isIntersectionInRows = function (sheetId, row) {
|
||
if (!this.m_oInsertRows.hasOwnProperty(sheetId))
|
||
return false;
|
||
var arrInsertRows = this.m_oInsertRows[sheetId];
|
||
for (var i = 0; i < arrInsertRows.length; ++i) {
|
||
if (arrInsertRows[i].r1 <= row && row <= arrInsertRows[i].r2)
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
CCollaborativeEditing.prototype.getArrayInsertColumnsBySheetId = function (sheetId) {
|
||
if (!this.m_oInsertColumns.hasOwnProperty(sheetId))
|
||
return [];
|
||
|
||
return this.m_oInsertColumns[sheetId];
|
||
};
|
||
CCollaborativeEditing.prototype.getArrayInsertRowsBySheetId = function (sheetId) {
|
||
if (!this.m_oInsertRows.hasOwnProperty(sheetId))
|
||
return [];
|
||
|
||
return this.m_oInsertRows[sheetId];
|
||
};
|
||
CCollaborativeEditing.prototype.getLockMeColumn = function (sheetId, col) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId))
|
||
return col;
|
||
return this.m_oRecalcIndexColumns[sheetId].getLockMe(col);
|
||
};
|
||
CCollaborativeEditing.prototype.getLockMeRow = function (sheetId, row) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId))
|
||
return row;
|
||
return this.m_oRecalcIndexRows[sheetId].getLockMe(row);
|
||
};
|
||
// Только когда от других пользователей изменения колонок (для пересчета)
|
||
CCollaborativeEditing.prototype.getLockMeColumn2 = function (sheetId, col) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId))
|
||
return col;
|
||
return this.m_oRecalcIndexColumns[sheetId].getLockMe2(col);
|
||
};
|
||
// Только когда от других пользователей изменения строк (для пересчета)
|
||
CCollaborativeEditing.prototype.getLockMeRow2 = function (sheetId, row) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId))
|
||
return row;
|
||
return this.m_oRecalcIndexRows[sheetId].getLockMe2(row);
|
||
};
|
||
// Только для принятия изменений от других пользователей! (для пересчета только в сохранении)
|
||
CCollaborativeEditing.prototype.getLockOtherColumn2 = function (sheetId, col) {
|
||
if (!this.m_oRecalcIndexColumns.hasOwnProperty(sheetId))
|
||
return col;
|
||
return this.m_oRecalcIndexColumns[sheetId].getLockSaveOther(col);
|
||
};
|
||
// Только для принятия изменений от других пользователей! (для пересчета только в сохранении)
|
||
CCollaborativeEditing.prototype.getLockOtherRow2 = function (sheetId, row) {
|
||
if (!this.m_oRecalcIndexRows.hasOwnProperty(sheetId))
|
||
return row;
|
||
return this.m_oRecalcIndexRows[sheetId].getLockSaveOther(row);
|
||
};
|
||
CCollaborativeEditing.prototype.checkObjectsLock = function (aObjectId, callback) {
|
||
var oApi = Asc.editor;
|
||
var bCanNotEdit = this.getGlobalLock() || oApi && !oApi.canEdit();
|
||
if (bCanNotEdit) {
|
||
if (callback) {
|
||
callback(false, true);
|
||
}
|
||
return false;
|
||
}
|
||
if (oApi) {
|
||
oApi.incrementCounterLongAction();
|
||
}
|
||
const oInkDrawerState = oApi.inkDrawer.getState();
|
||
var callbackEx = function (result, sync) {
|
||
if (oApi) {
|
||
oApi.decrementCounterLongAction();
|
||
}
|
||
if (callback) {
|
||
oApi.inkDrawer.restoreState(oInkDrawerState);
|
||
callback(result, sync);
|
||
oApi.inkDrawer.restoreState(oInkDrawerState);
|
||
}
|
||
};
|
||
var bRet = true;
|
||
if (!aObjectId.length) {
|
||
asc_applyFunction(callbackEx, true, true);
|
||
return bRet;
|
||
}
|
||
this.onStartCheckLock();
|
||
for (var i = 0; i < aObjectId.length; i++) {
|
||
var lockInfo = this.getLockInfo(AscCommonExcel.c_oAscLockTypeElem.Object, null, "", aObjectId[i]);
|
||
if (false === this.getCollaborativeEditing()) {
|
||
asc_applyFunction(callbackEx, true, true);
|
||
callbackEx = undefined;
|
||
}
|
||
if (false !== this.getLockIntersection(lockInfo, c_oAscLockTypes.kLockTypeMine, false)) {
|
||
continue;
|
||
} else if (false !== this.getLockIntersection(lockInfo, c_oAscLockTypes.kLockTypeOther, false)) {
|
||
asc_applyFunction(callbackEx, false);
|
||
return false;
|
||
}
|
||
this.addCheckLock(lockInfo);
|
||
}
|
||
this.onEndCheckLock(callbackEx);
|
||
return bRet;
|
||
};
|
||
CCollaborativeEditing.prototype.Add_ForeignCursor = function (UserId, DocumentPos, UserShortId) {
|
||
var isEqual = function (val1, val2) {
|
||
var res = false;
|
||
if (val1.isEdit === val2.isEdit && val1.sheetId === val2.sheetId) {
|
||
if (val1.ranges.length === val2.ranges.length) {
|
||
res = true;
|
||
for (var i = 0; i < val1.ranges.length; i++) {
|
||
if (!val1.ranges[i].isEqual(val2.ranges[i])) {
|
||
res = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
|
||
if (this.m_aForeignCursorsData[UserId] && isEqual(this.m_aForeignCursorsData[UserId], DocumentPos)) {
|
||
return false;
|
||
}
|
||
|
||
if (DocumentPos) {
|
||
DocumentPos.shortId = UserShortId;
|
||
}
|
||
this.m_aForeignCursorsData[UserId] = DocumentPos;
|
||
|
||
return true;
|
||
};
|
||
CCollaborativeEditing.prototype.Remove_ForeignCursor = function (UserId) {
|
||
delete this.m_aForeignCursorsData[UserId];
|
||
};
|
||
CCollaborativeEditing.prototype.Remove_AllForeignCursors = function () {
|
||
this.handlers.trigger("cleanSelection");
|
||
for (var UserId in this.m_aForeignCursorsData) {
|
||
this.Remove_ForeignCursor(UserId);
|
||
}
|
||
this.handlers.trigger("drawSelection");
|
||
};
|
||
CCollaborativeEditing.prototype.getForeignSelectIntersection = function (col, row) {
|
||
var res = null;
|
||
for (var i in this.m_aForeignCursorsData) {
|
||
if (this.m_aForeignCursorsData[i]) {
|
||
for (var j = 0; j < this.m_aForeignCursorsData[i].ranges.length; j++) {
|
||
if (this.m_aForeignCursorsData[i].ranges[j].contains(col, row)) {
|
||
res = this.m_aForeignCursorsData[i];
|
||
res.userId = i;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
CCollaborativeEditing.prototype.PreUndo = function () {
|
||
let res = AscCommon.CCollaborativeEditingBase.prototype.PreUndo.apply(this);
|
||
|
||
this.oRedoObjectParam = new AscCommonExcel.RedoObjectParam();
|
||
AscCommon.History.UndoRedoPrepare(this.oRedoObjectParam, false, true);
|
||
//todo встроить в GetReverseOwnChanges
|
||
if (this.CoHistory.OwnRanges.length > 0) {
|
||
let range = this.CoHistory.OwnRanges[this.CoHistory.OwnRanges.length - 1];
|
||
let change = this.CoHistory.Changes[range.Position];
|
||
if (change && change.oData && change.oData.snapshot) {
|
||
this.oRedoObjectParam.snapshot = change.oData.snapshot
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
CCollaborativeEditing.prototype.PostUndo = function (state, changes) {
|
||
let Point = {Items: []}
|
||
if (changes.length > 0) {
|
||
//изменение не последнее потому что могут добавиться при корректировке
|
||
let elem = changes.find(function(elem){
|
||
if(elem && elem.oData && elem.oData.Point) {
|
||
return true;
|
||
}
|
||
});
|
||
if (elem) {
|
||
Point = elem.oData.Point;
|
||
}
|
||
}
|
||
//todo Apply_LinkData inside UndoRedoEnd
|
||
AscCommon.CollaborativeEditing.Apply_LinkData();
|
||
AscCommon.History.UndoRedoEnd(Point, this.oRedoObjectParam, false);
|
||
|
||
AscCommon.CCollaborativeEditingBase.prototype.PostUndo.apply(this, arguments);
|
||
}
|
||
|
||
AscCommon.CCollaborativeHistory.prototype.CommuteRelated = function(oClass, oChange, nStartPosition)
|
||
{
|
||
//todo снаследоваться потому что планируется обьедениение sdk
|
||
var arrChangesForProceed = this.Changes;
|
||
for (var nIndex = nStartPosition, nOverallCount = arrChangesForProceed.length; nIndex < nOverallCount; ++nIndex) {
|
||
var oOtherAction = arrChangesForProceed[nIndex];
|
||
if (!oOtherAction) {
|
||
continue;
|
||
}
|
||
if (true !== oOtherAction.IsReverted() && oChange.CommuteRelated && false === oChange.CommuteRelated(oChange, oOtherAction)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
|
||
AscCommon.CCollaborativeHistory.prototype.saveChanges = function(changesToSend)
|
||
{
|
||
this.CoEditing.sendChanges(false, true, changesToSend);
|
||
};
|
||
|
||
/**
|
||
* Отвечает за лок в совместном редактировании
|
||
* -----------------------------------------------------------------------------
|
||
*
|
||
* @constructor
|
||
* @memberOf Asc
|
||
*/
|
||
function CLock(element) {
|
||
this.Type = c_oAscLockTypes.kLockTypeNone;
|
||
this.UserId = null;
|
||
this.Element = element;
|
||
|
||
this.init();
|
||
|
||
return this;
|
||
}
|
||
|
||
CLock.prototype.init = function () {
|
||
};
|
||
CLock.prototype.getType = function () {
|
||
return this.Type;
|
||
};
|
||
CLock.prototype.setType = function (newType) {
|
||
if (newType === c_oAscLockTypes.kLockTypeNone)
|
||
this.UserId = null;
|
||
|
||
this.Type = newType;
|
||
};
|
||
|
||
CLock.prototype.Lock = function (bMine) {
|
||
if (c_oAscLockTypes.kLockTypeNone === this.Type) {
|
||
if (true === bMine)
|
||
this.Type = c_oAscLockTypes.kLockTypeMine;
|
||
else
|
||
this.Type = c_oAscLockTypes.kLockTypeOther;
|
||
}
|
||
};
|
||
|
||
CLock.prototype.setUserId = function (UserId) {
|
||
this.UserId = UserId;
|
||
};
|
||
|
||
function CRecalcIndexElement(recalcType, position, bIsSaveIndex) {
|
||
if (!(this instanceof CRecalcIndexElement)) {
|
||
return new CRecalcIndexElement(recalcType, position, bIsSaveIndex);
|
||
}
|
||
|
||
this._recalcType = recalcType; // Тип изменений (удаление или добавление)
|
||
this._position = position; // Позиция, в которой произошли изменения
|
||
this._count = 1; // Считаем все изменения за простейшие
|
||
this.m_bIsSaveIndex = !!bIsSaveIndex; // Это индексы из изменений других пользователей (которые мы еще не применили)
|
||
|
||
return this;
|
||
}
|
||
|
||
// Пересчет для других
|
||
CRecalcIndexElement.prototype.getLockOther = function (position, type) {
|
||
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? +1 : -1;
|
||
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType &&
|
||
true === this.m_bIsSaveIndex) {
|
||
// Мы еще не применили чужие изменения (поэтому для insert не нужно отрисовывать)
|
||
// RecalcIndexRemove (потому что перевертываем для правильной отработки, от другого пользователя
|
||
// пришло RecalcIndexAdd
|
||
return null;
|
||
} else if (position === this._position &&
|
||
c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType &&
|
||
c_oAscLockTypes.kLockTypeMine === type && false === this.m_bIsSaveIndex) {
|
||
// Для пользователя, который удалил столбец, рисовать залоченные ранее в данном столбце ячейки
|
||
// не нужно
|
||
return null;
|
||
} else if (position < this._position)
|
||
return position;
|
||
else
|
||
return (position + inc);
|
||
};
|
||
// Пересчет для других (только для сохранения)
|
||
CRecalcIndexElement.prototype.getLockSaveOther = function (position, type) {
|
||
if (this.m_bIsSaveIndex)
|
||
return position;
|
||
|
||
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? +1 : -1;
|
||
if (position === this._position && c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType &&
|
||
true === this.m_bIsSaveIndex) {
|
||
// Мы еще не применили чужие изменения (поэтому для insert не нужно отрисовывать)
|
||
// RecalcIndexRemove (потому что перевертываем для правильной отработки, от другого пользователя
|
||
// пришло RecalcIndexAdd
|
||
return null;
|
||
} else if (position === this._position &&
|
||
c_oAscRecalcIndexTypes.RecalcIndexRemove === this._recalcType &&
|
||
c_oAscLockTypes.kLockTypeMine === type && false === this.m_bIsSaveIndex) {
|
||
// Для пользователя, который удалил столбец, рисовать залоченные ранее в данном столбце ячейки
|
||
// не нужно
|
||
return null;
|
||
} else if (position < this._position)
|
||
return position;
|
||
else
|
||
return (position + inc);
|
||
};
|
||
// Пересчет для себя
|
||
CRecalcIndexElement.prototype.getLockMe = function (position) {
|
||
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? -1 : +1;
|
||
if (position < this._position)
|
||
return position;
|
||
else
|
||
return (position + inc);
|
||
};
|
||
// Только когда от других пользователей изменения (для пересчета)
|
||
CRecalcIndexElement.prototype.getLockMe2 = function (position) {
|
||
var inc = (c_oAscRecalcIndexTypes.RecalcIndexAdd === this._recalcType) ? -1 : +1;
|
||
if (true !== this.m_bIsSaveIndex || position < this._position)
|
||
return position;
|
||
else
|
||
return (position + inc);
|
||
};
|
||
|
||
function CRecalcIndex() {
|
||
if (!(this instanceof CRecalcIndex)) {
|
||
return new CRecalcIndex();
|
||
}
|
||
|
||
this._arrElements = []; // Массив CRecalcIndexElement
|
||
|
||
return this;
|
||
}
|
||
|
||
CRecalcIndex.prototype.add = function (recalcType, position, count, bIsSaveIndex) {
|
||
for (var i = 0; i < count; ++i)
|
||
this._arrElements.push(new CRecalcIndexElement(recalcType, position, bIsSaveIndex));
|
||
};
|
||
// Удаляет из пересчета, для undo
|
||
CRecalcIndex.prototype.remove = function (count) {
|
||
for (var i = 0; i < count; ++i)
|
||
this._arrElements.pop();
|
||
};
|
||
CRecalcIndex.prototype.clear = function () {
|
||
this._arrElements.length = 0;
|
||
};
|
||
|
||
// Пересчет для других
|
||
CRecalcIndex.prototype.getLockOther = function (position, type) {
|
||
var newPosition = position;
|
||
/*var count = this._arrElements.length;
|
||
for (var i = 0; i < count; ++i) {
|
||
newPosition = this._arrElements[i].getLockOther(newPosition, type);
|
||
if (null === newPosition)
|
||
break;
|
||
}*/
|
||
|
||
var count = this._arrElements.length;
|
||
if (0 >= count)
|
||
return newPosition;
|
||
// Для пересчета, когда добавил сам - обратный порядок
|
||
// Для пересчета, когда добавил кто-то другой - прямой
|
||
var bIsDirect = !this._arrElements[0].m_bIsSaveIndex;
|
||
var i;
|
||
if (bIsDirect) {
|
||
for (i = 0; i < count; ++i) {
|
||
newPosition = this._arrElements[i].getLockOther(newPosition, type);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
} else {
|
||
for (i = count - 1; i >= 0; --i) {
|
||
newPosition = this._arrElements[i].getLockOther(newPosition, type);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
}
|
||
|
||
return newPosition;
|
||
};
|
||
// Пересчет для других (только для сохранения)
|
||
CRecalcIndex.prototype.getLockSaveOther = function (position, type) {
|
||
var newPosition = position;
|
||
var count = this._arrElements.length;
|
||
for (var i = 0; i < count; ++i) {
|
||
newPosition = this._arrElements[i].getLockSaveOther(newPosition, type);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
|
||
return newPosition;
|
||
};
|
||
// Пересчет для себя
|
||
CRecalcIndex.prototype.getLockMe = function (position) {
|
||
var newPosition = position;
|
||
var count = this._arrElements.length;
|
||
if (0 >= count)
|
||
return newPosition;
|
||
// Для пересчета, когда добавил сам - обратный порядок
|
||
// Для пересчета, когда добавил кто-то другой - прямой
|
||
var bIsDirect = this._arrElements[0].m_bIsSaveIndex;
|
||
var i;
|
||
if (bIsDirect) {
|
||
for (i = 0; i < count; ++i) {
|
||
newPosition = this._arrElements[i].getLockMe(newPosition);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
} else {
|
||
for (i = count - 1; i >= 0; --i) {
|
||
newPosition = this._arrElements[i].getLockMe(newPosition);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
}
|
||
|
||
return newPosition;
|
||
};
|
||
// Только когда от других пользователей изменения (для пересчета)
|
||
CRecalcIndex.prototype.getLockMe2 = function (position) {
|
||
var newPosition = position;
|
||
var count = this._arrElements.length;
|
||
if (0 >= count)
|
||
return newPosition;
|
||
// Для пересчета, когда добавил сам - обратный порядок
|
||
// Для пересчета, когда добавил кто-то другой - прямой
|
||
var bIsDirect = this._arrElements[0].m_bIsSaveIndex;
|
||
var i;
|
||
if (bIsDirect) {
|
||
for (i = 0; i < count; ++i) {
|
||
newPosition = this._arrElements[i].getLockMe2(newPosition);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
} else {
|
||
for (i = count - 1; i >= 0; --i) {
|
||
newPosition = this._arrElements[i].getLockMe2(newPosition);
|
||
if (null === newPosition)
|
||
break;
|
||
}
|
||
}
|
||
|
||
return newPosition;
|
||
};
|
||
|
||
//----------------------------------------------------------export----------------------------------------------------
|
||
window['Asc'] = window['Asc'] || {};
|
||
window['AscCommonExcel'] = window['AscCommonExcel'] || {};
|
||
window['AscCommonExcel'].CLock = CLock;
|
||
|
||
window['AscCommonExcel'].CCollaborativeEditing = CCollaborativeEditing;
|
||
window['Asc'].CRecalcIndexElement = CRecalcIndexElement;
|
||
window['Asc'].CRecalcIndex = CRecalcIndex;
|
||
}
|
||
)(window);
|