mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-16 10:59:56 +00:00
3365c0fd66
The base widgets we are going to use (notably OO.ui.OptionWidget and OO.ui.SelectWidget) also have events, and some of them use the same names. Such conflicts are really hard to track down. This is meant to be temporary. The goal is to use the events from the base classes and get rid of the custom ones, if possible. Bug: T285323 Change-Id: I0f103a5bbb8fb800e57009e3bf709f00a651fdda
252 lines
7.6 KiB
JavaScript
252 lines
7.6 KiB
JavaScript
/*!
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* Container for template, as rendered in the template dialog sidebar.
|
|
*
|
|
* @class
|
|
* @extends ve.ui.MWTransclusionOutlinePartWidget
|
|
*
|
|
* @constructor
|
|
* @param {ve.dm.MWTemplateModel} template
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget = function VeUiMWTransclusionOutlineTemplateWidget( template ) {
|
|
var spec = template.getSpec();
|
|
|
|
// Parent constructor
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.super.call( this, template, {
|
|
icon: 'puzzle',
|
|
label: spec.getLabel()
|
|
} );
|
|
|
|
// Initialization
|
|
this.templateModel = template.connect( this, {
|
|
add: 'onAddParameter',
|
|
remove: 'onRemoveParameter'
|
|
} );
|
|
|
|
var widget = this;
|
|
var checkboxes = this.templateModel
|
|
.getAllParametersOrdered()
|
|
.filter( function ( paramName ) {
|
|
if ( spec.isParameterDeprecated( paramName ) && !template.hasParameter( paramName ) ) {
|
|
return false;
|
|
}
|
|
// Don't create a checkbox for ve.ui.MWParameterPlaceholderPage
|
|
return paramName;
|
|
} )
|
|
.map( function ( paramName ) {
|
|
return widget.createCheckbox( paramName );
|
|
} );
|
|
|
|
this.searchWidget = new OO.ui.SearchInputWidget( {
|
|
placeholder: ve.msg( 'visualeditor-dialog-transclusion-filter-placeholder' ),
|
|
classes: [ 've-ui-mwTransclusionOutlineTemplateWidget-searchWidget' ]
|
|
} ).connect( this, {
|
|
change: 'filterParameters'
|
|
} ).toggle( false );
|
|
this.infoWidget = new OO.ui.LabelWidget( {
|
|
label: new OO.ui.HtmlSnippet( ve.msg( 'visualeditor-dialog-transclusion-filter-no-match' ) ),
|
|
classes: [ 've-ui-mwTransclusionOutlineTemplateWidget-no-match' ]
|
|
} ).toggle( false );
|
|
|
|
this.parameters = new OO.ui.FieldsetLayout()
|
|
.connect( this, { change: 'onCheckboxListChange' } );
|
|
this.parameters.addItems( checkboxes );
|
|
|
|
this.$element.append(
|
|
this.searchWidget.$element,
|
|
this.infoWidget.$element,
|
|
this.parameters.$element
|
|
);
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ui.MWTransclusionOutlineTemplateWidget, ve.ui.MWTransclusionOutlinePartWidget );
|
|
|
|
/* Events */
|
|
|
|
/**
|
|
* @event selectParameter
|
|
* @param {string} paramId Unique id of the parameter, e.g. something like "part_1/param1"
|
|
*/
|
|
|
|
/**
|
|
* Triggered when the user uses the search widget at the top to filter the list of parameters.
|
|
*
|
|
* @event filterParameters
|
|
* @param {Object.<string,boolean>} visibility Keyed by unique id of the parameter, e.g. something
|
|
* like "part_1/param1". Note this lists only parameters that are currently in use.
|
|
*/
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* @private
|
|
* @param {string} paramName
|
|
* @return {ve.ui.MWTemplateOutlineParameterCheckboxLayout}
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.createCheckbox = function ( paramName ) {
|
|
var spec = this.templateModel.getSpec();
|
|
|
|
return new ve.ui.MWTemplateOutlineParameterCheckboxLayout( {
|
|
required: spec.isParameterRequired( paramName ),
|
|
label: spec.getParameterLabel( paramName ),
|
|
data: paramName,
|
|
selected: this.templateModel.hasParameter( paramName )
|
|
} ).connect( this, {
|
|
parameterSelectionChanged: 'onParameterSelectionChanged',
|
|
parameterFocused: 'onParameterFocused'
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {ve.ui.MWTemplateOutlineParameterCheckboxLayout} checkbox
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.insertCheckboxAtCanonicalPosition = function ( checkbox ) {
|
|
var paramName = checkbox.getData(),
|
|
insertAt = 0,
|
|
// Note this might include parameters that don't have a checkbox, e.g. deprecated
|
|
allParamNames = this.templateModel.getAllParametersOrdered();
|
|
for ( var i = 0; i < allParamNames.length; i++ ) {
|
|
if ( allParamNames[ i ] === paramName || !this.parameters.items[ insertAt ] ) {
|
|
break;
|
|
} else if ( this.parameters.items[ insertAt ].getData() === allParamNames[ i ] ) {
|
|
insertAt++;
|
|
}
|
|
}
|
|
this.parameters.addItems( [ checkbox ], insertAt );
|
|
};
|
|
|
|
/**
|
|
* Handles a template model add event {@see ve.dm.MWTemplateModel}.
|
|
* Triggered when a parameter is added to the template model.
|
|
*
|
|
* @private
|
|
* @param {ve.dm.MWParameterModel} param
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onAddParameter = function ( param ) {
|
|
var paramName = param.getName();
|
|
// The placeholder (currently) doesn't get a corresponding item in the sidebar
|
|
if ( !paramName ) {
|
|
return;
|
|
}
|
|
|
|
// All parameters known via the spec already have a checkbox
|
|
var checkbox = this.parameters.findItemFromData( paramName );
|
|
if ( !checkbox ) {
|
|
checkbox = this.createCheckbox( paramName );
|
|
this.insertCheckboxAtCanonicalPosition( checkbox );
|
|
// Make sure an active filter is applied to the new checkbox as well
|
|
var filter = this.searchWidget.getValue();
|
|
if ( filter ) {
|
|
this.filterParameters( filter );
|
|
}
|
|
}
|
|
|
|
checkbox.setSelected( true, true );
|
|
|
|
// Reset filter, but only if it hides the relevant checkbox
|
|
if ( !checkbox.isVisible() ) {
|
|
this.searchWidget.setValue( '' );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handles a template model remove event {@see ve.dm.MWTemplateModel}.
|
|
* Triggered when a parameter is removed from the template model.
|
|
*
|
|
* @private
|
|
* @param {ve.dm.MWParameterModel} param
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onRemoveParameter = function ( param ) {
|
|
var checkbox = this.parameters.findItemFromData( param.getName() );
|
|
if ( checkbox ) {
|
|
checkbox.setSelected( false, true );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handles a parameter checkbox change event {@see ve.ui.MWTemplateOutlineParameterCheckboxLayout}
|
|
*
|
|
* @private
|
|
* @param {string} paramName
|
|
* @param {boolean} selected
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onParameterSelectionChanged = function ( paramName, selected ) {
|
|
var param = this.templateModel.getParameter( paramName );
|
|
if ( !selected ) {
|
|
this.templateModel.removeParameter( param );
|
|
} else if ( !param ) {
|
|
this.templateModel.addParameter( new ve.dm.MWParameterModel( this.templateModel, paramName ) );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {string} paramName
|
|
* @fires selectParameter
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onParameterFocused = function ( paramName ) {
|
|
var param = this.templateModel.getParameter( paramName );
|
|
if ( param ) {
|
|
this.emit( 'selectParameter', param.getId() );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {OO.ui.Element[]} items
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onCheckboxListChange = function ( items ) {
|
|
this.searchWidget.toggle( items.length >= 1 );
|
|
};
|
|
|
|
/**
|
|
* Narrows the list of checkboxes down to parameters that match the user's input. The search
|
|
* algorithm is modelled after {@see ve.ui.MWParameterSearchWidget.buildIndex}. We search the
|
|
* parameter's primary name, aliases, label, and description. But not e.g. the example value.
|
|
*
|
|
* @private
|
|
* @param {string} query user input
|
|
* @fires filterParameters
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.filterParameters = function ( query ) {
|
|
var self = this,
|
|
template = this.templateModel,
|
|
spec = this.templateModel.getSpec(),
|
|
visibility = {},
|
|
nothingFound = true;
|
|
|
|
query = query.trim().toLowerCase();
|
|
|
|
// Note: We can't really cache this because the list of know parameters can change any time
|
|
this.parameters.items.forEach( function ( checkbox ) {
|
|
var paramName = checkbox.getData(),
|
|
placesToSearch = [
|
|
spec.getPrimaryParameterName( paramName ),
|
|
spec.getParameterLabel( paramName ),
|
|
spec.getParameterDescription( paramName )
|
|
].concat( spec.getParameterAliases( paramName ) );
|
|
|
|
var foundSomeMatch = placesToSearch.some( function ( term ) {
|
|
return term && term.toLowerCase().indexOf( query ) !== -1;
|
|
} );
|
|
|
|
checkbox.toggle( foundSomeMatch );
|
|
|
|
nothingFound = nothingFound && !foundSomeMatch;
|
|
|
|
var param = template.getParameter( paramName );
|
|
if ( param ) {
|
|
visibility[ param.getId() ] = foundSomeMatch;
|
|
}
|
|
} );
|
|
|
|
this.infoWidget.toggle( nothingFound );
|
|
self.emit( 'filterParameters', visibility );
|
|
};
|