mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiEditor
synced 2024-11-27 17:50:44 +00:00
6384498d75
In order to get a better look-up experience (images, description, redirects, and disambigutation pages listed last), swich from a custom title-autocomplete input (that used jquery.suggestions) to OOUI's standard one (which is used in a bunch of other places in MediaWiki). This means a fair bit of code can be deleted from jquery.wikiEditor.dialogs.config.js, and some of it moved to the new OOUI classes. This patch aims to be the minimum required, and so leaves a few things for subsequent patches (such as converting the other parts of the insert-link dialog to OOUI). Bug: T289214 Change-Id: I9fb7e66bf925eb9a8260d6245d2a7db54a7a2fec
147 lines
4.5 KiB
JavaScript
147 lines
4.5 KiB
JavaScript
var InsertLinkTitleOptionWidget = require( './TitleOptionWidget.js' );
|
|
|
|
/**
|
|
* A custom TitleInputWidget that adds support for external links
|
|
* (any string that starts with a protocol or `www.` and doesn't exist as a page).
|
|
*
|
|
* @class
|
|
* @extends mw.widgets.TitleInputWidget
|
|
* @constructor
|
|
*/
|
|
function TitleInputWidget() {
|
|
TitleInputWidget.parent.call( this, {
|
|
showImages: true,
|
|
showDescriptions: true,
|
|
showDisambigsLast: true,
|
|
placeholder: mw.msg( 'wikieditor-toolbar-tool-link-int-target-tooltip' ),
|
|
$overlay: this.getOverlay(),
|
|
validateTitle: false,
|
|
showInterwikis: true,
|
|
required: true,
|
|
addQueryInput: true
|
|
} );
|
|
}
|
|
|
|
OO.inheritClass( TitleInputWidget, mw.widgets.TitleInputWidget );
|
|
|
|
/**
|
|
* Regular expression for determining what might be an external link.
|
|
*
|
|
* @static
|
|
* @property {RegExp}
|
|
*/
|
|
TitleInputWidget.static.urlRegex = new RegExp( '^(' + mw.config.get( 'wgUrlProtocols' ) + '|www\\.)', 'i' );
|
|
|
|
/**
|
|
* When leaving the input without selecting a menu item,
|
|
* automatically select a matching item if there is one.
|
|
* Even though we specify addQueryInput=true in the config, the entered string
|
|
* is not always available to be selected. See T291056.
|
|
*/
|
|
TitleInputWidget.prototype.onLookupInputBlur = function () {
|
|
TitleInputWidget.parent.prototype.onLookupInputBlur.apply( this );
|
|
var that = this;
|
|
this.getLookupMenuItems().done( function ( items ) {
|
|
// The matching item is not always the first,
|
|
// because disambiguation pages are moved to the end.
|
|
for ( var i = 0; i < items.length; i++ ) {
|
|
var item = items[ i ];
|
|
var queryVal = that.getQueryValue();
|
|
// Check for exact match, or a match with uppercase first character.
|
|
if ( item.getData() === queryVal ||
|
|
item.getData() === queryVal.charAt( 0 ).toUpperCase() + queryVal.slice( 1 )
|
|
) {
|
|
// If a matching title is is found, fire an event and stop looking.
|
|
that.emit( 'select', item );
|
|
break;
|
|
}
|
|
}
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* Get menu option widget data from the title and page data,
|
|
* adding an `external` property.
|
|
*
|
|
* @param {string} title Page title
|
|
* @param {Object} data Page data
|
|
* @return {Object} Data for option widget
|
|
*/
|
|
TitleInputWidget.prototype.getOptionWidgetData = function ( title, data ) {
|
|
var widgetData = TitleInputWidget.parent.prototype.getOptionWidgetData.call( this, title, data );
|
|
widgetData.external = data.originalData.external;
|
|
return widgetData;
|
|
};
|
|
|
|
/**
|
|
* Create a InsertLinkTitleOptionWidget.
|
|
*
|
|
* @param {Object} data Data for option widget
|
|
* @return {OO.ui.MenuOptionWidget} The option widget
|
|
*/
|
|
TitleInputWidget.prototype.createOptionWidget = function ( data ) {
|
|
return new InsertLinkTitleOptionWidget( data );
|
|
};
|
|
|
|
/**
|
|
* Get pages' data from the API response, adding an `external` property for
|
|
* pages that do not exist and which look like external URLs.
|
|
*
|
|
* @param {Object} response
|
|
* @return {Object}
|
|
*/
|
|
TitleInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
|
|
var res = TitleInputWidget.parent.prototype.getLookupCacheDataFromResponse( response );
|
|
// Guard against zero responses.
|
|
if ( res.pages === undefined ) {
|
|
return res;
|
|
}
|
|
for ( var pageId in res.pages ) {
|
|
if ( Object.prototype.hasOwnProperty.call( res.pages, pageId ) ) {
|
|
var page = res.pages[ pageId ];
|
|
page.external = page.missing !== undefined && this.isExternalLink( page.title );
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
/**
|
|
* Handle menu item 'choose' event, updating the text input value to the value of the clicked item.
|
|
*
|
|
* @param {OO.ui.MenuOptionWidget} item Selected item
|
|
*/
|
|
TitleInputWidget.prototype.onLookupMenuChoose = function ( item ) {
|
|
TitleInputWidget.parent.prototype.onLookupMenuChoose.call( this, item );
|
|
this.emit( 'select', item );
|
|
};
|
|
|
|
/**
|
|
* Get a custom overlay for the dropdown menu, so it's not contained within the jQuery UI dialog.
|
|
*
|
|
* @private
|
|
* @return {jQuery}
|
|
*/
|
|
TitleInputWidget.prototype.getOverlay = function () {
|
|
// Overlay z-index must be greater than the jQuery UI dialog's of 1002.
|
|
var $overlay = OO.ui.getDefaultOverlay()
|
|
.clone()
|
|
.css( 'z-index', '1010' );
|
|
$( document.body ).append( $overlay );
|
|
return $overlay;
|
|
};
|
|
|
|
/**
|
|
* Determine if a given string is likely to be an external URL.
|
|
* External URLs start with either a valid protocol (from $wgUrlProtocols) or `www.`.
|
|
*
|
|
* @public
|
|
* @param {string} urlString The possible URL.
|
|
* @return {boolean}
|
|
*/
|
|
TitleInputWidget.prototype.isExternalLink = function ( urlString ) {
|
|
var matches = urlString.match( this.constructor.static.urlRegex );
|
|
return matches !== null && matches.length > 0;
|
|
};
|
|
|
|
module.exports = TitleInputWidget;
|