jenkins-bot has submitted this change and it was merged.

Change subject: Fix various annoyances in new search overlay
......................................................................


Fix various annoyances in new search overlay

* Show virtual keyboard when overlay opens on Android devices
* Hide virtual keyboard when scrolling starts
* Don't trigger search when closing virtual keyboard
* Cache previous search results so that when user hits backspace, we
  don't send a new query
* Remove cursor: pointer for .page-list which caused the whole list to
  be highlighted on tap in search, watchlist and other .page-lists (at
  least on Android)

Bug: 58246
Change-Id: I1b8b5ce86431c76ba204b7c7ea4a127c6b77e13e
---
M javascripts/common/Overlay.js
M javascripts/modules/searchNew/SearchApi.js
M javascripts/modules/searchNew/SearchOverlay.js
M javascripts/modules/searchNew/search.js
M less/common/pagelist.less
5 files changed, 102 insertions(+), 69 deletions(-)

Approvals:
  Jdlrobson: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/javascripts/common/Overlay.js b/javascripts/common/Overlay.js
index 21aaa72..63672ed 100644
--- a/javascripts/common/Overlay.js
+++ b/javascripts/common/Overlay.js
@@ -38,20 +38,20 @@
                                ev.stopPropagation();
                        } );
                },
-               show: function() {
+
+               _hideOnRoute: function() {
                        var self = this;
+                       M.router.one( 'route', function( ev ) {
+                               if ( !self.hide() ) {
+                                       ev.preventDefault();
+                                       self._hideOnRoute();
+                               }
+                       } );
+               },
 
-                       function hideOnRoute() {
-                               M.router.one( 'route', function( ev ) {
-                                       if ( !self.hide() ) {
-                                               ev.preventDefault();
-                                               hideOnRoute();
-                                       }
-                               } );
-                       }
-
+               show: function() {
                        if ( this.closeOnBack ) {
-                               hideOnRoute();
+                               this._hideOnRoute();
                        }
 
                        // FIXME: prevent zooming within overlays but don't 
break the rendering!
diff --git a/javascripts/modules/searchNew/SearchApi.js 
b/javascripts/modules/searchNew/SearchApi.js
index a31dca9..b72663e 100644
--- a/javascripts/modules/searchNew/SearchApi.js
+++ b/javascripts/modules/searchNew/SearchApi.js
@@ -28,24 +28,37 @@
        }
 
        SearchApi = Api.extend( {
+               initialize: function() {
+                       this._super();
+                       this.searchCache = {};
+               },
+
                search: function( query ) {
-                       return this.get( {
-                               search: query,
-                               action: 'opensearch',
-                               namespace: 0,
-                               limit: 15
-                       } ).then( function( data ) {
-                               return {
-                                       query: data[0],
-                                       results: $.map( data[1], function( 
title ) {
-                                               return {
-                                                       heading: 
highlightSearchTerm( title, query ),
-                                                       title: title,
-                                                       url: mw.util.getUrl( 
title )
-                                               };
-                                       } )
-                               };
-                       } );
+                       if ( !this.searchCache[query] ) {
+                               this.searchCache[query] = this.get( {
+                                       search: query,
+                                       action: 'opensearch',
+                                       namespace: 0,
+                                       limit: 15
+                               } ).then( function( data ) {
+                                       return {
+                                               query: data[0],
+                                               results: $.map( data[1], 
function( title ) {
+                                                       return {
+                                                               heading: 
highlightSearchTerm( title, query ),
+                                                               title: title,
+                                                               url: 
mw.util.getUrl( title )
+                                                       };
+                                               } )
+                                       };
+                               } );
+                       }
+
+                       return this.searchCache[query];
+               },
+
+               isCached: function( query ) {
+                       return !!this.searchCache[query];
                }
        } );
 
diff --git a/javascripts/modules/searchNew/SearchOverlay.js 
b/javascripts/modules/searchNew/SearchOverlay.js
index be4f3d8..e0081fd 100644
--- a/javascripts/modules/searchNew/SearchOverlay.js
+++ b/javascripts/modules/searchNew/SearchOverlay.js
@@ -3,7 +3,6 @@
        var
                OverlayNew = M.require( 'OverlayNew' ),
                SearchApi = M.require( 'modules/searchNew/SearchApi' ),
-               KEY_ENTER = 13,
                SEARCH_DELAY = 500,
                SearchOverlay;
 
@@ -18,11 +17,19 @@
                        searchContentNoResultsMsg: mw.msg( 
'mobile-frontend-search-content-no-results' ),
                        action: mw.config.get( 'wgScript' )
                },
-               closeOnBack: true,
+               closeOnBack: false,
 
                initialize: function( options ) {
+                       var self = this;
                        this._super( options );
                        this.api = new SearchApi();
+
+                       // FIXME: horrible, remove when we get overlay manager
+                       // we need this because of the focus/delay hack in 
search.js
+                       M.router.one( 'route', function() {
+                               self.closeOnBack = true;
+                               self._hideOnRoute();
+                       } );
                },
 
                postRender: function( options ) {
@@ -33,13 +40,8 @@
 
                        this._super( options );
 
-                       this.$input = this.$( 'input' ).on( 'input', function( 
ev ) {
-                               if ( ev.which === KEY_ENTER ) {
-                                       $form.submit();
-                               } else {
-                                       self.performSearch();
-                               }
-
+                       this.$input = this.$( 'input' ).on( 'input', function() 
{
+                               self.performSearch();
                                $clear.toggle( self.$input.val() !== '' );
                        } );
 
@@ -54,6 +56,7 @@
                                // can't use $.proxy because it would pass ev 
to submit() which would
                                // be treated as alternative form data
                                on( M.tapEvent( 'click' ), function() {
+                                       window.history.back();
                                        $form.submit();
                                } );
 
@@ -63,6 +66,12 @@
                        } );
                        this.$( '> div' ).on( M.tapEvent( 'click' ), function( 
ev ) {
                                ev.stopPropagation();
+                       } );
+
+                       // hide the keyboard when scrolling starts (avoid weird 
situation when
+                       // user taps on an item, the keyboard hides and wrong 
item is clicked)
+                       this.$( '.results' ).on( 'touchstart mousedown', 
function() {
+                               self.$input.blur();
                        } );
                },
 
