diff --git a/apps/api/documents/api.js b/apps/api/documents/api.js
index e3de713aa..4ba9c3d1a 100644
--- a/apps/api/documents/api.js
+++ b/apps/api/documents/api.js
@@ -838,9 +838,24 @@
return extensionParams["url"] + "apps/";
}
+
+ function getTestPath() {
+ var scripts = document.getElementsByTagName('script'),
+ match;
+
+ for (var i = scripts.length - 1; i >= 0; i--) {
+ match = scripts[i].src.match(/(.*)apps\/api\/documents\/api.js/i);
+ if (match) {
+ return match[1] + "test/";
+ }
+ }
+
+ return "";
+ }
+
function getAppPath(config) {
var extensionPath = getExtensionPath(),
- path = extensionPath ? extensionPath : getBasePath(),
+ path = extensionPath ? extensionPath : (config.type=="test" ? getTestPath() : getBasePath()),
appMap = {
'text': 'documenteditor',
'text-pdf': 'documenteditor',
diff --git a/test/common/Gateway.js b/test/common/Gateway.js
new file mode 100644
index 000000000..675a7421a
--- /dev/null
+++ b/test/common/Gateway.js
@@ -0,0 +1,363 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+
+if (window.Common === undefined) {
+ window.Common = {};
+}
+
+ Common.Gateway = new(function() {
+ var me = this,
+ $me = $(me);
+
+ var commandMap = {
+ 'init': function(data) {
+ $me.trigger('init', data);
+ },
+
+ 'openDocument': function(data) {
+ $me.trigger('opendocument', data);
+ },
+
+ 'showMessage': function(data) {
+ $me.trigger('showmessage', data);
+ },
+
+ 'applyEditRights': function(data) {
+ $me.trigger('applyeditrights', data);
+ },
+
+ 'processSaveResult': function(data) {
+ $me.trigger('processsaveresult', data);
+ },
+
+ 'processRightsChange': function(data) {
+ $me.trigger('processrightschange', data);
+ },
+
+ 'refreshHistory': function(data) {
+ $me.trigger('refreshhistory', data);
+ },
+
+ 'setHistoryData': function(data) {
+ $me.trigger('sethistorydata', data);
+ },
+
+ 'setEmailAddresses': function(data) {
+ $me.trigger('setemailaddresses', data);
+ },
+
+ 'setActionLink': function (data) {
+ $me.trigger('setactionlink', data.url);
+ },
+
+ 'processMailMerge': function(data) {
+ $me.trigger('processmailmerge', data);
+ },
+
+ 'downloadAs': function(data) {
+ $me.trigger('downloadas', data);
+ },
+
+ 'processMouse': function(data) {
+ $me.trigger('processmouse', data);
+ },
+
+ 'internalCommand': function(data) {
+ $me.trigger('internalcommand', data);
+ },
+
+ 'resetFocus': function(data) {
+ $me.trigger('resetfocus', data);
+ },
+
+ 'setUsers': function(data) {
+ $me.trigger('setusers', data);
+ },
+
+ 'showSharingSettings': function(data) {
+ $me.trigger('showsharingsettings', data);
+ },
+
+ 'setSharingSettings': function(data) {
+ $me.trigger('setsharingsettings', data);
+ },
+
+ 'insertImage': function(data) {
+ $me.trigger('insertimage', data);
+ },
+
+ 'setMailMergeRecipients': function(data) {
+ $me.trigger('setmailmergerecipients', data);
+ },
+
+ 'setRevisedFile': function(data) {
+ $me.trigger('setrevisedfile', data);
+ },
+
+ 'setFavorite': function(data) {
+ $me.trigger('setfavorite', data);
+ },
+
+ 'requestClose': function(data) {
+ $me.trigger('requestclose', data);
+ },
+
+ 'blurFocus': function(data) {
+ $me.trigger('blurfocus', data);
+ },
+
+ 'grabFocus': function(data) {
+ $me.trigger('grabfocus', data);
+ }
+ };
+
+ var _postMessage = function(msg) {
+ // TODO: specify explicit origin
+ if (window.parent && window.JSON) {
+ msg.frameEditorId = window.frameEditorId;
+ window.parent.postMessage(window.JSON.stringify(msg), "*");
+ }
+ };
+
+ var _onMessage = function(msg) {
+ // TODO: check message origin
+ if (msg.origin !== window.parentOrigin && msg.origin !== window.location.origin && !(msg.origin==="null" && (window.parentOrigin==="file://" || window.location.origin==="file://"))) return;
+
+ var data = msg.data;
+ if (Object.prototype.toString.apply(data) !== '[object String]' || !window.JSON) {
+ return;
+ }
+
+ var cmd, handler;
+
+ try {
+ cmd = window.JSON.parse(data)
+ } catch(e) {
+ cmd = '';
+ }
+
+ if (cmd) {
+ handler = commandMap[cmd.command];
+ if (handler) {
+ handler.call(this, cmd.data);
+ }
+ }
+ };
+
+ var fn = function(e) { _onMessage(e); };
+
+ if (window.attachEvent) {
+ window.attachEvent('onmessage', fn);
+ } else {
+ window.addEventListener('message', fn, false);
+ }
+
+ return {
+
+ appReady: function() {
+ _postMessage({ event: 'onAppReady' });
+ },
+
+ requestEditRights: function() {
+ _postMessage({ event: 'onRequestEditRights' });
+ },
+
+ requestHistory: function() {
+ _postMessage({ event: 'onRequestHistory' });
+ },
+
+ requestHistoryData: function(revision) {
+ _postMessage({
+ event: 'onRequestHistoryData',
+ data: revision
+ });
+ },
+
+ requestRestore: function(version, url, fileType) {
+ _postMessage({
+ event: 'onRequestRestore',
+ data: {
+ version: version,
+ url: url,
+ fileType: fileType
+ }
+ });
+ },
+
+ requestEmailAddresses: function() {
+ _postMessage({ event: 'onRequestEmailAddresses' });
+ },
+
+ requestStartMailMerge: function() {
+ _postMessage({event: 'onRequestStartMailMerge'});
+ },
+
+ requestHistoryClose: function(revision) {
+ _postMessage({event: 'onRequestHistoryClose'});
+ },
+
+ reportError: function(code, description) {
+ _postMessage({
+ event: 'onError',
+ data: {
+ errorCode: code,
+ errorDescription: description
+ }
+ });
+ },
+
+ reportWarning: function(code, description) {
+ _postMessage({
+ event: 'onWarning',
+ data: {
+ warningCode: code,
+ warningDescription: description
+ }
+ });
+ },
+
+ sendInfo: function(info) {
+ _postMessage({
+ event: 'onInfo',
+ data: info
+ });
+ },
+
+ setDocumentModified: function(modified) {
+ _postMessage({
+ event: 'onDocumentStateChange',
+ data: modified
+ });
+ },
+
+ internalMessage: function(type, data) {
+ _postMessage({
+ event: 'onInternalMessage',
+ data: {
+ type: type,
+ data: data
+ }
+ });
+ },
+
+ updateVersion: function() {
+ _postMessage({ event: 'onOutdatedVersion' });
+ },
+
+ downloadAs: function(url, fileType) {
+ _postMessage({
+ event: 'onDownloadAs',
+ data: {
+ url: url,
+ fileType: fileType
+ }
+ });
+ },
+
+ requestSaveAs: function(url, title, fileType) {
+ _postMessage({
+ event: 'onRequestSaveAs',
+ data: {
+ url: url,
+ title: title,
+ fileType: fileType
+ }
+ });
+ },
+
+ collaborativeChanges: function() {
+ _postMessage({event: 'onCollaborativeChanges'});
+ },
+
+ requestRename: function(title) {
+ _postMessage({event: 'onRequestRename', data: title});
+ },
+
+ metaChange: function(meta) {
+ _postMessage({event: 'onMetaChange', data: meta});
+ },
+
+ documentReady: function() {
+ _postMessage({ event: 'onDocumentReady' });
+ },
+
+ requestClose: function() {
+ _postMessage({event: 'onRequestClose'});
+ },
+
+ requestMakeActionLink: function (config) {
+ _postMessage({event:'onMakeActionLink', data: config});
+ },
+
+ requestUsers: function () {
+ _postMessage({event:'onRequestUsers'});
+ },
+
+ requestSendNotify: function (emails) {
+ _postMessage({event:'onRequestSendNotify', data: emails});
+ },
+
+ requestInsertImage: function (command) {
+ _postMessage({event:'onRequestInsertImage', data: {c: command}});
+ },
+
+ requestMailMergeRecipients: function () {
+ _postMessage({event:'onRequestMailMergeRecipients'});
+ },
+
+ requestCompareFile: function () {
+ _postMessage({event:'onRequestCompareFile'});
+ },
+
+ requestSharingSettings: function () {
+ _postMessage({event:'onRequestSharingSettings'});
+ },
+
+ requestCreateNew: function () {
+ _postMessage({event:'onRequestCreateNew'});
+ },
+
+ pluginsReady: function() {
+ _postMessage({ event: 'onPluginsReady' });
+ },
+
+ on: function(event, handler){
+ var localHandler = function(event, data){
+ handler.call(me, data)
+ };
+
+ $me.on(event, localHandler);
+ }
+ }
+
+ })();
diff --git a/test/common/main/lib/util/LocalStorage.js b/test/common/main/lib/util/LocalStorage.js
new file mode 100644
index 000000000..be30d339c
--- /dev/null
+++ b/test/common/main/lib/util/LocalStorage.js
@@ -0,0 +1,137 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2021
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+
+!window.common && (window.common = {});
+
+common.localStorage = new (function() {
+ var _storeName, _filter;
+ var _store = {};
+
+ var ongetstore = function(data) {
+ if (data.type == 'localstorage') {
+ _store = data.keys;
+ }
+ };
+
+ Common.Gateway.on('internalcommand', ongetstore);
+
+ var _refresh = function() {
+ if (!_lsAllowed)
+ Common.Gateway.internalMessage('localstorage', {cmd:'get', keys:_filter});
+ };
+
+ var _save = function() {
+ if (!_lsAllowed)
+ Common.Gateway.internalMessage('localstorage', {cmd:'set', keys:_store});
+ };
+
+ var _setItem = function(name, value, just) {
+ if (_lsAllowed) {
+ try
+ {
+ localStorage.setItem(name, value);
+ }
+ catch (error){}
+
+ } else {
+ _store[name] = value;
+
+ if (just===true) {
+ Common.Gateway.internalMessage('localstorage', {
+ cmd:'set',
+ keys: {
+ name: value
+ }
+ });
+ }
+ }
+ };
+
+ var _setItemAsBool = function(name, value, just) {
+ _setItem(name, value ? 1 : 0, just);
+ };
+
+ var _getItem = function(name) {
+ if (_lsAllowed)
+ return localStorage.getItem(name);
+ else
+ return _store[name]===undefined ? null : _store[name];
+ };
+
+ var _getItemAsBool = function (name, defValue) {
+ var value = _getItem(name);
+ defValue = defValue || false;
+ return (value!==null) ? (parseInt(value) != 0) : defValue;
+ };
+
+ var _getItemExists = function (name) {
+ var value = _getItem(name);
+ return value !== null;
+ };
+
+ var _removeItem = function(name) {
+ if (_lsAllowed)
+ localStorage.removeItem(name);
+ else
+ delete _store[name];
+ };
+
+ try {
+ var _lsAllowed = !!window.localStorage;
+ } catch (e) {
+ _lsAllowed = false;
+ }
+
+ return {
+ getId: function() {
+ return _storeName;
+ },
+ setId: function(name) {
+ _storeName = name;
+ },
+ getItem: _getItem,
+ getBool: _getItemAsBool,
+ setBool: _setItemAsBool,
+ setItem: _setItem,
+ removeItem: _removeItem,
+ setKeysFilter: function(value) {
+ _filter = value;
+ },
+ getKeysFilter: function() {
+ return _filter;
+ },
+ itemExists: _getItemExists,
+ sync: _refresh,
+ save: _save
+ };
+})();
diff --git a/test/common/main/lib/util/utils.js b/test/common/main/lib/util/utils.js
index d9b9b3c97..89ca68344 100644
--- a/test/common/main/lib/util/utils.js
+++ b/test/common/main/lib/util/utils.js
@@ -1,33 +1,55 @@
-/**
- * utils.js
+/*
*
- * Unit test
+ * (c) Copyright Ascensio System SIA 2010-2019
*
- * Created by Alexander Yuzhin on 5/7/14
- * Copyright (c) 2018 Ascensio System SIA. All rights reserved.
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
*
*/
-define([
- '../../../../../apps/common/main/lib/util/utils.js'
-],function() {
- describe('Common.Utils.String', function(){
- it('Test format', function(){
- assert.equal('successively: first, second', Common.Utils.String.format('successively: {0}, {1}', 'first', 'second'));
- assert.equal('revers: second, first', Common.Utils.String.format('revers: {1}, {0}', 'first', 'second'));
- });
++function () {
+ !window.common && (window.common = {});
+ !common.utils && (common.utils = {});
- it('Test htmlEncode', function(){
- assert.equal('Curly, Larry & Moe', Common.Utils.String.htmlEncode('Curly, Larry & Moe'));
- });
+ common.utils = new(function(){
+ return {
+ htmlEncode: function(value) {
+ return $('
').text(value).html();
+ },
- it('Test htmlDecode', function(){
- assert.equal('Curly, Larry & Moe', Common.Utils.String.htmlDecode('Curly, Larry & Moe'));
- });
-
- it('Test ellipsis', function(){
- assert.equal('Truncate a s...', Common.Utils.String.ellipsis('Truncate a string and add an ellipsis', 15));
- assert.equal('Truncate a string and add...', Common.Utils.String.ellipsis('Truncate a string and add an ellipsis', 30, true));
- });
- });
-});
\ No newline at end of file
+ fillUserInfo: function(info, lang, defname, defid) {
+ var _user = info || {};
+ _user.anonymous = !_user.id;
+ !_user.id && (_user.id = defid);
+ _user.fullname = !_user.name ? defname : _user.name;
+ _user.group && (_user.fullname = (_user.group).toString() + AscCommon.UserInfoParser.getSeparator() + _user.fullname);
+ _user.guest = !_user.name;
+ return _user;
+ }
+ };
+ })();
+}();
diff --git a/test/common/main/resources/less/common.less b/test/common/main/resources/less/common.less
new file mode 100644
index 000000000..860c2a90f
--- /dev/null
+++ b/test/common/main/resources/less/common.less
@@ -0,0 +1,786 @@
+// Core variables and mixins
+@import "../../../../../vendor/bootstrap/less/variables.less";
+
+@icon-font-path: "../../../../../../vendor/bootstrap/dist/fonts/";
+
+@import "../../../../../vendor/bootstrap/less/mixins.less";
+
+// Reset
+@import "../../../../../vendor/bootstrap/less/normalize.less";
+@import "../../../../../vendor/bootstrap/less/print.less";
+
+// Core CSS
+@import "../../../../../vendor/bootstrap/less/scaffolding.less";
+@import "../../../../../vendor/bootstrap/less/type.less";
+//@import "code.less";
+//@import "grid.less";
+//@import "tables.less";
+@import "../../../../../vendor/bootstrap/less/forms.less";
+@import "../../../../../vendor/bootstrap/less/buttons.less";
+
+// Components
+@import "../../../../../vendor/bootstrap/less/component-animations.less";
+//@import "../../../../../../vendor/bootstrap/less/glyphicons.less";
+//@import "dropdowns.less";
+//@import "button-groups.less";
+//@import "input-groups.less";
+//@import "navs.less";
+//@import "navbar.less";
+//@import "breadcrumbs.less";
+//@import "pagination.less";
+//@import "pager.less";
+@import "../../../../../vendor/bootstrap/less/labels.less";
+//@import "badges.less";
+//@import "jumbotron.less";
+//@import "thumbnails.less";
+@import "../../../../../vendor/bootstrap/less/alerts.less";
+//@import "progress-bars.less";
+//@import "media.less";
+//@import "list-group.less";
+//@import "panels.less";
+//@import "wells.less";
+@import "../../../../../vendor/bootstrap/less/close.less";
+
+// Components w/ JavaScript
+@import "../../../../../vendor/bootstrap/less/modals.less";
+@import "../../../../../vendor/bootstrap/less/tooltip.less";
+//@import "../../../../../../vendor/bootstrap/less/popovers.less";
+@import "../../../../../vendor/bootstrap/less/dropdowns.less";
+//@import "carousel.less";
+
+// Utility classes
+@import "../../../../../vendor/bootstrap/less/utilities.less";
+@import "../../../../../vendor/bootstrap/less/responsive-utilities.less";
+
+@toolbarBorderColor: #dbdbdb;
+@toolbarBorderShadowColor: #FAFAFA;
+@toolbarTopColor: #F7F7F7;
+@toolbarBottomColor: #CCCCCC;
+@toolbarHoverColor: #7698DE;
+@toolbarFontSize: 12px;
+@buttonFontSize: 11px;
+@controlBtnHoverTopColor: #6180C4;
+@controlBtnHoverBottomColor: #8AACF1;
+@btnColor: #d8dadc;
+@btnActiveColor: #7d858c;
+@btnColored: #446995;
+@btnActiveColored: #293F59;
+@btnHoverColored: #375478;
+@notificationColor: #fcfed7;
+
+@iconSpriteCommonPath: "../../../../unit-tests/common/main/resources/img/glyphicons.png";
+@icon-socnet-size: 40px;
+
+.input-xs {
+ .input-size(@input-height-small - 8px; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
+}
+
+.embed-body {
+ -moz-user-select: -moz-none;
+ -khtml-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ font-size: @toolbarFontSize;
+ overflow: hidden;
+}
+
+// Document Viewer
+// -------------------------
+.viewer {
+ position: absolute;
+ margin: 0;
+ padding: 0;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ &.top {
+ top: 48px;
+ bottom: 0;
+ }
+
+ &.bottom {
+ top: 0;
+ bottom: 46px;
+ }
+}
+
+// Toolbar
+// -------------------------
+.toolbar {
+ position: fixed;
+ font-size: @toolbarFontSize;
+ min-width: 340px;
+ z-index: 100;
+ background-color: @toolbarTopColor;
+
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+
+ &.top {
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 48px;
+
+ -webkit-box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
+ //-moz-box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
+ box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
+ }
+
+ &.bottom {
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 46px;
+
+ -webkit-box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
+ //-moz-box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
+ box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
+ }
+
+ .group {
+ margin: 0;
+ padding: 0;
+
+ .item {
+ input {
+ display: inline-block;
+ width: 35px;
+ padding: 0;
+ text-align: right;
+ }
+
+ .text {
+ cursor: default;
+ }
+ }
+
+ &.left {
+ left: 0;
+ padding-left: 10px;
+
+ .item {
+ float: left;
+ }
+
+ & > div {
+ display: inline-block;
+ vertical-align: middle;
+ }
+ }
+
+ &.right {
+ right: 0;
+ padding-right: 10px;
+
+ .item {
+ display: inline-block;
+ }
+ }
+
+ &.center {
+ display: flex;
+ justify-content: center;
+ flex-grow: 1;
+ overflow: hidden;
+ padding: 0 20px;
+
+ #title-doc-name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+
+ .separator {
+ height: 22px;
+ margin: 0 9px;
+ border-right: 1px solid @toolbarBorderShadowColor;
+ border-left: 1px solid @toolbarBorderColor;
+ }
+ }
+
+ .close {
+ font-size: 28px;
+ font-family: Arial, sans-serif;
+ color: #666666;
+ opacity: 0.8;
+ display: block;
+ line-height: 22px;
+
+ &:hover {
+ opacity: 1;
+ color: #666666;
+ }
+ }
+
+ .margin-right-small {
+ margin-right: 8px;
+ }
+ .margin-right-large {
+ margin-right: 12px;
+ }
+ .margin-left-small {
+ margin-left: 8px;
+ }
+ .margin-left-large {
+ margin-left: 12px;
+ }
+}
+
+// Logo
+// -------------------------
+/*.brand-logo {
+ display: block;
+ width: 100px;
+ height: 24px;
+ background: data-uri('../../../../unit-tests/common/main/resources/img/logo.svg') no-repeat;
+}*/
+
+// Control buttons
+// -------------------------
+.control-btn {
+ display: inline-block;
+ vertical-align: middle;
+ cursor: pointer;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 2px;
+
+ width: 22px;
+ height: 22px;
+ background-origin: content-box;
+ padding: 0 1px;
+ font-size: @buttonFontSize;
+
+ &.has-caption {
+ width: auto;
+ padding-right: 5px;
+ }
+
+ &.colored {
+ padding: 0 16px;
+ height: 28px;
+ background-color: @btnColored;
+ border-radius: 3px;
+ color: #ffffff;
+ font-weight: 700;
+ }
+
+ // Hover state
+ &:hover:not(:disabled) {
+ text-decoration: none;
+ background-color: @btnColor;
+
+ &.colored {
+ background-color: @btnHoverColored;
+ }
+ }
+
+ &:active:not(:disabled) {
+ &, .btn-icon {
+ background-position-y: -@icon-height !important;
+ }
+
+ &.has-caption {
+ color: #ffffff
+ }
+
+ &.colored {
+ background-color: @btnActiveColored;
+ }
+ }
+
+// Focus state for keyboard and accessibility
+ &:focus {
+ .tab-focus();
+ outline: none;
+ }
+
+// Active state
+ &.active:not(:disabled),
+ &:active:not(:disabled) {
+ outline: none;
+ border: 1px solid @btnActiveColor;
+ background-color: @btnActiveColor;
+ }
+
+ &[disabled] {
+ opacity: 0.4;
+ }
+}
+
+// Overlay control
+// -------------------------
+.overlay-controls {
+ position: absolute;
+ bottom: 55px;
+ z-index: 10;
+ left: 50%;
+
+ ul {
+ padding: 0;
+ list-style-type: none;
+ margin: 0 auto;
+
+ li {
+ display: inline-block;
+
+ &:first-child {
+ margin-right: 5px;
+ }
+
+ &:last-child {
+ margin-left: 5px;
+ }
+ }
+ }
+
+ .overlay {
+ width: 32px;
+ height: 32px;
+
+ display: inline-block;
+ cursor: pointer;
+ background-color: black;
+ border: 5px solid black;
+ border-radius: 50%;
+ outline: none;
+ opacity: 0.3;
+
+ background-origin: content-box;
+ padding: 1px 0 0 1px;
+
+ -webkit-box-shadow: 0 0 0 2px rgba(255,255,255,0.3);
+ -moz-box-shadow: 0 0 0 2px rgba(255,255,255,0.3);
+ box-shadow: 0 0 0 2px rgba(255,255,255,0.3);
+
+ &:hover {
+ opacity: .6;
+ }
+
+ &.active, &:active {
+ opacity: .8;
+ }
+ }
+}
+
+// Error mask
+// -------------------------
+.errormask {
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ border: none;
+ background-color: #f4f4f4;
+ z-index: 30002;
+
+ .error-body {
+ position: relative;
+ top: 40%;
+ width: 400px;
+ margin: 0 auto;
+ padding: 20px;
+ background-color: #FFFFFF;
+ border: 1px solid #C0C0C0;
+
+ .title {
+ font-weight: bold;
+ font-size: 1.6em;
+ padding-bottom: 10px;
+ }
+ }
+}
+
+// Modals
+// -------------------------
+.modal {
+ .modal-header {
+ //padding: 5px 15px;
+ }
+
+ .modal-footer {
+ //border-top: none;
+ }
+
+ //&.in .modal-dialog { .translate(0, 100%)}
+}
+
+.share-buttons {
+ ul {
+ width: 244px;
+ //height: 25px;
+ list-style-type: none;
+ margin: 5px 0 0;
+ overflow: hidden;
+
+ li {
+ display: inline-block;
+ float: left;
+ margin: 1px 5px 0 0;
+ vertical-align: middle;
+
+ &.share-mail {
+ float: right;
+ padding-right: 1px;
+ margin: 0;
+
+ a {
+ min-width: 64px;
+ }
+
+ .glyphicon {
+ margin-right: 4px;
+ }
+ }
+
+ &.share-twitter {
+ max-width: 93px;
+ }
+ }
+ }
+}
+
+.size-manual {
+ margin-bottom: 10px;
+
+ .right {
+ float: right;
+ }
+
+ .caption {
+ margin-top: 2px;
+ margin-right: 8px;
+ }
+
+ input {
+ display: inline-block;
+ font-size: 1em;
+ padding: 0 4px;
+ //border-radius: 0;
+ margin: 0;
+ margin-top: -1px;
+
+ &.input-xs {
+ width: 50px;
+ }
+ }
+}
+
+.socnet-btn(@index) {
+ background-position: -@icon-socnet-size*@index 0;
+
+ &:hover {
+ background-position: -@icon-socnet-size*@index -@icon-socnet-size;
+ }
+}
+
+/*.svg {
+ background: data-uri('../../../../unit-tests/common/main/resources/img/icon-social-sprite.svg');
+
+ width: 40px;
+ height: 40px;
+ background-size: @icon-socnet-size*4 @icon-socnet-size*2;
+
+ &.big-facebook:hover {
+ background-position: 0 -@icon-socnet-size;
+ }
+
+ &.big-twitter { .socnet-btn(1); }
+ &.big-gplus { .socnet-btn(2); }
+ &.big-email { .socnet-btn(3); }
+}*/
+
+@icon-width: 20px;
+@icon-height: 20px;
+/*.svg-icon {
+ background: data-uri('../../../../unit-tests/common/main/resources/img/icon-menu-sprite.svg') no-repeat;
+ background-size: @icon-width*19 @icon-height*2;
+
+ &.download {
+ background-position: -@icon-width 0;
+ }
+ &.share {
+ background-position: -@icon-width*2 0;
+ }
+ &.embed {
+ background-position: -@icon-width*3 0;
+ }
+ &.fullscr {
+ background-position: -@icon-width*4 0;
+ }
+ &.zoom-up {
+ background-position: -@icon-width*5 -@icon-height;
+ }
+ &.zoom-down {
+ background-position: -@icon-width*6 -@icon-height;
+ }
+ &.slide-prev {
+ background-position: -@icon-width*7 -@icon-height;
+ }
+ &.slide-next {
+ background-position: -@icon-width*8 -@icon-height;
+ }
+
+ &.play {
+ background-position: -@icon-width*9 -@icon-height;
+ }
+
+ &.pause {
+ background-position: -@icon-width*10 -@icon-height;
+ }
+
+ &.print {
+ background-position: -@icon-width*11 0;
+ }
+
+ &.arrow-up {
+ background-position: -@icon-width*17 0;
+ }
+ &.arrow-down {
+ background-position: -@icon-width*16 0;
+ }
+ &.clear-style {
+ background-position: -@icon-width*12 0;
+ }
+ &.go-to-location {
+ background-position: -@icon-width*15 0;
+ }
+ &.more-vertical {
+ background-position: -@icon-width*14 0;
+ }
+}
+
+.mi-icon {
+ width: @icon-width;
+ height: @icon-height;
+ float: left;
+ margin: -3px 4px 0 -24px;
+}*/
+.btn-icon {
+ width: 22px;
+ height: 22px;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.btn, button {
+ &:focus, &:active:focus {
+ outline: 0 none;
+ }
+
+ background-color: @btnColor;
+}
+
+.modal-dialog {
+ margin-top: 100px;
+ .share-buttons {
+ height: 40px;
+ text-align: center;
+
+ span {
+ display: inline-block;
+ margin: 0 7px;
+ cursor: pointer;
+ }
+ }
+
+ .share-link {
+ margin: 0 0 15px 0;
+ }
+}
+
+.modal-header {
+ padding-bottom: 10px;
+ text-align: center;
+
+ .close {
+ margin-top: 0;
+ opacity: 0.5;
+
+ &:hover {
+ opacity: 0.7;
+ }
+ }
+}
+
+.modal-body {
+ padding: 20px;
+}
+
+.modal-footer {
+ text-align: center;
+}
+
+#dlg-share, #dlg-embed {
+ .modal-dialog {
+ width: 330px;
+ }
+
+ textarea {
+ width: 288px;
+ resize: none;
+ cursor: auto;
+ font-size: 1em;
+ border-radius: 0;
+ }
+}
+
+.dropdown-menu {
+ > li > a {
+ padding: 8px 20px 8px 28px;
+ &:hover, &:focus {
+ background-color: @btnColor;
+ outline: 0 none;
+ }
+ font-size: @buttonFontSize;
+ }
+
+ .divider {
+ margin: 4px 0;
+ }
+}
+
+.dropdown {
+ &.open {
+ > button {
+ background-color: @btnActiveColor !important;
+ background-position: -@icon-width*14 -@icon-height;
+ }
+ }
+}
+
+#box-tools {
+ display: inline-block;
+ a {
+ cursor: pointer;
+ }
+}
+
+.masked {
+ background-color: transparent;
+ border-color: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+#pages {
+ cursor: pointer;
+ display: inline-block;
+ line-height: 22px;
+ padding: 0 0 0 3px;
+}
+
+#page-number {
+ &.masked {
+ cursor: pointer;
+ }
+}
+
+.tooltip {
+ .tooltip-inner {
+ background-color: #fff;
+ border: 1px solid rgba(0,0,0,0.15);
+ color: #333;
+ font-weight: bold;
+ font-size: 11px;
+ box-shadow: 0 6px 12px rgba(0,0,0,0.175);
+ max-width: 350px;
+
+ padding: 5px 12px;
+ white-space: pre-wrap;
+ text-align: left;
+ word-wrap: break-word;
+ }
+
+ .tooltip-arrow {
+ display: none;
+ }
+}
+
+.form-control {
+ &:focus {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+}
+
+.submit-tooltip {
+ position: absolute;
+ z-index: 1000;
+ top: 58px;
+ right: 15px;
+
+ padding: 7px 15px;
+ border-radius: 5px;
+ background-color: @notificationColor;
+ -webkit-box-shadow: 0 4px 15px -2px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 4px 15px -2px rgba(0, 0, 0, 0.5);
+ font-size: 11px;
+}
+
+.required-tooltip {
+ position: absolute;
+ z-index: 1000;
+
+ padding: 15px;
+ border-radius: 5px;
+ background-color: @btnColored;
+ color: #fff;
+ -webkit-box-shadow: 0 4px 15px -2px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 4px 15px -2px rgba(0, 0, 0, 0.5);
+ font-size: 11px;
+
+ &.bottom-left {
+ border-top-right-radius: 0;
+ margin: 15px 0 0 0;
+
+ .tip-arrow {
+ position: absolute;
+ overflow: hidden;
+ right: 0;
+ top: -15px;
+ width: 15px;
+ height: 15px;
+ .box-shadow(8px 5px 8px -5px rgba(0, 0, 0, 0.2));
+
+ &:after {
+ content: '';
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ background-color: @btnColored;
+ width: 15px;
+ height: 15px;
+
+ -moz-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -webkit-transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ transform: rotate(45deg);
+ .box-shadow(0 0 8px -1px rgba(0, 0, 0, 0.2));
+ }
+ }
+ }
+ .close-div {
+ display: inline-block;
+ border: 1px solid #fff;
+ border-radius: 2px;
+ padding: 3px 12px;
+ margin-top: 10px;
+ }
+}
+
+.tooltip {
+ .tooltip-inner {
+ .toolbar & {
+ font-weight: normal;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/documenteditor/main/index.html b/test/documenteditor/main/index.html
new file mode 100644
index 000000000..b1ef1a729
--- /dev/null
+++ b/test/documenteditor/main/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+ Documents
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/documenteditor/main/js/ApplicationController.js b/test/documenteditor/main/js/ApplicationController.js
new file mode 100644
index 000000000..d704f28d8
--- /dev/null
+++ b/test/documenteditor/main/js/ApplicationController.js
@@ -0,0 +1,342 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+DE.ApplicationController = new(function(){
+ var me,
+ api,
+ config = {},
+ docConfig = {},
+ permissions = {},
+ created = false,
+ appOptions = {},
+ bodyWidth = 0;
+
+ var LoadingDocument = -256;
+
+ // Check browser
+ // -------------------------
+
+ if (typeof isBrowserSupported !== 'undefined' && !isBrowserSupported()){
+ console.error(this.unsupportedBrowserErrorText);
+ return;
+ }
+
+ common.localStorage.setId('text');
+ common.localStorage.setKeysFilter('de-,asc.text');
+ common.localStorage.sync();
+
+ // Handlers
+ // -------------------------
+
+ function loadConfig(data) {
+ config = $.extend(config, data.config);
+ }
+
+ function loadDocument(data) {
+ docConfig = data.doc;
+
+ if (docConfig) {
+ permissions = $.extend(permissions, docConfig.permissions);
+
+ var _permissions = $.extend({}, docConfig.permissions),
+ docInfo = new Asc.asc_CDocInfo(),
+ _user = new Asc.asc_CUserInfo();
+
+ var canRenameAnonymous = !((typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') && (config.customization.anonymous.request===false)),
+ guestName = (typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') &&
+ (typeof (config.customization.anonymous.label) == 'string') && config.customization.anonymous.label.trim()!=='' ?
+ common.utils.htmlEncode(config.customization.anonymous.label) : me.textGuest,
+ value = canRenameAnonymous ? common.localStorage.getItem("guest-username") : null;//,
+ user = common.utils.fillUserInfo(config.user, config.lang, value ? (value + ' (' + guestName + ')' ) : me.textAnonymous,
+ common.localStorage.getItem("guest-id") || ('uid-' + Date.now()));
+ user.anonymous && common.localStorage.setItem("guest-id", user.id);
+
+ _user.put_Id(user.id);
+ _user.put_FullName(user.fullname);
+ _user.put_IsAnonymousUser(user.anonymous);
+
+ docInfo.put_Id(docConfig.key);
+ docInfo.put_Url(docConfig.url);
+ docInfo.put_Title(docConfig.title);
+ docInfo.put_Format(docConfig.fileType);
+ docInfo.put_VKey(docConfig.vkey);
+ docInfo.put_UserInfo(_user);
+ docInfo.put_Token(docConfig.token);
+ docInfo.put_Permissions(_permissions);
+ docInfo.put_EncryptedInfo(config.encryptionKeys);
+
+ docInfo.asc_putIsEnabledMacroses(true);
+ docInfo.asc_putIsEnabledPlugins(true);
+
+
+ var type = /^(?:(pdf|djvu|xps))$/.exec(docConfig.fileType);
+ if (type && typeof type[1] === 'string') {
+ permissions.edit = permissions.review = false;
+ }
+
+ if (api) {
+ api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
+ //api.asc_registerCallback('asc_onRunAutostartMacroses', onRunAutostartMacroses);
+ api.asc_setDocInfo(docInfo);
+ api.asc_getEditorPermissions(config.licenseUrl, config.customerId);
+ api.asc_enableKeyEvents(true);
+ }
+ }
+ }
+
+ function onLongActionBegin(type, id) {
+
+ if (type == Asc.c_oAscAsyncActionType['BlockInteraction']) {
+ console.log('Action begin');
+ }
+ }
+
+ function onLongActionEnd(type, id){
+ console.log('Action end');
+ }
+
+ function onDocumentContentReady() {
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ var zf = (config.customization && config.customization.zoom ? parseInt(config.customization.zoom) : -2);
+ (zf == -1) ? api.zoomFitToPage() : ((zf == -2) ? api.zoomFitToWidth() : api.zoom(zf>0 ? zf : 100));
+
+ api.asc_registerCallback('asc_onStartAction', onLongActionBegin);
+ api.asc_registerCallback('asc_onEndAction', onLongActionEnd);
+
+ Common.Gateway.on('processmouse', onProcessMouse);
+ Common.Gateway.on('downloadas', onDownloadAs);
+ Common.Gateway.on('requestclose', onRequestClose);
+
+
+ // TODO: add asc_hasRequiredFields to sdk
+ Common.Gateway.documentReady();
+ }
+
+ function onEditorPermissions(params) {
+
+ var licType = params.asc_getLicenseType();
+ appOptions.canLicense = (licType === Asc.c_oLicenseResult.Success || licType === Asc.c_oLicenseResult.SuccessLimit);
+ appOptions.canFillForms = appOptions.canLicense && (permissions.fillForms===true) && (config.mode !== 'view');
+ appOptions.canSubmitForms = appOptions.canLicense && (typeof (config.customization) == 'object') && !!config.customization.submitForm;
+
+ api.asc_SetFastCollaborative(true);
+ api.asc_setAutoSaveGap(1);
+
+ onLongActionBegin(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ api.asc_LoadDocument();
+ api.Resize();
+ }
+
+ function onError(id, level, errData) {
+ if (id == Asc.c_oAscError.ID.LoadingScriptError) {
+ console.error(me.criticalErrorTitle,me.scriptLoadError);
+ return;
+ }
+
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ var message;
+
+ switch (id)
+ {
+ case Asc.c_oAscError.ID.Unknown:
+ message = me.unknownErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationTimeout:
+ message = me.convertationTimeoutText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationError:
+ message = me.convertationErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.DownloadError:
+ message = me.downloadErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationPassword:
+ message = me.errorFilePassProtect;
+ break;
+
+ case Asc.c_oAscError.ID.UserDrop:
+ message = me.errorUserDrop;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationOpenLimitError:
+ message = me.errorFileSizeExceed;
+ break;
+
+ case Asc.c_oAscError.ID.UpdateVersion:
+ message = me.errorUpdateVersionOnDisconnect;
+ break;
+
+ case Asc.c_oAscError.ID.AccessDeny:
+ message = me.errorAccessDeny;
+ break;
+
+ case Asc.c_oAscError.ID.Submit:
+ message = me.errorSubmit;
+ break;
+
+ case Asc.c_oAscError.ID.EditingError:
+ message = me.errorEditingDownloadas;
+ break;
+
+ case Asc.c_oAscError.ID.ForceSaveButton:
+ case Asc.c_oAscError.ID.ForceSaveTimeout:
+ message = me.errorForceSave;
+ break;
+
+ case Asc.c_oAscError.ID.LoadingFontError:
+ message = me.errorLoadingFont;
+ break;
+
+ default:
+ message = me.errorDefaultMessage.replace('%1', id);
+ break;
+ }
+
+ if (level == Asc.c_oAscError.Level.Critical) {
+ console.error(id,message);
+ }
+ else {
+ console.warn(id, message);
+
+ }
+ }
+
+ function onExternalMessage(error) {
+ if (error) {
+ console.error(error.msg);
+ }
+ }
+
+
+ function onProcessMouse(data) {
+ if (data.type == 'mouseup') {
+ var e = document.getElementById('editor_sdk');
+ if (e) {
+ var r = e.getBoundingClientRect();
+ api.OnMouseUp(
+ data.x - r.left,
+ data.y - r.top
+ );
+ }
+ }
+ }
+
+ function onRequestClose() {
+ Common.Gateway.requestClose();
+ }
+
+ function onDownloadAs() {
+ if ( permissions.download === false) {
+ //Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, me.errorAccessDeny);
+ console.error(Asc.c_oAscError.ID.AccessDeny, me.errorAccessDeny);
+ return;
+ }
+ if (api) api.asc_DownloadAs(new Asc.asc_CDownloadOptions(Asc.c_oAscFileType.DOCX, false));
+ }
+
+ function onBeforeUnload () {
+ common.localStorage.save();
+ }
+
+ function onDocumentResize() {
+ api && api.Resize();
+ bodyWidth = $('body').width();
+ }
+
+ function createController(){
+ if (created)
+ return me;
+
+ me = this;
+ created = true;
+
+ $(window).resize(function(){
+ onDocumentResize();
+ });
+ window.onbeforeunload = onBeforeUnload;
+
+ $('#editor_sdk').on('click', function(e) {
+ if ( e.target.localName == 'canvas' ) {
+ e.currentTarget.focus();
+ }
+ });
+
+ window["flat_desine"] = true;
+ api = new Asc.asc_docs_api({
+ 'id-view' : 'editor_sdk',
+ 'embedded' : true
+ });
+
+ if (api){
+ api.asc_registerCallback('asc_onError', onError);
+ api.asc_registerCallback('asc_onDocumentContentReady', onDocumentContentReady);
+
+ // Initialize api gateway
+ Common.Gateway.on('init', loadConfig);
+ Common.Gateway.on('opendocument', loadDocument);
+ Common.Gateway.on('showmessage', onExternalMessage);
+ Common.Gateway.appReady();
+ }
+
+ return me;
+ }
+
+ return {
+ create : createController,
+ errorDefaultMessage : 'Error code: %1',
+ unknownErrorText : 'Unknown error.',
+ convertationTimeoutText : 'Conversion timeout exceeded.',
+ convertationErrorText : 'Conversion failed.',
+ downloadErrorText : 'Download failed.',
+ criticalErrorTitle : 'Error',
+ scriptLoadError: 'The connection is too slow, some of the components could not be loaded. Please reload the page.',
+ errorFilePassProtect: 'The file is password protected and cannot be opened.',
+ errorAccessDeny: 'You are trying to perform an action you do not have rights for. Please contact your Document Server administrator.',
+ errorUserDrop: 'The file cannot be accessed right now.',
+ unsupportedBrowserErrorText: 'Your browser is not supported.',
+ errorFileSizeExceed: 'The file size exceeds the limitation set for your server. Please contact your Document Server administrator for details.',
+ errorUpdateVersionOnDisconnect: 'Internet connection has been restored, and the file version has been changed. Before you can continue working, you need to download the file or copy its content to make sure nothing is lost, and then reload this page.',
+ errorSubmit: 'Submit failed.',
+ errorEditingDownloadas: 'An error occurred during the work with the document. Use the \'Download as...\' option to save the file backup copy to your computer hard drive.',
+ textGuest: 'Guest',
+ textAnonymous: 'Anonymous',
+ errorForceSave: "An error occurred while saving the file. Please use the 'Download as' option to save the file to your computer hard drive or try again later.",
+ errorLoadingFont: 'Fonts are not loaded. Please contact your Document Server administrator.'
+ }
+})();
\ No newline at end of file
diff --git a/test/documenteditor/main/js/ApplicationView.js b/test/documenteditor/main/js/ApplicationView.js
new file mode 100644
index 000000000..9285bd802
--- /dev/null
+++ b/test/documenteditor/main/js/ApplicationView.js
@@ -0,0 +1,50 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+if (DE === undefined) {
+ var DE = {};
+}
+
+DE.ApplicationView = new(function(){
+
+
+ // Initialize view
+
+ function createView(){
+
+ }
+
+ return {
+ create: createView
+
+ }
+})();
diff --git a/test/documenteditor/main/js/application.js b/test/documenteditor/main/js/application.js
new file mode 100644
index 000000000..f6102359b
--- /dev/null
+++ b/test/documenteditor/main/js/application.js
@@ -0,0 +1,37 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
++function ($) {
+ DE.ApplicationView.create();
+ DE.ApplicationController.create();
+
+}();
diff --git a/test/documenteditor/main/resources/less/application.less b/test/documenteditor/main/resources/less/application.less
new file mode 100644
index 000000000..95cba0a92
--- /dev/null
+++ b/test/documenteditor/main/resources/less/application.less
@@ -0,0 +1,2 @@
+// Common styles
+@import "../../../../common/main/resources/less/common.less";
\ No newline at end of file
diff --git a/test/presentationeditor/main/index.html b/test/presentationeditor/main/index.html
new file mode 100644
index 000000000..4ee99595f
--- /dev/null
+++ b/test/presentationeditor/main/index.html
@@ -0,0 +1,195 @@
+
+
+
+
+ Documents
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/presentationeditor/main/js/ApplicationController.js b/test/presentationeditor/main/js/ApplicationController.js
new file mode 100644
index 000000000..bcd50030c
--- /dev/null
+++ b/test/presentationeditor/main/js/ApplicationController.js
@@ -0,0 +1,325 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+PE.ApplicationController = new(function(){
+ var me,
+ api,
+ config = {},
+ docConfig = {},
+ permissions = {},
+ created = false;
+
+ var LoadingDocument = -256;
+
+ // Check browser
+ // -------------------------
+
+ if (typeof isBrowserSupported !== 'undefined' && !isBrowserSupported()){
+ console.error(this.unsupportedBrowserErrorText);
+ return;
+ }
+
+ common.localStorage.setId('text');
+ common.localStorage.setKeysFilter('pe-,asc.presentation');
+ common.localStorage.sync();
+
+ // Handlers
+ // -------------------------
+
+ function loadConfig(data) {
+ config = $.extend(config, data.config);
+ }
+
+ function loadDocument(data) {
+ docConfig = data.doc;
+
+ if (docConfig) {
+ permissions = $.extend(permissions, docConfig.permissions);
+
+ var _permissions = $.extend({}, docConfig.permissions),
+ docInfo = new Asc.asc_CDocInfo(),
+ _user = new Asc.asc_CUserInfo();
+
+ var canRenameAnonymous = !((typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') && (config.customization.anonymous.request===false)),
+ guestName = (typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') &&
+ (typeof (config.customization.anonymous.label) == 'string') && config.customization.anonymous.label.trim()!=='' ?
+ common.utils.htmlEncode(config.customization.anonymous.label) : me.textGuest,
+ value = canRenameAnonymous ? common.localStorage.getItem("guest-username") : null,
+ user = common.utils.fillUserInfo(config.user, config.lang, value ? (value + ' (' + guestName + ')' ) : me.textAnonymous,
+ common.localStorage.getItem("guest-id") || ('uid-' + Date.now()));
+ user.anonymous && common.localStorage.setItem("guest-id", user.id);
+
+ _user.put_Id(user.id);
+ _user.put_FullName(user.fullname);
+ _user.put_IsAnonymousUser(user.anonymous);
+
+ docInfo.put_Id(docConfig.key);
+ docInfo.put_Url(docConfig.url);
+ docInfo.put_Title(docConfig.title);
+ docInfo.put_Format(docConfig.fileType);
+ docInfo.put_VKey(docConfig.vkey);
+ docInfo.put_UserInfo(_user);
+ docInfo.put_Token(docConfig.token);
+ docInfo.put_Permissions(_permissions);
+ docInfo.put_EncryptedInfo(config.encryptionKeys);
+
+ docInfo.asc_putIsEnabledMacroses(true);
+ docInfo.asc_putIsEnabledPlugins(true);
+
+ if (api) {
+ api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
+ api.asc_setDocInfo(docInfo);
+ api.asc_getEditorPermissions(config.licenseUrl, config.customerId);
+ api.asc_enableKeyEvents(true);
+
+ }
+ }
+ }
+
+ function onLongActionBegin(type, id) {
+
+ if (type == Asc.c_oAscAsyncActionType['BlockInteraction']) {
+
+ console.log('Action begin');
+ }
+ }
+
+ function onLongActionEnd(){
+ console.log('Action end');
+ }
+
+ function onDocumentContentReady() {
+ api.ShowThumbnails(true);
+
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ api.asc_registerCallback('asc_onStartAction', onLongActionBegin);
+ api.asc_registerCallback('asc_onEndAction', onLongActionEnd);
+
+ Common.Gateway.on('processmouse', onProcessMouse);
+ Common.Gateway.on('downloadas', onDownloadAs);
+ Common.Gateway.on('requestclose', onRequestClose);
+
+ $('#editor_sdk').on('click', function(e) {
+ if ( e.target.localName == 'canvas' ) {
+ e.currentTarget.focus();
+ }
+ });
+ Common.Gateway.documentReady();
+ }
+
+ function onEditorPermissions(params) {
+ onLongActionBegin(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+ api.asc_setViewMode(false);
+
+ api.asc_LoadDocument();
+ api.Resize();
+ }
+
+ function onError(id, level, errData) {
+ if (id == Asc.c_oAscError.ID.LoadingScriptError) {
+ console.error(me.scriptLoadError);
+ return;
+ }
+
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ var message;
+
+ switch (id)
+ {
+ case Asc.c_oAscError.ID.Unknown:
+ message = me.unknownErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationTimeout:
+ message = me.convertationTimeoutText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationError:
+ message = me.convertationErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.DownloadError:
+ message = me.downloadErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationPassword:
+ message = me.errorFilePassProtect;
+ break;
+
+ case Asc.c_oAscError.ID.UserDrop:
+ message = me.errorUserDrop;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationOpenLimitError:
+ message = me.errorFileSizeExceed;
+ break;
+
+ case Asc.c_oAscError.ID.UpdateVersion:
+ message = me.errorUpdateVersionOnDisconnect;
+ break;
+
+ case Asc.c_oAscError.ID.AccessDeny:
+ message = me.errorAccessDeny;
+ break;
+
+ case Asc.c_oAscError.ID.ForceSaveButton:
+ case Asc.c_oAscError.ID.ForceSaveTimeout:
+ message = me.errorForceSave;
+ break;
+
+ case Asc.c_oAscError.ID.LoadingFontError:
+ message = me.errorLoadingFont;
+ break;
+
+ default:
+ message = me.errorDefaultMessage.replace('%1', id);
+ break;
+ }
+
+ if (level == Asc.c_oAscError.Level.Critical) {
+
+ // report only critical errors
+ console.error(id,message);
+ }
+ else {
+ console.warn(id,message);
+ }
+
+}
+
+ function onExternalMessage(error) {
+ if (error) {
+ console.error(error.msg);
+ }
+ }
+
+ function onProcessMouse(data) {
+ if (data.type == 'mouseup') {
+ var e = document.getElementById('editor_sdk');
+ if (e) {
+ var r = e.getBoundingClientRect();
+ api.OnMouseUp(
+ data.x - r.left,
+ data.y - r.top
+ );
+ }
+ }
+ }
+
+ function onRequestClose() {
+ Common.Gateway.requestClose();
+ }
+
+ function onDownloadAs() {
+ if ( permissions.download === false) {
+ console.error(Asc.c_oAscError.ID.AccessDeny, me.errorAccessDeny);
+ return;
+ }
+ if (api) api.asc_DownloadAs(new Asc.asc_CDownloadOptions(Asc.c_oAscFileType.PPTX, false));
+ }
+
+ function onBeforeUnload () {
+ common.localStorage.save();
+ }
+
+ // Helpers
+ // -------------------------
+
+ function onDocumentResize() {
+ if (api) {
+ api.Resize();
+ }
+ }
+
+ function createController(){
+ if (created) return me;
+
+ me = this;
+ created = true;
+
+ // popover ui handlers
+
+ $(window).resize(function(){
+ onDocumentResize();
+ });
+ window.onbeforeunload = onBeforeUnload;
+
+ api = new Asc.asc_docs_api({
+ 'id-view' : 'editor_sdk',
+ 'embedded' : true
+ });
+
+ if (api){
+ api.SetThemesPath("../../../../sdkjs/slide/themes/");
+
+ api.asc_registerCallback('asc_onError', onError);
+ api.asc_registerCallback('asc_onDocumentContentReady', onDocumentContentReady);
+
+ // Initialize api gateway
+ Common.Gateway.on('init', loadConfig);
+ Common.Gateway.on('opendocument', loadDocument);
+ Common.Gateway.on('showmessage', onExternalMessage);
+ Common.Gateway.appReady();
+
+ }
+
+ return me;
+ }
+
+ return {
+ create : createController,
+ errorDefaultMessage : 'Error code: %1',
+ unknownErrorText : 'Unknown error.',
+ convertationTimeoutText : 'Conversion timeout exceeded.',
+ convertationErrorText : 'Conversion failed.',
+ downloadErrorText : 'Download failed.',
+ criticalErrorTitle : 'Error',
+ notcriticalErrorTitle : 'Warning',
+ scriptLoadError: 'The connection is too slow, some of the components could not be loaded. Please reload the page.',
+ errorFilePassProtect: 'The file is password protected and cannot be opened.',
+ errorAccessDeny: 'You are trying to perform an action you do not have rights for. Please contact your Document Server administrator.',
+ errorUserDrop: 'The file cannot be accessed right now.',
+ unsupportedBrowserErrorText: 'Your browser is not supported.',
+ downloadTextText: 'Downloading presentation...',
+ waitText: 'Please, wait...',
+ textLoadingDocument: 'Loading presentation',
+ txtClose: 'Close',
+ errorFileSizeExceed: 'The file size exceeds the limitation set for your server. Please contact your Document Server administrator for details.',
+ errorUpdateVersionOnDisconnect: 'Internet connection has been restored, and the file version has been changed. Before you can continue working, you need to download the file or copy its content to make sure nothing is lost, and then reload this page.',
+ textGuest: 'Guest',
+ textAnonymous: 'Anonymous',
+ errorForceSave: "An error occurred while saving the file. Please use the 'Download as' option to save the file to your computer hard drive or try again later.",
+ errorLoadingFont: 'Fonts are not loaded. Please contact your Document Server administrator.'
+ }
+})();
diff --git a/test/presentationeditor/main/js/ApplicationView.js b/test/presentationeditor/main/js/ApplicationView.js
new file mode 100644
index 000000000..16b97ea83
--- /dev/null
+++ b/test/presentationeditor/main/js/ApplicationView.js
@@ -0,0 +1,46 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+if (PE === undefined) {
+ var PE = {};
+}
+
+PE.ApplicationView = new(function(){
+ // Initialize view
+
+ function createView(){
+ }
+
+ return {
+ create: createView
+ }
+})();
diff --git a/test/presentationeditor/main/js/application.js b/test/presentationeditor/main/js/application.js
new file mode 100644
index 000000000..65e765ec1
--- /dev/null
+++ b/test/presentationeditor/main/js/application.js
@@ -0,0 +1,36 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+(function ($) {
+ PE.ApplicationView.create();
+ PE.ApplicationController.create();
+})(window.jQuery);
diff --git a/test/presentationeditor/main/resources/less/application.less b/test/presentationeditor/main/resources/less/application.less
new file mode 100644
index 000000000..ddb4760a3
--- /dev/null
+++ b/test/presentationeditor/main/resources/less/application.less
@@ -0,0 +1,34 @@
+// Bootstrap core variables and mixins
+@import "../../../../common/main/resources/less/common.less";
+
+.overlay-controls {
+ /*bottom: 15px;*/
+}
+
+.overlay-icon-move-left { background-position: -64px -120px; }
+.overlay-icon-move-right { background-position: -96px -120px; }
+
+#box-preview {
+ position:absolute;
+ left: 0;
+ top: 0;
+ display:none;
+ width:100%;
+ height:100%;
+ z-index: 10;
+ padding: 48px 0 0 0;
+}
+
+#id-preview {
+ width:100%;
+ height:100%;
+ position: relative;
+}
+
+.svg-icon {
+ &.play {
+ &.pause {
+ background-position: -20px*10 -20px;
+ }
+ }
+}
diff --git a/test/spreadsheeteditor/main/index.html b/test/spreadsheeteditor/main/index.html
new file mode 100644
index 000000000..f36a0cf78
--- /dev/null
+++ b/test/spreadsheeteditor/main/index.html
@@ -0,0 +1,167 @@
+
+
+
+
+ Documents
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/spreadsheeteditor/main/js/ApplicationController.js b/test/spreadsheeteditor/main/js/ApplicationController.js
new file mode 100644
index 000000000..dca9bf116
--- /dev/null
+++ b/test/spreadsheeteditor/main/js/ApplicationController.js
@@ -0,0 +1,386 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+SSE.ApplicationController = new(function(){
+ var me,
+ api,
+ config = {},
+ docConfig = {},
+ permissions = {},
+ maxPages = 0,
+ created = false;
+
+ var LoadingDocument = -256;
+
+ // Check browser
+ // -------------------------
+
+ if (typeof isBrowserSupported !== 'undefined' && !isBrowserSupported()){
+ console.error( this.unsupportedBrowserErrorText);
+ return;
+ }
+
+ common.localStorage.setId('text');
+ common.localStorage.setKeysFilter('sse-,asc.table');
+ common.localStorage.sync();
+
+ // Handlers
+ // -------------------------
+
+ function loadConfig(data) {
+ config = $.extend(config, data.config);
+ }
+
+ function loadDocument(data) {
+ docConfig = data.doc;
+
+ if (docConfig) {
+ permissions = $.extend(permissions, docConfig.permissions);
+
+ var _permissions = $.extend({}, docConfig.permissions),
+ docInfo = new Asc.asc_CDocInfo(),
+ _user = new Asc.asc_CUserInfo();
+
+ var canRenameAnonymous = !((typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') && (config.customization.anonymous.request===false)),
+ guestName = (typeof (config.customization) == 'object') && (typeof (config.customization.anonymous) == 'object') &&
+ (typeof (config.customization.anonymous.label) == 'string') && config.customization.anonymous.label.trim()!=='' ?
+ common.utils.htmlEncode(config.customization.anonymous.label) : me.textGuest,
+ value = canRenameAnonymous ? common.localStorage.getItem("guest-username") : null,
+ user = common.utils.fillUserInfo(config.user, config.lang, value ? (value + ' (' + guestName + ')' ) : me.textAnonymous,
+ common.localStorage.getItem("guest-id") || ('uid-' + Date.now()));
+ user.anonymous && common.localStorage.setItem("guest-id", user.id);
+
+ _user.put_Id(user.id);
+ _user.put_FullName(user.fullname);
+ _user.put_IsAnonymousUser(user.anonymous);
+
+ docInfo.put_Id(docConfig.key);
+ docInfo.put_Url(docConfig.url);
+ docInfo.put_Title(docConfig.title);
+ docInfo.put_Format(docConfig.fileType);
+ docInfo.put_VKey(docConfig.vkey);
+ docInfo.put_UserInfo(_user);
+ docInfo.put_Token(docConfig.token);
+ docInfo.put_Permissions(_permissions);
+ docInfo.put_EncryptedInfo(config.encryptionKeys);
+ docInfo.put_Lang(config.lang);
+ docInfo.put_Mode(config.mode);
+
+ docInfo.asc_putIsEnabledMacroses(true);
+ docInfo.asc_putIsEnabledPlugins(true);
+
+ if (api) {
+ api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
+ api.asc_setDocInfo(docInfo);
+ api.asc_getEditorPermissions(config.licenseUrl, config.customerId);
+ api.asc_enableKeyEvents(false);
+ }
+ }
+ }
+
+ function setActiveWorkSheet(index) {
+ var $box = $('#worksheets');
+ $box.find('> li').removeClass('active');
+ $box.find('#worksheet' + index).addClass('active');
+
+ api.asc_showWorksheet(index);
+ }
+
+ function onSheetsChanged(){
+ maxPages = api.asc_getWorksheetsCount();
+
+ var handleWorksheet = function(e){
+ var $worksheet = $(this);
+ var index = $worksheet.attr('id').match(/\d+$/);
+
+ if (index.length > 0) {
+ index = parseInt(index[0]);
+
+ if (index > -1 && index < maxPages)
+ setActiveWorkSheet(index);
+ }
+ };
+
+ var $box = $('#worksheets');
+ $box.find('li').off();
+ $box.empty();
+
+ var tpl = '
{title}
';
+ for (var i = 0; i < maxPages; i++) {
+ var item = tpl.replace(/\{index}/, i).replace(/\{title}/,api.asc_getWorksheetName(i).replace(/\s/g,' '));
+ $(item).appendTo($box).on('click', handleWorksheet);
+ }
+
+ setActiveWorkSheet(api.asc_getActiveWorksheetIndex());
+ }
+
+ function onDocumentContentReady() {
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+ api.asc_registerCallback('asc_onStartAction', onLongActionBegin);
+
+ Common.Gateway.on('processmouse', onProcessMouse);
+ Common.Gateway.on('downloadas', onDownloadAs);
+ Common.Gateway.on('requestclose', onRequestClose);
+
+
+ $('#editor_sdk').on('click', function(e) {
+ if ( e.target.localName == 'canvas' ) {
+ e.currentTarget.focus();
+ }
+ });
+
+ $(document).on('mousewheel', function (e) {
+ if ((e.ctrlKey || e.metaKey) && !e.altKey) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+
+ Common.Gateway.documentReady();
+ }
+
+ function onEditorPermissions(params) {
+ api.asc_SetFastCollaborative(true);
+ api.asc_setAutoSaveGap(1);
+
+ onLongActionBegin(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+ api.asc_LoadDocument();
+ }
+
+ function onLongActionBegin(type, id){
+ if (type == Asc.c_oAscAsyncActionType['BlockInteraction']) {
+ console.log('Action begin');
+ }
+ }
+
+ function onLongActionEnd(type, id){
+ if (type === Asc.c_oAscAsyncActionType.BlockInteraction) {
+ switch (id) {
+ case Asc.c_oAscAsyncAction.Open:
+ if (api) {
+ api.asc_Resize();
+ var zf = (config.customization && config.customization.zoom ? parseInt(config.customization.zoom)/100 : 1);
+ api.asc_setZoom(zf>0 ? zf : 1);
+ }
+
+ onDocumentContentReady();
+ onSheetsChanged();
+ break;
+ }
+
+ console.log('Action end');
+ }
+ }
+
+ function onError(id, level, errData) {
+ if (id == Asc.c_oAscError.ID.LoadingScriptError) {
+ console.error(id,me.scriptLoadError);
+ return;
+ }
+
+ onLongActionEnd(Asc.c_oAscAsyncActionType['BlockInteraction'], LoadingDocument);
+
+ var message;
+
+ switch (id)
+ {
+ case Asc.c_oAscError.ID.Unknown:
+ message = me.unknownErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationTimeout:
+ message = me.convertationTimeoutText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationError:
+ message = me.convertationErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.DownloadError:
+ message = me.downloadErrorText;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationPassword:
+ message = me.errorFilePassProtect;
+ break;
+
+ case Asc.c_oAscError.ID.UserDrop:
+ message = me.errorUserDrop;
+ break;
+
+ case Asc.c_oAscError.ID.ConvertationOpenLimitError:
+ message = me.errorFileSizeExceed;
+ break;
+
+ case Asc.c_oAscError.ID.UpdateVersion:
+ message = me.errorUpdateVersionOnDisconnect;
+ break;
+
+ case Asc.c_oAscError.ID.AccessDeny:
+ message = me.errorAccessDeny;
+ break;
+
+ case Asc.c_oAscError.ID.ForceSaveButton:
+ case Asc.c_oAscError.ID.ForceSaveTimeout:
+ message = me.errorForceSave;
+ break;
+
+ case Asc.c_oAscError.ID.LoadingFontError:
+ message = me.errorLoadingFont;
+ break;
+
+ default:
+ message = me.errorDefaultMessage.replace('%1', id);
+ break;
+ }
+
+ if (level == Asc.c_oAscError.Level.Critical) {
+ console.error(id,message);
+ }
+ else {
+ console.warn(id,message);
+ }
+ }
+
+ function onExternalMessage(error) {
+ if (error) {
+ $('#id-error-mask-title').text(me.criticalErrorTitle);
+ $('#id-error-mask-text').text(error.msg);
+ $('#id-error-mask').css('display', 'block');
+ }
+ }
+
+ function onProcessMouse(data) {
+ if (data.type == 'mouseup') {
+ var editor = document.getElementById('editor_sdk');
+ if (editor) {
+ var rect = editor.getBoundingClientRect();
+ var event = window.event || arguments.callee.caller.arguments[0];
+ api.asc_onMouseUp(event, data.x - rect.left, data.y - rect.top);
+ }
+ }
+ }
+
+ function onDownloadAs() {
+ if ( permissions.download === false) {
+ console.error(Asc.c_oAscError.ID.AccessDeny, me.errorAccessDeny);
+ return;
+ }
+ api.asc_DownloadAs(new Asc.asc_CDownloadOptions(Asc.c_oAscFileType.XLSX, true));
+ }
+
+ function onRequestClose() {
+ Common.Gateway.requestClose();
+ }
+
+ function onBeforeUnload () {
+ common.localStorage.save();
+ }
+
+ function onDocumentResize() {
+ if (api) api.asc_Resize();
+ }
+
+ function createController(){
+ if (created)
+ return me;
+
+ me = this;
+ created = true;
+
+ // popover ui handlers
+
+ $(window).resize(function(){
+ onDocumentResize();
+ });
+ window.onbeforeunload = onBeforeUnload;
+
+ api = new Asc.spreadsheet_api({
+ 'id-view': 'editor_sdk',
+ 'id-input' : 'ce-cell-content',
+ 'embedded' : true
+ });
+
+ if (api){
+ api.asc_registerCallback('asc_onEndAction', onLongActionEnd);
+ api.asc_registerCallback('asc_onError', onError);
+ api.asc_registerCallback('asc_onSheetsChanged', onSheetsChanged);
+ api.asc_registerCallback('asc_onActiveSheetChanged', setActiveWorkSheet);
+
+ if(SSE.CellEditorController ) {
+ SSE.CellEditorController.create();
+ SSE.CellEditorController.setApi(api);
+ }
+ // Initialize api gateway
+ Common.Gateway.on('init', loadConfig);
+ Common.Gateway.on('opendocument', loadDocument);
+ Common.Gateway.on('showmessage', onExternalMessage);
+ Common.Gateway.appReady();
+ }
+
+ api.asc_enableKeyEvents(true);
+ var ismodalshown = false;
+ $(document.body).on('blur', 'input, textarea',
+ function(e) {
+ if ( !ismodalshown ) {
+ if (!/area_id/.test(e.target.id) ) {
+ api.asc_enableKeyEvents(true);
+ }
+ }
+ }
+ );
+
+ return me;
+ }
+
+ return {
+ create : createController,
+ errorDefaultMessage : 'Error code: %1',
+ unknownErrorText : 'Unknown error.',
+ convertationTimeoutText : 'Conversion timeout exceeded.',
+ convertationErrorText : 'Conversion failed.',
+ downloadErrorText : 'Download failed.',
+ criticalErrorTitle : 'Error',
+ notcriticalErrorTitle : 'Warning',
+ scriptLoadError: 'The connection is too slow, some of the components could not be loaded. Please reload the page.',
+ errorFilePassProtect: 'The file is password protected and cannot be opened.',
+ errorAccessDeny: 'You are trying to perform an action you do not have rights for. Please contact your Document Server administrator.',
+ errorUserDrop: 'The file cannot be accessed right now.',
+ unsupportedBrowserErrorText: 'Your browser is not supported.',
+ errorFileSizeExceed: 'The file size exceeds the limitation set for your server. Please contact your Document Server administrator for details.',
+ errorUpdateVersionOnDisconnect: 'Internet connection has been restored, and the file version has been changed. Before you can continue working, you need to download the file or copy its content to make sure nothing is lost, and then reload this page.',
+ textGuest: 'Guest',
+ textAnonymous: 'Anonymous',
+ errorForceSave: "An error occurred while saving the file. Please use the 'Download as' option to save the file to your computer hard drive or try again later.",
+ errorLoadingFont: 'Fonts are not loaded. Please contact your Document Server administrator.'
+ }
+})();
\ No newline at end of file
diff --git a/test/spreadsheeteditor/main/js/ApplicationView.js b/test/spreadsheeteditor/main/js/ApplicationView.js
new file mode 100644
index 000000000..5be014e3a
--- /dev/null
+++ b/test/spreadsheeteditor/main/js/ApplicationView.js
@@ -0,0 +1,45 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+
+if (SSE === undefined) {
+ var SSE = {};
+}
+
+SSE.ApplicationView = new(function(){
+ function createView(){
+ }
+
+ return {
+ create: createView
+ }
+})();
diff --git a/test/spreadsheeteditor/main/js/CellEditorController.js b/test/spreadsheeteditor/main/js/CellEditorController.js
new file mode 100644
index 000000000..ee7f806a9
--- /dev/null
+++ b/test/spreadsheeteditor/main/js/CellEditorController.js
@@ -0,0 +1,100 @@
+!window.common && (window.common = {});
+!common.controller && (common.controller = {});
+if (SSE === undefined) {
+ var SSE = {};
+}
+SSE.Keys={RETURN: 13};
+
+SSE.CellEditorController = new(function(){
+ var me,
+ api,
+ editor,
+ created=false;
+
+ function onCellName(e){
+ if (e.keyCode == SSE.Keys.RETURN){
+ var name = editor.$cellname.val();
+ if (name && name.length) {
+ api.asc_findCell(name);
+ }
+ }
+ }
+
+ function onKeyupCellEditor(e) {
+ if(e.keyCode == SSE.Keys.RETURN && !e.altKey){
+ api.isCEditorFocused = 'clear';
+ }
+ }
+
+ function onBlurCellEditor() {
+ if (api.isCEditorFocused == 'clear')
+ api.isCEditorFocused = undefined;
+ else if (api.isCellEdited)
+ api.isCEditorFocused = true;
+ }
+
+
+
+ function events() {
+ editor.$el.find('#ce-cell-name').on( 'keyup', onCellName);
+ editor.$el.find('textarea#ce-cell-content').on( 'keyup', onKeyupCellEditor);
+ editor.$el.find('textarea#ce-cell-content').on('blur', onBlurCellEditor);
+ }
+
+ function onLaunch(){
+ SSE.CellEditorView.create();
+ editor = SSE.CellEditorView;
+ events();
+
+ editor.$el.parent().find('.after').css({zIndex: '4'}); // for spreadsheets - bug 23127
+
+ var val = common.localStorage.getItem('sse-celleditor-height');
+ editor.keep_height = 19;//(val!==null && parseInt(val)>0) ? parseInt(val) : 19;
+ if (common.localStorage.getBool('sse-celleditor-expand')) {
+ editor.$el.height(editor.keep_height);
+ }
+ this.namedrange_locked = false;
+ }
+
+ function createController() {
+ me = this;
+ if (created) return me;
+
+ created = true;
+ onLaunch();
+ return me;
+ }
+
+ function onApiCellSelection(info){
+ editor.cell.updateInfo(info);
+ }
+
+ function onApiEditCell(state) {
+ if (state == Asc.c_oAscCellEditorState.editStart){
+ api.isCellEdited = true;
+ editor.cell.nameDisabled(true);
+ } else if (state == Asc.c_oAscCellEditorState.editInCell) {
+ api.isCEditorFocused = 'clear';
+ } else if (state == Asc.c_oAscCellEditorState.editEnd) {
+ api.isCellEdited = false;
+ api.isCEditorFocused = false;
+ editor.cell.nameDisabled(false);
+ }
+ }
+
+ function setApi(apiF){
+ api=apiF;
+
+ api.isCEditorFocused = false;
+ api.asc_registerCallback('asc_onSelectionNameChanged', onApiCellSelection);
+ api.asc_registerCallback('asc_onEditCell', onApiEditCell);
+ }
+
+
+
+ return {
+ create: createController,
+ setApi: setApi
+ }
+
+})();
\ No newline at end of file
diff --git a/test/spreadsheeteditor/main/js/CellEditorView.js b/test/spreadsheeteditor/main/js/CellEditorView.js
new file mode 100644
index 000000000..9ee6e016e
--- /dev/null
+++ b/test/spreadsheeteditor/main/js/CellEditorView.js
@@ -0,0 +1,72 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2021
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+ */
+if (SSE === undefined) {
+ var SSE = {};
+}
+
+SSE.CellEditorView = new(function (){
+ var me;
+
+ function createView()
+ {
+ me=this;
+ me.$el = $('#cell-editing-box');
+ me.$cellcontent=$('#ce-cell-content');
+ me.$cellname = $('#ce-cell-name');
+
+ me.$cellname.on('focus', function(e){
+ var txt = me.$cellname[0];
+ txt.selectionStart = 0;
+ txt.selectionEnd = txt.value.length;
+ txt.scrollLeft = txt.scrollWidth;
+ });
+ }
+
+ function updateCellInfo(info) {
+ if (info) {
+ me.$cellname.val(typeof(info)=='string' ? info : info.asc_getName());
+ }
+ }
+
+ function cellNameDisabled(disabled){
+ (disabled) ? me.$cellname.attr('disabled', 'disabled') : me.$cellname.removeAttr('disabled');
+ }
+
+ return {
+ create: createView,
+ cell: {
+ updateInfo: updateCellInfo,
+ nameDisabled: cellNameDisabled
+ }
+ }
+})();
\ No newline at end of file
diff --git a/test/spreadsheeteditor/main/js/application.js b/test/spreadsheeteditor/main/js/application.js
new file mode 100644
index 000000000..00e21c9f8
--- /dev/null
+++ b/test/spreadsheeteditor/main/js/application.js
@@ -0,0 +1,40 @@
+/*
+ *
+ * (c) Copyright Ascensio System SIA 2010-2019
+ *
+ * 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-12 Ernesta Birznieka-Upisha
+ * 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
+ *
+*/
+(function ($) {
+
+ $(function(){
+ SSE.ApplicationView.create();
+ SSE.ApplicationController.create();
+ })
+
+})(window.jQuery);
diff --git a/test/spreadsheeteditor/main/resources/less/application.less b/test/spreadsheeteditor/main/resources/less/application.less
new file mode 100644
index 000000000..35840c55e
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/application.less
@@ -0,0 +1,56 @@
+// Common styles
+@import "../../../../common/main/resources/less/common.less";
+
+// Worksheets
+// -------------------------
+.viewer {
+ display: flex;
+ flex-direction: column;
+
+ .sdk-view {
+ position: relative;
+ flex-grow: 1;
+ }
+
+ ul.worksheet-list {
+ flex-grow: 0;
+ flex-shrink: 0;
+ margin: 0;
+ padding: 0 9px;
+ border-top: 1px solid #5A5A5A;
+ border-bottom: 1px solid #BABABA;
+ #gradient > .vertical(#B6B6B6, #CACACA);
+ box-shadow: 0 4px 4px -4px #333 inset;
+
+
+ li {
+ float: left;
+ cursor: pointer;
+ list-style: none;
+ margin: 0 2px 2px 3px;
+ padding: 0 13px;
+ color: #FFFFFF;
+ #gradient > .vertical(#9A9A9A, #828282);
+ box-shadow: 0 4px 4px -4px #333 inset;
+ -webkit-border-bottom-right-radius: 4px;
+// -moz-border-radius-bottomright: 4px;
+ border-bottom-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+// -moz-border-radius-bottomleft: 4px;
+ border-bottom-left-radius: 4px;
+
+ border-bottom: 1px solid #929292;
+ border-top-color: transparent;
+
+ &.active {
+ margin-top: -1px;
+ padding: 0 12px;
+ border: 1px solid #929292;
+ border-top-color: transparent;
+ background: #DDDDDD;
+ color: #000;
+ box-shadow: none;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/spreadsheeteditor/main/resources/less/asc-mixins.less b/test/spreadsheeteditor/main/resources/less/asc-mixins.less
new file mode 100644
index 000000000..e6e8a3d7b
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/asc-mixins.less
@@ -0,0 +1,373 @@
+*, *:before, *:after {
+ -moz-user-select: none;
+}
+
+:focus {
+ outline: none;
+}
+
+.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) {
+ background: @color;
+ background: -webkit-gradient(linear, left bottom,left top, color-stop(0, @start), color-stop(1, @stop));
+ background: -moz-linear-gradient(center bottom, @start 0%, @stop 100%);
+ background: -o-linear-gradient(@stop, @start);
+ background: linear-gradient(bottom, @start, @stop);
+}
+
+.box-shadow(@arguments) {
+ -webkit-box-shadow: @arguments;
+ box-shadow: @arguments;
+}
+
+.box-inner-shadow(@arguments) {
+ -webkit-box-shadow: inset @arguments;
+ box-shadow: inset @arguments;
+}
+
+.border-radius(@radius: 2px) {
+ border-radius: @radius;
+}
+
+.position(@type: absolute, @left: 0, @top: 0, @right: 0, @bottom: 0) {
+ position: @type;
+ left: @left;
+ top: @top;
+ right: @right;
+ bottom: @bottom;
+}
+
+.fontsize(@value) {
+ font-size: @value;
+}
+
+// User select
+.user-select(@select: none) {
+ -webkit-user-select: @select;
+ -moz-user-select: @select;
+ -ms-user-select: @select;
+// -o-user-select: @select;
+ user-select: @select;
+}
+
+.toolbar-btn-icon(@icon-class, @index, @icon-size, @offset-x: 0, @offset-y: 0) {
+ .@{icon-class} {background-position: 0 -(@index * @icon-size - @offset-y);}
+ .btn.active > .@{icon-class},
+ .btn:active > .@{icon-class} {background-position: (-1 * @icon-size - @offset-x) -(@index * @icon-size - @offset-y);}
+ .btn.disabled > .@{icon-class} {background-position: (-2 * @icon-size - @offset-x) -(@index * @icon-size - @offset-y);}
+}
+
+.toolbar-group-btn-icon(@icon-class, @index, @icon-size, @offset-x: 0, @offset-y: 0) {
+ .@{icon-class} {background-position: 0 -(@index * @icon-size - @offset-y);}
+ .btn-group.open > .@{icon-class},
+ .btn.active > .@{icon-class},
+ .btn:active > .@{icon-class} {background-position: (-1 * @icon-size - @offset-x) -(@index * @icon-size - @offset-y);}
+ .btn.disabled > .@{icon-class} {background-position: (-2 * @icon-size - @offset-x) -(@index * @icon-size - @offset-y);}
+}
+
+.menu-btn-icon(@icon-class, @index, @icon-size) {
+ .menu-item-icon.@{icon-class} {background-position: 0 -@index*@icon-size;}
+ li > a.checked > .menu-item-icon.@{icon-class} {background-position: -1*@icon-size -@index*@icon-size;}
+}
+
+.options-btn-icon(@icon-class, @index, @icon-size) {
+ .@{icon-class} {background-position: 0 -@index*@icon-size;}
+ button.over > .@{icon-class} {background-position: -1*@icon-size -@index*@icon-size;}
+// .btn-group.open > .@{icon-class},
+ button.active > .@{icon-class},
+ button:active > .@{icon-class} {background-position: -2*@icon-size -@index*@icon-size;}
+ button.disabled > .@{icon-class} {background-position: -3*@icon-size -@index*@icon-size;}
+}
+
+/**
+*/
+:root {
+ --bgX: 0px;
+
+ --pixel-ratio-factor: 1;
+
+ .pixel-ratio__1_5 {
+ @ratio: 1.5;
+ @one-px: 1px / @ratio;
+ @two-px: 2px / @ratio;
+
+ --pixel-ratio-factor: @ratio;
+ --scaled-one-pixel: @one-px;
+ --scaled-two-pixel: @two-px;
+ }
+
+ .pixel-ratio__2 {
+ }
+
+ .pixel-ratio__1_25 {
+ @ratio: 1.25;
+ @one-px: 1px / @ratio;
+ @two-px: 2px / @ratio;
+
+ --pixel-ratio-factor: @ratio;
+ --scaled-one-pixel: @one-px;
+ --scaled-two-pixel: @two-px;
+ }
+
+ .pixel-ratio__1_75 {
+ @ratio: 1.75;
+ @one-px: 1px / @ratio;
+ @two-px: 2px / @ratio;
+
+ --pixel-ratio-factor: @ratio;
+ --scaled-one-pixel: @one-px;
+ --scaled-two-pixel: @two-px;
+ }
+}
+
+.button-normal-icon(@icon-class, @index, @icon-size, @normal-h-offset: 0px) {
+ .@{icon-class} {
+ background-position: -0*@icon-size -@index*@icon-size;
+ background-position: @normal-h-offset -@index*@icon-size;
+ }
+}
+
+.button-otherstates-icon(@icon-class, @icon-size) {
+ .btn {
+ &:active, &.active {
+ &:not(:disabled):not(.disabled) {
+ > .@{icon-class} {
+ @iconsize: -1*@icon-size;
+
+ background-position-x: @iconsize;
+ --bgX: @iconsize;
+ }
+ }
+ }
+ }
+}
+
+.mx-button-otherstates-icon2(@offset) {
+ &.active, &:active{
+ &:not(:disabled):not(.disabled) {
+ .icon {
+ background-position-x: @offset;
+ }
+ }
+ }
+}
+
+.button-otherstates-icon2(@icon-class, @icon-size) {
+ button.@{icon-class} {
+ .mx-button-otherstates-icon2(@icon-size);
+ }
+}
+
+.menu-icon-normal(@icon-class, @index, @icon-size) {
+ .menu-item-icon.@{icon-class} {
+ background-position: 0 -@index*@icon-size;
+ background-position: var(--bgX) -@index*@icon-size;
+ }
+}
+
+.menu-otherstates-icon(@menu-class, @icon-size) {
+ .@{menu-class} li > a.checked > .menu-item-icon {background-position-x: -1*@icon-size; --bgX: calc(-1*@icon-size);}
+ .@{menu-class} li.disabled .menu-item-icon {background-position-x: -2*@icon-size; --bgX: calc(-2*@icon-size);}
+}
+
+/**/
+
+.background-ximage(@image, @image2x, @w: auto, @h: auto, @repeat: no-repeat) {
+ background-image: data-uri(%("%s",@image));
+ background-repeat: @repeat;
+
+ @media
+ only screen and (-webkit-min-device-pixel-ratio: 2),
+ only screen and (min-resolution: 2dppx),
+ only screen and (min-resolution: 192dpi) {
+ background-image: data-uri(%("%s",@image2x));
+ background-size: @w @h;
+ }
+}
+
+.choose-image-path(@fromcommon) when (@fromcommon = false) {
+ @path: if(@icon-src-base64, @app-image-path, @app-image-const-path);
+};
+
+.choose-image-path(@fromcommon) when (@fromcommon = true) {
+ @path: if(@icon-src-base64, @common-image-path, @common-image-const-path);
+}
+
+.background-ximage-v2(@image, @w: auto, @h: auto, @repeat: no-repeat, @commonimage: true) {
+ .choose-image-path(@commonimage);
+ @imagepath: '@{path}/@{image}';
+
+ background-image: if(@icon-src-base64, data-uri(%("%s", '@{imagepath}')), ~"url(@{imagepath})");
+ background-repeat: @repeat;
+
+ @1d5ximage: replace(@imagepath, '\.png$', '@1.5x.png');
+ @1d75ximage: replace(@imagepath, '\.png$', '@1.75x.png');
+ @1d25ximage: replace(@imagepath, '\.png$', '@1.25x.png');
+ @2ximage: replace(@imagepath, '\.png$', '@2x.png');
+
+ @media only screen {
+ @media (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.9),
+ (min-resolution: 1.5dppx) and (max-resolution: 1.9dppx),
+ (min-resolution: 144dpi) and (max-resolution: 191dpi)
+ {
+ background-image: ~"url(@{1d5ximage})";
+ background-size: @w @h;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 2),
+ (min-resolution: 2dppx),
+ (min-resolution: 192dpi)
+ {
+ background-image: ~"url(@{2ximage})";
+ background-size: @w @h;
+ }
+ }
+}
+
+.background-ximage-all(@image, @w: auto, @h: auto, @repeat: no-repeat, @commonimage: true) {
+ .choose-image-path(@commonimage);
+ @imagepath: '@{path}/@{image}';
+
+ background-image: if(@icon-src-base64, data-uri(%("%s", '@{imagepath}')), ~"url(@{imagepath})");
+ background-repeat: @repeat;
+
+ @1d5ximage: replace(@imagepath, '\.png$', '@1.5x.png');
+ @1d75ximage: replace(@imagepath, '\.png$', '@1.75x.png');
+ @1d25ximage: replace(@imagepath, '\.png$', '@1.25x.png');
+ @2ximage: replace(@imagepath, '\.png$', '@2x.png');
+
+ @media only screen {
+ @media (-webkit-min-device-pixel-ratio: 1.25) and (-webkit-max-device-pixel-ratio: 1.49),
+ (min-resolution: 1.25dppx) and (max-resolution: 1.49dppx),
+ (min-resolution: 120dpi) and (max-resolution: 143dpi)
+ {
+ background-image: ~"url(@{1d25ximage})";
+ background-size: @w @h;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.74),
+ (min-resolution: 1.5dppx) and (max-resolution: 1.74dppx),
+ (min-resolution: 144dpi) and (max-resolution: 167dpi)
+ {
+ background-image: ~"url(@{1d5ximage})";
+ background-size: @w @h;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 1.75) and (-webkit-max-device-pixel-ratio: 1.9),
+ (min-resolution: 1.75dppx) and (max-resolution: 1.9dppx),
+ (min-resolution: 168dpi) and (max-resolution: 191dpi)
+ {
+ background-image: ~"url(@{1d75ximage})";
+ background-size: @w @h;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 2),
+ (min-resolution: 2dppx),
+ (min-resolution: 192dpi)
+ {
+ background-image: ~"url(@{2ximage})";
+ background-size: @w @h;
+ }
+ }
+}
+
+.img-commonctrl {
+ &.img-colored {
+ filter: none;
+ }
+}
+
+@common-controls-width: 100px;
+.img-commonctrl,
+ .dropdown-menu li .checked:before, .input-error:before, .input-warning:before,
+ .btn-toolbar .icon.img-commonctrl, .list-item div.checked:before
+{
+ background-image: if(@icon-src-base64, data-uri(%("%s",'@{common-image-path}/@{common-controls}')), ~"url(@{common-image-const-path}/@{common-controls})");
+ background-repeat: no-repeat;
+ filter: @component-normal-icon-filter;
+
+ @1d25ximage: replace(@common-controls, '\.png$', '@1.25x.png');
+ @1d5ximage: replace(@common-controls, '\.png$', '@1.5x.png');
+ @1d75ximage: replace(@common-controls, '\.png$', '@1.75x.png');
+ @2ximage: replace(@common-controls, '\.png$', '@2x.png');
+
+ @media only screen {
+ @media (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.9),
+ (min-resolution: 1.5dppx) and (max-resolution: 1.9dppx),
+ (min-resolution: 144dpi) and (max-resolution: 191dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/@{1d5ximage})";
+ background-size: @common-controls-width auto;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 2),
+ (min-resolution: 2dppx),
+ (min-resolution: 192dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/@{2ximage})";
+ background-size: @common-controls-width auto;
+ }
+ }
+
+ .pixel-ratio__1_25 & {
+ background-image: ~"url(@{common-image-const-path}/@{1d25ximage})";
+ background-size: @common-controls-width auto;
+ }
+
+ .pixel-ratio__1_75 & {
+ background-image: ~"url(@{common-image-const-path}/@{1d75ximage})";
+ background-size: @common-controls-width auto;
+ }
+}
+
+@img-colorpicker-width: 205px;
+.img-colorpicker, .hsb-colorpicker .empty-color:before
+{
+ background-image: if(@icon-src-base64, data-uri(%("%s",'@{common-image-path}/hsbcolorpicker/hsb-colorpicker.png')), ~"url(@{common-image-const-path}/hsbcolorpicker/hsb-colorpicker.png)");
+ background-repeat: no-repeat;
+
+ @media only screen {
+ @media (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.9),
+ (min-resolution: 1.5dppx) and (max-resolution: 1.9dppx),
+ (min-resolution: 144dpi) and (max-resolution: 191dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/hsbcolorpicker/hsb-colorpicker@1.5x.png)";
+ background-size: @img-colorpicker-width auto;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 2),
+ (min-resolution: 2dppx),
+ (min-resolution: 192dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/hsbcolorpicker/hsb-colorpicker@2x.png)";
+ background-size: @img-colorpicker-width auto;
+ }
+ }
+}
+
+.icon.lang-flag {
+ @img-flags-width: 48px;
+
+ width: 16px;
+ height: 12px;
+
+ background-image: if(@icon-src-base64, data-uri(%("%s",'@{common-image-path}/controls/flags.png')), ~"url(@{common-image-const-path}/controls/flags.png)");
+ background-repeat: no-repeat;
+
+ @media only screen {
+ @media (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 1.9),
+ (min-resolution: 1.5dppx) and (max-resolution: 1.9dppx),
+ (min-resolution: 144dpi) and (max-resolution: 191dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/controls/flags@1.5x.png)";
+ background-size: @img-flags-width auto;
+ }
+
+ @media (-webkit-min-device-pixel-ratio: 2),
+ (min-resolution: 2dppx),
+ (min-resolution: 192dpi)
+ {
+ background-image: ~"url(@{common-image-const-path}/controls/flags@2x.png)";
+ background-size: @img-flags-width auto;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/spreadsheeteditor/main/resources/less/celleditor.less b/test/spreadsheeteditor/main/resources/less/celleditor.less
new file mode 100644
index 000000000..f278663c8
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/celleditor.less
@@ -0,0 +1,167 @@
+// Common styles
+@import "colors-table-ie-fix.less";
+@import "variables.less";
+@import "colors-table.less";
+@import "asc-mixins.less";
+#cell-editing-box {
+ border-bottom: solid @scaled-one-px-value-ie @border-toolbar-ie;
+ border-bottom: solid @scaled-one-px-value @border-toolbar;
+ border-left: solid @scaled-one-px-value-ie @border-toolbar-ie;
+ border-left: solid @scaled-one-px-value @border-toolbar;
+ min-height: 20px;
+ background-color: @background-toolbar-ie;
+ background-color: @background-toolbar;
+
+ .ce-group-name {
+ float: left;
+ height: 20px;
+ background-color: @background-toolbar-ie;
+ background-color: @background-toolbar;
+
+ #ce-cell-name {
+ width: 100px;
+ height: 19px;
+ //height: calc(19px + (1px - 1px/var(--pixel-ratio-factor,1)));
+ padding: 0px 19px 0 4px;
+ vertical-align: top;
+ display: inline-block;
+ border: 0 none;
+ border-right: @scaled-one-px-value-ie solid @border-toolbar-ie;
+ border-right: @scaled-one-px-value solid @border-toolbar;
+ transition: none;
+ -webkit-transition: none;
+ box-shadow: 0 @scaled-one-px-value-ie 0 0 @border-toolbar-ie;
+ box-shadow: 0 @scaled-one-px-value 0 0 @border-toolbar;
+
+ &[disabled] {
+ color: @border-preview-select-ie;
+ color: @border-preview-select;
+ opacity: 0.5;
+ }
+ }
+
+ #ce-cell-name-menu {
+ display: inline-block;
+ position: absolute;
+ left: 80px;
+ background-color: @background-toolbar-ie;
+ background-color: @background-toolbar;
+
+ button {
+ background-color: @background-normal-ie;
+ background-color: @background-normal;
+ height: 19px;
+
+ &.disabled {
+ opacity: 0.5;
+ }
+
+ &:active:not(.disabled),
+ &.active:not(.disabled){
+ .caret {
+ border-color: @icon-normal;
+ }
+ }
+ }
+
+ .dropdown-menu a {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+
+ #ce-func-label {
+ height: 20px;
+ margin-left: -3px;
+ .border-radius(0);
+
+ &.disabled {
+ opacity: 0.4;
+ }
+ }
+ }
+
+ &:not(.expanded) {
+ #ce-func-label {
+ border-bottom: @scaled-one-px-value-ie solid @border-toolbar-ie;
+ border-bottom: @scaled-one-px-value solid @border-toolbar;
+ }
+ }
+
+ .ce-group-expand {
+ float: right;
+ //height: 20px;
+ height: 100%;
+ background-color: @background-normal-ie;
+ background-color: @background-normal;
+ }
+
+ .ce-group-content {
+ margin: 0 2px 0 120px;
+ height: 100%;
+ border-left: @scaled-one-px-value-ie solid @border-toolbar-ie;
+ border-left: @scaled-one-px-value solid @border-toolbar;
+ #ce-cell-content {
+ height: 100%;
+ resize: none;
+ min-height: 19px;
+ border: 0 none;
+ font-size: 12px;
+ line-height: 18px;
+ padding-bottom: 0;
+ padding-top: 0;
+ &[disabled] {
+ color: @border-preview-select-ie;
+ color: @border-preview-select;
+ opacity: 0.5;
+ }
+ }
+ }
+
+ #ce-cell-name, #ce-cell-content {
+ border-radius: 0;
+ }
+
+ &+.layout-resizer {
+ border-top: 0 none;
+ border-bottom: 0 none;
+
+ &.move {
+ border-top: @scaled-one-px-value-ie solid @border-toolbar-ie;
+ border-top: @scaled-one-px-value solid @border-toolbar;
+ border-bottom: @scaled-one-px-value-ie solid @border-toolbar-ie;
+ border-bottom: @scaled-one-px-value solid @border-toolbar;
+ opacity: 0.4;
+ }
+ }
+}
+
+#ce-btn-expand {
+ width: 16px;
+ height: 18px;
+ .border-radius(0);
+ background: transparent;
+ padding: 0 2px 0;
+
+ .caret {
+ transition: transform .2s;
+ border-color: @icon-normal;
+ }
+
+ &.btn-collapse {
+ .caret {
+ transform: rotate(45deg);
+ }
+ }
+}
+
+.layout-resizer {
+ z-index: @zindex-dropdown - 10;
+ background: @background-toolbar-ie;
+ background: @background-toolbar;
+ border: 0 none;
+
+ &.move {
+ opacity: 0.4;
+ }
+}
diff --git a/test/spreadsheeteditor/main/resources/less/colors-table-ie-fix.less b/test/spreadsheeteditor/main/resources/less/colors-table-ie-fix.less
new file mode 100644
index 000000000..442ff10da
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/colors-table-ie-fix.less
@@ -0,0 +1,70 @@
+
+@toolbar-header-document-ie: #446995;
+@toolbar-header-spreadsheet-ie: #40865c;
+@toolbar-header-presentation-ie: #aa5252;
+
+@background-normal-ie: #fff;
+@background-toolbar-ie: #f1f1f1;
+@background-toolbar-additional-ie: #f1f1f1;
+@background-primary-dialog-button-ie: #7d858c;
+@background-tab-underline-ie: #444;
+@background-notification-popover-ie: #fcfed7;
+@background-notification-badge-ie: #ffd112;
+@background-scrim-ie: fade(#000, 20%);
+@background-loader-ie: fade(#000, 65%);
+@background-alt-key-hint-ie: #FFD938;
+
+@highlight-button-hover-ie: #d8dadc;
+@highlight-button-pressed-ie: #7d858c;
+@highlight-button-pressed-hover-ie: #7d858c;
+@highlight-primary-dialog-button-hover-ie: #666d73;
+@highlight-header-button-hover-ie: fade(#fff, 20%);
+@highlight-header-button-pressed-ie: fade(#000, 20%);
+@highlight-toolbar-tab-underline-ie: #444;
+@highlight-text-select-ie: #3494fb;
+
+@border-toolbar-ie: #cbcbcb;
+@border-divider-ie: #cbcbcb;
+@border-regular-control-ie: #cfcfcf;
+@border-toolbar-button-hover-ie: #d8dadc;
+@border-preview-hover-ie: #cfcfcf;
+@border-preview-select-ie: #848484;
+@border-control-focus-ie: #848484;
+@border-color-shading-ie: fade(#000, 20%);
+@border-error-ie: #d9534f;
+
+@text-normal-ie: #444;
+@text-normal-pressed-ie: #fff;
+@text-secondary-ie: #a5a5a5;
+@text-tertiary-ie: #a5a5a5;
+@text-link-ie: #acbfff;
+@text-inverse-ie: #fff;
+@text-toolbar-header-ie: #fff;
+@text-contrast-background-ie: #fff;
+
+@icon-normal-ie: #444;
+@icon-normal-pressed-ie: #fff;
+@icon-inverse-ie: #444;
+@icon-toolbar-header-ie: fade(#fff, 80%);
+@icon-notification-badge-ie: #000;
+@icon-contrast-popover-ie: #fff;
+@icon-success-ie: #5b9f27;
+
+@canvas-scroll-thumb-hover-ie: #c0c0c0;
+@canvas-scroll-thumb-border-hover-ie: #cbcbcb;
+
+@button-header-normal-icon-offset-x-ie: -20px;
+@button-header-active-icon-offset-x-ie: -20px;
+@scaled-one-px-value-ie: 1px;
+
+@component-disabled-opacity-ie: .4;
+
+/*.ie {
+ .toolbar__icon.toolbar__icon-big {
+ @big-icon-background-image-ie: ~"url(@{app-image-const-path}/iconsbig.png)";
+ background-image: @big-icon-background-image-ie;
+ }
+}*/
+
+//@huge-icon-background-image-ie: ~"url(@{app-image-const-path}/iconshuge.png)";
+
diff --git a/test/spreadsheeteditor/main/resources/less/colors-table.less b/test/spreadsheeteditor/main/resources/less/colors-table.less
new file mode 100644
index 000000000..7c0c7e4d4
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/colors-table.less
@@ -0,0 +1,239 @@
+@import "colors-table-ie-fix.less";
+
+// Brand colors
+// -------------------------
+
+@brand-primary: #428bca;
+@brand-success: #5cb85c;
+@brand-warning: #f0ad4e;
+@brand-danger: #d9534f;
+@brand-info: #5bc0de;
+
+
+:root {
+ --toolbar-header-document: #446995;
+ --toolbar-header-spreadsheet: #40865c;
+ --toolbar-header-presentation: #aa5252;
+
+ --background-normal: #fff;
+ --background-toolbar: #f7f7f7;
+ --background-toolbar-additional: #efefef;
+ --background-primary-dialog-button: #444;
+ --background-tab-underline: #444;
+ --background-notification-popover: #fcfed7;
+ --background-notification-badge: #ffd112;
+ --background-scrim: fade(#000, 20%);
+ --background-loader: fade(#181818, 90%);
+ --background-alt-key-hint: #FFD938;
+
+ --highlight-button-hover: #e0e0e0;
+ --highlight-button-pressed: #cbcbcb;
+ --highlight-button-pressed-hover: #bababa;
+ --highlight-primary-dialog-button-hover: #1c1c1c;
+ --highlight-header-button-hover: fade(#fff, 15%);
+ --highlight-header-button-pressed: fade(#fff, 25%);
+ --highlight-toolbar-tab-underline: #444;
+ --highlight-text-select: #3494fb;
+
+ --border-toolbar: #cbcbcb;
+ --border-divider: #dfdfdf;
+ --border-regular-control: #c0c0c0;
+ --border-toolbar-button-hover: #e0e0e0;
+ --border-preview-hover: #bababa;
+ --border-preview-select: #888;
+ --border-control-focus: #848484;
+ --border-color-shading: fade(#000, 15%);
+ --border-error: #f62211;
+
+ --text-normal: fade(#000, 80%);
+ --text-normal-pressed: fade(#000, 80%);
+ --text-secondary: fade(#000, 60%);
+ --text-tertiary: fade(#000, 40%);
+ --text-link: #445799;
+ --text-link-hover: #445799;
+ --text-link-active: #445799;
+ --text-link-visited: #445799;
+ --text-inverse: #fff;
+ --text-toolbar-header: #fff;
+ --text-contrast-background: #fff;
+
+ --icon-normal: #444;
+ --icon-normal-pressed: #444;
+ --icon-inverse: #fff;
+ --icon-toolbar-header: #fff;
+ --icon-notification-badge: #000;
+ --icon-contrast-popover: #fff;
+ --icon-success: #090;
+
+ // Canvas
+
+ --canvas-background: #eee;
+ --canvas-content-background: #fff;
+ --canvas-page-border: #ccc;
+
+ --canvas-ruler-background: #fff;
+ --canvas-ruler-margins-background: #d9d9d9;
+ --canvas-ruler-mark: #555;
+ --canvas-ruler-handle-border: #555;
+ --canvas-ruler-handle-border-disabled: #aaa;
+
+ --canvas-high-contrast: #000;
+ --canvas-high-contrast-disabled: #666;
+
+ --canvas-cell-border: fade(#000, 10%);
+ --canvas-cell-title-hover: #dfdfdf;
+ --canvas-cell-title-selected: #cfcfcf;
+ --canvas-cell-title-border: #d8d8d8;
+ --canvas-cell-title-border-hover: #c9c9c9;
+ --canvas-cell-title-border-selected: #bbb;
+
+ --canvas-dark-cell-title: #444;
+ --canvas-dark-cell-title-hover: #666 ;
+ --canvas-dark-cell-title-selected: #111;
+ --canvas-dark-cell-title-border: #3d3d3d;
+ --canvas-dark-cell-title-border-hover: #5c5c5c;
+ --canvas-dark-cell-title-border-selected: #0f0f0f;
+
+ --canvas-scroll-thumb: #f7f7f7;
+ --canvas-scroll-thumb-hover: #c0c0c0;
+ --canvas-scroll-thumb-pressed: #adadad;
+ --canvas-scroll-thumb-border: #cbcbcb;
+ --canvas-scroll-thumb-border-hover: #cbcbcb;
+ --canvas-scroll-thumb-border-pressed: #adadad;
+ --canvas-scroll-arrow: #adadad;
+ --canvas-scroll-arrow-hover: #f7f7f7;
+ --canvas-scroll-arrow-pressed: #f7f7f7;
+ --canvas-scroll-thumb-target: #c0c0c0;
+ --canvas-scroll-thumb-target-hover: #f7f7f7;
+ --canvas-scroll-thumb-target-pressed: #f7f7f7;
+
+ // Others
+
+ //--button-small-normal-icon-offset-x: 0;
+ //--button-small-active-icon-offset-x: 0;
+ //--button-large-normal-icon-offset-x: 0;
+ //--button-large-active-icon-offset-x: 0;
+ //--button-huge-normal-icon-offset-x: 0;
+ //--button-huge-active-icon-offset-x: 0;
+ //--button-xhuge-normal-icon-offset-x: 0;
+ //--button-xhuge-active-icon-offset-x: 0;
+ --button-header-normal-icon-offset-x: -20px;
+ --button-header-active-icon-offset-x: -20px;
+ //--menu-icon-item-checked-offset-x: 0;
+
+ --modal-window-mask-opacity: 0.2;
+ --image-border-types-filter: none;
+ --image-border-types-filter-selected: none;
+ --component-normal-icon-filter: none;
+
+ --component-normal-icon-opacity: .8;
+ --component-hover-icon-opacity: .8;
+ --component-active-icon-opacity: 1;
+ --component-active-hover-icon-opacity: 1;
+ --component-disabled-opacity: .4;
+
+ --header-component-normal-icon-opacity: 1;
+ --header-component-hover-icon-opacity: 1;
+ --header-component-active-icon-opacity: 1;
+ --header-component-active-hover-icon-opacity: 1;
+ //--button-icon-opacity: 1;
+}
+
+// Background
+// -------------------------
+@background-normal: var(--background-normal);
+@background-toolbar: var(--background-toolbar);
+@background-toolbar-additional: var(--background-toolbar-additional);
+@background-primary-dialog-button: var(--background-primary-dialog-button);
+@background-tab-underline: var(--background-tab-underline);
+@background-notification-popover: var(--background-notification-popover);
+@background-notification-badge: var(--background-notification-badge);
+@background-scrim: var(--background-scrim);
+@background-loader: var(--background-loader);
+@background-alt-key-hint: var(--background-alt-key-hint);
+
+// Highlight
+// -------------------------
+@highlight-button-hover: var(--highlight-button-hover);
+@highlight-button-pressed: var(--highlight-button-pressed);
+@highlight-button-pressed-hover: var(--highlight-button-pressed-hover);
+@highlight-primary-dialog-button-hover: var(--highlight-primary-dialog-button-hover);
+@highlight-header-button-hover: var(--highlight-header-button-hover);
+@highlight-header-button-pressed: var(--highlight-header-button-pressed);
+@highlight-toolbar-tab-underline: var(--highlight-toolbar-tab-underline);
+@highlight-text-select: var(--highlight-text-select);
+
+// Border
+// -------------------------
+@border-toolbar: var(--border-toolbar);
+@border-divider: var(--border-divider);
+@border-regular-control: var(--border-regular-control);
+@border-toolbar-button-hover: var(--border-toolbar-button-hover);
+@border-preview-hover: var(--border-preview-hover);
+@border-preview-select: var(--border-preview-select);
+@border-control-focus: var(--border-control-focus);
+@border-color-shading: var(--border-color-shading);
+@border-error: var(--border-error);
+
+// Text
+// -------------------------
+@text-normal: var(--text-normal);
+@text-normal-pressed: var(--text-normal-pressed);
+@text-secondary: var(--text-secondary);
+@text-tertiary: var(--text-tertiary);
+@text-link: var(--text-link);
+@text-link-hover: var(--text-link-hover);
+@text-link-active: var(--text-link-active);
+@text-link-visited: var(--text-link-visited);
+@text-inverse: var(--text-inverse);
+@text-toolbar-header: var(--text-toolbar-header);
+@text-contrast-background: var(--text-contrast-background);
+@text-alt-key-hint: var(--text-alt-key-hint);
+
+// Icon
+// -------------------------
+@icon-normal: var(--icon-normal);
+@icon-normal-pressed: var(--icon-normal-pressed);
+@icon-inverse: var(--icon-inverse);
+@icon-toolbar-header: var(--icon-toolbar-header);
+@icon-contrast-popover: var(--icon-contrast-popover);
+@icon-notification-badge: var(--icon-notification-badge);
+@icon-success: var(--icon-success);
+
+@button-small-normal-icon-offset-x: var(--button-small-normal-icon-offset-x,0);
+@button-small-active-icon-offset-x: var(--button-small-active-icon-offset-x,0);
+@button-large-normal-icon-offset-x: var(--button-large-normal-icon-offset-x, 0);
+@button-large-active-icon-offset-x: var(--button-large-active-icon-offset-x, 0);
+@button-huge-normal-icon-offset-x: var(--button-huge-normal-icon-offset-x, 0);
+@button-xhuge-normal-icon-offset-x: var(--button-xhuge-normal-icon-offset-x, 0);
+@button-xhuge-active-icon-offset-x: var(--button-xhuge-active-icon-offset-x, 0);
+//@button-huge-normal-icon-offset-x: var(--button-huge-normal-icon-offset-x, 0);
+//@button-huge-active-icon-offset-x: var(--button-huge-active-icon-offset-x, 0);
+
+@button-header-normal-icon-offset-x: var(--button-header-normal-icon-offset-x, -20px);
+@button-header-active-icon-offset-x: var(--button-header-active-icon-offset-x, -20px);
+
+@component-normal-icon-filter: var(--component-normal-icon-filter);
+@component-normal-icon-opacity: var(--component-normal-icon-opacity, .8);
+@component-hover-icon-opacity: var(--component-hover-icon-opacity, .8);
+@component-active-icon-opacity: var(--component-active-icon-opacity, .8);
+@component-active-hover-icon-opacity: var(--component-active-hover-icon-opacity, .8);
+@component-disabled-opacity: var(--component-disabled-opacity, .4);
+//@button-icon-opacity: var(--button-icon-opacity, 1);
+
+@header-component-normal-icon-opacity: var(--header-component-normal-icon-opacity, 1);
+@header-component-hover-icon-opacity: var(--header-component-hover-icon-opacity, 1);
+@header-component-active-icon-opacity: var(--header-component-active-icon-opacity, 1);
+@header-component-active-hover-icon-opacity: var(--header-component-active-hover-icon-opacity, 1);
+
+@menu-icon-item-checked-offset-x: var(--menu-icon-item-checked-offset-x, 0);
+@img-border-type-filter: var(--image-border-types-filter, none);
+@img-border-type-filter-selected: var(--image-border-types-filter-selected, none);
+
+// Canvas
+// ---------------------------
+@canvas-background: var(--canvas-background);
+@canvas-content-background: var(--canvas-content-background);
+@canvas-page-border: var(--canvas-page-border);
+@canvas-scroll-thumb-hover: var(--canvas-scroll-thumb-hover);
+@canvas-scroll-thumb-border-hover: var(--canvas-scroll-thumb-border-hover);
diff --git a/test/spreadsheeteditor/main/resources/less/variables.less b/test/spreadsheeteditor/main/resources/less/variables.less
new file mode 100644
index 000000000..42eac33a7
--- /dev/null
+++ b/test/spreadsheeteditor/main/resources/less/variables.less
@@ -0,0 +1,799 @@
+//
+// Global values
+// --------------------------------------------------
+@pixel-ratio-factor: var(--pixel-ratio-factor, 1);
+@scaled-one-px-value: var(--scaled-one-pixel, 1px);
+@scaled-two-px-value: var(--scaled-two-pixel, 2px);
+
+// Paths
+// -------------------------
+
+@app-image-path: "../../resources/img"; // use for data-uri(...)
+@common-image-path: "../../../../common/main/resources/img"; // use for data-uri(...)
+@app-image-const-path: "resources/img"; // use for url(...)
+@common-image-const-path: "../../common/main/resources/img"; // use for url(...)
+
+// Grays
+// -------------------------
+
+//@gray-deep: #444444; //rgb(68, 68, 68)
+//@gray-darker: #848484; //rgb(132, 132, 132)
+//@gray-dark: #cbcbcb; //rgb(203, 203, 203)
+//@gray: #cfcfcf; //rgb(207, 207, 207)
+//@gray-light: #f1f1f1; //rgb(241, 241, 241)
+//@gray-lighter: #ededed; //rgb(237, 237, 237)
+//@gray-soft: #adadad; //rgb(173, 173, 173)
+
+//@primary: #7d858c; //rgb(125, 133, 140)
+//@primary-hover: #666d73; //rgb(102, 109, 115)
+//@secondary: #d8dadc; //rgb(216, 218, 220)
+//@secondary-hover: #cbced1; //rgb(203, 206, 209)
+
+//@black: #000000;
+
+// Brand colors
+// -------------------------
+
+@brand-primary: #428bca;
+@brand-success: #5cb85c;
+@brand-warning: #f0ad4e;
+@brand-danger: #d9534f;
+@brand-info: #5bc0de;
+
+// Scaffolding
+// -------------------------
+
+@body-bg: #fff;
+@text-color: #cbcbcb; // @gray-dark
+
+// Links
+// -------------------------
+
+@link-color: @brand-primary;
+@link-hover-color: darken(@link-color, 15%);
+@link-hover-decoration: underline;
+
+// Typography
+// -------------------------
+
+@font-family-sans-serif: Arial, Helvetica, "Helvetica Neue", sans-serif;
+@font-family-serif: Georgia, "Times New Roman", Times, serif;
+@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
+@font-family-tahoma: tahoma, arial, verdana, sans-serif;
+@font-family-base: @font-family-sans-serif;
+
+@font-size-base: 11px;
+@font-size-large: 13px;
+@font-size-small: 9px;
+
+@font-size-h1: floor(@font-size-base * 2.6);
+@font-size-h2: floor(@font-size-base * 2.15);
+@font-size-h3: ceil(@font-size-base * 1.7);
+@font-size-h4: ceil(@font-size-base * 1.25);
+@font-size-h5: @font-size-base;
+@font-size-h6: ceil(@font-size-base * 0.85);
+
+@line-height-base: 1.428571429; // 20/14
+@line-height-computed: floor(@font-size-base * @line-height-base);
+
+@headings-font-family: @font-family-base;
+@headings-font-weight: 500;
+@headings-line-height: 1.1;
+@headings-color: inherit;
+
+
+// Iconography
+// -------------------------
+
+@icon-font-path: "../fonts/";
+@icon-font-name: "glyphicons-halflings-regular";
+@icon-font-svg-id: "glyphicons_halflingsregular";
+
+@icon-src-base64: false;
+@huge-icon-size: 37px;
+@x-huge-icon-size: 45px;
+
+// Components
+// -------------------------
+// Based on 14px font-size and 1.428 line-height (~20px to start)
+
+@padding-base-vertical: 1px;
+@padding-base-horizontal: 3px;
+
+@padding-large-vertical: 10px;
+@padding-large-horizontal: 16px;
+
+@padding-small-vertical: 1px;
+@padding-small-horizontal: 3px;
+
+@padding-xs-vertical: 1px;
+@padding-xs-horizontal: 5px;
+
+@line-height-large: 1.33;
+@line-height-small: 1.5;
+
+@border-radius-base: 4px;
+@border-radius-large: 6px;
+@border-radius-small: 2px;
+
+@component-active-color: #fff;
+@component-active-bg: #7d858c; // @primary;
+
+@caret-width-base: 4px;
+@caret-width-large: 5px;
+
+// Tables
+// -------------------------
+
+@table-cell-padding: 8px;
+@table-condensed-cell-padding: 5px;
+
+@table-bg: transparent; // overall background-color
+@table-bg-accent: #f9f9f9; // for striping
+@table-bg-hover: #f5f5f5;
+@table-bg-active: @table-bg-hover;
+
+@table-border-color: #ddd; // table and cell border
+
+
+// Buttons
+// -------------------------
+
+@btn-font-weight: normal;
+
+@btn-default-color: #333;
+@btn-default-bg: #fff;
+@btn-default-border: #ccc;
+
+@btn-primary-color: #fff;
+@btn-primary-bg: @brand-primary;
+@btn-primary-border: darken(@btn-primary-bg, 5%);
+
+@btn-success-color: #fff;
+@btn-success-bg: @brand-success;
+@btn-success-border: darken(@btn-success-bg, 5%);
+
+@btn-warning-color: #fff;
+@btn-warning-bg: @brand-warning;
+@btn-warning-border: darken(@btn-warning-bg, 5%);
+
+@btn-danger-color: #fff;
+@btn-danger-bg: @brand-danger;
+@btn-danger-border: darken(@btn-danger-bg, 5%);
+
+@btn-info-color: #fff;
+@btn-info-bg: @brand-info;
+@btn-info-border: darken(@btn-info-bg, 5%);
+
+@btn-link-disabled-color: #f1f1f1; // @gray-light;
+
+// Allows for customizing button radius independently from global border radius
+@btn-border-radius-base: @border-radius-base;
+@btn-border-radius-large: @border-radius-large;
+@btn-border-radius-small: @border-radius-small;
+
+// Forms
+// -------------------------
+
+@input-bg: #fff;
+@input-bg-disabled: #ededed; // @gray-lighter;
+
+@input-color: #000;
+@input-border: #cfcfcf; // @gray;
+@input-border-radius: @border-radius-base;
+@input-border-radius-large: @border-radius-large;
+@input-border-radius-small: @border-radius-small;
+@input-border-focus: #66afe9;
+
+// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
+//** Default `.form-control` border radius
+// This has no effect on `