*/
$wgUseMediaWikiUIEverywhere = false;
-/**
- * Temporary variable that determines whether Special:Preferences should use OOUI or not.
- * This will be removed later and OOUI will become the only option.
- *
- * @since 1.32
- */
-$wgOOUIPreferences = true;
-
/**
* Whether to label the store-to-database-and-show-to-others button in the editor
* as "Save page"/"Save changes" if false (the default) or, if true, instead as
use Exception;
use Hooks;
use Html;
-use HtmlArmor;
use HTMLForm;
use HTMLFormField;
use IContextSource;
use Psr\Log\NullLogger;
use Skin;
use SpecialPage;
-use SpecialPreferences;
use Status;
use Title;
use UnexpectedValueException;
public function getFormDescriptor( User $user, IContextSource $context ) {
$preferences = [];
- if ( SpecialPreferences::isOouiEnabled( $context ) ) {
- OutputPage::setupOOUI(
- strtolower( $context->getSkin()->getSkinName() ),
- $context->getLanguage()->getDir()
- );
- }
+ OutputPage::setupOOUI(
+ strtolower( $context->getSkin()->getSkinName() ),
+ $context->getLanguage()->getDir()
+ );
$canIPUseHTTPS = wfCanIPUseHTTPS( $context->getRequest()->getIP() );
$this->profilePreferences( $user, $context, $preferences, $canIPUseHTTPS );
protected function profilePreferences(
User $user, IContextSource $context, &$defaultPreferences, $canIPUseHTTPS
) {
- $oouiEnabled = SpecialPreferences::isOouiEnabled( $context );
-
// retrieving user name for GENDER and misc.
$userName = $user->getName();
if ( $canEditPrivateInfo && $this->authManager->allowsAuthenticationDataChange(
new PasswordAuthenticationRequest(), false )->isGood()
) {
- if ( $oouiEnabled ) {
- $link = new \OOUI\ButtonWidget( [
+ $defaultPreferences['password'] = [
+ 'type' => 'info',
+ 'raw' => true,
+ 'default' => (string)new \OOUI\ButtonWidget( [
'href' => SpecialPage::getTitleFor( 'ChangePassword' )->getLinkURL( [
'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText()
] ),
'label' => $context->msg( 'prefs-resetpass' )->text(),
- ] );
- } else {
- $link = $this->linkRenderer->makeLink( SpecialPage::getTitleFor( 'ChangePassword' ),
- $context->msg( 'prefs-resetpass' )->text(), [],
- [ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
- }
-
- $defaultPreferences['password'] = [
- 'type' => 'info',
- 'raw' => true,
- 'default' => (string)$link,
+ ] ),
'label-message' => 'yourpassword',
'section' => 'personal/info',
];
$emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
if ( $canEditPrivateInfo && $this->authManager->allowsPropertyChange( 'emailaddress' ) ) {
- if ( $oouiEnabled ) {
- $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 );
- } else {
- $link = $this->linkRenderer->makeLink(
- SpecialPage::getTitleFor( 'ChangeEmail' ),
+ $button = new \OOUI\ButtonWidget( [
+ 'href' => SpecialPage::getTitleFor( 'ChangeEmail' )->getLinkURL( [
+ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText()
+ ] ),
+ 'label' =>
$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()
- );
- }
+ $emailAddress .= $emailAddress == '' ? $button : ( '<br />' . $button );
}
$defaultPreferences['emailaddress'] = [
$emailauthenticationclass = 'mw-email-authenticated';
} else {
$disableEmailPrefs = true;
- if ( $oouiEnabled ) {
- $emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' .
- new \OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'Confirmemail' )->getLinkURL(),
- 'label' => $context->msg( 'emailconfirmlink' )->text(),
- ] );
- } else {
- $emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' .
- $this->linkRenderer->makeKnownLink(
- SpecialPage::getTitleFor( 'Confirmemail' ),
- $context->msg( 'emailconfirmlink' )->text()
- ) . '<br />';
- }
+ $emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' .
+ new \OOUI\ButtonWidget( [
+ 'href' => SpecialPage::getTitleFor( 'Confirmemail' )->getLinkURL(),
+ 'label' => $context->msg( 'emailconfirmlink' )->text(),
+ ] );
$emailauthenticationclass = "mw-email-not-authenticated";
}
} else {
protected function watchlistPreferences(
User $user, IContextSource $context, &$defaultPreferences
) {
- $oouiEnabled = SpecialPreferences::isOouiEnabled( $context );
-
$watchlistdaysMax = ceil( $this->config->get( 'RCMaxAge' ) / ( 3600 * 24 ) );
# # Watchlist #####################################
];
foreach ( $editWatchlistModes as $mode => $options ) {
// Messages: prefs-editwatchlist-edit, prefs-editwatchlist-raw, prefs-editwatchlist-clear
- if ( $oouiEnabled ) {
- $editWatchlistLinks .=
- new \OOUI\ButtonWidget( [
- 'href' => SpecialPage::getTitleFor( 'EditWatchlist', $options['subpage'] )->getLinkURL(),
- 'flags' => $options[ 'flags' ],
- 'label' => new \OOUI\HtmlSnippet(
- $context->msg( "prefs-editwatchlist-{$mode}" )->parse()
- ),
- ] );
- } else {
- $editWatchlistLinksOld[] = $this->linkRenderer->makeKnownLink(
- SpecialPage::getTitleFor( 'EditWatchlist', $options['subpage'] ),
- new HtmlArmor( $context->msg( "prefs-editwatchlist-{$mode}" )->parse() )
- );
- }
+ $editWatchlistLinks .=
+ new \OOUI\ButtonWidget( [
+ 'href' => SpecialPage::getTitleFor( 'EditWatchlist', $options['subpage'] )->getLinkURL(),
+ 'flags' => $options[ 'flags' ],
+ 'label' => new \OOUI\HtmlSnippet(
+ $context->msg( "prefs-editwatchlist-{$mode}" )->parse()
+ ),
+ ] );
}
$defaultPreferences['editwatchlist'] = [
'type' => 'info',
'raw' => true,
- 'default' => $oouiEnabled ?
- $editWatchlistLinks :
- $context->getLanguage()->pipeList( $editWatchlistLinksOld ),
+ 'default' => $editWatchlistLinks,
'label-message' => 'prefs-editwatchlist-label',
'section' => 'watchlist/editwatchlist',
];
'type' => 'api',
];
- if ( $oouiEnabled ) {
- $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,
- ];
- } else {
- $defaultPreferences['watchlisttoken-info'] = [
- 'type' => 'info',
- 'section' => 'watchlist/tokenwatchlist',
- 'label-message' => 'prefs-watchlist-token',
- 'default' => $user->getTokenFromOption( 'watchlisttoken' ),
- 'help-message' => 'prefs-help-watchlist-token2',
- ];
- }
+ $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,
+ ];
$defaultPreferences['wlenhancedfilters-disable'] = [
'type' => 'toggle',
$formClass = PreferencesFormLegacy::class,
array $remove = []
) {
- if ( SpecialPreferences::isOouiEnabled( $context ) ) {
- // We use ButtonWidgets in some of the getPreferences() functions
- $context->getOutput()->enableOOUI();
- }
+ // We use ButtonWidgets in some of the getPreferences() functions
+ $context->getOutput()->enableOOUI();
$formDescriptor = $this->getFormDescriptor( $user, $context );
if ( count( $remove ) ) {
$urlOptions['eauth'] = 1;
}
- if (
- $context->getRequest()->getFuzzyBool( 'ooui' ) !==
- $context->getConfig()->get( 'OOUIPreferences' )
- ) {
- $urlOptions[ 'ooui' ] = $context->getRequest()->getFuzzyBool( 'ooui' ) ? 1 : 0;
- }
-
$urlOptions += $form->getExtraSuccessRedirectParameters();
$url = $form->getTitle()->getFullURL( $urlOptions );
* @ingroup SpecialPage
*/
class SpecialPreferences extends SpecialPage {
- /**
- * @var bool Whether OOUI should be enabled here
- */
- private $oouiEnabled = false;
-
function __construct() {
parent::__construct( 'Preferences' );
}
/**
- * Check if OOUI mode is enabled, by config or query string
*
* @since 1.32
- * @param IContextSource $context The context.
+ * @deprecated since 1.32
* @return bool
*/
- public static function isOouiEnabled( IContextSource $context ) {
- return $context->getRequest()->getFuzzyBool( 'ooui',
- $context->getConfig()->get( 'OOUIPreferences' )
- );
+ public static function isOouiEnabled() {
+ // wfDeprecated( __METHOD__, '1.31' );
+ return true;
}
public function doesWrites() {
}
public function execute( $par ) {
- $this->oouiEnabled = static::isOouiEnabled( $this->getContext() );
-
$this->setHeaders();
$this->outputHeader();
$out = $this->getOutput();
return;
}
- if ( $this->oouiEnabled ) {
- $out->addModules( 'mediawiki.special.preferences.ooui' );
- $out->addModuleStyles( 'mediawiki.special.preferences.styles.ooui' );
- $out->addModuleStyles( 'oojs-ui-widgets.styles' );
- } else {
- $out->addModules( 'mediawiki.special.preferences' );
- $out->addModuleStyles( 'mediawiki.special.preferences.styles' );
- }
+ $out->addModules( 'mediawiki.special.preferences.ooui' );
+ $out->addModuleStyles( 'mediawiki.special.preferences.styles.ooui' );
+ $out->addModuleStyles( 'oojs-ui-widgets.styles' );
$session = $this->getRequest()->getSession();
if ( $session->get( 'specialPreferencesSaveSuccess' ) ) {
$htmlForm = $this->getFormObject( $user, $this->getContext() );
$sectionTitles = $htmlForm->getPreferenceSections();
- if ( $this->oouiEnabled ) {
- $prefTabs = [];
- foreach ( $sectionTitles as $key ) {
- $prefTabs[] = [
- 'name' => $key,
- 'label' => $htmlForm->getLegend( $key ),
- ];
- }
- $out->addJsConfigVars( 'wgPreferencesTabs', $prefTabs );
- } else {
-
- $prefTabs = '';
- foreach ( $sectionTitles as $key ) {
- $prefTabs .= Html::rawElement( 'li',
- [
- 'role' => 'presentation',
- 'class' => ( $key === 'personal' ) ? 'selected' : null
- ],
- Html::element( '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->addHTML(
- Html::rawElement( 'ul',
- [
- 'id' => 'preftoc',
- 'role' => 'tablist'
- ],
- $prefTabs )
- );
+ $prefTabs = [];
+ foreach ( $sectionTitles as $key ) {
+ $prefTabs[] = [
+ 'name' => $key,
+ 'label' => $htmlForm->getLegend( $key ),
+ ];
}
-
- $htmlForm->addHiddenField( 'ooui', $this->oouiEnabled ? '1' : '0' );
+ $out->addJsConfigVars( 'wgPreferencesTabs', $prefTabs );
$htmlForm->show();
}
*/
protected function getFormObject( $user, IContextSource $context ) {
$preferencesFactory = MediaWikiServices::getInstance()->getPreferencesFactory();
- if ( $this->oouiEnabled ) {
- $form = $preferencesFactory->getForm( $user, $context, PreferencesFormOOUI::class );
- } else {
- $form = $preferencesFactory->getForm( $user, $context, PreferencesFormLegacy::class );
- }
+ $form = $preferencesFactory->getForm( $user, $context, PreferencesFormOOUI::class );
return $form;
}
* @file
*/
-use MediaWiki\MediaWikiServices;
-
/**
* Form to edit user preferences.
*
* @since 1.32
*/
-class PreferencesFormLegacy extends HTMLForm {
- // Override default value from HTMLForm
- protected $mSubSectionBeforeFields = false;
-
- private $modifiedUser;
-
- /**
- * @param User $user
- */
- public function setModifiedUser( $user ) {
- $this->modifiedUser = $user;
- }
-
- /**
- * @return User
- */
- public function getModifiedUser() {
- if ( $this->modifiedUser === null ) {
- return $this->getUser();
- } else {
- return $this->modifiedUser;
- }
- }
-
- /**
- * Get extra parameters for the query string when redirecting after
- * successful save.
- *
- * @return array
- */
- public function getExtraSuccessRedirectParameters() {
- return [];
- }
-
- /**
- * @param string $html
- * @return string
- */
- function wrapForm( $html ) {
- $html = Xml::tags( 'div', [ 'id' => 'preferences' ], $html );
-
- return parent::wrapForm( $html );
- }
-
- /**
- * @return string
- */
- function getButtons() {
- $attrs = [ 'id' => 'mw-prefs-restoreprefs' ];
-
- if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
- return '';
- }
-
- $html = parent::getButtons();
-
- if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
- $t = $this->getTitle()->getSubpage( 'reset' );
-
- $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 );
- }
-
- return $html;
- }
-
- /**
- * Separate multi-option preferences into multiple preferences, since we
- * have to store them separately
- * @param array $data
- * @return array
- */
- function filterDataForSubmit( $data ) {
- foreach ( $this->mFlatFields as $fieldname => $field ) {
- if ( $field instanceof HTMLNestedFilterable ) {
- $info = $field->mParams;
- $prefix = $info['prefix'] ?? $fieldname;
- foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) {
- $data["$prefix$key"] = $value;
- }
- unset( $data[$fieldname] );
- }
- }
-
- return $data;
- }
-
- /**
- * Get the whole body of the form.
- * @return string
- */
- function getBody() {
- return $this->displaySection( $this->mFieldTree, '', 'mw-prefsection-' );
- }
-
- /**
- * Get the "<legend>" for a given section key. Normally this is the
- * prefs-$key message but we'll allow extensions to override it.
- * @param string $key
- * @return string
- */
- function getLegend( $key ) {
- $aliasKey = ( $key === 'optoutwatchlist' || $key === 'optoutrc' ) ? 'opt-out' : $key;
- $legend = parent::getLegend( $aliasKey );
- Hooks::run( 'PreferencesGetLegend', [ $this, $key, &$legend ] );
- return $legend;
- }
-
- /**
- * Get the keys of each top level preference section.
- * @return array of section keys
- */
- function getPreferenceSections() {
- return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
- }
+class PreferencesFormLegacy extends PreferencesFormOOUI {
+ // No-op
}
/**
* Retain the old class name for backwards compatibility.
- * In the future, this alias will be changed to point to PreferencesFormOOUI.
*
* @deprecated since 1.32
*/
'oojs-ui-core',
],
],
- 'mediawiki.special.preferences' => [
- 'targets' => [ 'desktop', 'mobile' ],
- 'scripts' => [
- 'resources/src/mediawiki.special.preferences/confirmClose.js',
- 'resources/src/mediawiki.special.preferences/convertmessagebox.js',
- 'resources/src/mediawiki.special.preferences/tabs.legacy.js',
- 'resources/src/mediawiki.special.preferences/timezone.js',
- 'resources/src/mediawiki.special.preferences/personalEmail.js',
- ],
- 'messages' => [
- 'prefs-tabs-navigation-hint',
- 'prefswarning-warning',
- 'saveprefs',
- 'savedprefs',
- ],
- 'dependencies' => [
- 'mediawiki.language',
- 'mediawiki.confirmCloseWindow',
- 'mediawiki.notification.convertmessagebox',
- ],
- ],
- 'mediawiki.special.preferences.styles' => [
- 'targets' => [ 'desktop', 'mobile' ],
- // legacy
- 'styles' => 'resources/src/mediawiki.special.preferences.styles.css',
- ],
'mediawiki.special.preferences.ooui' => [
'targets' => [ 'desktop', 'mobile' ],
'scripts' => [
- // FIXME: This uses files already belonging to another module
- 'resources/src/mediawiki.special.preferences/confirmClose.js',
- 'resources/src/mediawiki.special.preferences/convertmessagebox.js',
+ 'resources/src/mediawiki.special.preferences.ooui/confirmClose.js',
+ 'resources/src/mediawiki.special.preferences.ooui/convertmessagebox.js',
'resources/src/mediawiki.special.preferences.ooui/editfont.js',
'resources/src/mediawiki.special.preferences.ooui/tabs.js',
- 'resources/src/mediawiki.special.preferences/timezone.js',
- 'resources/src/mediawiki.special.preferences/personalEmail.js',
+ 'resources/src/mediawiki.special.preferences.ooui/timezone.js',
+ 'resources/src/mediawiki.special.preferences.ooui/personalEmail.js',
],
'messages' => [
'prefs-tabs-navigation-hint',
--- /dev/null
+/*!
+ * JavaScript for Special:Preferences: Enable save button and prevent the window being accidentally
+ * closed when any form field is changed.
+ */
+( function () {
+ $( function () {
+ var allowCloseWindow, saveButton, restoreButton;
+
+ // 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.)
+ function isPrefsChanged() {
+ var inputs = $( '#mw-prefs-form :input[name]' ),
+ input, $input, inputType,
+ index, optIndex,
+ opt;
+
+ for ( index = 0; index < inputs.length; index++ ) {
+ input = inputs[ index ];
+ $input = $( input );
+
+ // Different types of inputs have different methods for accessing defaults
+ if ( $input.is( 'select' ) ) {
+ // <select> has the property defaultSelected for each option
+ for ( optIndex = 0; optIndex < input.options.length; optIndex++ ) {
+ opt = input.options[ optIndex ];
+ if ( opt.selected !== opt.defaultSelected ) {
+ return true;
+ }
+ }
+ } else if ( $input.is( 'input' ) || $input.is( 'textarea' ) ) {
+ // <input> has defaultValue or defaultChecked
+ inputType = input.type;
+ if ( inputType === 'radio' || inputType === 'checkbox' ) {
+ if ( input.checked !== input.defaultChecked ) {
+ return true;
+ }
+ } else if ( input.value !== input.defaultValue ) {
+ return true;
+ }
+ }
+ }
+
+ 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
+ saveButton.setDisabled( !isPrefsChanged() );
+ // Attach capturing event handlers to the document, to catch events inside OOUI dropdowns:
+ // * Use capture because OO.ui.SelectWidget also does, and it stops event propagation,
+ // so the event is not fired on descendant elements
+ // * Attach to the document because the dropdowns are in the .oo-ui-defaultOverlay element
+ // (and it doesn't exist yet at this point, so we can't attach them to it)
+ [ 'change', 'keyup', 'mouseup' ].forEach( function ( eventType ) {
+ document.addEventListener( eventType, function () {
+ // Make sure SelectWidget's event handlers run first
+ setTimeout( function () {
+ saveButton.setDisabled( !isPrefsChanged() );
+ } );
+ }, true );
+ } );
+
+ // Set up a message to notify users if they try to leave the page without
+ // saving.
+ allowCloseWindow = mw.confirmCloseWindow( {
+ test: isPrefsChanged,
+ message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ),
+ namespace: 'prefswarning'
+ } );
+ $( '#mw-prefs-form' ).on( 'submit', 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();
+ } );
+ } );
+}() );
--- /dev/null
+/*!
+ * JavaScript for Special:Preferences: Check for successbox to replace with notifications.
+ */
+( function () {
+ $( function () {
+ var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
+ convertmessagebox();
+ } );
+}() );
--- /dev/null
+/*!
+ * JavaScript for Special:Preferences: Email preferences better UX
+ */
+( function () {
+ $( function () {
+ var allowEmail, allowEmailFromNewUsers;
+
+ allowEmail = $( '#wpAllowEmail' );
+ allowEmailFromNewUsers = $( '#wpAllowEmailFromNewUsers' );
+
+ function toggleDisabled() {
+ if ( allowEmail.is( ':checked' ) && allowEmail.is( ':enabled' ) ) {
+ allowEmailFromNewUsers.prop( 'disabled', false );
+ } else {
+ allowEmailFromNewUsers.prop( 'disabled', true );
+ }
+ }
+
+ if ( allowEmail ) {
+ allowEmail.on( 'change', toggleDisabled );
+ toggleDisabled();
+ }
+ } );
+}() );
--- /dev/null
+/*!
+ * JavaScript for Special:Preferences: Timezone field enhancements.
+ */
+( function () {
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var timezoneWidget, $localtimeHolder, servertime,
+ $target = $root.find( '#wpTimeCorrection' );
+
+ if (
+ !$target.length ||
+ $target.closest( '.mw-htmlform-autoinfuse-lazy' ).length
+ ) {
+ return;
+ }
+
+ // 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( $target );
+ } catch ( err ) {
+ // This preference could theoretically be disabled ($wgHiddenPrefs)
+ timezoneWidget = null;
+ }
+
+ $localtimeHolder = $( '#wpLocalTime' );
+ servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
+
+ function minutesToHours( min ) {
+ var tzHour = Math.floor( Math.abs( min ) / 60 ),
+ tzMin = Math.abs( min ) % 60,
+ tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
+ ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
+ return tzString;
+ }
+
+ function hoursToMinutes( hour ) {
+ var minutes,
+ arr = hour.split( ':' );
+
+ arr[ 0 ] = parseInt( arr[ 0 ], 10 );
+
+ if ( arr.length === 1 ) {
+ // Specification is of the form [-]XX
+ minutes = arr[ 0 ] * 60;
+ } else {
+ // Specification is of the form [-]XX:XX
+ minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 );
+ if ( arr[ 0 ] < 0 ) {
+ minutes *= -1;
+ }
+ }
+ // Gracefully handle non-numbers.
+ if ( isNaN( minutes ) ) {
+ return 0;
+ } else {
+ return minutes;
+ }
+ }
+
+ function updateTimezoneSelection() {
+ var minuteDiff, localTime,
+ type = timezoneWidget.dropdowninput.getValue();
+
+ if ( type === 'other' ) {
+ // User specified time zone manually in <input>
+ // Grab data from the textbox, parse it.
+ minuteDiff = hoursToMinutes( timezoneWidget.textinput.getValue() );
+ } 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' );
+ } else {
+ // Grab data from the dropdown value
+ minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0;
+ }
+ }
+
+ // Determine local time from server time and minutes difference, for display.
+ localTime = servertime + minuteDiff;
+
+ // Bring time within the [0,1440) range.
+ localTime = ( ( localTime % 1440 ) + 1440 ) % 1440;
+
+ $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) );
+ }
+
+ if ( timezoneWidget ) {
+ timezoneWidget.dropdowninput.on( 'change', updateTimezoneSelection );
+ timezoneWidget.textinput.on( 'change', updateTimezoneSelection );
+ updateTimezoneSelection();
+ }
+
+ } );
+}() );
+++ /dev/null
-/*!
- * JavaScript for Special:Preferences: Enable save button and prevent the window being accidentally
- * closed when any form field is changed.
- */
-( function () {
- $( function () {
- var allowCloseWindow, saveButton, restoreButton,
- oouiEnabled = $( '#mw-prefs-form' ).hasClass( 'mw-htmlform-ooui' );
-
- // 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.)
- function isPrefsChanged() {
- var inputs = $( '#mw-prefs-form :input[name]' ),
- input, $input, inputType,
- index, optIndex,
- opt;
-
- for ( index = 0; index < inputs.length; index++ ) {
- input = inputs[ index ];
- $input = $( input );
-
- // Different types of inputs have different methods for accessing defaults
- if ( $input.is( 'select' ) ) {
- // <select> has the property defaultSelected for each option
- for ( optIndex = 0; optIndex < input.options.length; optIndex++ ) {
- opt = input.options[ optIndex ];
- if ( opt.selected !== opt.defaultSelected ) {
- return true;
- }
- }
- } else if ( $input.is( 'input' ) || $input.is( 'textarea' ) ) {
- // <input> has defaultValue or defaultChecked
- inputType = input.type;
- if ( inputType === 'radio' || inputType === 'checkbox' ) {
- if ( input.checked !== input.defaultChecked ) {
- return true;
- }
- } else if ( input.value !== input.defaultValue ) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- if ( oouiEnabled ) {
- 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
- saveButton.setDisabled( !isPrefsChanged() );
- // Attach capturing event handlers to the document, to catch events inside OOUI dropdowns:
- // * Use capture because OO.ui.SelectWidget also does, and it stops event propagation,
- // so the event is not fired on descendant elements
- // * Attach to the document because the dropdowns are in the .oo-ui-defaultOverlay element
- // (and it doesn't exist yet at this point, so we can't attach them to it)
- [ 'change', 'keyup', 'mouseup' ].forEach( function ( eventType ) {
- document.addEventListener( eventType, function () {
- // Make sure SelectWidget's event handlers run first
- setTimeout( function () {
- saveButton.setDisabled( !isPrefsChanged() );
- } );
- }, true );
- } );
- } else {
- // Disable the button to save preferences unless preferences have changed
- // Check if preferences have been changed before JS has finished loading
- $( '#prefcontrol' ).prop( 'disabled', !isPrefsChanged() );
- $( '#preferences > fieldset' ).on( 'change keyup mouseup', function () {
- $( '#prefcontrol' ).prop( 'disabled', !isPrefsChanged() );
- } );
- }
-
- // Set up a message to notify users if they try to leave the page without
- // saving.
- allowCloseWindow = mw.confirmCloseWindow( {
- test: isPrefsChanged,
- message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ),
- namespace: 'prefswarning'
- } );
- $( '#mw-prefs-form' ).on( 'submit', allowCloseWindow.release );
- if ( oouiEnabled ) {
- 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();
- } );
- } else {
- $( '#mw-prefs-restoreprefs' ).on( 'click', allowCloseWindow.release );
- }
- } );
-}() );
+++ /dev/null
-/*!
- * JavaScript for Special:Preferences: Check for successbox to replace with notifications.
- */
-( function () {
- $( function () {
- var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
- convertmessagebox();
- } );
-}() );
+++ /dev/null
-/*!
- * JavaScript for Special:Preferences: Email preferences better UX
- */
-( function () {
- $( function () {
- var allowEmail, allowEmailFromNewUsers;
-
- allowEmail = $( '#wpAllowEmail' );
- allowEmailFromNewUsers = $( '#wpAllowEmailFromNewUsers' );
-
- function toggleDisabled() {
- if ( allowEmail.is( ':checked' ) && allowEmail.is( ':enabled' ) ) {
- allowEmailFromNewUsers.prop( 'disabled', false );
- } else {
- allowEmailFromNewUsers.prop( 'disabled', true );
- }
- }
-
- if ( allowEmail ) {
- allowEmail.on( 'change', toggleDisabled );
- toggleDisabled();
- }
- } );
-}() );
+++ /dev/null
-/*!
- * JavaScript for Special:Preferences: Timezone field enhancements.
- */
-( function () {
- mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
- var $tzSelect, $tzTextbox, timezoneWidget, $localtimeHolder, servertime,
- $target = $root.find( '#wpTimeCorrection' ),
- oouiEnabled = $( '#mw-prefs-form' ).hasClass( 'mw-htmlform-ooui' );
-
- if (
- !$target.length ||
- $target.closest( '.mw-htmlform-autoinfuse-lazy' ).length
- ) {
- return;
- }
-
- // Timezone functions.
- // Guesses Timezone from browser and updates fields onchange.
-
- if ( oouiEnabled ) {
- // This is identical to OO.ui.infuse( ... ), but it makes the class name of the result known.
- try {
- timezoneWidget = mw.widgets.SelectWithInputWidget.static.infuse( $target );
- } catch ( err ) {
- // This preference could theoretically be disabled ($wgHiddenPrefs)
- timezoneWidget = null;
- }
- } else {
- $tzSelect = $target;
- $tzTextbox = $( '#wpTimeCorrection-other' );
- }
-
- $localtimeHolder = $( '#wpLocalTime' );
- servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
-
- function minutesToHours( min ) {
- var tzHour = Math.floor( Math.abs( min ) / 60 ),
- tzMin = Math.abs( min ) % 60,
- tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
- ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
- return tzString;
- }
-
- function hoursToMinutes( hour ) {
- var minutes,
- arr = hour.split( ':' );
-
- arr[ 0 ] = parseInt( arr[ 0 ], 10 );
-
- if ( arr.length === 1 ) {
- // Specification is of the form [-]XX
- minutes = arr[ 0 ] * 60;
- } else {
- // Specification is of the form [-]XX:XX
- minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 );
- if ( arr[ 0 ] < 0 ) {
- minutes *= -1;
- }
- }
- // Gracefully handle non-numbers.
- if ( isNaN( minutes ) ) {
- return 0;
- } else {
- return minutes;
- }
- }
-
- function updateTimezoneSelection() {
- var minuteDiff, localTime,
- type = oouiEnabled ? timezoneWidget.dropdowninput.getValue() : $tzSelect.val(),
- val = oouiEnabled ? timezoneWidget.textinput.getValue() : $tzTextbox.val();
-
- if ( type === 'other' ) {
- // User specified time zone manually in <input>
- // Grab data from the textbox, parse it.
- minuteDiff = hoursToMinutes( val );
- } else {
- // Time zone not manually specified by user
- if ( type === 'guess' ) {
- // Get browser timezone & fill it in
- minuteDiff = -( new Date().getTimezoneOffset() );
- if ( oouiEnabled ) {
- timezoneWidget.textinput.setValue( minutesToHours( minuteDiff ) );
- timezoneWidget.dropdowninput.setValue( 'other' );
- } else {
- $tzTextbox.val( minutesToHours( minuteDiff ) );
- $tzSelect.val( 'other' );
- }
- } else {
- // Grab data from the dropdown value
- minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0;
- }
- }
-
- // Determine local time from server time and minutes difference, for display.
- localTime = servertime + minuteDiff;
-
- // Bring time within the [0,1440) range.
- localTime = ( ( localTime % 1440 ) + 1440 ) % 1440;
-
- $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) );
- }
-
- if ( oouiEnabled ) {
- if ( timezoneWidget ) {
- timezoneWidget.dropdowninput.on( 'change', updateTimezoneSelection );
- timezoneWidget.textinput.on( 'change', updateTimezoneSelection );
- updateTimezoneSelection();
- }
- } else {
- if ( $tzSelect.length && $tzTextbox.length ) {
- $tzSelect.change( updateTimezoneSelection );
- $tzTextbox.blur( updateTimezoneSelection );
- updateTimezoneSelection();
- }
- }
-
- } );
-}() );