Merge branch 'release/v9.1.0'
# Conflicts: # .github/workflows/rebuild-macros-tips.yaml
@ -513,7 +513,7 @@
|
||||
|
||||
if (typeof _config.document.fileType === 'string' && _config.document.fileType != '') {
|
||||
_config.document.fileType = _config.document.fileType.toLowerCase();
|
||||
var type = /^(?:(xls|xlsx|ods|csv|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb|sxc|et|ett|numbers)|(pps|ppsx|ppt|pptx|odp|gslides|pot|potm|potx|ppsm|pptm|fodp|otp|sxi|dps|dpt|key|odg)|(pdf|djvu|xps|oxps)|(doc|docx|odt|gdoc|txt|rtf|mht|htm|html|mhtml|epub|docm|dot|dotm|dotx|fodt|ott|fb2|xml|oform|docxf|sxw|stw|wps|wpt|pages|hwp|hwpx|md)|(vsdx|vssx|vstx|vsdm|vssm|vstm))$/
|
||||
var type = /^(?:(xls|xlsx|ods|csv|gsheet|xlsm|xlt|xltm|xltx|fods|ots|xlsb|sxc|et|ett|numbers)|(pps|ppsx|ppt|pptx|odp|gslides|pot|potm|potx|ppsm|pptm|fodp|otp|sxi|dps|dpt|key|odg)|(pdf|djvu|xps|oxps)|(doc|docx|odt|gdoc|txt|rtf|mht|htm|html|mhtml|epub|docm|dot|dotm|dotx|fodt|ott|fb2|xml|oform|docxf|sxw|stw|wps|wpt|pages|hwp|hwpx|md|hml)|(vsdx|vssx|vstx|vsdm|vssm|vstm))$/
|
||||
.exec(_config.document.fileType);
|
||||
if (!type) {
|
||||
window.alert("The \"document.fileType\" parameter for the config object is invalid. Please correct it.");
|
||||
@ -669,16 +669,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
var _processSaveResult = function(result, message) {
|
||||
_sendCommand({
|
||||
command: 'processSaveResult',
|
||||
data: {
|
||||
result: result,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: remove processRightsChange, use denyEditingRights
|
||||
var _processRightsChange = function(enabled, message) {
|
||||
_sendCommand({
|
||||
@ -903,7 +893,6 @@
|
||||
|
||||
return {
|
||||
showMessage : _showMessage,
|
||||
processSaveResult : _processSaveResult,
|
||||
processRightsChange : _processRightsChange,
|
||||
denyEditingRights : _denyEditingRights,
|
||||
refreshHistory : _refreshHistory,
|
||||
|
||||
@ -313,10 +313,13 @@ div {
|
||||
fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType;
|
||||
fileType = fileType.toLowerCase();
|
||||
let customizationClose = !!(fileInfo.ClosePostMessage || fileInfo.CloseUrl);
|
||||
const canEdit = (fileInfo.UserCanOnlyComment || fileInfo.UserCanWrite || fileInfo.UserCanReview);
|
||||
//connector Nextcloud Office 8.4.5 (SupportsUpdate=undefined, UserCanWrite=true, UserCanNotWriteRelative=false)
|
||||
let customizationSaveAs = (fileInfo.SupportsUpdate || fileInfo.UserCanWrite) && !fileInfo.UserCanNotWriteRelative;
|
||||
let customizationSaveAs = (fileInfo.SupportsUpdate || canEdit) && !fileInfo.UserCanNotWriteRelative;
|
||||
let customizationFormSubmit = queryParams.formsubmit === "1";
|
||||
let permissionsEdit = !fileInfo.ReadOnly && fileInfo.UserCanWrite && !customizationFormSubmit;
|
||||
let permissionsEdit = !fileInfo.ReadOnly && (!fileInfo.UserCanOnlyComment && fileInfo.UserCanWrite) && !customizationFormSubmit;
|
||||
const permissionsReview = (fileInfo.UserCanOnlyComment || fileInfo.SupportsReviewing===false) ? false : (fileInfo.UserCanReview===false ? false : fileInfo.UserCanReview);
|
||||
const permissionsComment = permissionsEdit || !!fileInfo.UserCanOnlyComment;
|
||||
let permissionsFillForm = permissionsEdit || customizationFormSubmit;
|
||||
sessionId = userAuth.userSessionId;
|
||||
var config = {
|
||||
@ -346,7 +349,8 @@ div {
|
||||
},
|
||||
"permissions": {
|
||||
"edit": permissionsEdit,
|
||||
"review": (fileInfo.SupportsReviewing===false) ? false : (fileInfo.UserCanReview===false ? false : fileInfo.UserCanReview),
|
||||
"review": permissionsReview,
|
||||
"comment": permissionsComment,
|
||||
"copy": fileInfo.CopyPasteRestrictions!=="CurrentDocumentOnly" && fileInfo.CopyPasteRestrictions!=="BlockAll",
|
||||
"print": !fileInfo.DisablePrint && !fileInfo.HidePrintOption,
|
||||
"chat": queryParams.dchat!=="1",
|
||||
|
||||
@ -59,10 +59,6 @@ if (window.Common === undefined) {
|
||||
$me.trigger('applyeditrights', data);
|
||||
},
|
||||
|
||||
'processSaveResult': function(data) {
|
||||
$me.trigger('processsaveresult', data);
|
||||
},
|
||||
|
||||
'processRightsChange': function(data) {
|
||||
$me.trigger('processrightschange', data);
|
||||
},
|
||||
|
||||
350
apps/common/embed/lib/controller/Shortcuts.js
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2024
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
* version 3 as published by the Free Software Foundation. In accordance with
|
||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||
* of any third-party rights.
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
*
|
||||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||
* street, Riga, Latvia, EU, LV-1050.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of the Program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU AGPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||
* grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||
* well as technical writing content are licensed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+function() {
|
||||
!window.common && (window.common = {});
|
||||
!common.controller && (common.controller = {});
|
||||
|
||||
common.controller.Shortcuts = new(function() {
|
||||
var localStorageKey = '',
|
||||
actionsMap = {},
|
||||
api = null;
|
||||
|
||||
|
||||
var setApi = function(newApi) {
|
||||
api = newApi;
|
||||
|
||||
if(window.DE) {
|
||||
localStorageKey = 'de-shortcuts';
|
||||
} else if(window.PDFE) {
|
||||
localStorageKey = 'pdfe-shortcuts';
|
||||
} else if(window.PE) {
|
||||
localStorageKey = 'pe-shortcuts';
|
||||
} else if(window.SSE) {
|
||||
localStorageKey = 'sse-shortcuts';
|
||||
} else if(window.VE) {
|
||||
localStorageKey = 've-shortcuts';
|
||||
}
|
||||
|
||||
_fillActionsMap();
|
||||
api && _applyShortcutsInSDK();
|
||||
};
|
||||
|
||||
var _keyCodeToKeyName = function(code) {
|
||||
const specialKeys = {
|
||||
8: 'Backspace',
|
||||
9: 'Tab',
|
||||
12: 'Clear',
|
||||
13: 'Enter',
|
||||
16: 'Shift',
|
||||
17: 'Ctrl',
|
||||
18: 'Alt',
|
||||
19: 'Pause',
|
||||
20: 'CapsLock',
|
||||
27: 'Escape',
|
||||
32: 'Space',
|
||||
33: 'PageUp',
|
||||
34: 'PageDown',
|
||||
35: 'End',
|
||||
36: 'Home',
|
||||
37: 'ArrowLeft',
|
||||
38: 'ArrowUp',
|
||||
39: 'ArrowRight',
|
||||
40: 'ArrowDown',
|
||||
44: 'PrintScreen',
|
||||
45: 'Insert',
|
||||
46: 'Delete',
|
||||
91: 'Meta',
|
||||
93: 'ContextMenu',
|
||||
96: "Num 0",
|
||||
97: "Num 1",
|
||||
98: "Num 2",
|
||||
99: "Num 3",
|
||||
100: "Num 4",
|
||||
101: "Num 5",
|
||||
102: "Num 6",
|
||||
103: "Num 7",
|
||||
104: "Num 8",
|
||||
105: "Num 9",
|
||||
106: "Num *",
|
||||
107: "Num +",
|
||||
108: "Num Enter",
|
||||
109: "Num -",
|
||||
110: "Num .",
|
||||
111: "Num /",
|
||||
112: 'F1',
|
||||
113: 'F2',
|
||||
114: 'F3',
|
||||
115: 'F4',
|
||||
116: 'F5',
|
||||
117: 'F6',
|
||||
118: 'F7',
|
||||
119: 'F8',
|
||||
120: 'F9',
|
||||
121: 'F10',
|
||||
122: 'F11',
|
||||
123: 'F12',
|
||||
144: 'NumLock',
|
||||
145: 'ScrollLock',
|
||||
173: 'ff-',
|
||||
61: 'ff=',
|
||||
186: ';',
|
||||
187: '=',
|
||||
188: ',',
|
||||
189: '-',
|
||||
190: '.',
|
||||
191: '/',
|
||||
192: '`',
|
||||
219: '[',
|
||||
220: '\\',
|
||||
221: ']',
|
||||
222: '\'',
|
||||
};
|
||||
|
||||
if (specialKeys[code]) {
|
||||
return specialKeys[code];
|
||||
}
|
||||
return String.fromCharCode(code);
|
||||
};
|
||||
|
||||
var _getDefaultShortcutActions = function() {
|
||||
if(window.DE || window.PDFE) {
|
||||
return Asc.c_oAscDocumentShortcutType;
|
||||
} else if(window.PE) {
|
||||
return Asc.c_oAscPresentationShortcutType;
|
||||
} else if(window.SSE) {
|
||||
return Asc.c_oAscSpreadsheetShortcutType;
|
||||
} else if(window.VE) {
|
||||
return Asc.c_oAscDiagramShortcutType;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
var _fillActionsMap = function() {
|
||||
actionsMap = {};
|
||||
|
||||
const shortcutActions = _getDefaultShortcutActions();
|
||||
const unlockedTypes = Asc.c_oAscUnlockedShortcutActionTypes || {};
|
||||
for (let actionName in shortcutActions) {
|
||||
const type = shortcutActions[actionName];
|
||||
actionsMap[type] = {
|
||||
action: {
|
||||
name: actionName,
|
||||
type: type,
|
||||
isLocked: !unlockedTypes[type]
|
||||
},
|
||||
shortcuts: []
|
||||
}
|
||||
}
|
||||
|
||||
pairs(Asc.c_oAscDefaultShortcuts).forEach(function(item) {
|
||||
const actionType = item[0];
|
||||
const shortcuts = item[1];
|
||||
const actionItem = actionsMap[actionType];
|
||||
|
||||
if(actionItem) {
|
||||
actionItem.shortcuts = shortcuts.map(function(ascShortcut) {
|
||||
return {
|
||||
keys: _getAscShortcutKeys(ascShortcut),
|
||||
isCustom: false,
|
||||
ascShortcut: ascShortcut,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let removableIndexes = {};
|
||||
pairs(_getModifiedShortcuts()).forEach(function(item) {
|
||||
const actionType = item[0];
|
||||
const shortcuts = item[1];
|
||||
const actionItem = actionsMap[actionType];
|
||||
|
||||
if(actionItem) {
|
||||
shortcuts.forEach(function(ascShortcut) {
|
||||
const ascShortcutIndex = ascShortcut.asc_GetShortcutIndex();
|
||||
const defaultShortcutIndex = findIndex(actionItem.shortcuts, function(shortcut) {
|
||||
return shortcut.ascShortcut.asc_GetShortcutIndex() == ascShortcutIndex;
|
||||
});
|
||||
|
||||
if(defaultShortcutIndex != -1) {
|
||||
actionItem.shortcuts[defaultShortcutIndex].ascShortcut = ascShortcut;
|
||||
} else {
|
||||
removableIndexes[ascShortcutIndex] = actionType;
|
||||
actionItem.shortcuts.push({
|
||||
keys: _getAscShortcutKeys(ascShortcut),
|
||||
isCustom: true,
|
||||
ascShortcut: ascShortcut,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
for (const actionType in actionsMap) {
|
||||
const item = actionsMap[actionType];
|
||||
const shortcuts = actionsMap[actionType].shortcuts;
|
||||
if(shortcuts.length == 0 && item.action.isLocked) {
|
||||
// Delete actions if it has no shortcuts and the action is locked
|
||||
delete actionsMap[actionType];
|
||||
} else if(Object.keys(removableIndexes).length > 0) {
|
||||
// Remove shortcuts from other actions if they conflict with updated shortcuts
|
||||
const foundIndex = findIndex(shortcuts, function(shortcut) {
|
||||
const ascShortcutIndex = shortcut.ascShortcut.asc_GetShortcutIndex();
|
||||
if(removableIndexes[ascShortcutIndex] && removableIndexes[ascShortcutIndex] != actionType) {
|
||||
delete removableIndexes[ascShortcutIndex];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(foundIndex != -1) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(shortcuts[foundIndex].ascShortcut.asc_ToJson());
|
||||
copyAscShortcut.asc_SetIsHidden(true);
|
||||
shortcuts[foundIndex].ascShortcut = copyAscShortcut;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var _applyShortcutsInSDK = function() {
|
||||
const applyMethod = function(storage) {
|
||||
storage = JSON.parse(storage || common.localStorage.getItem(localStorageKey) || "{}");
|
||||
for (const actionType in storage) {
|
||||
storage[actionType] = storage[actionType].map(function(ascShortcutJson) {
|
||||
const ascShortcut = new Asc.CAscShortcut();
|
||||
ascShortcut.asc_FromJson(ascShortcutJson);
|
||||
return ascShortcut;
|
||||
});
|
||||
}
|
||||
|
||||
api.asc_resetAllShortcutTypes();
|
||||
|
||||
const modifiedShortcuts = flatten(values(storage));
|
||||
if(modifiedShortcuts.length) {
|
||||
api.asc_applyAscShortcuts(modifiedShortcuts);
|
||||
}
|
||||
};
|
||||
|
||||
$(window).on('storage', function (e) {
|
||||
if(e.key == localStorageKey) {
|
||||
applyMethod(e.originalEvent.newValue);
|
||||
_fillActionsMap();
|
||||
}
|
||||
});
|
||||
|
||||
applyMethod();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves user-modified shortcuts from localStorage.
|
||||
* @returns {Object<number, CAscShortcut[]>}
|
||||
* An object where keys are action types and values are arrays of ascShortcut instances.
|
||||
*/
|
||||
var _getModifiedShortcuts = function() {
|
||||
const storage = JSON.parse(common.localStorage.getItem(localStorageKey) || "{}");
|
||||
for (const actionType in storage) {
|
||||
storage[actionType] = storage[actionType].map(function(ascShortcutJson) {
|
||||
const ascShortcut = new Asc.CAscShortcut();
|
||||
ascShortcut.asc_FromJson(ascShortcutJson);
|
||||
return ascShortcut;
|
||||
});
|
||||
}
|
||||
return storage;
|
||||
};
|
||||
|
||||
|
||||
var _getAscShortcutKeys = function(ascShortcut) {
|
||||
const keys = [];
|
||||
ascShortcut.asc_IsCommand() && keys.push('⌘');
|
||||
ascShortcut.asc_IsCtrl() && keys.push('Ctrl');
|
||||
ascShortcut.asc_IsAlt() && keys.push('Alt');
|
||||
ascShortcut.asc_IsShift() && keys.push('Shift');
|
||||
keys.push(_keyCodeToKeyName(ascShortcut.asc_GetKeyCode()));
|
||||
return keys;
|
||||
};
|
||||
|
||||
|
||||
// Utils
|
||||
var pairs = function(obj) {
|
||||
var result = [];
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
result.push([key, obj[key]]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
var flatten = function(array) {
|
||||
var result = [];
|
||||
|
||||
function flat(arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var value = arr[i];
|
||||
if (Array.isArray(value)) {
|
||||
flat(value);
|
||||
} else {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flat(array);
|
||||
return result;
|
||||
};
|
||||
|
||||
var values = function(obj) {
|
||||
var result = [];
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
result.push(obj[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
var findIndex = function(array, predicate) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (predicate(array[i], i, array)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
return {
|
||||
setApi: setApi
|
||||
}
|
||||
});
|
||||
}();
|
||||
@ -152,6 +152,11 @@
|
||||
config.callback(btn);
|
||||
}
|
||||
});
|
||||
$dlgWarning.on('click', '[data-dismiss="modal"]', function() {
|
||||
if (config.closecallback) {
|
||||
config.closecallback();
|
||||
}
|
||||
});
|
||||
|
||||
$dlgWarning.on('hidden.bs.modal', function() {
|
||||
$dlgWarning.remove();
|
||||
|
||||
@ -1097,6 +1097,14 @@ define([
|
||||
|
||||
this.updateIcon();
|
||||
Common.NotificationCenter.on('uitheme:changed', this.updateIcons.bind(this));
|
||||
|
||||
if (this.cmpEl && this.options.customAttributes) {
|
||||
for (var key in this.options.customAttributes) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.options.customAttributes, key)) {
|
||||
this.cmpEl.attr(Common.Utils.String.htmlEncode(key), Common.Utils.String.htmlEncode(this.options.customAttributes[key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateIcons: function() {
|
||||
|
||||
@ -125,7 +125,10 @@ define([
|
||||
cls: 'color-menu ' + (options.eyeDropper ? 'shifted-right' : 'shifted-left'),
|
||||
additionalAlign: options.additionalAlign,
|
||||
items: (options.additionalItemsBefore ? options.additionalItemsBefore : []).concat(auto).concat([
|
||||
{ template: _.template('<div id="' + id + '-color-menu" style="width: ' + width + '; height:' + height + '; display: inline-block;"></div>') }
|
||||
{
|
||||
template: _.template('<div id="' + id + '-color-menu" style="width: ' + width + '; height:' + height + '; display: inline-block;"></div>'),
|
||||
stopPropagation: options.hidePaletteOnClick===false
|
||||
}
|
||||
]).concat(options.hideColorsSeparator ? [] : {caption: '--'}).concat(eyedropper).concat([
|
||||
{
|
||||
id: id + '-color-new',
|
||||
|
||||
@ -1404,9 +1404,9 @@ define([
|
||||
if (data.keyCode==Common.UI.Keys.RETURN) {
|
||||
if (this.selectedBeforeHideRec) // only for ComboDataView menuPicker
|
||||
rec = this.selectedBeforeHideRec;
|
||||
if (this.canAddRecents) // only for DaraViewShape
|
||||
if (this.canAddRecents) // only for DataViewShape
|
||||
this.addRecentItem(rec);
|
||||
this.trigger('item:click', this, this, rec, e);
|
||||
rec && this.trigger('item:click', this, this, rec, e);
|
||||
if (this.parentMenu)
|
||||
this.parentMenu.hide();
|
||||
} else {
|
||||
@ -1880,6 +1880,8 @@ define([
|
||||
this.addRecentItem(record);
|
||||
},
|
||||
addRecentItem: function (rec) {
|
||||
if (!rec) return;
|
||||
|
||||
var me = this,
|
||||
exist = false,
|
||||
type = rec.get('data').shapeType,
|
||||
|
||||
@ -685,7 +685,7 @@ define([
|
||||
}
|
||||
})(), Common.UI.InputFieldBtnPassword || {}));
|
||||
|
||||
Common.UI.InputFieldBtnCalendar = Common.UI.InputFieldBtn.extend((function (){
|
||||
Common.UI.InputFieldBtnCalendar = Common.UI.InputFieldBtn.extend(_.extend((function() {
|
||||
return {
|
||||
options: {
|
||||
id: null,
|
||||
@ -767,7 +767,7 @@ define([
|
||||
|
||||
textDate: 'Select date'
|
||||
}
|
||||
})());
|
||||
})(), Common.UI.InputFieldBtnCalendar || {}));
|
||||
|
||||
Common.UI.InputFieldFixed = Common.UI.InputField.extend((function() {
|
||||
return {
|
||||
|
||||
@ -189,11 +189,11 @@ define([
|
||||
labelEl.text(name);
|
||||
},
|
||||
|
||||
setHeaderWidth: function(index, width) {
|
||||
setHeaderWidth: function(index, width, innerLabel) {
|
||||
if(index < 0 || index > this.options.headers.length - 1 || !this.headerEl) return;
|
||||
|
||||
var labelEl = $(this.headerEl.find('.table-header-item')[index]);
|
||||
if(labelEl.attr('sort-type')) {
|
||||
if(labelEl.attr('sort-type') && innerLabel) {
|
||||
labelEl = labelEl.find('label')[0];
|
||||
}
|
||||
|
||||
|
||||
@ -631,9 +631,25 @@ define([
|
||||
if (item.options.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
var me = this;
|
||||
_.delay(function(){
|
||||
me.$el.parent().parent().find('[data-toggle=dropdown]').focus();
|
||||
}, 10);
|
||||
const _callback = function (records, observer) {
|
||||
if (records[0].oldValue && records[0].oldValue.indexOf('over') && !me.$el.hasClass('over')) {
|
||||
observer.disconnect();
|
||||
_.delay(function(){
|
||||
me.$el.parent().parent().find('[data-toggle=dropdown]').focus();
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
if ((this.menuAlignEl || this.menuRoot.parent()).is('li.dropdown-submenu')) { // for bug 24712, click from submenu
|
||||
(new MutationObserver(_callback)).observe(this.$el[0], {
|
||||
attributes : true,
|
||||
attributeFilter : ['class'],
|
||||
attributeOldValue: true
|
||||
});
|
||||
} else { // click from button menu, set focus to button
|
||||
_.delay(function(){
|
||||
me.$el.parent().find('[data-toggle=dropdown]').focus();
|
||||
}, 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.trigger(item.isCustomItem ? 'item:custom-click' : 'item:click', this, item, e);
|
||||
|
||||
@ -205,26 +205,7 @@ define([
|
||||
}
|
||||
|
||||
if (me.options.hint) {
|
||||
el.attr('data-toggle', 'tooltip');
|
||||
el.tooltip({
|
||||
title : me.options.hint,
|
||||
placement : me.options.hintAnchor||function(tip, element) {
|
||||
var pos = Common.Utils.getBoundingClientRect(element),
|
||||
actualWidth = tip.offsetWidth,
|
||||
actualHeight = tip.offsetHeight,
|
||||
innerWidth = Common.Utils.innerWidth(),
|
||||
innerHeight = Common.Utils.innerHeight();
|
||||
var top = pos.top,
|
||||
left = pos.left + pos.width + 2;
|
||||
if (top + actualHeight > innerHeight) {
|
||||
top = innerHeight - actualHeight - 2;
|
||||
}
|
||||
if (left + actualWidth > innerWidth) {
|
||||
left = pos.left - actualWidth - 2;
|
||||
}
|
||||
Common.Utils.setOffset($(tip),{top: top,left: left}).addClass('in');
|
||||
}
|
||||
});
|
||||
this.createHint();
|
||||
}
|
||||
|
||||
if (this.cls)
|
||||
@ -260,6 +241,39 @@ define([
|
||||
return this;
|
||||
},
|
||||
|
||||
createHint: function() {
|
||||
if(!this.cmpEl) return;
|
||||
|
||||
this.cmpEl.attr('data-toggle', 'tooltip');
|
||||
this.cmpEl.tooltip({
|
||||
title : this.options.hint,
|
||||
placement : this.options.hintAnchor||function(tip, element) {
|
||||
var pos = Common.Utils.getBoundingClientRect(element),
|
||||
actualWidth = tip.offsetWidth,
|
||||
actualHeight = tip.offsetHeight,
|
||||
innerWidth = Common.Utils.innerWidth(),
|
||||
innerHeight = Common.Utils.innerHeight();
|
||||
var top = pos.top,
|
||||
left = pos.left + pos.width + 2;
|
||||
if (top + actualHeight > innerHeight) {
|
||||
top = innerHeight - actualHeight - 2;
|
||||
}
|
||||
if (left + actualWidth > innerWidth) {
|
||||
left = pos.left - actualWidth - 2;
|
||||
}
|
||||
Common.Utils.setOffset($(tip),{top: top,left: left}).addClass('in');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateHint: function(hint) {
|
||||
this.options.hint = hint;
|
||||
if (!this.rendered) return;
|
||||
|
||||
this.cmpEl.tooltip('destroy');
|
||||
this.createHint();
|
||||
},
|
||||
|
||||
setCaption: function(caption) {
|
||||
this.caption = caption;
|
||||
|
||||
|
||||
@ -379,7 +379,9 @@ define([
|
||||
if (this.options.hold && ( e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.DOWN)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (this.switches.timeout===undefined) {
|
||||
if (e.metaKey) {
|
||||
this._step(e.keyCode === Common.UI.Keys.UP);
|
||||
} else if (this.switches.timeout===undefined) {
|
||||
this.switches.fromKeyDown = true;
|
||||
this._startSpin(e.keyCode==Common.UI.Keys.UP, e);
|
||||
}
|
||||
|
||||
@ -160,6 +160,7 @@ define([
|
||||
Common.NotificationCenter.on('uitheme:changed', _.bind(function() {
|
||||
this.clearActiveData();
|
||||
this.processPanelVisible();
|
||||
this.repaintMoreBtns();
|
||||
}, this));
|
||||
},
|
||||
|
||||
@ -378,7 +379,28 @@ define([
|
||||
|
||||
var _tabTemplate = _.template('<li class="ribtab" style="display: none;" <% if (typeof layoutname == "string") print(" data-layout-name=" + \' \' + layoutname) + \' \' %>><a role="tab" id="<%= action %>" data-tab="<%= action %>" data-title="<%= caption %>" data-hint="0" data-hint-direction="bottom" data-hint-offset="small" <% if (typeof dataHintTitle !== "undefined") { %> data-hint-title="<%= dataHintTitle %>" <% } %> ><%= caption %></a></li>');
|
||||
|
||||
config.tabs[after + 1] = tab;
|
||||
if (after===undefined || tab.aux)
|
||||
after = config.tabs.length-1;
|
||||
|
||||
if (tab.aux) { // alwayw show tab at the end of toolbar
|
||||
config.tabs.push(tab);
|
||||
} else if (config.tabs[after + 1]) {
|
||||
var index = -1;
|
||||
for (let i=after + 2; i<config.tabs.length; i++) {
|
||||
if (config.tabs[i]===undefined) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index<0 || index>config.tabs.length-1)
|
||||
config.tabs.splice(after+1, 0, tab);
|
||||
else {
|
||||
config.tabs.splice(index, 1);
|
||||
config.tabs.splice(after+1, 0, tab);
|
||||
}
|
||||
} else {
|
||||
config.tabs[after + 1] = tab;
|
||||
}
|
||||
var _after_action = _get_tab_action(after);
|
||||
|
||||
var _elements = this.$tabs || this.$layout.find('.tabs');
|
||||
@ -424,7 +446,8 @@ define([
|
||||
},
|
||||
|
||||
getLastTabIdx: function() {
|
||||
return config.tabs.length;
|
||||
var index = _.findIndex(config.tabs, {aux: true});
|
||||
return index<0 ? config.tabs.length-1 : index-1;
|
||||
},
|
||||
|
||||
isCompact: function () {
|
||||
@ -462,9 +485,9 @@ define([
|
||||
* hide button's caption to decrease panel width
|
||||
* ##adopt-panel-width
|
||||
**/
|
||||
processPanelVisible: function(panel, force) {
|
||||
processPanelVisible: function(panel, reset, force) {
|
||||
var me = this;
|
||||
function _fc() {
|
||||
function _fc(reset) {
|
||||
var $active = panel || me.$panels.filter('.active');
|
||||
if ( $active && $active.length ) {
|
||||
var _maxright = $active.parents('.box-controls').width(),
|
||||
@ -524,9 +547,9 @@ define([
|
||||
}
|
||||
data.rightedge = _rightedge;
|
||||
}
|
||||
me.resizeToolbar(force);
|
||||
me.resizeToolbar(reset);
|
||||
} else {
|
||||
more_section.is(':visible') && me.resizeToolbar(force);
|
||||
more_section.is(':visible') && me.resizeToolbar(reset);
|
||||
if (!more_section.is(':visible')) {
|
||||
for (var i=0; i<_btns.length; i++) {
|
||||
var btn = _btns[i];
|
||||
@ -558,12 +581,13 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
if (!me._timer_id) {
|
||||
_fc();
|
||||
if (!me._timer_id || force) {
|
||||
me._timer_id && clearInterval(me._timer_id);
|
||||
_fc(reset);
|
||||
me._needProcessPanel = false;
|
||||
me._timer_id = setInterval(function() {
|
||||
me._timer_id = setInterval(function() {
|
||||
if (me._needProcessPanel) {
|
||||
_fc();
|
||||
_fc(me._needProcessPanel.reset);
|
||||
me._needProcessPanel = false;
|
||||
} else {
|
||||
clearInterval(me._timer_id);
|
||||
@ -571,7 +595,7 @@ define([
|
||||
}
|
||||
}, 100);
|
||||
} else
|
||||
me._needProcessPanel = true;
|
||||
me._needProcessPanel = {reset: me._needProcessPanel ? me._needProcessPanel.reset || reset : reset};
|
||||
},
|
||||
/**/
|
||||
|
||||
@ -618,6 +642,9 @@ define([
|
||||
var moreContainer = $('<div class="dropdown-menu more-container" data-tab="' + tab + '"><div style="display: inline;"></div></div>');
|
||||
optsFold.$bar.append(moreContainer);
|
||||
btnsMore[tab].panel = moreContainer.find('div');
|
||||
} else if (btnsMore[tab].needRepaint && panel.is(':visible')) {
|
||||
btnsMore[tab].cmpEl.closest('.more-box').css('top', Common.Utils.getPosition(panel).top);
|
||||
btnsMore[tab].needRepaint = false;
|
||||
}
|
||||
this.$moreBar = btnsMore[tab].panel;
|
||||
},
|
||||
@ -625,8 +652,11 @@ define([
|
||||
repaintMoreBtns: function() {
|
||||
for (var btn in btnsMore) {
|
||||
if (btnsMore[btn] && btnsMore[btn].cmpEl) {
|
||||
var box = btnsMore[btn].cmpEl.closest('.more-box');
|
||||
box.css('top', Common.Utils.getPosition(box.parent()).top);
|
||||
var box = btnsMore[btn].cmpEl.closest('.more-box'),
|
||||
panel = box.parent(),
|
||||
isVisible = panel.is(':visible');
|
||||
isVisible && box.css('top', Common.Utils.getPosition(panel).top);
|
||||
btnsMore[btn].needRepaint = !isVisible;
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -646,6 +676,22 @@ define([
|
||||
}
|
||||
},
|
||||
|
||||
moveAllFromMoreButton: function(tab) {
|
||||
if (btnsMore[tab]) {
|
||||
var moreBar = btnsMore[tab].panel,
|
||||
items = moreBar ? moreBar.children() : [];
|
||||
if (items.length>0) {
|
||||
items.removeAttr('hidden-on-resize');
|
||||
items.removeAttr('data-hidden-tb-item');
|
||||
items.removeAttr('group-state');
|
||||
var panel = this.$panels.filter('[data-tab=' + tab + ']');
|
||||
panel.length && panel.find('.more-box').before(items);
|
||||
this.clearMoreButton(tab);
|
||||
}
|
||||
}
|
||||
this.clearActiveData();
|
||||
},
|
||||
|
||||
clearActiveData: function(tab) {
|
||||
var panel = tab ? this.$panels.filter('[data-tab=' + tab + ']') : this.$panels.filter('.active');
|
||||
if ( panel.length ) {
|
||||
@ -727,7 +773,7 @@ define([
|
||||
var $panel = this.getTab(tab),
|
||||
$morepanel = this.getMorePanel(tab),
|
||||
$moresection = $panel ? $panel.find('.more-box') : null;
|
||||
($moresection.length<1) && ($moresection = null);
|
||||
($moresection && $moresection.length<1) && ($moresection = null);
|
||||
return $panel ? !($panel.find('> .group').length>0 || $morepanel && $morepanel.find('.group').length>0) : false;
|
||||
},
|
||||
|
||||
|
||||
@ -132,12 +132,15 @@ define([
|
||||
this.cmpEl = me.$el;
|
||||
}
|
||||
|
||||
this.cmpEl.find('.track-center').width(me.options.width - 14);
|
||||
this.cmpEl[me.direction === 'vertical' ? 'height' : 'width'](me.options.width);
|
||||
|
||||
this.track = this.cmpEl.find('.track');
|
||||
this.thumb = this.cmpEl.find('.thumb');
|
||||
|
||||
const halfThumbSize = this.thumb.outerWidth() / 2;
|
||||
this.width = this.options.width - halfThumbSize;
|
||||
|
||||
this.cmpEl.find('.track-center').width(me.options.width - 14);
|
||||
this.cmpEl[me.direction === 'vertical' ? 'height' : 'width'](this.width);
|
||||
|
||||
var onMouseUp = function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -179,7 +182,7 @@ define([
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
me._dragstart = me.direction === 'vertical' ? (e.pageY*Common.Utils.zoom() - Common.Utils.getOffset(me.thumb).top) : (e.pageX*Common.Utils.zoom() - Common.Utils.getOffset(me.thumb).left) - 6;
|
||||
me._dragstart = me.direction === 'vertical' ? (e.pageY*Common.Utils.zoom() - Common.Utils.getOffset(me.thumb).top) : (e.pageX*Common.Utils.zoom() - Common.Utils.getOffset(me.thumb).left) - halfThumbSize;
|
||||
|
||||
me.thumb.addClass('active');
|
||||
$(document).on('mouseup', onMouseUp);
|
||||
@ -248,13 +251,6 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
const thumbWidth = this.thumb.width() / 2;
|
||||
const delta = -thumbWidth * 2;
|
||||
this.thumbRange = new Float32Array(101);
|
||||
for (let i = 0; i < 101; i++) {
|
||||
this.thumbRange[i] = thumbWidth + delta * (i / 100);
|
||||
}
|
||||
|
||||
this.setThumbPosition(me.options.value);
|
||||
|
||||
me.rendered = true;
|
||||
@ -267,10 +263,8 @@ define([
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
const offset = pos / 100 * this.width + this.thumbRange[pos];
|
||||
|
||||
this.track.css('--slider-unfill-percent', 100 - pos + '%');
|
||||
this.thumb.css(this.direction === 'vertical' ? 'top' : 'left', offset + 'px');
|
||||
this.thumb.css(this.direction === 'vertical' ? 'top' : 'left', pos + '%');
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
|
||||
@ -74,7 +74,17 @@ define([
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
this.textSynchronize += Common.Utils.String.platformKey('Ctrl+S');
|
||||
const me = this;
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
app.getController('Common.Controllers.Shortcuts').updateShortcutHints({
|
||||
Save: {
|
||||
label: '',
|
||||
applyCallback: function(item, hintText) {
|
||||
me.textSynchronize += hintText;
|
||||
},
|
||||
ignoreUpdates: true
|
||||
},
|
||||
});
|
||||
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
this.target = this.options.target;
|
||||
@ -102,7 +112,7 @@ define([
|
||||
this.cmpEl.find('.btn-div').on('click', _.bind(function() { this.trigger('buttonclick');}, this));
|
||||
|
||||
this.closable && this.cmpEl.addClass('closable');
|
||||
this.binding.windowresize = _.bind(this.applyPlacement, this);
|
||||
this.binding.windowresize = _.bind(this.onWindowResize, this);
|
||||
}
|
||||
|
||||
this.applyPlacement();
|
||||
@ -131,8 +141,18 @@ define([
|
||||
this.automove && $(window).off('resize', this.binding.windowresize);
|
||||
},
|
||||
|
||||
applyPlacement: function () {
|
||||
onWindowResize: function() {
|
||||
this.applyPlacement();
|
||||
},
|
||||
|
||||
applyPlacement: function (repeatOnce) {
|
||||
var target = this.target && this.target.length>0 ? this.target : $(document.body);
|
||||
|
||||
if (!target.is(':visible') && !repeatOnce) {
|
||||
var me = this;
|
||||
setTimeout(function(){ me.applyPlacement(true); }, 100);
|
||||
return;
|
||||
}
|
||||
var showxy = Common.Utils.getOffset(target),
|
||||
offset = this.offset || {x: 0, y: 0};
|
||||
if (this.placement=='target' && !this.position) {
|
||||
@ -237,6 +257,7 @@ define([
|
||||
// maxwidth: 250 // number or string '123px/none/...', 250 by default,
|
||||
// extCls: '' //
|
||||
// noHighlight: false // false by default,
|
||||
// noArrow: false // false by default,
|
||||
// multiple: false // false by default, show tip multiple times,
|
||||
// isNewFeature: false // false by default, show "New" tip in the header
|
||||
// }
|
||||
@ -264,14 +285,22 @@ define([
|
||||
return _helpTips[step] && !(_helpTips[step].name && Common.localStorage.getItem(_helpTips[step].name));
|
||||
};
|
||||
|
||||
var _applyPlacement = function(step) {
|
||||
if (_helpTips[step] && _helpTips[step].tip && _helpTips[step].tip.isVisible())
|
||||
_helpTips[step].tip.applyPlacement();
|
||||
};
|
||||
|
||||
var _closeTip = function(step, force, preventNext) {
|
||||
var props = _helpTips[step];
|
||||
if (props) {
|
||||
preventNext && (props.next = undefined);
|
||||
props.tip && props.tip.close();
|
||||
props.tip = undefined;
|
||||
force && props.name && Common.localStorage.setItem(props.name, 1);
|
||||
}
|
||||
var steps = typeof step === 'string' ? [step] : step;
|
||||
steps && steps.forEach(function(step) {
|
||||
var props = _helpTips[step];
|
||||
if (props) {
|
||||
preventNext && (props.next = undefined);
|
||||
props.tip && props.tip.close();
|
||||
props.tip = undefined;
|
||||
force && props.name && Common.localStorage.setItem(props.name, 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _findTarget = function(target) {
|
||||
@ -323,7 +352,7 @@ define([
|
||||
}
|
||||
|
||||
props.tip = new Common.UI.SynchronizeTip({
|
||||
extCls: 'colored' + (props.extCls ? ' ' + props.extCls : '') + (props.noHighlight ? ' no-arrow' : ''),
|
||||
extCls: 'colored' + (props.extCls ? ' ' + props.extCls : '') + (props.noArrow ? ' no-arrow' : ''),
|
||||
style: 'min-width:200px;max-width:' + (props.maxwidth ? props.maxwidth + (typeof props.maxwidth === 'number' ? 'px;' : ';') : '250px;'),
|
||||
placement: placement,
|
||||
position: props.position,
|
||||
@ -335,6 +364,7 @@ define([
|
||||
textLink: props.link ? props.link.text : '',
|
||||
closable: props.closable !== false, // true by default
|
||||
showButton: props.showButton !== false, // true by default
|
||||
textButton: props.textButton, // button text, Got it by default
|
||||
automove: !!props.automove
|
||||
});
|
||||
props.tip.on({
|
||||
@ -378,7 +408,8 @@ define([
|
||||
closeTip: _closeTip,
|
||||
removeTip: _removeTip,
|
||||
addTips: _addTips,
|
||||
getNeedShow: _getNeedShow
|
||||
getNeedShow: _getNeedShow,
|
||||
applyPlacement: _applyPlacement
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
@ -54,7 +54,7 @@ define([
|
||||
this.iconTitle = '';
|
||||
this.index = -1;
|
||||
this.template = _.template(['<li class="list-item <% if(active){ %>active selected<% } %> <% if(cls.length){%><%= cls %><%}%><% if(iconVisible){%> icon-visible <%}%>" data-label="<%- label %>">',
|
||||
'<span tabtitle="<%- label %>" draggable="true" oo_editor_input="true" tabindex="-1" data-index="<%= index %>">',
|
||||
'<span tabtitle="<%- label %>" draggable="true" oo_editor_input="true" tabindex="-1" data-index="<%= sheetindex %>">',
|
||||
'<div class="toolbar__icon <% if(iconCls.length){%><%= iconCls %><%}%>" title="<% if(iconTitle.length){%><%=Common.Utils.String.htmlEncode(iconTitle)%><%}%>"></div>',
|
||||
'<%- label %>',
|
||||
'</span>',
|
||||
|
||||
@ -64,6 +64,14 @@ define([
|
||||
|
||||
StateManager.prototype.initialize = function (options) {
|
||||
this.bar = options.bar;
|
||||
if (!Common.Utils.isIE && !Common.Utils.isSafari) {
|
||||
if (Common.Utils.isMac) {
|
||||
this.ghostImage = new Image();
|
||||
this.ghostImage.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
} else {
|
||||
this.ghostImage = document.createElement('div');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
StateManager.prototype.attach = function (tab) {
|
||||
@ -204,8 +212,7 @@ define([
|
||||
{dragstart: $.proxy(function (e) {
|
||||
var event = e.originalEvent;
|
||||
if (!Common.Utils.isIE && !Common.Utils.isSafari) {
|
||||
var img = document.createElement('div');
|
||||
event.dataTransfer.setDragImage(img, 0, 0);
|
||||
event.dataTransfer.setDragImage(this.ghostImage, 0, 0);
|
||||
} else if (Common.Utils.isIE) {
|
||||
this.bar.selectTabs.forEach(function (tab) {
|
||||
tab.$el.find('span').prop('tabtitle', '');
|
||||
@ -326,6 +333,7 @@ define([
|
||||
this.isDragDrop = true;
|
||||
}
|
||||
this.trigger('tab:drop', event.dataTransfer, 'last', (event.ctrlKey || Common.Utils.isMac && event.altKey));
|
||||
this.preventCutTab = true;
|
||||
} else {
|
||||
this.isDrop = undefined;
|
||||
}
|
||||
|
||||
@ -103,7 +103,9 @@
|
||||
cls : opts.cls,
|
||||
html : opts.html,
|
||||
hideonclick : opts.hideonclick,
|
||||
keepvisible: opts.keepvisible
|
||||
keepvisible: opts.keepvisible,
|
||||
dir : opts.dir,
|
||||
animation : opts.animation
|
||||
});
|
||||
|
||||
if (opts.hideonclick) {
|
||||
|
||||
@ -158,6 +158,7 @@ define([
|
||||
minheight: 0,
|
||||
enableKeyEvents: true,
|
||||
automove: true,
|
||||
transparentMask: false,
|
||||
role: 'dialog'
|
||||
};
|
||||
|
||||
@ -536,7 +537,11 @@ define([
|
||||
(Math.max(text.width(), check.length>0 ? $(check).find('.checkbox-indeterminate').outerWidth(true) : 0)));
|
||||
window.setSize(width, parseInt(body.css('height')) + parseInt(header.css('height')));
|
||||
} else {
|
||||
text.css('white-space', 'normal');
|
||||
text.css({
|
||||
'white-space': 'normal',
|
||||
'overflow-wrap': 'break-word',
|
||||
'word-wrap': 'break-word'
|
||||
});
|
||||
window.setWidth(options.width);
|
||||
text_cnt.height(Math.max(text.height(), icon_height) + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0));
|
||||
body.height(parseInt(text_cnt.css('height')) + parseInt(footer.css('height')));
|
||||
@ -767,7 +772,7 @@ define([
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))+1);
|
||||
mask.show();
|
||||
} else {
|
||||
var maskOpacity = $(':root').css('--modal-window-mask-opacity');
|
||||
var maskOpacity = this.initConfig.transparentMask ? 0 : $(':root').css('--modal-window-mask-opacity');
|
||||
|
||||
mask.css('opacity', 0);
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))+1);
|
||||
@ -794,8 +799,9 @@ define([
|
||||
} else
|
||||
if (!this.$window.is(':visible')) {
|
||||
this.$window.css({opacity: 0});
|
||||
(_.isNumber(x) && _.isNumber(y)) && this.setPosition(x, y);
|
||||
_setVisible.call(this);
|
||||
this.$window.show()
|
||||
this.$window.show();
|
||||
}
|
||||
|
||||
$(document).on('keydown.' + this.cid, this.binding.keydown);
|
||||
@ -874,7 +880,7 @@ define([
|
||||
|
||||
if ( hide_mask ) {
|
||||
if (this.options.animate !== false) {
|
||||
var maskOpacity = $(':root').css('--modal-window-mask-opacity');
|
||||
var maskOpacity = this.initConfig.transparentMask ? 0 : $(':root').css('--modal-window-mask-opacity');
|
||||
mask.css(_getTransformation(0));
|
||||
|
||||
setTimeout(function () {
|
||||
@ -916,7 +922,7 @@ define([
|
||||
|
||||
if ( hide_mask ) {
|
||||
if (this.options.animate !== false) {
|
||||
var maskOpacity = $(':root').css('--modal-window-mask-opacity');
|
||||
var maskOpacity = this.initConfig.transparentMask ? 0 : $(':root').css('--modal-window-mask-opacity');
|
||||
mask.css(_getTransformation(0));
|
||||
|
||||
setTimeout(function () {
|
||||
@ -951,7 +957,7 @@ define([
|
||||
},
|
||||
|
||||
setWidth: function(width) {
|
||||
if (width >= 0) {
|
||||
if (this.$window && width >= 0) {
|
||||
var min = parseInt(this.$window.css('min-width'));
|
||||
width < min && (width = min);
|
||||
width -= (parseInt(this.$window.css('border-left-width')) + parseInt(this.$window.css('border-right-width')));
|
||||
@ -960,11 +966,11 @@ define([
|
||||
},
|
||||
|
||||
getWidth: function() {
|
||||
return parseInt(this.$window.css('width'));
|
||||
return this.$window ? parseInt(this.$window.css('width')) : undefined;
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
if (height >= 0) {
|
||||
if (this.$window && height >= 0) {
|
||||
var min = parseInt(this.$window.css('min-height'));
|
||||
height < min && (height = min);
|
||||
height -= (parseInt(this.$window.css('border-bottom-width')) + parseInt(this.$window.css('border-top-width')));
|
||||
@ -978,7 +984,7 @@ define([
|
||||
},
|
||||
|
||||
getHeight: function() {
|
||||
return parseInt(this.$window.css('height'));
|
||||
return this.$window ? parseInt(this.$window.css('height')) : undefined;
|
||||
},
|
||||
|
||||
setSize: function(w, h) {
|
||||
@ -1023,14 +1029,14 @@ define([
|
||||
setResizable: function(resizable, minSize, maxSize) {
|
||||
if (resizable !== this.resizable) {
|
||||
if (resizable) {
|
||||
var bordersTemplate = '<div class="resize-border left" style="top:' + ((this.initConfig.header) ? '33' : '5') + 'px; bottom: 5px; height: auto; border-right-style: solid; cursor: w-resize;"></div>' +
|
||||
'<div class="resize-border left bottom" style="border-bottom-left-radius: 5px; cursor: sw-resize;"></div>' +
|
||||
var bordersTemplate = '<div class="resize-border left bottom" style="cursor: sw-resize;"></div>' +
|
||||
'<div class="resize-border left" style="top:' + ((this.initConfig.header) ? '33' : '5') + 'px; bottom: 5px; height: auto; border-right-style: solid; cursor: w-resize;"></div>' +
|
||||
'<div class="resize-border bottom" style="left: 4px; right: 4px; width: auto; z-index: 2; border-top-style: solid; cursor: s-resize;"></div>' +
|
||||
'<div class="resize-border right bottom" style="border-bottom-right-radius: 5px; cursor: se-resize;"></div>' +
|
||||
'<div class="resize-border right bottom" style="cursor: se-resize;"></div>' +
|
||||
'<div class="resize-border right" style="top:' + ((this.initConfig.header) ? '33' : '5') + 'px; bottom: 5px; height: auto; border-left-style: solid; cursor: e-resize;"></div>' +
|
||||
'<div class="resize-border left top" style="border-top-left-radius: 5px; cursor: nw-resize;"></div>' +
|
||||
'<div class="resize-border left top" style="cursor: nw-resize;"></div>' +
|
||||
'<div class="resize-border top" style="left: 4px; right: 4px; width: auto; z-index: 2; border-bottom-style:' + ((this.initConfig.header) ? "none" : "solid") + '; cursor: n-resize;"></div>' +
|
||||
'<div class="resize-border right top" style="border-top-right-radius: 5px; cursor: ne-resize;"></div>';
|
||||
'<div class="resize-border right top" style="cursor: ne-resize;"></div>';
|
||||
if (this.initConfig.header)
|
||||
bordersTemplate += '<div class="resize-border left" style="top: 5px; height: 28px; cursor: w-resize;"></div>' +
|
||||
'<div class="resize-border right" style="top: 5px; height: 28px; cursor: e-resize;"></div>';
|
||||
|
||||
@ -80,6 +80,9 @@ define([
|
||||
isDummyComment : false,
|
||||
|
||||
initialize: function () {
|
||||
this.currentGroupFilter = null;
|
||||
this.currentTypeFilter = null;
|
||||
this.isPDFEditor = !!window.PDFE;
|
||||
|
||||
this.addListeners({
|
||||
'Common.Views.Comments': {
|
||||
@ -103,7 +106,8 @@ define([
|
||||
|
||||
'comment:closeEditing': _.bind(this.closeEditing, this),
|
||||
'comment:sort': _.bind(this.setComparator, this),
|
||||
'comment:filtergroups': _.bind(this.setFilterGroups, this)
|
||||
'comment:filtergroups': _.bind(this.setFilterGroups, this),
|
||||
'comment:filtercomments': _.bind(this.setFilterComments, this)
|
||||
},
|
||||
|
||||
'Common.Views.ReviewPopover': {
|
||||
@ -659,6 +663,8 @@ define([
|
||||
// SDK
|
||||
|
||||
onApiAddComment: function (id, data) {
|
||||
if (this.isPDFEditor && (this.findComment(id) || this.findCommentInGroup(id))) return; // fix for PDF, do not add comment with existing id
|
||||
|
||||
var requestObj = {},
|
||||
comment = this.readSDKComment(id, data, requestObj);
|
||||
if (comment) {
|
||||
@ -781,8 +787,9 @@ define([
|
||||
var usergroups = comment.get('parsedGroups');
|
||||
t.fillUserGroups(usergroups);
|
||||
var group = Common.Utils.InternalSettings.get(t.appPrefix + "comments-filtergroups");
|
||||
var filter = !!group && (group!==-1) && (!usergroups || usergroups.length<1 || usergroups.indexOf(group)<0);
|
||||
comment.set('filtered', filter);
|
||||
var groupFilter = !!group && (group !== -1) && (!usergroups || usergroups.length < 1 || usergroups.indexOf(group) < 0);
|
||||
var typeFilter = (t.currentTypeFilter === 'open' && comment.get('resolved')) || (t.currentTypeFilter === 'resolved' && !comment.get('resolved'));
|
||||
comment.set('filtered', groupFilter || typeFilter);
|
||||
}
|
||||
|
||||
replies = _.clone(comment.get('replys'));
|
||||
@ -1033,7 +1040,7 @@ define([
|
||||
this.getPopover().showComments(false, undefined, undefined, text);
|
||||
}
|
||||
|
||||
this.getPopover().setLeftTop(posX, posY, leftX, undefined, true);
|
||||
this.getPopover().setLeftTop(posX, posY, leftX, undefined);
|
||||
|
||||
// if (this.isSelectedComment && (0 === _.difference(this.uids, uids).length)) {
|
||||
//NOTE: click to sdk view ?
|
||||
@ -1335,9 +1342,11 @@ define([
|
||||
var usergroups = comment.get('parsedGroups');
|
||||
this.fillUserGroups(usergroups);
|
||||
var group = Common.Utils.InternalSettings.get(this.appPrefix + "comments-filtergroups");
|
||||
var filter = !!group && (group!==-1) && (!usergroups || usergroups.length<1 || usergroups.indexOf(group)<0);
|
||||
comment.set('filtered', filter);
|
||||
var groupFilter = !!group && (group !== -1) && (!usergroups || usergroups.length < 1 || usergroups.indexOf(group) < 0);
|
||||
var typeFilter = (this.currentTypeFilter === 'open' && comment.get('resolved')) || (this.currentTypeFilter === 'resolved' && !comment.get('resolved'));
|
||||
comment.set('filtered', groupFilter || typeFilter);
|
||||
}
|
||||
|
||||
var replies = this.readSDKReplies(data, requestObj);
|
||||
if (replies.length) {
|
||||
comment.set('replys', replies);
|
||||
@ -1755,27 +1764,41 @@ define([
|
||||
}
|
||||
},
|
||||
|
||||
setFilterGroups: function (group) {
|
||||
Common.Utils.InternalSettings.set(this.appPrefix + "comments-filtergroups", group);
|
||||
applyCombinedFilter: function () {
|
||||
var i, end = true;
|
||||
|
||||
for (i = this.collection.length - 1; i >= 0; --i) {
|
||||
var item = this.collection.at(i);
|
||||
if (!item.get('hide')) {
|
||||
var usergroups = item.get('parsedGroups');
|
||||
item.set('filtered', !!group && (group!==-1) && (!usergroups || usergroups.length<1 || usergroups.indexOf(group)<0), {silent: true});
|
||||
}
|
||||
if (end && !item.get('hide') && !item.get('filtered')) {
|
||||
item.set('last', true, {silent: true});
|
||||
var usergroups = item.get('parsedGroups');
|
||||
|
||||
var groupFiltered = !!this.currentGroupFilter && this.currentGroupFilter !== -1 && (!usergroups || usergroups.length < 1 || usergroups.indexOf(this.currentGroupFilter) < 0);
|
||||
var typeFiltered = (this.currentTypeFilter === 'open' && item.get('resolved')) || (this.currentTypeFilter === 'resolved' && !item.get('resolved'));
|
||||
var shouldFilter = groupFiltered || typeFiltered;
|
||||
|
||||
item.set('filtered', shouldFilter, { silent: true });
|
||||
|
||||
if (end && !shouldFilter && !item.get('hide')) {
|
||||
item.set('last', true, { silent: true });
|
||||
end = false;
|
||||
} else {
|
||||
if (item.get('last')) {
|
||||
item.set('last', false, {silent: true});
|
||||
}
|
||||
} else if (item.get('last')) {
|
||||
item.set('last', false, { silent: true });
|
||||
}
|
||||
}
|
||||
|
||||
this.updateComments(true);
|
||||
},
|
||||
|
||||
setFilterGroups: function (group) {
|
||||
Common.Utils.InternalSettings.set(this.appPrefix + "comments-filtergroups", group);
|
||||
this.currentGroupFilter = group;
|
||||
this.applyCombinedFilter();
|
||||
},
|
||||
|
||||
setFilterComments: function (type) {
|
||||
this.currentTypeFilter = type;
|
||||
this.applyCombinedFilter();
|
||||
},
|
||||
|
||||
onAppReady: function (config) {
|
||||
var me = this;
|
||||
(new Promise(function (accept, reject) {
|
||||
|
||||
@ -214,7 +214,7 @@ define([
|
||||
}
|
||||
const ctrl_print = webapp.getController('Print');
|
||||
if ( ctrl_print )
|
||||
ctrl_print.setPrinterInfo(currentPrinter, printers);
|
||||
ctrl_print.setPrintersInfo(currentPrinter, printers);
|
||||
} else
|
||||
if (/file:saveas/.test(cmd)) {
|
||||
webapp.getController('Main').api.asc_DownloadAs();
|
||||
@ -543,6 +543,7 @@ define([
|
||||
const _f_ = rawarray[i];
|
||||
if ( utils.matchFileFormat( _f_.type ) ) {
|
||||
if (_re_name.test(_f_.path)) {
|
||||
_f_.path = $('<div>').html(_f_.path).text();
|
||||
const name = _re_name.exec(_f_.path)[1],
|
||||
dir = _f_.path.slice(0, _f_.path.length - name.length - 1);
|
||||
|
||||
|
||||
@ -48,8 +48,10 @@ define([
|
||||
var appLang = '{{DEFAULT_LANG}}',
|
||||
customization = undefined,
|
||||
targetApp = '',
|
||||
canRequestOpen = false,
|
||||
externalEditor = null,
|
||||
isAppFirstOpened = true;
|
||||
isAppFirstOpened = true,
|
||||
isChartUpdating = false;
|
||||
|
||||
|
||||
var createExternalEditor = function() {
|
||||
@ -80,6 +82,7 @@ define([
|
||||
'onAppReady' : function() {},
|
||||
'onDocumentStateChange' : function() {},
|
||||
'onError' : function() {},
|
||||
'onRequestOpen' : canRequestOpen ? this.onRequestOpen : undefined,
|
||||
'onInternalMessage' : _.bind(this.onInternalMessage, this)
|
||||
}
|
||||
});
|
||||
@ -107,8 +110,8 @@ define([
|
||||
'show': _.bind(function(cmp){
|
||||
var h = this.diagramEditorView.getHeight(),
|
||||
innerHeight = Common.Utils.innerHeight() - Common.Utils.InternalSettings.get('window-inactive-area-top');
|
||||
if (innerHeight<h) {
|
||||
this.diagramEditorView.setHeight(innerHeight);
|
||||
if (innerHeight<h || isAppFirstOpened) {
|
||||
this.diagramEditorView.setHeight(innerHeight<h ? innerHeight : h);
|
||||
}
|
||||
|
||||
if (externalEditor) {
|
||||
@ -153,7 +156,7 @@ define([
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onCloseChartEditor', _.bind(this.onDiagrammEditingDisabled, this));
|
||||
this.api.asc_registerCallback('asc_sendFromGeneralToFrameEditor', _.bind(this.onSendFromGeneralToFrameEditor, this));
|
||||
this.api.asc_registerCallback('asc_sendFromGeneralToChartEditor', _.bind(this.onSendFromGeneralToFrameEditor, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -180,6 +183,7 @@ define([
|
||||
if (data.config.lang) appLang = data.config.lang;
|
||||
if (data.config.customization) customization = data.config.customization;
|
||||
if (data.config.targetApp) targetApp = data.config.targetApp;
|
||||
canRequestOpen = !!data.config.canRequestOpen;
|
||||
}
|
||||
},
|
||||
|
||||
@ -216,20 +220,29 @@ define([
|
||||
if (this.needDisableEditing) {
|
||||
this.onDiagrammEditingDisabled();
|
||||
}
|
||||
if (isChartUpdating) {
|
||||
Common.NotificationCenter.trigger('data:updatereferences', [isChartUpdating]);
|
||||
Common.NotificationCenter.trigger('action:end', Asc.c_oAscAsyncActionType.BlockInteraction, Common.UI.blockOperations.UpdateChart);
|
||||
isChartUpdating = false;
|
||||
}
|
||||
} else
|
||||
if (eventData.type == 'chartDataReady') {
|
||||
if (eventData.type == 'frameEditorReady') {
|
||||
if (this.needDisableEditing===undefined)
|
||||
this.diagramEditorView.setControlsDisabled(false);
|
||||
} else
|
||||
if (eventData.type == "shortcut") {
|
||||
if (eventData.data.key == 'escape')
|
||||
if (eventData.data.key == 'escape') {
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('getChartData');
|
||||
}
|
||||
this.diagramEditorView.hide();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == "canClose") {
|
||||
if (eventData.data.answer === true) {
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('setAppDisabled',true);
|
||||
externalEditor.serviceCommand((eventData.data.mr == 'ok') ? 'getChartData' : 'clearChartData');
|
||||
externalEditor.serviceCommand('getChartData');
|
||||
}
|
||||
this.diagramEditorView.hide();
|
||||
}
|
||||
@ -266,10 +279,29 @@ define([
|
||||
}
|
||||
},
|
||||
|
||||
onRequestOpen: function(event) {
|
||||
if (event && event.data)
|
||||
Common.Gateway.requestOpen(event.data);
|
||||
},
|
||||
|
||||
onSendFromGeneralToFrameEditor: function(data) {
|
||||
externalEditor && externalEditor.serviceCommand('generalToFrameData', data);
|
||||
},
|
||||
|
||||
updateChartSilent: function(externalRef) {
|
||||
if (!this.api) return;
|
||||
|
||||
if (!externalEditor && !isChartUpdating) {
|
||||
isChartUpdating = externalRef;
|
||||
Common.NotificationCenter.trigger('action:start', Asc.c_oAscAsyncActionType.BlockInteraction, Common.UI.blockOperations.UpdateChart);
|
||||
this.diagramEditorView.options.animate = false;
|
||||
this.diagramEditorView.show(-10000, -10000);
|
||||
this.diagramEditorView.hide();
|
||||
this.diagramEditorView.options.animate = true;
|
||||
} else
|
||||
Common.NotificationCenter.trigger('data:updatereferences', [externalRef]);
|
||||
},
|
||||
|
||||
warningTitle: 'Warning',
|
||||
warningText: 'The object is disabled because of editing by another user.',
|
||||
textClose: 'Close',
|
||||
|
||||
264
apps/common/main/lib/controller/ExternalLinks.js
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2023
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
* version 3 as published by the Free Software Foundation. In accordance with
|
||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||
* of any third-party rights.
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
*
|
||||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||
* street, Riga, Latvia, EU, LV-1050.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of the Program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU AGPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||
* grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||
* well as technical writing content are licensed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* ExternalLinks.js
|
||||
*
|
||||
* Created on 23.11.23
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Controllers = Common.Controllers || {};
|
||||
|
||||
define([
|
||||
'core',
|
||||
// 'common/main/lib/view/ExternalLinksDlg'
|
||||
], function () { 'use strict';
|
||||
Common.Controllers.ExternalLinks = Backbone.Controller.extend(_.extend({
|
||||
models: [],
|
||||
collections: [],
|
||||
views: [
|
||||
'Common.Views.ExternalLinksDlg'
|
||||
],
|
||||
|
||||
initialize: function() {
|
||||
this.externalData = {
|
||||
stackRequests: [],
|
||||
stackResponse: [],
|
||||
callback: undefined,
|
||||
isUpdating: false,
|
||||
linkStatus: {}
|
||||
};
|
||||
this.externalSource = {
|
||||
externalRef: undefined
|
||||
};
|
||||
this._state = {};
|
||||
},
|
||||
|
||||
onLaunch: function() {
|
||||
//
|
||||
},
|
||||
|
||||
setConfig: function(config) {
|
||||
this.toolbar = config.toolbar;
|
||||
return this;
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
if ((this.toolbar.mode.canRequestReferenceData || this.toolbar.mode.isOffline) && this.api) {
|
||||
!!window.SSE && this.api.asc_registerCallback('asc_onNeedUpdateExternalReference', _.bind(this.onNeedUpdateExternalReference, this));
|
||||
this.api.asc_registerCallback('asc_onNeedUpdateExternalReferenceOnOpen', _.bind(this.onNeedUpdateExternalReferenceOnOpen, this));
|
||||
this.api.asc_registerCallback('asc_onStartUpdateExternalReference', _.bind(this.onStartUpdateExternalReference, this));
|
||||
this.api.asc_registerCallback('asc_onUpdateExternalReference', _.bind(this.onUpdateExternalReference, this));
|
||||
this.api.asc_registerCallback('asc_onErrorUpdateExternalReference', _.bind(this.onErrorUpdateExternalReference, this));
|
||||
Common.Gateway.on('setreferencedata', _.bind(this.setReferenceData, this));
|
||||
}
|
||||
if (this.toolbar.mode.canRequestReferenceSource) {
|
||||
Common.Gateway.on('setreferencesource', _.bind(this.setReferenceSource, this));
|
||||
}
|
||||
Common.NotificationCenter.on('data:externallinks', _.bind(this.onExternalLinks, this));
|
||||
Common.NotificationCenter.on('data:updatereferences', _.bind(this.updateReferences, this));
|
||||
Common.NotificationCenter.on('data:openlink', _.bind(this.openLink, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
onExternalLinks: function() {
|
||||
var me = this;
|
||||
this.externalLinksDlg = (new Common.Views.ExternalLinksDlg({
|
||||
api: this.api,
|
||||
isUpdating: this.externalData.isUpdating,
|
||||
canRequestReferenceData: this.toolbar.mode.canRequestReferenceData || this.toolbar.mode.isOffline,
|
||||
canRequestOpen: this.toolbar.mode.canRequestOpen || this.toolbar.mode.isOffline,
|
||||
canRequestReferenceSource: this.toolbar.mode.canRequestReferenceSource || this.toolbar.mode.isOffline,
|
||||
isOffline: this.toolbar.mode.isOffline,
|
||||
handler: function(result) {
|
||||
Common.NotificationCenter.trigger('edit:complete');
|
||||
}
|
||||
}));
|
||||
this.externalLinksDlg.on('close', function(win){
|
||||
me.externalLinksDlg = null;
|
||||
});
|
||||
this.externalLinksDlg.on('change:source', function(win, externalRef){
|
||||
me.externalSource = {
|
||||
externalRef: externalRef
|
||||
};
|
||||
Common.Gateway.requestReferenceSource();
|
||||
});
|
||||
this.externalLinksDlg.show()
|
||||
},
|
||||
|
||||
onUpdateExternalReference: function(arr, callback) {
|
||||
if (this.toolbar.mode.isEdit && this.toolbar.editMode) {
|
||||
var me = this;
|
||||
me.externalData = {
|
||||
stackRequests: [],
|
||||
stackResponse: [],
|
||||
callback: undefined,
|
||||
isUpdating: false,
|
||||
linkStatus: {}
|
||||
};
|
||||
arr && arr.length>0 && arr.forEach(function(item) {
|
||||
var data;
|
||||
switch (item.asc_getType()) {
|
||||
case Asc.c_oAscExternalReferenceType.link:
|
||||
data = {link: item.asc_getData()};
|
||||
break;
|
||||
case Asc.c_oAscExternalReferenceType.path:
|
||||
data = {path: item.asc_getData()};
|
||||
break;
|
||||
case Asc.c_oAscExternalReferenceType.referenceData:
|
||||
data = {
|
||||
referenceData: item.asc_getData(),
|
||||
path: item.asc_getPath(),
|
||||
link: item.asc_getLink()
|
||||
};
|
||||
break;
|
||||
}
|
||||
data && me.externalData.stackRequests.push({data: data, id: item.asc_getId(), isExternal: item.asc_isExternalLink(), source: item.asc_getSource() || ''});
|
||||
});
|
||||
me.externalData.callback = callback;
|
||||
me.requestReferenceData();
|
||||
}
|
||||
},
|
||||
|
||||
requestReferenceData: function() {
|
||||
if (this.externalData.stackRequests.length>0) {
|
||||
var item = this.externalData.stackRequests.shift();
|
||||
this.externalData.linkStatus.id = item.id;
|
||||
this.externalData.linkStatus.source = item.source;
|
||||
this.externalData.linkStatus.isExternal = item.isExternal;
|
||||
Common.Gateway.requestReferenceData(item.data);
|
||||
}
|
||||
},
|
||||
|
||||
setReferenceData: function(data) {
|
||||
if (this.toolbar.mode.isEdit && this.toolbar.editMode) {
|
||||
if (data) {
|
||||
this.externalData.stackResponse.push(data);
|
||||
this.externalData.linkStatus.result = this.externalData.linkStatus.isExternal ? '' : data.error || '';
|
||||
if (this.externalLinksDlg) {
|
||||
this.externalLinksDlg.setLinkStatus(this.externalData.linkStatus.id, this.externalData.linkStatus.result);
|
||||
} else if (this.externalData.linkStatus.result && !this._state.isFromDlg)
|
||||
Common.NotificationCenter.trigger('showmessage', {msg: this.externalData.linkStatus.result + (this.externalData.linkStatus.source ? ' (' + this.externalData.linkStatus.source + ')' : '') });
|
||||
}
|
||||
if (this.externalData.stackRequests.length>0)
|
||||
this.requestReferenceData();
|
||||
else if (this.externalData.callback)
|
||||
this.externalData.callback(this.externalData.stackResponse);
|
||||
}
|
||||
},
|
||||
|
||||
onStartUpdateExternalReference: function(status) {
|
||||
this.externalData.isUpdating = status;
|
||||
if (this.externalLinksDlg) {
|
||||
this.externalLinksDlg.setIsUpdating(status);
|
||||
}
|
||||
!status && (this._state.isFromDlg = status);
|
||||
},
|
||||
|
||||
onNeedUpdateExternalReferenceOnOpen: function() {
|
||||
var value = this.api.asc_getUpdateLinks();
|
||||
Common.UI.warning({
|
||||
msg: value ? (!!window.SSE ? this.warnUpdateExternalAutoupdate : !!window.PE ? this.warnUpdateExternalAutoupdatePE : this.warnUpdateExternalAutoupdateDE) :
|
||||
(!!window.SSE ? this.warnUpdateExternalData : !!window.PE ? this.warnUpdateExternalDataPE : this.warnUpdateExternalDataDE),
|
||||
buttons: [{value: 'ok', caption: value ? this.textContinue : this.textUpdate, primary: true}, {value: 'cancel', caption: value ? this.textTurnOff : this.textDontUpdate}],
|
||||
maxwidth: 500,
|
||||
callback: _.bind(function(btn) {
|
||||
if (btn==='ok') {
|
||||
var links = this.api.asc_getExternalReferences();
|
||||
links && (links.length>0) && this.updateReferences(links);
|
||||
}
|
||||
value && this.api.asc_setUpdateLinks(btn==='ok', true);
|
||||
}, this)
|
||||
});
|
||||
},
|
||||
|
||||
onErrorUpdateExternalReference: function(id) {
|
||||
if (this.externalLinksDlg) {
|
||||
this.externalLinksDlg.setLinkStatus(id, this.txtErrorExternalLink);
|
||||
}
|
||||
},
|
||||
|
||||
onNeedUpdateExternalReference: function() {
|
||||
Common.NotificationCenter.trigger('showmessage', {msg: this.textAddExternalData});
|
||||
},
|
||||
|
||||
setReferenceSource: function(data) { // gateway
|
||||
if (this.toolbar.mode.isEdit && this.toolbar.editMode && this.api) {
|
||||
this.api.asc_changeExternalReference(this.externalSource.externalRef, data);
|
||||
}
|
||||
},
|
||||
|
||||
openLink: function(externalRef) {
|
||||
if (!externalRef) return;
|
||||
var data = this.api.asc_openExternalReference(externalRef);
|
||||
if (data) {
|
||||
switch (data.asc_getType()) {
|
||||
case Asc.c_oAscExternalReferenceType.link:
|
||||
data = {link: data.asc_getData()};
|
||||
break;
|
||||
case Asc.c_oAscExternalReferenceType.path:
|
||||
data = {path: data.asc_getData()};
|
||||
break;
|
||||
case Asc.c_oAscExternalReferenceType.referenceData:
|
||||
data = {
|
||||
referenceData: data.asc_getData(),
|
||||
path: data.asc_getPath()
|
||||
};
|
||||
break;
|
||||
}
|
||||
data.windowName = 'wname-' + Date.now();
|
||||
window.open("", data.windowName);
|
||||
Common.Gateway.requestOpen(data);
|
||||
}
|
||||
},
|
||||
|
||||
updateReferences: function(data, fromDlg) {
|
||||
this._state.isFromDlg = !!fromDlg;
|
||||
this.api && this.api.asc_updateExternalReferences(data);
|
||||
},
|
||||
|
||||
txtErrorExternalLink: 'Error: updating is failed',
|
||||
warnUpdateExternalData: 'This workbook contains links to one or more external sources that could be unsafe.<br>If you trust the links, update them to get the latest data.',
|
||||
warnUpdateExternalDataDE: 'This document contains links to one or more external sources that could be unsafe.<br>If you trust the links, update them to get the latest data.',
|
||||
warnUpdateExternalDataPE: 'This presentation contains links to one or more external sources that could be unsafe.<br>If you trust the links, update them to get the latest data.',
|
||||
textUpdate: 'Update',
|
||||
textDontUpdate: 'Don\'t Update',
|
||||
textAddExternalData: 'The link to an external source has been added. You can update such links in the Data tab.',
|
||||
textTurnOff: 'Turn off auto update',
|
||||
textContinue: 'Continue'
|
||||
|
||||
}, Common.Controllers.ExternalLinks || {}));
|
||||
});
|
||||
@ -151,7 +151,6 @@ define([
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onCloseMergeEditor', _.bind(this.onMergeEditingDisabled, this));
|
||||
this.api.asc_registerCallback('asc_sendFromGeneralToFrameEditor', _.bind(this.onSendFromGeneralToFrameEditor, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -266,10 +265,6 @@ define([
|
||||
}
|
||||
},
|
||||
|
||||
onSendFromGeneralToFrameEditor: function(data) {
|
||||
externalEditor && externalEditor.serviceCommand('generalToFrameData', data);
|
||||
},
|
||||
|
||||
warningTitle: 'Warning',
|
||||
warningText: 'The object is disabled because of editing by another user.',
|
||||
textClose: 'Close',
|
||||
|
||||
@ -60,7 +60,7 @@ define([
|
||||
height : '100%',
|
||||
documentType: 'cell',
|
||||
document : {
|
||||
url : '_chart_',
|
||||
url : '_ole_',
|
||||
permissions : {
|
||||
edit : true,
|
||||
download: false
|
||||
@ -153,7 +153,7 @@ define([
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onCloseOleEditor', _.bind(this.onOleEditingDisabled, this));
|
||||
this.api.asc_registerCallback('asc_sendFromGeneralToFrameEditor', _.bind(this.onSendFromGeneralToFrameEditor, this));
|
||||
this.api.asc_registerCallback('asc_sendFromGeneralToOleEditor', _.bind(this.onSendFromGeneralToFrameEditor, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -217,7 +217,7 @@ define([
|
||||
this.onOleEditingDisabled();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == 'oleEditorReady') {
|
||||
if (eventData.type == 'frameEditorReady') {
|
||||
if (this.needDisableEditing===undefined)
|
||||
this.oleEditorView.setControlsDisabled(false);
|
||||
} else
|
||||
|
||||
@ -48,6 +48,7 @@ Common.UI.ExternalUsers = new( function() {
|
||||
externalUsersInfo = [],
|
||||
isUsersInfoLoading = false,
|
||||
stackUsersInfoResponse = [],
|
||||
requestedUsersInfo = [],
|
||||
api,
|
||||
userColors = [];
|
||||
|
||||
@ -55,11 +56,13 @@ Common.UI.ExternalUsers = new( function() {
|
||||
if (type==='info') {
|
||||
(typeof ids !== 'object') && (ids = [ids]);
|
||||
ids && (ids = _.uniq(ids));
|
||||
ids = _.difference(ids, requestedUsersInfo);
|
||||
requestedUsersInfo = requestedUsersInfo.concat(ids);
|
||||
if (ids.length>100) {
|
||||
while (ids.length>0) {
|
||||
Common.Gateway.requestUsers('info', ids.splice(0, 100));
|
||||
}
|
||||
} else
|
||||
} else if (ids.length>0)
|
||||
Common.Gateway.requestUsers('info', ids);
|
||||
} else {
|
||||
if (isUsersLoading) return;
|
||||
|
||||
@ -274,7 +274,7 @@ define([
|
||||
//$('<div class="separator long"></div>').appendTo(me.$toolbarPanelPlugins);
|
||||
group = $('<div class="group" style="' + (Common.UI.isRTL() ? 'padding-right: 0;' : 'padding-left: 0;') + '"></div>');
|
||||
this.viewPlugins.backgroundBtn = this.viewPlugins.createBackgroundPluginsButton();
|
||||
var $backgroundSlot = $('<span class="btn-slot text x-huge"></span>').appendTo(group);
|
||||
var $backgroundSlot = $('<span class="btn-slot text x-huge" id="slot-background-plugin"></span>').appendTo(group);
|
||||
this.viewPlugins.backgroundBtn.render($backgroundSlot);
|
||||
this.viewPlugins.backgroundBtn.hide();
|
||||
|
||||
|
||||
605
apps/common/main/lib/controller/Shortcuts.js
Normal file
@ -0,0 +1,605 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2024
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
* version 3 as published by the Free Software Foundation. In accordance with
|
||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||
* of any third-party rights.
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
*
|
||||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||
* street, Riga, Latvia, EU, LV-1050.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of the Program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU AGPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||
* grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||
* well as technical writing content are licensed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created on 1/9/2025.
|
||||
*/
|
||||
|
||||
|
||||
define([
|
||||
'core'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.Controllers.Shortcuts = Backbone.Controller.extend(_.extend({
|
||||
initialize: function() {
|
||||
this.localStorageKey = '';
|
||||
if(window.DE) {
|
||||
this.localStorageKey = 'de-shortcuts';
|
||||
} else if(window.PDFE) {
|
||||
this.localStorageKey = 'pdfe-shortcuts';
|
||||
} else if(window.PE) {
|
||||
this.localStorageKey = 'pe-shortcuts';
|
||||
} else if(window.SSE) {
|
||||
this.localStorageKey = 'sse-shortcuts';
|
||||
} else if(window.VE) {
|
||||
this.localStorageKey = 've-shortcuts';
|
||||
}
|
||||
|
||||
this.actionsMap = {};
|
||||
this.eventsMap = {};
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
|
||||
this._fillActionsMap();
|
||||
api && this._applyShortcutsInSDK();
|
||||
this._eventsTrigger();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
keyCodeToKeyName: function(code) {
|
||||
const specialKeys = {
|
||||
8: 'Backspace',
|
||||
9: 'Tab',
|
||||
12: 'Clear',
|
||||
13: 'Enter',
|
||||
16: 'Shift',
|
||||
17: 'Ctrl',
|
||||
18: 'Alt',
|
||||
19: 'Pause',
|
||||
20: 'CapsLock',
|
||||
27: 'Escape',
|
||||
32: 'Space',
|
||||
33: 'PageUp',
|
||||
34: 'PageDown',
|
||||
35: 'End',
|
||||
36: 'Home',
|
||||
37: 'ArrowLeft',
|
||||
38: 'ArrowUp',
|
||||
39: 'ArrowRight',
|
||||
40: 'ArrowDown',
|
||||
44: 'PrintScreen',
|
||||
45: 'Insert',
|
||||
46: 'Delete',
|
||||
91: 'Meta',
|
||||
93: 'ContextMenu',
|
||||
96: "Num 0",
|
||||
97: "Num 1",
|
||||
98: "Num 2",
|
||||
99: "Num 3",
|
||||
100: "Num 4",
|
||||
101: "Num 5",
|
||||
102: "Num 6",
|
||||
103: "Num 7",
|
||||
104: "Num 8",
|
||||
105: "Num 9",
|
||||
106: "Num *",
|
||||
107: "Num +",
|
||||
108: "Num Enter",
|
||||
109: "Num -",
|
||||
110: "Num .",
|
||||
111: "Num /",
|
||||
112: 'F1',
|
||||
113: 'F2',
|
||||
114: 'F3',
|
||||
115: 'F4',
|
||||
116: 'F5',
|
||||
117: 'F6',
|
||||
118: 'F7',
|
||||
119: 'F8',
|
||||
120: 'F9',
|
||||
121: 'F10',
|
||||
122: 'F11',
|
||||
123: 'F12',
|
||||
144: 'NumLock',
|
||||
145: 'ScrollLock',
|
||||
173: 'ff-',
|
||||
61: 'ff=',
|
||||
186: ';',
|
||||
187: '=',
|
||||
188: ',',
|
||||
189: '-',
|
||||
190: '.',
|
||||
191: '/',
|
||||
192: '`',
|
||||
219: '[',
|
||||
220: '\\',
|
||||
221: ']',
|
||||
222: '\'',
|
||||
};
|
||||
|
||||
if (specialKeys[code]) {
|
||||
return specialKeys[code];
|
||||
}
|
||||
return String.fromCharCode(code);
|
||||
},
|
||||
|
||||
resetAllShortcuts: function() {
|
||||
const me = this;
|
||||
|
||||
this.api.asc_resetAllShortcutTypes();
|
||||
for (const actionType in Asc.c_oAscDefaultShortcuts) {
|
||||
const actionItem = this.getActionsMap()[actionType];
|
||||
actionItem.shortcuts = Asc.c_oAscDefaultShortcuts[actionType].map(function(ascShortcut) {
|
||||
return {
|
||||
keys: me._getAscShortcutKeys(ascShortcut),
|
||||
isCustom: false,
|
||||
ascShortcut: ascShortcut,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._eventsTrigger();
|
||||
Common.localStorage.setItem(this.localStorageKey, '');
|
||||
Common.NotificationCenter.trigger('shortcuts:update');
|
||||
},
|
||||
|
||||
updateShortcutsForAction: function(actionType, updatedShortcuts) {
|
||||
let resultShortcuts = [];
|
||||
const originalShortcuts = this.getActionsMap()[actionType].shortcuts;
|
||||
|
||||
// Update hidden status and create copies for those not in updatedShortcuts
|
||||
originalShortcuts.forEach(function(item) {
|
||||
const existsInUpdated = _.some(updatedShortcuts, function(el) {
|
||||
return el.ascShortcut.asc_GetShortcutIndex() === item.ascShortcut.asc_GetShortcutIndex();
|
||||
});
|
||||
if(!existsInUpdated && !item.ascShortcut.asc_IsHidden()) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(item.ascShortcut.asc_ToJson());
|
||||
item.ascShortcut = copyAscShortcut;
|
||||
}
|
||||
item.ascShortcut.asc_SetIsHidden(!existsInUpdated);
|
||||
resultShortcuts.push(item);
|
||||
});
|
||||
|
||||
// Add new custom shortcuts that are not in originalShortcuts
|
||||
updatedShortcuts.forEach(function(item) {
|
||||
const existsInOriginal = _.some(originalShortcuts, function(el) {
|
||||
return el.ascShortcut.asc_GetShortcutIndex() === item.ascShortcut.asc_GetShortcutIndex();
|
||||
});
|
||||
if(!existsInOriginal) {
|
||||
item.isCustom = true;
|
||||
resultShortcuts.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
const action = this.getActionsMap()[actionType];
|
||||
resultShortcuts = resultShortcuts.sort(this._sortComparator);
|
||||
action && (action.shortcuts = resultShortcuts);
|
||||
|
||||
// Remove shortcuts from other actions if they conflict with updated shortcuts
|
||||
const removableIndexes = updatedShortcuts.map(function(item) {
|
||||
return item.ascShortcut.asc_GetShortcutIndex()
|
||||
});
|
||||
const removableFromStorage = {};
|
||||
for (const type in this.getActionsMap()) {
|
||||
if(removableIndexes.length == 0) break;
|
||||
if(type == actionType) continue;
|
||||
|
||||
const shortcuts = this.getActionsMap()[type].shortcuts;
|
||||
const foundIndex = _.findIndex(shortcuts, function(shortcut) {
|
||||
const foundIndex = _.indexOf(removableIndexes, shortcut.ascShortcut.asc_GetShortcutIndex());
|
||||
(foundIndex != -1) && removableIndexes.splice(foundIndex, 1);
|
||||
return foundIndex != -1;
|
||||
});
|
||||
if(foundIndex != -1) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(shortcuts[foundIndex].ascShortcut.asc_ToJson());
|
||||
copyAscShortcut.asc_SetIsHidden(true);
|
||||
shortcuts[foundIndex].ascShortcut = copyAscShortcut;
|
||||
|
||||
!removableFromStorage[type] && (removableFromStorage[type] = []);
|
||||
removableFromStorage[type].push(shortcuts[foundIndex].ascShortcut);
|
||||
}
|
||||
}
|
||||
|
||||
this.api.asc_applyAscShortcuts(resultShortcuts.map(function(shortcut) {
|
||||
return shortcut.ascShortcut;
|
||||
}));
|
||||
|
||||
//Filter for save in local storage
|
||||
const savedInStorage = {
|
||||
[actionType] : _.filter(resultShortcuts, function(item) {
|
||||
return item.isCustom !== item.ascShortcut.asc_IsHidden();
|
||||
}).map(function(shortcut) {
|
||||
return shortcut.ascShortcut;
|
||||
})
|
||||
};
|
||||
this._saveModifiedShortcuts(savedInStorage, removableFromStorage);
|
||||
|
||||
Common.NotificationCenter.trigger('shortcuts:update');
|
||||
this._eventsTrigger([actionType].concat(_.keys(removableFromStorage)));
|
||||
},
|
||||
|
||||
getActionsMap: function() {
|
||||
return this.actionsMap;
|
||||
},
|
||||
|
||||
getDefaultShortcutActions: function() {
|
||||
if(window.DE || window.PDFE) {
|
||||
return Asc.c_oAscDocumentShortcutType;
|
||||
} else if(window.PE) {
|
||||
return Asc.c_oAscPresentationShortcutType;
|
||||
} else if(window.SSE) {
|
||||
return Asc.c_oAscSpreadsheetShortcutType;
|
||||
} else if(window.VE) {
|
||||
return Asc.c_oAscDiagramShortcutType;
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of shortcuts for the given action type.
|
||||
*
|
||||
* @param {string|number} actionType
|
||||
* The action type identifier. Can be:
|
||||
* - `string` — action type name ('Save', 'Undo', 'Copy' and so on)
|
||||
* - `number` — numeric action type id
|
||||
*
|
||||
* @returns {Array<{keys: string[], isCustom: boolean, ascShortcut: CAscShortcut}>|null}
|
||||
*
|
||||
* @example
|
||||
* getShortcutsByActionType('Save');
|
||||
* getShortcutsByActionType(7);
|
||||
*/
|
||||
getShortcutsByActionType: function(actionType, withHidden) {
|
||||
const actionTypeNumber = (typeof actionType === 'number')
|
||||
? actionType
|
||||
: this.getDefaultShortcutActions()[actionType];
|
||||
const actionItem = this.actionsMap[actionTypeNumber];
|
||||
let shortcuts = actionItem ? actionItem.shortcuts : null;
|
||||
if(!withHidden && shortcuts) {
|
||||
shortcuts = shortcuts.filter(function(shortcut) {
|
||||
return !shortcut.ascShortcut.asc_IsHidden();
|
||||
});
|
||||
}
|
||||
return shortcuts;
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates button hints for shortcuts.
|
||||
*
|
||||
* For each action type, finds the first visible shortcut (non-hidden)
|
||||
* and appends its key combination to the base label. Then applies the
|
||||
* updated hint to the button or via a custom callback.
|
||||
*
|
||||
* @param {Object<string, {
|
||||
* btn: Object,
|
||||
* label: string,
|
||||
* applyCallback?: function(Object, string):void,
|
||||
* ignoreUpdates?: boolean
|
||||
* }>} shortcutHints
|
||||
*
|
||||
* An object where:
|
||||
* - key is the action type (actionType),
|
||||
* - value is a config object:
|
||||
*
|
||||
* - `btn` {Object} — button object that provides `updateHint(string)` method.
|
||||
* - `label` {string} — the base label text for the hint.
|
||||
* - `applyCallback` [optional] — custom function to apply the generated hint text.
|
||||
* Receives `(item, hintText)` as arguments.
|
||||
* - `ignoreUpdates` [optional] — if `true`, will not be updated when shortcuts are updated
|
||||
*
|
||||
* @example
|
||||
* updateShortcutHints({
|
||||
* EditUndo: {
|
||||
* btn: btnUndo,
|
||||
* label: 'Undo'
|
||||
* },
|
||||
* EditRedo: {
|
||||
* label: 'Redo',
|
||||
* applyCallback: function(item, hintText) {
|
||||
* console.log('Custom hint:', text);
|
||||
* },
|
||||
* ignoreUpdates: true
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
updateShortcutHints: function(shortcutHints) {
|
||||
for (const actionType in shortcutHints) {
|
||||
const item = shortcutHints[actionType];
|
||||
if(item) {
|
||||
const callback = function() {
|
||||
const defaultShortcutsActions = this.getDefaultShortcutActions();
|
||||
const type = defaultShortcutsActions[actionType];
|
||||
const action = type ? this.actionsMap[type] : null;
|
||||
|
||||
const firstShortcut = action
|
||||
? _.find(action.shortcuts, (shortcut) => {
|
||||
return !shortcut.ascShortcut.asc_IsHidden();
|
||||
})
|
||||
: null;
|
||||
const hintText = (item.label || '') + (firstShortcut ? ' (' + firstShortcut.keys.join('+') + ')' : '');
|
||||
|
||||
if(item.applyCallback) {
|
||||
item.applyCallback(item, hintText);
|
||||
} else {
|
||||
item.btn.updateHint(hintText);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
callback();
|
||||
if(!item.ignoreUpdates) {
|
||||
!this.eventsMap[actionType] && (this.eventsMap[actionType] = []);
|
||||
this.eventsMap[actionType].push(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getDefaultShortcutActionsInvert: function() {
|
||||
if(!this._defaultShortcutsActionsInvert) {
|
||||
this._defaultShortcutsActionsInvert = _.invert(this.getDefaultShortcutActions());
|
||||
}
|
||||
return this._defaultShortcutsActionsInvert;
|
||||
},
|
||||
|
||||
_eventsTrigger: function(actionTypes) {
|
||||
const me = this;
|
||||
let lists = [];
|
||||
if(actionTypes) {
|
||||
lists = actionTypes.map(function(type) {
|
||||
type = (typeof +type === 'number')
|
||||
? me._getDefaultShortcutActionsInvert()[type]
|
||||
: type;
|
||||
return me.eventsMap[type];
|
||||
});
|
||||
} else {
|
||||
lists = _.values(this.eventsMap);
|
||||
}
|
||||
|
||||
_.each(lists, function(callbacks) {
|
||||
_.each(callbacks, function(cb) {
|
||||
cb && cb();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_fillActionsMap: function() {
|
||||
this.actionsMap = {};
|
||||
|
||||
const me = this;
|
||||
const shortcutActions = this.getDefaultShortcutActions();
|
||||
const unlockedTypes = Asc.c_oAscUnlockedShortcutActionTypes || {};
|
||||
for (let actionName in shortcutActions) {
|
||||
const type = shortcutActions[actionName];
|
||||
this.actionsMap[type] = {
|
||||
action: {
|
||||
name: this['txtLabel' + actionName],
|
||||
description: this['txtDescription' + actionName],
|
||||
type: type,
|
||||
isLocked: !unlockedTypes[type]
|
||||
},
|
||||
shortcuts: []
|
||||
}
|
||||
}
|
||||
|
||||
_.pairs(Asc.c_oAscDefaultShortcuts).forEach(function(item) {
|
||||
const actionType = item[0];
|
||||
const shortcuts = item[1];
|
||||
const actionItem = me.actionsMap[actionType];
|
||||
|
||||
if(actionItem) {
|
||||
actionItem.shortcuts = shortcuts.map(function(ascShortcut) {
|
||||
return {
|
||||
keys: me._getAscShortcutKeys(ascShortcut),
|
||||
isCustom: false,
|
||||
ascShortcut: ascShortcut,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let removableIndexes = {};
|
||||
_.pairs(me._getModifiedShortcuts()).forEach(function(item) {
|
||||
const actionType = item[0];
|
||||
const shortcuts = item[1];
|
||||
const actionItem = me.actionsMap[actionType];
|
||||
|
||||
if(actionItem) {
|
||||
shortcuts.forEach(function(ascShortcut) {
|
||||
const ascShortcutIndex = ascShortcut.asc_GetShortcutIndex();
|
||||
const defaultShortcutIndex = _.findIndex(actionItem.shortcuts, function(shortcut) {
|
||||
return shortcut.ascShortcut.asc_GetShortcutIndex() == ascShortcutIndex;
|
||||
});
|
||||
|
||||
if(defaultShortcutIndex != -1) {
|
||||
actionItem.shortcuts[defaultShortcutIndex].ascShortcut = ascShortcut;
|
||||
} else {
|
||||
removableIndexes[ascShortcutIndex] = actionType;
|
||||
actionItem.shortcuts.push({
|
||||
keys: me._getAscShortcutKeys(ascShortcut),
|
||||
isCustom: true,
|
||||
ascShortcut: ascShortcut,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
for (const actionType in this.actionsMap) {
|
||||
const item = this.actionsMap[actionType];
|
||||
const shortcuts = this.actionsMap[actionType].shortcuts;
|
||||
if(shortcuts.length == 0 && item.action.isLocked) {
|
||||
// Delete actions if it has no shortcuts and the action is locked
|
||||
delete this.actionsMap[actionType];
|
||||
} else if(Object.keys(removableIndexes).length > 0) {
|
||||
// Remove shortcuts from other actions if they conflict with updated shortcuts
|
||||
const foundIndex = _.findIndex(shortcuts, function(shortcut) {
|
||||
const ascShortcutIndex = shortcut.ascShortcut.asc_GetShortcutIndex();
|
||||
if(removableIndexes[ascShortcutIndex] && removableIndexes[ascShortcutIndex] != actionType) {
|
||||
delete removableIndexes[ascShortcutIndex];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(foundIndex != -1) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(shortcuts[foundIndex].ascShortcut.asc_ToJson());
|
||||
copyAscShortcut.asc_SetIsHidden(true);
|
||||
shortcuts[foundIndex].ascShortcut = copyAscShortcut;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_applyShortcutsInSDK: function() {
|
||||
const applyMethod = function(storage) {
|
||||
storage = JSON.parse(storage || Common.localStorage.getItem(this.localStorageKey) || "{}");
|
||||
for (const actionType in storage) {
|
||||
storage[actionType] = storage[actionType].map(function(ascShortcutJson) {
|
||||
const ascShortcut = new Asc.CAscShortcut();
|
||||
ascShortcut.asc_FromJson(ascShortcutJson);
|
||||
return ascShortcut;
|
||||
});
|
||||
}
|
||||
|
||||
this.api.asc_resetAllShortcutTypes();
|
||||
|
||||
const modifiedShortcuts = _.flatten(_.values(storage));
|
||||
if(modifiedShortcuts.length) {
|
||||
this.api.asc_applyAscShortcuts(modifiedShortcuts);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
$(window).on('storage', function (e) {
|
||||
if(e.key == this.localStorageKey) {
|
||||
applyMethod(e.originalEvent.newValue);
|
||||
this._fillActionsMap();
|
||||
this._eventsTrigger();
|
||||
Common.NotificationCenter.trigger('shortcuts:update');
|
||||
}
|
||||
}.bind(this))
|
||||
|
||||
applyMethod();
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves user-modified shortcuts from localStorage.
|
||||
* @returns {Object<number, CAscShortcut[]>}
|
||||
* An object where keys are action types and values are arrays of ascShortcut instances.
|
||||
*/
|
||||
_getModifiedShortcuts: function() {
|
||||
const storage = JSON.parse(Common.localStorage.getItem(this.localStorageKey) || "{}");
|
||||
for (const actionType in storage) {
|
||||
storage[actionType] = storage[actionType].map(function(ascShortcutJson) {
|
||||
const ascShortcut = new Asc.CAscShortcut();
|
||||
ascShortcut.asc_FromJson(ascShortcutJson);
|
||||
return ascShortcut;
|
||||
});
|
||||
}
|
||||
return storage;
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves modified shortcuts to localStorage by applying added and removed changes.
|
||||
* @param {Object<number, CAscShortcut[]>} savedActionsMap
|
||||
* An object containing new or updated shortcuts, grouped by action type.
|
||||
* @param {Object<number, CAscShortcut[]>} removedActionsMap
|
||||
* An object containing shortcuts to be removed, grouped by action type.
|
||||
* @example
|
||||
* this._saveModifiedShortcuts(
|
||||
* { "7": [ascShortcut1, ascShortcut2] },
|
||||
* { "52": [ascShortcut3] }
|
||||
* );
|
||||
* // Result:
|
||||
* // - For action type "7", shortcuts are replaced with [ascShortcut1, ascShortcut2]
|
||||
* // - For action type "52", ascShortcut3 is removed
|
||||
* // - The final shortcuts are saved to localStorage
|
||||
*/
|
||||
_saveModifiedShortcuts: function(savedActionsMap, removedActionsMap) {
|
||||
const customShortcuts = _.extend({}, this._getModifiedShortcuts(), savedActionsMap || {});
|
||||
|
||||
for (const actionType in removedActionsMap || {}) {
|
||||
if (!customShortcuts[actionType]) continue;
|
||||
|
||||
const removed = removedActionsMap[actionType];
|
||||
customShortcuts[actionType] = _.filter(customShortcuts[actionType], function(ascShortcut) {
|
||||
return !_.some(removed, function(r) {
|
||||
return ascShortcut.asc_GetShortcutIndex() === r.asc_GetShortcutIndex();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const actionType in customShortcuts) {
|
||||
customShortcuts[actionType] = customShortcuts[actionType].map(function(ascShortcut) {
|
||||
return ascShortcut.asc_ToJson();
|
||||
});
|
||||
}
|
||||
Common.localStorage.setItem(this.localStorageKey, JSON.stringify(customShortcuts));
|
||||
},
|
||||
|
||||
_getAscShortcutKeys: function(ascShortcut) {
|
||||
const keys = [];
|
||||
ascShortcut.asc_IsCommand() && keys.push('⌘');
|
||||
ascShortcut.asc_IsCtrl() && keys.push('Ctrl');
|
||||
ascShortcut.asc_IsAlt() && keys.push('Alt');
|
||||
ascShortcut.asc_IsShift() && keys.push('Shift');
|
||||
keys.push(this.keyCodeToKeyName(ascShortcut.asc_GetKeyCode()));
|
||||
return keys;
|
||||
},
|
||||
|
||||
_sortComparator: function(first, second) {
|
||||
const priorityModifierKeys = ['asc_IsCommand', 'asc_IsCtrl', 'asc_IsAlt', 'asc_IsShift'];
|
||||
function getWeight(ascShortcut) {
|
||||
// Search for the first modifier key
|
||||
let keyIndex = priorityModifierKeys.length;
|
||||
for (let i = 0; i < priorityModifierKeys.length; i++) {
|
||||
if (ascShortcut[priorityModifierKeys[i]]()) {
|
||||
keyIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyIndex === priorityModifierKeys.length) return -1;
|
||||
|
||||
// Count extra modifier keys
|
||||
let extras = 0;
|
||||
for (let j = 0; j < priorityModifierKeys.length; j++) {
|
||||
if (j !== keyIndex && ascShortcut[priorityModifierKeys[j]]()) extras++;
|
||||
}
|
||||
|
||||
// weight = range for main key + “cost” of extra keys
|
||||
return keyIndex * 100 + extras;
|
||||
}
|
||||
let wFirst = getWeight(first.ascShortcut);
|
||||
let wSecond = getWeight(second.ascShortcut);
|
||||
|
||||
if (wFirst !== wSecond) return wFirst - wSecond;
|
||||
|
||||
return first.ascShortcut.asc_GetKeyCode() - second.ascShortcut.asc_GetKeyCode();
|
||||
}
|
||||
}, Common.Controllers.Shortcuts || {}));
|
||||
});
|
||||
@ -70,7 +70,7 @@ define([
|
||||
--sk-canvas-page-border: #dde0e5; --sk-canvas-line: rgba(0,0,0,.05);
|
||||
--sk-height-formula: 24px; --sk-padding-formula: 0 0 4px 0;
|
||||
--sk-border-style-formula: solid; --sk-gap-formula-field: 20px;
|
||||
--sk-border-radius-formula-field: 0px;
|
||||
--sk-border-radius-formula-field: 0px; --sk-layout-padding-placeholder: 46px auto;
|
||||
}`
|
||||
},
|
||||
},
|
||||
@ -91,7 +91,7 @@ define([
|
||||
--sk-canvas-page-border: #dde0e5; --sk-canvas-line: rgba(0,0,0,.05);
|
||||
--sk-height-formula: 24px; --sk-padding-formula: 0 0 4px 0;
|
||||
--sk-border-style-formula: solid; --sk-gap-formula-field: 20px;
|
||||
--sk-border-radius-formula-field: 0px;
|
||||
--sk-border-radius-formula-field: 0px; --sk-layout-padding-placeholder: 46px auto;
|
||||
}`
|
||||
},
|
||||
},
|
||||
@ -113,7 +113,7 @@ define([
|
||||
--sk-canvas-page-border: #555; --sk-canvas-line: rgba(0,0,0,.05);
|
||||
--sk-height-formula: 24px; --sk-padding-formula: 0 0 4px 0;
|
||||
--sk-border-style-formula: solid; --sk-gap-formula-field: 20px;
|
||||
--sk-border-radius-formula-field: 0px;
|
||||
--sk-border-radius-formula-field: 0px; --sk-layout-padding-placeholder: 46px auto;
|
||||
}
|
||||
.content-theme-dark {
|
||||
--sk-canvas-content-background: #3a3a3a; --sk-canvas-page-border: #616161;
|
||||
@ -139,7 +139,7 @@ define([
|
||||
--sk-canvas-page-border: #555; --sk-canvas-line: rgba(0,0,0,.05);
|
||||
--sk-height-formula: 24px; --sk-padding-formula: 0 0 4px 0;
|
||||
--sk-border-style-formula: solid; --sk-gap-formula-field: 20px;
|
||||
--sk-border-radius-formula-field: 0px;
|
||||
--sk-border-radius-formula-field: 0px; --sk-layout-padding-placeholder: 46px auto;
|
||||
}
|
||||
.content-theme-dark {
|
||||
--sk-canvas-content-background: #3a3a3a;
|
||||
@ -164,7 +164,7 @@ define([
|
||||
--sk-canvas-page-border: #ccc; --sk-canvas-line: rgba(0,0,0,.05);
|
||||
--sk-height-formula: 24px; --sk-padding-formula: 0 0 4px 0;
|
||||
--sk-border-style-formula: solid; --sk-gap-formula-field: 20px;
|
||||
--sk-border-radius-formula-field: 0px;
|
||||
--sk-border-radius-formula-field: 0px; --sk-layout-padding-placeholder: 46px auto;
|
||||
}`
|
||||
},
|
||||
},
|
||||
@ -360,6 +360,22 @@ define([
|
||||
return out_object;
|
||||
}
|
||||
|
||||
const validate_vars = function (obj) {
|
||||
if ( obj ) {
|
||||
let i = 0, count = 5;
|
||||
for (const value of Object.values(obj)) {
|
||||
if (value != "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ++i < count )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var create_colors_css = function (id, colors) {
|
||||
if ( !!colors && !!id ) {
|
||||
var _css_array = [':root .', id, '{'];
|
||||
@ -563,27 +579,31 @@ define([
|
||||
}
|
||||
|
||||
const colors_obj = get_current_theme_colors();
|
||||
colors_obj.type = themes_map[theme_id].type;
|
||||
colors_obj.name = theme_id;
|
||||
this.api.asc_setSkin(colors_obj);
|
||||
if ( validate_vars(colors_obj) ) {
|
||||
colors_obj.type = themes_map[theme_id].type;
|
||||
colors_obj.name = theme_id;
|
||||
this.api.asc_setSkin(colors_obj);
|
||||
|
||||
if ( !(Common.Utils.isIE10 || Common.Utils.isIE11) ) {
|
||||
// if ( themes_map[id].source != 'static' ) { // TODO: check writing styles
|
||||
const theme_obj = Object.assign({
|
||||
id:id,
|
||||
colors: colors_obj},
|
||||
themes_map[id]);
|
||||
delete theme_obj.source;
|
||||
if ( !(Common.Utils.isIE10 || Common.Utils.isIE11) ) {
|
||||
const theme_str = Common.localStorage.getItem("ui-theme");
|
||||
let theme_id;
|
||||
if ( theme_str ) {
|
||||
const reid = /id":\s?"([\w-]+)/.exec(theme_str);
|
||||
if ( reid[1] ) {
|
||||
theme_id = reid[1];
|
||||
}
|
||||
}
|
||||
|
||||
// const theme_obj = {
|
||||
// id: id,
|
||||
// type: themes_map[id].type,
|
||||
// text: themes_map[id].text,
|
||||
// colors: colors_obj,
|
||||
// };
|
||||
if ( theme_id !== id ) {
|
||||
|
||||
Common.localStorage.setItem('ui-theme', JSON.stringify(theme_obj));
|
||||
// }
|
||||
// if ( themes_map[id].source != 'static' ) { // TODO: check writing styles
|
||||
const theme_obj = Object.assign({id:id, colors: colors_obj},
|
||||
themes_map[id]);
|
||||
delete theme_obj.source;
|
||||
|
||||
Common.localStorage.setItem('ui-theme', JSON.stringify(theme_obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
theme_props = {};
|
||||
}
|
||||
@ -622,6 +642,12 @@ define([
|
||||
this.api = api;
|
||||
|
||||
const theme_id = window.uitheme.relevant_theme_id();
|
||||
if ( window.uitheme.type && themes_map[theme_id] &&
|
||||
window.uitheme.type !== themes_map[theme_id].type )
|
||||
{
|
||||
apply_theme.call(this, window.uitheme.id);
|
||||
}
|
||||
|
||||
const obj = get_current_theme_colors(name_colors);
|
||||
obj.type = window.uitheme.type ? window.uitheme.type : themes_map[theme_id] ? themes_map[theme_id].type : THEME_TYPE_LIGHT;
|
||||
obj.name = theme_id;
|
||||
@ -772,6 +798,10 @@ define([
|
||||
}
|
||||
} else if (prop==='tab-style') {
|
||||
return (Common.Utils.isIE || Common.Controllers.Desktop && Common.Controllers.Desktop.isWinXp()) ? 'fill' : window.getComputedStyle(document.body).getPropertyValue("--toolbar-preferred-tab-style") || 'line';
|
||||
} else if (prop==='small-btn-size') {
|
||||
if (!theme_props[prop]) {
|
||||
theme_props[prop] = window.getComputedStyle(document.body).getPropertyValue("--x-small-btn-size") || '20px';
|
||||
}
|
||||
}
|
||||
return theme_props[prop];
|
||||
}
|
||||
|
||||
@ -6,22 +6,22 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large">
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label"><%= scope.textAxisTitle %></label>
|
||||
<div id="chart-dlg-combo-hor-title-<%=idx%>" class="input-group-nr"></div>
|
||||
<div id="chart-dlg-combo-hor-title-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-large">
|
||||
<label class="input-label margin-left-15"><%= scope.textGridLines %></label>
|
||||
<div id="chart-dlg-combo-hor-grid-<%=idx%>" class="input-group-nr margin-left-15"></div>
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label margin-left-7"><%= scope.textGridLines %></label>
|
||||
<div id="chart-dlg-combo-hor-grid-<%=idx%>" class="input-group-nr margin-left-7"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cols="3" style="width: 100%" role="presentation">
|
||||
<tr>
|
||||
<td class="padding-small" width="100">
|
||||
<td class="padding-small" width="110">
|
||||
<label class="input-label"><%= scope.textAxisCrosses %></label>
|
||||
</td>
|
||||
<td class="padding-small padding-right-10" width="115">
|
||||
<td class="padding-small padding-right-10" width="120">
|
||||
<div id="chart-dlg-combo-h-crosstype-<%=idx%>"></div>
|
||||
</td>
|
||||
<td class="padding-small" width="90">
|
||||
@ -29,7 +29,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large" width="100">
|
||||
<td class="padding-large" width="110">
|
||||
<label class="input-label"><%= scope.textAxisPos %></label>
|
||||
</td>
|
||||
<td colspan=2 class="padding-large">
|
||||
@ -51,13 +51,13 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-small" width="140">
|
||||
<td class="padding-small" width="50%">
|
||||
<label class="input-label"><%= scope.textMajorType %></label>
|
||||
<div id="chart-dlg-combo-h-major-type-<%=idx%>" class="input-group-nr"></div>
|
||||
<div id="chart-dlg-combo-h-major-type-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-small">
|
||||
<label class="input-label margin-left-15"><%= scope.textMinorType %></label>
|
||||
<div id="chart-dlg-combo-h-minor-type-<%=idx%>" class="input-group-nr margin-left-15"></div>
|
||||
<td class="padding-small" width="50%">
|
||||
<label class="input-label margin-left-7"><%= scope.textMinorType %></label>
|
||||
<div id="chart-dlg-combo-h-minor-type-<%=idx%>" class="input-group-nr margin-left-7"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -66,10 +66,10 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large" width="140">
|
||||
<div id="chart-dlg-input-marks-interval-<%=idx%>"></div>
|
||||
<td class="padding-large" width="50%">
|
||||
<div id="chart-dlg-input-marks-interval-<%=idx%>" class="margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-large">
|
||||
<td class="padding-large" width="50%">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -82,13 +82,13 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-small" width="140">
|
||||
<td class="padding-small" width="50%">
|
||||
<label class="input-label"><%= scope.textLabelPos %></label>
|
||||
<div id="chart-dlg-combo-h-label-pos-<%=idx%>" class="input-group-nr"></div>
|
||||
<div id="chart-dlg-combo-h-label-pos-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-small">
|
||||
<label class="input-label margin-left-15"><%= scope.textLabelDist %></label>
|
||||
<div id="chart-dlg-input-label-dist-<%=idx%>" class="margin-left-15"></div>
|
||||
<td class="padding-small" width="50%">
|
||||
<label class="input-label margin-left-7"><%= scope.textLabelDist %></label>
|
||||
<div id="chart-dlg-input-label-dist-<%=idx%>" class="margin-left-7"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -6,22 +6,22 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large">
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label"><%= scope.textAxisTitle %></label>
|
||||
<div id="chart-dlg-combo-vert-title-<%=idx%>" class="input-group-nr"></div>
|
||||
<div id="chart-dlg-combo-vert-title-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-large">
|
||||
<label class="input-label margin-left-15"><%= scope.textGridLines %></label>
|
||||
<div id="chart-dlg-combo-vert-grid-<%=idx%>" class="input-group-nr margin-left-15"></div>
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label margin-left-7"><%= scope.textGridLines %></label>
|
||||
<div id="chart-dlg-combo-vert-grid-<%=idx%>" class="input-group-nr margin-left-7"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cols="3" style="width: 100%" role="presentation">
|
||||
<tr>
|
||||
<td class="padding-small" width="100">
|
||||
<td class="padding-small" width="110">
|
||||
<label class="input-label"><%= scope.textMinValue %></label>
|
||||
</td>
|
||||
<td class="padding-small padding-right-10" width="115">
|
||||
<td class="padding-small padding-right-10" width="120">
|
||||
<div id="chart-dlg-combo-mintype-<%=idx%>"></div>
|
||||
</td>
|
||||
<td class="padding-small" width="90">
|
||||
@ -29,10 +29,10 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-small" width="100">
|
||||
<td class="padding-small" width="110">
|
||||
<label class="input-label"><%= scope.textMaxValue %></label>
|
||||
</td>
|
||||
<td class="padding-small padding-right-10" width="115">
|
||||
<td class="padding-small padding-right-10" width="120">
|
||||
<div id="chart-dlg-combo-maxtype-<%=idx%>"></div>
|
||||
</td>
|
||||
<td class="padding-small" width="90">
|
||||
@ -40,10 +40,10 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large" width="100">
|
||||
<td class="padding-large" width="110">
|
||||
<label class="input-label"><%= scope.textAxisCrosses %></label>
|
||||
</td>
|
||||
<td class="padding-large padding-right-10" width="115">
|
||||
<td class="padding-large padding-right-10" width="120">
|
||||
<div id="chart-dlg-combo-v-crosstype-<%=idx%>"></div>
|
||||
</td>
|
||||
<td class="padding-large" width="90">
|
||||
@ -53,10 +53,10 @@
|
||||
</table>
|
||||
<table cols="2" role="presentation">
|
||||
<tr>
|
||||
<td class="padding-small padding-right-10" style="min-width: 100px;">
|
||||
<td class="padding-small padding-right-10" style="min-width: 110px;">
|
||||
<label class="input-label"><%= scope.textUnits %></label>
|
||||
</td>
|
||||
<td class="padding-small padding-right-10" width="115">
|
||||
<td class="padding-small padding-right-10" width="120>
|
||||
<div id="chart-dlg-combo-units-<%=idx%>"></div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -90,13 +90,13 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding-large">
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label"><%= scope.textMajorType %></label>
|
||||
<div id="chart-dlg-combo-v-major-type-<%=idx%>" class="input-group-nr"></div>
|
||||
<div id="chart-dlg-combo-v-major-type-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td class="padding-large">
|
||||
<label class="input-label margin-left-15"><%= scope.textMinorType %></label>
|
||||
<div id="chart-dlg-combo-v-minor-type-<%=idx%>" class="input-group-nr margin-left-15"></div>
|
||||
<td class="padding-large" width="50%">
|
||||
<label class="input-label margin-left-7"><%= scope.textMinorType %></label>
|
||||
<div id="chart-dlg-combo-v-minor-type-<%=idx%>" class="input-group-nr margin-left-7"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -112,11 +112,11 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="chart-dlg-combo-v-label-pos-<%=idx%>" class="input-group-nr"></div>
|
||||
<td width="50%">
|
||||
<div id="chart-dlg-combo-v-label-pos-<%=idx%>" class="input-group-nr margin-right-7"></div>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-text-default auto margin-left-15" id="chart-dlg-btn-v-format-<%=idx%>" style="min-width: 100px;"><%= scope.textFormat %></button>
|
||||
<td width="50%">
|
||||
<button type="button" class="btn btn-text-default auto margin-left-7" id="chart-dlg-btn-v-format-<%=idx%>" style="min-width: 100px;"><%= scope.textFormat %></button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
<div style="padding:10px 0 0 0;">
|
||||
<label class="input-label" style="width:12px;">#</label>
|
||||
<input id="extended-text-color" type="text" role="textbox" style="width:67px;display:inline-block;" class="vertical-align-middle text-align-right">
|
||||
<input id="extended-text-color" type="text" role="textbox" style="width:67px;display:inline-block;" class="vertical-align-middle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<div id="search-header">
|
||||
<label id="search-adv-title" role="heading"></label>
|
||||
<div id="search-btn-close" class="float-right"></div>
|
||||
<div id="search-btn-redact-open" class="float-right redact-no-replace-btn"></div>
|
||||
</div>
|
||||
<div id="search-container">
|
||||
<div id="search-adv-settings">
|
||||
@ -19,8 +20,7 @@
|
||||
<%= scope.textSearchResults %>
|
||||
</label>
|
||||
<div class="search-nav-btns float-right">
|
||||
<div id="search-adv-back"></div>
|
||||
<div id="search-adv-next"></div>
|
||||
<div id="search-adv-back"></div><div id="search-adv-next"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -30,6 +30,12 @@
|
||||
<button type="button" class="btn btn-text-default" id="search-adv-replace-all" data-hint="1" data-hint-direction="bottom" data-hint-offset="big"><%= scope.textReplaceAll %></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="redact-setting">
|
||||
<td class="padding-large">
|
||||
<button type="button" class="btn btn-text-default" id="search-adv-mark" data-hint="1" data-hint-direction="bottom" data-hint-offset="big"><%= scope.textMark %></button>
|
||||
<button type="button" class="btn btn-text-default" id="search-adv-mark-all" data-hint="1" data-hint-direction="bottom" data-hint-offset="big"><%= scope.textMarkAll %></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="search-options-block">
|
||||
<td class="padding-large">
|
||||
<div id="open-search-options" data-hint="1" data-hint-direction="left" data-hint-offset="0, -15">
|
||||
|
||||
@ -441,6 +441,33 @@ Common.util.LanguageInfo = new(function() {
|
||||
0x0433 : ["ven-ZA", "South Africa", "South Africa"]
|
||||
};
|
||||
|
||||
var getLocalLanguageName = function(code) {
|
||||
return localLanguageName[code] || ['', code];
|
||||
};
|
||||
|
||||
var getLocalLanguageDisplayName = function(code) {
|
||||
var lang = localLanguageName[code];
|
||||
if(lang) {
|
||||
var nativeName = lang[1];
|
||||
var englishName = lang[2];
|
||||
function replaceBrackets(text) {
|
||||
let newText = text.replace('(', '– ');
|
||||
let lastCloseBracketIndex = newText.lastIndexOf(')');
|
||||
if (lastCloseBracketIndex !== -1) {
|
||||
newText = newText.slice(0, lastCloseBracketIndex) + newText.slice(lastCloseBracketIndex + 1);
|
||||
}
|
||||
return newText;
|
||||
}
|
||||
|
||||
if(englishName) {
|
||||
return { native: replaceBrackets(nativeName), english: replaceBrackets(englishName) };
|
||||
} else {
|
||||
return { native: nativeName, english: ''};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var defLanguages = {
|
||||
'ar': 0x0401, // ar-SA
|
||||
'az': 0x042C, // az-Latn-AZ
|
||||
@ -459,10 +486,10 @@ Common.util.LanguageInfo = new(function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
var regionalData;
|
||||
|
||||
return {
|
||||
getLocalLanguageName: function(code) {
|
||||
return localLanguageName[code] || ['', code];
|
||||
},
|
||||
getLocalLanguageName: getLocalLanguageName,
|
||||
|
||||
getLocalLanguageCode: _getLocalLanguageCode,
|
||||
|
||||
@ -477,28 +504,7 @@ Common.util.LanguageInfo = new(function() {
|
||||
* If the English name is missing, returns an object with an empty string for English.
|
||||
* Returns `null` if no language code is found.
|
||||
*/
|
||||
getLocalLanguageDisplayName: function(code) {
|
||||
var lang = localLanguageName[code];
|
||||
if(lang) {
|
||||
var nativeName = lang[1];
|
||||
var englishName = lang[2];
|
||||
function replaceBrackets(text) {
|
||||
let newText = text.replace('(', '– ');
|
||||
let lastCloseBracketIndex = newText.lastIndexOf(')');
|
||||
if (lastCloseBracketIndex !== -1) {
|
||||
newText = newText.slice(0, lastCloseBracketIndex) + newText.slice(lastCloseBracketIndex + 1);
|
||||
}
|
||||
return newText;
|
||||
}
|
||||
|
||||
if(englishName) {
|
||||
return { native: replaceBrackets(nativeName), english: replaceBrackets(englishName) };
|
||||
} else {
|
||||
return { native: nativeName, english: ''};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getLocalLanguageDisplayName: getLocalLanguageDisplayName,
|
||||
|
||||
getDefaultLanguageCode: function(name) {
|
||||
name = name.toLowerCase();
|
||||
@ -510,6 +516,23 @@ Common.util.LanguageInfo = new(function() {
|
||||
|
||||
getLanguages: function() {
|
||||
return localLanguageName;
|
||||
},
|
||||
|
||||
getRegionalData: function() {
|
||||
if (regionalData) return regionalData;
|
||||
|
||||
regionalData = [{ value: 0x0401 }, { value: 0x042C }, { value: 0x0402 }, { value: 0x0405 }, { value: 0x0406 }, { value: 0x0C07 }, { value: 0x0407 }, {value: 0x0807}, { value: 0x0408 }, { value: 0x0C09 }, { value: 0x3809 }, { value: 0x0809 }, { value: 0x0409 }, { value: 0x0C0A }, { value: 0x080A },
|
||||
{ value: 0x040B }, { value: 0x040C }, { value: 0x100C }, { value: 0x0421 }, { value: 0x0410 }, { value: 0x0810 }, { value: 0x0411 }, { value: 0x0412 }, { value: 0x0426 }, { value: 0x040E }, { value: 0x0413 }, { value: 0x0415 }, { value: 0x0416 },
|
||||
{ value: 0x0816 }, { value: 0x0419 }, { value: 0x041B }, { value: 0x0424 }, { value: 0x281A }, { value: 0x241A }, { value: 0x081D }, { value: 0x041D }, { value: 0x041F }, { value: 0x0422 }, { value: 0x042A }, { value: 0x0804 }, { value: 0x0404 }];
|
||||
|
||||
regionalData.forEach(function(item) {
|
||||
var langinfo = getLocalLanguageName(item.value);
|
||||
var displayName = getLocalLanguageDisplayName(item.value);
|
||||
item.displayValue = displayName.native;
|
||||
item.displayValueEn = displayName.english;
|
||||
item.langName = langinfo[0];
|
||||
});
|
||||
return regionalData;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
@ -132,6 +132,7 @@ const tip = function ($) {
|
||||
|
||||
if (this.options.arrow === false) $tip.addClass('arrow-free');
|
||||
if (this.options.cls) $tip.addClass(this.options.cls);
|
||||
if (this.options.dir) $tip.attr('dir', this.options.dir);
|
||||
|
||||
var placementEx = (typeof this.options.placement !== 'function') ? /^([a-zA-Z]+)-?([a-zA-Z]*)$/.exec(this.options.placement) : null;
|
||||
if (!at && placementEx && !placementEx[2].length) {
|
||||
|
||||
@ -215,7 +215,7 @@ define([], function () {
|
||||
return false;
|
||||
},
|
||||
getBoundingClientRect = function(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let rect = _extend_object({}, element.getBoundingClientRect());
|
||||
if (!isOffsetUsedZoom())
|
||||
return rect;
|
||||
|
||||
@ -233,13 +233,13 @@ define([], function () {
|
||||
return newRect;
|
||||
},
|
||||
getOffset = function($element) {
|
||||
let pos = $element.offset();
|
||||
let pos = _extend_object({}, $element.offset());
|
||||
if (!isOffsetUsedZoom())
|
||||
return pos;
|
||||
return {left: pos.left * me.zoom, top: pos.top * me.zoom};
|
||||
},
|
||||
getPosition = function($element) {
|
||||
let pos = $element.position();
|
||||
let pos = _extend_object({}, $element.position());
|
||||
if (!isOffsetUsedZoom())
|
||||
return pos;
|
||||
return {left: pos.left * me.zoom, top: pos.top * me.zoom};
|
||||
@ -1600,6 +1600,12 @@ define([], function () {
|
||||
paletteWidth: 174
|
||||
};
|
||||
|
||||
Common.UI.blockOperations = {
|
||||
ApplyEditRights: -255,
|
||||
LoadingDocument: -256,
|
||||
UpdateChart: -257
|
||||
};
|
||||
|
||||
Common.UI.isValidNumber = function (val) {
|
||||
let regstr = new RegExp('^\s*[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)\s*$');
|
||||
if (typeof val === 'string') {
|
||||
|
||||
@ -152,9 +152,9 @@ define([], function () { 'use strict';
|
||||
$window.find('.body > .box').css('height', height);
|
||||
},
|
||||
|
||||
fixHeight: function() { // check height of the content
|
||||
fixHeight: function(force) { // check height of the content
|
||||
let diff = this.content_panels.filter('.active').height() - this.content_panel.height();
|
||||
(diff>0) && this.setInnerHeight(parseInt(this.$window.find('.body > .box').css('height')) + diff);
|
||||
(force || diff>0) && this.setInnerHeight(parseInt(this.$window.find('.body > .box').css('height')) + diff);
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
|
||||
@ -351,7 +351,6 @@ define([
|
||||
iconCls: 'toolbar__icon btn-more',
|
||||
hint: this.textSort,
|
||||
menu: new Common.UI.Menu({
|
||||
style: 'min-width: auto;',
|
||||
items: [
|
||||
{
|
||||
caption: this.mniDateDesc,
|
||||
@ -399,8 +398,41 @@ define([
|
||||
},
|
||||
{
|
||||
caption: '--',
|
||||
visible: false
|
||||
visible: true
|
||||
},
|
||||
this.menuFilterComments = new Common.UI.MenuItem({
|
||||
caption: this.mniFilterComments,
|
||||
checkable: false,
|
||||
visible: true,
|
||||
menu: new Common.UI.Menu({
|
||||
menuAlign: 'tl-tr',
|
||||
style: 'min-width: auto;',
|
||||
items: [
|
||||
{
|
||||
caption: this.textOpen,
|
||||
checkable: true,
|
||||
visible: true,
|
||||
toggleGroup: 'filterstatus',
|
||||
value: 'open'
|
||||
},
|
||||
{
|
||||
caption: this.textResolved,
|
||||
checkable: true,
|
||||
visible: true,
|
||||
toggleGroup: 'filterstatus',
|
||||
value: 'resolved'
|
||||
},
|
||||
{
|
||||
caption: this.textAll,
|
||||
checkable: true,
|
||||
visible: true,
|
||||
toggleGroup: 'filterstatus',
|
||||
value: 'all',
|
||||
checked: true
|
||||
}
|
||||
]
|
||||
})
|
||||
}),
|
||||
this.menuFilterGroups = new Common.UI.MenuItem({
|
||||
caption: this.mniFilterGroups,
|
||||
checkable: false,
|
||||
@ -441,7 +473,9 @@ define([
|
||||
this.buttonCancel.on('click', _.bind(this.onClickCancelDocumentComment, this));
|
||||
this.buttonClose.on('click', _.bind(this.onClickClosePanel, this));
|
||||
this.buttonSort.menu.on('item:toggle', _.bind(this.onSortClick, this));
|
||||
this.buttonSort.menu.on('show:before', _.bind(this.onShowBeforeSortButtonMenu, this));
|
||||
this.menuFilterGroups.menu.on('item:toggle', _.bind(this.onFilterGroupsClick, this));
|
||||
this.menuFilterComments.menu.on('item:toggle', _.bind(this.onFilterCommentsClick, this));
|
||||
this.mnuAddCommentToDoc.on('click', _.bind(this.onClickShowBoxDocumentComment, this));
|
||||
this.buttonAddNew.on('click', _.bind(this.onClickAddNewComment, this));
|
||||
|
||||
@ -903,10 +937,18 @@ define([
|
||||
state && this.fireEvent('comment:sort', [item.value]);
|
||||
},
|
||||
|
||||
onShowBeforeSortButtonMenu: function(menu, item, state) {
|
||||
Common.UI.TooltipManager.closeTip('commentFilter');
|
||||
},
|
||||
|
||||
onFilterGroupsClick: function(menu, item, state) {
|
||||
state && this.fireEvent('comment:filtergroups', [item.value]);
|
||||
},
|
||||
|
||||
onFilterCommentsClick: function(menu, item, state) {
|
||||
state && this.fireEvent('comment:filtercomments', [item.value]);
|
||||
},
|
||||
|
||||
onClickClosePanel: function() {
|
||||
Common.NotificationCenter.trigger('leftmenu:change', 'hide');
|
||||
},
|
||||
@ -921,6 +963,7 @@ define([
|
||||
textClose : 'Close',
|
||||
textResolved : 'Resolved',
|
||||
textResolve : 'Resolve',
|
||||
textOpen : 'Open',
|
||||
textEnterCommentHint : 'Enter your comment here',
|
||||
textEdit : 'Edit',
|
||||
textAdd : "Add",
|
||||
@ -937,6 +980,7 @@ define([
|
||||
textClosePanel: 'Close comments',
|
||||
textViewResolved: 'You have not permission for reopen comment',
|
||||
mniFilterGroups: 'Filter by Group',
|
||||
mniFilterComments: 'Show comments',
|
||||
textAll: 'All',
|
||||
txtEmpty: 'There are no comments in the document.',
|
||||
textSortFilter: 'Sort and filter comments',
|
||||
|
||||
@ -55,20 +55,31 @@ define([], function () { 'use strict';
|
||||
buttons: ['ok']
|
||||
}, options || {});
|
||||
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
const shortcutsController = app.getController('Common.Controllers.Shortcuts');
|
||||
|
||||
const keysShortcuts = { Copy: '', Cut: '', Paste: ''};
|
||||
for (const actionType in keysShortcuts) {
|
||||
const shortcuts = shortcutsController.getShortcutsByActionType(actionType);
|
||||
if(shortcuts && shortcuts[0]) {
|
||||
keysShortcuts[actionType] = shortcuts[0].keys.join('+');
|
||||
}
|
||||
}
|
||||
|
||||
this.template = [
|
||||
'<div class="box">',
|
||||
'<p class="message">' + this.textMsg + '</p>',
|
||||
'<div class="hotkeys">',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+C', '{0}') + '</p>',
|
||||
'<p class="hotkey">' + keysShortcuts.Copy + '</p>',
|
||||
'<p class="message">' + this.textToCopy + '</p>',
|
||||
'</div>',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+X', '{0}') + '</p>',
|
||||
'<p class="hotkey">' + keysShortcuts.Cut + '</p>',
|
||||
'<p class="message">' + this.textToCut + '</p>',
|
||||
'</div>',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+V', '{0}') + '</p>',
|
||||
'<p class="hotkey">' + keysShortcuts.Paste + '</p>',
|
||||
'<p class="message">' + this.textToPaste + '</p>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
@ -44,12 +44,14 @@ define([
|
||||
_.extend(_options, {
|
||||
id: 'id-external-diagram-editor',
|
||||
title: this.textTitle,
|
||||
storageName: 'diagram-editor',
|
||||
// storageName: 'diagram-editor',
|
||||
sdkplaceholder: 'id-diagram-editor-placeholder',
|
||||
initwidth: 900,
|
||||
initheight: 700,
|
||||
initwidth: 730,
|
||||
initheight: 275,
|
||||
minwidth: 730,
|
||||
minheight: 275
|
||||
minheight: 275,
|
||||
footer: false,
|
||||
transparentMask: true
|
||||
}, options);
|
||||
|
||||
this._chartData = null;
|
||||
|
||||
@ -42,36 +42,44 @@ define([], function () {
|
||||
initialize : function(options) {
|
||||
var filter = Common.localStorage.getKeysFilter(),
|
||||
appPrefix = (filter && filter.length) ? filter.split(',')[0] : '';
|
||||
this.storageName = appPrefix + (options.storageName || 'external-editor');
|
||||
this.storageName = options.storageName ? appPrefix + options.storageName : null;
|
||||
|
||||
var _options = {},
|
||||
width = options.initwidth || 900,
|
||||
height = options.initheight || 700;
|
||||
var value = Common.localStorage.getItem(this.storageName + '-width');
|
||||
value && (width = parseInt(value));
|
||||
value = Common.localStorage.getItem(this.storageName + '-height');
|
||||
value && (height = parseInt(value));
|
||||
height = options.initheight || 700,
|
||||
footer = options.footer !== undefined ? options.footer : true;
|
||||
|
||||
if (this.storageName) {
|
||||
var value = Common.localStorage.getItem(this.storageName + '-width');
|
||||
value && (width = parseFloat(value));
|
||||
value = Common.localStorage.getItem(this.storageName + '-height');
|
||||
value && (height = parseFloat(value));
|
||||
}
|
||||
|
||||
_.extend(_options, {
|
||||
width: width,
|
||||
height: height,
|
||||
cls: 'advanced-settings-dlg',
|
||||
header: true,
|
||||
toolclose: 'hide',
|
||||
toolcallback: _.bind(this.onToolClose, this),
|
||||
resizable: true
|
||||
resizable: true,
|
||||
footer: footer
|
||||
}, options);
|
||||
// (!_options.buttons || _.size(_options.buttons)<1) && (_options.cls += ' no-footer');
|
||||
_options.contentHeight = height;
|
||||
|
||||
!footer && (_options.cls += ' no-footer');
|
||||
|
||||
this.template = [
|
||||
'<div id="id-editor-container" class="box" style="height:' + _options.contentHeight + 'px; padding: 0 5px;">',
|
||||
'<div id="id-editor-container" class="box" style="padding: 0 5px;">',
|
||||
'<div id="' + (_options.sdkplaceholder || '') + '" style="width: 100%;height: 100%;"></div>',
|
||||
'</div>',
|
||||
'<% if (footer) { %>',
|
||||
'<div class="separator horizontal"></div>',
|
||||
'<div class="footer" style="text-align: center;">',
|
||||
'<button id="id-btn-editor-apply" class="btn normal dlg-btn primary auto" result="ok" data-hint="1" data-hint-direction="bottom" data-hint-offset="big">' + this.textSave + '</button>',
|
||||
'<button id="id-btn-editor-cancel" class="btn normal dlg-btn" result="cancel" data-hint="1" data-hint-direction="bottom" data-hint-offset="big">' + this.textClose + '</button>',
|
||||
'</div>'
|
||||
'</div>',
|
||||
'<% } %>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template)(_options);
|
||||
@ -86,15 +94,14 @@ define([], function () {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
this.boxEl = this.$window.find('.body > .box');
|
||||
var bodyEl = this.$window.find('> .body');
|
||||
this._headerFooterHeight = this.initConfig.header ? parseInt(this.$window.find('.header').css('height')) : 0;
|
||||
this._headerFooterHeight += parseInt(this.$window.find('.footer').css('height')) + parseInt(bodyEl.css('padding-top')) + parseInt(bodyEl.css('padding-bottom'));
|
||||
this._headerFooterHeight += ((parseInt(this.$window.css('border-top-width')) + parseInt(this.$window.css('border-bottom-width'))));
|
||||
this._headerFooterHeight = this.initConfig.header ? parseFloat(this.$window.find('.header').css('height')) : 0;
|
||||
this._headerFooterHeight += (this.initConfig.footer ? parseFloat(this.$window.find('.footer').css('height')) : 0) + parseFloat(bodyEl.css('padding-top')) + parseFloat(bodyEl.css('padding-bottom'));
|
||||
this._headerFooterHeight += ((parseFloat(this.$window.css('border-top-width')) + parseFloat(this.$window.css('border-bottom-width'))));
|
||||
var resizeborder = this.$window.find('.resize-border.bottom');
|
||||
if (resizeborder.length>0)
|
||||
this._headerFooterHeight += $(resizeborder[0]).height()-2;
|
||||
|
||||
var _inner_height = Common.Utils.innerHeight() - Common.Utils.InternalSettings.get('window-inactive-area-top');
|
||||
if (_inner_height < this.initConfig.contentHeight + this._headerFooterHeight) {
|
||||
this.initConfig.contentHeight = _inner_height - this._headerFooterHeight;
|
||||
this.boxEl.css('height', this.initConfig.contentHeight);
|
||||
}
|
||||
this.boxEl.css('height', this.getHeight() - this._headerFooterHeight);
|
||||
|
||||
this.btnSave = new Common.UI.Button({
|
||||
el: this.$window.find('#id-btn-editor-apply'),
|
||||
@ -142,12 +149,12 @@ define([], function () {
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
if (height >= 0) {
|
||||
if (this.$window && height >= 0) {
|
||||
var min = parseInt(this.$window.css('min-height'));
|
||||
height < min && (height = min);
|
||||
this.$window.height(height);
|
||||
|
||||
var header_height = (this.initConfig.header) ? parseInt(this.$window.find('> .header').css('height')) : 0;
|
||||
var header_height = (this.initConfig.header) ? parseFloat(this.$window.find('> .header').css('height')) : 0;
|
||||
|
||||
this.$window.find('> .body').css('height', height-header_height);
|
||||
this.$window.find('> .body > .box').css('height', height-this._headerFooterHeight);
|
||||
@ -166,8 +173,8 @@ define([], function () {
|
||||
setInnerSize: function(width, height) {
|
||||
var maxHeight = Common.Utils.innerHeight(),
|
||||
maxWidth = Common.Utils.innerWidth(),
|
||||
borders_width = (parseInt(this.$window.css('border-left-width')) + parseInt(this.$window.css('border-right-width'))),
|
||||
paddings = (parseInt(this.boxEl.css('padding-left')) + parseInt(this.boxEl.css('padding-right')));
|
||||
borders_width = (parseFloat(this.$window.css('border-left-width')) + parseFloat(this.$window.css('border-right-width'))),
|
||||
paddings = (parseFloat(this.boxEl.css('padding-left')) + parseFloat(this.boxEl.css('padding-right')));
|
||||
height += 90; // add toolbar and statusbar height
|
||||
if (maxHeight<height + this._headerFooterHeight)
|
||||
height = maxHeight - this._headerFooterHeight;
|
||||
@ -188,8 +195,10 @@ define([], function () {
|
||||
onWindowResize: function (args) {
|
||||
if (args && args[1]=='end') {
|
||||
var value = this.getSize();
|
||||
Common.localStorage.setItem(this.storageName + '-width', value[0]);
|
||||
Common.localStorage.setItem(this.storageName + '-height', value[1]);
|
||||
if (this.storageName) {
|
||||
Common.localStorage.setItem(this.storageName + '-width', value[0]);
|
||||
Common.localStorage.setItem(this.storageName + '-height', value[1]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -42,9 +42,7 @@ define([
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
SSE.Views = SSE.Views || {};
|
||||
|
||||
SSE.Views.ExternalLinksDlg = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
Common.Views.ExternalLinksDlg = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
|
||||
options: {
|
||||
alias: 'ExternalLinksDlg',
|
||||
@ -219,7 +217,10 @@ define([
|
||||
|
||||
_setDefaults: function (props) {
|
||||
this.refreshList();
|
||||
this.api && this.chUpdate.setValue(this.api.asc_getUpdateLinks(), true);
|
||||
if (!window.SSE)
|
||||
this.chUpdate.setVisible(false);
|
||||
else if (this.api)
|
||||
this.chUpdate.setValue(this.api.asc_getUpdateLinks(), true);
|
||||
},
|
||||
|
||||
refreshList: function() {
|
||||
@ -247,7 +248,7 @@ define([
|
||||
var rec = this.linksList.getSelectedRec();
|
||||
if (rec) {
|
||||
this.isOffline && this.setLinkStatus(rec.get('linkid'), this.textOk);
|
||||
this.api.asc_updateExternalReferences([rec.get('externalRef')]);
|
||||
Common.NotificationCenter.trigger('data:updatereferences', [rec.get('externalRef')], true);
|
||||
}
|
||||
},
|
||||
|
||||
@ -261,7 +262,7 @@ define([
|
||||
arr.push(item.get('externalRef'));
|
||||
me.isOffline && me.setLinkStatus(item.get('linkid'), me.textOk);
|
||||
}, this);
|
||||
(arr.length>0) && this.api.asc_updateExternalReferences(arr);
|
||||
(arr.length>0) && Common.NotificationCenter.trigger('data:updatereferences', arr, true);
|
||||
} else
|
||||
this.onUpdate();
|
||||
},
|
||||
@ -387,8 +388,6 @@ define([
|
||||
var props = Common.UI.Themes.getThemeProps('font');
|
||||
el.style.fontSize = props && props.size ? props.size : '11px';
|
||||
el.style.fontFamily = props && props.name ? props.name : 'Arial, Helvetica, "Helvetica Neue", sans-serif';
|
||||
|
||||
el.style.fontFamily = document.documentElement.style.getPropertyValue("--font-family-base-custom") || 'Arial, Helvetica, "Helvetica Neue", sans-serif';
|
||||
el.style.position = "absolute";
|
||||
el.style.top = '-1000px';
|
||||
el.style.left = '-1000px';
|
||||
@ -435,5 +434,5 @@ define([
|
||||
textUpdating: 'Updating...',
|
||||
textAutoUpdate: 'Update automatically'
|
||||
|
||||
}, SSE.Views.ExternalLinksDlg || {}));
|
||||
}, Common.Views.ExternalLinksDlg || {}));
|
||||
});
|
||||
@ -51,7 +51,7 @@ define([
|
||||
initwidth: 1030,
|
||||
initheight: 700,
|
||||
minwidth: 1030,
|
||||
minheight: 275
|
||||
minheight: 310
|
||||
}, options);
|
||||
|
||||
this._oleData = null;
|
||||
|
||||
@ -41,10 +41,10 @@ define([
|
||||
'common/main/lib/view/AdvancedSettingsWindow',
|
||||
], function () { 'use strict';
|
||||
|
||||
SSE.Views.FormatSettingsDialog = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
Common.Views.FormatSettingsDialog = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
options: {
|
||||
contentWidth: 284,
|
||||
contentHeight: 260
|
||||
contentHeight: 265
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
@ -84,7 +84,7 @@ define([
|
||||
this.props = options.props;
|
||||
this.linked = options.linked || false;
|
||||
|
||||
var height = this.linked ? 275 : 260;
|
||||
var height = this.linked ? 275 : 265;
|
||||
_.extend(this.options, {
|
||||
title: this.textTitle,
|
||||
contentHeight: height,
|
||||
@ -132,10 +132,16 @@ define([
|
||||
'<div id="format-settings-combo-negative" class="input-group-nr" style="width:264px;"></div>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr class="format-lang">',
|
||||
'<td class="padding-large">',
|
||||
'<label class="header">', me.textLocale,'</label>',
|
||||
'<div id="format-settings-combo-lang" class="input-group-nr" style="width:264px;"></div>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr class="format-type">',
|
||||
'<td class="padding-large">',
|
||||
'<label class="header">', me.textFormat,'</label>',
|
||||
'<div id="format-settings-combo-type" class="input-group-nr" style="width:264px;"></div>',
|
||||
'<div id="format-settings-list-type" class="input-group-nr" style="width:264px; height: 93px;"></div>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr class="format-code">',
|
||||
@ -220,16 +226,14 @@ define([
|
||||
});
|
||||
this.cmbSymbols.on('selected', _.bind(this.onSymbolsSelect, this));
|
||||
|
||||
this.cmbType = new Common.UI.ComboBox({
|
||||
el: $('#format-settings-combo-type'),
|
||||
cls: 'input-group-nr',
|
||||
menuStyle: 'min-width: 264px;max-height:235px;',
|
||||
editable: false,
|
||||
data: [],
|
||||
scrollAlwaysVisible: true,
|
||||
takeFocusOnClose: true
|
||||
this.listType = new Common.UI.ListView({
|
||||
el: $('#format-settings-list-type'),
|
||||
store: new Common.UI.DataViewStore(),
|
||||
tabindex: 1,
|
||||
itemTemplate: _.template('<div id="<%= id %>" class="list-item" style="pointer-events:none;overflow: hidden; text-overflow: ellipsis;"><%= Common.Utils.String.htmlEncode(displayValue) %></div>')
|
||||
});
|
||||
this.cmbType.on('selected', _.bind(this.onTypeSelect, this));
|
||||
this.listType.on('item:select', _.bind(this.onListTypeSelect, this));
|
||||
this.listType.on('entervalue', _.bind(this.onPrimary, this));
|
||||
|
||||
this.codesList = new Common.UI.ListView({
|
||||
el: $('#format-settings-list-code'),
|
||||
@ -270,6 +274,34 @@ define([
|
||||
});
|
||||
this.chLinked.setVisible(this.linked);
|
||||
|
||||
this.cmbLang = new Common.UI.ComboBox({
|
||||
el : $('#format-settings-combo-lang'),
|
||||
menuStyle : 'min-width: 100%; max-height: 185px;',
|
||||
cls : 'input-group-nr',
|
||||
editable : false,
|
||||
takeFocusOnClose: true,
|
||||
data : Common.util.LanguageInfo.getRegionalData(),
|
||||
itemsTemplate: _.template([
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>">',
|
||||
'<a tabindex="-1" type="menuitem" role="menuitemcheckbox" aria-checked="false">',
|
||||
'<div>',
|
||||
'<%= item.displayValue %>',
|
||||
'</div>',
|
||||
'<label style="opacity: 0.6"><%= item.displayValueEn %></label>',
|
||||
'</a>',
|
||||
'</li>',
|
||||
'<% }); %>'
|
||||
].join('')),
|
||||
search: true,
|
||||
searchFields: ['displayValue', 'displayValueEn'],
|
||||
scrollAlwaysVisible: true
|
||||
});
|
||||
this.cmbLang.setValue(0x0409);
|
||||
this.cmbLang.on('selected', _.bind(function(combo, record) {
|
||||
this.onSelectLang(record.value);
|
||||
}, this));
|
||||
|
||||
this._decimalPanel = this.$window.find('.format-decimal');
|
||||
this._negativePanel = this.$window.find('.format-negative');
|
||||
this._separatorPanel = this.$window.find('.format-separator');
|
||||
@ -277,6 +309,7 @@ define([
|
||||
this._symbolsPanel = this.$window.find('.format-symbols');
|
||||
this._codePanel = this.$window.find('.format-code');
|
||||
this._nocodePanel = this.$window.find('.format-no-code');
|
||||
this._langPanel = this.$window.find('.format-lang');
|
||||
this.$window.find('.format-sample').toggleClass('hidden', this.linked);
|
||||
|
||||
this.lblExample = this.$window.find('#format-settings-label-example');
|
||||
@ -285,7 +318,7 @@ define([
|
||||
},
|
||||
|
||||
getFocusedComponents: function() {
|
||||
return [this.cmbFormat, this.spnDecimal, this.chSeparator, this.cmbSymbols, this.cmbNegative, this.cmbType, this.inputCustomFormat, this.codesList, this.chLinked].concat(this.getFooterButtons());
|
||||
return [this.cmbFormat, this.spnDecimal, this.chSeparator, this.cmbSymbols, this.cmbNegative, this.cmbLang, this.listType, this.inputCustomFormat, this.codesList, this.chLinked].concat(this.getFooterButtons());
|
||||
},
|
||||
|
||||
getDefaultFocusableComponent: function () {
|
||||
@ -302,12 +335,18 @@ define([
|
||||
|
||||
_setDefaults: function (props) {
|
||||
if (props && props.formatInfo) {
|
||||
if (this.langId)
|
||||
if (props.langId)
|
||||
this.langId = props.langId;
|
||||
this.cmbFormat.setValue(props.formatInfo.asc_getType(), this.txtCustom);
|
||||
|
||||
var type = props.formatInfo.asc_getType(),
|
||||
item = this.cmbLang.store.findWhere({value: type == Asc.c_oAscNumFormatType.Date || type == Asc.c_oAscNumFormatType.Time ? props.formatInfo.asc_getSymbol() || this.langId : this.langId});
|
||||
item = item ? item.get('value') : 0x0409;
|
||||
this.cmbLang.setValue(item)
|
||||
|
||||
this.cmbFormat.setValue(type, this.txtCustom);
|
||||
|
||||
this.FormatInfo = props.formatInfo;
|
||||
if ((props.formatInfo.asc_getType() == Asc.c_oAscNumFormatType.Custom) && props.format)
|
||||
if ((type == Asc.c_oAscNumFormatType.Custom) && props.format)
|
||||
this.CustomFormat = this.Format = props.format;
|
||||
|
||||
this.onFormatSelect(this.cmbFormat, this.cmbFormat.getSelectedRecord(), null, props.formatInfo);
|
||||
@ -326,15 +365,21 @@ define([
|
||||
else
|
||||
this.cmbNegative.setValue(this.api.asc_getLocaleExample(props.format));
|
||||
} else if (this._state.hasType) {
|
||||
var selectedItem = this.cmbType.store.findWhere({value: props.format});
|
||||
if (selectedItem)
|
||||
this.cmbType.selectRecord(selectedItem);
|
||||
else if (props.formatInfo.asc_getType() == Asc.c_oAscNumFormatType.Fraction)
|
||||
this.cmbType.setValue(this.txtCustom);
|
||||
else if (props.formatInfo.asc_getType() == Asc.c_oAscNumFormatType.Time)
|
||||
this.cmbType.setValue(this.api.asc_getLocaleExample(props.format, 1.534));
|
||||
else
|
||||
this.cmbType.setValue(this.api.asc_getLocaleExample(props.format, 38822));
|
||||
var selectedItem = this.listType.store.findWhere({value: props.format});
|
||||
if(selectedItem) {
|
||||
this.listType.selectRecord(selectedItem);
|
||||
this.listType.scrollToRecord(selectedItem);
|
||||
} else if(type == Asc.c_oAscNumFormatType.Time.Fraction) {
|
||||
this.listType.deselectAll();
|
||||
} else {
|
||||
var defaultNumber = (type == Asc.c_oAscNumFormatType.Time ? 1.534 : 38822);
|
||||
selectedItem = this.listType.store.unshift({
|
||||
value: props.format,
|
||||
displayValue: this.api.asc_getLocaleExample(props.format, defaultNumber)
|
||||
});
|
||||
this.listType.selectRecord(selectedItem);
|
||||
this.listType.scrollToRecord(selectedItem);
|
||||
}
|
||||
}
|
||||
this.Format = props.format;
|
||||
this.lblExample.text(this.api.asc_getLocaleExample(this.Format));
|
||||
@ -449,8 +494,8 @@ define([
|
||||
this.chLinked.setValue(false, true);
|
||||
},
|
||||
|
||||
onTypeSelect: function(combo, record){
|
||||
this.Format = record.value;
|
||||
onListTypeSelect: function(listView, itemView, record) {
|
||||
this.Format = record.get('value');
|
||||
this.lblExample.text(this.api.asc_getLocaleExample(this.Format));
|
||||
this.chLinked.setValue(false, true);
|
||||
},
|
||||
@ -471,11 +516,12 @@ define([
|
||||
|
||||
this.FormatType = record.value;
|
||||
|
||||
var hasDecimal = (record.value == Asc.c_oAscNumFormatType.Number || record.value == Asc.c_oAscNumFormatType.Scientific || record.value == Asc.c_oAscNumFormatType.Accounting ||
|
||||
var isDateTime = record.value == Asc.c_oAscNumFormatType.Date || record.value == Asc.c_oAscNumFormatType.Time,
|
||||
hasDecimal = (record.value == Asc.c_oAscNumFormatType.Number || record.value == Asc.c_oAscNumFormatType.Scientific || record.value == Asc.c_oAscNumFormatType.Accounting ||
|
||||
record.value == Asc.c_oAscNumFormatType.Currency || record.value == Asc.c_oAscNumFormatType.Percent),
|
||||
hasNegative = (record.value == Asc.c_oAscNumFormatType.Number || record.value == Asc.c_oAscNumFormatType.Currency || record.value == Asc.c_oAscNumFormatType.Accounting),
|
||||
hasSeparator = (record.value == Asc.c_oAscNumFormatType.Number),
|
||||
hasType = (record.value == Asc.c_oAscNumFormatType.Date || record.value == Asc.c_oAscNumFormatType.Time || record.value == Asc.c_oAscNumFormatType.Fraction),
|
||||
hasType = (isDateTime || record.value == Asc.c_oAscNumFormatType.Fraction),
|
||||
hasSymbols = (record.value == Asc.c_oAscNumFormatType.Accounting || record.value == Asc.c_oAscNumFormatType.Currency),
|
||||
hasCode = (record.value == Asc.c_oAscNumFormatType.Custom),
|
||||
me = this,
|
||||
@ -489,7 +535,7 @@ define([
|
||||
info.asc_setDecimalPlaces(hasDecimal ? valDecimal : 0);
|
||||
info.asc_setSeparator(hasSeparator ? valSeparator : false);
|
||||
|
||||
if (hasNegative || record.value == Asc.c_oAscNumFormatType.Date || record.value == Asc.c_oAscNumFormatType.Time) {
|
||||
if (hasNegative || isDateTime) {
|
||||
if (hasSymbols) {
|
||||
if (!me.CurrencySymbolsData) {
|
||||
me.CurrencySymbolsData = [];
|
||||
@ -513,6 +559,8 @@ define([
|
||||
this.cmbSymbols.setValue(valSymbol);
|
||||
}
|
||||
info.asc_setSymbol(this.cmbSymbols.getValue());
|
||||
} else if (isDateTime) {
|
||||
info.asc_setSymbol(this.cmbLang.getValue());
|
||||
}
|
||||
|
||||
var formatsarr = this.api.asc_getFormatCells(info),
|
||||
@ -526,14 +574,20 @@ define([
|
||||
this.cmbNegative.selectRecord(this.cmbNegative.store.at(0));
|
||||
this.cmbNegative.cmpEl.find('li:nth-child(2) a, li:nth-child(4) a').css({color: '#ff0000'});
|
||||
} else {
|
||||
this.cmbType.setData(data);
|
||||
this.cmbType.selectRecord(this.cmbType.store.at(0));
|
||||
this.listType.store.reset(data);
|
||||
this.listType.selectRecord(this.listType.store.at(0));
|
||||
this.listType.scrollToRecord(this.listType.store.at(0));
|
||||
|
||||
this.listType.$el[0].style.height = "93px";
|
||||
}
|
||||
this.Format = formatsarr[0];
|
||||
} else if (record.value == Asc.c_oAscNumFormatType.Fraction) {
|
||||
this.cmbType.setData(this.FractionData);
|
||||
this.cmbType.selectRecord(this.cmbType.store.at(0));
|
||||
this.Format = this.cmbType.getValue();
|
||||
this.listType.store.reset(this.FractionData);
|
||||
this.listType.selectRecord(this.listType.store.at(0));
|
||||
this.listType.scrollToRecord(this.listType.store.at(0));
|
||||
|
||||
this.listType.$el[0].style.height = "139px";
|
||||
this.Format = this.listType.getSelectedRec().get('value');
|
||||
} else {
|
||||
this.Format = this.api.asc_getFormatCells(info)[0];
|
||||
}
|
||||
@ -581,11 +635,35 @@ define([
|
||||
this._symbolsPanel.toggleClass('hidden', !hasSymbols);
|
||||
this._codePanel.toggleClass('hidden', !hasCode);
|
||||
this._nocodePanel.toggleClass('hidden', hasCode);
|
||||
this._langPanel.toggleClass('hidden', !isDateTime);
|
||||
this._state = { hasDecimal: hasDecimal, hasNegative: hasNegative, hasSeparator: hasSeparator, hasType: hasType, hasSymbols: hasSymbols, hasCode: hasCode};
|
||||
|
||||
!initFormatInfo && this.chLinked.setValue(false, true);
|
||||
},
|
||||
|
||||
onSelectLang: function(lang) {
|
||||
var info = new Asc.asc_CFormatCellsInfo();
|
||||
info.asc_setType(this.FormatType);
|
||||
info.asc_setDecimalPlaces(0);
|
||||
info.asc_setSeparator(false);
|
||||
info.asc_setSymbol(lang);
|
||||
|
||||
var me = this,
|
||||
formatsarr = this.api.asc_getFormatCells(info),
|
||||
data = [],
|
||||
exampleVal = (this.FormatType == Asc.c_oAscNumFormatType.Date) ? 38822 : ((this.FormatType == Asc.c_oAscNumFormatType.Time) ? 1.534 : parseFloat("-1234.12345678901234567890"));
|
||||
formatsarr.forEach(function(item) {
|
||||
data.push({value: item, displayValue: me.api.asc_getLocaleExample(item, exampleVal)});
|
||||
});
|
||||
this.listType.store.reset(data, {silent: false});
|
||||
this.listType.selectRecord(this.listType.store.at(0));
|
||||
this.listType.scrollToRecord(this.listType.store.at(0));
|
||||
|
||||
this.Format = formatsarr[0];
|
||||
this.FormatInfo = info;
|
||||
this.lblExample.text(this.api.asc_getLocaleExample(this.Format));
|
||||
},
|
||||
|
||||
textTitle: 'Number Format',
|
||||
textCategory: 'Category',
|
||||
textDecimal: 'Decimal',
|
||||
@ -615,7 +693,8 @@ define([
|
||||
txtSample: 'Sample:',
|
||||
txtNone: 'None',
|
||||
textLinked: 'Linked to source',
|
||||
txtCustomWarning: 'Please enter the custom number format carefully. Spreadsheet Editor does not check custom formats for errors that may affect the xlsx file.'
|
||||
txtCustomWarning: 'Please enter the custom number format carefully. Spreadsheet Editor does not check custom formats for errors that may affect the xlsx file.',
|
||||
textLocale: 'Locale'
|
||||
|
||||
}, SSE.Views.FormatSettingsDialog || {}))
|
||||
}, Common.Views.FormatSettingsDialog || {}))
|
||||
});
|
||||
@ -156,7 +156,7 @@ define([
|
||||
'</div>' +
|
||||
'<div class="lr-separator" id="id-box-doc-name">' +
|
||||
// '<label id="title-doc-name" /></label>' +
|
||||
'<input id="title-doc-name" autofill="off" autocomplete="off"/></input>' +
|
||||
'<input id="title-doc-name" autofill="off" autocomplete="off" spellcheck="false"/></input>' +
|
||||
'</div>' +
|
||||
'<div class="hedset">' +
|
||||
'<div class="btn-slot" data-layout-name="header-user">' +
|
||||
@ -453,7 +453,6 @@ define([
|
||||
}
|
||||
|
||||
if ( me.btnPrint ) {
|
||||
me.btnPrint.updateHint(me.tipPrint + Common.Utils.String.platformKey('Ctrl+P'));
|
||||
me.btnPrint.on('click', function (e) {
|
||||
me.fireEvent('print', me);
|
||||
});
|
||||
@ -467,28 +466,24 @@ define([
|
||||
}
|
||||
|
||||
if ( me.btnSave ) {
|
||||
me.btnSave.updateHint(appConfig.canSaveToFile || appConfig.isDesktopApp && appConfig.isOffline ? me.tipSave + (isPDFEditor ? '' : Common.Utils.String.platformKey('Ctrl+S')) : me.tipDownload);
|
||||
me.btnSave.on('click', function (e) {
|
||||
me.fireEvent('save', me);
|
||||
});
|
||||
}
|
||||
|
||||
if ( me.btnUndo ) {
|
||||
me.btnUndo.updateHint(me.tipUndo + Common.Utils.String.platformKey('Ctrl+Z'));
|
||||
me.btnUndo.on('click', function (e) {
|
||||
me.fireEvent('undo', me);
|
||||
});
|
||||
}
|
||||
|
||||
if ( me.btnRedo ) {
|
||||
me.btnRedo.updateHint(me.tipRedo + Common.Utils.String.platformKey('Ctrl+Y'));
|
||||
me.btnRedo.on('click', function (e) {
|
||||
me.fireEvent('redo', me);
|
||||
});
|
||||
}
|
||||
|
||||
if (me.btnStartOver) {
|
||||
me.btnStartOver.updateHint(me.tipStartOver + (Common.Utils.String.platformKey(Common.Utils.isMac ? 'Ctrl+Shift+enter' : 'Ctrl+F5')));
|
||||
me.btnStartOver.on('click', function (e) {
|
||||
me.fireEvent('startover', me);
|
||||
});
|
||||
@ -606,8 +601,6 @@ define([
|
||||
});
|
||||
}
|
||||
|
||||
if (me.btnSearch)
|
||||
me.btnSearch.updateHint(me.tipSearch + Common.Utils.String.platformKey('Ctrl+F'));
|
||||
|
||||
var menuTemplate = _.template('<a id="<%= id %>" tabindex="-1" type="menuitem" class="menu-item"><div>' +
|
||||
'<% if (!_.isEmpty(iconCls)) { %>' +
|
||||
@ -711,6 +704,11 @@ define([
|
||||
}
|
||||
if (appConfig.twoLevelHeader && !appConfig.compactHeader)
|
||||
Common.NotificationCenter.on('window:resize', onResize);
|
||||
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
if(app && app.getController('Common.Controllers.Shortcuts')) {
|
||||
app.getController('Common.Controllers.Shortcuts').updateShortcutHints(this.shortcutHints);
|
||||
}
|
||||
}
|
||||
|
||||
function onFocusDocName(e){
|
||||
@ -796,6 +794,8 @@ define([
|
||||
var filter = Common.localStorage.getKeysFilter();
|
||||
this.appPrefix = (filter && filter.length) ? filter.split(',')[0] : '';
|
||||
|
||||
this.shortcutHints = {};
|
||||
|
||||
me.btnGoBack = new Common.UI.Button({
|
||||
id: 'btn-go-back',
|
||||
cls: 'btn-header',
|
||||
@ -820,6 +820,10 @@ define([
|
||||
dataHintDirection: 'bottom',
|
||||
dataHintOffset: 'big'
|
||||
});
|
||||
this.shortcutHints.OpenFindDialog = {
|
||||
btn: me.btnSearch,
|
||||
label: me.tipSearch
|
||||
};
|
||||
|
||||
me.btnFavorite = new Common.UI.Button({
|
||||
id: 'id-btn-favorite',
|
||||
@ -876,7 +880,7 @@ define([
|
||||
this.logo.addClass('hidden');
|
||||
} else if (this.branding.logo.image || this.branding.logo.imageDark || this.branding.logo.imageLight) {
|
||||
_logoImage = logo.image;
|
||||
this.logo.html('<img src="' + _logoImage + '" style="max-width:100px; max-height:20px; margin: 0;"/>');
|
||||
this.logo.html('<img src="' + _logoImage + '" style="max-width:300px; max-height:20px; margin: 0;"/>');
|
||||
this.logo.css({'background-image': 'none', width: 'auto'});
|
||||
(this.branding.logo.url || this.branding.logo.url===undefined) && this.logo.addClass('link');
|
||||
}
|
||||
@ -919,8 +923,13 @@ define([
|
||||
if ( (config.canDownload || config.canDownloadOrigin) && !config.isOffline )
|
||||
this.btnDownload = createTitleButton('toolbar__icon icon--inverse btn-download', $html.findById('#slot-hbtn-download'), undefined, 'bottom', 'big');
|
||||
|
||||
if ( config.canPrint )
|
||||
if ( config.canPrint ) {
|
||||
this.btnPrint = createTitleButton('toolbar__icon icon--inverse btn-print', $html.findById('#slot-hbtn-print'), undefined, 'bottom', 'big', 'P');
|
||||
this.shortcutHints.PrintPreviewAndPrint = {
|
||||
btn: me.btnPrint,
|
||||
label: me.tipPrint + (!!window.VE ? (Common.Utils.String.platformKey('Ctrl+P')) : '')
|
||||
};
|
||||
}
|
||||
|
||||
if ( config.canQuickPrint )
|
||||
this.btnPrintQuick = createTitleButton('toolbar__icon icon--inverse btn-quick-print', $html.findById('#slot-hbtn-print-quick'), undefined, 'bottom', 'big', 'Q');
|
||||
@ -1060,6 +1069,10 @@ define([
|
||||
|
||||
if ( config.canPrint && config.twoLevelHeader ) {
|
||||
me.btnPrint = createTitleButton('toolbar__icon icon--inverse btn-print', $html.findById('#slot-btn-dt-print'), true, undefined, undefined, 'P');
|
||||
me.shortcutHints.PrintPreviewAndPrint = {
|
||||
btn: me.btnPrint,
|
||||
label: me.tipPrint
|
||||
};
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-print', true) && me.btnPrint.hide();
|
||||
}
|
||||
if ( config.canQuickPrint && config.twoLevelHeader ) {
|
||||
@ -1070,16 +1083,40 @@ define([
|
||||
let save_icon = config.canSaveToFile || config.isDesktopApp && config.isOffline ? 'btn-save' : 'btn-download';
|
||||
me.btnSave = createTitleButton('toolbar__icon icon--inverse ' + save_icon, $html.findById('#slot-btn-dt-save'), true, undefined, undefined, 'S');
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-save', true) && me.btnSave.hide();
|
||||
|
||||
// Set hint text based on save availability and editor type
|
||||
if (appConfig.canSaveToFile || appConfig.isDesktopApp && appConfig.isOffline) {
|
||||
me.shortcutHints.Save = {
|
||||
btn: me.btnSave,
|
||||
label: me.tipSave
|
||||
};
|
||||
} else {
|
||||
me.btnSave.updateHint(me.tipDownload);
|
||||
}
|
||||
}
|
||||
me.btnUndo = createTitleButton('toolbar__icon icon--inverse btn-undo icon-rtl', $html.findById('#slot-btn-dt-undo'), true, undefined, undefined, 'Z',
|
||||
[Common.enumLock.undoLock, Common.enumLock.fileMenuOpened, Common.enumLock.lostConnect]);
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-undo', true) && me.btnUndo.hide();
|
||||
me.shortcutHints.EditUndo = {
|
||||
btn: me.btnUndo,
|
||||
label: me.tipUndo
|
||||
};
|
||||
|
||||
me.btnRedo = createTitleButton('toolbar__icon icon--inverse btn-redo icon-rtl', $html.findById('#slot-btn-dt-redo'), true, undefined, undefined, 'Y',
|
||||
[Common.enumLock.redoLock, Common.enumLock.fileMenuOpened, Common.enumLock.lostConnect]);
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-redo', true) && me.btnRedo.hide();
|
||||
me.shortcutHints.EditRedo = {
|
||||
btn: me.btnRedo,
|
||||
label: me.tipRedo
|
||||
};
|
||||
|
||||
if (isPEEditor) {
|
||||
me.btnStartOver= createTitleButton('toolbar__icon icon--inverse btn-preview', $html.findById('#slot-btn-dt-start-over'), true, undefined, undefined, 'O');
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-start-over', true) && me.btnStartOver.hide();
|
||||
me.btnStartOver= createTitleButton('toolbar__icon icon--inverse btn-preview', $html.findById('#slot-btn-dt-start-over'), true, undefined, undefined, 'O');
|
||||
!Common.localStorage.getBool(me.appPrefix + 'quick-access-start-over', true) && me.btnStartOver.hide();
|
||||
me.shortcutHints.DemonstrationStartPresentation = {
|
||||
btn: me.btnStartOver,
|
||||
label: me.tipStartOver
|
||||
};
|
||||
}
|
||||
me.btnQuickAccess = new Common.UI.Button({
|
||||
cls: 'btn-header no-caret',
|
||||
@ -1111,7 +1148,7 @@ define([
|
||||
element.addClass('hidden');
|
||||
} else if (value.logo.image || value.logo.imageDark || value.logo.imageLight) {
|
||||
_logoImage = logo.image;
|
||||
element.html('<img src="' + _logoImage + '" style="max-width:100px; max-height:20px; margin: 0;"/>');
|
||||
element.html('<img src="' + _logoImage + '" style="max-width:300px; max-height:20px; margin: 0;"/>');
|
||||
element.css({'background-image': 'none', width: 'auto'});
|
||||
(value.logo.url || value.logo.url===undefined) && element.addClass('link');
|
||||
}
|
||||
|
||||
@ -265,6 +265,7 @@ define([
|
||||
createBackgroundPluginsButton: function () {
|
||||
var _set = Common.enumLock;
|
||||
var btn = new Common.UI.Button({
|
||||
id: 'id-toolbar-btn-background-plugin',
|
||||
cls: 'btn-toolbar x-huge icon-top',
|
||||
iconCls: 'toolbar__icon btn-background-plugins',
|
||||
caption: this.textBackgroundPlugins,
|
||||
@ -329,7 +330,8 @@ define([
|
||||
lock: model.get('isDisplayedInViewer') ? [_set.viewMode, _set.previewReviewMode, _set.viewFormMode, _set.selRangeEdit, _set.editFormula] : [_set.viewMode, _set.previewReviewMode, _set.viewFormMode, _set.docLockView, _set.docLockForms, _set.docLockComments, _set.selRangeEdit, _set.editFormula ],
|
||||
dataHint: '1',
|
||||
dataHintDirection: 'bottom',
|
||||
dataHintOffset: 'small'
|
||||
dataHintOffset: 'small',
|
||||
customAttributes: {'data-plugin-guid': guid}
|
||||
});
|
||||
|
||||
if ( btn.split ) {
|
||||
|
||||
@ -84,8 +84,8 @@ define([
|
||||
'<div class= <% if (typeof format !== "undefined") {%> "img-format-<%=format %>"<% } else {%> "svg-file-recent"<%} %>></div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="file-name"><% if (typeof title !== "undefined") {%><%= Common.Utils.String.htmlEncode(title || "") %><% } %></div>',
|
||||
'<div class="file-info"><% if (typeof folder !== "undefined") {%><%= Common.Utils.String.htmlEncode(folder || "") %><% } %></div>',
|
||||
'<div class="file-name"><% if (typeof title !== "undefined") {%><%= title || "" %><% } %></div>',
|
||||
'<div class="file-info"><% if (typeof folder !== "undefined") {%><%= folder || "" %><% } %></div>',
|
||||
'</div>'
|
||||
].join(''))
|
||||
});
|
||||
|
||||
@ -664,7 +664,15 @@ define([
|
||||
}
|
||||
me.btnSharing && me.btnSharing.updateHint(me.tipSharing);
|
||||
me.btnHistory && me.btnHistory.updateHint(me.tipHistory);
|
||||
me.btnChat && me.btnChat.updateHint(me.txtChat + Common.Utils.String.platformKey('Alt+Q', ' (' + (Common.Utils.isMac ? Common.Utils.String.textCtrl + '+' : '') + '{0})'));
|
||||
if(me.btnChat) {
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
app.getController('Common.Controllers.Shortcuts').updateShortcutHints({
|
||||
OpenChatPanel: {
|
||||
btn: me.btnChat,
|
||||
label: me.txtChat
|
||||
}
|
||||
});
|
||||
}
|
||||
me.btnMailRecepients && me.btnMailRecepients.updateHint(me.tipMailRecepients);
|
||||
if (me.btnCoAuthMode) {
|
||||
me.btnCoAuthMode.setMenu(
|
||||
|
||||
@ -768,6 +768,7 @@ define([
|
||||
if (commentsView && arrowView && editorView && editorView.get(0)) {
|
||||
editorBounds = Common.Utils.getBoundingClientRect(editorView.get(0));
|
||||
if (editorBounds) {
|
||||
editorBounds.height = Math.min(editorBounds.height, Math.max(300, editorBounds.height * 0.75));
|
||||
sdkBoundsHeight = editorBounds.height - this.sdkBounds.padding * 2;
|
||||
|
||||
this.$window.css({maxHeight: sdkBoundsHeight + 'px'});
|
||||
@ -910,6 +911,7 @@ define([
|
||||
if (editorView && editorView.get(0)) {
|
||||
editorBounds = Common.Utils.getBoundingClientRect(editorView.get(0));
|
||||
if (editorBounds) {
|
||||
editorBounds.height = Math.min(editorBounds.height, Math.max(300, editorBounds.height * 0.75));
|
||||
sdkBoundsHeight = editorBounds.height - this.sdkBounds.padding * 2;
|
||||
sdkBoundsTopPos = sdkBoundsTop;
|
||||
windowHeight = this.$window.outerHeight();
|
||||
|
||||
@ -66,7 +66,9 @@ define([
|
||||
'<div class="tools">',
|
||||
'<div id="search-bar-back"></div>',
|
||||
'<div id="search-bar-next"></div>',
|
||||
this.options.showOpenPanel ? '<div id="search-bar-open-panel"></div>' : '',
|
||||
this.options.showOpenPanel
|
||||
? '<div id="search-bar-open-panel"></div><div id="search-bar-open-panel-redact"></div>'
|
||||
: '',
|
||||
'<div id="search-bar-close"></div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
@ -74,10 +76,10 @@ define([
|
||||
|
||||
this.options.tpl = _.template(this.template)(this.options);
|
||||
this.iconType = this.options.iconType;
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||
|
||||
Common.NotificationCenter.on('layout:changed', _.bind(this.onLayoutChanged, this));
|
||||
Common.NotificationCenter.on('pdf:mode-apply', _.bind(this.onModeChanged, this));
|
||||
$(window).on('resize', _.bind(this.onLayoutChanged, this));
|
||||
},
|
||||
|
||||
@ -112,6 +114,8 @@ define([
|
||||
this.btnNext.on('click', _.bind(this.onBtnNextClick, this, 'next'));
|
||||
|
||||
if (this.options.showOpenPanel) {
|
||||
var me = this;
|
||||
|
||||
this.btnOpenPanel = new Common.UI.Button({
|
||||
parentEl: $('#search-bar-open-panel'),
|
||||
cls: 'btn-toolbar',
|
||||
@ -119,6 +123,30 @@ define([
|
||||
hint: this.tipOpenAdvancedSettings
|
||||
});
|
||||
this.btnOpenPanel.on('click', _.bind(this.onOpenPanel, this));
|
||||
|
||||
this.btnOpenPanelRedact = new Common.UI.Button({
|
||||
parentEl: $('#search-bar-open-panel-redact'),
|
||||
cls: 'btn-toolbar',
|
||||
menu: true,
|
||||
iconCls: 'toolbar__icon btn-more-vertical',
|
||||
hint: this.tipOpenAdvancedSettings
|
||||
});
|
||||
this.btnOpenPanelRedact.setMenu(
|
||||
new Common.UI.Menu({
|
||||
items: [
|
||||
{caption: me.capFind, value: 'find', hint: this.tipOpenAdvancedSettings},
|
||||
{caption: me.capFindRedact, value: 'find-redact', hint: this.tipOpenAdvancedSettingsRedact},
|
||||
]
|
||||
}).on('item:click', function (menu, item, e) {
|
||||
if (item.value === 'find') {
|
||||
me.hide();
|
||||
me.fireEvent('search:show', [true, me.inputSearch.val()]);
|
||||
} else {
|
||||
me.hide();
|
||||
me.fireEvent('search:showredact', [true, me.inputSearch.val()])
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
this.btnClose = new Common.UI.Button({
|
||||
@ -141,6 +169,8 @@ define([
|
||||
this.updateResultsNumber(resultNumber, allResults);
|
||||
}, this));
|
||||
|
||||
this.btnOpenPanelRedact && this.btnOpenPanelRedact.setVisible(this.mode === 'edit')
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -189,6 +219,12 @@ define([
|
||||
this.$window.css({left: left, top: top});
|
||||
},
|
||||
|
||||
onModeChanged: function (mode) {
|
||||
this.mode = mode;
|
||||
this.btnOpenPanel.setVisible(this.mode !== 'edit')
|
||||
this.btnOpenPanelRedact.setVisible(this.mode == 'edit')
|
||||
},
|
||||
|
||||
onBtnNextClick: function(action) {
|
||||
this.fireEvent('search:'+action, [this.inputSearch.val(), false]);
|
||||
},
|
||||
|
||||
@ -127,6 +127,16 @@ define([
|
||||
});
|
||||
this.btnReplaceAll.on('click', _.bind(this.onReplaceClick, this, 'replaceall'));
|
||||
|
||||
this.btnMark = new Common.UI.Button({
|
||||
el: $('#search-adv-mark')
|
||||
});
|
||||
this.btnMark.on('click', _.bind(this.onMarkClick, this, 'mark'));
|
||||
|
||||
this.btnMarkAll = new Common.UI.Button({
|
||||
el: $('#search-adv-mark-all')
|
||||
});
|
||||
this.btnMarkAll.on('click', _.bind(this.onMarkClick, this, 'markall'));
|
||||
|
||||
this.$reaultsNumber = $('#search-adv-results-number');
|
||||
this.updateResultsNumber('no-results');
|
||||
|
||||
@ -173,6 +183,19 @@ define([
|
||||
});
|
||||
this.buttonClose.on('click', _.bind(this.onClickClosePanel, this));
|
||||
|
||||
this.buttonRedactSearch = new Common.UI.Button({
|
||||
parentEl: $('#search-btn-redact-open', this.$el),
|
||||
cls: 'btn-toolbar',
|
||||
iconCls: 'toolbar__icon btn-find-redacted',
|
||||
hint: this.textFindRedact,
|
||||
dataHint: '1',
|
||||
dataHintDirection: 'bottom',
|
||||
dataHintOffset: 'medium'
|
||||
});
|
||||
this.buttonRedactSearch.on('click', _.bind(function() {
|
||||
this.fireEvent('search:showredact');
|
||||
}, this));
|
||||
|
||||
this.$resultsContainer = $('#search-results');
|
||||
this.$resultsContainer.hide();
|
||||
|
||||
@ -184,6 +207,8 @@ define([
|
||||
});
|
||||
|
||||
Common.NotificationCenter.on('search:updateresults', _.bind(this.disableNavButtons, this));
|
||||
Common.NotificationCenter.on('pdf:mode-apply', _.bind(this.onModeChanged, this));
|
||||
|
||||
if (window.SSE) {
|
||||
this.cmbWithin = new Common.UI.ComboBox({
|
||||
el: $('#search-adv-cmb-within'),
|
||||
@ -332,8 +357,10 @@ define([
|
||||
|
||||
setSearchMode: function (mode) {
|
||||
if (this.mode !== mode) {
|
||||
this.$el.find('.edit-setting')[mode !== 'no-replace' ? 'show' : 'hide']();
|
||||
this.$el.find('#search-adv-title').text(mode !== 'no-replace' ? this.textFindAndReplace : this.textFind);
|
||||
this.$el.find('.edit-setting')[mode !== 'no-replace' && mode !== 'redact' ? 'show' : 'hide']();
|
||||
this.$el.find('.redact-setting')[mode === 'redact' && this.options.mode.isPDFEdit ? 'show' : 'hide']();
|
||||
this.$el.find('.redact-no-replace-btn')[mode === 'no-replace' && this.options.mode.isPDFEdit === true ? 'show' : 'hide']();
|
||||
this.$el.find('#search-adv-title').text(mode === 'no-replace' ? this.textFind : mode === 'redact' ? this.textFindAndRedact : this.textFindAndReplace);
|
||||
this.mode = mode;
|
||||
}
|
||||
},
|
||||
@ -390,6 +417,7 @@ define([
|
||||
}
|
||||
this.updateResultsContainerHeight();
|
||||
!window.SSE && this.disableReplaceButtons(!count);
|
||||
!window.SSE && this.disableRedactButtons(!count);
|
||||
},
|
||||
|
||||
showToManyResults: function () {
|
||||
@ -419,6 +447,17 @@ define([
|
||||
this.fireEvent('search:'+action, [this.inputText.getValue(), this.inputReplace.getValue()]);
|
||||
},
|
||||
|
||||
onMarkClick: function (action) {
|
||||
this.fireEvent('search:'+action, [this.inputText.getValue()]);
|
||||
},
|
||||
|
||||
onModeChanged: function (isEdit) {
|
||||
if (isEdit !== 'edit') {
|
||||
Common.NotificationCenter.trigger('search:resetmode');
|
||||
}
|
||||
this.$el.find('.redact-no-replace-btn')[this.mode === 'no-replace' && isEdit === 'edit' ? 'show' : 'hide']();
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return {
|
||||
textsearch: this.inputText.getValue(),
|
||||
@ -449,6 +488,16 @@ define([
|
||||
this.btnNext.setDisabled(disable);
|
||||
},
|
||||
|
||||
disableRedactButtons: function (disable) {
|
||||
if (typeof disable === 'object') {
|
||||
this.btnMark.setDisabled(disable.current)
|
||||
this.btnMarkAll.setDisabled(disable.all)
|
||||
} else {
|
||||
this.btnMark.setDisabled(disable)
|
||||
this.btnMarkAll.setDisabled(disable)
|
||||
}
|
||||
},
|
||||
|
||||
disableReplaceButtons: function (disable) {
|
||||
this.btnReplace.setDisabled(disable);
|
||||
this.btnReplaceAll.setDisabled(disable);
|
||||
|
||||
258
apps/common/main/lib/view/ShortcutsDialog.js
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2024
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
* version 3 as published by the Free Software Foundation. In accordance with
|
||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||
* of any third-party rights.
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
*
|
||||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||
* street, Riga, Latvia, EU, LV-1050.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of the Program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU AGPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||
* grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||
* well as technical writing content are licensed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* ShortcutsDialog.js
|
||||
*
|
||||
* Created on 23/06/25
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/view/AdvancedSettingsWindow'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.ShortcutsDialog = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
options: {
|
||||
contentWidth: 550,
|
||||
separator: false
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
_.extend(this.options, {
|
||||
id: 'shortcuts-gialog',
|
||||
title: this.txtTitle,
|
||||
contentStyle: 'padding: 16px 16px 0;',
|
||||
contentTemplate: _.template([
|
||||
'<div id="header-row">',
|
||||
'<input id="search-input" type="text" spellcheck="false" class="form-control" placeholder="<%= scope.txtSearch %>...">',
|
||||
'<label id="reset-all-btn" class="link"><%= scope.txtRestoreAll %></label>',
|
||||
'</div>',
|
||||
'<div id="actions-list"></div>',
|
||||
'<div id="action-description">',
|
||||
'<b><%= scope.txtDescription %>: </b>',
|
||||
'<span id="action-description-text"></span>',
|
||||
'</div>'
|
||||
].join(''))({scope: this}),
|
||||
buttons: []
|
||||
}, options);
|
||||
|
||||
this.handler = options.handler;
|
||||
this.api = options.api;
|
||||
|
||||
this._state = {
|
||||
searchValue: ''
|
||||
};
|
||||
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
this._shortcutsController = app.getController('Common.Controllers.Shortcuts');
|
||||
|
||||
Common.Views.AdvancedSettingsWindow.prototype.initialize.call(this, this.options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.Views.AdvancedSettingsWindow.prototype.render.call(this);
|
||||
|
||||
this.actionsList = new Common.UI.ListView({
|
||||
el: $('#actions-list', this.$window),
|
||||
emptyText: this.txtEmpty,
|
||||
store: new Common.UI.DataViewStore(),
|
||||
itemTemplate: _.template([
|
||||
'<div id="<%= id %>" class="list-item">',
|
||||
'<div class="action-name"><%= action.name %></div>',
|
||||
'<div class="action-keys">',
|
||||
'<% _.each(_.filter(shortcuts, function(shortcut) { return !shortcut.ascShortcut.asc_IsHidden() }), function(shortcut, shortcutIndex) { %>',
|
||||
'<div class="action-keys-item">',
|
||||
'<% _.each(shortcut.keys, function(key, keyIndex) { %>',
|
||||
'<% if (keyIndex != 0) { %>',
|
||||
'<div class="action-keys-item-plus">+</div>',
|
||||
'<% } %>',
|
||||
'<div class="action-keys-item-key"><%= key %></div>',
|
||||
'<% }); %>',
|
||||
'<div class="action-keys-item-comma">,</div>',
|
||||
'</div>',
|
||||
'<% }); %>',
|
||||
'</div>',
|
||||
'<% if (action.isLocked) { %>',
|
||||
'<i class="icon toolbar__icon btn-lock icon-lock"> </i>',
|
||||
'<% } else { %>',
|
||||
'<button type="button" class="action-edit btn-toolbar">',
|
||||
'<i class="icon toolbar__icon btn-edit"> </i>',
|
||||
'</button>',
|
||||
'<% } %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
tabindex: 1
|
||||
});
|
||||
this.actionsList.on('item:select', _.bind(this.onSelectActionItem, this));
|
||||
this.actionsList.on('item:click', _.bind(this.onClickActionItem, this));
|
||||
this.actionsList.on('item:dblclick', _.bind(this.onEditActionItem, this));
|
||||
this.actionsList.on('entervalue', _.bind(function(list, record) {
|
||||
this.onEditActionItem(list, null, record);
|
||||
}, this));
|
||||
|
||||
this.searchInput = this.$window.find('#search-input');
|
||||
this.searchInput.on('input', _.bind(this.onInputSearch, this));
|
||||
|
||||
|
||||
this.resetAllBtn = new Common.UI.Button({
|
||||
el: this.$window.find('#reset-all-btn')
|
||||
});
|
||||
this.resetAllBtn.on('click', _.bind(this.onResetAll, this));
|
||||
|
||||
Common.NotificationCenter.on('shortcuts:update', _.bind(function() {
|
||||
this._setDefaults();
|
||||
this.shortcutsEditDialog && this.shortcutsEditDialog.renderShortcutsWarning();
|
||||
}, this));
|
||||
this._setDefaults();
|
||||
},
|
||||
|
||||
getFocusedComponents: function() {
|
||||
return [this.searchInput, this.resetAllBtn, this.actionsList];
|
||||
},
|
||||
|
||||
getDefaultFocusableComponent: function () {
|
||||
return this.actionsList;
|
||||
},
|
||||
|
||||
_setDefaults: function() {
|
||||
this._updateActionsList();
|
||||
},
|
||||
|
||||
_getActionsMap: function() {
|
||||
return this._shortcutsController.getActionsMap();
|
||||
},
|
||||
|
||||
_updateActionsList: function() {
|
||||
const selectedActionIndex = this.actionsList.store.findIndex(function(item) {
|
||||
return item.get('selected');
|
||||
});
|
||||
const scrollPos = this.actionsList.scroller.getScrollTop();
|
||||
|
||||
if(this._state.searchValue) {
|
||||
this._filterActionsList();
|
||||
} else {
|
||||
this.actionsList.store.reset(_.values(this._getActionsMap()));
|
||||
}
|
||||
|
||||
this.actionsList.scroller.scrollTop(scrollPos);
|
||||
if(selectedActionIndex != -1) {
|
||||
this.actionsList.selectByIndex(selectedActionIndex);
|
||||
}
|
||||
},
|
||||
|
||||
_filterActionsList: function() {
|
||||
let filteredData;
|
||||
const me = this;
|
||||
const actionsData = _.values(this._getActionsMap());
|
||||
if(me._state.searchValue) {
|
||||
filteredData = actionsData.filter(function(item) {
|
||||
return (item.action.name || '').toLowerCase().includes(me._state.searchValue);
|
||||
});
|
||||
} else {
|
||||
filteredData = actionsData;
|
||||
}
|
||||
this.actionsList.store.reset(filteredData);
|
||||
},
|
||||
|
||||
onSelectActionItem: function(list, item, record, event) {
|
||||
const text = record ? record.get('action').description : '';
|
||||
this.$window.find('#action-description-text').text(text);
|
||||
},
|
||||
|
||||
onClickActionItem: function(list, item, record, event) {
|
||||
if($(event.target).hasClass('action-edit') || $(event.target).parent().hasClass('action-edit')) {
|
||||
this.onEditActionItem(list, item, record);
|
||||
}
|
||||
},
|
||||
|
||||
onEditActionItem: function(list, item, record) {
|
||||
if(record.get('action').isLocked) return;
|
||||
|
||||
const me = this;
|
||||
|
||||
this.shortcutsEditDialog = new Common.Views.ShortcutsEditDialog({
|
||||
action: record.get('action')
|
||||
});
|
||||
this.shortcutsEditDialog.show();
|
||||
this.shortcutsEditDialog.on('close', function() {
|
||||
me.shortcutsEditDialog = null;
|
||||
me.actionsList.focus();
|
||||
});
|
||||
},
|
||||
|
||||
onInputSearch: function(event) {
|
||||
this._state.searchValue = $(event.target).val().toLowerCase().trim();
|
||||
this._filterActionsList();
|
||||
this.onSelectActionItem(null, null, null);
|
||||
},
|
||||
|
||||
onResetAll: function() {
|
||||
const me = this;
|
||||
|
||||
Common.UI.warning({
|
||||
title: this.txtRestoreToDefault,
|
||||
msg: this.txtRestoreDescription + '<br/>' + this.txtRestoreContinue,
|
||||
buttons: ['ok', 'cancel'],
|
||||
width: 400,
|
||||
callback: function(btn) {
|
||||
if(btn == 'ok') {
|
||||
me._shortcutsController.resetAllShortcuts();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
let state = (typeof(event) == 'object') ? event.currentTarget.attributes['result'].value : event;
|
||||
if (state == 'ok') {
|
||||
this.handler && this.handler.call(this, state, (state == 'ok') ? null : undefined);
|
||||
}
|
||||
|
||||
this.close();
|
||||
},
|
||||
|
||||
onPrimary: function() {
|
||||
this.onDlgBtnClick('ok');
|
||||
return false;
|
||||
},
|
||||
|
||||
txtTitle: 'Keyboard Shortcuts',
|
||||
txtDescription: 'Description',
|
||||
txtEmpty: 'No matches found. Adjust your search.',
|
||||
txtSearch: 'Search',
|
||||
txtRestoreAll: 'Restore All to Defaults',
|
||||
txtRestoreToDefault: 'Restore to default',
|
||||
txtRestoreDescription: 'All shortcuts settings will be restored to deafult.',
|
||||
txtRestoreContinue: 'Do you want to continue?'
|
||||
|
||||
}, Common.Views.ShortcutsDialog || {}))
|
||||
});
|
||||
484
apps/common/main/lib/view/ShortcutsEditDialog.js
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* (c) Copyright Ascensio System SIA 2010-2024
|
||||
*
|
||||
* This program is a free software product. You can redistribute it and/or
|
||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||
* version 3 as published by the Free Software Foundation. In accordance with
|
||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||
* of any third-party rights.
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
*
|
||||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||
* street, Riga, Latvia, EU, LV-1050.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of the Program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU AGPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||
* grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||
* well as technical writing content are licensed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* ShortcutsEditDialog.js
|
||||
*
|
||||
* Created on 23/06/25
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/view/AdvancedSettingsWindow',
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.ShortcutsEditDialog = Common.Views.AdvancedSettingsWindow.extend(_.extend({
|
||||
options: {
|
||||
height: 'auto',
|
||||
contentWidth: 268,
|
||||
contentHeight: 'auto',
|
||||
separator: false
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
_.extend(this.options, {
|
||||
id: 'shortcut-edit-gialog',
|
||||
title: this.txtTitle,
|
||||
contentStyle: 'padding: 16px 16px 0;',
|
||||
contentTemplate: _.template([
|
||||
'<div class="settings-panel active">',
|
||||
'<label id="action-label">',
|
||||
'<span><%= scope.txtAction %>: </span>',
|
||||
'<span id="action-label-name"><%= options.action.name %></span>',
|
||||
'</label>',
|
||||
'<div id="shortcuts-list"></div>',
|
||||
'<div id="buttons-row">',
|
||||
'<label id="new-shortcut-btn" class="link"><%= scope.txtNewShortcut %></label>',
|
||||
'<label id="reset-btn" class="link"><%= scope.txtRestoreToDefault %></label>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join(''))({scope: this, options: options}),
|
||||
}, options);
|
||||
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
this._shortcutsController = app.getController('Common.Controllers.Shortcuts');
|
||||
this._prevKeysForActiveInput = [];
|
||||
|
||||
Common.Views.AdvancedSettingsWindow.prototype.initialize.call(this, this.options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.Views.AdvancedSettingsWindow.prototype.render.call(this);
|
||||
|
||||
this.newShortcutsBtn = this.$window.find('#new-shortcut-btn');
|
||||
this.newShortcutsBtn.on('click', _.bind(this.onAddShortcut, this));
|
||||
|
||||
this.resetBtn = this.$window.find('#reset-btn');
|
||||
this.resetBtn.on('click', _.bind(this.onReset, this));
|
||||
|
||||
this.scrollerOptions = {
|
||||
el: this.$window.find('#shortcuts-list'),
|
||||
wheelSpeed: 8,
|
||||
alwaysVisibleY: true
|
||||
};
|
||||
this.scroller = new Common.UI.Scroller(this.scrollerOptions);
|
||||
|
||||
this._setDefaults();
|
||||
},
|
||||
|
||||
getFocusedComponents: function() {
|
||||
const dynamicComponents = [];
|
||||
this.shortcutsCollection.each(function(record) {
|
||||
dynamicComponents.push(record.get('keysInput'), record.get('removeBtn'));
|
||||
});
|
||||
return dynamicComponents.concat(this.getFooterButtons());
|
||||
},
|
||||
|
||||
getDefaultFocusableComponent: function() {
|
||||
return this.shortcutsCollection.at(0).get('keysInput');
|
||||
},
|
||||
|
||||
_setDefaults: function() {
|
||||
this.shortcutsCollection = new Backbone.Collection([]);
|
||||
this.shortcutsCollection.on('reset', function(newCollection, details) {
|
||||
this._renderShortcutsList(details.previousModels);
|
||||
}, this);
|
||||
this.shortcutsCollection.on('add', function(record, newCollection) {
|
||||
const prevCollection = newCollection.filter(function(item) { return item != record });
|
||||
this._renderShortcutsList(prevCollection);
|
||||
}, this);
|
||||
this.shortcutsCollection.on('remove', function(record, newCollection) {
|
||||
const prevCollection = newCollection.toArray();
|
||||
prevCollection.push(record);
|
||||
this._renderShortcutsList(prevCollection);
|
||||
}, this);
|
||||
this.shortcutsCollection.on('add remove reset change:keys', this.renderShortcutsWarning, this);
|
||||
|
||||
//Get shortcuts for the current action and copy the instances so as not to modify the original instances
|
||||
let shortcuts = _.filter(this._getOriginalShortcuts(), function(shortcut) {
|
||||
return !shortcut.ascShortcut.asc_IsHidden();
|
||||
});
|
||||
shortcuts = shortcuts.map(function(shortcut) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(shortcut.ascShortcut.asc_ToJson());
|
||||
return {
|
||||
keys: shortcut.keys,
|
||||
ascShortcut: copyAscShortcut
|
||||
};
|
||||
});
|
||||
this.shortcutsCollection.reset(shortcuts);
|
||||
if(this.shortcutsCollection.length == 0) {
|
||||
this.onAddShortcut();
|
||||
}
|
||||
},
|
||||
|
||||
_getActionsMap: function() {
|
||||
return this._shortcutsController.getActionsMap();
|
||||
},
|
||||
|
||||
_getOriginalShortcuts: function() {
|
||||
return this._getActionsMap()[this.options.action.type].shortcuts;
|
||||
},
|
||||
|
||||
// Is this shortcut default for this action?
|
||||
_isDefaultShortcut: function(ascShortcut) {
|
||||
const shortcutIndex = ascShortcut.asc_GetShortcutIndex();
|
||||
return _.some(Asc.c_oAscDefaultShortcuts[ascShortcut.asc_GetType()], function(someAscShortcut) {
|
||||
return shortcutIndex == someAscShortcut.asc_GetShortcutIndex();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds all actions that already have the given shortcut assigned.
|
||||
*
|
||||
* If `extraAction` is provided and its `extraAction.actionType` matches the current item,
|
||||
* the method will check `extraAction.shortcuts` instead of the original shortcuts.
|
||||
*
|
||||
* @param {CAscShortcut} ascShortcut The shortcut to search for.
|
||||
*
|
||||
* @param {Object} [extraAction] Optional object that can replace the shortcuts of a matching action.
|
||||
* @param {number} extraAction.actionType The type of the action to match.
|
||||
* @param {CAscShortcut[]} extraAction.shortcuts Custom list of shortcuts to check for this action.
|
||||
* @returns {Object[]} Array of action objects that already use the given shortcut.
|
||||
*/
|
||||
_findAssignedActions: function(ascShortcut, extraAction) {
|
||||
const shortcutIndex = ascShortcut.asc_GetShortcutIndex();
|
||||
const foundItems = [];
|
||||
const values = _.values(this._getActionsMap());
|
||||
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const item = {
|
||||
action: values[i].action,
|
||||
shortcuts: values[i].shortcuts
|
||||
};
|
||||
|
||||
if (extraAction && extraAction.actionType === item.action.type ) {
|
||||
item.shortcuts = extraAction.shortcuts;
|
||||
}
|
||||
|
||||
const existsVisible = _.some(item.shortcuts, function(shortcut) {
|
||||
return shortcut.ascShortcut.asc_GetShortcutIndex() == shortcutIndex &&
|
||||
!shortcut.ascShortcut.asc_IsHidden();
|
||||
});
|
||||
|
||||
if (existsVisible) {
|
||||
foundItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return _.map(foundItems, function(item) { return item.action; });
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the default shortcuts for the current action type.
|
||||
*
|
||||
* @returns {Array<Object>} Array of shortcut objects.
|
||||
* @returns {string[]} return[].keys - Array of key strings representing the shortcut (["Ctrl", "S"]).
|
||||
* @returns {ascShortcut} return[].ascShortcut - Instance of CAscShortcut.
|
||||
*/
|
||||
_getDefaultShortcuts: function() {
|
||||
const me = this;
|
||||
const ascShortcuts = Asc.c_oAscDefaultShortcuts[this.options.action.type];
|
||||
return ascShortcuts.map(function(ascShortcut) {
|
||||
const copyAscShortcut = new Asc.CAscShortcut();
|
||||
copyAscShortcut.asc_FromJson(ascShortcut.asc_ToJson());
|
||||
copyAscShortcut.asc_SetIsHidden(false);
|
||||
return {
|
||||
keys: me._shortcutsController._getAscShortcutKeys(copyAscShortcut),
|
||||
ascShortcut: copyAscShortcut
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_renderShortcutsList: function(prevCollection) {
|
||||
const me = this;
|
||||
|
||||
this.$window.find('#shortcuts-list').empty();
|
||||
this.shortcutsCollection.each(function(item, index) {
|
||||
const ascShortcut = item.get('ascShortcut');
|
||||
const isLocked = ascShortcut.asc_IsLocked();
|
||||
const keysStr = item.get('keys').join(' + ');
|
||||
const $item = $(
|
||||
'<div class="item ' + (index == 0 ? 'first' : '') + '">' +
|
||||
'<div class="keys-input"></div>' +
|
||||
(isLocked
|
||||
? '<button type="button" class="btn-toolbar">' +
|
||||
'<i class="icon toolbar__icon btn-menu-about"> </i>' +
|
||||
'</button>'
|
||||
: '<button type="button" class="btn-toolbar remove-btn">' +
|
||||
'<i class="icon toolbar__icon btn-cc-remove"> </i>' +
|
||||
'</button>'
|
||||
) +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// if(me.shortcutsCollection.length == 1) {
|
||||
// $item.find('.remove-btn').attr('disabled', true).addClass('disabled');
|
||||
// }
|
||||
me.$window.find('#shortcuts-list').append($item);
|
||||
|
||||
const keysInput = new Common.UI.InputField({
|
||||
el : $item.find('.keys-input'),
|
||||
value : keysStr,
|
||||
editable : false,
|
||||
placeHolder : me.txtInputPlaceholder,
|
||||
disabled : isLocked
|
||||
});
|
||||
const removeButton = new Common.UI.Button({
|
||||
el: $item.find('.remove-btn'),
|
||||
});
|
||||
item.set({ keysInput: keysInput, removeBtn: removeButton });
|
||||
|
||||
const $keysInput = $item.find('.keys-input input');
|
||||
$keysInput.on('keydown', function(e) {
|
||||
const alowedSingleKeys = [
|
||||
Common.UI.Keys.F1, Common.UI.Keys.F2, Common.UI.Keys.F3, Common.UI.Keys.F4, Common.UI.Keys.F5,
|
||||
Common.UI.Keys.F6, Common.UI.Keys.F7, Common.UI.Keys.F8, Common.UI.Keys.F9, Common.UI.Keys.F10,
|
||||
Common.UI.Keys.F11, Common.UI.Keys.F12,Common.UI.Keys.INSERT, Common.UI.Keys.HOME,
|
||||
Common.UI.Keys.PAGEUP, Common.UI.Keys.DELETE, Common.UI.Keys.END, Common.UI.Keys.PAGEDOWN,
|
||||
Common.UI.Keys.LEFT, Common.UI.Keys.UP, Common.UI.Keys.RIGHT, Common.UI.Keys.DOWN
|
||||
];
|
||||
|
||||
const forbiddensKeys = [Common.UI.Keys.ESC, Common.UI.Keys.TAB];
|
||||
if(!Common.Utils.isMac) {
|
||||
forbiddensKeys.push(91); //Meta (Super, Win)
|
||||
}
|
||||
|
||||
if (forbiddensKeys.includes(e.keyCode)) {
|
||||
// Restore previous input state when press Tab
|
||||
if(e.keyCode == Common.UI.Keys.TAB && me._prevKeysForActiveInput.length) {
|
||||
item.set('keys', me._prevKeysForActiveInput);
|
||||
$item.find('input').val(me._prevKeysForActiveInput.join(' + '));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if(!alowedSingleKeys.includes(e.keyCode) && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keys = [];
|
||||
|
||||
if (e.ctrlKey) keys.push('Ctrl');
|
||||
if (e.shiftKey) keys.push('Shift');
|
||||
if (e.altKey) keys.push('Alt');
|
||||
if (e.metaKey && Common.Utils.isMac) keys.push('⌘');
|
||||
|
||||
if (![Common.UI.Keys.CTRL, Common.UI.Keys.SHIFT, Common.UI.Keys.ALT, 91].includes(e.keyCode)) {
|
||||
const app = (window.DE || window.PE || window.SSE || window.PDFE || window.VE);
|
||||
keys.push(app.getController('Common.Controllers.Shortcuts').keyCodeToKeyName(e.keyCode));
|
||||
ascShortcut.asc_SetKeyCode(e.keyCode);
|
||||
} else {
|
||||
ascShortcut.asc_SetKeyCode(null);
|
||||
}
|
||||
|
||||
ascShortcut.asc_SetIsCtrl(!!e.ctrlKey);
|
||||
ascShortcut.asc_SetIsShift(!!e.shiftKey);
|
||||
ascShortcut.asc_SetIsAlt(!!e.altKey);
|
||||
ascShortcut.asc_SetIsCommand(!!e.metaKey && Common.Utils.isMac);
|
||||
|
||||
item.set('keys', keys);
|
||||
$item.find('input').val(keys.join(' + '));
|
||||
});
|
||||
|
||||
|
||||
const removeKeysIfOnlyModifiers = function(removedKeys) {
|
||||
const modifierKeys = ['Ctrl', 'Shift', 'Alt', '⌘'];
|
||||
const keys = item.get('keys');
|
||||
const hasExtra = _.some(keys, function(k) {
|
||||
return !_.contains(modifierKeys, k);
|
||||
});
|
||||
|
||||
if (!hasExtra && removedKeys && removedKeys.length) {
|
||||
const filteredKeys = keys.filter(function(k) {
|
||||
return !_.contains(removedKeys, k);
|
||||
});
|
||||
|
||||
item.set('keys', filteredKeys);
|
||||
$item.find('input').val(filteredKeys.join(' + '));
|
||||
}
|
||||
};
|
||||
|
||||
$keysInput.on('keyup', function(e) {
|
||||
const modifierKeyMap = {
|
||||
[Common.UI.Keys.CTRL]: 'Ctrl',
|
||||
[Common.UI.Keys.ALT]: 'Alt',
|
||||
[Common.UI.Keys.SHIFT]: 'Shift',
|
||||
91: '⌘'
|
||||
};
|
||||
const modifierKey = modifierKeyMap[e.keyCode];
|
||||
removeKeysIfOnlyModifiers(modifierKey ? [modifierKey] : []);
|
||||
if(!modifierKey) {
|
||||
me._prevKeysForActiveInput = item.get('keys');
|
||||
}
|
||||
});
|
||||
|
||||
$keysInput.on('focusin', function() {
|
||||
me._prevKeysForActiveInput = item.get('keys');
|
||||
});
|
||||
|
||||
$keysInput.on('focusout', function() {
|
||||
me._prevKeysForActiveInput = [];
|
||||
removeKeysIfOnlyModifiers(item.get('keys'));
|
||||
});
|
||||
|
||||
$item.find('.remove-btn').on('click', function() {
|
||||
me.shortcutsCollection.remove(item);
|
||||
if(me.shortcutsCollection.length == 0) {
|
||||
me.onAddShortcut();
|
||||
}
|
||||
me.$window.find('#shortcuts-list .item input').last().focus();
|
||||
});
|
||||
});
|
||||
this.fixHeight(true);
|
||||
this.scroller.update(this.scrollerOptions);
|
||||
|
||||
//Update focus controll
|
||||
Common.UI.FocusManager.remove(this, 0, prevCollection.length * 2 + 2);
|
||||
Common.UI.FocusManager.add(this, this.getFocusedComponents());
|
||||
},
|
||||
|
||||
renderShortcutsWarning: function() {
|
||||
const me = this;
|
||||
let isButtonDisabled = false;
|
||||
|
||||
this.shortcutsCollection.each(function(item) {
|
||||
const ascShortcut = item.get('ascShortcut');
|
||||
const assignedActionNames = [];
|
||||
const assignedActions = me._findAssignedActions(ascShortcut, {
|
||||
actionType: me.options.action.type,
|
||||
shortcuts: me.shortcutsCollection.toJSON().slice(0, _.indexOf(me.shortcutsCollection.models, item))
|
||||
});
|
||||
const isDefaultShortcut = me._isDefaultShortcut(ascShortcut);
|
||||
const isDisabled = !isDefaultShortcut &&
|
||||
_.some(assignedActions, function(action) { return action.isLocked; });
|
||||
|
||||
isButtonDisabled = isButtonDisabled || isDisabled;
|
||||
|
||||
for (let i = 0; i < assignedActions.length; i++) {
|
||||
const action = assignedActions[i];
|
||||
if(action.isLocked == isDisabled) {
|
||||
assignedActionNames.push('“' + action.name + '”');
|
||||
}
|
||||
}
|
||||
|
||||
let txtKey = null;
|
||||
if (assignedActionNames.length === 1) {
|
||||
txtKey = isDisabled ? 'txtInputWarnOneLocked' : 'txtInputWarnOne';
|
||||
} else if (assignedActionNames.length > 1) {
|
||||
txtKey = isDisabled ? 'txtInputWarnManyLocked' : 'txtInputWarnMany';
|
||||
}
|
||||
item.get('keysInput').showWarning(
|
||||
txtKey
|
||||
? [me[txtKey].replace('%1', assignedActionNames.join(', '))]
|
||||
: null
|
||||
);
|
||||
});
|
||||
this.getFooterButtons()[0].setDisabled(isButtonDisabled);
|
||||
},
|
||||
|
||||
onAddShortcut: function() {
|
||||
const lastShortcutRecord = this.shortcutsCollection.at(this.shortcutsCollection.length - 1);
|
||||
if(!lastShortcutRecord || lastShortcutRecord.get('keys').length) {
|
||||
this.shortcutsCollection.add({
|
||||
keys: [],
|
||||
ascShortcut: new Asc.CAscShortcut(this.options.action.type)
|
||||
});
|
||||
}
|
||||
this.$window.find('#shortcuts-list .item input').last().focus();
|
||||
},
|
||||
|
||||
onReset: function() {
|
||||
const me = this;
|
||||
|
||||
Common.UI.warning({
|
||||
title: this.txtRestoreToDefault,
|
||||
msg: this.txtRestoreDescription.replace('%1', me.options.action.name) + '<br/>' +
|
||||
this.txtRestoreContinue,
|
||||
buttons: ['ok', 'cancel'],
|
||||
width: 400,
|
||||
callback: function(btn) {
|
||||
if(btn == 'ok') {
|
||||
const shortcuts = me._getDefaultShortcuts();
|
||||
me.shortcutsCollection.reset(shortcuts);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
let state = (typeof(event) == 'object') ? event.currentTarget.attributes['result'].value : event;
|
||||
if (state == 'ok') {
|
||||
const seen = {};
|
||||
const filteredShortcuts = [];
|
||||
|
||||
(this.shortcutsCollection.toJSON() || []).forEach(function(item) {
|
||||
if (!item.keys.length) return;
|
||||
|
||||
let idx = item.ascShortcut.asc_GetShortcutIndex();
|
||||
if (seen[idx]) return;
|
||||
|
||||
seen[idx] = true;
|
||||
filteredShortcuts.push({
|
||||
keys: item.keys,
|
||||
ascShortcut: item.ascShortcut
|
||||
});
|
||||
});
|
||||
|
||||
this._shortcutsController.updateShortcutsForAction(this.options.action.type, filteredShortcuts);
|
||||
}
|
||||
|
||||
this.close();
|
||||
},
|
||||
|
||||
onPrimary: function() {
|
||||
this.onDlgBtnClick('ok');
|
||||
return false;
|
||||
},
|
||||
|
||||
txtTitle: 'Edit shortcut',
|
||||
txtAction: 'Action',
|
||||
txtInputPlaceholder: 'Type desired shortcut',
|
||||
txtInputWarnOne: 'The shortcut used by action %1',
|
||||
txtInputWarnOneLocked: 'The shortcut used by action %1 and can’t be changed',
|
||||
txtInputWarnMany: 'The shortcut used by actions %1',
|
||||
txtInputWarnManyLocked: 'The shortcut used by actions %1 and can’t be changed',
|
||||
txtNewShortcut: 'New shortcut',
|
||||
txtRestoreToDefault: 'Restore to default',
|
||||
txtTypeDesiredShortcut: 'Type desired shortcut',
|
||||
txtRestoreDescription: 'All shortcuts for action “%1” will be restored to deafult.',
|
||||
txtRestoreContinue: 'Do you want to continue?'
|
||||
|
||||
}, Common.Views.ShortcutsEditDialog || {}))
|
||||
});
|
||||
@ -344,14 +344,19 @@ define([
|
||||
|
||||
var minScrollbarLength = 20;
|
||||
var wheelSpeed = 20;
|
||||
|
||||
var _4letterLangs = ['pt-pt', 'zh-tw', 'sr-cyrl'];
|
||||
|
||||
var loadTranslation = function(lang, callback) {
|
||||
lang = lang.split(/[\-_]/)[0].toLocaleLowerCase();
|
||||
lang = lang.toLowerCase().split(/[\-_]/);
|
||||
lang = lang[0] + (lang.length>1 ? '-' + lang[1] : '');
|
||||
var idx4Letters = _4letterLangs.indexOf(lang); // try to load 4 letters language
|
||||
lang = (idx4Letters<0) ? lang.split(/[\-]/)[0] : _4letterLangs[idx4Letters];
|
||||
Common.Utils.loadConfig('resources/symboltable/' + lang + '.json', function (langJson) {
|
||||
for (var i=1; i<274; i++) {
|
||||
var val = oRangeNames[i];
|
||||
oRangeNames[i] = langJson[val] || val;
|
||||
if ( langJson !== 'error' ) {
|
||||
for (var i=1; i<274; i++) {
|
||||
var val = oRangeNames[i];
|
||||
oRangeNames[i] = langJson[val] || val;
|
||||
}
|
||||
}
|
||||
callback && callback();
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 516 B |
|
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 124 B |
|
After Width: | Height: | Size: 314 B |
BIN
apps/common/main/resources/img/toolbar/1.25x/btn-macros-stop.png
Normal file
|
After Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
|
After Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
BIN
apps/common/main/resources/img/toolbar/1.5x/btn-macros-pause.png
Normal file
|
After Width: | Height: | Size: 123 B |
|
After Width: | Height: | Size: 356 B |
BIN
apps/common/main/resources/img/toolbar/1.5x/btn-macros-stop.png
Normal file
|
After Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 548 B After Width: | Height: | Size: 548 B |
|
After Width: | Height: | Size: 708 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 132 B |
|
After Width: | Height: | Size: 356 B |
BIN
apps/common/main/resources/img/toolbar/1.75x/btn-macros-stop.png
Normal file
|
After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 674 B |
BIN
apps/common/main/resources/img/toolbar/1x/big/btn-properties.png
Normal file
|
After Width: | Height: | Size: 440 B |
|
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 148 B |
BIN
apps/common/main/resources/img/toolbar/1x/btn-macros-pause.png
Normal file
|
After Width: | Height: | Size: 109 B |
BIN
apps/common/main/resources/img/toolbar/1x/btn-macros-record.png
Normal file
|
After Width: | Height: | Size: 285 B |
BIN
apps/common/main/resources/img/toolbar/1x/btn-macros-stop.png
Normal file
|
After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
|
||||
<path fill="#000" d="M20.69 14a7 7 0 0 0-.038-.84l-.085-.585 2.256-1.716-1.625-2.731-2.175.842-.516.2-.443-.331a7 7 0 0 0-1.513-.862l-.526-.217L15.62 5h-3.24l-.405 2.771-.541.212c-.377.148-.88.427-1.522.874l-.437.305-2.672-1.034-1.625 2.731 2.257 1.716-.085.584a7 7 0 0 0-.04.841c0 .427.017.696.038.84l.085.585-2.257 1.715 1.625 2.731 2.176-.84.515-.2.444.33q.54.404 1.12.687l.392.175.527.217.403 2.76h3.242l.406-2.771.54-.212c.378-.148.881-.427 1.522-.874l.438-.305.496.192 2.175.841 1.625-2.731-2.256-1.715.085-.584A7 7 0 0 0 20.69 14m.987.575a5 5 0 0 1-.035.411l2.162 1.643q.336.234.096.657l-2.067 3.475q-.168.287-.52.216l-.104-.029-2.548-.985q-1.008.704-1.73.985l-.384 2.63q-.096.421-.48.422h-4.133l-.092-.007q-.261-.04-.36-.316l-.029-.1-.384-2.629a8 8 0 0 1-1.73-.985l-2.548.985q-.432.141-.624-.187l-2.066-3.475q-.24-.422.095-.657l2.163-1.643A7 7 0 0 1 6.31 14q0-.657.048-.986L4.196 11.37q-.294-.205-.147-.555l.052-.102 2.066-3.475q.192-.328.624-.187l2.548.985q1.01-.704 1.73-.985l.384-2.63q.084-.369.389-.415L11.934 4h4.133q.384 0 .48.423l.385 2.629q.912.375 1.73.985l2.547-.985q.432-.141.624.187l2.067 3.475q.24.422-.096.657l-2.162 1.643q.048.329.048.986z"/>
|
||||
<path fill="#000" d="M16 14a2 2 0 1 0-4 0 2 2 0 0 0 4 0m1 0a3 3 0 1 1-6 0 3 3 0 0 1 6 0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
@ -0,0 +1,4 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 13H8V7h1zm3 0h-1V7h1z" fill="#000"/>
|
||||
<path d="M17 17H3V3h14zM4 16h12V4H4z" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 212 B |
@ -0,0 +1,5 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.5 10a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9m0 1a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7" fill="#000"/>
|
||||
<path d="M17 9h-1V6H4v10h5v1H3V3h14zM4 5h12V4H4z" fill="#000"/>
|
||||
<path d="M9 12H6v-1h3zm3-3H6V8h6zm2.5 3.25a2.25 2.25 0 1 1 0 4.5 2.25 2.25 0 0 1 0-4.5" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 390 B |
@ -0,0 +1,4 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 13H7V7h6z" fill="#000"/>
|
||||
<path d="M17 17H3V3h14zM4 16h12V4H4z" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 477 B |
BIN
apps/common/main/resources/img/toolbar/2x/big/btn-properties.png
Normal file
|
After Width: | Height: | Size: 895 B |
|
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 224 B |
BIN
apps/common/main/resources/img/toolbar/2x/btn-macros-pause.png
Normal file
|
After Width: | Height: | Size: 136 B |
BIN
apps/common/main/resources/img/toolbar/2x/btn-macros-record.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
apps/common/main/resources/img/toolbar/2x/btn-macros-stop.png
Normal file
|
After Width: | Height: | Size: 132 B |
|
Before Width: | Height: | Size: 789 B After Width: | Height: | Size: 789 B |
|
After Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 534 B |
|
After Width: | Height: | Size: 197 B |
|
After Width: | Height: | Size: 603 B |
|
After Width: | Height: | Size: 244 B |
|
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 465 B |
|
After Width: | Height: | Size: 959 B |
|
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 523 B |
|
After Width: | Height: | Size: 208 B |