mirror of
https://github.com/ONLYOFFICE/sdkjs.git
synced 2025-04-18 14:24:11 +03:00
299 lines
8.7 KiB
JavaScript
299 lines
8.7 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) {
|
||
'use strict';
|
||
|
||
// Класс надстройка, для online и offline работы
|
||
var CSpellCheckApi = function () {
|
||
this._SpellCheckApi = new SpellCheckApi();
|
||
this._onlineWork = false;
|
||
|
||
this.onDisconnect = null;
|
||
this.onSpellCheck = null;
|
||
};
|
||
|
||
CSpellCheckApi.prototype.init = function (docid) {
|
||
if (this._SpellCheckApi && this._SpellCheckApi.isRightURL()) {
|
||
var t = this;
|
||
this._SpellCheckApi.onDisconnect = function (e, isDisconnectAtAll, isCloseCoAuthoring) {
|
||
t.callback_OnDisconnect(e, isDisconnectAtAll, isCloseCoAuthoring);
|
||
};
|
||
this._SpellCheckApi.onSpellCheck = function (e) {
|
||
t.callback_OnSpellCheck(e);
|
||
};
|
||
this._SpellCheckApi.onInit = function (e) {
|
||
t.callback_OnInit(e);
|
||
};
|
||
|
||
this._SpellCheckApi.init(docid);
|
||
this._onlineWork = true;
|
||
}
|
||
};
|
||
|
||
CSpellCheckApi.prototype.set_url = function (url) {
|
||
if (this._SpellCheckApi) {
|
||
this._SpellCheckApi.set_url(url);
|
||
}
|
||
};
|
||
|
||
CSpellCheckApi.prototype.get_state = function () {
|
||
if (this._SpellCheckApi) {
|
||
return this._SpellCheckApi.get_state();
|
||
}
|
||
|
||
return 0;
|
||
};
|
||
|
||
CSpellCheckApi.prototype.disconnect = function () {
|
||
if (this._SpellCheckApi && this._onlineWork) {
|
||
this._SpellCheckApi.disconnect();
|
||
}
|
||
};
|
||
|
||
CSpellCheckApi.prototype.spellCheck = function (spellCheckData) {
|
||
if (this._SpellCheckApi && this._onlineWork) {
|
||
this._SpellCheckApi.spellCheck(spellCheckData);
|
||
}
|
||
};
|
||
|
||
CSpellCheckApi.prototype.checkDictionary = function (lang) {
|
||
if (this._SpellCheckApi && this._onlineWork) {
|
||
return this._SpellCheckApi.checkDictionary(lang);
|
||
}
|
||
return true;
|
||
};
|
||
|
||
CSpellCheckApi.prototype.callback_OnSpellCheck = function (e) {
|
||
if (this.onSpellCheck) {
|
||
return this.onSpellCheck(e);
|
||
}
|
||
};
|
||
CSpellCheckApi.prototype.callback_OnInit = function (e) {
|
||
if (this.onInit) {
|
||
return this.onInit(e);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Event об отсоединении от сервера
|
||
* @param {jQuery} e event об отсоединении с причиной
|
||
* @param {Bool} isDisconnectAtAll окончательно ли отсоединяемся(true) или будем пробовать сделать reconnect(false) + сами отключились
|
||
*/
|
||
CSpellCheckApi.prototype.callback_OnDisconnect = function (e, isDisconnectAtAll, isCloseCoAuthoring) {
|
||
if (this.onDisconnect) {
|
||
return this.onDisconnect(e, isDisconnectAtAll, isCloseCoAuthoring);
|
||
}
|
||
};
|
||
|
||
/** States
|
||
* -1 - reconnect state
|
||
* 0 - not initialized
|
||
* 1 - opened
|
||
* 3 - closed
|
||
*/
|
||
var SpellCheckApi = function () {
|
||
this.onDisconnect = null;
|
||
this.onConnect = null;
|
||
this.onSpellCheck = null;
|
||
this.onInit = null;
|
||
|
||
this._state = 0;
|
||
// Мы сами отключились от совместного редактирования
|
||
this.isCloseCoAuthoring = false;
|
||
this.isInit = false;
|
||
|
||
this.languages = null;
|
||
|
||
// Массив данных, который стоит отправить как только подключимся
|
||
this.dataNeedSend = [];
|
||
|
||
this._url = "";
|
||
};
|
||
|
||
SpellCheckApi.prototype.isRightURL = function () {
|
||
return ("" !== this._url);
|
||
};
|
||
|
||
SpellCheckApi.prototype.set_url = function (url) {
|
||
this._url = url;
|
||
};
|
||
|
||
SpellCheckApi.prototype.get_state = function () {
|
||
return this._state;
|
||
};
|
||
|
||
SpellCheckApi.prototype.spellCheck = function (spellCheckData) {
|
||
this._send({"type": "spellCheck", "spellCheckData": spellCheckData});
|
||
};
|
||
|
||
SpellCheckApi.prototype.checkDictionary = function (lang) {
|
||
// Check init. May arrive earlier than initialization
|
||
return !this.isInit || !!this.languages[lang];
|
||
};
|
||
|
||
SpellCheckApi.prototype.disconnect = function () {
|
||
// Отключаемся сами
|
||
this.isCloseCoAuthoring = true;
|
||
return this.sockjs.close();
|
||
};
|
||
|
||
SpellCheckApi.prototype._send = function (data) {
|
||
if (data !== null && typeof data === "object") {
|
||
if (this._state > 0) {
|
||
this.sockjs.send(JSON.stringify(data));
|
||
} else {
|
||
this.dataNeedSend.push(data);
|
||
}
|
||
}
|
||
};
|
||
|
||
SpellCheckApi.prototype._sendAfterConnect = function () {
|
||
var data;
|
||
while (this._state > 0 && undefined !== (data = this.dataNeedSend.shift()))
|
||
this._send(data);
|
||
};
|
||
|
||
SpellCheckApi.prototype._onSpellCheck = function (data) {
|
||
if (data["spellCheckData"] && this.onSpellCheck) {
|
||
this.onSpellCheck(data["spellCheckData"]);
|
||
}
|
||
};
|
||
SpellCheckApi.prototype._onInit = function (data) {
|
||
if (!this.isInit && data["languages"]) {
|
||
if (this.onInit) {
|
||
this.onInit(data["languages"]);
|
||
}
|
||
this.languages = data["languages"].reduce(function(map, value) {
|
||
map[value] = 1;
|
||
return map;
|
||
}, {});
|
||
this.isInit = true;
|
||
}
|
||
};
|
||
|
||
var reconnectTimeout, attemptCount = 0;
|
||
|
||
function initSocksJs(url, docsCoApi) {
|
||
if (window['IS_NATIVE_EDITOR']) {
|
||
return;
|
||
}
|
||
|
||
//ограничиваем transports WebSocket и XHR / JSONP polling, как и engine.io https://github.com/socketio/engine.io
|
||
//при переборе streaming transports у клиента с wirewall происходило зацикливание(не повторялось в версии sock.js 0.3.4)
|
||
var sockjs = new (AscCommon.getSockJs())(url, null,
|
||
{'transports': ['websocket', 'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling']});
|
||
|
||
sockjs.onopen = function () {
|
||
if (reconnectTimeout) {
|
||
clearTimeout(reconnectTimeout);
|
||
attemptCount = 0;
|
||
}
|
||
docsCoApi._state = 1; // Opened state
|
||
if (docsCoApi.onConnect) {
|
||
docsCoApi.onConnect();
|
||
}
|
||
|
||
// Отправляем все данные, которые пришли до соединения с сервером
|
||
docsCoApi._sendAfterConnect();
|
||
};
|
||
|
||
sockjs.onmessage = function (e) {
|
||
//TODO: add checks and error handling
|
||
//Get data type
|
||
var dataObject = JSON.parse(e.data);
|
||
var type = dataObject.type;
|
||
switch (type) {
|
||
case 'spellCheck' :
|
||
docsCoApi._onSpellCheck(dataObject);
|
||
break;
|
||
case 'init':
|
||
docsCoApi._onInit(dataObject);
|
||
break;
|
||
}
|
||
};
|
||
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;
|
||
}
|
||
|
||
SpellCheckApi.prototype.init = function (docid) {
|
||
this._docid = docid;
|
||
var re = /^https?:\/\//;
|
||
var spellcheckUrl = this._url + '/doc/' + docid + '/c';
|
||
|
||
if (re.test(this._url)) {
|
||
this.sockjs_url = spellcheckUrl;
|
||
} else {
|
||
this.sockjs_url = AscCommon.getBaseUrl() + "../../../.." + spellcheckUrl;
|
||
}
|
||
|
||
//Begin send auth
|
||
this.sockjs = initSocksJs(this.sockjs_url, this);
|
||
};
|
||
|
||
//-----------------------------------------------------------export---------------------------------------------------
|
||
window['AscCommon'] = window['AscCommon'] || {};
|
||
window["AscCommon"].CSpellCheckApi = CSpellCheckApi;
|
||
})(window);
|
||
|