From 51a4c783e8900fdfabc353573991367ab63e11cf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Fri, 15 Sep 2017 20:45:24 +0200 Subject: [PATCH] Split mediawiki.special.preferences into separate file for each function This JavaScript code does four things: * Convert a simple form into one with tab navigation * Convert a simple message box into pretty notifications * Prevent browser window from being closed with unsaved changes to preferences * Add some enhancements to the timezone field I will be making some large changes here for T117781 and having everything mixed in one file was making that difficult. I avoided making any cleanup changes to make it easier to review this change. Change-Id: I5e31a661177002e40708614011c1f7e08ec4f44d --- resources/Resources.php | 7 +- ...iawiki.special.preferences.confirmClose.js | 63 ++++++++ ...i.special.preferences.convertmessagebox.js | 9 ++ ... => mediawiki.special.preferences.tabs.js} | 144 +----------------- .../mediawiki.special.preferences.timezone.js | 92 +++++++++++ 5 files changed, 172 insertions(+), 143 deletions(-) create mode 100644 resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js create mode 100644 resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js rename resources/src/mediawiki.special/{mediawiki.special.preferences.js => mediawiki.special.preferences.tabs.js} (55%) create mode 100644 resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js diff --git a/resources/Resources.php b/resources/Resources.php index 10786dacaa..52dccdbc4c 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -2092,7 +2092,12 @@ return [ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css', ], 'mediawiki.special.preferences' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.preferences.js', + 'scripts' => [ + 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js', + 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js', + 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js', + 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js', + ], 'messages' => [ 'prefs-tabs-navigation-hint', 'prefswarning-warning', diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js b/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js new file mode 100644 index 0000000000..45df37ffd2 --- /dev/null +++ b/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js @@ -0,0 +1,63 @@ +/*! + * JavaScript for Special:Preferences: Enable save button and prevent the window being accidentally + * closed when any form field is changed. + */ +( function ( mw, $ ) { + $( function () { + var allowCloseWindow; + + // Check if all of the form values are unchanged + function isPrefsChanged() { + var inputs = $( '#mw-prefs-form :input[name]' ), + 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' ) ) { + // 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; + } + + // Disable the button to save preferences unless preferences have changed + // Check if preferences have been changed before JS has finished loading + if ( !isPrefsChanged() ) { + $( '#prefcontrol' ).prop( 'disabled', true ); + $( '#preferences > fieldset' ).one( 'change keydown mousedown', function () { + $( '#prefcontrol' ).prop( 'disabled', false ); + } ); + } + + // Set up a message to notify users if they try to leave the page without + // saving. + allowCloseWindow = mw.confirmCloseWindow( { + test: isPrefsChanged, + message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ), + namespace: 'prefswarning' + } ); + $( '#mw-prefs-form' ).submit( $.proxy( allowCloseWindow, 'release' ) ); + $( '#mw-prefs-restoreprefs' ).click( $.proxy( allowCloseWindow, 'release' ) ); + } ); +}( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js b/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js new file mode 100644 index 0000000000..cee7382963 --- /dev/null +++ b/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js @@ -0,0 +1,9 @@ +/*! + * JavaScript for Special:Preferences: Check for successbox to replace with notifications. + */ +( function ( mw, $ ) { + $( function () { + var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' ); + convertmessagebox(); + } ); +}( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.js b/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js similarity index 55% rename from resources/src/mediawiki.special/mediawiki.special.preferences.js rename to resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js index b86f21838c..dcfad271d1 100644 --- a/resources/src/mediawiki.special/mediawiki.special.preferences.js +++ b/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js @@ -1,11 +1,9 @@ /*! - * JavaScript for Special:Preferences + * JavaScript for Special:Preferences: Tab navigation. */ ( function ( mw, $ ) { $( function () { - var $preftoc, $preferences, $fieldsets, labelFunc, previousTab, - $tzSelect, $tzTextbox, $localtimeHolder, servertime, allowCloseWindow, - convertmessagebox = require( 'mediawiki.notification.convertmessagebox' ); + var $preftoc, $preferences, $fieldsets, labelFunc, previousTab; labelFunc = function () { return this.id.replace( /^mw-prefsection/g, 'preftab' ); @@ -79,9 +77,6 @@ } } - // Check for successbox to replace with notifications - convertmessagebox(); - // Enable keyboard users to use left and right keys to switch tabs $preftoc.on( 'keydown', function ( event ) { var keyLeft = 37, @@ -153,88 +148,6 @@ detectHash(); } - // Timezone functions. - // Guesses Timezone from browser and updates fields onchange. - - $tzSelect = $( '#mw-input-wptimecorrection' ); - $tzTextbox = $( '#mw-input-wptimecorrection-other' ); - $localtimeHolder = $( '#wpLocalTime' ); - servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 ); - - function minutesToHours( min ) { - var tzHour = Math.floor( Math.abs( min ) / 60 ), - tzMin = Math.abs( min ) % 60, - tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour + - ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin; - return tzString; - } - - function hoursToMinutes( hour ) { - var minutes, - arr = hour.split( ':' ); - - arr[ 0 ] = parseInt( arr[ 0 ], 10 ); - - if ( arr.length === 1 ) { - // Specification is of the form [-]XX - minutes = arr[ 0 ] * 60; - } else { - // Specification is of the form [-]XX:XX - minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 ); - if ( arr[ 0 ] < 0 ) { - minutes *= -1; - } - } - // Gracefully handle non-numbers. - if ( isNaN( minutes ) ) { - return 0; - } else { - return minutes; - } - } - - function updateTimezoneSelection() { - var minuteDiff, localTime, - type = $tzSelect.val(); - - if ( type === 'other' ) { - // User specified time zone manually in - // Grab data from the textbox, parse it. - minuteDiff = hoursToMinutes( $tzTextbox.val() ); - } else { - // Time zone not manually specified by user - if ( type === 'guess' ) { - // Get browser timezone & fill it in - minuteDiff = -( new Date().getTimezoneOffset() ); - $tzTextbox.val( minutesToHours( minuteDiff ) ); - $tzSelect.val( 'other' ); - $tzTextbox.prop( 'disabled', false ); - } else { - // Grab data from the $tzSelect value - minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0; - $tzTextbox.val( minutesToHours( minuteDiff ) ); - } - - // Set defaultValue prop on the generated box so we don't trigger the - // unsaved preferences check - $tzTextbox.prop( 'defaultValue', $tzTextbox.val() ); - } - - // Determine local time from server time and minutes difference, for display. - localTime = servertime + minuteDiff; - - // Bring time within the [0,1440) range. - localTime = ( ( localTime % 1440 ) + 1440 ) % 1440; - - $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) ); - } - - if ( $tzSelect.length && $tzTextbox.length ) { - $tzSelect.change( updateTimezoneSelection ); - $tzTextbox.blur( updateTimezoneSelection ); - updateTimezoneSelection(); - } - // Restore the active tab after saving the preferences previousTab = mw.storage.session.get( 'mwpreferences-prevTab' ); if ( previousTab ) { @@ -248,58 +161,5 @@ mw.storage.session.set( 'mwpreferences-prevTab', value ); } ); - // Check if all of the form values are unchanged - function isPrefsChanged() { - var inputs = $( '#mw-prefs-form :input[name]' ), - 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' ) ) { - // 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; - } - - // Disable the button to save preferences unless preferences have changed - // Check if preferences have been changed before JS has finished loading - if ( !isPrefsChanged() ) { - $( '#prefcontrol' ).prop( 'disabled', true ); - $( '#preferences > fieldset' ).one( 'change keydown mousedown', function () { - $( '#prefcontrol' ).prop( 'disabled', false ); - } ); - } - - // Set up a message to notify users if they try to leave the page without - // saving. - allowCloseWindow = mw.confirmCloseWindow( { - test: isPrefsChanged, - message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ), - namespace: 'prefswarning' - } ); - $( '#mw-prefs-form' ).submit( $.proxy( allowCloseWindow, 'release' ) ); - $( '#mw-prefs-restoreprefs' ).click( $.proxy( allowCloseWindow, 'release' ) ); } ); }( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js b/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js new file mode 100644 index 0000000000..58a5f84a9f --- /dev/null +++ b/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js @@ -0,0 +1,92 @@ +/*! + * JavaScript for Special:Preferences: Timezone field enhancements. + */ +( function ( mw, $ ) { + $( function () { + var + $tzSelect, $tzTextbox, $localtimeHolder, servertime; + + // Timezone functions. + // Guesses Timezone from browser and updates fields onchange. + + $tzSelect = $( '#mw-input-wptimecorrection' ); + $tzTextbox = $( '#mw-input-wptimecorrection-other' ); + $localtimeHolder = $( '#wpLocalTime' ); + servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 ); + + function minutesToHours( min ) { + var tzHour = Math.floor( Math.abs( min ) / 60 ), + tzMin = Math.abs( min ) % 60, + tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour + + ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin; + return tzString; + } + + function hoursToMinutes( hour ) { + var minutes, + arr = hour.split( ':' ); + + arr[ 0 ] = parseInt( arr[ 0 ], 10 ); + + if ( arr.length === 1 ) { + // Specification is of the form [-]XX + minutes = arr[ 0 ] * 60; + } else { + // Specification is of the form [-]XX:XX + minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 ); + if ( arr[ 0 ] < 0 ) { + minutes *= -1; + } + } + // Gracefully handle non-numbers. + if ( isNaN( minutes ) ) { + return 0; + } else { + return minutes; + } + } + + function updateTimezoneSelection() { + var minuteDiff, localTime, + type = $tzSelect.val(); + + if ( type === 'other' ) { + // User specified time zone manually in + // Grab data from the textbox, parse it. + minuteDiff = hoursToMinutes( $tzTextbox.val() ); + } else { + // Time zone not manually specified by user + if ( type === 'guess' ) { + // Get browser timezone & fill it in + minuteDiff = -( new Date().getTimezoneOffset() ); + $tzTextbox.val( minutesToHours( minuteDiff ) ); + $tzSelect.val( 'other' ); + $tzTextbox.prop( 'disabled', false ); + } else { + // Grab data from the $tzSelect value + minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0; + $tzTextbox.val( minutesToHours( minuteDiff ) ); + } + + // Set defaultValue prop on the generated box so we don't trigger the + // unsaved preferences check + $tzTextbox.prop( 'defaultValue', $tzTextbox.val() ); + } + + // Determine local time from server time and minutes difference, for display. + localTime = servertime + minuteDiff; + + // Bring time within the [0,1440) range. + localTime = ( ( localTime % 1440 ) + 1440 ) % 1440; + + $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) ); + } + + if ( $tzSelect.length && $tzTextbox.length ) { + $tzSelect.change( updateTimezoneSelection ); + $tzTextbox.blur( updateTimezoneSelection ); + updateTimezoneSelection(); + } + + } ); +}( mediaWiki, jQuery ) ); -- 2.20.1