* @cfg {boolean} [showRedirectTargets=true] Show the targets of redirects
* @cfg {boolean} [showImages] Show page images
* @cfg {boolean} [showDescriptions] Show page descriptions
+ * @cfg {boolean} [showMissing=true] Show missing pages
* @cfg {boolean} [excludeCurrentPage] Exclude the current page from suggestions
* @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
* the widget will marks itself red for invalid inputs, including an empty query).
this.showRedirectTargets = config.showRedirectTargets !== false;
this.showImages = !!config.showImages;
this.showDescriptions = !!config.showDescriptions;
+ this.showMissing = config.showMissing !== false;
this.excludeCurrentPage = !!config.excludeCurrentPage;
this.validateTitle = config.validateTitle !== undefined ? config.validateTitle : true;
this.cache = config.cache;
this.api = config.api || new mw.Api();
+ // Supports: IE10, FF28, Chrome23
+ this.compare = window.Intl && Intl.Collator ?
+ new Intl.Collator( mw.config.get( 'wgContentLanguage' ), { sensitivity: 'base' } ).compare :
+ null;
// Initialization
this.$element.addClass( 'mw-widget-titleWidget' );
// Do nothing. This is just so OOUI doesn't break due to abort being undefined.
} };
- if ( mw.Title.newFromText( query ) ) {
- return this.getInterwikiPrefixesPromise().then( function ( interwikiPrefixes ) {
- var params,
- interwiki = query.substring( 0, query.indexOf( ':' ) );
- if (
- interwiki && interwiki !== '' &&
- interwikiPrefixes.indexOf( interwiki ) !== -1
- ) {
- return $.Deferred().resolve( { query: {
- pages: [ {
- title: query
- } ]
- } } ).promise( promiseAbortObject );
- } else {
- params = {
- action: 'query',
- prop: [ 'info', 'pageprops' ],
- generator: 'prefixsearch',
- gpssearch: query,
- gpsnamespace: widget.namespace !== null ? widget.namespace : undefined,
- gpslimit: widget.limit,
- ppprop: 'disambiguation'
- };
- if ( widget.showRedirectTargets ) {
- params.redirects = true;
- }
- if ( widget.showImages ) {
- params.prop.push( 'pageimages' );
- params.pithumbsize = 80;
- params.pilimit = widget.limit;
- }
- if ( widget.showDescriptions ) {
- params.prop.push( 'pageterms' );
- params.wbptterms = 'description';
- }
- req = api.get( params );
- promiseAbortObject.abort = req.abort.bind( req ); // TODO ew
- return req.then( function ( ret ) {
- if ( ret.query === undefined ) {
- ret = api.get( { action: 'query', titles: query } );
- promiseAbortObject.abort = ret.abort.bind( ret );
- }
- return ret;
- } );
- }
- } ).promise( promiseAbortObject );
- } else {
+ if ( !mw.Title.newFromText( query ) ) {
// Don't send invalid titles to the API.
// Just pretend it returned nothing so we can show the 'invalid title' section
return $.Deferred().resolve( {} ).promise( promiseAbortObject );
}
+
+ return this.getInterwikiPrefixesPromise().then( function ( interwikiPrefixes ) {
+ var interwiki = query.substring( 0, query.indexOf( ':' ) );
+ if (
+ interwiki && interwiki !== '' &&
+ interwikiPrefixes.indexOf( interwiki ) !== -1
+ ) {
+ return $.Deferred().resolve( { query: {
+ pages: [ {
+ title: query
+ } ]
+ } } ).promise( promiseAbortObject );
+ } else {
+ req = api.get( widget.getApiParams( query ) );
+ promiseAbortObject.abort = req.abort.bind( req ); // TODO ew
+ return req.then( function ( ret ) {
+ if ( widget.showMissing && ret.query === undefined ) {
+ ret = api.get( { action: 'query', titles: query } );
+ promiseAbortObject.abort = ret.abort.bind( ret );
+ }
+ return ret;
+ } );
+ }
+ } ).promise( promiseAbortObject );
+ };
+
+ /**
+ * Get API params for a given query
+ *
+ * @param {string} query User query
+ * @return {Object} API params
+ */
+ mw.widgets.TitleWidget.prototype.getApiParams = function ( query ) {
+ var params = {
+ action: 'query',
+ prop: [ 'info', 'pageprops' ],
+ generator: 'prefixsearch',
+ gpssearch: query,
+ gpsnamespace: this.namespace !== null ? this.namespace : undefined,
+ gpslimit: this.limit,
+ ppprop: 'disambiguation'
+ };
+ if ( this.showRedirectTargets ) {
+ params.redirects = true;
+ }
+ if ( this.showImages ) {
+ params.prop.push( 'pageimages' );
+ params.pithumbsize = 80;
+ params.pilimit = this.limit;
+ }
+ if ( this.showDescriptions ) {
+ params.prop.push( 'pageterms' );
+ params.wbptterms = 'description';
+ }
+ return params;
};
/**
for ( index in data.pages ) {
suggestionPage = data.pages[ index ];
+
// When excludeCurrentPage is set, don't list the current page unless the user has type the full title
if ( this.excludeCurrentPage && suggestionPage.title === currentPageName && suggestionPage.title !== titleObj.getPrefixedText() ) {
continue;
imageUrl: OO.getProp( suggestionPage, 'thumbnail', 'source' ),
description: OO.getProp( suggestionPage, 'terms', 'description' ),
// Sort index
- index: suggestionPage.index
+ index: suggestionPage.index,
+ originalData: suggestionPage
};
// Throw away pages from wrong namespaces. This can happen when 'showRedirectTargets' is true
disambiguation: false,
description: mw.msg( 'mw-widgets-titleinput-description-redirect', suggestionPage.title ),
// Sort index, just below its target
- index: suggestionPage.index + 0.5
+ index: suggestionPage.index + 0.5,
+ originalData: suggestionPage
};
titles.push( redirects[ i ] );
}
} );
// If not found, run value through mw.Title to avoid treating a match as a
- // mismatch where normalisation would make them matching (bug 48476)
+ // mismatch where normalisation would make them matching (T50476)
pageExistsExact = (
Object.prototype.hasOwnProperty.call( pageData, this.getQueryValue() ) &&
for ( i = 0, len = titles.length; i < len; i++ ) {
page = pageData[ titles[ i ] ] || {};
- items.push( new mw.widgets.TitleOptionWidget( this.getOptionWidgetData( titles[ i ], page ) ) );
+ items.push( this.createOptionWidget( this.getOptionWidgetData( titles[ i ], page ) ) );
}
return items;
};
+ /**
+ * Create a menu option widget with specified data
+ *
+ * @param {Object} data Data for option widget
+ * @return {OO.ui.MenuOptionWidget} Data for option widget
+ */
+ mw.widgets.TitleWidget.prototype.createOptionWidget = function ( data ) {
+ return new mw.widgets.TitleOptionWidget( data );
+ };
+
/**
* Get menu option widget data from the title and page data
*
mwTitle.getRelativeText( this.namespace ) :
title,
url: mwTitle.getUrl(),
+ showImages: this.showImages,
imageUrl: this.showImages ? data.imageUrl : null,
description: this.showDescriptions ? description : null,
missing: data.missing,
redirect: data.redirect,
disambiguation: data.disambiguation,
- query: this.getQueryValue()
+ query: this.getQueryValue(),
+ compare: this.compare
};
};