MediaWiki:Gadget-nearby.js

// complete rewrite of hippietrail's obsolete User:Hippietrail/nearbypages.js. // TODO: query only when visible? //        setInterval( function  {if (mw.viewport.isElementInViewport($("#French"))) doFrench;}, 100);

function WiktNearby { this.hasDiacritics = ["English", "French"]; //these languages have weird sortkey generation procedure this.hasWeirderSortkeyGeneration = ["Japanese"]; //these languages have even weirder sorkey generation mechanism than the ones listed above this.sortkeys = {}; //[lang] -> sortkey // entry point this.initialize = function { mw.util.addCSS(".loader{border:3px solid #ccc;border-top:3px solid #7a0000;border-radius:50%;width:6px;height:6px;animation:spin 0.9s linear infinite}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}"); var that = this; var pairs; if (!window.tabbedLanguages) pairs = this.getLanguageElementPairs; else pairs = this.getLanguageElementPairsForTabbed;

let lemmaLanguages = pairs.filter(pair => $(`#mw-normal-catlinks li:contains('${pair.lang} lemmas')`).length > 0); lemmaLanguages.forEach(pair => pair.addLoadingIcon); lemmaLanguages.forEach(pair => {			that.queryAndDisplay(pair.lang, pair.elem);		}); };

this.getLanguageElementPairs = function { return $("#bodyContent h2>.mw-headline, #bodyContent div.mw-heading>h2").map((index, headline_elem) => {			var s = $(headline_elem);			var lang = s.text;			var $elem = $(" » ");			return {				lang: lang,				elem: $elem,				addLoadingIcon:  => {					s.parent.after($elem);					s.parent.after(" Nearby ");				}			};		}).get; };

this.getLanguageElementPairsForTabbed = function { return $("#bodyContent .languageContainer").map((index, headline_elem) => {			var s = $(headline_elem);			var lang = s.attr("id"); lang = lang.substring(0, lang.length - "container".length);			var $elem = $(" » ");			return {				lang: lang,				elem: $elem,				addLoadingIcon:  => {					s.prepend($elem);					s.prepend(" Nearby ");				}			};		}).get; };

this.getSortkeyPrefix = function(lang) {		//console.log("getSortkeyPrefix: ", lang); var fetchSortkeys = => {			if (this.sortkeys.length > 0) return Promise.resolve(this.sortkeys); var getCatsParams = { action: "query", format: "json", titles: mw.config.values.wgTitle, clprop: "sortkey", prop: "categories", clcategories: this.hasWeirderSortkeyGeneration.map(l => "Category:" + l + " lemmas").join("|") };			var prms = new mw.Api.get(getCatsParams).then(r => {				//console.log("mw.Api: ", r);				let fetchedCategories = r.query.pages[mw.config.get("wgArticleId")].categories;				fetchedCategories = fetchedCategories || [];				fetchedCategories.forEach((val) => { var lang = val.title.match("Category:(.*) lemmas"); if (lang !== null) { lang = lang[1]; this.sortkeys[lang] = val.sortkeyprefix; }				});				return this.sortkeys;			}); return Promise.resolve(prms); };		if ($.inArray(lang, this.hasWeirderSortkeyGeneration) >= 0) return Promise.resolve(fetchSortkeys.then(sortkeys => sortkeys[lang])); else return Promise.resolve(mw.config.values.wgTitle); };	this.queryAndDisplay = function(lang, $elem) { var that = this;

if (!window.NearbyPagesConfig) window.NearbyPagesConfig = {}; var quantity = window.NearbyPagesConfig.quantity || 5;

var params = { action: "query", cmlimit: quantity + 1, format: "json", list: "categorymembers", cmtitle: "Category:" + lang + " lemmas", cmsort: "sortkey" };		this.getSortkeyPrefix(lang).then(function(title) {			//console.log("title: " + title);			params["cmstartsortkeyprefix"] = title;			return params;		}).then(function(params)		{			var nextStuff, prevStuff;			new mw.Api.get(params).then(function(response) { response.query.categorymembers.shift; nextStuff = response.query.categorymembers.map(item => $("").attr("href", mw.util.getUrl(item.title)).text(item.title)[0].outerHTML).join(" • "); params.cmdir = "desc"; return new mw.Api.get(params); }).then(function(response) { response.query.categorymembers.reverse; if ($.inArray(lang, that.hasDiacritics) < 0) response.query.categorymembers.pop; else response.query.categorymembers.shift; prevStuff = response.query.categorymembers.map(item => $("").attr("href", mw.util.getUrl(item.title)).text(item.title)[0].outerHTML).join(" • "); var cur = "" + mw.config.values.wgTitle + " "; $elem.html("» " + prevStuff + " • " + cur + " • " + nextStuff); });		});	}; }

if (mw.config.values.wgNamespaceNumber === 0) $( => {		mw.loader.using(['mediawiki.util', 'mediawiki.api'], => { new WiktNearby.initialize; });	});