/* * * (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 * */ /** * ViewTab.js * * Created by Julia Svinareva on 22.02.2022 * Copyright (c) 2022 Ascensio System SIA. All rights reserved. * */ define([ 'core', 'common/main/lib/view/SearchPanel' ], function () { 'use strict'; SSE.Controllers.Search = Backbone.Controller.extend(_.extend({ sdkViewName : '#id_main', views: [ 'Common.Views.SearchPanel' ], initialize: function () { this.addListeners({ 'SearchBar': { 'search:back': _.bind(this.onSearchNext, this, 'back'), 'search:next': _.bind(this.onSearchNext, this, 'next'), 'search:input': _.bind(function (text, afterShow) { if (afterShow && !text) { if (this._state.isResults) { this._state.noSearchEmptyCells = true; this.onQuerySearch(); } return; } if (this._state.searchText === text) { Common.NotificationCenter.trigger('search:updateresults', this._state.currentResult, this._state.resultsNumber); return; } this.onInputSearchChange(text); }, this), 'search:keydown': _.bind(this.onSearchNext, this, 'keydown'), 'show': _.bind(this.onSelectSearchingResults, this, true), 'hide': _.bind(this.onSelectSearchingResults, this, false) }, 'Common.Views.SearchPanel': { 'search:back': _.bind(this.onSearchNext, this, 'back'), 'search:next': _.bind(this.onSearchNext, this, 'next'), 'search:replace': _.bind(this.onQueryReplace, this), 'search:replaceall': _.bind(this.onQueryReplaceAll, this), 'search:input': _.bind(this.onInputSearchChange, this), 'search:options': _.bind(this.onChangeSearchOption, this), 'search:keydown': _.bind(this.onSearchNext, this, 'keydown'), 'show': _.bind(this.onShowPanel, this), 'hide': _.bind(this.onHidePanel, this) }, 'LeftMenu': { 'search:aftershow': _.bind(this.onShowAfterSearch, this) } }); }, onLaunch: function () { this._state = { searchText: undefined, matchCase: false, matchWord: false, useRegExp: false, withinSheet: Asc.c_oAscSearchBy.Sheet, searchByRows: true, lookInFormulas: true, isValidSelectedRange: true, lastSelectedItem: undefined, isContentChanged: false, isResults: false, noSearchEmptyCells: false, isReturnPressed: false }; }, setMode: function (mode) { this.view = this.createView('Common.Views.SearchPanel', { mode: mode }); this.view.on('render:after', _.bind(this.onAfterRender, this)); }, setApi: function (api) { if (api) { this.api = api; this.api.asc_registerCallback('asc_onRenameCellTextEnd', _.bind(this.onRenameText, this)); this.api.asc_registerCallback('asc_onSetSearchCurrent', _.bind(this.onUpdateSearchCurrent, this)); this.api.asc_registerCallback('asc_onStartTextAroundSearch', _.bind(this.onStartTextAroundSearch, this)); this.api.asc_registerCallback('asc_onEndTextAroundSearch', _.bind(this.onEndTextAroundSearch, this)); this.api.asc_registerCallback('asc_onGetTextAroundSearchPack', _.bind(this.onApiGetTextAroundSearch, this)); this.api.asc_registerCallback('asc_onRemoveTextAroundSearch', _.bind(this.onApiRemoveTextAroundSearch, this)); this.api.asc_registerCallback('asc_onActiveSheetChanged', _.bind(this.onActiveSheetChanged, this)); this.api.asc_registerCallback('asc_onModifiedDocument', _.bind(this.onApiModifiedDocument, this)); this.api.asc_registerCallback('asc_onUpdateSearchElem', _.bind(this.onApiUpdateSearchElem, this)); } return this; }, getView: function(name) { return !name && this.view ? this.view : Backbone.Controller.prototype.getView.call(this, name); }, onAfterRender: function () { var me = this; this.view.inputSelectRange.validation = function(value) { if (_.isEmpty(value)) { return true; } var isvalid = me.api.asc_checkDataRange(undefined, value); me._state.isValidSelectedRange = isvalid !== Asc.c_oAscError.ID.DataRangeError; return (isvalid === Asc.c_oAscError.ID.DataRangeError) ? me.textInvalidRange : true; }; this.view.inputSelectRange.on('button:click', _.bind(this.onRangeSelect, this)); }, onChangeSearchOption: function (option, value, noSearch) { var runSearch = true; switch (option) { case 'case-sensitive': this._state.matchCase = value; break; case 'match-word': this._state.matchWord = value; break; case 'regexp': this._state.useRegExp = value; break; case 'within': this._state.withinSheet = value === 0 ? Asc.c_oAscSearchBy.Sheet : (value === 1 ? Asc.c_oAscSearchBy.Workbook : Asc.c_oAscSearchBy.Range); this.view.inputSelectRange.setDisabled(value !== Asc.c_oAscSearchBy.Range); if (value === Asc.c_oAscSearchBy.Range) { runSearch = this._state.isValidSelectedRange && !!this._state.selectedRange; } this.view.inputSelectRange.$el[value === Asc.c_oAscSearchBy.Range ? 'show' : 'hide'](); this.view.updateResultsContainerHeight(); break; case 'range': this._state.selectedRange = value; runSearch = !noSearch; break; case 'search': this._state.searchByRows = value; break; case 'lookIn': this._state.lookInFormulas = value; break; } if (runSearch) { this.onQuerySearch(); } }, onRangeSelect: function () { var me = this; var handlerDlg = function(dlg, result) { if (result == 'ok') { var valid = dlg.getSettings(); me.view.inputSelectRange.setValue(valid); me.view.inputSelectRange.checkValidate(); me.onChangeSearchOption('range', valid); } }; var win = new SSE.Views.CellRangeDialog({ handler: handlerDlg }).on('close', function() { _.delay(function(){ me.view.inputSelectRange.focus(); },1); }); win.show(); win.setSettings({ api: me.api, range: (!_.isEmpty(me.view.inputSelectRange.getValue()) && (me.view.inputSelectRange.checkValidate()==true)) ? me.view.inputSelectRange.getValue() : me._state.selectedRange, type: Asc.c_oAscSelectionDialogType.PrintTitles }); }, onSearchNext: function (type, text, e) { var isReturnKey = type === 'keydown' && e.keyCode === Common.UI.Keys.RETURN; if (isReturnKey || type !== 'keydown') { this._state.searchText = text; this.onQuerySearch(type); } this._state.isReturnPressed = isReturnKey; }, onInputSearchChange: function (text) { if (!text && !this._state.isReturnPressed) { this._state.noSearchEmptyCells = true; } this._state.isReturnPressed = false; var me = this; if (this._state.searchText !== text) { this._state.newSearchText = text; this._lastInputChange = (new Date()); if (this.searchTimer === undefined) { this.searchTimer = setInterval(function(){ if ((new Date()) - me._lastInputChange < 400) return; me._state.searchText = me._state.newSearchText; if (!me.onQuerySearch() && me._state.newSearchText === '') { me.view.updateResultsNumber('no-results'); me.view.disableNavButtons(); Common.NotificationCenter.trigger('search:updateresults', undefined, 0); } }, 10); } } }, onQuerySearch: function (d, isNeedRecalc) { this.searchTimer && clearInterval(this.searchTimer); this.searchTimer = undefined; var me = this; if (this._state.withinSheet === Asc.c_oAscSearchBy.Range && !this._state.isValidSelectedRange) { Common.UI.warning({ title: this.notcriticalErrorTitle, msg: this.textInvalidRange, buttons: ['ok'], callback: function () { me.view.focus('range'); } }); return; } this.hideResults(); var options = new Asc.asc_CFindOptions(); options.asc_setFindWhat(this._state.searchText); options.asc_setScanForward(d != 'back'); options.asc_setIsMatchCase(this._state.matchCase); options.asc_setIsWholeCell(this._state.matchWord); options.asc_setScanOnOnlySheet(this._state.withinSheet); if (this._state.withinSheet === Asc.c_oAscSearchBy.Range) { options.asc_setSpecificRange(this._state.selectedRange); } options.asc_setScanByRows(this._state.searchByRows); options.asc_setLookIn(this._state.lookInFormulas ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); options.asc_setNeedRecalc(isNeedRecalc); if (this._state.isContentChanged) { options.asc_setLastSearchElem(this._state.lastSelectedItem); this.view.disableReplaceButtons(false); this._state.isContentChanged = false; if (!this.view.$el.is(':visible')) { this.resultItems = []; } } options.asc_setNotSearchEmptyCells(this._state.noSearchEmptyCells); if (!this.api.asc_findText(options)) { this._state.isResults = false; if (this._state.noSearchEmptyCells) { this.removeResultItems('no-results'); this._state.noSearchEmptyCells = false; } else { this.removeResultItems(); } return false; } this._state.isResults = true; if (this.view.$el.is(':visible')) { this.api.asc_StartTextAroundSearch(); } return true; }, onQueryReplace: function(textSearch, textReplace) { this.api.isReplaceAll = false; var options = new Asc.asc_CFindOptions(); options.asc_setFindWhat(textSearch); options.asc_setReplaceWith(textReplace); options.asc_setIsMatchCase(this._state.matchCase); options.asc_setIsWholeCell(this._state.matchWord); options.asc_setScanOnOnlySheet(this._state.withinSheet); if (this._state.withinSheet === Asc.c_oAscSearchBy.Range) { options.asc_setSpecificRange(this._state.selectedRange); } options.asc_setScanByRows(this._state.searchByRows); options.asc_setLookIn(this._state.lookIn ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); options.asc_setIsReplaceAll(false); this.api.asc_replaceText(options); }, onQueryReplaceAll: function(textSearch, textReplace) { this.api.isReplaceAll = true; var options = new Asc.asc_CFindOptions(); options.asc_setFindWhat(textSearch); options.asc_setReplaceWith(textReplace); options.asc_setIsMatchCase(this._state.matchCase); options.asc_setIsWholeCell(this._state.matchWord); options.asc_setScanOnOnlySheet(this._state.withinSheet); if (this._state.withinSheet === Asc.c_oAscSearchBy.Range) { options.asc_setSpecificRange(this._state.selectedRange); } options.asc_setScanByRows(this._state.searchByRows); options.asc_setLookIn(this._state.lookIn ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); options.asc_setIsReplaceAll(true); this.api.asc_replaceText(options); }, onRenameText: function (found, replaced) { var me = this; if (this.api.isReplaceAll) { if (!found) { this.removeResultItems(); } else { !(found-replaced) && this.removeResultItems(); Common.UI.info({ msg: (!(found-replaced) || replaced > found) ? Common.Utils.String.format(this.textReplaceSuccess,replaced) : Common.Utils.String.format(this.textReplaceSkipped,found-replaced), callback: function() { me.view.focus(); } }); } } else { this.onQuerySearch(); } }, removeResultItems: function (type) { this.resultItems = []; this.hideResults(); this.view.updateResultsNumber(type, 0); // type === undefined, count === 0 -> no matches this._state.currentResult = 0; this._state.resultsNumber = 0; this.view.disableNavButtons(); Common.NotificationCenter.trigger('search:updateresults', undefined, 0); }, onApiRemoveTextAroundSearch: function (arr) { var me = this; arr.forEach(function (id) { var ind = _.findIndex(me.resultItems, {id: id}); if (ind !== -1) { me.resultItems[ind].$el.remove(); me.resultItems.splice(ind, 1); } }); if (this.resultItems.length === 0) { this.removeResultItems(); } }, onUpdateSearchCurrent: function (current, all) { if (current === -1) return; this._state.currentResult = current; this._state.resultsNumber = all; if (this.view) { this.view.updateResultsNumber(current, all); this.view.disableNavButtons(current, all); if (this.resultItems && this.resultItems.length > 0) { this.resultItems.forEach(function (item) { item.selected = false; }); if (this.resultItems[current]) { this._state.lastSelectedItem = this.resultItems[current].data; this.resultItems[current].selected = true; $('#search-results').find('.item').removeClass('selected'); this.resultItems[current].$el.addClass('selected'); } } } Common.NotificationCenter.trigger('search:updateresults', current, all); }, scrollToSelectedResult: function (ind) { var index = ind !== undefined ? ind : _.findIndex(this.resultItems, {selected: true}); if (index !== -1) { var item = this.resultItems[index].$el, itemHeight = item.outerHeight(), itemTop = item.position().top, container = this.view.$resultsContainer.find('.search-items'), containerHeight = container.outerHeight(), containerTop = container.scrollTop(); if (itemTop < 0 || (containerTop === 0 && itemTop > containerHeight)) { this.view.$resultsContainer.scroller.scrollTop(containerTop + itemTop - 12); } else if (itemTop + itemHeight > containerHeight) { this.view.$resultsContainer.scroller.scrollTop(containerTop + itemHeight); } } }, onStartTextAroundSearch: function () { if (this.view) { this._state.isStartedAddingResults = true; } }, onEndTextAroundSearch: function () { if (this.view) { this._state.isStartedAddingResults = false; this.view.$resultsContainer.scroller.update({alwaysVisibleY: true}); } }, onApiGetTextAroundSearch: function (data) { // [id, sheet, name, cell, value, formula] if (this.view && this._state.isStartedAddingResults) { if (data.length > 300 || !data.length) return; var me = this, $innerResults = me.view.$resultsContainer.find('.search-items'), selectedInd; me.resultItems = []; data.forEach(function (item, ind) { var isSelected = ind === me._state.currentResult; var tr = '