diff --git a/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js b/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js index 9cc423981..6163cc5fc 100644 --- a/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js +++ b/apps/spreadsheeteditor/main/app/controller/DocumentHolder.js @@ -258,7 +258,7 @@ define([ click: function(e) { if (me.api) { me.api.isTextAreaBlur = false; - if (e.target.localName == 'canvas' && !me.isEditFormula) { + if (e.target.localName == 'canvas' && (!me.isEditFormula || me.rangeSelectionMode)) { if (me._preventClick) me._preventClick = false; else @@ -1987,7 +1987,7 @@ define([ value : addarr ? addarr[index] : menuItem, style: (typeof menuItem == 'string' && _.isEmpty(menuItem.trim())) ? 'min-height: 25px;' : '' }).on('click', function(item, e) { - me.api.asc_insertFormula(item.value, Asc.c_oAscPopUpSelectorType.None, false ); + me.api.asc_insertInCell(item.value, Asc.c_oAscPopUpSelectorType.None, false ); }); menu.addItem(mnu); }); @@ -2032,7 +2032,7 @@ define([ }, onFormulaCompleteMenu: function(funcarr) { - if (!this.documentHolder.funcMenu) return; + if (!this.documentHolder.funcMenu || Common.Utils.ModalWindow.isVisible() || this.rangeSelectionMode) return; if (funcarr) { var me = this, @@ -2064,7 +2064,7 @@ define([ caption: name, hint : (funcdesc && funcdesc[origname]) ? funcdesc[origname].d : '' }).on('click', function(item, e) { - setTimeout(function(){ me.api.asc_insertFormula(item.caption, type, false ); }, 10); + setTimeout(function(){ me.api.asc_insertInCell(item.caption, type, false ); }, 10); }); menu.addItem(mnu); }); diff --git a/apps/spreadsheeteditor/main/app/controller/FormulaDialog.js b/apps/spreadsheeteditor/main/app/controller/FormulaDialog.js index 45a977803..25cb50b7c 100644 --- a/apps/spreadsheeteditor/main/app/controller/FormulaDialog.js +++ b/apps/spreadsheeteditor/main/app/controller/FormulaDialog.js @@ -44,7 +44,8 @@ define([ 'core', 'spreadsheeteditor/main/app/collection/FormulaGroups', 'spreadsheeteditor/main/app/view/FormulaDialog', - 'spreadsheeteditor/main/app/view/FormulaTab' + 'spreadsheeteditor/main/app/view/FormulaTab', + 'spreadsheeteditor/main/app/view/FormulaWizard' ], function () { 'use strict'; @@ -95,7 +96,10 @@ define([ if (func.origin === 'more') { this.showDialog(group); } else { - this.api.asc_insertFormula(func.name, Asc.c_oAscPopUpSelectorType.Func, !!autocomplete); + if (autocomplete) + this.api.asc_insertInCell(func.name, Asc.c_oAscPopUpSelectorType.Func, !!autocomplete); + else + this.api.asc_startWizard(func.name); !autocomplete && this.updateLast10Formulas(func.origin); } } @@ -112,6 +116,7 @@ define([ setApi: function (api) { this.api = api; + this.api.asc_registerCallback('asc_onSendFunctionWizardInfo', _.bind(this.onSendFunctionWizardInfo, this)); if (this.formulasGroups && this.api) { Common.Utils.InternalSettings.set("sse-settings-func-last", Common.localStorage.getItem("sse-settings-func-last")); @@ -216,9 +221,39 @@ define([ this.formulas.fillFormulasGroups(); } } - this.formulas.show(group); + this._formulagroup = group; + this.api.asc_startWizard(); } }, + + onSendFunctionWizardInfo: function(props) { + if (props) { + // show formula settings + var me = this; + var name = props.asc_getName(), + descrarr = this.getDescription(Common.Utils.InternalSettings.get("sse-settings-func-locale")), + funcprops = { + name: this.api.asc_getFormulaLocaleName(name), + origin: name, + args: ((descrarr && descrarr[name]) ? descrarr[name].a : '').replace(/[,;]/g, this.api.asc_getFunctionArgumentSeparator()), + desc: (descrarr && descrarr[name]) ? descrarr[name].d : '' + }; + + (new SSE.Views.FormulaWizard({ + api : this.api, + lang : this.appOptions.lang, + funcprops: funcprops, + props : props, + handler : function(dlg, result, settings) { + if (result == 'ok') { + } + } + })).show(); + } else + this.formulas.show(this._formulagroup); + this._formulagroup = undefined; + }, + hideDialog: function () { if (this.formulas && this.formulas.isVisible()) { this.formulas.hide(); diff --git a/apps/spreadsheeteditor/main/app/controller/Toolbar.js b/apps/spreadsheeteditor/main/app/controller/Toolbar.js index b9dc6e1dc..eaf086b4f 100644 --- a/apps/spreadsheeteditor/main/app/controller/Toolbar.js +++ b/apps/spreadsheeteditor/main/app/controller/Toolbar.js @@ -1237,7 +1237,7 @@ define([ (new SSE.Views.NamedRangePasteDlg({ handler: function(result, settings) { if (result == 'ok' && settings) { - me.api.asc_insertFormula(settings.asc_getName(true), settings.asc_getIsTable() ? Asc.c_oAscPopUpSelectorType.Table : Asc.c_oAscPopUpSelectorType.Range, false); + me.api.asc_insertInCell(settings.asc_getName(true), settings.asc_getIsTable() ? Asc.c_oAscPopUpSelectorType.Table : Asc.c_oAscPopUpSelectorType.Range, false); Common.component.Analytics.trackEvent('ToolBar', 'Paste Named Range'); } Common.NotificationCenter.trigger('edit:complete', me.toolbar); diff --git a/apps/spreadsheeteditor/main/app/view/CellRangeDialog.js b/apps/spreadsheeteditor/main/app/view/CellRangeDialog.js index 19c89d13b..de07e7116 100644 --- a/apps/spreadsheeteditor/main/app/view/CellRangeDialog.js +++ b/apps/spreadsheeteditor/main/app/view/CellRangeDialog.js @@ -81,7 +81,7 @@ define([ el : $('#id-dlg-cell-range'), name : 'range', style : 'width: 100%;', - allowBlank : false, + allowBlank : this.options.allowBlank || false, blankError : this.txtEmpty, validateOnChange: true }); @@ -103,6 +103,7 @@ define([ setSettings: function(settings) { var me = this; + this.settings = settings; this.inputRange.setValue(settings.range ? settings.range : ''); if (settings.type===undefined) @@ -121,18 +122,52 @@ define([ if (settings.validation) { return settings.validation.call(me, value); } else { - var isvalid = me.api.asc_checkDataRange(settings.type, value, false); + if (settings.type === Asc.c_oAscSelectionDialogType.Function) { + settings.argvalues[settings.argindex] = value; + me.api.asc_insertArgumentsInFormula(settings.argvalues); + } + var isvalid = (settings.type === Asc.c_oAscSelectionDialogType.Function) || me.api.asc_checkDataRange(settings.type, value, false); return (isvalid==Asc.c_oAscError.ID.DataRangeError) ? me.txtInvalidRange : true; } }; + + if (settings.type == Asc.c_oAscSelectionDialogType.Function) { + _.delay(function(){ + me.inputRange._input.focus(); + if (settings.selection) { + me.inputRange._input[0].selectionStart = settings.selection.start; + me.inputRange._input[0].selectionEnd = settings.selection.end; + } + },10); + me.inputRange._input.on('focus', function() { + me._addedTextLength=0; + me.api.asc_cleanSelectRange(); + }); + } }, getSettings: function () { return this.inputRange.getValue(); }, - onApiRangeChanged: function(info) { - this.inputRange.setValue(info.asc_getName()); + onApiRangeChanged: function(name) { + if (this.settings.type == Asc.c_oAscSelectionDialogType.Function) { + var oldlen = this._addedTextLength || 0, + val = this.inputRange.getValue(), + input = this.inputRange._input[0], + start = input.selectionStart - oldlen, + end = input.selectionEnd, + add = (start>0 && oldlen==0) && !this.api.asc_canEnterWizardRange(val.charAt(start-1)) ? '+' : ''; + this._addedTextLength = name.length; + + val = val.substring(0, start) + add + name + val.substring(end, val.length); + this.inputRange.setValue(val); + input.selectionStart = input.selectionEnd = start + add.length + this._addedTextLength; + + this.settings.argvalues[this.settings.argindex] = val; + this.api.asc_insertArgumentsInFormula(this.settings.argvalues); + } else + this.inputRange.setValue(name); if (this.inputRange.cmpEl.hasClass('error')) this.inputRange.cmpEl.removeClass('error'); }, diff --git a/apps/spreadsheeteditor/main/app/view/FormulaDialog.js b/apps/spreadsheeteditor/main/app/view/FormulaDialog.js index adeb12697..611c44c4b 100644 --- a/apps/spreadsheeteditor/main/app/view/FormulaDialog.js +++ b/apps/spreadsheeteditor/main/app/view/FormulaDialog.js @@ -153,6 +153,7 @@ define([ me.inputSearch.$el.find('input').focus(); }, 100, this); } + this._preventCloseCellEditor = false; }, hide: function () { @@ -166,6 +167,8 @@ define([ this.recommended = this.filter = undefined; Common.UI.Window.prototype.hide.call(this); + + !this._preventCloseCellEditor && this.api.asc_closeCellEditor(true); }, onBtnClick: function (event) { @@ -198,6 +201,7 @@ define([ if (this.handler && state == 'ok') { if (this.btnOk.isDisabled()) return; + this._preventCloseCellEditor = true; this.handler.call(this, this.applyFunction); } diff --git a/apps/spreadsheeteditor/main/app/view/FormulaWizard.js b/apps/spreadsheeteditor/main/app/view/FormulaWizard.js new file mode 100644 index 000000000..068b8ef96 --- /dev/null +++ b/apps/spreadsheeteditor/main/app/view/FormulaWizard.js @@ -0,0 +1,435 @@ +/* + * + * (c) Copyright Ascensio System SIA 2010-2020 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ +/** + * FormulaWizard.js + * + * Created by Julia Radzhabova on 17.04.20 + * Copyright (c) 2020 Ascensio System SIA. All rights reserved. + * + */ + +define([ + 'common/main/lib/view/AdvancedSettingsWindow', + 'common/main/lib/component/MetricSpinner' +], function () { 'use strict'; + + SSE.Views.FormulaWizard = Common.Views.AdvancedSettingsWindow.extend(_.extend({ + options: { + contentWidth: 580, + height: 397 + }, + + initialize : function(options) { + var me = this; + _.extend(this.options, { + title: this.textTitle, + template: [ + '
', + '
', + '
', + '', + '', + '', + '', + '
', + '', + '
', + '
', + '', + '
', + '
', + '
', + '', + '
', + '
', + '
', + '
', + '
', + // '', + '', + '', + '', + '', + '
', + '
', + '
', + '
', + '
', + '
' + ].join('') + }, options); + + this.props = this.options.props; + this.funcprops = this.options.funcprops; + this.api = this.options.api; + this.lang = this.options.lang; + + this._noApply = false; + this.args = []; + this.repeatedArg = undefined; + this.helpUrl = undefined; + this.minArgCount = 1; + this.maxArgCount = 1; + this.minArgWidth = 50; + + Common.Views.AdvancedSettingsWindow.prototype.initialize.call(this, this.options); + }, + + render: function() { + Common.Views.AdvancedSettingsWindow.prototype.render.call(this); + + var $window = this.getChild(); + $window.find('input').on('keypress', _.bind(this.onKeyPress, this)); + + this.contentPanel = $window.find('.content-panel'); + this.innerPanel = $window.find('.inner-content'); + + this.panelArgs = $window.find('#formula-wizard-panel-args'); + this.tableArgs = $window.find('#formula-wizard-tbl-args'); + this.panelDesc = $window.find('#formula-wizard-panel-desc'); + this.lblArgDesc = $window.find('#formula-wizard-arg-desc'); + this.lblFormulaResult = $window.find('#formula-wizard-value'); + this.lblFunctionResult = $window.find('#formula-wizard-lbl-val-func'); + + this._preventCloseCellEditor = false; + + this.afterRender(); + }, + + afterRender: function() { + this._setDefaults(); + }, + + _handleInput: function(state) { + if (this.options.handler) + this.options.handler.call(this, state, (state == 'ok') ? this.getSettings() : undefined); + this._preventCloseCellEditor = (state == 'ok'); + this.close(); + }, + + onDlgBtnClick: function(event) { + this._handleInput(event.currentTarget.attributes['result'].value); + }, + + onKeyPress: function(event) { + if (event.keyCode == Common.UI.Keys.RETURN) { + this._handleInput('ok'); + } + }, + + onPrimary: function() { + this._handleInput('ok'); + return false; + }, + + _setDefaults: function () { + var me = this; + if (this.funcprops) { + var props = this.funcprops; + props.args ? $('#formula-wizard-args').html('' + props.name + '' + props.args) : $('#formula-wizard-args').addClass('hidden'); + props.desc ? $('#formula-wizard-desc').text(props.desc) : $('#formula-wizard-desc').addClass('hidden'); + props.name ? $('#formula-wizard-name').html(this.textFunction + ': ' + props.name) : $('#formula-wizard-name').addClass('hidden'); + + this.$window.find('#formula-wizard-help').on('click', function (e) { + me.showHelp(); + }) + } + this.recalcArgTableSize(); + this.minArgWidth = this.$window.find('#formula-wizard-lbl-func-res').width(); + + if (this.props) { + // fill arguments + var props = this.props; + this.minArgCount = props.asc_getArgumentMin(); + this.maxArgCount = props.asc_getArgumentMax(); + + var result = props.asc_getFunctionResult(); + this.lblFunctionResult.html('= ' + ((result!==undefined && result!==null) ? result : '')); + result = props.asc_getFormulaResult(); + this.lblFormulaResult.html('' + this.textValue + ': ' + ((result!==undefined && result!==null)? result : '')); + + var argres = props.asc_getArgumentsResult(), + argtype = props.asc_getArgumentsType(), + argval = props.asc_getArgumentsValue(); + + if (argtype) { + for (var i=0; i
' + + '
' + + '
', + div = $(Common.Utils.String.format(argtpl, argcount)); + this.tableArgs.append(div); + + var txt = new Common.UI.InputFieldBtn({ + el: div.find('#formula-wizard-txt-arg'+argcount), + index: argcount, + validateOnChange: true, + validateOnBlur: false + }).on('changed:after', function(input, newValue, oldValue, e) { + }).on('changing', function(input, newValue, oldValue, e) { + if (newValue == oldValue) return; + me.onInputChanging(input, newValue, oldValue); + }).on('button:click', _.bind(this.onSelectData, this)); + txt.setValue((argval!==undefined && argval!==null) ? argval : ''); + txt._input.on('focus', _.bind(this.onSelectArgument, this, txt)); + + me.args.push({ + index: argcount, + lblName: div.find('#formula-wizard-lbl-name-arg'+argcount), + lblValue: div.find('#formula-wizard-lbl-val-arg'+argcount), + argInput: txt, + argName: 'Argument ' + (argcount+1), + // argDesc: 'some argument description', + argType: argtype, + argTypeName: me.getArgType(argtype) + }); + if (argcount' + me.args[argcount].argName + ''); + else + me.args[argcount].lblName.html(me.args[argcount].argName); + me.args[argcount].lblValue.html('= '+ ( argres!==null && argres!==undefined ? argres : '' + me.args[argcount].argTypeName + '')); + }, + + onInputChanging: function(input, newValue, oldValue, e) { + var me = this, + index = input.options.index, + arg = me.args[index]; + var res = me.api.asc_insertArgumentsInFormula(me.getArgumentsValue(), index, arg.argType), + argres = res ? res.asc_getArgumentsResult() : undefined; + argres = argres ? argres[index] : undefined; + arg.lblValue.html('= '+ (argres!==null && argres !==undefined ? argres : '' + arg.argTypeName + '' )); + + var result = res ? res.asc_getFunctionResult() : undefined; + me.lblFunctionResult.html('= ' + ((result!==undefined && result!==null)? result : '')); + result = res ? res.asc_getFormulaResult() : undefined; + me.lblFormulaResult.html('' + me.textValue + ': ' + ((result!==undefined && result!==null)? result : '')); + }, + + getArgumentsValue: function() { + var res = [], + len = this.args.length, + empty = true; + for (var i=len-1; i>=0; i--) { + var val = this.args[i].argInput.getValue(); + empty && (empty = !val); + (!empty) && (res[i] = val); + } + return res; + }, + + getArgType: function(type) { + var str = ''; + switch (type) { + case Asc.c_oAscFormulaArgumentType.number: + str = 'number'; + break; + case Asc.c_oAscFormulaArgumentType.text: + str = 'text'; + break; + case Asc.c_oAscFormulaArgumentType.reference: + str = 'reference'; + break; + case Asc.c_oAscFormulaArgumentType.any: + str = 'any'; + break; + case Asc.c_oAscFormulaArgumentType.logical: + str = 'logical'; + break; + } + return str; + }, + + onSelectArgument: function(input) { + var index = input.options.index, + arg = this.args[index]; + arg.argDesc ? this.lblArgDesc.html('' + arg.argName + ': ' + arg.argDesc) : this.lblArgDesc.addClass('hidden'); + if (!this._noApply && index==this.args.length-1 && this.repeatedArg && index+this.repeatedArg.length