Check each Special:Preferences input for changes
authorGeoffrey Mon <geofbot@gmail.com>
Thu, 26 Nov 2015 21:41:41 +0000 (16:41 -0500)
committerDerk-Jan Hartman <hartman.wiki@gmail.com>
Fri, 25 Dec 2015 21:19:58 +0000 (22:19 +0100)
When checking for changes in the Special:Preferences form, instead of serializing
original form data (which fails with asynchronous loading of JS, if the user changes
something before JS is done loading), compare the value of each input to the default
value.

Bug: T119732
Change-Id: Ib48a9b334f639e417a0642c6c090ba18afc477ce

resources/src/mediawiki.special/mediawiki.special.preferences.js

index f90f859..7f3de38 100644 (file)
                        } );
                }
 
+               // Check if all of the form values are unchanged
+               function isPrefsChanged() {
+                       var inputs = $( '#mw-prefs-form :input' ),
+                               input, $input, inputType,
+                               index, optIndex,
+                               opt;
+
+                       for ( index = 0; index < inputs.length; index++ ) {
+                               input = inputs[ index ];
+                               $input = $( input );
+
+                               // Different types of inputs have different methods for accessing defaults
+                               if ( $input.is( 'select' ) ) { // <select> has the property defaultSelected for each option
+                                       for ( optIndex = 0; optIndex < input.options.length; optIndex++ ) {
+                                               opt = input.options[ optIndex ];
+                                               if ( opt.selected !== opt.defaultSelected ) {
+                                                       return true;
+                                               }
+                                       }
+                               } else if ( $input.is( 'input' ) ) { // <input> has defaultValue or defaultChecked
+                                       inputType = input.type;
+                                       if ( inputType === 'radio' || inputType === 'checkbox' ) {
+                                               if ( input.checked !== input.defaultChecked ) {
+                                                       return true;
+                                               }
+                                       } else if ( input.value !== input.defaultValue ) {
+                                               return true;
+                                       }
+                               }
+                       }
+
+                       return false;
+               }
+
                // Set up a message to notify users if they try to leave the page without
                // saving.
-               $( '#mw-prefs-form' ).data( 'origdata', $( '#mw-prefs-form' ).serialize() );
                allowCloseWindow = mw.confirmCloseWindow( {
-                       test: function () {
-                               return $( '#mw-prefs-form' ).serialize() !== $( '#mw-prefs-form' ).data( 'origdata' );
-                       },
-
+                       test: isPrefsChanged,
                        message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ),
                        namespace: 'prefswarning'
                } );