mediawiki-extensions-Visual.../modules/ve-mw/ui/widgets/ve.ui.MWParameterSearchWidget.js
Thiemo Kreuz 4367235dcc Inline many var declarations in the code below
This makes the code more readable and easier to reason about.
The ESLint rule responsible for this code style was removed
just recently.

Notes:
* I focus on classes that are relevant for what the WMDE team
  does right now.
* I merge multiple `var` keywords only when the variables are
  strongly connected.
* Caching the length in a for loop makes the code hard to
  read, but not really faster when it's a trivial property
  access anyway.

Bug: T284895
Change-Id: I621fed61d894a83dc95f58129bbe679d82b0f5f5
2021-06-23 09:02:24 +00:00

184 lines
4.9 KiB
JavaScript

/*!
* VisualEditor UserInterface MWParameterSearchWidget class.
*
* @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Creates an ve.ui.MWParameterSearchWidget object.
*
* @class
* @extends OO.ui.SearchWidget
*
* @constructor
* @param {ve.dm.MWTemplateModel} template Template model
* @param {Object} [config] Configuration options
* @cfg {number|null} [limit=3] Limit on the number of initial options to show, null to show all
*/
ve.ui.MWParameterSearchWidget = function VeUiMWParameterSearchWidget( template, config ) {
// Configuration initialization
config = ve.extendObject( {
placeholder: ve.msg( 'visualeditor-parameter-input-placeholder' ),
limit: 3
}, config );
// Parent constructor
ve.ui.MWParameterSearchWidget.super.call( this, config );
// Properties
this.template = template;
this.index = [];
this.showAll = false;
this.limit = config.limit || null;
// Events
this.template.connect( this, { add: 'buildIndex', remove: 'buildIndex' } );
this.getResults().connect( this, { choose: 'onSearchResultsChoose' } );
this.query.$input.attr( 'aria-label', ve.msg( 'visualeditor-parameter-input-placeholder' ) );
// Initialization
this.$element.addClass( 've-ui-mwParameterSearchWidget' );
this.query.$input.attr( 'aria-label', ve.msg( 'visualeditor-parameter-input-placeholder' ) );
this.buildIndex();
};
/* Inheritance */
OO.inheritClass( ve.ui.MWParameterSearchWidget, OO.ui.SearchWidget );
/* Events */
/**
* @event choose
* @param {string|null} name Parameter name or null if no item is selected
*/
/* Methods */
/**
* Handle select widget select events.
*
* @param {string} value New value
*/
ve.ui.MWParameterSearchWidget.prototype.onQueryChange = function () {
// Parent method
ve.ui.MWParameterSearchWidget.super.prototype.onQueryChange.call( this );
// Populate
this.addResults();
};
/**
* Handle SelectWidget choose events.
*
* @param {OO.ui.OptionWidget} item Selected item
* @fires choose
*/
ve.ui.MWParameterSearchWidget.prototype.onSearchResultsChoose = function ( item ) {
if ( item instanceof ve.ui.MWParameterResultWidget ) {
this.emit( 'choose', item.getData().name );
} else if ( item instanceof ve.ui.MWMoreParametersResultWidget ) {
this.showAll = true;
this.addResults();
}
};
/**
* Build a searchable index of parameters.
*/
ve.ui.MWParameterSearchWidget.prototype.buildIndex = function () {
var spec = this.template.getSpec(),
knownParams = spec.getParameterNames();
this.index.length = 0;
for ( var i = 0; i < knownParams.length; i++ ) {
var name = knownParams[ i ];
// Skip parameters already in use
if ( this.template.hasParameter( name ) ) {
continue;
}
var label = spec.getParameterLabel( name ),
aliases = spec.getParameterAliases( name ),
description = spec.getParameterDescription( name );
this.index.push( {
// Query information
text: [ label, description ].join( ' ' ).toLowerCase(),
names: [ name ].concat( aliases ).join( '|' ).toLowerCase(),
// Display information
name: name,
label: label,
aliases: aliases,
description: description,
deprecated: spec.isParameterDeprecated( name )
} );
}
// Re-populate
this.onQueryChange();
};
/**
* Handle media query response events.
*/
ve.ui.MWParameterSearchWidget.prototype.addResults = function () {
var textMatch, nameMatch, remainder,
exactMatch = false,
value = this.query.getValue().trim().replace( /[|{}]/g, '' ),
query = value.toLowerCase(),
hasQuery = !!query.length,
items = [];
this.results.clearItems();
for ( var i = 0; i < this.index.length; i++ ) {
var item = this.index[ i ];
if ( hasQuery ) {
textMatch = item.text.indexOf( query ) >= 0;
nameMatch = item.names.indexOf( query ) >= 0;
}
if ( !hasQuery || textMatch || nameMatch ) {
// Only show exact matches for deprecated params
if ( item.deprecated && query !== item.name && item.aliases.indexOf( query ) === -1 ) {
continue;
}
items.push( new ve.ui.MWParameterResultWidget( { data: item } ) );
if ( hasQuery && nameMatch ) {
exactMatch = true;
}
}
if ( !hasQuery && !this.showAll && items.length >= this.limit ) {
remainder = this.index.length - i;
break;
}
}
if ( hasQuery && !exactMatch && value.length && !this.template.hasParameter( value ) ) {
items.unshift( new ve.ui.MWParameterResultWidget( {
data: {
name: value,
label: value,
aliases: [],
description: ve.msg( 'visualeditor-parameter-search-unknown' )
}
} ) );
}
if ( !items.length ) {
items.push( new ve.ui.MWNoParametersResultWidget( {
data: {},
disabled: true
} ) );
} else if ( remainder ) {
items.push( new ve.ui.MWMoreParametersResultWidget( {
data: { remainder: remainder }
} ) );
}
this.results.addItems( items );
if ( hasQuery ) {
this.results.highlightItem( this.results.findFirstSelectableItem() );
}
};