Files
mediawiki-extensions-Univer…/resources/js/ext.uls.launch.js
Sam Smith 3b9134f8ac launchULS: Add context to interface.language.change hook
Now that the interface.language.change hook is fired when the user
switches language using the Compact Language Switcher, we should provide
additional context to the UniversalLanguageSelector instrument.

Bug: T280770
Change-Id: I6c4ddf9738e527ac42581c9fb4924ed1d12748b4
2021-06-21 21:25:31 +00:00

185 lines
6.2 KiB
JavaScript

/**
* Setup code for content language selector dialog
*/
/* eslint-disable no-implicit-globals */
var commonInterlanguageList = null;
/**
* @param {string[]} languageCodes array of language codes available
* @return {Array} of languages filtered to those commonly used
*/
function filterForCommonLanguagesForUser( languageCodes ) {
if ( commonInterlanguageList === null ) {
commonInterlanguageList = mw.uls.getFrequentLanguageList()
.filter( function ( language ) {
return languageCodes.indexOf( language ) >= 0;
} );
}
return commonInterlanguageList;
}
/**
* @param {Object} languagesObject mapping language codes to DOMElements
* @return {Object} mapping language codes to the textContent of DOMElements
*/
function languageObjectTextContent( languagesObject ) {
var newLanguageObject = {};
Object.keys( languagesObject ).forEach( function ( langCode ) {
newLanguageObject[ langCode ] = languagesObject[ langCode ].textContent;
} );
return newLanguageObject;
}
/**
* Launches an instance of UniversalLanguageSelector for changing to another
* article language.
*
* @param {jQuery.Object} $trigger for opening ULS dialog
* @param {Object} languagesObject of the available languages, mapping code (string) to Element
* @param {boolean} forCLS Whether to enable compact language links specific behavior
*/
function launchULS( $trigger, languagesObject, forCLS ) {
var ulsConfig = {
/**
* Language selection handler
*
* @param {string} language language code
* @param {Object} event jQuery event object
*/
onSelect: function ( language, event ) {
$trigger.removeClass( 'selector-open' );
mw.uls.addPreviousLanguage( language );
// Switch the current tab to the new language, unless it was
// {Ctrl,Shift,Command} activation on a link
if (
event.target instanceof HTMLAnchorElement &&
( event.metaKey || event.shiftKey || event.ctrlKey )
) {
return;
}
// TODO: The name of this hook should probably be changed to reflect that it covers
// both the user changing their interface language and the user switching to a
// different language.
mw.hook( 'mw.uls.interface.language.change' ).fire( language, 'content-language-switcher' );
location.href = languagesObject[ language ].href;
},
onPosition: function () {
// Override the default positioning. See https://phabricator.wikimedia.org/T276248
// Default positioning of jquery.uls is middle of the screen under the trigger.
// This code aligns it under the trigger and to the trigger edge depending on which
// side of the page the trigger is - should work automatically for both LTR and RTL.
var offset, height, width;
// These are for the trigger.
offset = $trigger.offset();
width = $trigger.outerWidth();
height = $trigger.outerHeight();
if ( offset.left + ( width / 2 ) > $( window ).width() / 2 ) {
// Midpoint of the trigger is on the right side of the viewport.
return {
// Right edge of the dialog aligns with the right edge of the trigger.
right: $( window ).width() - ( offset.left + width ),
top: offset.top + height
};
} else {
// Midpoint of the trigger is on the left side of the viewport.
return {
// Left edge of the dialog aligns with the left edge of the trigger.
left: offset.left,
top: offset.top + height
};
}
},
onVisible: function () {
$trigger.addClass( 'selector-open' );
// Note well that this hook is unstable.
mw.hook( 'mw.uls.compact_language_links.open' ).fire( $trigger );
},
languageDecorator: function ( $languageLink, language ) {
var element = languagesObject[ language ];
// Set href, text, and tooltip exactly same as what was in
// interlanguage link. The ULS autonym might be different in some
// cases like sr. In ULS it is "српски", while in interlanguage links
// it is "српски / srpski"
$languageLink
.prop( {
href: element.href,
title: element.title
} )
.text( element.textContent );
// This code is to support badges used in Wikimedia
// eslint-disable-next-line mediawiki/class-doc
$languageLink.parent().addClass( element.parentNode.className );
},
onCancel: function () {
$trigger.removeClass( 'selector-open' );
},
languages: languageObjectTextContent( languagesObject ),
ulsPurpose: 'compact-language-links',
// Show common languages
quickList: filterForCommonLanguagesForUser(
Object.keys( languagesObject )
),
noResultsTemplate: function () {
var $defaultTemplate = $.fn.lcd.defaults.noResultsTemplate.call( this );
// Customize the message
$defaultTemplate
.find( '.uls-no-results-found-title' )
.data( 'i18n', 'ext-uls-compact-no-results' );
return $defaultTemplate;
}
};
if ( forCLS ) {
// Styles for these classes are defined in the ext.uls.compactlinks module
ulsConfig.onReady = function () {
// This class enables the caret
this.$menu.addClass( 'interlanguage-uls-menu' );
};
ulsConfig.onPosition = function () {
// Compact language links specific positioning with a caret
var top, left, offset, height, width, triangleWidth;
// The panel is positioned carefully so that our pointy triangle,
// which is implemented as a square box rotated 45 degrees with
// rotation origin in the middle. See the corresponding style file.
// These are for the trigger
offset = $trigger.offset();
width = $trigger.outerWidth();
height = $trigger.outerHeight();
// Triangle width is: who knows now, but this still looks fine.
triangleWidth = 12;
// selector-{left,right} control which side the caret appears.
// It needs to match the positioning of the dialog.
if ( offset.left > $( window ).width() / 2 ) {
left = offset.left - this.$menu.outerWidth() - triangleWidth;
this.$menu.removeClass( 'selector-left' ).addClass( 'selector-right' );
} else {
left = offset.left + width + triangleWidth;
this.$menu.removeClass( 'selector-right' ).addClass( 'selector-left' );
}
// Offset from the middle of the trigger
top = offset.top + ( height / 2 ) - 27;
return {
left: left,
top: top
};
};
}
// Attach ULS behavior to the trigger. ULS will be shown only once it is clicked.
$trigger.uls( ulsConfig );
}
module.exports = launchULS;