Thiemo Mättig (WMDE) has submitted this change and it was merged. Change subject: Implemented pagesuggester widget ......................................................................
Implemented pagesuggester widget (bug 68905) For now, $.wikibase.pagesuggester features the functionality extracted from SitePageInterface. Change-Id: I44a22407c6c31c4b6b1b5f91700c1b7381d0fdec --- M lib/WikibaseLib.hooks.php M lib/resources/Resources.php A lib/resources/jquery.wikibase/jquery.wikibase.pagesuggester.js M lib/resources/wikibase.ui.PropertyEditTool.EditableValue.Interface.js M lib/resources/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.js A lib/tests/qunit/jquery.wikibase/jquery.wikibase.pagesuggester.tests.js M lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.tests.js M lib/tests/qunit/wikibase.ui.SiteLinksEditTool.tests.js 8 files changed, 235 insertions(+), 85 deletions(-) Approvals: WikidataJenkins: Verified Thiemo Mättig (WMDE): Looks good to me, approved jenkins-bot: Checked diff --git a/lib/WikibaseLib.hooks.php b/lib/WikibaseLib.hooks.php index 1b9868e..c1b4263 100644 --- a/lib/WikibaseLib.hooks.php +++ b/lib/WikibaseLib.hooks.php @@ -186,6 +186,16 @@ ), ); + $testModules['qunit']['jquery.wikibase.pagesuggester.tests'] = $moduleBase + array( + 'scripts' => array( + 'tests/qunit/jquery.wikibase/jquery.wikibase.pagesuggester.tests.js' + ), + 'dependencies' => array( + 'jquery', + 'jquery.wikibase.pagesuggester', + ), + ); + $testModules['qunit']['jquery.wikibase.referenceview.tests'] = $moduleBase + array( 'scripts' => array( 'tests/qunit/jquery.wikibase/jquery.wikibase.referenceview.tests.js', diff --git a/lib/resources/Resources.php b/lib/resources/Resources.php index a87d710..f64c76b 100644 --- a/lib/resources/Resources.php +++ b/lib/resources/Resources.php @@ -320,6 +320,7 @@ 'jquery.ui.suggester', 'util.inherit', 'jquery.wikibase.entityselector', + 'jquery.wikibase.pagesuggester', 'jquery.wikibase.toolbareditgroup', 'jquery.wikibase.siteselector', 'mediawiki.api', @@ -497,6 +498,16 @@ ) ), + 'jquery.wikibase.pagesuggester' => $moduleTemplate + array( + 'scripts' => array( + 'jquery.wikibase/jquery.wikibase.pagesuggester.js', + ), + 'dependencies' => array( + 'jquery.ui.suggester', + 'wikibase.sites', + ), + ), + 'jquery.wikibase.listview' => $moduleTemplate + array( 'scripts' => array( 'jquery.wikibase/jquery.wikibase.listview.js', diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.pagesuggester.js b/lib/resources/jquery.wikibase/jquery.wikibase.pagesuggester.js new file mode 100644 index 0000000..13e3e93 --- /dev/null +++ b/lib/resources/jquery.wikibase/jquery.wikibase.pagesuggester.js @@ -0,0 +1,115 @@ +/** + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + */ +( function( $, mw, wb ) { + 'use strict'; + +/** + * Suggester enhanced input element for selecting a site link's page. + * @since 0.5 + * + * @option {string} [siteId] + * + * @option {string} [pageName] + */ +$.widget( 'wikibase.pagesuggester', $.ui.suggester, { + /** + * @see jQuery.ui.suggester.options + */ + options: { + siteId: null, + pageName: null + }, + + /** + * @see jQuery.ui.suggester._create + */ + _create: function() { + var self = this; + + if( this.option( 'pageName' ) ) { + this.element.val( this.option( 'pageName' ) ); + } + + if( !this.option( 'source' ) ) { + this.option( 'source', this._request() ); + } + + $.ui.suggester.prototype._create.call( this ); + + this.element + .on( this.widgetEventPrefix + 'change.' + this.widgetName, function( event ) { + if( $.trim( self.element.val() ) !== self.option( 'pageName' ) ) { + self.option( 'pageName', $.trim( self.element.val() ) ); + } + } ); + }, + + /** + * @see jQuery.ui.suggester._setOption + */ + _setOption: function( key, value ) { + $.ui.suggester.prototype._setOption.apply( this, arguments ); + + if( key === 'siteId' ) { + this._trigger( 'change' ); + } + + if( key === 'pageName' ) { + this.element.val( this.option( 'pageName' ) ); + this._trigger( 'change' ); + } + }, + + /** + * @see $.ui.suggester.search + */ + search: function( event ) { + // Reject searching when there is no siteId specified: + if( !this.option( 'siteId' ) ) { + var deferred = $.Deferred(); + return deferred.reject( 'siteId-undefined' ).promise(); + } + return $.ui.suggester.prototype.search.apply( this, arguments ); + }, + + /** + * @see jQuery.ui.suggester._getSuggestions + * + * @return {Object} jQuery.Promise + * Resolved parameters: + * - {string[]} + * - {string} + * Rejected parameters: + * - {string} + */ + _request: function() { + var self = this; + + return function( term ) { + var deferred = $.Deferred(); + + $.ajax( { + url: wb.sites.getSite( self.option( 'siteId' ) ).getApi(), + dataType: 'jsonp', + data: { + search: term, + action: 'opensearch' + }, + timeout: 8000 + } ) + .done( function( response ) { + deferred.resolve( response[1], response[0] ); + } ) + .fail( function( jqXHR, textStatus ) { + // Since this is a JSONP request, this will always fail with a timeout... + deferred.reject( textStatus ); + } ); + + return deferred.promise(); + }; + } + +} ); +}( jQuery, mediaWiki, wikibase ) ); diff --git a/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.Interface.js b/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.Interface.js index 42e4f02..11b225a 100644 --- a/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.Interface.js +++ b/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.Interface.js @@ -199,15 +199,12 @@ */ updateLanguageAttributes: function() { // apply subject's language attributes or attributes according to user language. - if ( this._inputElem !== null ) { - var lang = this.getSubject().attr( 'lang' ); - if ( lang === undefined ) { - lang = mw.config.get( 'wgUserLanguage' ); - } + if( this._inputElem ) { + var lang = this.getSubject().attr( 'lang' ) || mw.config.get( 'wgUserLanguage' ); - // Get the computed dir from CSS, to make sure that it's explicit and not 'auto', which - // is less useful for <input>: - var dir = this.getSubject().css( 'direction' ); + var dir = ( $.uls && $.uls.data.getDir( lang ) ) + || this.getSubject().css( 'direction' ) + || 'auto'; this._inputElem.attr( 'lang', lang ).attr( 'dir', dir ); } diff --git a/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.js b/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.js index d8a96b2..bd352cf 100644 --- a/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.js +++ b/lib/resources/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.js @@ -20,18 +20,6 @@ */ wb.ui.PropertyEditTool.EditableValue.SitePageInterface = util.inherit( PARENT, { /** - * Url the AJAX request will point to (if ajax should be used to define a result set). - * @type {string} - */ - url: null, - - /** - * Additional params for the AJAX request (if ajax should be used to define a result set) - * @type {Object} - */ - ajaxParams: null, - - /** * Information for which site this autocomplete interface should serve input suggestions * @var wikibase.Site */ @@ -69,32 +57,36 @@ var $input = PARENT.prototype._buildInputElement.call( this ); - $input.suggester( { - source: this._request() + $input.pagesuggester( { + siteId: this._site ? this._site.getId() : null } ); this._initBadgeEditing(); $input - .on( 'keyup close', function( event ) { + .on( 'pagesuggesterchange pagesuggesterclose', function( event ) { + this._currentResults = []; + + var menu = $input.data( 'pagesuggester' ).option( 'menu' ); + + if( menu ) { + $.each( menu.option( 'items' ), function() { + self._currentResults.push( this.getValue() ); + } ); + } + // The input element might have been removed already with the event still being in the // loop: if ( !self.isDisabled() && self._inputElem !== null ) { self._onInputRegistered(); } } ) - .on( 'suggesterresponse suggesterselect', function( event, results ) { - self._currentResults = results; - if ( !self.isDisabled() ) { - self._onInputRegistered(); - } - } ) - .on( 'suggestererror', function( event, textStatus, errorThrown ) { - if ( textStatus !== 'abort' ) { + .on( 'pagesuggestererror', function( event, message ) { + if ( message !== 'abort' ) { var error = { - code: textStatus, + code: message, message: mw.msg( 'wikibase-error-autocomplete-connection' ), - detailedMessage: mw.msg( 'wikibase-error-autocomplete-response', errorThrown ) + detailedMessage: mw.msg( 'wikibase-error-autocomplete-response', message ) }; self._inputElem.wbtooltip( { content: error, @@ -166,36 +158,6 @@ }, /** - * Generates the suggester source function. - */ - _request: function() { - var self = this; - - return function( term ) { - var deferred = $.Deferred(); - - $.ajax( { - url: self._site.getApi(), - dataType: 'jsonp', - data: { - search: term, - action: 'opensearch' - }, - timeout: 8000 - } ) - .done( function( response ) { - deferred.resolve( response[1], response[0] ); - } ) - .fail( function( jqXHR, textStatus ) { - // Since this is a JSONP request, this will always fail with a timeout... - deferred.reject( textStatus ); - } ); - - return deferred.promise(); - }; - }, - - /** * Allows to set the site, the pages should be selected from. * * @param wb.Site site @@ -207,6 +169,10 @@ this._site = site; + if( this._inputElem ) { + this._inputElem.data( 'pagesuggester' ).option( 'siteId', site.getId() ); + } + this._currentResults = []; // empty current suggestions... }, @@ -215,23 +181,9 @@ */ updateLanguageAttributes: function() { PARENT.prototype.updateLanguageAttributes.call( this ); - // apply input's language attributes or attributes according to user language - if ( this._inputElem !== null ) { - var lang = this._inputElem.attr( 'lang' ); - if ( lang === undefined ) { - lang = mw.config.get( 'wgUserLanguage' ); - } - var dir = this._inputElem.attr( 'dir' ); - if ( dir === undefined ) { - if ( wb.getLanguages()[lang] !== undefined ) { - dir = $.uls.data.getDir( lang ); - } - } - if ( dir === undefined ) { - dir = 'auto'; // Shouldn't happen, but go figure - } - this._inputElem.data( 'suggester' ).options.menu.element - .attr( 'lang', lang ).attr( 'dir', dir ); + + if( this._inputElem ) { + this._inputElem.data( 'pagesuggester' ).repositionMenu(); } }, @@ -328,9 +280,9 @@ var success = PARENT.prototype._setState.call( this, state ); if( this._inputElem !== null ) { if( state === this.STATE.DISABLED ) { - this._inputElem.data( 'suggester').disable(); + this._inputElem.data( 'pagesuggester').disable(); } else { - this._inputElem.data( 'suggester').enable(); + this._inputElem.data( 'pagesuggester').enable(); } } return success; diff --git a/lib/tests/qunit/jquery.wikibase/jquery.wikibase.pagesuggester.tests.js b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.pagesuggester.tests.js new file mode 100644 index 0000000..abd1970 --- /dev/null +++ b/lib/tests/qunit/jquery.wikibase/jquery.wikibase.pagesuggester.tests.js @@ -0,0 +1,65 @@ +/** + * @licence GNU GPL v2+ + * @author H. Snater < mediaw...@snater.com > + */ +( function( $, QUnit ) { + 'use strict'; + + /** + * Factory creating a jQuery.wikibase.pagesuggester widget suitable for testing. + * + * @param {Object} [options] + */ + var newTestPageSuggester = function( options ) { + return $( '<input/>' ) + .addClass( 'test_pagesuggester') + .appendTo( 'body' ) + .pagesuggester( options ); + }; + + QUnit.module( 'jquery.wikibase.pagesuggester', { + teardown: function() { + var $pageSuggester = $( '.test_pagesuggester' ), + pageSuggester = $pageSuggester.data( 'pagesuggester' ); + if( pageSuggester ) { + pageSuggester.destroy(); + } + $pageSuggester.remove(); + } + } ); + + QUnit.test( 'Create', function( assert ) { + var $pageSuggester = newTestPageSuggester(); + + assert.ok( + $pageSuggester.data( 'pagesuggester' ) instanceof $.wikibase.pagesuggester, + 'Instantiated page suggester.' + ); + } ); + + QUnit.test( 'Try searching for suggestions without a site', 1, function( assert ) { + var $pageSuggester = newTestPageSuggester(), + pageSuggester = $pageSuggester.data( 'pagesuggester' ); + + QUnit.stop(); + + pageSuggester.search() + .done( function() { + assert.ok( + false, + 'Searching successful although supposed to fail.' + ); + } ) + .fail( function() { + assert.ok( + true, + 'Searching failed as expected.' + ); + } ) + .always( function() { + QUnit.start(); + } ); + + } ); + +}( jQuery, QUnit ) ); diff --git a/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.tests.js b/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.tests.js index 47d7d9e..4a7e821 100644 --- a/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.tests.js +++ b/lib/tests/qunit/wikibase.ui.PropertyEditTool.EditableValue.SitePageInterface.tests.js @@ -113,13 +113,13 @@ this.subject.setLanguageAttributes( this.language.rtl.code, this.language.rtl.dir ); equal( - this.subject._inputElem.data( 'suggester' ).options.menu.element.attr( 'lang' ), + this.subject._inputElem.data( 'pagesuggester' ).options.menu.element.attr( 'lang' ), this.language.rtl.code, 'assign rtl language code to auto-complete menu' ); equal( - this.subject._inputElem.data( 'suggester' ).options.menu.element.attr( 'dir' ), + this.subject._inputElem.data( 'pagesuggester' ).options.menu.element.attr( 'dir' ), this.language.rtl.dir, 'assign rtl language direction to auto-complete menu' ); diff --git a/lib/tests/qunit/wikibase.ui.SiteLinksEditTool.tests.js b/lib/tests/qunit/wikibase.ui.SiteLinksEditTool.tests.js index 5309dc3..da87352 100644 --- a/lib/tests/qunit/wikibase.ui.SiteLinksEditTool.tests.js +++ b/lib/tests/qunit/wikibase.ui.SiteLinksEditTool.tests.js @@ -89,7 +89,7 @@ // set result set for validation newValue.sitePageInterface._sites = siteLink[1]; - newValue.sitePageInterface._inputElem.data( 'suggester' ).option( 'source', siteLink[1] ); + newValue.sitePageInterface._inputElem.data( 'pagesuggester' ).option( 'source', siteLink[1] ); // pretend API success var fakeApiResponse = { entity: { sitelinks: {} } }; -- To view, visit https://gerrit.wikimedia.org/r/151097 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I44a22407c6c31c4b6b1b5f91700c1b7381d0fdec Gerrit-PatchSet: 11 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Adrian Lang <adrian.l...@wikimedia.de> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Hoo man <h...@online.de> Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: WikidataJenkins <wikidata-servi...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits