2 * JavaScript for Special:Preferences: Tab navigation.
6 var $preferences
, tabs
, wrapper
, previousTab
;
8 $preferences
= $( '#preferences' );
10 // Make sure the accessibility tip is selectable so that screen reader users take notice,
11 // but hide it per default to reduce interface clutter. Also make sure it becomes visible
12 // when selected. Similar to jquery.mw-jump
13 $( '<div>' ).addClass( 'mw-navigation-hint' )
14 .text( mw
.msg( 'prefs-tabs-navigation-hint' ) )
15 .attr( 'tabIndex', 0 )
16 .on( 'focus blur', function ( e
) {
17 if ( e
.type
=== 'blur' || e
.type
=== 'focusout' ) {
18 $( this ).css( 'height', '0' );
20 $( this ).css( 'height', 'auto' );
22 } ).prependTo( '#mw-content-text' );
24 tabs
= new OO
.ui
.IndexLayout( {
26 // Do not remove focus from the tabs menu after choosing a tab
30 mw
.config
.get( 'wgPreferencesTabs' ).forEach( function ( tabConfig
) {
31 var panel
, $panelContents
;
33 panel
= new OO
.ui
.TabPanelLayout( tabConfig
.name
, {
35 label
: tabConfig
.label
37 $panelContents
= $( '#mw-prefsection-' + tabConfig
.name
);
39 // Hide the unnecessary PHP PanelLayouts
40 // (Do not use .remove(), as that would remove event handlers for everything inside them)
41 $panelContents
.parent().detach();
43 panel
.$element
.append( $panelContents
);
44 tabs
.addTabPanels( [ panel
] );
46 // Remove duplicate labels
47 // (This must be after .addTabPanels(), otherwise the tab item doesn't exist yet)
48 $panelContents
.children( 'legend' ).remove();
49 $panelContents
.attr( 'aria-labelledby', panel
.getTabItem().getElementId() );
52 wrapper
= new OO
.ui
.PanelLayout( {
57 wrapper
.$element
.append( tabs
.$element
);
58 $preferences
.prepend( wrapper
.$element
);
60 function updateHash( panel
) {
61 var scrollTop
, active
;
62 // Handle hash manually to prevent jumping,
63 // therefore save and restore scrollTop to prevent jumping.
64 scrollTop
= $( window
).scrollTop();
65 // Changing the hash apparently causes keyboard focus to be lost?
66 // Save and restore it. This makes no sense though.
67 active
= document
.activeElement
;
68 location
.hash
= '#mw-prefsection-' + panel
.getName();
72 $( window
).scrollTop( scrollTop
);
75 tabs
.on( 'set', updateHash
);
79 * @param {string} name the name of a tab without the prefix ("mw-prefsection-")
80 * @param {string} [mode] A hash will be set according to the current
81 * open section. Set mode 'noHash' to supress this.
83 function switchPrefTab( name
, mode
) {
84 if ( mode
=== 'noHash' ) {
85 tabs
.off( 'set', updateHash
);
87 tabs
.setTabPanel( name
);
88 if ( mode
=== 'noHash' ) {
89 tabs
.on( 'set', updateHash
);
93 // Jump to correct section as indicated by the hash.
94 // This function is called onload and onhashchange.
95 function detectHash() {
96 var hash
= location
.hash
,
97 matchedElement
, parentSection
;
98 if ( hash
.match( /^#mw-prefsection-[\w]+$/ ) ) {
99 mw
.storage
.session
.remove( 'mwpreferences-prevTab' );
100 switchPrefTab( hash
.replace( '#mw-prefsection-', '' ) );
101 } else if ( hash
.match( /^#mw-[\w-]+$/ ) ) {
102 matchedElement
= document
.getElementById( hash
.slice( 1 ) );
103 parentSection
= $( matchedElement
).parent().closest( '[id^="mw-prefsection-"]' );
104 if ( parentSection
.length
) {
105 mw
.storage
.session
.remove( 'mwpreferences-prevTab' );
106 // Switch to proper tab and scroll to selected item.
107 switchPrefTab( parentSection
.attr( 'id' ).replace( 'mw-prefsection-', '' ), 'noHash' );
108 matchedElement
.scrollIntoView();
113 // Handle other things that change the hash (e.g. using
114 // the Back and Forward browser navigation).
115 if ( 'onhashchange' in window
) {
116 $( window
).on( 'hashchange', function () {
117 var hash
= location
.hash
;
118 if ( hash
.match( /^#mw-[\w-]+/ ) ) {
120 } else if ( hash
=== '' ) {
121 switchPrefTab( 'personal', 'noHash' );
126 // If we've reloaded the page or followed an open-in-new-window,
127 // make the selected tab visible.
130 // Restore the active tab after saving the preferences
131 previousTab
= mw
.storage
.session
.get( 'mwpreferences-prevTab' );
133 switchPrefTab( previousTab
, 'noHash' );
134 // Deleting the key, the tab states should be reset until we press Save
135 mw
.storage
.session
.remove( 'mwpreferences-prevTab' );
138 $( '#mw-prefs-form' ).on( 'submit', function () {
139 var value
= tabs
.getCurrentTabPanelName();
140 mw
.storage
.session
.set( 'mwpreferences-prevTab', value
);
144 }( mediaWiki
, jQuery
) );