mediawiki-extensions-Visual.../modules/ve-mw/ui/widgets/ve.ui.MWParameterSearchWidget.js
Trevor Parscal 0c3ca665d2 Retain original param names and ignore leading/trailing whitespace
Objectives:

* Trim leading or trailing whitespace that parsoid may have left on
  parameter names
* Preserve the original name for round-tripping cleanliness
* Ignore leading or trailing whitespace when entering new parameter names
  in the parameter search widget
* Consider aliases when listing suggested parameters

Changes:

ve.ui.MWParameterSearchWidget.js
* Use hasParameter method instead of using indexOf - uses map lookup
  internally, which is much faster, and also take aliases into account
* Trim query input value to prevent leading or trailing whitespace from
  being considered when filtering known or creating unknown parameters
* Take aliases into account when showing filtered results

ve.dm.MWTransclusionModel.js
* Use original name when round-tripping

ve.dm.MWTemplateParameterModel.js
* Store original name for round tripping, and trim the original name for
  other uses
* Add getOriginalName method

ve.dm.MWTemplateModel.js
* Add hasParameter method, which currently just does a map lookup, but can
  do other processing in the future

ve.dm.MWTemplateSpecModel.js
* Add isParameterKnown method

Bug: 50715
Bug: 50717
Change-Id: I36a5e93ca8938ac3401a6e274647597704700468
2013-07-10 15:34:36 -07:00

163 lines
3.8 KiB
JavaScript

/*!
* VisualEditor UserInterface MWParameterSearchWidget class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Creates an ve.ui.MWParameterSearchWidget object.
*
* @class
* @extends ve.ui.SearchWidget
*
* @constructor
* @param {Object} [config] Config options
*/
ve.ui.MWParameterSearchWidget = function VeUiMWParameterSearchWidget( template, config ) {
// Configuration intialization
config = ve.extendObject( {}, config, {
'placeholder': ve.msg( 'visualeditor-parameter-input-placeholder' )
} );
// Parent constructor
ve.ui.SearchWidget.call( this, config );
// Properties
this.template = template;
this.index = [];
// Events
this.template.connect( this, { 'add': 'buildIndex', 'remove': 'buildIndex' } );
// Initialization
this.$.addClass( 've-ui-mwParameterSearchWidget' );
this.buildIndex();
};
/* Inheritance */
ve.inheritClass( ve.ui.MWParameterSearchWidget, ve.ui.SearchWidget );
/* Events */
/**
* @event select
* @param {string|null} name Parameter name or null if no item is selected
*/
/* Methods */
/**
* Handle select widget select events.
*
* @method
* @param {string} value New value
*/
ve.ui.MWParameterSearchWidget.prototype.onQueryChange = function () {
// Parent method
ve.ui.SearchWidget.prototype.onQueryChange.call( this );
// Populate
this.addResults();
};
/**
* Handle select widget select events.
*
* @method
* @param {ve.ui.OptionWidget} item Selected item
* @emits select
*/
ve.ui.MWParameterSearchWidget.prototype.onResultsSelect = function ( item ) {
this.emit( 'select', item && item.getData() ? item.getData().name : null );
};
/**
* Build a serchable index of parameters.
*
* @method
* @param {ve.dm.MWTemplateSpecModel} spec Template specification
*/
ve.ui.MWParameterSearchWidget.prototype.buildIndex = function () {
var i, len, name, label, aliases, description,
spec = this.template.getSpec(),
knownParams = spec.getParameterNames();
this.index.length = 0;
for ( i = 0, len = knownParams.length; i < len; i++ ) {
name = knownParams[i];
if (
// Skip aliases
spec.getParameterOrigin( name ) !== name ||
// Skip parameters already in use
this.template.hasParameter( name )
) {
continue;
}
label = spec.getParameterLabel( name );
aliases = spec.getParameterAliases( name );
description = spec.getParameterDescription( name );
this.index.push( {
'text': [ name, aliases.join( ' ' ), description ].join( ' ' ),
'name': name,
'label': label,
'aliases': aliases,
'description': description
} );
}
// Re-populate
this.onQueryChange();
};
/**
* Handle media query response events.
*
* @method
*/
ve.ui.MWParameterSearchWidget.prototype.addResults = function () {
var i, len, item,
exactMatch = false,
value = this.query.getValue().trim(),
query = value.toLowerCase(),
items = [];
for ( i = 0, len = this.index.length; i < len; i++ ) {
item = this.index[i];
if ( item.text.indexOf( query ) >= 0 ) {
items.push( new ve.ui.MWParameterResultWidget( item, { '$$': this.$$ } ) );
if ( item.name === value || ve.indexOf( value, item.aliases ) !== -1 ) {
exactMatch = true;
}
}
}
if ( !exactMatch && value.length && !this.template.hasParameter( value ) ) {
items.unshift( new ve.ui.MWParameterResultWidget( {
'name': value,
'label': value,
'aliases': [],
'description': ve.msg( 'visualeditor-parameter-search-unknown' )
}, { '$$': this.$$ } ) );
}
if ( !items.length ) {
items.push( new ve.ui.MWParameterResultWidget(
{
'name': null,
'label': '',
'aliases': [],
'description': ve.msg( 'visualeditor-parameter-search-no-unused' )
},
{ '$$': this.$$, 'disabled': true }
) );
}
this.results.addItems( items );
if ( query.length ) {
this.results.selectItem( this.results.getFirstSelectableItem() );
}
};