* @return array|null
*/
static function getPreferences( $user, IContextSource $context ) {
- OutputPage::setupOOUI(
- strtolower( $context->getSkin()->getSkinName() ),
- $context->getLanguage()->getDir()
- );
-
$defaultPreferences = [];
self::profilePreferences( $user, $context, $defaultPreferences );
if ( $canEditPrivateInfo && $authManager->allowsAuthenticationDataChange(
new PasswordAuthenticationRequest(), false )->isGood()
) {
- $link = new OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'ChangePassword' )->getLinkURL( [
- 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText()
- ] ),
- 'label' => $context->msg( 'prefs-resetpass' )->text(),
- ] );
+ $link = $linkRenderer->makeLink( SpecialPage::getTitleFor( 'ChangePassword' ),
+ $context->msg( 'prefs-resetpass' )->text(), [],
+ [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
$defaultPreferences['password'] = [
'type' => 'info',
'raw' => true,
- 'default' => (string)$link,
+ 'default' => $link,
'label-message' => 'yourpassword',
'section' => 'personal/info',
];
$emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
if ( $canEditPrivateInfo && $authManager->allowsPropertyChange( 'emailaddress' ) ) {
- $link = new OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'ChangeEmail' )->getLinkURL( [
- 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText()
- ] ),
- 'label' =>
- $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->text(),
- ] );
-
- $emailAddress .= $emailAddress == '' ? $link : ( '<br />' . $link );
+ $link = $linkRenderer->makeLink(
+ SpecialPage::getTitleFor( 'ChangeEmail' ),
+ $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->text(),
+ [],
+ [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
+
+ $emailAddress .= $emailAddress == '' ? $link : (
+ $context->msg( 'word-separator' )->escaped()
+ . $context->msg( 'parentheses' )->rawParams( $link )->escaped()
+ );
}
$defaultPreferences['emailaddress'] = [
} else {
$disableEmailPrefs = true;
$emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' .
- new OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'Confirmemail' )->getLinkURL(),
- 'label' => $context->msg( 'emailconfirmlink' )->text(),
- ] );
+ $linkRenderer->makeKnownLink(
+ SpecialPage::getTitleFor( 'Confirmemail' ),
+ $context->msg( 'emailconfirmlink' )->text()
+ ) . '<br />';
$emailauthenticationclass = "mw-email-not-authenticated";
}
} else {
'default' => $tzSetting,
'size' => 20,
'section' => 'rendering/timeoffset',
- 'id' => 'wpTimeCorrection',
];
}
# # Watchlist #####################################
if ( $user->isAllowed( 'editmywatchlist' ) ) {
- $editWatchlistLinks = '';
+ $editWatchlistLinks = [];
$editWatchlistModes = [
'edit' => [ 'EditWatchlist', false ],
'raw' => [ 'EditWatchlist', 'raw' ],
$linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
foreach ( $editWatchlistModes as $editWatchlistMode => $mode ) {
// Messages: prefs-editwatchlist-edit, prefs-editwatchlist-raw, prefs-editwatchlist-clear
- $editWatchlistLinks .=
- new OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( $mode[0], $mode[1] )->getLinkURL(),
- 'label' => new OOUI\HtmlSnippet(
- $context->msg( "prefs-editwatchlist-{$editWatchlistMode}" )->parse()
- ),
- ] );
+ $editWatchlistLinks[] = $linkRenderer->makeKnownLink(
+ SpecialPage::getTitleFor( $mode[0], $mode[1] ),
+ new HtmlArmor( $context->msg( "prefs-editwatchlist-{$editWatchlistMode}" )->parse() )
+ );
}
$defaultPreferences['editwatchlist'] = [
'type' => 'info',
'raw' => true,
- 'default' => $editWatchlistLinks,
+ 'default' => $context->getLanguage()->pipeList( $editWatchlistLinks ),
'label-message' => 'prefs-editwatchlist-label',
'section' => 'watchlist/editwatchlist',
];
$defaultPreferences['watchlisttoken'] = [
'type' => 'api',
];
-
- $tokenButton = new OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'ResetTokens' )->getLinkURL( [
- 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText()
- ] ),
- 'label' => $context->msg( 'prefs-watchlist-managetokens' )->text(),
- ] );
$defaultPreferences['watchlisttoken-info'] = [
'type' => 'info',
'section' => 'watchlist/tokenwatchlist',
'label-message' => 'prefs-watchlist-token',
- 'help-message' => 'prefs-help-tokenmanagement',
- 'raw' => true,
- 'default' => (string)$tokenButton,
+ 'default' => $user->getTokenFromOption( 'watchlisttoken' ),
+ 'help-message' => 'prefs-help-watchlist-token2',
];
}
}
$formClass = 'PreferencesForm',
array $remove = []
) {
- // We use ButtonWidgets in some of the getPreferences() functions
- $context->getOutput()->enableOOUI();
-
$formDescriptor = self::getPreferences( $user, $context );
if ( count( $remove ) ) {
$removeKeys = array_flip( $remove );
public function alterForm( HTMLForm $form ) {
$resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
- $form->setSubmitDestructive();
-
$form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
$i = 0;
return;
}
- $out->addModules( 'mediawiki.special.preferences.ooui' );
- $out->addModuleStyles( 'mediawiki.special.preferences.styles.ooui' );
+ $out->addModules( 'mediawiki.special.preferences' );
+ $out->addModuleStyles( 'mediawiki.special.preferences.styles' );
$session = $this->getRequest()->getSession();
if ( $session->get( 'specialPreferencesSaveSuccess' ) ) {
$htmlForm = $this->getFormObject( $user, $this->getContext() );
$htmlForm->setSubmitCallback( [ 'Preferences', 'tryUISubmit' ] );
-
- $prefTabs = [];
- foreach ( $htmlForm->getPreferenceSections() as $key ) {
- $prefTabs[] = [
- 'name' => $key,
- 'label' => $htmlForm->getLegend( $key ),
- ];
+ $sectionTitles = $htmlForm->getPreferenceSections();
+
+ $prefTabs = '';
+ foreach ( $sectionTitles as $key ) {
+ $prefTabs .= Html::rawElement( 'li',
+ [
+ 'role' => 'presentation',
+ 'class' => ( $key === 'personal' ) ? 'selected' : null
+ ],
+ Html::rawElement( 'a',
+ [
+ 'id' => 'preftab-' . $key,
+ 'role' => 'tab',
+ 'href' => '#mw-prefsection-' . $key,
+ 'aria-controls' => 'mw-prefsection-' . $key,
+ 'aria-selected' => ( $key === 'personal' ) ? 'true' : 'false',
+ 'tabIndex' => ( $key === 'personal' ) ? 0 : -1,
+ ],
+ $htmlForm->getLegend( $key )
+ )
+ );
}
- $out->addJsConfigVars( 'wgPreferencesTabs', $prefTabs );
-
- // TODO: Render fake tabs here to avoid FOUC.
- // $out->addHTML( $fakeTabs );
+ $out->addHTML(
+ Html::rawElement( 'ul',
+ [
+ 'id' => 'preftoc',
+ 'role' => 'tablist'
+ ],
+ $prefTabs )
+ );
$htmlForm->show();
}
$context = new DerivativeContext( $this->getContext() );
$context->setTitle( $this->getPageTitle( 'reset' ) ); // Reset subpage
- $htmlForm = HTMLForm::factory( 'ooui', [], $context, 'prefs-restore' );
+ $htmlForm = new HTMLForm( [], $context, 'prefs-restore' );
$htmlForm->setSubmitTextMsg( 'restoreprefs' );
$htmlForm->setSubmitDestructive();
* @param HTMLForm $form
*/
protected function alterForm( HTMLForm $form ) {
- $form->setSubmitDestructive();
if ( $this->getTokensList() ) {
$form->setSubmitTextMsg( 'resettokens-resetbutton' );
} else {
* @file
*/
+use MediaWiki\MediaWikiServices;
+
/**
* Form to edit user preferences.
*/
-class PreferencesForm extends OOUIHTMLForm {
+class PreferencesForm extends HTMLForm {
// Override default value from HTMLForm
protected $mSubSectionBeforeFields = false;
* @return string
*/
function getButtons() {
+ $attrs = [ 'id' => 'mw-prefs-restoreprefs' ];
+
if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
return '';
}
if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
$t = $this->getTitle()->getSubpage( 'reset' );
- $html .= new OOUI\ButtonWidget( [
- 'infusable' => true,
- 'id' => 'mw-prefs-restoreprefs',
- 'label' => $this->msg( 'restoreprefs' )->text(),
- 'href' => $t->getLinkURL(),
- 'flags' => [ 'destructive' ],
- 'framed' => false,
- ] );
+ $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+ $html .= "\n" . $linkRenderer->makeLink( $t, $this->msg( 'restoreprefs' )->text(),
+ Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ) );
$html = Xml::tags( 'div', [ 'class' => 'mw-prefs-buttons' ], $html );
}
"prefs-watchlist-edits": "Maximum number of changes to show in watchlist:",
"prefs-watchlist-edits-max": "Maximum number: 1000",
"prefs-watchlist-token": "Watchlist token:",
- "prefs-watchlist-managetokens": "Manage tokens",
"prefs-misc": "Misc",
"prefs-resetpass": "Change password",
"prefs-changeemail": "Change or remove email address",
"recentchangesdays-max": "Maximum $1 {{PLURAL:$1|day|days}}",
"recentchangescount": "Number of edits to show by default:",
"prefs-help-recentchangescount": "This includes recent changes, page histories, and logs.",
- "prefs-help-tokenmanagement": "You can see and reset the secret key for your account that can access the Web feed of your watchlist. Anyone who knows the key will be able to read your watchlist, so do not share it.",
+ "prefs-help-watchlist-token2": "This is the secret key to the web feed of your watchlist.\nAnyone who knows it will be able to read your watchlist, so do not share it.\nIf you need to, [[Special:ResetTokens|you can reset it]].",
"savedprefs": "Your preferences have been saved.",
"savedrights": "The user groups of {{GENDER:$1|$1}} have been saved.",
"timezonelegend": "Time zone:",
"prefs-watchlist-edits": "Used in [[Special:Preferences]], tab \"Watchlist\".",
"prefs-watchlist-edits-max": "Shown as hint in [[Special:Preferences]], tab \"Watchlist\"",
"prefs-watchlist-token": "Used in [[Special:Preferences]], tab Watchlist.",
- "prefs-watchlist-managetokens": "Label for the button to see and reset the user's private tokens",
"prefs-misc": "Tab used on the [[Special:Preferences|user preferences]] special page.",
"prefs-resetpass": "Button on user data tab in user preferences. When you click the button you go to the special page [[Special:ResetPass]].\n\n{{Identical|Change password}}",
"prefs-changeemail": "Link on [[Special:Preferences]] to [[Special:ChangeEmail]]. [[Special:ChangeEmail]] also allows removing email address. \n\nSee also:\n* {{msg-mw|prefs-help-email-required|help}}\n* {{msg-mw|prefs-help-email|help}}\n* {{msg-mw|prefs-help-email-others|help}}\n* {{msg-mw|prefs-setemail|link title}}",
"recentchangesdays-max": "Shown as hint in [[Special:Preferences]], tab \"Recent changes\". Parameters:\n* $1 - number of days\nSee also:\n* {{msg-mw|Prefs-watchlist-days-max}}",
"recentchangescount": "Used in [[Special:Preferences]], tab \"Recent changes\".",
"prefs-help-recentchangescount": "Used in [[Special:Preferences]], tab \"Recent changes\".",
- "prefs-help-tokenmanagement": "Used in [[Special:Preferences]], Watchlist tab.",
+ "prefs-help-watchlist-token2": "Used in [[Special:Preferences]], tab Watchlist. (Formerly in {{msg-mw|prefs-help-watchlist-token}}.)",
"savedprefs": "This message appears after saving changes to your user preferences.",
"savedrights": "This message appears after saving the user groups on [[Special:UserRights]].\n* $1 - The user name of the user which groups was saved.",
"timezonelegend": "{{Identical|Time zone}}",
'mediawiki.special.pagesWithProp' => [
'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css',
],
- 'mediawiki.special.preferences.ooui' => [
+ 'mediawiki.special.preferences' => [
'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.editfont.js',
'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js',
'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js',
],
'mediawiki.language',
'mediawiki.confirmCloseWindow',
'mediawiki.notification.convertmessagebox',
- 'oojs-ui-widgets',
- 'mediawiki.widgets.SelectWithInputWidget',
- 'mediawiki.editfont.styles',
],
],
- 'mediawiki.special.preferences.styles.ooui' => [
+ 'mediawiki.special.preferences.styles' => [
'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.css',
],
'mediawiki.special.recentchanges' => [
font-size: larger;
}
+/* preference page with js-genrated toc */
+#preftoc {
+ float: left;
+ margin: 1em 1em 1em 1em;
+ width: 13em;
+}
+
+#preftoc li {
+ border: 1px solid #fff;
+}
+
+#preftoc li.selected {
+ background-color: #f9f9f9;
+ border: 1px dashed #aaa;
+}
+
+#preftoc a,
+#preftoc a:active {
+ display: block;
+ color: #005189;
+}
+
.mw-prefs-buttons {
clear: left;
float: left;
*/
( function ( mw, $ ) {
$( function () {
- var allowCloseWindow, saveButton, restoreButton;
+ var allowCloseWindow;
- // Check if all of the form values are unchanged.
- // (This function could be changed to infuse and check OOUI widgets, but that would only make it
- // slower and more complicated. It works fine to treat them as HTML elements.)
+ // Check if all of the form values are unchanged
function isPrefsChanged() {
var inputs = $( '#mw-prefs-form :input[name]' ),
input, $input, inputType,
return false;
}
- saveButton = OO.ui.infuse( $( '#prefcontrol' ) );
- restoreButton = OO.ui.infuse( $( '#mw-prefs-restoreprefs' ) );
-
// Disable the button to save preferences unless preferences have changed
// Check if preferences have been changed before JS has finished loading
if ( !isPrefsChanged() ) {
- saveButton.setDisabled( true );
- $( '#preferences .oo-ui-fieldsetLayout' ).one( 'change keydown mousedown', function () {
- saveButton.setDisabled( false );
+ $( '#prefcontrol' ).prop( 'disabled', true );
+ $( '#preferences > fieldset' ).one( 'change keydown mousedown', function () {
+ $( '#prefcontrol' ).prop( 'disabled', false );
} );
}
namespace: 'prefswarning'
} );
$( '#mw-prefs-form' ).submit( $.proxy( allowCloseWindow, 'release' ) );
- restoreButton.on( 'click', function () {
- allowCloseWindow.release();
- // The default behavior of events in OOUI is always prevented. Follow the link manually.
- // Note that middle-click etc. still works, as it doesn't emit a OOUI 'click' event.
- location.href = restoreButton.getHref();
- } );
+ $( '#mw-prefs-restoreprefs' ).click( $.proxy( allowCloseWindow, 'release' ) );
} );
}( mediaWiki, jQuery ) );
+++ /dev/null
-/*!
- * JavaScript for Special:Preferences: editfont field enhancements.
- */
-( function ( mw, $ ) {
- $( function () {
- var widget, lastValue;
-
- try {
- widget = OO.ui.infuse( $( '#mw-input-wpeditfont' ) );
- } catch ( err ) {
- // This preference could theoretically be disabled ($wgHiddenPrefs)
- return;
- }
-
- // Style options
- widget.dropdownWidget.menu.items.forEach( function ( item ) {
- item.$label.addClass( 'mw-editfont-' + item.getData() );
- } );
-
- function updateLabel( value ) {
- // Style selected item label
- widget.dropdownWidget.$label
- .removeClass( 'mw-editfont-' + lastValue )
- .addClass( 'mw-editfont-' + value );
- lastValue = value;
- }
-
- widget.on( 'change', updateLabel );
- updateLabel( widget.getValue() );
-
- } );
-}( mediaWiki, jQuery ) );
/* Reuses colors from mediawiki.legacy/shared.css */
-.mw-email-not-authenticated .oo-ui-labelWidget,
-.mw-email-none .oo-ui-labelWidget {
+.mw-email-not-authenticated .mw-input,
+.mw-email-none .mw-input {
border: 1px solid #fde29b;
background-color: #fdf1d1;
color: #000;
}
/* Authenticated email field has its own class too. Unstyled by default */
/*
-.mw-email-authenticated .oo-ui-labelWidget { }
+.mw-email-authenticated .mw-input { }
*/
-
-/* This is needed because add extra buttons in a weird way */
-.mw-prefs-buttons .mw-htmlform-submit-buttons {
- margin: 0;
- display: inline;
+/* This breaks due to nolabel styling */
+#preferences > fieldset td.mw-label {
+ width: 20%;
}
-.mw-prefs-buttons {
- margin-top: 1em;
+#preferences > fieldset table {
+ width: 100%;
}
-
-#prefcontrol {
- margin-right: 0.5em;
+#preferences > fieldset table.mw-htmlform-matrix {
+ width: auto;
}
+/* The CSS below is also for JS enabled version, because we want to prevent FOUC */
+
/*
* Hide, but keep accessible for screen-readers.
* Like .mw-jump, #jump-to-nav from shared.css
zoom: 1;
}
-/* Override OOUI styles so that dropdowns near the bottom of the form don't get clipped,
- * e.g.'Appearance' / 'Threshold for stub link formatting'. This is hacky and bad, it would be
- * better solved by setting overlays for the widgets, but we can't do it from PHP... */
-#preferences .oo-ui-panelLayout {
- position: static;
- overflow: visible;
- -webkit-transform: none;
- transform: none;
-}
-
-#preferences .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
- border-color: #c8ccd1;
- border-width: 1px 0 0;
- border-radius: 0;
- padding-left: 0;
- padding-right: 0;
- box-shadow: none;
+.client-nojs #preftoc {
+ display: none;
}
-/* Tweak the margins to reduce the shifting of form contents
- * after JS code loads and rearranges the page */
-.client-js #preferences > .oo-ui-panelLayout {
- margin: 1em 0;
+.client-js #preferences > fieldset {
+ display: none;
}
-.client-js #preferences .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
- margin-left: 0.25em;
-}
-
-.client-js #preferences .oo-ui-tabPanelLayout {
- padding-top: 0.5em;
- padding-bottom: 0.5em;
-}
-
-.client-js #preferences .oo-ui-tabPanelLayout .oo-ui-panelLayout-framed {
- margin-left: 0;
- margin-bottom: 0;
- border: 0;
- padding-top: 0;
-}
-
-.client-js #preferences > .oo-ui-panelLayout > .oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-header {
- margin-bottom: 1em;
-}
-
-/* Make the "Basic information" section more compact */
-/* OOUI's `align: 'left'` for FieldLayouts sucks, so we do our own */
-#mw-htmlform-info > .oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
- width: 20%;
- display: inline-block;
- vertical-align: middle;
- padding: 0;
-}
-
-#mw-htmlform-info > .oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
- width: 80%;
- display: inline-block;
- vertical-align: middle;
-}
-
-/* Expand the dropdown and textfield of "Time zone" field to the */
-/* usual maximum width and display them on separate lines. */
-#wpTimeCorrection .oo-ui-dropdownInputWidget,
-#wpTimeCorrection .oo-ui-textInputWidget {
+/* Only the 1st tab is shown by default in JS mode */
+.client-js #preferences #mw-prefsection-personal {
display: block;
- max-width: 50em;
-}
-
-#wpTimeCorrection .oo-ui-textInputWidget {
- margin-top: 0.5em;
}
*/
( function ( mw, $ ) {
$( function () {
- var $preferences, tabs, wrapper, previousTab;
+ var $preftoc, $preferences, $fieldsets, labelFunc, previousTab;
+ labelFunc = function () {
+ return this.id.replace( /^mw-prefsection/g, 'preftab' );
+ };
+
+ $preftoc = $( '#preftoc' );
$preferences = $( '#preferences' );
+ $fieldsets = $preferences.children( 'fieldset' )
+ .attr( {
+ role: 'tabpanel',
+ 'aria-labelledby': labelFunc
+ } );
+ $fieldsets.not( '#mw-prefsection-personal' )
+ .hide()
+ .attr( 'aria-hidden', 'true' );
+
+ // T115692: The following is kept for backwards compatibility with older skins
+ $preferences.addClass( 'jsprefs' );
+ $fieldsets.addClass( 'prefsection' );
+ $fieldsets.children( 'legend' ).addClass( 'mainLegend' );
+
// Make sure the accessibility tip is selectable so that screen reader users take notice,
// but hide it per default to reduce interface clutter. Also make sure it becomes visible
// when selected. Similar to jquery.mw-jump
} else {
$( this ).css( 'height', 'auto' );
}
- } ).prependTo( '#mw-content-text' );
-
- tabs = new OO.ui.IndexLayout( {
- expanded: false,
- // Do not remove focus from the tabs menu after choosing a tab
- autoFocus: false
- } );
-
- mw.config.get( 'wgPreferencesTabs' ).forEach( function ( tabConfig ) {
- var panel, $panelContents;
-
- panel = new OO.ui.TabPanelLayout( tabConfig.name, {
- expanded: false,
- label: tabConfig.label
- } );
- $panelContents = $( '#mw-prefsection-' + tabConfig.name );
-
- // Hide the unnecessary PHP PanelLayouts
- // (Do not use .remove(), as that would remove event handlers for everything inside them)
- $panelContents.parent().detach();
-
- panel.$element.append( $panelContents );
- tabs.addTabPanels( [ panel ] );
-
- // Remove duplicate labels
- // (This must be after .addTabPanels(), otherwise the tab item doesn't exist yet)
- $panelContents.children( 'legend' ).remove();
- $panelContents.attr( 'aria-labelledby', panel.getTabItem().getElementId() );
- } );
-
- wrapper = new OO.ui.PanelLayout( {
- expanded: false,
- padded: false,
- framed: true
- } );
- wrapper.$element.append( tabs.$element );
- $preferences.prepend( wrapper.$element );
-
- function updateHash( panel ) {
- var scrollTop, active;
- // Handle hash manually to prevent jumping,
- // therefore save and restore scrollTop to prevent jumping.
- scrollTop = $( window ).scrollTop();
- // Changing the hash apparently causes keyboard focus to be lost?
- // Save and restore it. This makes no sense though.
- active = document.activeElement;
- location.hash = '#mw-prefsection-' + panel.getName();
- if ( active ) {
- active.focus();
- }
- $( window ).scrollTop( scrollTop );
- }
-
- tabs.on( 'set', updateHash );
+ } ).insertBefore( $preftoc );
/**
+ * It uses document.getElementById for security reasons (HTML injections in $()).
+ *
* @ignore
* @param {string} name the name of a tab without the prefix ("mw-prefsection-")
* @param {string} [mode] A hash will be set according to the current
- * open section. Set mode 'noHash' to supress this.
+ * open section. Set mode 'noHash' to surpress this.
*/
function switchPrefTab( name, mode ) {
- if ( mode === 'noHash' ) {
- tabs.off( 'set', updateHash );
+ var $tab, scrollTop;
+ // Handle hash manually to prevent jumping,
+ // therefore save and restore scrollTop to prevent jumping.
+ scrollTop = $( window ).scrollTop();
+ if ( mode !== 'noHash' ) {
+ location.hash = '#mw-prefsection-' + name;
}
- tabs.setTabPanel( name );
- if ( mode === 'noHash' ) {
- tabs.on( 'set', updateHash );
+ $( window ).scrollTop( scrollTop );
+
+ $preftoc.find( 'li' ).removeClass( 'selected' )
+ .find( 'a' ).attr( {
+ tabIndex: -1,
+ 'aria-selected': 'false'
+ } );
+
+ $tab = $( document.getElementById( 'preftab-' + name ) );
+ if ( $tab.length ) {
+ $tab.attr( {
+ tabIndex: 0,
+ 'aria-selected': 'true'
+ } ).focus()
+ .parent().addClass( 'selected' );
+
+ $preferences.children( 'fieldset' ).hide().attr( 'aria-hidden', 'true' );
+ $( document.getElementById( 'mw-prefsection-' + name ) ).show().attr( 'aria-hidden', 'false' );
}
}
+ // Enable keyboard users to use left and right keys to switch tabs
+ $preftoc.on( 'keydown', function ( event ) {
+ var keyLeft = 37,
+ keyRight = 39,
+ $el;
+
+ if ( event.keyCode === keyLeft ) {
+ $el = $( '#preftoc li.selected' ).prev().find( 'a' );
+ } else if ( event.keyCode === keyRight ) {
+ $el = $( '#preftoc li.selected' ).next().find( 'a' );
+ } else {
+ return;
+ }
+ if ( $el.length > 0 ) {
+ switchPrefTab( $el.attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ }
+ } );
+
// Jump to correct section as indicated by the hash.
// This function is called onload and onhashchange.
function detectHash() {
}
}
- // Handle other things that change the hash (e.g. using
+ // In browsers that support the onhashchange event we will not bind click
+ // handlers and instead let the browser do the default behavior (clicking the
+ // <a href="#.."> will naturally set the hash, handled by onhashchange.
+ // But other things that change the hash will also be caught (e.g. using
// the Back and Forward browser navigation).
- if ( 'onhashchange' in window ) {
+ // Note the special check for IE "compatibility" mode.
+ if ( 'onhashchange' in window &&
+ ( document.documentMode === undefined || document.documentMode >= 8 )
+ ) {
$( window ).on( 'hashchange', function () {
var hash = location.hash;
if ( hash.match( /^#mw-[\w-]+/ ) ) {
} else if ( hash === '' ) {
switchPrefTab( 'personal', 'noHash' );
}
+ } )
+ // Run the function immediately to select the proper tab on startup.
+ .trigger( 'hashchange' );
+ // In older browsers we'll bind a click handler as fallback.
+ // We must not have onhashchange *and* the click handlers, otherwise
+ // the click handler calls switchPrefTab() which sets the hash value,
+ // which triggers onhashchange and calls switchPrefTab() again.
+ } else {
+ $preftoc.on( 'click', 'li a', function ( e ) {
+ switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ e.preventDefault();
} );
+ // If we've reloaded the page or followed an open-in-new-window,
+ // make the selected tab visible.
+ detectHash();
}
- // If we've reloaded the page or followed an open-in-new-window,
- // make the selected tab visible.
- detectHash();
-
// Restore the active tab after saving the preferences
previousTab = mw.storage.session.get( 'mwpreferences-prevTab' );
if ( previousTab ) {
}
$( '#mw-prefs-form' ).on( 'submit', function () {
- var value = tabs.getCurrentTabPanelName();
+ var value = $( $preftoc ).find( 'li.selected a' ).attr( 'id' ).replace( 'preftab-', '' );
mw.storage.session.set( 'mwpreferences-prevTab', value );
} );
( function ( mw, $ ) {
$( function () {
var
- timezoneWidget, $localtimeHolder, servertime;
+ $tzSelect, $tzTextbox, $localtimeHolder, servertime;
// Timezone functions.
// Guesses Timezone from browser and updates fields onchange.
- // This is identical to OO.ui.infuse( ... ), but it makes the class name of the result known.
- try {
- timezoneWidget = mw.widgets.SelectWithInputWidget.static.infuse( $( '#wpTimeCorrection' ) );
- } catch ( err ) {
- // This preference could theoretically be disabled ($wgHiddenPrefs)
- timezoneWidget = null;
- }
-
+ $tzSelect = $( '#mw-input-wptimecorrection' );
+ $tzTextbox = $( '#mw-input-wptimecorrection-other' );
$localtimeHolder = $( '#wpLocalTime' );
servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
function updateTimezoneSelection() {
var minuteDiff, localTime,
- type = timezoneWidget.dropdowninput.getValue();
+ type = $tzSelect.val();
if ( type === 'other' ) {
// User specified time zone manually in <input>
// Grab data from the textbox, parse it.
- minuteDiff = hoursToMinutes( timezoneWidget.textinput.getValue() );
+ 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() );
- timezoneWidget.textinput.setValue( minutesToHours( minuteDiff ) );
- timezoneWidget.dropdowninput.setValue( 'other' );
+ $tzTextbox.val( minutesToHours( minuteDiff ) );
+ $tzSelect.val( 'other' );
} else {
- // Grab data from the dropdown value
+ // Grab data from the $tzSelect value
minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0;
}
}
$localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) );
}
- if ( timezoneWidget ) {
- timezoneWidget.dropdowninput.on( 'change', updateTimezoneSelection );
- timezoneWidget.textinput.on( 'change', updateTimezoneSelection );
+ if ( $tzSelect.length && $tzTextbox.length ) {
+ $tzSelect.change( updateTimezoneSelection );
+ $tzTextbox.blur( updateTimezoneSelection );
updateTimezoneSelection();
}
class PreferencesPage extends Page {
- get realName() { return browser.element( '#mw-input-wprealname .oo-ui-inputWidget-input' ); }
- get save() { return browser.element( '#prefcontrol .oo-ui-buttonElement-button' ); }
+ get realName() { return browser.element( '#mw-input-wprealname' ); }
+ get save() { return browser.element( '#prefcontrol' ); }
open() {
super.open( 'Special:Preferences' );