Merge "auth: Follow up on e907d4328dc3e"
[lhc/web/wiklou.git] / resources / src / mediawiki.special.preferences.ooui / tabs.js
1 /*!
2 * JavaScript for Special:Preferences: Tab navigation.
3 */
4 ( function () {
5 $( function () {
6 var $preferences, tabs, wrapper, previousTab, switchingNoHash;
7
8 $preferences = $( '#preferences' );
9
10 // Make sure the accessibility tip is focussable so that keyboard users take notice,
11 // but hide it by default to reduce visual clutter.
12 // Make sure it becomes visible when focused.
13 $( '<div>' ).addClass( 'mw-navigation-hint' )
14 .text( mw.msg( 'prefs-tabs-navigation-hint' ) )
15 .attr( {
16 tabIndex: 0,
17 'aria-hidden': 'true'
18 } )
19 .insertBefore( '.mw-htmlform-ooui-wrapper' );
20
21 tabs = new OO.ui.IndexLayout( {
22 expanded: false,
23 // Do not remove focus from the tabs menu after choosing a tab
24 autoFocus: false
25 } );
26
27 mw.config.get( 'wgPreferencesTabs' ).forEach( function ( tabConfig ) {
28 var panel, $panelContents;
29
30 panel = new OO.ui.TabPanelLayout( tabConfig.name, {
31 expanded: false,
32 label: tabConfig.label
33 } );
34 $panelContents = $( '#mw-prefsection-' + tabConfig.name );
35
36 // Hide the unnecessary PHP PanelLayouts
37 // (Do not use .remove(), as that would remove event handlers for everything inside them)
38 $panelContents.parent().detach();
39
40 panel.$element.append( $panelContents );
41 tabs.addTabPanels( [ panel ] );
42
43 // Remove duplicate labels
44 // (This must be after .addTabPanels(), otherwise the tab item doesn't exist yet)
45 $panelContents.children( 'legend' ).remove();
46 $panelContents.attr( 'aria-labelledby', panel.getTabItem().getElementId() );
47 } );
48
49 wrapper = new OO.ui.PanelLayout( {
50 expanded: false,
51 padded: false,
52 framed: true
53 } );
54 wrapper.$element.append( tabs.$element );
55 $preferences.prepend( wrapper.$element );
56 $( '.mw-prefs-faketabs' ).remove();
57
58 function enhancePanel( panel ) {
59 if ( !panel.$element.data( 'mw-section-infused' ) ) {
60 // mw-htmlform-autoinfuse-lazy class has been removed by replacing faketabs
61 mw.hook( 'htmlform.enhance' ).fire( panel.$element );
62 panel.$element.data( 'mw-section-infused', true );
63 }
64 }
65
66 function onTabPanelSet( panel ) {
67 var scrollTop, active;
68
69 if ( switchingNoHash ) {
70 return;
71 }
72 // Handle hash manually to prevent jumping,
73 // therefore save and restore scrollTop to prevent jumping.
74 scrollTop = $( window ).scrollTop();
75 // Changing the hash apparently causes keyboard focus to be lost?
76 // Save and restore it. This makes no sense though.
77 active = document.activeElement;
78 location.hash = '#mw-prefsection-' + panel.getName();
79 if ( active ) {
80 active.focus();
81 }
82 $( window ).scrollTop( scrollTop );
83 }
84
85 tabs.on( 'set', onTabPanelSet );
86
87 /**
88 * @ignore
89 * @param {string} name the name of a tab without the prefix ("mw-prefsection-")
90 * @param {boolean} [noHash] A hash will be set according to the current
91 * open section. Use this flag to suppress this.
92 */
93 function switchPrefTab( name, noHash ) {
94 if ( noHash ) {
95 switchingNoHash = true;
96 }
97 tabs.setTabPanel( name );
98 enhancePanel( tabs.getCurrentTabPanel() );
99 if ( noHash ) {
100 switchingNoHash = false;
101 }
102 }
103
104 // Jump to correct section as indicated by the hash.
105 // This function is called onload and onhashchange.
106 function detectHash() {
107 var hash = location.hash,
108 matchedElement, parentSection;
109 if ( hash.match( /^#mw-prefsection-[\w]+$/ ) ) {
110 mw.storage.session.remove( 'mwpreferences-prevTab' );
111 switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
112 } else if ( hash.match( /^#mw-[\w-]+$/ ) ) {
113 matchedElement = document.getElementById( hash.slice( 1 ) );
114 parentSection = $( matchedElement ).parent().closest( '[id^="mw-prefsection-"]' );
115 if ( parentSection.length ) {
116 mw.storage.session.remove( 'mwpreferences-prevTab' );
117 // Switch to proper tab and scroll to selected item.
118 switchPrefTab( parentSection.attr( 'id' ).replace( 'mw-prefsection-', '' ), true );
119 matchedElement.scrollIntoView();
120 }
121 }
122 }
123
124 $( window ).on( 'hashchange', function () {
125 var hash = location.hash;
126 if ( hash.match( /^#mw-[\w-]+/ ) ) {
127 detectHash();
128 } else if ( hash === '' ) {
129 switchPrefTab( 'personal', true );
130 }
131 } )
132 // Run the function immediately to select the proper tab on startup.
133 .trigger( 'hashchange' );
134
135 // Restore the active tab after saving the preferences
136 previousTab = mw.storage.session.get( 'mwpreferences-prevTab' );
137 if ( previousTab ) {
138 switchPrefTab( previousTab, true );
139 // Deleting the key, the tab states should be reset until we press Save
140 mw.storage.session.remove( 'mwpreferences-prevTab' );
141 }
142
143 $( '#mw-prefs-form' ).on( 'submit', function () {
144 var value = tabs.getCurrentTabPanelName();
145 mw.storage.session.set( 'mwpreferences-prevTab', value );
146 } );
147
148 } );
149 }() );