User:Erutuon/scripts/searchLang.js

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.

  • Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
  • Konqueror and Chrome: click Reload or press F5;
  • Opera: clear the cache in Tools → Preferences;
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.

This script adds a box to search for languages in the sidebar. It gets language names and codes via Module:languages/javascript-interface and saves them in localStorage. It requires a modern browser with ECMAScript 2016 (ES7).

To do:

  • Make sure data is up-to-date. Set expiration date or check for edit to module?

Ideas:

  • Diacritic stripping.
  • Allow customization through a global object.
  • Search non-canonical names; but how to display them?

/* jshint boss: true, esversion: 6, latedef: true, loopfunc: true, undef: true, unused: true, varstmt: true */
/* globals $, mw */

$.getScript("//en.wiktionary.org/w/index.php?title=User:Erutuon/scripts/apiWrapper.js&action=raw")
.done(function () {
$.when(
	$.getScript("//en.wiktionary.org/w/index.php?title=User:Erutuon/scripts/LanguageSearcher.js&action=raw"),
	mw.loader.using([ "mediawiki.util", "mediawiki.storage" ])
).done(function () {
"use strict";

if (!(window.LanguageSearcher && mw.util && mw.storage))
	return console.error("failed to load necessary stuff");

function clearChildren(element) {
	if (!(element instanceof Node))
		throw new TypeError("Expected Node");
	
	let child;
	while (child = element.firstChild)
		element.removeChild(child);
}

function newSidebarBox(idPrefix, nextElementId) {
	const box = document.createElement("div");
	box.id = idPrefix;
	box.className = "portlet";

	const header = document.createElement("h3");
	header.id = idPrefix + "-label";

	const body = document.createElement("div");
	body.className = "pBody";

	box.appendChild(header);
	box.appendChild(body);
	
	if (nextElementId) {
		const nextElement = document.getElementById(nextElementId);
		if (!nextElement)
			throw new Error("No element with id " + nextElementId);
		nextElement.parentNode.insertBefore(box, nextElement);
	}
	else {
		const sidebar = document.getElementById("sidebar");
		if (!sidebar)
			throw new Error("Could not find sidebar");
		sidebar.appendChild(box);
	}
	
	
	return { box: box, header: header, body: body };
}

const idPrefix = "p-searchlang";
const searchLangBox = newSidebarBox(idPrefix, "p-lang");
searchLangBox.header.textContent = "Search for language";
searchLangBox.body.style.padding = "0.5em 0.4em 0.4em 0.4em";

const textBox = document.createElement("input");
textBox.type = "search";
textBox.style.width = "10.9em";
textBox.placeholder = "Language search";
textBox.title = "Search for a language by name";

const resultList = document.createElement("ul");
resultList.id = idPrefix + "-list";

const $textBox = $(textBox);

$textBox.on("keydown", event => {
	if (event.which == 0x0D) // enter key
		event.preventDefault();
});

// https://tomelliott.com/jquery/javascript-delay-input-field-change
const storageKey = "WiktionaryNameToCode";
const searcher = new window.LanguageSearcher(
	storageKey,
	results => {
		clearChildren(resultList);
		if (results.length > 0)
			results.forEach(result => resultList.appendChild(result.print()));
	});
const makeDelayedFunction = (func, delay) => {
	let timer;
	return () => {
		window.clearTimeout(timer);
		timer = window.setTimeout(func, delay);
	};
};
let prevVal;
$textBox.on("input", makeDelayedFunction(() => {
	const val = $textBox.val();
	
	if (val === prevVal)
		return;
	else
		prevVal = val;
	
	searcher.doSearch(val);
}, 300));

const form = document.createElement("form");
form.appendChild(textBox);

searchLangBox.body.appendChild(form);
searchLangBox.body.appendChild(resultList);

});

});