Merge "Fix at end navigation condition for query pages"
[mediawiki.git] / resources / mediawiki.special / mediawiki.special.preferences.js
blob0804825089600f29e8cbf1548f409b83c796a573
1 /*
2  * JavaScript for Special:Preferences
3  */
4 jQuery( document ).ready( function ( $ ) {
5 $( '#prefsubmit' ).attr( 'id', 'prefcontrol' );
6 var $preftoc = $('<ul id="preftoc"></ul>');
7 var $preferences = $( '#preferences' )
8         .addClass( 'jsprefs' )
9         .before( $preftoc );
11 var $fieldsets = $preferences.children( 'fieldset' )
12         .hide()
13         .addClass( 'prefsection' );
15 var $legends = $fieldsets.children( 'legend' )
16         .addClass( 'mainLegend' );
18 /**
19  * It uses document.getElementById for security reasons (html injections in
20  * jQuery()).
21  *
22  * @param String name: the name of a tab without the prefix ("mw-prefsection-")
23  * @param String mode: [optional] A hash will be set according to the current
24  * open section. Set mode 'noHash' to surpress this.
25  */
26 function switchPrefTab( name, mode ) {
27         var $tab, scrollTop;
28         // Handle hash manually to prevent jumping,
29         // therefore save and restore scrollTop to prevent jumping.
30         scrollTop = $( window ).scrollTop();
31         if ( mode !== 'noHash' ) {
32                 window.location.hash = '#mw-prefsection-' + name;
33         }
34         $( window ).scrollTop( scrollTop );
36         $preftoc.find( 'li' ).removeClass( 'selected' );
37         $tab = $( document.getElementById( 'preftab-' + name ) );
38         if ( $tab.length ) {
39                 $tab.parent().addClass( 'selected' );
40                 $preferences.children( 'fieldset' ).hide();
41                 $( document.getElementById( 'mw-prefsection-' + name ) ).show();
42         }
45 // Populate the prefToc
46 $legends.each( function ( i, legend ) {
47         var $legend = $(legend);
48         if ( i === 0 ) {
49                 $legend.parent().show();
50         }
51         var ident = $legend.parent().attr( 'id' );
53         var $li = $( '<li/>', {
54                 'class' : ( i === 0 ) ? 'selected' : null
55         });
56         var $a = $( '<a/>', {
57                 text : $legend.text(),
58                 id : ident.replace( 'mw-prefsection', 'preftab' ),
59                 href : '#' + ident
60         });
61         $li.append( $a );
62         $preftoc.append( $li );
63 } );
65 // If we've reloaded the page or followed an open-in-new-window,
66 // make the selected tab visible.
67 var hash = window.location.hash;
68 if ( hash.match( /^#mw-prefsection-[\w-]+/ ) ) {
69         switchPrefTab( hash.replace( '#mw-prefsection-' , '' ) );
72 // In browsers that support the onhashchange event we will not bind click
73 // handlers and instead let the browser do the default behavior (clicking the
74 // <a href="#.."> will naturally set the hash, handled by onhashchange.
75 // But other things that change the hash will also be catched (e.g. using
76 // the Back and Forward browser navigation).
77 if ( 'onhashchange' in window ) {
78         $(window).on( 'hashchange' , function () {
79                 var hash = window.location.hash;
80                 if ( hash.match( /^#mw-prefsection-[\w-]+/ ) ) {
81                         switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
82                 } else if ( hash === '' ) {
83                         switchPrefTab( 'personal', 'noHash' );
84                 }
85         });
86 // In older browsers we'll bind a click handler as fallback.
87 // We must not have onhashchange *and* the click handlers, other wise
88 // the click handler calls switchPrefTab() which sets the hash value,
89 // which triggers onhashcange and calls switchPrefTab() again.
90 } else {
91         $preftoc.on( 'click', 'li a', function ( e ) {
92                 switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
93                 e.preventDefault();
94         });
97 /**
98 * Timezone functions.
99 * Guesses Timezone from browser and updates fields onchange
102 var $tzSelect = $( '#mw-input-wptimecorrection' );
103 var $tzTextbox = $( '#mw-input-wptimecorrection-other' );
105 var $localtimeHolder = $( '#wpLocalTime' );
106 var servertime = parseInt( $( 'input[name=wpServerTime]' ).val(), 10 );
107 var minuteDiff = 0;
109 var minutesToHours = function ( min ) {
110         var tzHour = Math.floor( Math.abs( min ) / 60 );
111         var tzMin = Math.abs( min ) % 60;
112         var tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
113                 ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
114         return tzString;
117 var hoursToMinutes = function ( hour ) {
118         var arr = hour.split( ':' );
119         arr[0] = parseInt( arr[0], 10 );
121         var minutes;
122         if ( arr.length == 1 ) {
123                 // Specification is of the form [-]XX
124                 minutes = arr[0] * 60;
125         } else {
126                 // Specification is of the form [-]XX:XX
127                 minutes = Math.abs( arr[0] ) * 60 + parseInt( arr[1], 10 );
128                 if ( arr[0] < 0 ) {
129                         minutes *= -1;
130                 }
131         }
132         // Gracefully handle non-numbers.
133         if ( isNaN( minutes ) ) {
134                 return 0;
135         } else {
136                 return minutes;
137         }
140 var updateTimezoneSelection = function () {
141         var type = $tzSelect.val();
142         if ( type == 'guess' ) {
143                 // Get browser timezone & fill it in
144                 minuteDiff = -new Date().getTimezoneOffset();
145                 $tzTextbox.val( minutesToHours( minuteDiff ) );
146                 $tzSelect.val( 'other' );
147                 $tzTextbox.get( 0 ).disabled = false;
148         } else if ( type == 'other' ) {
149                 // Grab data from the textbox, parse it.
150                 minuteDiff = hoursToMinutes( $tzTextbox.val() );
151         } else {
152                 // Grab data from the $tzSelect value
153                 minuteDiff = parseInt( type.split( '|' )[1], 10 ) || 0;
154                 $tzTextbox.val( minutesToHours( minuteDiff ) );
155         }
157         // Determine local time from server time and minutes difference, for display.
158         var localTime = servertime + minuteDiff;
160         // Bring time within the [0,1440) range.
161         while ( localTime < 0 ) {
162                 localTime += 1440;
163         }
164         while ( localTime >= 1440 ) {
165                 localTime -= 1440;
166         }
167         $localtimeHolder.text( minutesToHours( localTime ) );
170 if ( $tzSelect.length && $tzTextbox.length ) {
171         $tzSelect.change( function () { updateTimezoneSelection(); } );
172         $tzTextbox.blur( function () { updateTimezoneSelection(); } );
173         updateTimezoneSelection();
175 } );