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

Change subject: Pageselector widget
......................................................................


Pageselector widget

* Widget: ext.cx.pageselector
* MobileFrontend-like widget to search pages.
* Shows thumbnail, page title, and page description for every
  page that match with the search query.
* Pages can be selected without using mouse too.
* Inherits the language and directionality of the input field to
  which the widget binds
* Can search and select pages from local wiki or any wiki with
  the help of optional mw.Api passed with correct URL

Bug: T87593
Change-Id: Ibf06d820c9554cb85798e1f4695e070b6a7909c3
---
M Resources.php
M modules/source/ext.cx.source.selector.js
A modules/widgets/pageselector/ext.cx.pageselector.js
A modules/widgets/pageselector/ext.cx.pageselector.less
4 files changed, 278 insertions(+), 7 deletions(-)

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



diff --git a/Resources.php b/Resources.php
index 6ccffd7..a99c1da 100644
--- a/Resources.php
+++ b/Resources.php
@@ -211,6 +211,7 @@
                'jquery.uls.compact',
                'mediawiki.ui.button',
                'ext.cx.widgets.overlay',
+               'ext.cx.pageselector',
        ),
        'messages' => array(
                'cx-sourceselector-dialog-new-translation',
@@ -229,6 +230,18 @@
        ),
 ) + $resourcePaths;
 
