From 4444d1d687f8d3718d9eb5e854383fc47d8bccb8 Mon Sep 17 00:00:00 2001 From: JuliaSvinareva Date: Sun, 3 Apr 2022 18:17:46 +0300 Subject: [PATCH] [SSE] Add methods for auto search --- apps/common/main/lib/view/SearchPanel.js | 22 +- .../main/app/controller/LeftMenu.js | 34 +- .../main/app/controller/Search.js | 337 +++++++++++++++--- 3 files changed, 304 insertions(+), 89 deletions(-) diff --git a/apps/common/main/lib/view/SearchPanel.js b/apps/common/main/lib/view/SearchPanel.js index 71acac950..79002492b 100644 --- a/apps/common/main/lib/view/SearchPanel.js +++ b/apps/common/main/lib/view/SearchPanel.js @@ -182,8 +182,11 @@ define([ cls: 'input-group-nr', data: [ { value: 0, displayValue: this.textSheet }, - { value: 1, displayValue: this.textWorkbook } + { value: 1, displayValue: this.textWorkbook }, + { value: 2, displayValue: this.textSpecificRange} ] + }).on('selected', function(combo, record) { + me.fireEvent('search:options', ['within', record.value]); }); this.cmbSearch = new Common.UI.ComboBox({ @@ -196,6 +199,10 @@ define([ { value: 0, displayValue: this.textByRows }, { value: 1, displayValue: this.textByColumns } ] + }).on('selected', function(combo, record) { + console.log(record.value); + console.log(!record.value); + me.fireEvent('search:options', ['search', !record.value]); }); this.cmbLookIn = new Common.UI.ComboBox({ @@ -208,6 +215,10 @@ define([ { value: 0, displayValue: this.textFormulas }, { value: 1, displayValue: this.textValues } ] + }).on('selected', function(combo, record) { + console.log(record.value); + console.log(!record.value); + me.fireEvent('search:options', ['lookIn', !record.value]); }); this.$searchOptionsBlock = $('.search-options-block'); @@ -293,14 +304,6 @@ define([ }; }, - getExtraSettings: function () { - return { - within: !this.cmbWithin.getValue(), - search: !this.cmbSearch.getValue(), - lookIn: !this.cmbLookIn.getValue() - }; - }, - expandSearchOptions: function () { this.extendedOptions = !this.extendedOptions; this.$searchOptionsBlock[this.extendedOptions ? 'removeClass' : 'addClass']('no-expand'); @@ -341,6 +344,7 @@ define([ textLookIn: 'Look in', textSheet: 'Sheet', textWorkbook: 'Workbook', + textSpecificRange: 'Specific range', textByRows: 'By rows', textByColumns: 'By columns', textFormulas: 'Formulas', diff --git a/apps/spreadsheeteditor/main/app/controller/LeftMenu.js b/apps/spreadsheeteditor/main/app/controller/LeftMenu.js index a9a17a479..f5c56da32 100644 --- a/apps/spreadsheeteditor/main/app/controller/LeftMenu.js +++ b/apps/spreadsheeteditor/main/app/controller/LeftMenu.js @@ -66,8 +66,7 @@ define([ 'file:show': _.bind(this.fileShowHide, this, true), 'file:hide': _.bind(this.fileShowHide, this, false), 'comments:show': _.bind(this.commentsShowHide, this, true), - 'comments:hide': _.bind(this.commentsShowHide, this, false), - 'search:aftershow': _.bind(this.onShowAfterSearch, this) + 'comments:hide': _.bind(this.commentsShowHide, this, false) }, 'Common.Views.About': { 'show': _.bind(this.aboutShowHide, this, true), @@ -856,15 +855,17 @@ define([ var selectedText = this.api.asc_GetSelectedText(); if (this.isSearchPanelVisible()) { selectedText && this.leftMenu.panelSearch.setFindText(selectedText); - this.leftMenu.panelSearch.focus(s); + this.leftMenu.panelSearch.focus(selectedText !== '' ? s : 'search'); + this.leftMenu.fireEvent('search:aftershow', this.leftMenu, selectedText); return false; } else if (this.getApplication().getController('Viewport').isSearchBarVisible()) { + var viewport = this.getApplication().getController('Viewport'); if (s === 'replace') { - this.getApplication().getController('Viewport').header.btnSearch.toggle(false); - this.onShowHideSearch(true, this.getApplication().getController('Viewport').searchBar.inputSearch.val()); + viewport.header.btnSearch.toggle(false); + this.onShowHideSearch(true, viewport.searchBar.inputSearch.val()); } else { - selectedText && this.getApplication().getController('Viewport').searchBar.setText(selectedText); - this.getApplication().getController('Viewport').searchBar.focus(); + selectedText && viewport.searchBar.setText(selectedText); + viewport.searchBar.focus(); return false; } } else if (s === 'search') { @@ -874,7 +875,7 @@ define([ this.onShowHideSearch(true, selectedText); } this.leftMenu.btnSearchBar.toggle(true,true); - this.leftMenu.panelSearch.focus(s); + this.leftMenu.panelSearch.focus(selectedText !== '' ? s : 'search'); } return false; case 'save': @@ -1012,28 +1013,13 @@ define([ if (state) { Common.UI.Menu.Manager.hideAll(); this.leftMenu.showMenu('advancedsearch'); - this.onShowAfterSearch(findText); + this.leftMenu.fireEvent('search:aftershow', this.leftMenu, findText); } else { this.leftMenu.btnSearchBar.toggle(false, true); this.leftMenu.onBtnMenuClick(this.leftMenu.btnSearchBar); } }, - onShowAfterSearch: function (findText) { - var viewport = this.getApplication().getController('Viewport'); - if (viewport.isSearchBarVisible()) { - viewport.searchBar.hide(); - } - - var text = findText || this.api.asc_GetSelectedText(); - if (text) { - this.leftMenu.panelSearch.setFindText(text); - } else if (text !== undefined) { - this.leftMenu.panelSearch.setFindText(''); - } - this.leftMenu.panelSearch.focus(); - }, - onMenuSearchBar: function(obj, show) { if (show) { var mode = this.mode.isEdit && !this.viewmode ? undefined : 'no-replace'; diff --git a/apps/spreadsheeteditor/main/app/controller/Search.js b/apps/spreadsheeteditor/main/app/controller/Search.js index 9fe63fbc2..5d4afe5e8 100644 --- a/apps/spreadsheeteditor/main/app/controller/Search.js +++ b/apps/spreadsheeteditor/main/app/controller/Search.js @@ -55,19 +55,37 @@ define([ initialize: function () { this.addListeners({ 'SearchBar': { - 'search:back': _.bind(this.onQuerySearch, this, 'back'), - 'search:next': _.bind(this.onQuerySearch, this, 'next'), + 'search:back': _.bind(this.onSearchNext, this, 'back'), + 'search:next': _.bind(this.onSearchNext, this, 'next'), + 'search:input': _.bind(this.onInputSearchChange, this), + 'search:keydown': _.bind(this.onSearchNext, this, 'keydown') }, 'Common.Views.SearchPanel': { - 'search:back': _.bind(this.onQuerySearch, this, 'back'), - 'search:next': _.bind(this.onQuerySearch, this, 'next'), + '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: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': { // TO DO + 'search:aftershow': _.bind(this.onShowAfterSearch, this) } }); }, onLaunch: function () { - this._state = {}; + this._state = { + searchText: '', + matchCase: false, + matchWord: false, + useRegExp: false, + withinSheet: true, + searchByRows: true, + lookInFormulas: true + }; }, setMode: function (mode) { @@ -78,6 +96,11 @@ define([ 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)); } return this; }, @@ -87,64 +110,119 @@ define([ this.view : Backbone.Controller.prototype.getView.call(this, name); }, - onQuerySearch: function (d, w, opts, fromPanel) { - var options = new Asc.asc_CFindOptions(); - options.asc_setFindWhat(opts.textsearch); - options.asc_setScanForward(d != 'back'); - options.asc_setIsMatchCase(opts.matchcase); - options.asc_setIsWholeCell(opts.matchword); + onChangeSearchOption: function (option, value) { + 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; + break; + case 'search': + this._state.searchByRows = value; + break; + case 'lookIn': + this._state.lookInFormulas = value; + break; - var extraOptions = this.view.getExtraSettings(); - options.asc_setScanOnOnlySheet(extraOptions.within); - options.asc_setScanByRows(extraOptions.search); - options.asc_setLookIn(extraOptions.lookIn ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); - - if (!this.api.asc_findText(options)) { - var me = this; - Common.UI.info({ - msg: this.textNoTextFound, - callback: function() { - if (fromPanel) { - me.view.focus(); - } else { - - } - } - }); } }, - onQueryReplace: function(w, opts) { - this.api.isReplaceAll = false; - - var options = new Asc.asc_CFindOptions(); - options.asc_setFindWhat(opts.textsearch); - options.asc_setReplaceWith(opts.textreplace); - options.asc_setIsMatchCase(opts.matchcase); - options.asc_setIsWholeCell(opts.matchword); - - var extraOptions = this.view.getExtraSettings(); - options.asc_setScanOnOnlySheet(extraOptions.within); - options.asc_setScanByRows(extraOptions.search); - options.asc_setLookIn(extraOptions.lookIn ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); - options.asc_setIsReplaceAll(false); - - this.api.asc_replaceText(options); + onSearchNext: function (type, text, e) { + if (text && text.length > 0 && (type === 'keydown' && e.keyCode === Common.UI.Keys.RETURN || type !== 'keydown')) { + this._state.searchText = text; + if (this.onQuerySearch(type) && this.searchTimer) { + this.hideResults(); + clearInterval(this.searchTimer); + this.searchTimer = undefined; + if (this.view.$el.is(':visible')) { + this.api.asc_StartTextAroundSearch(); + } + } + } }, - onQueryReplaceAll: function(w, opts) { - this.api.isReplaceAll = true; + onInputSearchChange: function (text) { + 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.hideResults(); + me._state.searchText = me._state.newSearchText; + if (me._state.newSearchText !== '' && me.onQuerySearch()) { + if (me.view.$el.is(':visible')) { + me.api.asc_StartTextAroundSearch(); + } + me.view.disableReplaceButtons(false); + } else if (me._state.newSearchText === '') { + me.view.updateResultsNumber('no-results'); + me.view.disableReplaceButtons(true); + } + clearInterval(me.searchTimer); + me.searchTimer = undefined; + }, 10); + } + } + }, + + onQuerySearch: function (d, w, opts, fromPanel) { var options = new Asc.asc_CFindOptions(); - options.asc_setFindWhat(opts.textsearch); - options.asc_setReplaceWith(opts.textreplace); - options.asc_setIsMatchCase(opts.matchcase); - options.asc_setIsWholeCell(opts.matchword); + 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); // TO DO + options.asc_setScanByRows(this._state.searchByRows); + options.asc_setLookIn(this._state.lookInFormulas ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); + if (!this.api.asc_findText(options)) { + this.resultItems = []; + this.view.updateResultsNumber(undefined, 0); + this.view.disableReplaceButtons(true); + this._state.currentResult = 0; + this._state.resultsNumber = 0; + this.view.disableNavButtons(); + return false; + } + return true; + }, - var extraOptions = this.view.getExtraSettings(); - options.asc_setScanOnOnlySheet(extraOptions.within); - options.asc_setScanByRows(extraOptions.search); - options.asc_setLookIn(extraOptions.lookIn ? Asc.c_oAscFindLookIn.Formulas : Asc.c_oAscFindLookIn.Value); + onQueryReplace: function(textSearch, textReplace) { + if (textSearch !== '') { + 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); // TO DO + 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); // TO DO + 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); @@ -152,7 +230,7 @@ define([ onRenameText: function (found, replaced) { var me = this; - if (this.api.isReplaceAll) { + /*if (this.api.isReplaceAll) { Common.UI.info({ msg: (found) ? ((!found-replaced) ? Common.Utils.String.format(this.textReplaceSuccess,replaced) : Common.Utils.String.format(this.textReplaceSkipped,found-replaced)) : this.textNoTextFound, callback: function() { @@ -181,7 +259,154 @@ define([ } }); } + }*/ + }, + + 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); + } + }); + }, + + 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.length > 0) { + this.resultItems.forEach(function (item) { + item.selected = false; + }); + if (this.resultItems[current]) { + this.resultItems[current].selected = true; + $('#search-results').find('.item').removeClass('selected'); + $(this.resultItems[current].el).addClass('selected'); + this.scrollToSelectedResult(current); + } + } } + 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, + containerHeight = container.outerHeight(), + containerTop = container.scrollTop(); + if (itemTop < 0 || (containerTop === 0 && itemTop > containerHeight)) { + container.scroller.scrollTop(containerTop + itemTop - 12); + } else if (itemTop + itemHeight > containerHeight) { + container.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) return; + var me = this; + me.resultItems = []; + data.forEach(function (item, ind) { + var el = document.createElement("div"), + isSelected = ind === me._state.currentResult; + el.className = 'item'; + el.innerHTML = item[4].trim(); + me.view.$resultsContainer.append(el); + if (isSelected) { + $(el).addClass('selected'); + } + + var resultItem = {id: item[0], $el: $(el), el: el, selected: isSelected}; + me.resultItems.push(resultItem); + $(el).on('click', _.bind(function (el) { + var id = item[0]; + me.api.asc_SelectSearchElement(id); + }, me)); + }); + + this.view.$resultsContainer.show(); + } + }, + + hideResults: function () { + if (this.view) { + this.view.$resultsContainer.hide(); + this.view.$resultsContainer.empty(); + } + }, + + onShowAfterSearch: function (findText) { + var viewport = this.getApplication().getController('Viewport'); + if (viewport.isSearchBarVisible()) { + viewport.searchBar.hide(); + } + + var text = findText || this.api.asc_GetSelectedText() || this._state.searchText; + if (text) { + this.view.setFindText(text); + } else if (text !== undefined) { + this.view.setFindText(''); + } + + this.hideResults(); + if (text !== '' && text === this._state.searchText) { // search was made + this.view.disableReplaceButtons(false); + this.api.asc_StartTextAroundSearch(); + } else if (text !== '') { // search wasn't made + this.onInputSearchChange(text); + } else { + this.resultItems = []; + this.view.disableReplaceButtons(true); + this.view.clearResultsNumber(); + } + this.view.disableNavButtons(this._state.currentResult, this._state.resultsNumber); + }, + + onShowPanel: function () { + if (this.resultItems && this.resultItems.length > 0 && !this._state.isStartedAddingResults) { + var me = this; + this.view.$resultsContainer.show(); + this.resultItems.forEach(function (item) { + me.view.$resultsContainer.append(item.el); + if (item.selected) { + $(item.el).addClass('selected'); + } + $(item.el).on('click', function (el) { + me.api.asc_SelectSearchElement(item.id); + $('#search-results').find('.item').removeClass('selected'); + $(el.currentTarget).addClass('selected'); + }); + }); + this.scrollToSelectedResult(); + } + }, + + onHidePanel: function () { + this.hideResults(); }, textNoTextFound: 'The data you have been searching for could not be found. Please adjust your search options.',