Merge "Update docs/hooks.txt for ShowSearchHitTitle"
[mediawiki.git] / resources / src / mediawiki / htmlform / multiselect.js
blob37c0554acd8e61da2c184001f7e3e368797b3715
1 /*
2  * HTMLForm enhancements:
3  * Convert multiselect fields from checkboxes to Chosen selector when requested.
4  */
5 ( function ( mw, $ ) {
7         function addMulti( $oldContainer, $container ) {
8                 var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ),
9                         oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen|mw-htmlform-dropdown)/g, '' ),
10                         $select = $( '<select>' ),
11                         dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' );
12                 oldClass = $.trim( oldClass );
13                 $select.attr( {
14                         name: name,
15                         multiple: 'multiple',
16                         'data-placeholder': dataPlaceholder.plain(),
17                         'class': 'htmlform-chzn-select mw-input ' + oldClass
18                 } );
19                 $oldContainer.find( 'input' ).each( function () {
20                         var $oldInput = $( this ),
21                                 checked = $oldInput.prop( 'checked' ),
22                                 $option = $( '<option>' );
23                         $option.prop( 'value', $oldInput.prop( 'value' ) );
24                         if ( checked ) {
25                                 $option.prop( 'selected', true );
26                         }
27                         $option.text( $oldInput.prop( 'value' ) );
28                         $select.append( $option );
29                 } );
30                 $container.append( $select );
31         }
33         function convertCheckboxesToMulti( $oldContainer, type ) {
34                 var $fieldLabel = $( '<td>' ),
35                         $td = $( '<td>' ),
36                         $fieldLabelText = $( '<label>' ),
37                         $container;
38                 if ( type === 'tr' ) {
39                         addMulti( $oldContainer, $td );
40                         $container = $( '<tr>' );
41                         $container.append( $td );
42                 } else if ( type === 'div' ) {
43                         $fieldLabel = $( '<div>' );
44                         $container = $( '<div>' );
45                         addMulti( $oldContainer, $container );
46                 }
47                 $fieldLabel.attr( 'class', 'mw-label' );
48                 $fieldLabelText.text( $oldContainer.find( '.mw-label label' ).text() );
49                 $fieldLabel.append( $fieldLabelText );
50                 $container.prepend( $fieldLabel );
51                 $oldContainer.replaceWith( $container );
52                 return $container;
53         }
55         function convertCheckboxesWidgetToCapsules( fieldLayout ) {
56                 var checkboxesWidget, checkboxesOptions, capsulesOptions, capsulesWidget;
58                 checkboxesWidget = fieldLayout.fieldWidget;
59                 checkboxesOptions = checkboxesWidget.checkboxMultiselectWidget.getItems();
60                 capsulesOptions = checkboxesOptions.map( function ( option ) {
61                         return new OO.ui.MenuOptionWidget( {
62                                 data: option.getData(),
63                                 label: option.getLabel()
64                         } );
65                 } );
66                 capsulesWidget = new OO.ui.CapsuleMultiselectWidget( {
67                         menu: {
68                                 items: capsulesOptions
69                         }
70                 } );
71                 capsulesWidget.setItemsFromData( checkboxesWidget.getValue() );
73                 // Data from CapsuleMultiselectWidget will not be submitted with the form, so keep the original
74                 // CheckboxMultiselectInputWidget up-to-date.
75                 capsulesWidget.on( 'change', function () {
76                         checkboxesWidget.setValue( capsulesWidget.getItemsData() );
77                 } );
79                 // Hide original widget and add new one in its place. This is a bit hacky, since the FieldLayout
80                 // still thinks it's connected to the old widget.
81                 checkboxesWidget.toggle( false );
82                 checkboxesWidget.$element.after( capsulesWidget.$element );
83         }
85         mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
86                 var $dropdowns = $root.find( '.mw-htmlform-field-HTMLMultiSelectField.mw-htmlform-dropdown' );
87                 if ( $dropdowns.length ) {
88                         $dropdowns.each( function () {
89                                 var $el = $( this ),
90                                         data, modules, extraModules;
91                                 if ( $el.is( '[data-ooui]' ) ) {
92                                         // Load 'oojs-ui-widgets' for CapsuleMultiselectWidget
93                                         modules = [ 'mediawiki.htmlform.ooui', 'oojs-ui-widgets' ];
94                                         data = $el.data( 'mw-modules' );
95                                         if ( data ) {
96                                                 // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
97                                                 extraModules = data.split( ',' );
98                                                 modules.push.apply( modules, extraModules );
99                                         }
100                                         mw.loader.using( modules, function () {
101                                                 convertCheckboxesWidgetToCapsules( OO.ui.FieldLayout.static.infuse( $el ) );
102                                         } );
103                                 } else {
104                                         mw.loader.using( 'jquery.chosen', function () {
105                                                 var type = $el.is( 'tr' ) ? 'tr' : 'div',
106                                                         $converted = convertCheckboxesToMulti( $el, type );
107                                                 $converted.find( '.htmlform-chzn-select' ).chosen( { width: 'auto' } );
108                                         } );
109                                 }
110                         } );
111                 }
112         } );
114 }( mediaWiki, jQuery ) );