/* * (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 * */ /** * MacrosDialog.js * * Created on 04.10.2024 * */ if (Common === undefined) var Common = {}; define([], function () { 'use strict'; Common.Views.MacrosDialog = Common.UI.Window.extend(_.extend({ initialize : function(options) { var _options = {}, innerHeight = Math.max(Common.Utils.innerHeight() - Common.Utils.InternalSettings.get('window-inactive-area-top'), 350), innerWidth = Math.max(Common.Utils.innerWidth(), 600); _.extend(_options, { id: 'macros-dialog', title: this.textTitle, header: true, help: true, width: Math.min(810, innerWidth), height: Math.min(512, innerHeight), minwidth: 750, minheight: 350, resizable: true, cls: 'modal-dlg invisible-borders', buttons: [{ value: 'ok', caption: this.textSave }, 'cancel'] }, options || {}); this.api = options.api; this.ItemTypes = { CustomFunction : 0, Macros : 1 }; this._state = { isFunctionsSupport: !!window.SSE, selectedItem: { record: null, type: null }, currentValue: '', currentPos: {row: 3, column: 0} }; this.template = [ '
' + '
' + '
style="height: 100%;" <% } %>>' + '' + '
' + '
' + '
' + '
style="display: none;" <% } %> >
' + '
style="display: none;" <% } %> >' + '' + '
' + '
' + '
' + '
' + '
' + '
' + '' + '
' + '' + '
' + '
'+ '
', ].join(''); _options.tpl = _.template(this.template)({ isFunctionsSupport: this._state.isFunctionsSupport, }); this.on({ 'help': this.onHelp, 'drag': function(args){ args[0].codeEditor && args[0].codeEditor.enablePointerEvents(args[1]!=='start'); }, 'resize': function(args){ args[0].codeEditor && args[0].codeEditor.enablePointerEvents(args[1]!=='start'); } }); Common.UI.Window.prototype.initialize.call(this, _options); }, render: function() { Common.UI.Window.prototype.render.call(this); var me = this, $window = this.getChild(); $window.find('.dlg-btn').on('click', _.bind(this.onBtnClick, this)); me.aceContainer = $window.find('#macros-code-editor'); // this.loadMask = new Common.UI.LoadMask({owner: this.$window.find('.body')[0]}); // this.loadMask.setTitle(this.textLoading); // this.loadMask.show(); me.createCodeEditor(); me.renderAfterAceLoaded(); me.calcHeaderBreakpoints(); me.collapseHeaderItems(); me.updateCustomFunctionLabel(); var throttleResizing = _.throttle(_.bind(this.collapseHeaderItems, this), 100); this.on('resizing', function(){ throttleResizing(); }); }, renderAfterAceLoaded: function() { this.btnUndo = new Common.UI.Button({ parentEl : $('#btn-macros-undo'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-undo icon-rtl', hint : this.tipUndo }).on('click', _.bind(this.onUndo, this)); this.btnRedo = new Common.UI.Button({ parentEl : $('#btn-macros-redo'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-redo icon-rtl', hint : this.tipRedo }).on('click', _.bind(this.onRedo, this)); this.btnRun = new Common.UI.Button({ parentEl : $('#btn-macros-run'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-run', caption : this.textRun, hint : this.tipMacrosRun }).on('click', _.bind(this.onRunMacros, this, false)); this.btnDebug = new Common.UI.Button({ parentEl : $('#btn-macros-debug'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-debug', caption : this.textDebug, hint : this.tipMacrosDebug }).on('click', _.bind(this.onRunMacros, this, true)); this.btnCopy = new Common.UI.Button({ parentEl : $('#btn-macros-copy'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-copy', caption : this.textCopy, hint : this.tipMacrosCopy }).on('click', _.bind(this.onCopyItem, this)); this.btnRename = new Common.UI.Button({ parentEl : $('#btn-macros-rename'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-rename', caption : this.textRename, hint : this.tipMacrosRename }).on('click', _.bind(this.onRenameItem, this)); this.btnDelete = new Common.UI.Button({ parentEl : $('#btn-macros-delete'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-cc-remove', caption : this.textDelete, hint : this.tipMacrosDelete }).on('click', _.bind(this.onDeleteItem, this)); this.chAutostart = new Common.UI.CheckBox({ el: $('#ch-macros-autostart'), labelText: this.textAutostart }).on('change', _.bind(this.onChangeAutostart, this)); var isPresentAI = this.api.checkAI(); this.btnAiMacrosAdd = new Common.UI.Button({ parentEl : $('#btn-ai-macros-add'), cls : 'btn-toolbar', iconCls : 'toolbar__icon btn-general-ai', menu : new Common.UI.Menu({ additionalAlign: this.menuAddAlign, items:[ {caption: this.textCreateFromDesc, value: 'create', disabled: !isPresentAI}, {caption: this.textConvertFromVBA, value: 'convert', disabled: !isPresentAI} ] }), hint : this.tipAi }); this.btnAiMacrosAdd.menu.on('item:click', _.bind(this.onAiMenu, this)); this.btnMacrosAdd = new Common.UI.Button({ parentEl: $('#btn-macros-add'), cls: 'btn-toolbar', iconCls: 'toolbar__icon btn-zoomup', hint: this.tipMacrosAdd }).on('click', _.bind(this.onCreateMacros, this, '')); this.listMacros = new Common.UI.ListView({ el: $('#macros-list', this.$window), store: new Common.UI.DataViewStore(), simpleAddMode: true, itemTemplate: _.template([ '
', '<% if (autostart) { %>', '(A)', '<% } %>', '
', '
<%= Common.Utils.String.htmlEncode(name) %>
' ].join('')) }); this.listMacros.on('item:add', _.bind(this.onAddListItem, this)); this.listMacros.on('item:select', _.bind(this.onSelectListMacrosItem, this)); this.setListMacros(); if(this._state.isFunctionsSupport) { this.btnFunctionAdd = new Common.UI.Button({ parentEl: $('#btn-function-add'), cls: 'btn-toolbar', iconCls: 'toolbar__icon btn-zoomup', hint: this.tipFunctionAdd }).on('click', _.bind(this.onCreateFunction, this)); this.listFunctions = new Common.UI.ListView({ el: $('#functions-list', this.$window), store: new Common.UI.DataViewStore(), tabindex: 1, cls: 'dbl-clickable', itemTemplate: _.template([ '
', '
<%= Common.Utils.String.htmlEncode(name) %>
' ].join('')) }); this.listFunctions.on('item:add', _.bind(this.onAddListItem, this)); this.listFunctions.on('item:select', _.bind(this.onSelectListFunctionItem, this)); this.setListFunctions(); } this.makeDragable(); }, createCodeEditor: function() { var me = this; this.codeEditor = new Common.UI.MonacoEditor({parentEl: '#macros-code-editor'}); this.codeEditor.on('ready', function() { me.codeEditor.updateTheme(); me.codeEditor.setValue(me._state.currentValue, me._state.currentPos); setTimeout(function() { me.aceContainer.removeClass('invisible'); }, 10); // me.loadMask.hide(); }); this.codeEditor.on('change', function(value, pos) { if(me._state.selectedItem.record) { me._state.currentValue = value; me._state.currentPos = pos; me._state.selectedItem.record.set('value', value); me._state.selectedItem.record.set('currentPos', pos); } }); }, calcHeaderBreakpoints: function() { this.breakpoints = []; var me = this; var maxHeaderWidth = 10; //10px - gap between chAutostart and btnDelete var headerItems = [ { btn: this.btnUndo, collapsible: false }, { btn: this.btnRedo, collapsible: false }, { btn: this.btnRun, collapsible: true }, { btn: this.btnDebug, collapsible: true }, { btn: this.btnCopy, collapsible: true }, { btn: this.btnRename, collapsible: true }, { btn: this.btnDelete, collapsible: true }, { btn: this.chAutostart, collapsible: false, withoutMargin: true } ]; this.collapsibleHeaderItems = headerItems.filter(function(item) { return item.collapsible }); headerItems.forEach(function(item) { var $caption = item.btn.$el.find('.caption'); var hasCaptionHidden = $caption.hasClass('hide'); $caption.removeClass('hide'); item.expandedWidth = item.btn.$el.outerWidth(!item.withoutMargin); item.collapsedWidth = item.collapsible ? (item.expandedWidth - $caption.outerWidth(true)) : item.expandedWidth; maxHeaderWidth += item.expandedWidth; hasCaptionHidden && $caption.addClass('hide'); }); this.collapsibleHeaderItems.forEach(function(item, index) { if(index == 0) { me.breakpoints.push({ width: maxHeaderWidth, collapseItems: [item] }); } else { var prevBreakpoint = me.breakpoints[index - 1]; var prevItem = me.collapsibleHeaderItems[index - 1]; me.breakpoints.push({ width: prevBreakpoint.width - (prevItem.expandedWidth - prevItem.collapsedWidth), collapseItems: [item].concat(prevBreakpoint.collapseItems) }); } }); }, collapseHeaderItems: function() { var width = this.getChild().find('#macros-dialog-right .menu-header').width(); var currentBreakpoint = null; for (let i = this.breakpoints.length - 1; i >= 0; i--) { if(width < this.breakpoints[i].width) { currentBreakpoint = this.breakpoints[i]; break; } } this.collapsibleHeaderItems.forEach(function(item) { var shouldCollapse = currentBreakpoint && currentBreakpoint.collapseItems.indexOf(item) !== -1; item.btn.$el.find('.caption').toggleClass('hide', !!shouldCollapse); }); }, updateCustomFunctionLabel: function() { var $window = this.getChild(); var $macrosDialogLeft = $window.find('#macros-dialog-left'); var $menuHeader = $window.find('#functions-menu .menu-header'); var $btnFunctionAdd = $window.find('#btn-function-add'); var $functionLabel = $window.find('#macros-dialog-functions-label'); var minWidth = parseFloat($macrosDialogLeft.css('min-width')) || 0; var menuHeaderPadding = (parseFloat($menuHeader.css('padding-left')) || 0) + (parseFloat($menuHeader.css('padding-right')) || 0); var btnWidth = $btnFunctionAdd.outerWidth(true) || 0; var allowedWidth = minWidth - menuHeaderPadding - btnWidth; if ($functionLabel.width() > allowedWidth) { $functionLabel.text(this.textFunctions); } }, setListMacros: function() { var me = this; var data = this.parseDataFromApi(this.api.pluginMethod_GetMacros()); var macrosList = data.macrosArray; var dataVBA = this.api.pluginMethod_GetVBAMacros(); if (dataVBA && typeof dataVBA === 'string' && dataVBA.includes('') + 12; var end = el.indexOf('', start); var macros = el.slice(start, end); start = el.indexOf('Name="') + 6; end = el.indexOf('"', start); var name = el.slice(start, end); var index = macrosList.findIndex(function(macr){return macr.name == name}); if (index == -1) { macros = macros.replace(/&/g,'&'); macros = macros.replace(/</g,'<'); macros = macros.replace(/>/g,'>'); macros = macros.replace(/'/g,'\''); macros = macros.replace(/"/g,'"'); macros = macros.replace(/Attribute [^\r\n]*\r\n/g, ""); macrosList.push({ guid: me.createGuid(), name: name, autostart: false, value: '(function()\n{\n\t/* Enter your code here. */\n})();\n\n/*\nExecution of VBA commands does not support.\n' + macros + '*/' }); } }); } if(macrosList && macrosList.length > 0) { macrosList.forEach(function (macros) { macros.autostart = !!macros.autostart; macros.currentPos = {row: 3, column: 0}; }); this.listMacros.store.reset(macrosList); var selectItem = this.listMacros.store.at(data.current); selectItem && this.listMacros.selectRecord(selectItem); } else { this.onCreateMacros(); } }, setListFunctions: function() { var data = this.parseDataFromApi(this.api.pluginMethod_GetCustomFunctions()); var macrosList = data.macrosArray; this.listFunctions.store.reset(macrosList); }, makeDragable: function() { var me = this; var currentElement; var currentIndex = 0; var insertIndex; var macrosList = document.getElementById("macros-list"); var functionList = document.getElementById("functions-list"); function getInsertIndex(cursorPosition, currentElement, elements) { // cursorPosition = cursorPosition * ((1 + (1 - zoom)).toFixed(1)); var currentIndex = elements.index(currentElement); var nextIndex = currentIndex; var currentElementCoord = Common.Utils.getBoundingClientRect(currentElement); var currentElementCenter = currentElementCoord.y + currentElementCoord.height * 0.45; if(cursorPosition > currentElementCenter) { nextIndex += 1; } return nextIndex } function handleDragstart(list, e) { me.codeEditor.disableDrop(true); var id = $(e.target).children('.list-item').attr('id'); e.dataTransfer.setData("text/plain", id); e.dataTransfer.effectAllowed = "move"; e.target.classList.add('dragged'); currentIndex = list.store.indexOf(list.store.findWhere({ id: id })); e.target.click(); } function handleDragend(list, e) { me.codeEditor.disableDrop(false); e.target.classList.remove('dragged'); $('.dragHovered').removeClass("dragHovered"); if (currentIndex === insertIndex || insertIndex == null) return; if (insertIndex === -1) insertIndex = list.store.length; if (currentIndex < insertIndex) insertIndex--; var newStoreArr = list.store.models.slice(); let tmp = newStoreArr.splice(currentIndex, 1)[0]; newStoreArr.splice(insertIndex, 0, tmp); list.store.reset(newStoreArr); currentIndex = 0; } function handleDragover(list, type, e) { e.preventDefault(); currentElement = e.target; let bDragAllowed = me._state.selectedItem.type === type; e.dataTransfer.dropEffect = bDragAllowed ? "move" : "none"; const isMoveable = currentElement.classList.contains('draggable'); if (!isMoveable || !bDragAllowed) return; insertIndex = getInsertIndex(e.clientY, currentElement, $(list).find('.item')); $('.dragHovered').removeClass("dragHovered") if(insertIndex < $(list).find('.item').length) { $(list).find('.item').last().removeClass(['dragHovered', 'last']); $(list).find('.item')[insertIndex].classList.add('dragHovered'); } else { $(list).find('.item').last().addClass(['dragHovered', 'last']); } } function handleDragleave(e) { if(e.fromElement) { if($(e.fromElement).attr('role') == 'list' || $(e.fromElement).attr('role') == 'listitem' || !!$(e.fromElement).parents('[role="listitem"]').length ) return; $('.dragHovered').removeClass("dragHovered"); insertIndex = null; } } macrosList.addEventListener('dragstart', function(e) { handleDragstart(me.listMacros, e); }); functionList.addEventListener('dragstart', function(e) { handleDragstart(me.listFunctions, e); }); macrosList.addEventListener('dragend', function(e) { handleDragend(me.listMacros, e); }); functionList.addEventListener('dragend', function(e) { handleDragend(me.listFunctions, e); }); macrosList.addEventListener('dragover', function(e) { handleDragover(macrosList, me.ItemTypes.Macros, e) }); functionList.addEventListener('dragover', function(e) { handleDragover(functionList, me.ItemTypes.CustomFunction, e) }); macrosList.addEventListener('dragleave', function(e) { handleDragleave(e); }); functionList.addEventListener('dragleave', function(e) { handleDragleave(e); }); }, selectItem: function(record, type) { this._state.selectedItem.record = record; this._state.selectedItem.type = type; this.codeEditor.setValue(record.get('value'), record.get('currentPos')!==undefined ? record.get('currentPos') : {row: 3, column: 0}); this.codeEditor.revealPositionInCenter(); this._state.currentValue = record.get('value'); this._state.currentPos = record.get('currentPos'); this.chAutostart.setValue(record.get('autostart')); this.getChild().find('.lock-for-function').toggleClass('hidden', type == this.ItemTypes.CustomFunction); if(type == this.ItemTypes.Macros && this.listFunctions) { this.listFunctions.deselectAll(); } if(type == this.ItemTypes.CustomFunction && this.listMacros) { this.listMacros.deselectAll(); } this.updateHintButtons(); this.setDisableButtons(false); }, updateHintButtons: function() { var typeString = (this._state.selectedItem.type == this.ItemTypes.Macros ? 'Macros' : 'Function'); this.btnCopy.updateHint(this['tip' + typeString + 'Copy']); this.btnRename.updateHint(this['tip' + typeString + 'Rename']); this.btnDelete.updateHint(this['tip' + typeString + 'Delete']); }, setDisableButtons: function(value) { this.btnUndo.setDisabled(value); this.btnRedo.setDisabled(value); this.btnRun.setDisabled(value); this.btnDebug.setDisabled(value); this.btnCopy.setDisabled(value); this.btnRename.setDisabled(value); this.btnDelete.setDisabled(value); this.chAutostart.setDisabled(value); }, parseDataFromApi: function(data) { var result = { macrosArray : [], current : -1 }; if (data) { try { result = JSON.parse(data); } catch (err) { result = { macrosArray: [], current: -1 }; } } return result; }, createGuid: function(a,b){ for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):''); return b }, getFocusedComponents: function() { return [].concat(this.getFooterButtons()); }, getDefaultFocusableComponent: function () { }, close: function(suppressevent) { this.codeEditor.destroyEditor(); Common.UI.Window.prototype.close.call(this, arguments); }, _handleInput: function(state) { if (this.options.handler) { this.options.handler.call(this, this, state); } if(state === 'ok') { this.api.pluginMethod_SetMacros(JSON.stringify({ macrosArray: this.listMacros.store.models.map(function(item) { return { guid: item.get('guid'), name: item.get('name'), autostart: item.get('autostart'), value: item.get('value') } }), current: this.listMacros.store.indexOf(this.listMacros.getSelectedRec()) })); if(this._state.isFunctionsSupport) { this.api.pluginMethod_SetCustomFunctions(JSON.stringify({ macrosArray: this.listFunctions.store.models.map(function(item) { return { guid: item.get('guid'), name: item.get('name'), value: item.get('value') } }) })); } } this.close(); }, onAddListItem: function(listView, itemView) { itemView.$el.attr('draggable', true); itemView.$el.addClass('draggable'); }, onCopyItem: function() { if(!this._state.selectedItem.record) return; let list = (this._state.selectedItem.type == this.ItemTypes.Macros ? this.listMacros : this.listFunctions); let item = this._state.selectedItem.record; list.store.add({ guid: this.createGuid(), name: item.get('name') + '_copy', value: item.get('value'), autostart: item.get('autostart') }); list.selectRecord(list.store.at(-1)); }, onRenameItem: function() { if(!this._state.selectedItem.record) return; var me = this; var windowSize = { width: 300, height: 90 }; var macrosWindowRect = Common.Utils.getBoundingClientRect(this.$window[0]); (new Common.Views.TextInputDialog({ value: me._state.selectedItem.record.get('name'), width: windowSize.width, height: windowSize.height, inputConfig: { allowBlank : false, validation: function(value) { return value.trim().length > 0 ? true : ''; } }, handler: function(result, value) { if (result == 'ok') { me._state.selectedItem.record.set('name', value.trim()); } } })).show( macrosWindowRect.left + (macrosWindowRect.width - windowSize.width) / 2, macrosWindowRect.top + (macrosWindowRect.height - windowSize.height) / 2 ); }, onCreateMacros: function(value) { var indexMax = 0; var macrosTextEn = 'Macro'; var macrosTextTranslate = this.textMacro; this.listMacros.store.each(function(macros, index) { var macrosName = macros.get('name'); if (0 == macrosName.indexOf(macrosTextEn)) { var index = parseInt(macrosName.substr(macrosTextEn.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } else if (0 == macrosName.indexOf(macrosTextTranslate)) { var index = parseInt(macrosName.substr(macrosTextTranslate.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } }); indexMax++; this.listMacros.store.add({ guid: this.createGuid(), name : (macrosTextTranslate + " " + indexMax), value : value || "(function()\n{\n \n})();", autostart: false, currentPos: {row: 3, column: 5} }); this.listMacros.selectRecord(this.listMacros.store.at(-1)); }, onSelectListMacrosItem: function(listView, itemView, record) { this.selectItem(record, this.ItemTypes.Macros); }, onUndo: function() { this.codeEditor.undo(); }, onRedo: function() { this.codeEditor.redo(); }, onAiMenu: function(menu, item) { var me = this; var title = ''; var instruction = ''; var instructionOutput = 'Generate JavaScript code as an Immediately Invoked Function Expression (IIFE), in the format (function(){ ... })();, that [describe what the code should do]. The code should be self-contained and execute immediately. '; var langCode = Common.Locale.getCurrentLanguage() var langName = Common.util.LanguageInfo.getLocalLanguageName(Common.util.LanguageInfo.getLocalLanguageCode(langCode)); if(langName && typeof langName[1] == "string") { langName = langName[1]; } else { langName = null; } var editorName = 'Document Editor'; if(window.PE) editorName = 'Presentation Editor'; if(window.SSE) editorName = 'Spreadsheet Editor'; if(item.value == 'create') { title = this.textCreateMacrosFromDesc; instruction = '' + 'Create a macro for OnlyOffice. ' + 'The macro should be written specifically for the OnlyOffice ' + editorName + '. ' + 'Return only code with comments, as plain text without markdown. ' + 'The format of the code is JavaScript. ' + 'Write comments in the same language as the user prompt. ' + 'The description of what the macro should do is also described in the user message. ' + instructionOutput; } else if(item.value == 'convert') { title = this.textConvertMacrosFromVBA; instruction = '' + 'Convert macro for OnlyOffice from VBA. ' + 'The macro should be written specifically for the OnlyOffice ' + editorName + '. ' + 'Return only code with comments, as plain text without markdown. ' + 'The code format is JavaScript. ' + 'Write comments in ' + langCode + (langName ? '(' + langName + ')' : '') + ' language. ' + 'The code of the macro in VBA should be presented in the user message. ' + instructionOutput; } if(item.value == 'create' || item.value == 'convert') { var macrosWindow = new Common.Views.MacrosAiDialog({ title: title, api: this.api, instruction: instruction, inputType: item.value == 'create' ? 'textarea' : 'codeEditor', handler: function(btnValue, value) { if(btnValue == 'ok') { me.onCreateMacros(value); } } }); macrosWindow.show(); } }, onRunMacros: function(isDebug) { this.api.callCommand(isDebug ? "debugger;\n" + this._state.currentValue : this._state.currentValue); }, onChangeAutostart: function(field, newValue) { if(!this._state.selectedItem.record) return; this._state.selectedItem.record.set('autostart', newValue == 'checked'); }, onDeleteItem: function() { if(!this._state.selectedItem.record) return; let list = (this._state.selectedItem.type == this.ItemTypes.Macros ? this.listMacros : this.listFunctions); let item = this._state.selectedItem.record; var deletedIndex = list.store.indexOf(item); list.store.remove(item); if(list.store.length > 0) { var selectedIndex = deletedIndex < list.store.length ? deletedIndex : list.store.length - 1; list.selectByIndex(selectedIndex); } else { this.codeEditor.setValue('', {row: 0, column: 0}, true); this.setDisableButtons(true); } }, onCreateFunction: function() { var indexMax = 0; var macrosTextEn = 'Custom function'; var macrosTextTranslate = this.textCustomFunction; this.listFunctions.store.each(function(macros, index) { var macrosName = macros.get('name'); if (0 == macrosName.indexOf("Custom function")) { var index = parseInt(macrosName.substr(macrosTextEn.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } else if (0 == macrosName.indexOf(macrosTextTranslate)) { var index = parseInt(macrosName.substr(macrosTextTranslate.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } }); indexMax++; this.listFunctions.store.add({ guid: this.createGuid(), name : (macrosTextTranslate + " " + indexMax), value : "(function()\n{\n\t/**\n\t * Function that returns the argument\n\t * @customfunction\n\t * @param {any} arg Any data.\n * @returns {any} The argumet of the function.\n\t*/\n\tfunction myFunction(arg) {\n\t\t\n\t return arg;\n\t}\n\tApi.AddCustomFunction(myFunction);\n})();", currentPos: {row: 10, column: 3} }); this.listFunctions.selectRecord(this.listFunctions.store.at(-1)); }, onSelectListFunctionItem: function(listView, itemView, record) { this.selectItem(record, this.ItemTypes.CustomFunction); }, onThemeChanged: function() { this.calcHeaderBreakpoints(); this.collapseHeaderItems(); Common.UI.Window.prototype.onThemeChanged.call(this); }, onHelp: function() { window.open('https://api.onlyoffice.com/docs/plugin-and-macros/macros/getting-started/', '_blank') }, onBtnClick: function(event) { this._handleInput(event.currentTarget.attributes['result'].value); }, // onPrimary: function() { // this.close(); // return false; // }, textTitle : 'Macros', textSave : 'Save', textMacro : 'Macro', textMacros : 'Macros', textRun : 'Run', textDebug : 'Debug', textAutostart : 'Autostart', textRename : 'Rename', textDelete : 'Delete', textCopy : 'Copy', textCustomFunction : 'Custom function', textCustomFunctions : 'Custom functions', textFunctions : 'Functions', textLoading : 'Loading...', textCreateFromDesc : 'Create from description', textCreateMacrosFromDesc : 'Create macros from description', textConvertFromVBA : 'Convert from VBA', textConvertMacrosFromVBA : 'Convert macros from VBA', tipUndo : 'Undo', tipRedo : 'Redo', tipMacrosRename : 'Rename macros', tipMacrosDelete : 'Delete macros', tipMacrosCopy : 'Copy macros', tipMacrosRun : 'Run macros', tipMacrosDebug : 'Debug macros', tipMacrosAdd : 'Add macros', tipFunctionRename : 'Rename custom function', tipFunctionDelete : 'Delete custom function', tipFunctionCopy : 'Copy custom function', tipFunctionAdd : 'Add custom function', tipAi : 'AI' }, Common.Views.MacrosDialog || {})) });