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