@@ -77,34 +86,40 @@
                                query = this.$input.val(),
                                $results = this.$( '.results' );
 
-                       this.api.abort();
-                       clearTimeout( this.timer );
-                       self.$searchContent.hide();
-                       $results.empty();
+                       // it seems the input event can be fired when virtual 
keyboard is closed
+                       // (Chrome for Android)
+                       if ( query !== this.lastQuery ) {
+                               this.api.abort();
+                               clearTimeout( this.timer );
+                               self.$searchContent.hide();
+                               $results.empty();
 
-                       if ( query.length ) {
-                               $results.addClass( 'loading' );
+                               if ( query.length ) {
+                                       $results.addClass( 'loading' );
 
-                               this.timer = setTimeout( function() {
-                                       self.api.search( query ).done( 
function( data ) {
-                                               // check if we're getting the 
rights response in case of out of
-                                               // order responses (need to get 
the current value of the input)
-                                               if ( data.query === 
self.$input.val() ) {
-                                                       self.$searchContent.
-                                                               show().
-                                                               find( 'p' ).
-                                                               hide().
-                                                               filter( 
data.results.length ? '.with-results' : '.without-results' ).
-                                                               show();
-                                                       $results.
-                                                               removeClass( 
'loading' ).
-                                                               html( 
M.template.get( 'articleList' ).render( { pages: data.results } ) );
-                                                       M.emit( 
'search-results', self, data.results );
-                                               }
-                                       } );
-                               }, SEARCH_DELAY );
-                       } else {
-                               $results.removeClass( 'loading' );
+                                       this.timer = setTimeout( function() {
+                                               self.api.search( query ).done( 
function( data ) {
+                                                       // check if we're 
getting the rights response in case of out of
+                                                       // order responses 
(need to get the current value of the input)
+                                                       if ( data.query === 
self.$input.val() ) {
+                                                               
self.$searchContent.
+                                                                       show().
+                                                                       find( 
'p' ).
+                                                                       hide().
+                                                                       filter( 
data.results.length ? '.with-results' : '.without-results' ).
+                                                                       show();
+                                                               $results.
+                                                                       
removeClass( 'loading' ).
+                                                                       html( 
M.template.get( 'articleList' ).render( { pages: data.results } ) );
+                                                               M.emit( 
'search-results', self, data.results );
+                                                       }
+                                               } );
+                                       }, this.api.isCached( query ) ? 0 : 
SEARCH_DELAY );
+                               } else {
+                                       $results.removeClass( 'loading' );
+                               }
+
+                               this.lastQuery = query;
                        }
                }
        } );
diff --git a/javascripts/modules/searchNew/search.js 
b/javascripts/modules/searchNew/search.js
index c8c5865..9d84f8d 100644
--- a/javascripts/modules/searchNew/search.js
+++ b/javascripts/modules/searchNew/search.js
@@ -3,9 +3,19 @@
        var SearchOverlay = M.require( 'modules/searchNew/SearchOverlay' );
 
        // FIXME change when micro.tap.js in stable
+       //
        // don't use focus event 
(https://bugzilla.wikimedia.org/show_bug.cgi?id=47499)
+       //
+       // focus() (see SearchOverlay#show) opens virtual keyboard only if 
triggered
+       // from user context event, so using it in route callback won't work
+       // 
http://stackoverflow.com/questions/6837543/show-virtual-keyboard-on-mobile-phones-in-javascript
        $( '#searchInput' ).on( M.tapEvent( 'touchend mouseup' ), function() {
-               M.router.navigate( 'search' );
+               new SearchOverlay().show();
+               // without this delay, the keyboard will not show up on 
Android...
+               // (tested in Chrome for Android)
+               setTimeout( function() {
+                       M.router.navigate( '/search' );
+               }, 300 );
        } );
 
        // FIXME: ugly hack that removes search from browser history when 
navigating
@@ -25,9 +35,5 @@
                        } );
                } );
        }
-
-       M.router.route( /^search$/, function() {
-               new SearchOverlay().show();
-       } );
 
 }( mw.mobileFrontend, jQuery ));
diff --git a/less/common/pagelist.less b/less/common/pagelist.less
index 0e652b6..2715259 100644
--- a/less/common/pagelist.less
+++ b/less/common/pagelist.less
@@ -44,7 +44,6 @@
 //
 // Styleguide 5.
 .page-list {
-       cursor: pointer;
        // needed for rotated watchstars to avoid horizontal scrollbar
        overflow: hidden;
 

-- 
To view, visit https://gerrit.wikimedia.org/r/101466
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I1b8b5ce86431c76ba204b7c7ea4a127c6b77e13e
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: JGonera <[email protected]>
Gerrit-Reviewer: JGonera <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to