mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-03 18:36:20 +00:00
937352a138
The event "focusTemplateParameterById" targets the right side of the dialog. The input field for the parameter should be focussed. This doesn't make any sense when the parameter was just removed (i.e. unselected). Change-Id: Ie75b1edaebe9d0444b98e66cb56a5c7774393bea
264 lines
8 KiB
JavaScript
264 lines
8 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: 'onParameterAddedToTemplateModel',
|
|
remove: 'onParameterRemovedFromTemplateModel'
|
|
} );
|
|
|
|
var parameterNames = 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;
|
|
} );
|
|
|
|
this.searchWidget = new OO.ui.SearchInputWidget( {
|
|
placeholder: ve.msg( 'visualeditor-dialog-transclusion-filter-placeholder' ),
|
|
classes: [ 've-ui-mwTransclusionOutlineTemplateWidget-searchWidget' ]
|
|
} ).connect( this, {
|
|
change: 'filterParameters'
|
|
} ).toggle( parameterNames.length );
|
|
this.infoWidget = new OO.ui.LabelWidget( {
|
|
label: ve.msg( 'visualeditor-dialog-transclusion-filter-no-match' ),
|
|
classes: [ 've-ui-mwTransclusionOutlineTemplateWidget-no-match' ]
|
|
} ).toggle( false );
|
|
|
|
this.parameters = new ve.ui.MWTransclusionOutlineParameterSelectWidget( {
|
|
items: parameterNames.map( this.createCheckbox.bind( this ) )
|
|
} )
|
|
.connect( this, {
|
|
choose: 'onTemplateParameterChoose',
|
|
templateParameterSelectionChanged: 'onTemplateParameterSelectionChanged',
|
|
change: 'onParameterWidgetListChanged'
|
|
} );
|
|
|
|
this.$element.append(
|
|
this.searchWidget.$element,
|
|
this.infoWidget.$element,
|
|
this.parameters.$element
|
|
);
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.ui.MWTransclusionOutlineTemplateWidget, ve.ui.MWTransclusionOutlinePartWidget );
|
|
|
|
/* Events */
|
|
|
|
/**
|
|
* @event focusTemplateParameterById
|
|
* @param {string} pageName Unique id of the {@see OO.ui.BookletLayout} page, e.g. something like
|
|
* "part_1" or "part_1/param1".
|
|
*/
|
|
|
|
/**
|
|
* Triggered when the user uses the search widget at the top to filter the list of parameters.
|
|
*
|
|
* @event filterParametersById
|
|
* @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 shown as a checkbox.
|
|
* The spec might contain more parameters (e.g. deprecated).
|
|
*/
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* @private
|
|
* @param {string} paramName Parameter name or alias as used in the model
|
|
* @return {OO.ui.OptionWidget}
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.createCheckbox = function ( paramName ) {
|
|
var spec = this.templateModel.getSpec();
|
|
return ve.ui.MWTransclusionOutlineParameterSelectWidget.static.createItem( {
|
|
required: spec.isParameterRequired( paramName ),
|
|
label: spec.getParameterLabel( paramName ),
|
|
data: paramName,
|
|
selected: this.templateModel.hasParameter( paramName )
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {string} paramName
|
|
* @return {number}
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.findCanonicalPosition = function ( paramName ) {
|
|
var 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++;
|
|
}
|
|
}
|
|
return insertAt;
|
|
};
|
|
|
|
/**
|
|
* @param {string} [paramName] Parameter name to highlight, e.g. "param1". Omit for no highlight.
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.highlightParameter = function ( paramName ) {
|
|
this.parameters.highlightParameter( paramName );
|
|
};
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.setSelected = function ( state ) {
|
|
if ( !state && this.isSelected() ) {
|
|
this.parameters.highlightItem();
|
|
}
|
|
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.super.prototype.setSelected.call( this, state );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {ve.dm.MWParameterModel} param
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onParameterAddedToTemplateModel = 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 item = this.parameters.findItemFromData( paramName );
|
|
if ( !item ) {
|
|
item = this.createCheckbox( paramName );
|
|
this.parameters.addItems( [ item ], this.findCanonicalPosition( paramName ) );
|
|
|
|
// Make sure an active filter is applied to the new checkbox as well
|
|
var filter = this.searchWidget.getValue();
|
|
if ( filter ) {
|
|
this.filterParameters( filter );
|
|
}
|
|
}
|
|
|
|
item.setSelected( true, true );
|
|
|
|
// Reset filter, but only if it hides the relevant checkbox
|
|
if ( !item.isVisible() ) {
|
|
this.searchWidget.setValue( '' );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {ve.dm.MWParameterModel} param
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onParameterRemovedFromTemplateModel = function ( param ) {
|
|
this.parameters.markParameterAsUnused( param.getName() );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {OO.ui.OptionWidget} item
|
|
* @param {boolean} selected
|
|
* @fires focusTemplateParameterById
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onTemplateParameterChoose = function ( item, selected ) {
|
|
this.onTemplateParameterSelectionChanged( item, selected );
|
|
|
|
var param = this.templateModel.getParameter( item.getData() );
|
|
if ( param && selected ) {
|
|
this.emit( 'focusTemplateParameterById', param.getId() );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {OO.ui.OptionWidget} item
|
|
* @param {boolean} selected
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onTemplateParameterSelectionChanged = function ( item, selected ) {
|
|
var paramName = item.getData(),
|
|
param = this.templateModel.getParameter( paramName );
|
|
if ( !selected ) {
|
|
this.templateModel.removeParameter( param );
|
|
} else if ( !param ) {
|
|
param = new ve.dm.MWParameterModel( this.templateModel, paramName );
|
|
this.templateModel.addParameter( param );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {OO.ui.Element[]} items
|
|
*/
|
|
ve.ui.MWTransclusionOutlineTemplateWidget.prototype.onParameterWidgetListChanged = 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 filterParametersById
|
|
*/
|
|
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 ( item ) {
|
|
var paramName = item.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;
|
|
} );
|
|
|
|
item.toggle( foundSomeMatch );
|
|
|
|
nothingFound = nothingFound && !foundSomeMatch;
|
|
|
|
var param = template.getParameter( paramName );
|
|
if ( param ) {
|
|
visibility[ param.getId() ] = foundSomeMatch;
|
|
}
|
|
} );
|
|
|
|
this.infoWidget.toggle( nothingFound );
|
|
self.emit( 'filterParametersById', visibility );
|
|
};
|