Merge "RCFilters UI: Ajaxify everything"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / ui / mw.rcfilters.ui.FormWrapperWidget.js
1 ( function ( mw ) {
2 /**
3 * Wrapper for the RC form with hide/show links
4 *
5 * @extends OO.ui.Widget
6 *
7 * @constructor
8 * @param {mw.rcfilters.dm.ChangesListViewModel} model Changes list view model
9 * @param {mw.rcfilters.Controller} controller RCfilters controller
10 * @param {jQuery} $formRoot Root element of the form to attach to
11 * @param {Object} config Configuration object
12 */
13 mw.rcfilters.ui.FormWrapperWidget = function MwRcfiltersUiFormWrapperWidget( model, controller, $formRoot, config ) {
14 config = config || {};
15
16 // Parent
17 mw.rcfilters.ui.FormWrapperWidget.parent.call( this, $.extend( {}, config, {
18 $element: $formRoot
19 } ) );
20 // Mixin constructors
21 OO.ui.mixin.PendingElement.call( this, config );
22
23 this.model = model;
24 this.controller = controller;
25 this.$submitButton = this.$element.find( 'form input[type=submit]' );
26
27 this.$element
28 .on( 'click', 'a[data-params]', this.onLinkClick.bind( this ) );
29
30 this.$element
31 .on( 'submit', 'form', this.onFormSubmit.bind( this ) );
32
33 // Events
34 this.model.connect( this, {
35 invalidate: 'onModelInvalidate',
36 update: 'onModelUpdate'
37 } );
38
39 // Initialize
40 this.cleanupForm();
41 this.$element
42 .addClass( 'mw-rcfilters-ui-FormWrapperWidget' )
43 .addClass( 'mw-rcfilters-ui-ready' );
44 };
45
46 /* Initialization */
47
48 OO.inheritClass( mw.rcfilters.ui.FormWrapperWidget, OO.ui.Widget );
49 OO.mixinClass( mw.rcfilters.ui.FormWrapperWidget, OO.ui.mixin.PendingElement );
50
51 /**
52 * Clean up the base form we're getting from the back-end.
53 * Remove <strong> tags and replace those with classes, so
54 * we can toggle those on click.
55 */
56 mw.rcfilters.ui.FormWrapperWidget.prototype.cleanupForm = function () {
57 this.$element.find( '[data-keys] strong' ).each( function () {
58 $( this )
59 .parent().addClass( 'mw-rcfilters-staticfilters-selected' );
60
61 $( this )
62 .replaceWith( $( this ).contents() );
63 } );
64 };
65
66 /**
67 * Respond to link click
68 *
69 * @param {jQuery.Event} e Event
70 * @return {boolean} false
71 */
72 mw.rcfilters.ui.FormWrapperWidget.prototype.onLinkClick = function ( e ) {
73 var $element = $( e.target ),
74 data = $element.data( 'params' ),
75 keys = $element.data( 'keys' ),
76 $similarElements = $element.parent().find( '[data-keys="' + keys + '"]' );
77
78 // Only highlight choice if this link isn't a show/hide link
79 if ( !$element.parents( '.rcshowhideoption' ).length ) {
80 // Remove the class from similar elements
81 $similarElements.removeClass( 'mw-rcfilters-staticfilters-selected' );
82 // Add the class to this element
83 $element.addClass( 'mw-rcfilters-staticfilters-selected' );
84 }
85
86 e.stopPropagation();
87
88 this.controller.updateChangesList( data );
89 return false;
90 };
91
92 /**
93 * Respond to form submit event
94 *
95 * @param {jQuery.Event} e Event
96 * @return {boolean} false
97 */
98 mw.rcfilters.ui.FormWrapperWidget.prototype.onFormSubmit = function ( e ) {
99 var data = {};
100
101 // Collect all data from form
102 $( e.target ).find( 'input:not([type="hidden"],[type="submit"]), select' ).each( function () {
103 if ( !$( this ).is( ':checkbox' ) || $( this ).is( ':checked' ) ) {
104 data[ $( this ).prop( 'name' ) ] = $( this ).val();
105 }
106 } );
107
108 this.controller.updateChangesList( data );
109 return false;
110 };
111
112 /**
113 * Respond to model invalidate
114 */
115 mw.rcfilters.ui.FormWrapperWidget.prototype.onModelInvalidate = function () {
116 this.pushPending();
117 this.$submitButton.prop( 'disabled', true );
118 };
119
120 /**
121 * Respond to model update, replace the show/hide links with the ones from the
122 * server so they feature the correct state.
123 *
124 * @param {jQuery|string} $changesList Updated changes list
125 * @param {jQuery} $fieldset Updated fieldset
126 */
127 mw.rcfilters.ui.FormWrapperWidget.prototype.onModelUpdate = function ( $changesList, $fieldset ) {
128 this.$submitButton.prop( 'disabled', false );
129
130 // Replace the links we have in the content
131 // We don't want to replace the entire thing, because there is a big difference between
132 // the links in the backend and the links we have initialized, since we are removing
133 // the ones that are implemented in the new system
134 this.$element.find( '.rcshowhide' ).children().each( function () {
135 // Go over existing links and replace only them
136 var classes = $( this ).attr( 'class' ).split( ' ' ),
137 // Look for that item in the fieldset from the server
138 $remoteItem = $fieldset.find( '.' + classes.join( '.' ) );
139
140 if ( $remoteItem ) {
141 $( this ).replaceWith( $remoteItem );
142 }
143 } );
144
145 this.popPending();
146 };
147 }( mediaWiki ) );