Separate compacting of language list from launching of dialog
This refactor will allow us to separate these two functions so that the modernized version of Vector can avoid loading the compact language list. Changes: * `options` is now optional to the CompactInterlanguageList constructor The max value is already defined in CompactInterlanguageList.prototype.init * this.interlanguageList is now initialized inside the constructor Previously calling CompactInterlanguageList.prototype.createSelector or getCompactList before calling init would throw an exception. This will be important in I0518ecdf402ebf5eb6bad2c430f6462322c0d8e1 when the responsibilities of wiring up the button and compacting the languages is separated. Bug: T264824 Change-Id: I9606df30a050d0cdaf7add2deff849cd5b895bab
This commit is contained in:
@@ -103,6 +103,35 @@
|
||||
} catch ( e ) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize a language code for ULS usage.
|
||||
*
|
||||
* MediaWiki language codes (especially on WMF sites) are inconsistent
|
||||
* with ULS codes. We need to use ULS codes to access the proper data.
|
||||
*
|
||||
* @param {string} code
|
||||
* @return {string} Normalized language code
|
||||
*/
|
||||
mw.uls.convertMediaWikiLanguageCodeToULS = function ( code ) {
|
||||
code = code.toLowerCase();
|
||||
return $.uls.data.isRedirect( code ) || code;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Element[]} nodes to parse
|
||||
* @return {Object} that maps language codes to the corresponding DOM elements
|
||||
*/
|
||||
mw.uls.getInterlanguageListFromNodes = function ( nodes ) {
|
||||
var interlanguageList = {};
|
||||
|
||||
Array.prototype.forEach.call( nodes, function ( el ) {
|
||||
var langCode = mw.uls.convertMediaWikiLanguageCodeToULS( el.lang );
|
||||
interlanguageList[ langCode ] = el;
|
||||
} );
|
||||
|
||||
return interlanguageList;
|
||||
};
|
||||
|
||||
mw.uls.getPreviousLanguages = function () {
|
||||
var previousLanguages = [];
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
( function () {
|
||||
'use strict';
|
||||
|
||||
var DEFAULT_LIST_SIZE = 9;
|
||||
var DEFAULT_LIST_SIZE = 9,
|
||||
launchULS = require( './ext.uls.launch.js' );
|
||||
|
||||
/**
|
||||
* @param {Array} target
|
||||
@@ -44,20 +45,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a language code for ULS usage.
|
||||
*
|
||||
* MediaWiki language codes (especially on WMF sites) are inconsistent
|
||||
* with ULS codes. We need to use ULS codes to access the proper data.
|
||||
*
|
||||
* @param {string} code
|
||||
* @return {string} Normalized language code
|
||||
*/
|
||||
function convertMediaWikiLanguageCodeToULS( code ) {
|
||||
code = code.toLowerCase();
|
||||
return $.uls.data.isRedirect( code ) || code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-defined assistant languages on wikis with Translate extension.
|
||||
*
|
||||
@@ -144,7 +131,9 @@
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {HTMLElement} listElement Interlanguage list element
|
||||
* @param {Object} options
|
||||
* @param {Object} [options]
|
||||
* @param {Number} [options.max] maximum number of languages to show
|
||||
* in the compacted list. This defaults to DEFAULT_LIST_SIZE.
|
||||
*/
|
||||
function CompactInterlanguageList( listElement, options ) {
|
||||
this.listElement = listElement;
|
||||
@@ -154,7 +143,9 @@
|
||||
* @private
|
||||
* @property {Object} interlanguageList
|
||||
*/
|
||||
this.interlanguageList = null;
|
||||
this.interlanguageList = mw.uls.getInterlanguageListFromNodes(
|
||||
listElement.querySelectorAll( '.interlanguage-link-target' )
|
||||
);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -174,7 +165,6 @@
|
||||
CompactInterlanguageList.prototype.init = function () {
|
||||
var max = this.options.max || DEFAULT_LIST_SIZE;
|
||||
|
||||
this.interlanguageList = this.getInterlanguageList();
|
||||
this.listSize = Object.keys( this.interlanguageList ).length;
|
||||
|
||||
if ( this.listSize <= max ) {
|
||||
@@ -213,99 +203,10 @@
|
||||
* @param {jQuery} $trigger Element to use as trigger.
|
||||
*/
|
||||
CompactInterlanguageList.prototype.createSelector = function ( $trigger ) {
|
||||
var languageCode,
|
||||
languages = Object.keys( this.interlanguageList ),
|
||||
self = this,
|
||||
ulsLanguageList = {};
|
||||
|
||||
for ( languageCode in this.interlanguageList ) {
|
||||
ulsLanguageList[ languageCode ] = this.interlanguageList[ languageCode ].textContent;
|
||||
}
|
||||
|
||||
// Attach ULS to the trigger
|
||||
$trigger.uls( {
|
||||
onReady: function () {
|
||||
this.$menu.addClass( 'interlanguage-uls-menu' );
|
||||
},
|
||||
/**
|
||||
* Language selection handler
|
||||
*
|
||||
* @param {string} language language code
|
||||
* @param {Object} event jQuery event object
|
||||
*/
|
||||
onSelect: function ( language, event ) {
|
||||
self.$trigger.removeClass( 'selector-open' );
|
||||
mw.uls.addPreviousLanguage( language );
|
||||
|
||||
// Switch the current tab to the new language,
|
||||
// unless it was Ctrl-click or Command-click
|
||||
if ( !event.metaKey && !event.shiftKey ) {
|
||||
location.href = self.interlanguageList[ language ].href;
|
||||
}
|
||||
},
|
||||
onVisible: function () {
|
||||
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;
|
||||
|
||||
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' );
|
||||
},
|
||||
languageDecorator: function ( $languageLink, language ) {
|
||||
var element = self.interlanguageList[ 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: ulsLanguageList,
|
||||
ulsPurpose: 'compact-language-links',
|
||||
// Show common languages
|
||||
quickList: self.getCommonLanguages( languages ),
|
||||
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;
|
||||
}
|
||||
} );
|
||||
launchULS(
|
||||
$trigger,
|
||||
this.interlanguageList
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -411,7 +312,7 @@
|
||||
CompactInterlanguageList.prototype.getLangsInText = function () {
|
||||
var languagesInText = [];
|
||||
Array.prototype.forEach.call( document.querySelectorAll( '#mw-content-text [lang]' ), function ( el ) {
|
||||
var lang = convertMediaWikiLanguageCodeToULS( el.lang );
|
||||
var lang = mw.uls.convertMediaWikiLanguageCodeToULS( el.lang );
|
||||
if ( languagesInText.indexOf( lang ) === -1 ) {
|
||||
languagesInText.push( lang );
|
||||
}
|
||||
@@ -430,7 +331,7 @@
|
||||
return Array.prototype.map.call(
|
||||
document.querySelectorAll( '#p-lang [class*="badge"]' ),
|
||||
function ( el ) {
|
||||
return convertMediaWikiLanguageCodeToULS(
|
||||
return mw.uls.convertMediaWikiLanguageCodeToULS(
|
||||
el.querySelector( '.interlanguage-link-target' ).lang
|
||||
);
|
||||
}
|
||||
@@ -443,14 +344,7 @@
|
||||
* @return {Object} Map of language codes to elements.
|
||||
*/
|
||||
CompactInterlanguageList.prototype.getInterlanguageList = function () {
|
||||
var interlanguageList = {};
|
||||
|
||||
Array.prototype.forEach.call( this.listElement.querySelectorAll( '.interlanguage-link-target' ), function ( el ) {
|
||||
var langCode = convertMediaWikiLanguageCodeToULS( el.lang );
|
||||
interlanguageList[ langCode ] = el;
|
||||
} );
|
||||
|
||||
return interlanguageList;
|
||||
return this.interlanguageList;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -524,10 +418,7 @@
|
||||
// Not all namespaces/pages/actions have #p-lang.
|
||||
return;
|
||||
}
|
||||
compactList = new CompactInterlanguageList( listElement, {
|
||||
// Compact the list to this size
|
||||
max: 9
|
||||
} );
|
||||
compactList = new CompactInterlanguageList( listElement );
|
||||
compactList.init();
|
||||
|
||||
}
|
||||
|
||||
128
resources/js/ext.uls.launch.js
Normal file
128
resources/js/ext.uls.launch.js
Normal file
@@ -0,0 +1,128 @@
|
||||
/* 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
|
||||
*/
|
||||
function launchULS( $trigger, languagesObject ) {
|
||||
// Attach ULS to the trigger
|
||||
$trigger.uls( {
|
||||
onReady: function () {
|
||||
this.$menu.addClass( 'interlanguage-uls-menu' );
|
||||
},
|
||||
/**
|
||||
* 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-click or Command-click
|
||||
if ( !event.metaKey && !event.shiftKey ) {
|
||||
location.href = languagesObject[ language ].href;
|
||||
}
|
||||
},
|
||||
onVisible: function () {
|
||||
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;
|
||||
|
||||
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' );
|
||||
},
|
||||
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;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
module.exports = launchULS;
|
||||
Reference in New Issue
Block a user