mirror of
https://github.com/ONLYOFFICE/sdkjs.git
synced 2026-04-07 14:09:12 +08:00
867 lines
31 KiB
JavaScript
867 lines
31 KiB
JavaScript
(function (global) {
|
||
'use strict';
|
||
|
||
var asc = window["Asc"];
|
||
var asc_user = asc.asc_CUser;
|
||
|
||
// Класс надстройка, для online и offline работы
|
||
var CDocsCoApi = function (options) {
|
||
this._CoAuthoringApi = new DocsCoApi();
|
||
this._onlineWork = false;
|
||
|
||
if (options)
|
||
{
|
||
this.onAuthParticipantsChanged = options.onAuthParticipantsChanged;
|
||
this.onParticipantsChanged = options.onParticipantsChanged;
|
||
this.onMessage = options.onMessage;
|
||
this.onLocksAcquired = options.onLocksAcquired;
|
||
this.onLocksReleased = options.onLocksReleased;
|
||
this.onDisconnect = options.onDisconnect;
|
||
this.onFirstLoadChanges = options.onFirstLoadChanges;
|
||
this.onConnectionStateChanged = options.onConnectionStateChanged;
|
||
this.onUserStateChanged = options.onUserStateChanged;
|
||
this.onSetIndexUser = options.onSetIndexUser;
|
||
this.onSaveChanges = options.onSaveChanges;
|
||
this.onStartCoAuthoring = options.onStartCoAuthoring;
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.init = function (user, docid, isviewermode, token, serverHost, serverPath, callback, isExcel) {
|
||
if (this._CoAuthoringApi && this._CoAuthoringApi.isRightURL()) {
|
||
var t = this;
|
||
this._CoAuthoringApi.onAuthParticipantsChanged = function (e) {t.callback_OnAuthParticipantsChanged(e);};
|
||
this._CoAuthoringApi.onParticipantsChanged = function (e) {t.callback_OnParticipantsChanged(e);};
|
||
this._CoAuthoringApi.onMessage = function (e) {t.callback_OnMessage(e);};
|
||
this._CoAuthoringApi.onLocksAcquired = function (e) {t.callback_OnLocksAcquired(e);};
|
||
this._CoAuthoringApi.onLocksReleased = function (e, bChanges) {t.callback_OnLocksReleased(e, bChanges);};
|
||
this._CoAuthoringApi.onDisconnect = function (e, isDisconnectAtAll, isCloseCoAuthoring) {t.callback_OnDisconnect(e, isDisconnectAtAll, isCloseCoAuthoring);};
|
||
this._CoAuthoringApi.onFirstLoadChanges = function (e) {t.callback_OnFirstLoadChanges(e);};
|
||
this._CoAuthoringApi.onConnectionStateChanged = function (e) {t.callback_OnConnectionStateChanged(e);};
|
||
this._CoAuthoringApi.onUserStateChanged = function (e) {t.callback_OnUserStateChanged(e);};
|
||
this._CoAuthoringApi.onSetIndexUser = function (e) {t.callback_OnSetIndexUser(e);};
|
||
this._CoAuthoringApi.onSaveChanges = function (e) {t.callback_OnSaveChanges(e);};
|
||
// Callback есть пользователей больше 1
|
||
this._CoAuthoringApi.onStartCoAuthoring = function (e) {t.callback_OnStartCoAuthoring(e);};
|
||
|
||
this._CoAuthoringApi.init(user, docid, isviewermode, token, serverHost, serverPath, callback, isExcel);
|
||
this._onlineWork = true;
|
||
}
|
||
else {
|
||
// Фиктивные вызовы
|
||
this.callback_OnSetIndexUser ("123");
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.set_url = function (url) {
|
||
if (this._CoAuthoringApi)
|
||
this._CoAuthoringApi.set_url(url);
|
||
};
|
||
|
||
CDocsCoApi.prototype.get_state = function () {
|
||
if (this._CoAuthoringApi)
|
||
return this._CoAuthoringApi.get_state();
|
||
|
||
return 0;
|
||
};
|
||
|
||
CDocsCoApi.prototype.getMessages = function () {
|
||
if (this._CoAuthoringApi && this._onlineWork)
|
||
this._CoAuthoringApi.getMessages();
|
||
};
|
||
|
||
CDocsCoApi.prototype.sendMessage = function (message) {
|
||
if (this._CoAuthoringApi && this._onlineWork)
|
||
this._CoAuthoringApi.sendMessage(message);
|
||
};
|
||
|
||
CDocsCoApi.prototype.askLock = function (arrayBlockId, callback) {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.askLock(arrayBlockId, callback);
|
||
}
|
||
else {
|
||
var t = this;
|
||
window.setTimeout(function () {
|
||
if (callback && _.isFunction(callback)) {
|
||
var lengthArray = (arrayBlockId) ? arrayBlockId.length : 0;
|
||
if (0 < lengthArray) {
|
||
callback({"lock": arrayBlockId[0]});
|
||
// Фиктивные вызовы
|
||
for (var i = 0; i < lengthArray; ++i) {
|
||
t.callback_OnLocksAcquired ({"state" : 2, "block": arrayBlockId[i]});
|
||
}
|
||
}
|
||
}
|
||
}, 1);
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.askSaveChanges = function (callback) {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.askSaveChanges(callback);
|
||
} else {
|
||
window.setTimeout(function () {
|
||
if (callback && _.isFunction(callback)) {
|
||
// Фиктивные вызовы
|
||
callback({"savelock": false});
|
||
}
|
||
}, 100);
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.unSaveChanges = function () {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.unSaveChanges();
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.saveChanges = function (arrayChanges) {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.saveChanges(arrayChanges);
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.getUsers = function () {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.getUsers();
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.releaseLocks = function (blockId) {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.releaseLocks(blockId);
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.disconnect = function () {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.disconnect();
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.set_isViewerMode = function (isViewerMode) {
|
||
if (this._CoAuthoringApi && this._onlineWork) {
|
||
this._CoAuthoringApi.set_isViewerMode(isViewerMode);
|
||
}
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnAuthParticipantsChanged = function (e) {
|
||
if (this.onAuthParticipantsChanged)
|
||
return this.onAuthParticipantsChanged(e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnParticipantsChanged = function (e) {
|
||
if (this.onParticipantsChanged)
|
||
return this.onParticipantsChanged (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnMessage = function (e) {
|
||
if (this.onMessage)
|
||
return this.onMessage (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnLocksAcquired = function (e) {
|
||
if (this.onLocksAcquired)
|
||
return this.onLocksAcquired (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnLocksReleased = function (e, bChanges) {
|
||
if (this.onLocksReleased)
|
||
return this.onLocksReleased (e, bChanges);
|
||
};
|
||
|
||
/**
|
||
* Event об отсоединении от сервера
|
||
* @param {jQuery} e event об отсоединении с причиной
|
||
* @param {Bool} isDisconnectAtAll окончательно ли отсоединяемся(true) или будем пробовать сделать reconnect(false) + сами отключились
|
||
* @param {Bool} isCloseCoAuthoring
|
||
*/
|
||
CDocsCoApi.prototype.callback_OnDisconnect = function (e, isDisconnectAtAll, isCloseCoAuthoring) {
|
||
if (this.onDisconnect)
|
||
return this.onDisconnect (e, isDisconnectAtAll, isCloseCoAuthoring);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnFirstLoadChanges = function (e) {
|
||
if (this.onFirstLoadChanges)
|
||
return this.onFirstLoadChanges (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnConnectionStateChanged = function (e) {
|
||
if (this.onConnectionStateChanged)
|
||
return this.onConnectionStateChanged (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnUserStateChanged = function (e) {
|
||
if (this.onUserStateChanged)
|
||
return this.onUserStateChanged (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnSetIndexUser = function (e) {
|
||
if (this.onSetIndexUser)
|
||
return this.onSetIndexUser (e);
|
||
};
|
||
|
||
CDocsCoApi.prototype.callback_OnSaveChanges = function (e) {
|
||
if (this.onSaveChanges)
|
||
return this.onSaveChanges (e);
|
||
};
|
||
CDocsCoApi.prototype.callback_OnStartCoAuthoring = function (e) {
|
||
if (this.onStartCoAuthoring)
|
||
return this.onStartCoAuthoring (e);
|
||
};
|
||
|
||
/** States
|
||
* -1 - reconnect state
|
||
* 0 - not initialized
|
||
* 1 - waiting session id
|
||
* 2 - authorized
|
||
* 3 - closed
|
||
*/
|
||
var DocsCoApi = function (options) {
|
||
if (options)
|
||
{
|
||
this.onAuthParticipantsChanged = options.onAuthParticipantsChanged;
|
||
this.onParticipantsChanged = options.onParticipantsChanged;
|
||
this.onMessage = options.onMessage;
|
||
this.onLocksAcquired = options.onLocksAcquired;
|
||
this.onLocksReleased = options.onLocksReleased;
|
||
this.onRelockFailed = options.onRelockFailed;
|
||
this.onDisconnect = options.onDisconnect;
|
||
this.onConnect = options.onConnect;
|
||
this.onFirstLoadChanges = options.onFirstLoadChanges;
|
||
this.onConnectionStateChanged = options.onConnectionStateChanged;
|
||
this.onUserStateChanged = options.onUserStateChanged;
|
||
}
|
||
this._state = 0;
|
||
this._participants = [];
|
||
this._user = "Anonymous";
|
||
this._locks = {};
|
||
this._msgBuffer = [];
|
||
this._lockCallbacks = {};
|
||
this._saveLock = false;
|
||
this._saveCallback = [];
|
||
this._id = "";
|
||
this._indexuser = -1;
|
||
// Если пользователей больше 1, то совместно редактируем
|
||
this.isCoAuthoring = false;
|
||
// Мы сами отключились от совместного редактирования
|
||
this.isCloseCoAuthoring = false;
|
||
|
||
// Максимальное число изменений, посылаемое на сервер (не может быть нечетным, т.к. пересчет обоих индексов должен быть)
|
||
this.maxCountSaveChanges = 20000;
|
||
// Текущий индекс для колличества изменений
|
||
this.currentIndex = 0;
|
||
// Массив изменений
|
||
this.arrayChanges = null;
|
||
|
||
this._url = "";
|
||
};
|
||
|
||
DocsCoApi.prototype.isRightURL = function () {
|
||
return ("" != this._url);
|
||
};
|
||
|
||
DocsCoApi.prototype.set_url = function (url) {
|
||
this._url = url;
|
||
};
|
||
|
||
DocsCoApi.prototype.get_state = function () {
|
||
return this._state;
|
||
};
|
||
|
||
DocsCoApi.prototype.get_indexUser = function () {
|
||
return this._indexuser;
|
||
};
|
||
|
||
DocsCoApi.prototype.getSessionId = function () {
|
||
return this._id;
|
||
};
|
||
// ToDo убрать getParticipants
|
||
DocsCoApi.prototype.getParticipants = function () {
|
||
return this._participants;
|
||
};
|
||
|
||
DocsCoApi.prototype.getUser = function () {
|
||
return this._user;
|
||
};
|
||
|
||
DocsCoApi.prototype.getLocks = function () {
|
||
return this._locks;
|
||
};
|
||
|
||
DocsCoApi.prototype.askLock = function (arrayBlockId, callback) {
|
||
// ask all elements in array
|
||
var i = 0;
|
||
var lengthArray = (arrayBlockId) ? arrayBlockId.length : 0;
|
||
var isLock = false;
|
||
var idLockInArray = null;
|
||
for (; i < lengthArray; ++i) {
|
||
idLockInArray = (this._isExcel) ? arrayBlockId[i].guid : arrayBlockId[i];
|
||
if (this._locks[idLockInArray] && 0 !== this._locks[idLockInArray].state) {
|
||
isLock = true;
|
||
break;
|
||
}
|
||
}
|
||
if (0 === lengthArray)
|
||
isLock = true;
|
||
|
||
idLockInArray = (this._isExcel) ? arrayBlockId[0].guid : arrayBlockId[0];
|
||
|
||
if (!isLock) {
|
||
//Ask
|
||
this._locks[idLockInArray] = {"state": 1};//1-asked for block
|
||
if (callback && _.isFunction(callback)) {
|
||
this._lockCallbacks[idLockInArray] = callback;
|
||
var lockCalbacks = this._lockCallbacks;
|
||
|
||
//Set reconnectTimeout
|
||
window.setTimeout(function () {
|
||
if (lockCalbacks.hasOwnProperty(idLockInArray)) {
|
||
//Not signaled already
|
||
callback({error: "Timed out"});
|
||
delete lockCalbacks[idLockInArray];
|
||
}
|
||
}, 5000);//5 sec to signal lock failure
|
||
}
|
||
if (this._isExcel)
|
||
this._send({"type": "getlockrange", "block": arrayBlockId});
|
||
else
|
||
this._send({"type": "getlock", "block": arrayBlockId});
|
||
} else {
|
||
// Вернем ошибку, т.к. залочены элементы
|
||
window.setTimeout(function () {
|
||
if (callback && _.isFunction(callback)) {
|
||
callback({error: idLockInArray + "-lock"});
|
||
}
|
||
}, 100);
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype.askSaveChanges = function (callback) {
|
||
if (this._saveCallback[this._saveCallback.length - 1]) {
|
||
// Мы еще не отработали старый callback и ждем ответа
|
||
return;
|
||
}
|
||
// Проверим состояние, если мы не подсоединились, то сразу отправим ошибку
|
||
if (-1 === this.get_state()) {
|
||
window.setTimeout(function () {
|
||
if (callback && _.isFunction(callback)) {
|
||
// Фиктивные вызовы
|
||
callback({error: "No connection"});
|
||
}
|
||
}, 100);
|
||
return;
|
||
}
|
||
if (callback && _.isFunction(callback)) {
|
||
var t = this;
|
||
var indexCallback = this._saveCallback.length;
|
||
this._saveCallback[indexCallback] = callback;
|
||
|
||
//Set reconnectTimeout
|
||
window.setTimeout(function () {
|
||
if (t._saveCallback[indexCallback]) {
|
||
//Not signaled already
|
||
t._saveCallback[indexCallback]({error: "Timed out"});
|
||
t._saveCallback[indexCallback] = null;
|
||
}
|
||
}, 5000);//5 sec to signal lock failure
|
||
}
|
||
this._send({"type": "issavelock"});
|
||
};
|
||
|
||
DocsCoApi.prototype.unSaveChanges = function () {
|
||
this._send({"type": "unsavelock"});
|
||
};
|
||
|
||
DocsCoApi.prototype.releaseLocks = function (blockId) {
|
||
if (this._locks[blockId] && 2 === this._locks[blockId].state /*lock is ours*/) {
|
||
//Ask
|
||
this._locks[blockId] = {"state": 0};//0-released
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype.saveChanges = function (arrayChanges, currentIndex) {
|
||
if (undefined === currentIndex) {
|
||
this.currentIndex = 0;
|
||
this.arrayChanges = arrayChanges;
|
||
} else {
|
||
this.currentIndex = currentIndex;
|
||
}
|
||
var startIndex = this.currentIndex * this.maxCountSaveChanges;
|
||
var endIndex = Math.min(this.maxCountSaveChanges * (this.currentIndex + 1), arrayChanges.length);
|
||
if (endIndex === arrayChanges.length) {
|
||
for (var key in this._locks) {
|
||
if (2 === this._locks[key].state /*lock is ours*/)
|
||
delete this._locks[key];
|
||
}
|
||
}
|
||
|
||
this._send({"type": "savechanges", "changes": JSON.stringify(arrayChanges.slice(startIndex, endIndex)),
|
||
"endSaveChanges": (endIndex == arrayChanges.length), "isExcel": this._isExcel});
|
||
};
|
||
|
||
DocsCoApi.prototype.getUsers = function () {
|
||
this._send({"type": "getusers"});
|
||
};
|
||
|
||
DocsCoApi.prototype.disconnect = function () {
|
||
// Отключаемся сами
|
||
this.isCloseCoAuthoring = true;
|
||
return this.sockjs.close();
|
||
};
|
||
|
||
DocsCoApi.prototype.set_isViewerMode = function (isViewerMode) {
|
||
// Выставляем режим редактирования
|
||
isViewerMode = !!isViewerMode;
|
||
if (this._isviewermode != isViewerMode) {
|
||
this._isviewermode = isViewerMode;
|
||
this._send({"type": "setisviewermode", "isviewermode": this._isviewermode});
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype.getMessages = function () {
|
||
this._send({"type": "getmessages"});
|
||
};
|
||
|
||
DocsCoApi.prototype.sendMessage = function (message) {
|
||
if (typeof message === 'string') {
|
||
this._send({"type": "message", "message": message});
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._sendPrebuffered = function () {
|
||
for (var i = 0; i < this._msgBuffer.length; i++) {
|
||
this._send(this._msgBuffer[i]);
|
||
}
|
||
this._msgBuffer = [];
|
||
};
|
||
|
||
DocsCoApi.prototype._send = function (data) {
|
||
if (data !== null && typeof data === "object") {
|
||
if (this._state > 0) {
|
||
this.sockjs.send(JSON.stringify(data));
|
||
}
|
||
else {
|
||
this._msgBuffer.push(data);
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onMessages = function (data) {
|
||
if (data["messages"] && this.onMessage) {
|
||
this.onMessage(data["messages"]);
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onGetLock = function (data) {
|
||
if (data["locks"]) {
|
||
for (var key in data["locks"]) {
|
||
if (data["locks"].hasOwnProperty(key)) {
|
||
var lock = data["locks"][key], blockTmp = (this._isExcel) ? lock["block"]["guid"] : key, blockValue = (this._isExcel) ? lock["block"] : key;
|
||
if (lock !== null) {
|
||
var changed = true;
|
||
if (this._locks[blockTmp] && 1 !== this._locks[blockTmp].state /*asked for it*/) {
|
||
//Exists
|
||
//Check lock state
|
||
changed = !(this._locks[blockTmp].state === (lock["sessionId"] === this._id ? 2 : 3) &&
|
||
this._locks[blockTmp]["user"] === lock["user"] &&
|
||
this._locks[blockTmp]["time"] === lock["time"] &&
|
||
this._locks[blockTmp]["block"] === blockTmp);
|
||
}
|
||
|
||
if (changed) {
|
||
this._locks[blockTmp] = {"state":lock["sessionId"] === this._id ? 2 : 3, "user":lock["user"], "time":lock["time"], "block": blockTmp, "blockValue": blockValue};//2-acquired by me!
|
||
}
|
||
if (this._lockCallbacks.hasOwnProperty(blockTmp) &&
|
||
this._lockCallbacks[blockTmp] !== null &&
|
||
_.isFunction(this._lockCallbacks[blockTmp])) {
|
||
if (lock["sessionId"] === this._id) {
|
||
//Do call back
|
||
this._lockCallbacks[blockTmp]({"lock":this._locks[blockTmp]});
|
||
}
|
||
else {
|
||
this._lockCallbacks[blockTmp]({"error":"Already locked by " + lock["user"]});
|
||
}
|
||
delete this._lockCallbacks[blockTmp];
|
||
}
|
||
if (this.onLocksAcquired && changed) {
|
||
this.onLocksAcquired(this._locks[blockTmp]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onReleaseLock = function (data) {
|
||
if (data["locks"]) {
|
||
for (var block in data["locks"]) {
|
||
if (data["locks"].hasOwnProperty(block)) {
|
||
var lock = data["locks"][block];
|
||
if (lock !== null) {
|
||
this._locks[lock["block"]] = {"state":0, "user":lock["user"], "time":lock["time"], "changes":lock["changes"], "block":lock["block"]};
|
||
if (this.onLocksReleased) {
|
||
// false - user not save changes
|
||
this.onLocksReleased(this._locks[lock["block"]], false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onSaveChanges = function (data) {
|
||
if (data["locks"]) {
|
||
for (var block in data["locks"]) {
|
||
if (data["locks"].hasOwnProperty(block)) {
|
||
var lock = data["locks"][block];
|
||
if (lock !== null) {
|
||
this._locks[lock["block"]] = {"state":0, "user":lock["user"], "time":lock["time"], "changes":lock["changes"], "block":lock["block"]};
|
||
if (this.onLocksReleased) {
|
||
// true - lock with save
|
||
this.onLocksReleased(this._locks[lock["block"]], true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (data["changes"]) {
|
||
if (this.onSaveChanges) {
|
||
this.onSaveChanges(JSON.parse(data["changes"]));
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onStartCoAuthoring = function (isStartEvent) {
|
||
if (false === this.isCoAuthoring) {
|
||
this.isCoAuthoring = true;
|
||
if (this.onStartCoAuthoring) {
|
||
this.onStartCoAuthoring(isStartEvent);
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onSaveLock = function (data) {
|
||
if (undefined != data["savelock"] && null != data["savelock"]) {
|
||
var indexCallback = this._saveCallback.length - 1;
|
||
if (this._saveCallback[indexCallback]) {
|
||
this._saveCallback[indexCallback] (data);
|
||
this._saveCallback[indexCallback] = null;
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onUnSaveLock = function (data) {
|
||
this._saveLock = false;
|
||
if (this.onUnSaveLock)
|
||
this.onUnSaveLock ();
|
||
};
|
||
|
||
DocsCoApi.prototype._onFirstLoadChanges = function (data) {
|
||
var t = this;
|
||
var allServerChanges = data["changes"];
|
||
if (allServerChanges && this.onFirstLoadChanges) {
|
||
var allChanges = [];
|
||
for (var changeId in allServerChanges) {
|
||
var change = allServerChanges[changeId];
|
||
var changesOneUser = change["changes"];
|
||
if (changesOneUser) {
|
||
changesOneUser = JSON.parse(changesOneUser);
|
||
for (var i in changesOneUser)
|
||
allChanges.push(changesOneUser[i]);
|
||
}
|
||
}
|
||
|
||
if (0 < allChanges.length) {
|
||
// Функция может быть долгой (и в IE10 происходит disconnect). Поэтому вызовем через timeout
|
||
window.setTimeout(function () {
|
||
t.onFirstLoadChanges(allChanges);
|
||
}, 10);
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onSetIndexUser = function (data) {
|
||
if (data && this.onSetIndexUser) {
|
||
this.onSetIndexUser (data);
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onSavePartChanges = function () {
|
||
this.saveChanges (this.arrayChanges, this.currentIndex + 1);
|
||
};
|
||
|
||
DocsCoApi.prototype._onPreviousLocks = function (locks, previousLocks) {
|
||
var i=0;
|
||
if (locks && previousLocks) {
|
||
for (var block in locks) {
|
||
if (locks.hasOwnProperty(block)) {
|
||
var lock = locks[block];
|
||
if (lock !== null && lock["block"]) {
|
||
//Find in previous
|
||
for (i=0; i < previousLocks.length; i++) {
|
||
if (previousLocks[i] === lock["block"] && lock["sessionId"] === this._id) {
|
||
//Lock is ours
|
||
previousLocks.remove(i);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (previousLocks.length>0 && this.onRelockFailed) {
|
||
this.onRelockFailed(previousLocks);
|
||
}
|
||
previousLocks=[];
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onParticipantsChanged = function (participants, isStartEvent) {
|
||
this._participants = [];
|
||
if (participants) {
|
||
var tmpUser, isViewerMode, countEditUsers = (!this._isviewermode) ? 1 : 0;
|
||
for (var i = 0; i < participants.length; ++i) {
|
||
isViewerMode = participants[i]["isviewermode"];
|
||
tmpUser = new asc_user ();
|
||
tmpUser.asc_setId (participants[i]["id"]);
|
||
tmpUser.asc_setUserName (participants[i]["username"]);
|
||
tmpUser.asc_setIsViewerMode (isViewerMode);
|
||
this._participants.push (tmpUser);
|
||
// Считаем только число пользователей, которые редактируют
|
||
if (!isViewerMode)
|
||
++countEditUsers;
|
||
}
|
||
|
||
if (isStartEvent) {
|
||
if (this.onAuthParticipantsChanged)
|
||
this.onAuthParticipantsChanged (this._participants);
|
||
}
|
||
else {
|
||
if (this.onParticipantsChanged)
|
||
this.onParticipantsChanged (this._participants);
|
||
}
|
||
|
||
// Посылаем эвент о совместном редактировании
|
||
if (1 < countEditUsers) {
|
||
this._onStartCoAuthoring(isStartEvent);
|
||
}
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onConnectionStateChanged = function (data) {
|
||
var userStateChanged = null;
|
||
if (undefined !== data["state"] && this.onConnectionStateChanged) {
|
||
userStateChanged = new asc_user();
|
||
userStateChanged.asc_setId(data["id"]);
|
||
userStateChanged.asc_setUserName(data["username"]);
|
||
userStateChanged.asc_setState(data["state"]);
|
||
this.onConnectionStateChanged(userStateChanged);
|
||
}
|
||
};
|
||
|
||
DocsCoApi.prototype._onUserStateChanged = function (data) {
|
||
var userStateChanged = null;
|
||
if (undefined != data["isviewermode"] && this.onUserStateChanged) {
|
||
userStateChanged = new asc_user();
|
||
userStateChanged.asc_setId(data["id"]);
|
||
userStateChanged.asc_setUserName(data["username"]);
|
||
userStateChanged.asc_setIsViewerMode(data["isviewermode"]);
|
||
this.onUserStateChanged(userStateChanged);
|
||
}
|
||
};
|
||
|
||
var reconnectTimeout, attemptCount=0;
|
||
|
||
function initSocksJs(url,docsCoApi) {
|
||
var sockjs = new SockJS(url, null, {debug: true});
|
||
|
||
sockjs.onopen = function () {
|
||
if (reconnectTimeout) {
|
||
clearTimeout(reconnectTimeout);
|
||
attemptCount = 0;
|
||
}
|
||
docsCoApi._state = 1; // Opened state
|
||
if (docsCoApi.onConnect) {
|
||
docsCoApi.onConnect();
|
||
}
|
||
if (docsCoApi._locks)
|
||
{
|
||
docsCoApi.ownedLockBlocks = [];
|
||
//If we already have locks
|
||
for (var block in docsCoApi._locks) {
|
||
if (docsCoApi._locks.hasOwnProperty(block)) {
|
||
var lock = docsCoApi._locks[block];
|
||
if (lock["state"] === 2) {
|
||
//Our lock.
|
||
docsCoApi.ownedLockBlocks.push(lock["block"]);
|
||
}
|
||
}
|
||
}
|
||
docsCoApi._locks = {};
|
||
}
|
||
docsCoApi._send(
|
||
{
|
||
"type":"auth",
|
||
"docid":docsCoApi._docid,
|
||
"isviewermode":docsCoApi._isviewermode,
|
||
"token":docsCoApi._token,
|
||
"user":docsCoApi._user.asc_getId(),
|
||
"username":docsCoApi._user.asc_getUserName(),
|
||
"locks":docsCoApi.ownedLockBlocks,
|
||
"sessionId":docsCoApi._id,
|
||
"serverHost": docsCoApi._serverHost,
|
||
"serverPath": docsCoApi._serverPath
|
||
});
|
||
|
||
};
|
||
|
||
sockjs.onmessage = function (e) {
|
||
//TODO: add checks and error handling
|
||
//Get data type
|
||
var dataObject = JSON.parse(e.data);
|
||
var type = dataObject.type;
|
||
docsCoApi.dataHandler[type](dataObject);
|
||
};
|
||
sockjs.onclose = function (evt) {
|
||
docsCoApi._state = -1; // Reconnect state
|
||
var bIsDisconnectAtAll = attemptCount >= 20 || docsCoApi.isCloseCoAuthoring;
|
||
if (bIsDisconnectAtAll)
|
||
docsCoApi._state = 3; // Closed state
|
||
if (docsCoApi.onDisconnect) {
|
||
docsCoApi.onDisconnect(evt.reason, bIsDisconnectAtAll, docsCoApi.isCloseCoAuthoring);
|
||
}
|
||
if (docsCoApi.isCloseCoAuthoring)
|
||
return;
|
||
//Try reconect
|
||
if (attemptCount < 20) {
|
||
tryReconnect();
|
||
}
|
||
};
|
||
|
||
|
||
function tryReconnect() {
|
||
if (reconnectTimeout)
|
||
{
|
||
clearTimeout(reconnectTimeout);
|
||
}
|
||
attemptCount++;
|
||
reconnectTimeout = setTimeout(function(){
|
||
delete docsCoApi.sockjs;
|
||
docsCoApi.sockjs = initSocksJs(url,docsCoApi);
|
||
},500*attemptCount);
|
||
|
||
}
|
||
|
||
return sockjs;
|
||
}
|
||
|
||
|
||
DocsCoApi.prototype.init = function (user, docid, isviewermode, token, serverHost, serverPath, callback, isExcel) {
|
||
this._user = user;
|
||
this._docid = docid;
|
||
this._isviewermode = isviewermode;
|
||
this._token = token;
|
||
this._initCallback = callback;
|
||
this.ownedLockBlocks=[];
|
||
//Begin send auth
|
||
var docsCoApi = this;
|
||
// Server info
|
||
this._serverHost = serverHost;
|
||
this._serverPath = serverPath;
|
||
this.sockjs_url = this._url + '/doc/'+docid+'/c';
|
||
this.sockjs = initSocksJs(this.sockjs_url, this);
|
||
this._isExcel = isExcel;
|
||
this._isAuth = false;
|
||
|
||
this.dataHandler =
|
||
{
|
||
"auth":function (data) {
|
||
if (true === docsCoApi._isAuth) {
|
||
// Мы уже авторизовывались, это просто reconnect
|
||
return;
|
||
}
|
||
if (data["result"] === 1) {
|
||
// Выставляем флаг, что мы уже авторизовывались
|
||
docsCoApi._isAuth = true;
|
||
|
||
//TODO: add checks
|
||
docsCoApi._state = 2; // Authorized
|
||
docsCoApi._id = data["sessionId"];
|
||
|
||
docsCoApi._onParticipantsChanged(data["participants"], /*isStartEvent*/ true);
|
||
|
||
if (data["indexuser"]) {
|
||
docsCoApi._indexuser = data["indexuser"];
|
||
docsCoApi._onSetIndexUser (docsCoApi._indexuser);
|
||
}
|
||
|
||
if (data["messages"] && docsCoApi.onMessage) {
|
||
docsCoApi._onMessages(data);
|
||
}
|
||
if (data["locks"]) {
|
||
if (docsCoApi.ownedLockBlocks && docsCoApi.ownedLockBlocks.length>0) {
|
||
docsCoApi._onPreviousLocks(data["locks"],docsCoApi.ownedLockBlocks);
|
||
}
|
||
docsCoApi._onGetLock(data);
|
||
}
|
||
if (data["changes"]) {
|
||
docsCoApi._onFirstLoadChanges(data);
|
||
}
|
||
|
||
//Send prebuffered
|
||
docsCoApi._sendPrebuffered();
|
||
}
|
||
//TODO: Add errors
|
||
if (docsCoApi._initCallback)
|
||
{
|
||
docsCoApi._initCallback({result:data["result"]});
|
||
}
|
||
},
|
||
"getusers":function (data) {
|
||
// Специально для возможности получения после прохождения авторизации
|
||
docsCoApi._onParticipantsChanged(data["participants"], /*isStartEvent*/ true);
|
||
},
|
||
"participants":function (data) {
|
||
//Pushed participants list from server
|
||
docsCoApi._onParticipantsChanged(data["participants"], /*isStartEvent*/ false);
|
||
},
|
||
"message":function (data) {
|
||
docsCoApi._onMessages(data);
|
||
},
|
||
"getlock":function (data) {
|
||
docsCoApi._onGetLock(data);
|
||
},
|
||
"releaselock":function (data) {
|
||
docsCoApi._onReleaseLock(data);
|
||
},
|
||
"connectstate":function (data) {
|
||
docsCoApi._onConnectionStateChanged(data);
|
||
},
|
||
"isviewermode":function (data) {
|
||
docsCoApi._onUserStateChanged(data);
|
||
},
|
||
"savechanges":function (data) {
|
||
docsCoApi._onSaveChanges(data);
|
||
},
|
||
"savelock":function (data) {
|
||
docsCoApi._onSaveLock(data);
|
||
},
|
||
"unsavelock":function (data) {
|
||
docsCoApi._onUnSaveLock(data);
|
||
},
|
||
"savePartChanges":function () {
|
||
docsCoApi._onSavePartChanges();
|
||
}
|
||
};
|
||
};
|
||
global["CDocsCoApi"] = CDocsCoApi;
|
||
|
||
//Helpers
|
||
/*Array.prototype.remove = function(from, to) {
|
||
var rest = this.slice((to || from) + 1 || this.length);
|
||
this.length = from < 0 ? this.length + from : from;
|
||
return this.push.apply(this, rest);
|
||
};*/
|
||
|
||
})(this);
|
||
|