Reported in https://github.com/wikimedia/jquery.uls/pull/383#pullrequestreview-613761459 Instead of checking the left edge of the trigger, check the midpoint. This is more reliable and does not cause the dialog to incorrectly swap sides in narrow screens in LTR direction, This patch does not touch the compact language links variant. Bug: T276248 Change-Id: Ic734abb7b350852f8c5c10ced8456bf146df62d8
181 lines
6.0 KiB
JavaScript
181 lines
6.0 KiB
JavaScript
/**
|
|
* Setup code for content language selector dialog
|
|
*/
|
|
|
|
/* eslint-disable no-implicit-globals */
|
|
var commonInterlanguageList;
|
|
|
|
/**
|
|
* @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;
|
|
}
|
|
location.href = languagesObject[ language ].href;
|
|
},
|
|
onVisible: 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.
|
|
//
|
|
// FIXME: make position() overrideable in ULS to avoid doing this after the dialog
|
|
// has been made visible
|
|
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.
|
|
this.$menu.css( {
|
|
left: 'auto',
|
|
// 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.
|
|
this.$menu.css( {
|
|
// Left edge of the dialog aligns with the left edge of the trigger.
|
|
left: offset.left,
|
|
right: 'auto',
|
|
top: offset.top + height
|
|
} );
|
|
}
|
|
|
|
$trigger.addClass( 'selector-open' );
|
|
},
|
|
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.onVisible = function () {
|
|
// Compact language links specific positioning with a caret
|
|
var 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 ) {
|
|
this.left = offset.left - this.$menu.outerWidth() - triangleWidth;
|
|
this.$menu.removeClass( 'selector-left' ).addClass( 'selector-right' );
|
|
} else {
|
|
this.left = offset.left + width + triangleWidth;
|
|
this.$menu.removeClass( 'selector-right' ).addClass( 'selector-left' );
|
|
}
|
|
// Offset from the middle of the trigger
|
|
this.top = offset.top + ( height / 2 ) - 27;
|
|
|
|
this.$menu.css( {
|
|
left: this.left,
|
|
top: this.top
|
|
} );
|
|
$trigger.addClass( 'selector-open' );
|
|
};
|
|
}
|
|
|
|
// Attach ULS behavior to the trigger. ULS will be shown only once it is clicked.
|
|
$trigger.uls( ulsConfig );
|
|
}
|
|
|
|
module.exports = launchULS;
|