Switch to OOUI TitleInputWidget for the link-inserter

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
This commit is contained in:
Sam Wilson 2021-09-01 15:17:53 +08:00 committed by Daimona Eaytoy
parent 4023b7af82
commit 6384498d75
17 changed files with 360 additions and 289 deletions

View file

@ -42,6 +42,9 @@
"group": "ext.wikiEditor",
"packageFiles": [
"ext.wikiEditor.js",
"insertlink/TitleInputField.js",
"insertlink/TitleInputWidget.js",
"insertlink/TitleOptionWidget.js",
"jquery.wikiEditor.js",
"jquery.wikiEditor.toolbar.js",
"jquery.wikiEditor.toolbar.config.js",
@ -54,6 +57,7 @@
}
],
"styles": [
"insertlink/TitleInputField.less",
"jquery.wikiEditor.less",
"jquery.wikiEditor.toolbar.less",
"jquery.wikiEditor.dialogs.less",
@ -271,7 +275,6 @@
"dependencies": [
"jquery.cookie",
"jquery.throttle-debounce",
"jquery.suggestions",
"jquery.textSelection",
"jquery.ui",
"mediawiki.api",
@ -281,6 +284,7 @@
"mediawiki.Title",
"mediawiki.user",
"mediawiki.util",
"mediawiki.widgets",
"oojs-ui.styles.icons-content",
"oojs-ui.styles.icons-editing-advanced",
"oojs-ui.styles.icons-editing-citation",

View file

@ -33,12 +33,12 @@
"wikieditor-toolbar-tool-link-ext-text": "Link text:",
"wikieditor-toolbar-tool-link-insert": "Insert link",
"wikieditor-toolbar-tool-link-cancel": "Cancel",
"wikieditor-toolbar-tool-link-int-target-status-exists": "Page exists",
"wikieditor-toolbar-tool-link-int-target-status-notexists": "Page does not exist",
"wikieditor-toolbar-tool-link-int-target-status-invalid": "Invalid title",
"wikieditor-toolbar-tool-link-int-target-status-exists": "This page exists on {{SITENAME}}",
"wikieditor-toolbar-tool-link-int-target-status-notexists": "This page does not exist on {{SITENAME}}",
"wikieditor-toolbar-tool-link-int-target-status-invalid": "The title you specified is invalid",
"wikieditor-toolbar-tool-link-int-target-status-external": "External link",
"wikieditor-toolbar-tool-link-int-target-status-loading": "Checking page existence...",
"wikieditor-toolbar-tool-link-int-target-status-disambig": "Disambiguation page",
"wikieditor-toolbar-tool-link-int-target-status-disambig": "This page is not a content page, it lists topics with similar names",
"wikieditor-toolbar-tool-link-int-invalid": "The title you specified is invalid.",
"wikieditor-toolbar-tool-link-lookslikeinternal": "The URL you specified looks like it was intended as a link to another wiki page.\nDo you want to make it an internal link?",
"wikieditor-toolbar-tool-link-lookslikeinternal-int": "Internal link",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,105 @@
var TitleInputWidget = require( './TitleInputWidget.js' );
var TitleOptionWidget = require( './TitleOptionWidget.js' );
/**
* A FieldLayout containing a custom TitleInputwidget and message-display system.
*
* @class
* @extends OO.ui.FieldLayout
* @mixes OO.EventEmitter
* @constructor
*/
function TitleInputField() {
var input = new TitleInputWidget();
input.connect( this, {
change: this.onChange,
select: this.onSelect
} );
// The URL mode is set by the user via radio buttons.
this.urlModes = {
internal: 'internal',
external: 'external'
};
this.urlMode = this.urlModes.internal;
var config = {
align: 'top',
label: mw.msg( 'wikieditor-toolbar-tool-link-int-target' ),
classes: [ 'ext-WikiEditor-InsertLink-TitleInputField' ]
};
TitleInputField.super.call( this, input, config );
OO.EventEmitter.call( this );
}
OO.inheritClass( TitleInputField, OO.ui.FieldLayout );
OO.mixinClass( TitleInputField, OO.EventEmitter );
/**
* @public
* @param {string} urlMode One of the `TitleInputField.urlModes.*` values.
*/
TitleInputField.prototype.setUrlMode = function ( urlMode ) {
this.urlMode = urlMode === this.urlModes.external ?
this.urlModes.external :
this.urlModes.internal;
};
/**
* @inheritDoc
*/
TitleInputField.prototype.makeMessage = function ( kind, text ) {
this.message = new OO.ui.MessageWidget( {
type: kind,
inline: true,
label: text
} );
return this.message.$element;
};
/**
* Set the displayed field message, replacing any that is already set.
*
* @param {string} icon
* @param {string} message
* @param {string} type
*/
TitleInputField.prototype.setMessage = function ( icon, message, type ) {
this.setNotices( [ message ] );
// Note that setNotices() must be called before this.message is available.
this.message.setType( type || 'notice' );
this.message.setIcon( icon );
};
/**
* @private
* @param {string} value
*/
TitleInputField.prototype.onChange = function ( value ) {
if ( this.urlMode === this.urlModes.internal && value !== '' && !mw.Title.newFromText( value ) ) {
this.setMessage( 'error', mw.message( 'wikieditor-toolbar-tool-link-int-target-status-invalid' ).parse(), 'error' );
this.emit( 'invalid' );
} else {
// Remove message; it'll be re-added if required (after selection or blur).
this.setNotices( [] );
this.emit( 'change', value );
}
};
/**
* @param {TitleOptionWidget} item
*/
TitleInputField.prototype.onSelect = function ( item ) {
if ( item.isExternal() ) {
this.setMessage( 'linkExternal', mw.message( 'wikieditor-toolbar-tool-link-int-target-status-external' ).parse() );
} else if ( item.isDisambiguation() ) {
this.setMessage( 'articleDisambiguation', mw.message( 'wikieditor-toolbar-tool-link-int-target-status-disambig' ).parse() );
} else if ( !item.isMissing() ) {
this.setMessage( 'article', mw.message( 'wikieditor-toolbar-tool-link-int-target-status-exists' ).parse() );
} else if ( item.isMissing() ) {
this.setMessage( 'articleNotFound', mw.message( 'wikieditor-toolbar-tool-link-int-target-status-notexists' ).parse() );
}
};
module.exports = TitleInputField;

View file

@ -0,0 +1,10 @@
@import 'mediawiki.ui/variables.less';
.ext-WikiEditor-InsertLink-TitleInputField {
margin-bottom: 8px;
.oo-ui-messageWidget {
color: @color-base--subtle;
font-weight: normal;
}
}

View file

@ -0,0 +1,146 @@
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;

View file

@ -0,0 +1,53 @@
/**
* A custom TitleOptionWidget that knows about external links.
*
* @class
* @extends mw.widgets.TitleOptionWidget
* @constructor
* @param {Object} config Configuration options.
* @cfg {boolean} [external] Page title is an external link.
*/
function InsertLinkTitleOptionWidget( config ) {
this.external = config.external || false;
if ( this.external ) {
config.icon = 'linkExternal';
config.description = mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-external' );
// Lowercase the first character; it was uppercased by the API.
config.url = config.data.substr( 0, 1 ).toLowerCase() + config.data.substr( 1 );
config.data = config.url;
// Prepend http:// if there is no protocol (i.e. if it starts with "www.").
// @TODO This is repeated when the link is inserted (in jquery.wikiEditor.dialogs.config.js).
if ( !config.url.match( /^[a-z]+:\/\/./ ) ) {
config.url = 'http://' + config.url;
}
config.missing = false;
}
this.disambiguation = config.disambiguation || false;
this.missing = config.missing || false;
InsertLinkTitleOptionWidget.super.call( this, config );
}
OO.inheritClass( InsertLinkTitleOptionWidget, mw.widgets.TitleOptionWidget );
/**
* @return {boolean}
*/
InsertLinkTitleOptionWidget.prototype.isExternal = function () {
return this.external;
};
/**
* @return {boolean}
*/
InsertLinkTitleOptionWidget.prototype.isMissing = function () {
return this.missing;
};
/**
* @return {boolean}
*/
InsertLinkTitleOptionWidget.prototype.isDisambiguation = function () {
return this.disambiguation;
};
module.exports = InsertLinkTitleOptionWidget;

View file

@ -3,8 +3,9 @@
*/
( function () {
var hasOwn = Object.prototype.hasOwnProperty,
toolbarModule = require( './jquery.wikiEditor.toolbar.js' ),
var toolbarModule = require( './jquery.wikiEditor.toolbar.js' ),
InsertLinkTitleInputField = require( './insertlink/TitleInputField.js' ),
insertLinkTitleInputField = new InsertLinkTitleInputField(),
configData = require( './data.json' );
function triggerButtonClick( element ) {
@ -103,173 +104,50 @@
htmlTemplate: 'dialogInsertLink.html',
init: function () {
var api = new mw.Api();
$( '.wikieditor-toolbar-link-target' ).replaceWith( insertLinkTitleInputField.$element );
function isExternalLink( s ) {
// The following things are considered to be external links:
// * Starts with a URL protocol
// * Starts with www.
// All of these are potentially valid titles, and the latter two categories match about 6300
// titles in enwiki's ns0. Out of 6.9M titles, that's 0.09%
/* eslint-disable no-caller */
if ( typeof arguments.callee.regex === 'undefined' ) {
// Cache the regex
arguments.callee.regex =
new RegExp( '^(' + mw.config.get( 'wgUrlProtocols' ) + '|www\\.)', 'i' );
}
return s.match( arguments.callee.regex );
/* eslint-enable no-caller */
}
// Updates the status indicator above the target link
function updateWidget( status, reason ) {
$( '#wikieditor-toolbar-link-int-target-status' ).children().hide();
$( '#wikieditor-toolbar-link-int-target' ).parent()
.removeClass(
'status-invalid status-external status-notexists status-exists status-loading'
);
if ( status ) {
$( '#wikieditor-toolbar-link-int-target-status-' + status ).show();
// Status classes listed above
// eslint-disable-next-line mediawiki/class-doc
$( '#wikieditor-toolbar-link-int-target' ).parent().addClass( 'status-' + status );
}
if ( status === 'invalid' ) {
// eslint-disable-next-line no-jquery/no-sizzle
$( '.ui-dialog:visible .ui-dialog-buttonpane button' ).first()
.prop( 'disabled', true )
.addClass( 'disabled' );
if ( reason ) {
$( '#wikieditor-toolbar-link-int-target-status-invalid' ).html( reason );
} else {
$( '#wikieditor-toolbar-link-int-target-status-invalid' )
.text( mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-invalid' ) );
}
} else {
// eslint-disable-next-line no-jquery/no-sizzle
$( '.ui-dialog:visible .ui-dialog-buttonpane button' ).first()
.prop( 'disabled', false )
.removeClass( 'disabled' );
}
}
// Updates the UI to show if the page title being inputted by the user exists or not
// accepts parameter internal for bypassing external link detection
function updateExistence( internal ) {
// Abort previous request
var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ),
target = $( '#wikieditor-toolbar-link-int-target' ).val(),
cache = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'existencecache' ),
reasoncache = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'reasoncache' );
// ensure the internal parameter is a boolean
if ( internal !== true ) {
internal = false;
}
if ( request ) {
request.abort();
}
if ( hasOwn.call( cache, target ) ) {
updateWidget( cache[ target ], reasoncache[ target ] );
return;
}
if ( target.replace( /^\s+$/, '' ) === '' ) {
// Hide the widget when the textbox is empty
updateWidget( false );
return;
}
// If the forced internal parameter was not true, check if the target is an external link
if ( !internal && isExternalLink( target ) ) {
updateWidget( 'external' );
return;
}
// Show loading spinner while waiting for the API to respond
updateWidget( 'loading' );
// Call the API to check page status, saving the request object so it can be aborted if
// necessary.
// This used to request a page that would show whether or not the target exists, but we can
// also check whether it has the disambiguation property and still get existence information.
// If the Disambiguator extension is not installed then such a property won't be set.
$( '#wikieditor-toolbar-link-int-target-status' ).data(
'request',
api.get( {
formatversion: 2,
action: 'query',
prop: 'pageprops',
titles: [ target ],
ppprop: 'disambiguation',
errorformat: 'html',
errorlang: mw.config.get( 'wgUserLanguage' )
} ).done( function ( data ) {
var reason = null;
var status;
if ( !data.query || !data.query.pages ) {
// This happens in some weird cases like interwiki links
status = false;
} else {
var page = data.query.pages[ 0 ];
status = 'exists';
if ( page.missing ) {
status = 'notexists';
} else if ( page.invalid ) {
status = 'invalid';
reason = page.invalidreason && page.invalidreason.html;
} else if ( page.pageprops ) {
status = 'disambig';
}
}
// Cache the status of the link target if the force internal
// parameter was not passed
if ( !internal ) {
cache[ target ] = status;
reasoncache[ target ] = reason;
}
updateWidget( status, reason );
} )
);
}
$( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' ).on( 'click', function () {
if ( $( '#wikieditor-toolbar-link-type-ext' ).prop( 'checked' ) ) {
// Abort previous request
var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' );
if ( request ) {
request.abort();
}
updateWidget( 'external' );
}
if ( $( '#wikieditor-toolbar-link-type-int' ).prop( 'checked' ) ) {
updateExistence( true );
}
} );
// Set labels of tabs based on rel values
$( this ).find( '[rel]' ).each( function () {
// eslint-disable-next-line mediawiki/msg-doc
$( this ).text( mw.msg( $( this ).attr( 'rel' ) ) );
} );
$( '#wikieditor-toolbar-link-int-target' ).attr( 'placeholder',
mw.msg( 'wikieditor-toolbar-tool-link-int-target-tooltip' ) );
$( '#wikieditor-toolbar-link-int-text' ).attr( 'placeholder',
mw.msg( 'wikieditor-toolbar-tool-link-int-text-tooltip' ) );
// Automatically copy the value of the internal link page title field to the link text field unless the
// user has changed the link text field - this is a convenience thing since most link texts are going to
// be the same as the page title - Also change the internal/external radio button accordingly
$( '#wikieditor-toolbar-link-int-target' ).on( 'change keydown paste cut', function () {
// $( this ).val() is the old value, before the keypress - Defer this until $( this ).val() has
// been updated
setTimeout( function () {
if ( isExternalLink( $( '#wikieditor-toolbar-link-int-target' ).val() ) ) {
insertLinkTitleInputField.connect( this, {
change: function ( val ) {
if ( insertLinkTitleInputField.getField().isExternalLink( val ) ) {
$( '#wikieditor-toolbar-link-type-ext' ).prop( 'checked', true );
updateWidget( 'external' );
} else {
$( '#wikieditor-toolbar-link-type-int' ).prop( 'checked', true );
updateExistence();
}
if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'untouched' ) ) {
$( '#wikieditor-toolbar-link-int-text' )
.val( $( '#wikieditor-toolbar-link-int-target' ).val() )
.val( val )
.trigger( 'change' );
}
}, 0 );
// eslint-disable-next-line no-jquery/no-sizzle
$( '.ui-dialog:visible .ui-dialog-buttonpane button' )
.first()
.prop( 'disabled', false )
.removeClass( 'disabled' );
},
invalid: function () {
// eslint-disable-next-line no-jquery/no-sizzle
$( '.ui-dialog:visible .ui-dialog-buttonpane button' )
.first()
.prop( 'disabled', true )
.addClass( 'disabled' );
}
} );
// Tell the title input field when the internal/external radio changes.
$( 'input[name="wikieditor-toolbar-link-type"]' ).on( 'change', function ( event ) {
var urlMode = event.target.id === 'wikieditor-toolbar-link-type-ext' ?
insertLinkTitleInputField.urlModes.external :
insertLinkTitleInputField.urlModes.internal;
insertLinkTitleInputField.setUrlMode( urlMode );
} );
$( '#wikieditor-toolbar-link-int-text' ).on( 'change keydown paste cut', function () {
var oldVal = $( this ).val(),
@ -280,75 +158,6 @@
}
}, 0 );
} );
// Add images to the page existence widget, which will be shown mutually exclusively to communicate if
// the page exists, does not exist or the title is invalid (like if it contains a | character)
$( '#wikieditor-toolbar-link-int-target-status' )
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-exists' )
.text( mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-exists' ) )
)
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-notexists' )
.text( mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-notexists' ) )
)
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-invalid' )
)
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-external' )
.text( mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-external' ) )
)
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-loading' )
.attr( 'title', mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-loading' ) )
)
.append( $( '<div>' )
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-disambig' )
.text( mw.msg( 'wikieditor-toolbar-tool-link-int-target-status-disambig' ) )
)
.data( 'existencecache', {} )
.data( 'reasoncache', {} )
.children().hide();
$( '#wikieditor-toolbar-link-int-target' )
.on( 'keyup paste cut', $.debounce( 500, updateExistence ) )
.on( 'change', updateExistence ); // update right now
// Title suggestions
$( '#wikieditor-toolbar-link-int-target' ).data( 'suggcache', {} ).suggestions( {
fetch: function () {
var that = this,
title = $( this ).val();
if ( isExternalLink( title ) || title.indexOf( '|' ) !== -1 || title === '' ) {
$( this ).suggestions( 'suggestions', [] );
return;
}
var cache = $( this ).data( 'suggcache' );
if ( hasOwn.call( cache, title ) ) {
$( this ).suggestions( 'suggestions', cache[ title ] );
return;
}
var request = api.get( {
formatversion: 2,
action: 'opensearch',
search: title,
namespace: 0
} ).done( function ( data ) {
cache[ title ] = data[ 1 ];
$( that ).suggestions( 'suggestions', data[ 1 ] );
} );
$( this ).data( 'request', request );
},
cancel: function () {
var request = $( this ).data( 'request' );
if ( request ) {
request.abort();
}
}
} );
},
dialog: {
width: 500,
@ -369,7 +178,7 @@
return s.replace( /(\]+)/g, '<nowiki>$1</nowiki>' );
}
var target = $( '#wikieditor-toolbar-link-int-target' ).val();
var target = insertLinkTitleInputField.getField().getValue();
if ( target === '' ) {
// eslint-disable-next-line no-alert
alert( mw.msg( 'wikieditor-toolbar-tool-link-empty' ) );
@ -454,7 +263,8 @@
}, $( this ) );
// Blank form
$( '#wikieditor-toolbar-link-int-target, #wikieditor-toolbar-link-int-text' ).val( '' );
insertLinkTitleInputField.getField().setValue( '' );
$( '#wikieditor-toolbar-link-int-text' ).val( '' );
$( '#wikieditor-toolbar-link-type-int, #wikieditor-toolbar-link-type-ext' )
.prop( 'checked', false );
},
@ -473,9 +283,10 @@
// Pre-fill the text fields based on the current selection
var context = $( this ).data( 'context' );
var selection = context.$textarea.textSelection( 'getSelection' );
$( '#wikieditor-toolbar-link-int-target' ).trigger( 'focus' );
insertLinkTitleInputField.getField().focus();
// Trigger the change event, so the link status indicator is up to date
$( '#wikieditor-toolbar-link-int-target' ).trigger( 'change' );
insertLinkTitleInputField.getField().$input.trigger( 'change' );
$( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ '', '' ] );
if ( selection !== '' ) {
var matches, target, text, type;
@ -513,7 +324,7 @@
$( '#wikieditor-toolbar-link-int-text' ).val( text ).trigger( 'change' );
}
if ( typeof target !== 'undefined' ) {
$( '#wikieditor-toolbar-link-int-target' ).val( target ).trigger( 'change' );
insertLinkTitleInputField.getField().setValue( target );
}
if ( typeof type !== 'undefined' ) {
$( '#wikieditor-toolbar-link-' + type ).prop( 'checked', true );
@ -521,9 +332,8 @@
}
$( '#wikieditor-toolbar-link-int-text' ).data( 'untouched',
$( '#wikieditor-toolbar-link-int-text' ).val() ===
$( '#wikieditor-toolbar-link-int-target' ).val()
insertLinkTitleInputField.getField().getValue()
);
$( '#wikieditor-toolbar-link-int-target' ).suggestions();
// don't overwrite user's text
if ( selection !== '' ) {

View file

@ -75,63 +75,10 @@
}
/* Insert Link Dialog */
#wikieditor-toolbar-link-int-target-status {
float: right;
line-height: 1.7em;
}
#wikieditor-toolbar-link-int-target,
#wikieditor-toolbar-link-int-text {
width: 100%;
}
#wikieditor-toolbar-tool-link-int-target-label {
float: left;
line-height: 1.7em;
}
#wikieditor-toolbar-link-int-target-status-exists,
#wikieditor-toolbar-link-int-target-status-notexists,
#wikieditor-toolbar-link-int-target-status-invalid,
#wikieditor-toolbar-link-int-target-status-external,
#wikieditor-toolbar-link-int-target-status-loading,
#wikieditor-toolbar-link-int-target-status-disambig {
padding-left: 30px;
background-position: 0 50%;
background-repeat: no-repeat;
}
#wikieditor-toolbar-link-int-target-status-exists {
.background-image('images/dialogs/insert-link-exists.png');
background-position: left;
}
#wikieditor-toolbar-link-int-target-status-notexists {
.background-image('images/dialogs/insert-link-notexists.png');
background-position: left;
}
#wikieditor-toolbar-link-int-target-status-invalid {
.background-image('images/dialogs/insert-link-invalid.png');
background-position: left;
}
#wikieditor-toolbar-link-int-target-status-external {
.background-image('images/dialogs/insert-link-external.png');
background-position: left;
}
#wikieditor-toolbar-link-int-target-status-loading {
.background-image('images/dialogs/loading-small.gif');
background-position: right;
height: 18px;
}
#wikieditor-toolbar-link-int-target-status-disambig {
.background-image('images/dialogs/insert-disambiguation.png');
background-position: left;
}
/* File dialog */
#wikieditor-toolbar-file-target,
#wikieditor-toolbar-file-caption,

View file

@ -1,9 +1,5 @@
<fieldset>
<div class="wikieditor-toolbar-field-wrapper">
<label for="wikieditor-toolbar-link-int-target" rel="wikieditor-toolbar-tool-link-int-target" id="wikieditor-toolbar-tool-link-int-target-label"></label>
<div id="wikieditor-toolbar-link-int-target-status"></div>
<input type="text" id="wikieditor-toolbar-link-int-target"/>
</div>
<div class="wikieditor-toolbar-link-target"></div>
<div class="wikieditor-toolbar-field-wrapper">
<label for="wikieditor-toolbar-link-int-text" rel="wikieditor-toolbar-tool-link-int-text"></label>
<input type="text" id="wikieditor-toolbar-link-int-text"/>