2 * MediaWiki Widgets - TitlesMultiselectWidget class.
4 * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
10 * @classdesc Titles multiselect widget.
13 * @extends OO.ui.MenuTagMultiselectWidget
14 * @mixes OO.ui.mixin.RequestManager
15 * @mixes OO.ui.mixin.PendingElement
16 * @mixes mw.widgets.TitleWidget
19 * @description Create an mw.widgets.TitlesMultiselectWidget object.
20 * @param {Object} [config] Configuration options
22 mw.widgets.TitlesMultiselectWidget = function MwWidgetsTitlesMultiselectWidget( config ) {
24 mw.widgets.TitlesMultiselectWidget.super.call( this, $.extend( true,
32 mw.widgets.TitleWidget.call( this, $.extend( true, {
34 highlightSearchQuery: false
36 OO.ui.mixin.RequestManager.call( this, config );
37 OO.ui.mixin.PendingElement.call( this, $.extend( true, {}, config, {
38 $pending: this.$handle
41 // Validate from mw.widgets.TitleWidget
42 this.input.setValidation( this.isQueryValid.bind( this ) );
44 // TODO limit max tag length to this.maxLength
48 .addClass( 'mw-widgets-titlesMultiselectWidget' );
51 // For consistency, use the same classes as TitleWidget
52 // expects for menu results
53 .addClass( 'mw-widget-titleWidget-menu' )
54 .toggleClass( 'mw-widget-titleWidget-menu-withImages', this.showImages )
55 .toggleClass( 'mw-widget-titleWidget-menu-withDescriptions', this.showDescriptions );
57 if ( 'name' in config ) {
58 // Use this instead of <input type="hidden">, because hidden inputs do not have separate
59 // 'value' and 'defaultValue' properties. The script on Special:Preferences
60 // (mw.special.preferences.confirmClose) checks this property to see if a field was changed.
61 this.$hiddenInput = $( '<textarea>' )
62 .addClass( 'oo-ui-element-hidden' )
63 .attr( 'name', config.name )
64 .appendTo( this.$element );
65 // Update with preset values
66 // Set the default value (it might be different from just being empty)
67 this.$hiddenInput.prop( 'defaultValue', this.getItems().map( ( item ) => item.getData() ).join( '\n' ) );
68 this.on( 'change', ( items ) => {
69 this.$hiddenInput.val( items.map( ( item ) => item.getData() ).join( '\n' ) );
70 // Trigger a 'change' event as if a user edited the text
71 // (it is not triggered when changing the value from JS code).
72 this.$hiddenInput.trigger( 'change' );
80 OO.inheritClass( mw.widgets.TitlesMultiselectWidget, OO.ui.MenuTagMultiselectWidget );
81 OO.mixinClass( mw.widgets.TitlesMultiselectWidget, OO.ui.mixin.RequestManager );
82 OO.mixinClass( mw.widgets.TitlesMultiselectWidget, OO.ui.mixin.PendingElement );
83 OO.mixinClass( mw.widgets.TitlesMultiselectWidget, mw.widgets.TitleWidget );
87 mw.widgets.TitlesMultiselectWidget.prototype.getQueryValue = function () {
88 return this.input.getValue();
94 mw.widgets.TitlesMultiselectWidget.prototype.onInputChange = function () {
98 this.menu.clearItems();
99 this.menu.addItems( this.getOptionsFromData( data ) );
102 mw.widgets.TitlesMultiselectWidget.super.prototype.onInputChange.call( this );
107 * We have an empty menu when the input is empty, override the implementation from
108 * MenuTagMultiselectWidget to avoid error and make tags editable.
110 * Only editable when the input is empty.
112 mw.widgets.TitlesMultiselectWidget.prototype.onTagSelect = function () {
113 if ( this.hasInput && !this.input.getValue() ) {
114 OO.ui.TagMultiselectWidget.prototype.onTagSelect.apply( this, arguments );
121 mw.widgets.TitlesMultiselectWidget.prototype.getRequestQuery = function () {
122 return this.getQueryValue();
128 mw.widgets.TitlesMultiselectWidget.prototype.getRequest = function () {
129 return this.getSuggestionsPromise();
135 mw.widgets.TitlesMultiselectWidget.prototype.getRequestCacheDataFromResponse = function ( response ) {
136 return response.query || {};