diff --git a/apps/common/main/lib/view/MacrosDialog.js b/apps/common/main/lib/view/MacrosDialog.js index 47ac9f0567..6d70882c3f 100644 --- a/apps/common/main/lib/view/MacrosDialog.js +++ b/apps/common/main/lib/view/MacrosDialog.js @@ -48,7 +48,7 @@ define([ template: '
' + '
' + - ''+ '
', @@ -93,14 +93,28 @@ define([ }, options || {}); this.api = options.api; - _options.tpl = _.template(this.template)(_options); - + this.CurrentElementModeType = { + CustomFunction : 0, + Macros : 1 + }; this._state = { - macrosItemMenuOpen: null - } + aceLoadedModules: { + tern: false, + langTools: window.isIE, + htmlBeautify: false + }, + isFunctionsSupport: !!window.SSE, + macrosItemMenuOpen: null, + functionItemMenuOpen: null, + isDisable: false, + currentElementMode: this.CurrentElementModeType.Macros + }; + + _options.tpl = _.template(this.template)({ + isFunctionsSupport: this._state.isFunctionsSupport, + }); this.on('help', this.onHelp); - this.on('close', this.onClose); Common.UI.Window.prototype.initialize.call(this, _options); }, @@ -112,6 +126,24 @@ define([ $window = this.getChild(); $window.find('.dlg-btn').on('click', _.bind(this.onBtnClick, this)); + + this.loadMask = new Common.UI.LoadMask({owner: this.$window.find('.body')[0]}); + this.loadMask.setTitle(this.textLoading); + this.loadMask.show(); + require(['../vendor/ace/ace'], function(ace) { + me.createCodeEditor(); + }); + }, + + onAceLoadModule: function() { + if( _.values(this._state.aceLoadedModules).every(function(val) { return val })) { + this.renderAfterAceLoaded(); + this.loadMask.hide(); + this.$window.find('.content').removeClass('invisible'); + } + }, + + renderAfterAceLoaded: function() { this.btnMacrosRun = new Common.UI.Button({ parentEl: $('#btn-macros-run'), cls: 'btn-toolbar borders--small', @@ -131,16 +163,6 @@ define([ dataHintOffset: 'small' }).on('click', _.bind(this.onCreateMacros, this)); - this.btnFunctionAdd = new Common.UI.Button({ - parentEl: $('#btn-function-add'), - cls: 'btn-toolbar borders--small', - iconCls: 'icon toolbar__icon btn-zoomup', - hint: this.tipFunctionAdd, - dataHint: '1', - dataHintDirection: 'bottom', - dataHintOffset: 'small' - }); - this.listMacros = new Common.UI.ListView({ el: $('#list-macros', this.$window), store: new Common.UI.DataViewStore(), @@ -156,12 +178,11 @@ define([ '
' ].join('')) }); - this.listMacros.on('item:add', _.bind(this.onAddListMacrosItem, this)); + this.listMacros.on('item:add', _.bind(this.onAddListItem, this)); this.listMacros.on('item:click', _.bind(this.onClickListMacrosItem, this)); this.listMacros.on('item:contextmenu', _.bind(this.onContextMenuListMacrosItem, this)); - + this.listMacros.on('item:select', _.bind(this.onSelectListMacrosItem, this)); this.setListMacros(); - this.makeDragable(); this.ctxMenuMacros = new Common.UI.Menu({ cls: 'shifted-right', @@ -193,52 +214,71 @@ define([ ] }); - this.inputText = new Common.UI.InputField({ - el: $('#search-adv-text'), - placeHolder: this.textFind, - allowBlank: true, - validateOnBlur: false, - style: 'width: 100%;', - type: 'search', - dataHint: '1', - dataHintDirection: 'left', - dataHintOffset: 'small' - }); + if(this._state.isFunctionsSupport) { + this.btnFunctionAdd = new Common.UI.Button({ + parentEl: $('#btn-function-add'), + cls: 'btn-toolbar borders--small', + iconCls: 'icon toolbar__icon btn-zoomup', + hint: this.tipFunctionAdd, + dataHint: '1', + dataHintDirection: 'bottom', + dataHintOffset: 'small' + }).on('click', _.bind(this.onCreateFunction, this)); - var windowRenameTpl = - '
' + - '
' + - '' + - '
' + - '
'; + this.listFunctions = new Common.UI.ListView({ + el: $('#list-functions', 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:click', _.bind(this.onClickListFunctionItem, this)); + this.listFunctions.on('item:contextmenu', _.bind(this.onContextMenuListFunctionItem, this)); + this.listFunctions.on('item:select', _.bind(this.onSelectListFunctionItem, this)); + this.setListFunctions(); - this.windowRename = new Common.UI.Window({ - id: 'macros-rename-dialog', - header: false, - width: 300, - height: 90, - cls: 'modal-dlg', - tpl: windowRenameTpl, - buttons: ['ok', 'cancel'] - }).on('render:after', _.bind(this.onRenderWindowRename, this)); + this.ctxMenuFunction = new Common.UI.Menu({ + cls: 'shifted-right', + items: [ + new Common.UI.MenuItem({ + caption : this.textRename, + checkable : false + }).on('click', _.bind(this.onRenameFunction, this)), + new Common.UI.MenuItem({ + caption : this.textDelete, + checkable : false + }).on('click', _.bind(this.onDeleteFunction, this)), + new Common.UI.MenuItem({ + caption : this.textCopy, + checkable : false + }).on('click', _.bind(this.onCopyFunction, this)), + ] + }); + } - this.createCodeEditor(); + this.makeDragable(); }, - createCodeEditor: function() { var me = this; - function on_init_server(type){ + function onInitServer(type){ if (type === (window.initCounter & type)) return; window.initCounter |= type; - if (window.initCounter === 3) - { - // this.load_library("onlyoffice", "./libs/" + 'de' + "/api.js"); + if (window.initCounter === 3) { + var nameDocEditor = 'word'; + if(!!window.SSE) nameDocEditor = 'cell'; + else if(!!window.PE) nameDocEditor = 'slide'; + loadLibrary("onlyoffice", "../../../vendor/ace/libs/" + nameDocEditor + "/api.js"); } } - function load_library(name, url) { + function loadLibrary(name, url) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onreadystatechange = function() @@ -247,7 +287,7 @@ define([ { var EditSession = ace.require("ace/edit_session").EditSession; var editDoc = new EditSession(xhr.responseText, "ace/mode/javascript"); - this.codeEditor.ternServer.addDoc(name, editDoc); + me.codeEditor.ternServer.addDoc(name, editDoc); } }; xhr.send(); @@ -262,10 +302,13 @@ define([ this.codeEditor.getSession().setWrapLimitRange(null, null); this.codeEditor.setShowPrintMargin(false); this.codeEditor.$blockScrolling = Infinity; + this.codeEditor.setTheme(Common.UI.Themes.isDarkTheme() ? "ace/theme/vs-dark" : "ace/theme/vs-light"); - on_init_server(2); + onInitServer(2); ace.config.loadModule('ace/ext/tern', function () { + me._state.aceLoadedModules.tern = true; + me.onAceLoadModule(); me.codeEditor.setOptions({ enableTern: { defs: ['browser', 'ecma5'], @@ -273,24 +316,29 @@ define([ useWorker: !!window.Worker, switchToDoc: function (name, start) {}, startedCb: function () { - on_init_server(1); + onInitServer(1); }, }, - enableSnippets: false + enableSnippets: false, + tooltipContainer: '#code-editor' }); }); - // if (!window.isIE) { - // ace.config.loadModule('ace/ext/language_tools', function () { - // me.codeEditor.setOptions({ - // enableBasicAutocompletion: false, - // enableLiveAutocompletion: true - // }); - // }); - // } + if (!window.isIE) { + me._state.aceLoadedModules.langTools = true; + me.onAceLoadModule(); + ace.config.loadModule('ace/ext/language_tools', function () { + me.codeEditor.setOptions({ + enableBasicAutocompletion: false, + enableLiveAutocompletion: true + }); + }); + } ace.config.loadModule('ace/ext/html_beautify', function (beautify) { + me._state.aceLoadedModules.htmlBeautify = true; + me.onAceLoadModule(); me.codeEditor.setOptions({ autoBeautify: true, htmlBeautify: true, @@ -299,65 +347,99 @@ define([ }); this.codeEditor.getSession().on('change', function() { - // let obj = (CurrentElementModeType.Macros === CurrentElementMode) ? Content : CustomFunctions; - // - // if (obj.current == -1 || window.isDisable) - // return; - - // obj.macrosArray[obj.current].value = editor.getValue(); - console.log(me.codeEditor); + var selectedItem = me._state.currentElementMode === me.CurrentElementModeType.Macros + ? me.listMacros.getSelectedRec() + : me.listFunctions.getSelectedRec(); + if(!selectedItem || me._state.isDisable) { + return; + } + selectedItem.set('value', me.codeEditor.getValue()); }); }, setListMacros: function() { - function parseData(data) { - var result; - if (data) { - try { - result = JSON.parse(data); - } catch (err) { - result = { - macrosArray: [], - current: -1 - }; - } - } - return result; - } - - // TODO: Добавить VBAMacros - var data = parseData(this.api.pluginMethod_GetMacros()); + var me = this; + var data = this.parseDataFromApi(this.api.pluginMethod_GetMacros()); var macrosList = data.macrosArray; - macrosList.forEach(function (macros) { - macros.autostart = false; - }); - this.listMacros.store.reset(macrosList); - var selectItem = this.listMacros.store.at(data.current); - selectItem && this.listMacros.selectRecord(selectItem); - }, - openContextMenuMacros: function(macrosItem, event) { - // TODO: Чтобы меню открывалось либо около курсора, либо около кнопки. - if (this._state.macrosItemMenuOpen === macrosItem && this.ctxMenuMacros.isVisible()) { - this.ctxMenuMacros.hide(); - return; + 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 + '*/', + }); + } + }); } - this._state.macrosItemMenuOpen = macrosItem; - var menu = this.ctxMenuMacros, - currentTarget = $(event.currentTarget), - parent = $('#menu_macros'); + if(macrosList.length > 0) { + macrosList.forEach(function (macros) { + macros.autostart = macros.autostart ?? false; + }); + 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); + }, + openContextMenu: function(elementMode, item, event) { + var itemMenuOpen, ctxMenu, modeName; + if(elementMode === this.CurrentElementModeType.Macros) { + itemMenuOpen = this._state.macrosItemMenuOpen; + ctxMenu = this.ctxMenuMacros; + modeName = 'macros'; + } else if(elementMode === this.CurrentElementModeType.CustomFunction){ + itemMenuOpen = this._state.functionItemMenuOpen; + ctxMenu = this.ctxMenuFunction; + modeName = 'functions'; + } else { + return false; + } - var menuContainer = parent.find('#macros-dialog-fields-container'); - if (!menu.rendered) { + if (itemMenuOpen === item && ctxMenu.isVisible()) { + ctxMenu.hide(); + return false; + } + + var currentTarget = $(event.currentTarget), + parent = elementMode === this.CurrentElementModeType.Macros ? $('#menu_macros') : $('#menu_functions'), + containerId = 'macros-dialog-ctx-' + modeName + '-container', + menuContainer = parent.find('#' + containerId); + + if (!ctxMenu.rendered) { if (menuContainer.length < 1) { - menuContainer = $('
', menu.id); + menuContainer = $('
', ctxMenu.id); parent.append(menuContainer); } - menu.render(menuContainer); - menu.cmpEl.attr({tabindex: "-1"}); + ctxMenu.render(menuContainer); + ctxMenu.cmpEl.attr({tabindex: "-1"}); - menu.on('show:after', function(cmp) { + ctxMenu.on('show:after', function(cmp) { if (cmp && cmp.menuAlignEl) cmp.menuAlignEl.toggleClass('over', true); }).on('hide:after', function(cmp) { @@ -366,22 +448,102 @@ define([ }); } - if(macrosItem.get('autostart')) { - menu.items[1].setVisible(false); - menu.items[2].setVisible(true); - } else { - menu.items[1].setVisible(true); - menu.items[2].setVisible(false); - } + var menuContainerRect = menuContainer[0].getBoundingClientRect(); - menu.menuAlignEl = currentTarget; - menu.setOffset(15, -currentTarget.height()/2 - 3); - menu.show(); + ctxMenu.menuAlignEl = currentTarget; + ctxMenu.setOffset(event.clientX - menuContainerRect.x, -currentTarget.height()/2 - 3); + ctxMenu.show(); _.delay(function() { - menu.cmpEl.focus(); + ctxMenu.cmpEl.focus(); }, 10); event.stopPropagation(); event.preventDefault(); + + return true; + }, + openContextMenuMacros: function(macrosItem, event) { + var isOpen = this.openContextMenu(this.CurrentElementModeType.Macros, macrosItem, event); + if(isOpen) { + this._state.macrosItemMenuOpen = macrosItem; + if(macrosItem.get('autostart')) { + this.ctxMenuMacros.items[1].setVisible(false); + this.ctxMenuMacros.items[2].setVisible(true); + } else { + this.ctxMenuMacros.items[1].setVisible(true); + this.ctxMenuMacros.items[2].setVisible(false); + } + } + }, + openContextMenuFunction: function(functionItem, event) { + var isOpen = this.openContextMenu(this.CurrentElementModeType.CustomFunction, functionItem, event); + if(isOpen) { + this._state.functionItemMenuOpen = functionItem; + } + }, + openWindowRename: function() { + var windowSize = { + width: 300, + height: 90 + }; + var windowRenameTpl = + '
' + + '
' + + '
'; + + var window = new Common.UI.Window({ + id: 'macros-rename-dialog', + header: false, + width: windowSize.width, + height: windowSize.height, + cls: 'modal-dlg', + tpl: windowRenameTpl, + buttons: ['ok', 'cancel'] + }).on('render:after', _.bind(onRender, this)); + + var macrosWindowRect = this.$window[0].getBoundingClientRect(); + window.show( + macrosWindowRect.left + (macrosWindowRect.width - windowSize.width) / 2, + macrosWindowRect.top + (macrosWindowRect.height - windowSize.height) / 2 + ); + + function onRender(windowView) { + function inputValidation(value) { + return value.trim().length > 0; + } + + var me = this; + var selectedItem = me._state.currentElementMode === me.CurrentElementModeType.Macros + ? me.listMacros.getSelectedRec() + : me.listFunctions.getSelectedRec(); + var input = new Common.UI.InputField({ + el: $('#macros-rename-field'), + allowBlank: true, + validation: inputValidation, + validateOnBlur: false, + style: 'width: 100%;', + type: 'text', + value: selectedItem.get('name'), + dataHint: '1', + dataHintDirection: 'left', + dataHintOffset: 'small' + }); + input.$el.find('input').select(); + + var buttons = $(windowView.$window[0]).find('.btn'); + buttons.on('click', function (e){ + var type = $(e.target).attr('result'); + if(type == 'ok') { + if(input.checkValidate() === true) { + if(selectedItem) { + selectedItem.set('name', input.getValue().trim()); + } + windowView.close(); + } + } else { + windowView.close(); + } + }); + }; }, makeDragable: function() { @@ -393,36 +555,31 @@ define([ var macrosList = document.getElementById("list-macros"); var functionList = document.getElementById("menu_functions"); - macrosList.addEventListener('dragstart', function(evt) { - var id = $(evt.target).children('.list-item').attr('id'); - evt.dataTransfer.setData("text", id); - evt.dataTransfer.effectAllowed = "move"; - activeElement = evt.target; - evt.target.classList.add('dragged'); - indActive = me.listMacros.store.indexOf(me.listMacros.store.findWhere({ id: id })); - evt.target.click(); - }); + function getNextElement(cursorPosition, currentElement) { + // cursorPosition = cursorPosition * ((1 + (1 - zoom)).toFixed(1)); + const currentElementCoord = currentElement.getBoundingClientRect(); + const currentElementCenter = currentElementCoord.y + currentElementCoord.height * 0.45; + return (cursorPosition < currentElementCenter) ? currentElement : currentElement.nextElementSibling; + } - functionList.addEventListener('dragstart', function(evt) { - window.CustomContextMenu.hide(); - evt.dataTransfer.setData("text", evt.target.id); - evt.dataTransfer.effectAllowed = "move"; - activeElement = evt.target; - evt.target.classList.add('dragged'); - indActive = CustomFunctions.macrosArray.findIndex(function(el) { - return (el.name == evt.target.innerText) - }) - evt.target.onclick(); - }); + function handleDragstart(list, e) { + var id = $(e.target).children('.list-item').attr('id'); + e.dataTransfer.setData("text/plain", id); + e.dataTransfer.effectAllowed = "move"; + activeElement = e.target; + e.target.classList.add('dragged'); + indActive = list.store.indexOf(list.store.findWhere({ id: id })); + e.target.click(); + } - macrosList.addEventListener('dragend', function(evt) { - evt.target.classList.remove('dragged'); + function handleDragend(list, e) { + e.target.classList.remove('dragged'); $('.dragHovered').removeClass("dragHovered"); - if (currentElement === activeElement) + if (currentElement === activeElement || !nextElement) return; - var indNext = me.listMacros.store.indexOf(me.listMacros.store.findWhere({ + var indNext = list.store.indexOf(list.store.findWhere({ id: $(nextElement).children('.list-item').attr('id') })); if (indNext === -1) @@ -431,84 +588,97 @@ define([ if (indActive < indNext) indNext--; - var newStoreArr = me.listMacros.store.models.slice(); + var newStoreArr = list.store.models.slice(); let tmp = newStoreArr.splice(indActive, 1)[0]; newStoreArr.splice(indNext, 0, tmp); - me.listMacros.store.reset(newStoreArr); + list.store.reset(newStoreArr); indActive = 0; - }); + } - functionList.addEventListener('dragend', function(evt) { - evt.target.classList.remove('dragged'); - $('.dragHovered').removeClass("dragHovered"); - - if (currentElement === activeElement) - return; - - try { - functionList.insertBefore(activeElement, nextElement); - } catch (err) { - return; - } - let indNext = CustomFunctions.macrosArray.findIndex(function(el) { - return (nextElement && el.name == nextElement.innerText) - }) - if (indNext === -1) - indNext = CustomFunctions.macrosArray.length; - - if (indActive < indNext) - indNext--; - - let tmp = CustomFunctions.macrosArray.splice(indActive, 1)[0]; - CustomFunctions.macrosArray.splice(indNext, 0, tmp); - CustomFunctions.current = indNext; - indActive = 0; - updateFunctionsMenu(); - }); - - function getNextElement(cursorPosition, currentElement) { - // cursorPosition = cursorPosition * ((1 + (1 - zoom)).toFixed(1)); - const currentElementCoord = currentElement.getBoundingClientRect(); - const currentElementCenter = currentElementCoord.y + currentElementCoord.height * 0.45; - const nextElement = (cursorPosition < currentElementCenter) ? currentElement : currentElement.nextElementSibling; - return nextElement; - }; - - macrosList.addEventListener('dragover', function(evt) { - currentElement = evt.target; - let bDragAllowed = true || !!((CurrentElementModeType.Macros === CurrentElementMode) && currentElement.id.includes('mac')); - evt.preventDefault(); - evt.dataTransfer.dropEffect = bDragAllowed ? "move" : "none"; + function handleDragover(list, elementModeType, e) { + e.preventDefault(); + currentElement = e.target; + let bDragAllowed = me._state.currentElementMode === elementModeType; + e.dataTransfer.dropEffect = bDragAllowed ? "move" : "none"; const isMoveable = currentElement.classList.contains('draggable'); - if (!isMoveable) + if (!isMoveable || !bDragAllowed) return; - nextElement = getNextElement(evt.clientY, currentElement); + nextElement = getNextElement(e.clientY, currentElement); + console.log(nextElement); $('.dragHovered').removeClass("dragHovered") if (nextElement) { if($(nextElement).attr('role') == 'listitem') { - $(macrosList).find('.item').last().removeClass(['dragHovered', 'last']); + $(list).find('.item').last().removeClass(['dragHovered', 'last']); nextElement.classList.add('dragHovered'); } else { - $(macrosList).find('.item').last().addClass(['dragHovered', 'last']); + $(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"); + nextElement = null; + } + } + + + macrosList.addEventListener('dragstart', function(e) { + handleDragstart(me.listMacros, e); + }); + functionList.addEventListener('dragstart', function(e) { + handleDragstart(me.listFunctions, e); }); - functionList.addEventListener('dragover', function(evt) { - currentElement = evt.target; - let bDragAllowed = false && !!((CurrentElementModeType.CustomFunction === CurrentElementMode) && currentElement.id.includes('function')); - evt.preventDefault(); - evt.dataTransfer.dropEffect = bDragAllowed ? "move" : "none"; - const isMoveable = currentElement.classList.contains('draggable'); - if (!isMoveable) - return; - - nextElement = getNextElement(evt.clientY, currentElement); - $('.dragHovered').removeClass("dragHovered") - if (nextElement) - nextElement.classList.add('dragHovered'); + 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.CurrentElementModeType.Macros, e) + }); + functionList.addEventListener('dragover', function(e) { + handleDragover(functionList, me.CurrentElementModeType.CustomFunction, e) + }); + + macrosList.addEventListener('dragleave', function(e) { + handleDragleave(e); + }); + functionList.addEventListener('dragleave', function(e) { + handleDragleave(e); + }); + }, + + 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() { @@ -536,50 +706,59 @@ define([ return { guid: item.get('guid'), name: item.get('name'), - value: item.get('value'), + autostart: item.get('autostart'), + value: item.get('value') } }), - // TODO: Изменить на выбранный элемент - current: -1 + 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'); + }, onCreateMacros: function() { var indexMax = 0; - var macrosTranslate = this.textMacros; + var macrosTextEn = 'Macros'; + var macrosTextTranslate = this.textMacros; this.listMacros.store.each(function(macros, index) { var macrosName = macros.get('name'); - if (0 == macrosName.indexOf("Macros")) + if (0 == macrosName.indexOf(macrosTextEn)) { - var index = parseInt(macrosName.substr(6)); + var index = parseInt(macrosName.substr(macrosTextEn.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } - else if (0 == macrosName.indexOf(macrosTranslate)) + else if (0 == macrosName.indexOf(macrosTextTranslate)) { - var index = parseInt(macrosName.substr(macrosTranslate.length)); + var index = parseInt(macrosName.substr(macrosTextTranslate.length)); if (!isNaN(index) && (indexMax < index)) indexMax = index; } }); indexMax++; this.listMacros.store.add({ - name : (macrosTranslate + " " + indexMax), + guid: this.createGuid(), + name : (macrosTextTranslate + " " + indexMax), value : "(function()\n{\n})();", autostart: false }); this.listMacros.selectRecord(this.listMacros.store.at(-1)); - - // TODO:СДЕЛАЙ ЭТО!!! - // CurrentElementMode = CurrentElementModeType.Macros; - // editor.focus(); - }, - onAddListMacrosItem: function(listView, itemView) { - itemView.$el.attr('draggable', true); - itemView.$el.addClass('draggable'); }, onClickListMacrosItem: function(listView, itemView, record) { var event = window.event ? window.event : window._event; @@ -597,6 +776,20 @@ define([ me.openContextMenuMacros(record, event); }, 10); }, + onSelectListMacrosItem: function(listView, itemView, record) { + this._state.currentElementMode = this.CurrentElementModeType.Macros; + this._state.isDisable = true; + this.codeEditor.setValue(record.get('value')); + this.codeEditor.setReadOnly(false); + this._state.isDisable = false; + + // TODO: Блокировать кнопку Run, если выбран элемент customFunction + this.codeEditor.focus(); + this.codeEditor.selection.clearSelection(); + this.codeEditor.scrollToRow(0); + + this.listFunctions && this.listFunctions.deselectAll(); + }, onRunMacros: function() { console.log('Run'); }, @@ -610,48 +803,119 @@ define([ this._state.macrosItemMenuOpen.set('autostart', false); }, + onRenameMacros: function() { if(!this._state.macrosItemMenuOpen) return; - this.windowRename.show(); + this.openWindowRename(); }, - onDeleteMacros: function() { - if(!this._state.macrosItemMenuOpen) return; + onRenameFunction: function() { + if(!this._state.functionItemMenuOpen) return; - var deletedIndex = this.listMacros.store.indexOf(this._state.macrosItemMenuOpen); - this.listMacros.store.remove(this._state.macrosItemMenuOpen); - if(this.listMacros.store.length > 0) { - var selectedIndex = deletedIndex < this.listMacros.store.length + this.openWindowRename(); + }, + + onDeleteItem: function(list, item) { + if(!item) return; + + var deletedIndex = list.store.indexOf(item); + list.store.remove(item); + if(list.store.length > 0) { + var selectedIndex = deletedIndex < list.store.length ? deletedIndex - : this.listMacros.store.length - 1; - this.listMacros.selectByIndex(selectedIndex); + : list.store.length - 1; + list.selectByIndex(selectedIndex); + } else { + this.codeEditor.setValue(''); + this.codeEditor.setReadOnly(true); } }, - onCopyMacros: function() { - if(!this._state.macrosItemMenuOpen) return; - - this.listMacros.store.add({ - name: this._state.macrosItemMenuOpen.get('name') + '_copy', - value: this._state.macrosItemMenuOpen.get('value'), - autostart: this._state.macrosItemMenuOpen.get('autostart') - }); - this.listMacros.selectRecord(this.listMacros.store.at(-1)); + onDeleteMacros: function() { + this.onDeleteItem(this.listMacros, this._state.macrosItemMenuOpen); }, - onRenderWindowRename: function(windowView) { - var buttons = $(windowView.$window[0]).find('.btn'); - buttons.on('click', (e) => { - var type = $(e.target).attr('result'); - console.log(type); - windowView.hide(); + onDeleteFunction: function() { + this.onDeleteItem(this.listFunctions, this._state.functionItemMenuOpen); + }, + + onCopyItem: function(list, item) { + 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)); + }, + onCopyMacros: function() { + this.onCopyItem(this.listMacros, this._state.macrosItemMenuOpen); + }, + onCopyFunction: function() { + this.onCopyItem(this.listFunctions, this._state.functionItemMenuOpen); + }, + + + 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 return arg;\n\t}\n\tApi.AddCustomFunction(myFunction);\n})();", + autostart: false + }); + this.listFunctions.selectRecord(this.listFunctions.store.at(-1)); + }, + onClickListFunctionItem: function(listView, itemView, record) { + var event = window.event ? window.event : window._event; + if(!event) return; + + var btn = $(event.target); + if (btn && btn.hasClass('listitem-icon')) { + this.openContextMenuFunction(record, event); + } + }, + onContextMenuListFunctionItem: function(listView, itemView, record, event) { + var me = this; + this.listFunctions.selectRecord(record); + _.delay(function() { + me.openContextMenuFunction(record, event); + }, 10); + }, + onSelectListFunctionItem: function(listView, itemView, record) { + this._state.currentElementMode = this.CurrentElementModeType.CustomFunction; + this._state.isDisable = true; + this.codeEditor.setValue(record.get('value')); + this.codeEditor.setReadOnly(false); + this._state.isDisable = false; + + // TODO: Блокировать кнопку Run, если выбран элемент customFunction + this.codeEditor.focus(); + this.codeEditor.selection.clearSelection(); + this.codeEditor.scrollToRow(0); + + this.listMacros && this.listMacros.deselectAll(); }, onHelp: function() { window.open('https://api.onlyoffice.com/plugin/macros', '_blank') }, - onClose: function() { - console.log('Close'); - }, onBtnClick: function(event) { this._handleInput(event.currentTarget.attributes['result'].value); }, @@ -670,6 +934,8 @@ define([ textRename : 'Rename', textDelete : 'Delete', textCopy : 'Copy', + textCustomFunction : 'Custom function', + textLoading : 'Loading...', tipMacrosRun : 'Run', tipMacrosAdd : 'Add macros', tipFunctionAdd : 'Add custom function', diff --git a/apps/common/main/resources/less/macros-dialog.less b/apps/common/main/resources/less/macros-dialog.less index bb06a3ca38..de7ad97bcd 100644 --- a/apps/common/main/resources/less/macros-dialog.less +++ b/apps/common/main/resources/less/macros-dialog.less @@ -11,6 +11,8 @@ .content { display: flex; flex: 1; + height: calc(100% - 37px); // 37px - footer height + .common_menu { display: flex; flex-direction: column; @@ -18,10 +20,6 @@ width: 30%; overflow: hidden; - border-right-color: #CBCBCB; - border-right-style: solid; - border-right-width: 1px; - #menu_macros { height: 50%; padding: 5px; @@ -49,7 +47,7 @@ } } } - #list-macros { + #list-macros, #list-functions { height: calc(100% - 45px); .listview { @@ -113,6 +111,96 @@ #code-editor { width: 100%; flex: 1; + + .ace_content { + background: @background-normal; + color: @text-normal; + } + .ace_layer.ace_gutter-layer.ace_folding-enabled { + color: @text-normal; + } + .divHeader { + border-color: @border-divider; + } + .ace_scroller { + border-left: none; + } + .ace_cursor { + color: @text-normal; + } + .Ace-Tern-tooltip, .Ace-Tern-jsdoc-param-description { + color: @text-normal; + background-color: @background-toolbar; + } + + .ace-chrome .ace_marker-layer .ace_selected-word { + background: rgb(250, 250, 255, 0.3) !important; + border: 1px solid rgb(200, 200, 250); + } + .ace_active-line { + border-color: #333 !important; + } + .ace_active-line, .ace_gutter-active-line, .ace_gutter-active-line-bg { + border-bottom: 1px solid; + border-top: 1px solid; + border-color: @border-divider !important; + background: @background-normal; + } + .oo_highlight { + background-color: #555 !important; + } + .ace_line-hover { + background-color: #333 !important; border-color: #555 !important; + } + .ace_completion-highlight { + color: #4FC1FF !important; text-shadow: 0 0 0.01em; + } + .Ace-Tern-farg { + color: gray; + } + .Ace-Tern-farg-current { + color: gray; + } + .Ace-Tern-type { + color: #569CD6; + } + .Ace-Tern-jsdoc-param-name { + color: gray; + } + .ace_gutter, .gutter_bg { + background: @background-normal !important; + } + .Ace-Tern-jsdoc-tag { + color: #FF5E5C; + } + .Ace-Tern-farg-current-description { + color : #FFFFFF; + } + .Ace-Tern-farg-current-name { + color : white; + } + .Ace-Tern-tooltip { + font-size: 11px; + border-radius: 0; + border: none; + border-top: 1px solid var(--border-divider); + background: @background-toolbar; + color: @text-normal; + width: 100%; + max-width: 100%; + bottom: 0; + + .Ace-Tern-tooltip-boxclose { + color: @icon-normal !important; + opacity: 0.7; + + &:hover { + opacity: 1; + background: none; + text-decoration: none; + } + } + } } } } diff --git a/apps/documenteditor/main/index.html b/apps/documenteditor/main/index.html index d638d11941..2fd98dc21a 100644 --- a/apps/documenteditor/main/index.html +++ b/apps/documenteditor/main/index.html @@ -436,7 +436,6 @@ -