diff --git a/apps/presentationeditor/mobile/app/controller/Search.js b/apps/presentationeditor/mobile/app/controller/Search.js index 81ce45a43..ea53666bc 100644 --- a/apps/presentationeditor/mobile/app/controller/Search.js +++ b/apps/presentationeditor/mobile/app/controller/Search.js @@ -81,7 +81,8 @@ define([ 'Search': { 'searchbar:show' : this.onSearchbarShow, 'searchbar:hide' : this.onSearchbarHide, - 'searchbar:render' : this.onSearchbarRender + 'searchbar:render' : this.onSearchbarRender, + 'searchbar:showsettings': this.onSearchbarSettings } }); }, @@ -130,7 +131,8 @@ define([ onSearchbarRender: function(bar) { var me = this, - searchString = Common.SharedSettings.get('search-search') || ''; + searchString = Common.SharedSettings.get('search-search') || '', + replaceString = Common.SharedSettings.get('search-replace')|| ''; me.searchBar = uiApp.searchbar('.searchbar.document .searchbar.search', { customSearch: true, @@ -139,13 +141,46 @@ define([ onClear : _.bind(me.onSearchClear, me) }); + me.replaceBar = uiApp.searchbar('.searchbar.document .searchbar.replace', { + customSearch: true, + onSearch : _.bind(me.onReplaceChange, me), + onEnable : _.bind(me.onReplaceEnable, me), + onClear : _.bind(me.onReplaceClear, me) + }); + me.searchPrev = $('.searchbar.document .prev'); me.searchNext = $('.searchbar.document .next'); + me.replaceBtn = $('.searchbar.document .link.replace'); me.searchPrev.single('click', _.bind(me.onSearchPrev, me)); me.searchNext.single('click', _.bind(me.onSearchNext, me)); + me.replaceBtn.single('click', _.bind(me.onReplace, me)); + + $$('.searchbar.document .link.replace').on('taphold', _.bind(me.onReplaceAll, me)); me.searchBar.search(searchString); + me.replaceBar.search(replaceString); + }, + + onSearchbarSettings: function (view) { + var strictBool = function (settingName) { + var value = Common.SharedSettings.get(settingName); + return !_.isUndefined(value) && (value === true); + }; + + var me = this, + isReplace = strictBool('search-is-replace'), + isCaseSensitive = strictBool('search-case-sensitive'), + $pageSettings = $('.page[data-page=search-settings]'), + $inputType = $pageSettings.find('input[name=search-type]'), + $inputCase = $pageSettings.find('#search-case-sensitive input:checkbox'); + + $inputType.val([isReplace ? 'replace' : 'search']); + $inputCase.prop('checked', isCaseSensitive); + + // init events + $inputType.single('change', _.bind(me.onTypeChange, me)); + $inputCase.single('change', _.bind(me.onCaseClick, me)); }, onSearchbarShow: function(bar) { @@ -153,7 +188,7 @@ define([ }, onSearchEnable: function (bar) { - // + this.replaceBar.container.removeClass('searchbar-active'); }, onSearchbarHide: function(bar) { @@ -166,7 +201,7 @@ define([ Common.SharedSettings.set('search-search', search.query); - _.each([me.searchPrev, me.searchNext], function(btn) { + _.each([me.searchPrev, me.searchNext, me.replaceBtn], function(btn) { btn.toggleClass('disabled', isEmpty); }); }, @@ -177,6 +212,21 @@ define([ // document.activeElement.blur(); }, + onReplaceChange: function(replace) { + var me = this, + isEmpty = (replace.query.trim().length < 1); + + Common.SharedSettings.set('search-replace', replace.query); + }, + + onReplaceEnable: function (bar) { + this.searchBar.container.removeClass('searchbar-active'); + }, + + onReplaceClear: function(replace) { + Common.SharedSettings.set('search-replace', ''); + }, + onSearchPrev: function(btn) { this.onQuerySearch(this.searchBar.query, 'back'); }, @@ -185,9 +235,37 @@ define([ this.onQuerySearch(this.searchBar.query, 'next'); }, + onReplace: function (btn) { + this.onQueryReplace(this.searchBar.query, this.replaceBar.query); + }, + + onReplaceAll: function (e) { + var me = this, + popover = [ + '
', + '
', + '', + '
', + '
' + ].join(''); + + popover = uiApp.popover(popover, $$(e.currentTarget)); + + $('#replace-all').single('click', _.bind(function () { + me.onQueryReplaceAll(this.searchBar.query, this.replaceBar.query); + uiApp.closeModal(popover); + }, me)) + }, + onQuerySearch: function(query, direction) { + var matchcase = Common.SharedSettings.get('search-case-sensitive') || false; + if (query && query.length) { - if (!this.api.findText(query, direction != 'back')) { + if (!this.api.findText(query, direction != 'back', matchcase)) { var me = this; uiApp.alert( '', @@ -200,9 +278,48 @@ define([ } }, + onQueryReplace: function(search, replace) { + var matchcase = Common.SharedSettings.get('search-case-sensitive') || false; + + if (search && search.length) { + if (!this.api.asc_replaceText(search, replace, false, matchcase)) { + var me = this; + uiApp.alert( + '', + me.textNoTextFound, + function () { + me.searchBar.input.focus(); + } + ); + } + } + }, + + onQueryReplaceAll: function(search, replace) { + var matchcase = Common.SharedSettings.get('search-case-sensitive') || false; + + if (search && search.length) { + this.api.asc_replaceText(search, replace, true, matchcase); + } + }, + + onTypeChange: function (e) { + var me = this, + $target = $(e.currentTarget), + isReplace = ($target.val() === 'replace'); + + Common.SharedSettings.set('search-is-replace', isReplace); + $('.searchbar.document').toggleClass('replace', isReplace); + }, + + onCaseClick: function (e) { + Common.SharedSettings.set('search-case-sensitive', $(e.currentTarget).is(':checked')); + }, + // API handlers - textNoTextFound : 'Text not found' + textNoTextFound : 'Text not found', + textReplaceAll: 'Replace All' } })(), PE.Controllers.Search || {})) }); \ No newline at end of file diff --git a/apps/presentationeditor/mobile/app/template/Search.template b/apps/presentationeditor/mobile/app/template/Search.template index c19a04bb2..2b4076cd7 100644 --- a/apps/presentationeditor/mobile/app/template/Search.template +++ b/apps/presentationeditor/mobile/app/template/Search.template @@ -2,19 +2,92 @@
+
+ + +
+ +
+
+ <% if (isEdit) { %> +
+
    +
  • + +
  • +
  • + +
  • +
+
+ <% } %> +
+
    +
  • +
    +
    +
    <%= scope.textCase %>
    +
    + +
    +
    +
    +
  • +
diff --git a/apps/presentationeditor/mobile/app/view/Search.js b/apps/presentationeditor/mobile/app/view/Search.js index 73e9a3c02..37f18643c 100644 --- a/apps/presentationeditor/mobile/app/view/Search.js +++ b/apps/presentationeditor/mobile/app/view/Search.js @@ -68,7 +68,7 @@ define([ }, initEvents: function() { - // + $('#search-settings').single('click', _.bind(this.showSettings, this)); }, // Render layout @@ -88,6 +88,57 @@ define([ this.render(); }, + showSettings: function (e) { + var me = this; + + uiApp.closeModal(); + + if (Common.SharedSettings.get('phone')) { + me.picker = $$(uiApp.popup([ + ''].join('') + )) + } else { + me.picker = uiApp.popover([ + '
', + '
', + '
', + '
', + '', + '
', + '
', + '
'].join(''), + $$('#search-settings') + ); + + // Prevent hide overlay. Conflict popover and modals. + var $overlay = $('.modal-overlay'); + + $$(me.picker).on('opened', function () { + $overlay.on('removeClass', function () { + if (!$overlay.hasClass('modal-overlay-visible')) { + $overlay.addClass('modal-overlay-visible') + } + }); + }).on('close', function () { + $overlay.off('removeClass'); + $overlay.removeClass('modal-overlay-visible') + }); + } + + if (Common.SharedSettings.get('android')) { + $$('.view.search-settings-view.navbar-through').removeClass('navbar-through').addClass('navbar-fixed'); + $$('.view.search-settings-view .navbar').prependTo('.view.search-settings-view > .pages > .page'); + } + + me.fireEvent('searchbar:showsettings', me); + }, + showSearch: function () { var me = this, searchBar = $$('.searchbar.document'); @@ -95,6 +146,10 @@ define([ if (searchBar.length < 1) { $(me.el).find('.pages .page').first().prepend(_layout.find('#search-panel-view').html()); + // Show replace mode if needed + var isReplace = Common.SharedSettings.get('search-is-replace'); + $('.searchbar.document').toggleClass('replace', !_.isUndefined(isReplace) && (isReplace === true)); + me.fireEvent('searchbar:render', me); me.fireEvent('searchbar:show', me); @@ -133,7 +188,13 @@ define([ } }, - textSearch: 'Search' + textFind: 'Find', + textFindAndReplace: 'Find and Replace', + textDone: 'Done', + textSearch: 'Search', + textReplace: 'Replace', + textCase: 'Case sensitive', + textHighlight: 'Highlight results' } })(), PE.Views.Search || {})) }); \ No newline at end of file diff --git a/apps/presentationeditor/mobile/app/view/Settings.js b/apps/presentationeditor/mobile/app/view/Settings.js index 40084d3a0..ed1a83fd4 100644 --- a/apps/presentationeditor/mobile/app/view/Settings.js +++ b/apps/presentationeditor/mobile/app/view/Settings.js @@ -221,7 +221,8 @@ define([ textSlideSize: 'Slide Size', mniSlideStandard: 'Standard (4:3)', mniSlideWide: 'Widescreen (16:9)', - textPoweredBy: 'Powered by' + textPoweredBy: 'Powered by', + textFindAndReplace: 'Find and Replace' } })(), PE.Views.Settings || {})) }); \ No newline at end of file diff --git a/apps/presentationeditor/mobile/locale/en.json b/apps/presentationeditor/mobile/locale/en.json index b7e512bed..c7d3eb8db 100644 --- a/apps/presentationeditor/mobile/locale/en.json +++ b/apps/presentationeditor/mobile/locale/en.json @@ -213,6 +213,7 @@ "PE.Controllers.Main.warnNoLicenseUsers": "This version of ONLYOFFICE Editors has certain limitations for concurrent users.
If you need more please consider purchasing a commercial license.", "PE.Controllers.Main.warnProcessRightsChange": "You have been denied the right to edit the file.", "PE.Controllers.Search.textNoTextFound": "Text not Found", + "PE.Controllers.Search.textReplaceAll": "Replace All", "PE.Controllers.Settings.notcriticalErrorTitle": "Warning", "PE.Controllers.Settings.txtLoading": "Loading...", "PE.Controllers.Toolbar.dlgLeaveMsgText": "You have unsaved changes in this document. Click 'Stay on this Page' to await the autosave of the document. Click 'Leave this Page' to discard all the unsaved changes.", @@ -423,6 +424,11 @@ "PE.Views.EditText.textSmallCaps": "Small Caps", "PE.Views.EditText.textStrikethrough": "Strikethrough", "PE.Views.EditText.textSubscript": "Subscript", + "PE.Views.Search.textCase": "Case sensitive", + "PE.Views.Search.textDone": "Done", + "PE.Views.Search.textFind": "Find", + "PE.Views.Search.textFindAndReplace": "Find and Replace", + "PE.Views.Search.textReplace": "Replace", "PE.Views.Search.textSearch": "Search", "PE.Views.Settings.mniSlideStandard": "Standard (4:3)", "PE.Views.Settings.mniSlideWide": "Widescreen (16:9)", @@ -437,6 +443,7 @@ "PE.Views.Settings.textEditPresent": "Edit Presentation", "PE.Views.Settings.textEmail": "email", "PE.Views.Settings.textFind": "Find", + "PE.Views.Settings.textFindAndReplace": "Find and Replace", "PE.Views.Settings.textHelp": "Help", "PE.Views.Settings.textLoading": "Loading...", "PE.Views.Settings.textPoweredBy": "Powered by", diff --git a/apps/presentationeditor/mobile/resources/css/app-ios.css b/apps/presentationeditor/mobile/resources/css/app-ios.css index bce01f9a0..fd0900f8a 100644 --- a/apps/presentationeditor/mobile/resources/css/app-ios.css +++ b/apps/presentationeditor/mobile/resources/css/app-ios.css @@ -6239,6 +6239,16 @@ html.pixel-ratio-3 .document-menu .list-block li:last-child li .item-inner:after background: url('../../../../common/mobile/resources/img/about/onlyoffice.svg') no-repeat center; margin-top: 20px; } +.tablet .searchbar.document.replace .center .searchbar:first-child { + margin-right: 10px; +} +.tablet .searchbar.document.replace .center .replace { + display: flex; +} +.tablet .searchbar.document.replace .right .replace { + display: flex; + margin: 0 10px; +} .tablet .searchbar.document .center { width: 100%; } @@ -6246,9 +6256,30 @@ html.pixel-ratio-3 .document-menu .list-block li:last-child li .item-inner:after background: inherit; padding: 0; } +.tablet .searchbar.document .center .replace { + display: none; +} .tablet .searchbar.document .right .prev { margin-left: 0; } +.tablet .searchbar.document .right .replace { + display: none; +} +.phone .searchbar.document.replace { + height: 88px; +} +.phone .searchbar.document.replace .left { + margin-top: -44px; +} +.phone .searchbar.document.replace .center .searchbar-input { + margin: 8px 0; +} +.phone .searchbar.document.replace .center .replace { + display: block; +} +.phone .searchbar.document.replace .right > .replace { + display: flex; +} .phone .searchbar.document .left, .phone .searchbar.document .center, .phone .searchbar.document .right { @@ -6264,9 +6295,15 @@ html.pixel-ratio-3 .document-menu .list-block li:last-child li .item-inner:after .phone .searchbar.document .center .searchbar:after { content: none; } +.phone .searchbar.document .center .replace { + display: none; +} .phone .searchbar.document .right > p { margin: 0; } +.phone .searchbar.document .right > .replace { + display: none; +} .searchbar.document { background: #e4e4e6; } diff --git a/apps/presentationeditor/mobile/resources/css/app-material.css b/apps/presentationeditor/mobile/resources/css/app-material.css index 068a5713a..281461beb 100644 --- a/apps/presentationeditor/mobile/resources/css/app-material.css +++ b/apps/presentationeditor/mobile/resources/css/app-material.css @@ -5838,8 +5838,14 @@ html.phone .document-menu .list-block .item-link { .about .logo { background: url('../../../../common/mobile/resources/img/about/onlyoffice.svg') no-repeat center; } -.tablet .searchbar.document .left { - min-width: 15px; +.tablet .searchbar.document.replace .center > .replace { + display: flex; +} +.tablet .searchbar.document.replace .right .replace { + display: flex; +} +.tablet .searchbar.document.replace .link.replace { + font-size: 16px; } .tablet .searchbar.document .center { width: 100%; @@ -5853,14 +5859,32 @@ html.phone .document-menu .list-block .item-link { .tablet .searchbar.document .center .searchbar.search { padding: 0; } +.tablet .searchbar.document .center > .replace { + display: none; +} +.tablet .searchbar.document .right .replace { + display: none; +} +.phone .searchbar.document.replace { + height: 96px; +} +.phone .searchbar.document.replace .link.replace { + font-size: 16px; +} +.phone .searchbar.document.replace .left { + margin-top: -48px; +} +.phone .searchbar.document.replace .center .replace { + display: block; +} +.phone .searchbar.document.replace .right > .replace { + display: flex; +} .phone .searchbar.document .left, .phone .searchbar.document .center, .phone .searchbar.document .right { flex-direction: column; } -.phone .searchbar.document .left { - min-width: 15px; -} .phone .searchbar.document .center { width: 100%; margin: 0; @@ -5869,12 +5893,18 @@ html.phone .document-menu .list-block .item-link { .phone .searchbar.document .center .searchbar { padding: 0; } +.phone .searchbar.document .center .replace { + display: none; +} .phone .searchbar.document .right > p { margin: 0; } .phone .searchbar.document .right > p a.link { height: 48px; } +.phone .searchbar.document .right > .replace { + display: none; +} i.icon.icon-expand-up { width: 17px; height: 17px; diff --git a/apps/presentationeditor/mobile/resources/less/ios/_search.less b/apps/presentationeditor/mobile/resources/less/ios/_search.less index 3d1a59f69..389fd54c2 100644 --- a/apps/presentationeditor/mobile/resources/less/ios/_search.less +++ b/apps/presentationeditor/mobile/resources/less/ios/_search.less @@ -1,6 +1,27 @@ // Search .tablet { + // Replace mode + .searchbar.document.replace { + .center { + .searchbar:first-child { + margin-right: 10px; + } + + .replace { + display: flex; + } + } + + .right { + .replace { + display: flex; + margin: 0 10px; + } + } + } + + // Search mode .searchbar.document { .center { width: 100%; @@ -9,17 +30,51 @@ background: inherit; padding: 0; } + + .replace { + display: none; + } } .right { .prev { margin-left: 0; } + + .replace { + display: none; + } } } } .phone { + // Replace mode + .searchbar.document.replace { + height: 88px; + + .left { + margin-top: -44px; + } + + .center { + .searchbar-input { + margin: 8px 0; + } + + .replace { + display: block; + } + } + + .right { + > .replace { + display: flex; + } + } + } + + // Search mode .searchbar.document { .left, .center, @@ -38,12 +93,20 @@ content: none; } } + + .replace { + display: none; + } } .right { > p { margin: 0; } + + > .replace { + display: none; + } } } } diff --git a/apps/presentationeditor/mobile/resources/less/material/_search.less b/apps/presentationeditor/mobile/resources/less/material/_search.less index b2b0bc97e..42e5d041f 100644 --- a/apps/presentationeditor/mobile/resources/less/material/_search.less +++ b/apps/presentationeditor/mobile/resources/less/material/_search.less @@ -1,11 +1,27 @@ // Search .tablet { - .searchbar.document { - .left { - min-width: 15px; + // Replace mode + .searchbar.document.replace { + .center { + > .replace { + display: flex; + } } + .right { + .replace { + display: flex; + } + } + + .link.replace { + font-size: 16px; + } + } + + // Search mode + .searchbar.document { .center { width: 100%; display: flex; @@ -19,6 +35,16 @@ padding: 0; } } + + > .replace { + display: none; + } + } + + .right { + .replace { + display: none; + } } } } @@ -26,6 +52,32 @@ @phoneSearchHeight: 48px; .phone { + // Replace mode + .searchbar.document.replace { + height: @phoneSearchHeight * 2; + + .link.replace { + font-size: 16px; + } + + .left { + margin-top: -@phoneSearchHeight; + } + + .center { + .replace { + display: block; + } + } + + .right { + > .replace { + display: flex; + } + } + } + + // Search mode .searchbar.document { .left, .center, @@ -34,7 +86,7 @@ } .left { - min-width: 15px; + //min-width: 15px; } .center { @@ -45,6 +97,10 @@ .searchbar { padding: 0; } + + .replace { + display: none; + } } .right { @@ -55,6 +111,10 @@ height: @phoneSearchHeight; } } + + > .replace { + display: none; + } } } } \ No newline at end of file