+$wgResourceModules['ext.cx.pageselector'] = array(
+       'scripts' =>  array(
+               'widgets/pageselector/ext.cx.pageselector.js'
+       ),
+       'styles' => array(
+               'widgets/pageselector/ext.cx.pageselector.less',
+       ),
+       'dependencies' => array(
+               'mediawiki.api',
+       ),
+) + $resourcePaths;
+
 $wgResourceModules['ext.cx.translation'] = array(
        'scripts' => array(
                'translation/ext.cx.translation.js',
diff --git a/modules/source/ext.cx.source.selector.js 
b/modules/source/ext.cx.source.selector.js
index 2cec8fd..f98abc8 100644
--- a/modules/source/ext.cx.source.selector.js
+++ b/modules/source/ext.cx.source.selector.js
@@ -248,12 +248,6 @@
                // The dialog will be unitialized until the first click.
                this.$trigger.click( $.proxy( this.show, this ) );
 
-               // Source title input input (search titles)
-               this.$sourceTitleInput.on(
-                       'input',
-                       $.debounce( 100, false, $.proxy( this.searchHandler, 
this ) )
-               );
-
                // Source title input or target title input, input or search 
(check)
                this.$dialog.on(
                        'input blur',
@@ -290,6 +284,11 @@
         */
        CXSourceSelector.prototype.sourceLanguageChangeHandler = function ( 
language ) {
                this.setSourceLanguage( language );
+               this.$sourceTitleInput.attr( {
+                       lang: language,
+                       dir: $.uls.data.getDir( language )
+               } );
+               this.$sourcePageSelector.setApi( this.siteMapper.getApi( 
language ) );
                this.check();
        };
 
@@ -840,7 +839,9 @@
                $sourceTitleInputContainer = $( '<div>' )
                        .addClass( 'cx-sourceselector-dialog__title' )
                        .append( this.$sourceTitleInput );
-
+               this.$sourcePageSelector = new mw.PageSelector( 
this.$sourceTitleInput, {
+                       api: this.siteMapper.getApi( this.getSourceLanguage() )
+               } );
                this.$targetTitleInput = $( '<input>' )
                        .attr( {
                                name: 'targetTitle',
diff --git a/modules/widgets/pageselector/ext.cx.pageselector.js 
b/modules/widgets/pageselector/ext.cx.pageselector.js
new file mode 100644
index 0000000..3989a54
--- /dev/null
+++ b/modules/widgets/pageselector/ext.cx.pageselector.js
@@ -0,0 +1,222 @@
+/**
+ * MediaWiki Page selector widget
+ */
+( function ( $, mw ) {
+       'use strict';
+
+       /**
+        * MediaWikiPageSelector widget
+        * @param {jQuery|HTMLElement} input field
+        * @param {Object} [options]
+        */
+       function MediaWikiPageSelector( input, options ) {
+               this.$input = $( input );
+               this.options = $.extend( {}, mw.PageSelector.defaults, options 
);
+               this.render();
+               this.listen();
+       }
+
+       /**
+        * Render the page selector
+        */
+       MediaWikiPageSelector.prototype.render = function () {
+               this.$menu = $( '<ul>' )
+                       .addClass( 'mw-pageselector-menu' )
+                       .hide();
+
+               // Append it to the body
+               $( 'body' ).append( this.$menu );
+       };
+
+       /**
+        * Set the API to use for querying pages.
+        * @param {mediawiki.Api} api MediaWiki API instance
+        */
+       MediaWikiPageSelector.prototype.setApi = function ( api ) {
+               this.options.api = api;
+       };
+
+       /**
+        * Get the pages matching the given query
+        * @param {string} input The query string
+        * @return {jQuery.Promise}
+        */
+       MediaWikiPageSelector.prototype.getPages = function ( input ) {
+               var api = this.options.api;
+
+               if ( !input || !input.trim() ) {
+                       return $.Deferred().reject();
+               }
+
+               return api.get( {
+                       action: 'query',
+                       generator: 'prefixsearch',
+                       gpssearch: input,
+                       gpslimit: 10,
+                       prop: [ 'pageimages', 'pageterms' ].join( '|' ),
+                       piprop: 'thumbnail',
+                       pithumbsize: 50,
+                       pilimit: 10,
+                       redirects: true,
+                       list: 'prefixsearch',
+                       pssearch: input,
+                       pslimit: 10
+               }, {
+                       dataType: 'jsonp',
+                       // This prevents warnings about the unrecognized 
parameter "_"
+                       cache: true
+               } );
+       };
+
+       MediaWikiPageSelector.prototype.search = function () {
+               var self = this;
+
+               this.getPages( this.$input.val().trim() ).then( function ( 
items ) {
+                       var page, pageId, pages, $resultItem;
+
+                       pages = items.query.pages;
+                       self.$menu.empty().attr( {
+                               lang: self.$input.attr( 'lang' ),
+                               dir: self.$input.attr( 'dir' )
+                       } );
+
+                       for ( pageId in pages ) {
+                               page = pages[ pageId ];
+                               $resultItem = $( '<li>' )
+                                       .append(
+                                               $( '<div>' ).addClass( 
'mw-page-title' ).text( page.title ),
+                                               $( '<div>' ).addClass( 
'mw-page-description' ).text( page.terms.description )
+                                       )
+                                       .data( 'page-title', page.title );
+                               if ( page.thumbnail ) {
+                                       $resultItem.css( {
+                                               'background-image': 'url(' + 
page.thumbnail.source + ')',
+                                               'background-size': 
page.thumbnail.width + 'px ' + page.thumbnail.height + 'px'
+                                       } );
+                               }
+                               self.$menu.append( $resultItem );
+                       }
+
+                       if ( pages ) {
+                               self.show();
+                       } else {
+                               self.hide();
+                       }
+               } );
+       };
+
+       /**
+        * Select the given page
+        * @param {jQuery} $item Menu item
+        */
+       MediaWikiPageSelector.prototype.select = function ( $item ) {
+               this.$input.val( $item.data( 'page-title' ) ).focus();
+       };
+
+       /**
+        * Show the menu when there is something in input field
+        */
+       MediaWikiPageSelector.prototype.show = function () {
+               var offset;
+
+               if ( this.$input.val().trim() ) {
+                       offset = this.$input.offset();
+                       this.$menu
+                               .css( {
+                                       left: offset.left,
+                                       top: offset.top
+                               } )
+                               .show();
+               }
+       };
+
+       /*
+        * Hide the menu.
+        */
+       MediaWikiPageSelector.prototype.hide = function () {
+               this.$menu.hide();
+       };
+
+       /**
+        * Event binding
+        */
+       MediaWikiPageSelector.prototype.listen = function () {
+               var self = this,
+                       $menu = this.$menu;
+
+               $menu.on( 'click', '> li', function () {
+                       self.select( $( this ) );
+                       self.hide();
+               } );
+
+               $menu.on( 'mouseover', '> li', function () {
+                       $( this ).addClass( 'mw-pageselector-selected' );
+               } );
+
+               $menu.on( 'mouseleave', '> li', function () {
+                       $( this ).removeClass( 'mw-pageselector-selected' );
+               } );
+
+               this.$input.one( 'focus', function () {
+                       $menu.css( 'min-width', $( this ).css( 'width' ) );
+               } );
+
+               // Hide the menu when clicked outside.
+               $( document ).on( 'click', $.proxy( this.hide, this ) );
+
+               this.$input.on( 'input', $.debounce( 250, false, $.proxy( 
this.search, this ) ) );
+
+               // Handle navigation by arrow keys and selection by enter key
+               this.$input.on( 'keydown', function ( event ) {
+                       var currentItem = 0,
+                               $items;
+
+                       if ( [ 13, 27, 38, 40 ].indexOf( event.keyCode ) < 0 ) {
+                               // Early return
+                               return;
+                       }
+
+                       $items = $menu.find( '> li' );
+                       if ( $items.length ) {
+                               self.show();
+                       }
+                       currentItem = $menu.find( '> 
li.mw-pageselector-selected' ).index();
+
+                       if ( event.keyCode === 40 ) {
+                               // Move to the next element
+                               currentItem++;
+                       }
+
+                       if ( event.keyCode === 38 ) {
+                               currentItem--;
+                       }
+
+                       if ( event.keyCode === 27 ) {
+                               // Escape handler
+                               self.hide();
+                               return false;
+                       }
+
+                       // Remove selected class from all elements
+                       $items.removeClass( 'mw-pageselector-selected' );
+                       // Add selected class to current item
+                       $items.eq( currentItem ).addClass( 
'mw-pageselector-selected' );
+                       self.select( $items.eq( currentItem ) );
+
+                       if ( event.keyCode === 13 ) {
+                               // Enter key handler
+                               self.hide();
+                               return false;
+                       }
+               } );
+       };
+
+       mw.PageSelector = MediaWikiPageSelector;
+
+       mw.PageSelector.defaults = {
+               // API to use for querying pages. By default queries the same 
wiki
+               // To query other wikis, set the ajax URL to mw.Api.
+               // Example: mw.Api( { ajax: { url: apiURL } } )
+               api: new mw.Api()
+       };
+}( jQuery, mediaWiki ) );
diff --git a/modules/widgets/pageselector/ext.cx.pageselector.less 
b/modules/widgets/pageselector/ext.cx.pageselector.less
new file mode 100644
index 0000000..7333275
--- /dev/null
+++ b/modules/widgets/pageselector/ext.cx.pageselector.less
@@ -0,0 +1,35 @@
+.mw-pageselector-menu {
+       position: absolute;
+       border: 1px solid #ccc;
+       box-shadow: 0 5px 10px rgba(0,0,0,0.2);
+       list-style: none;
+       margin: 30px 0;
+       color: black;
+       background-color: white;
+       // Show it on top of others
+       z-index: 9999;
+       max-width: 30%;
+
+       &> li {
+               border-bottom: 1px solid #eee;
+               background-repeat: no-repeat;
+               background-position: left center;
+               background-size: 50px 50px;
+               padding: 5px 5px 5px 60px;
+       }
+
+       li.mw-pageselector-selected {
+               cursor: pointer;
+               background-color: darken( white, 10% );
+       }
+
+       .mw-page-title {
+               font-size: 1em;
+       }
+
+       .mw-page-description {
+               font-size: 0.8em;
+               line-height: 1em;
+               color: #555;
+       }
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ibf06d820c9554cb85798e1f4695e070b6a7909c3
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Santhosh <santhosh.thottin...@gmail.com>
Gerrit-Reviewer: Amire80 <amir.ahar...@mail.huji.ac.il>
Gerrit-Reviewer: KartikMistry <kartik.mis...@gmail.com>
Gerrit-Reviewer: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Nikerabbit <niklas.laxst...@gmail.com>
Gerrit-Reviewer: Pginer <pgi...@wikimedia.org>
Gerrit-Reviewer: Santhosh <santhosh.thottin...@gmail.com>
Gerrit-Reviewer: Spage <sp...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to