User:Erutuon/scripts/LanguageSearcher.js

// have to load apiWrapper before loading this! // $.getScript("//en.wiktionary.org/w/index.php?title=User:Erutuon/scripts/apiWrapper.js&action=raw")

/* jshint boss: true, esversion: 6, undef: true */ /* globals apiWrapper, mw */

//

(function { "use strict";

function makeWikiLink(pageName, text) { const link = document.createElement("a"); link.href = mw.util.getUrl(pageName); link.textContent = text || pageName; return link; }

function LanguageSearchResult(name, code, index, words) { this.name = name; this.code = code; this.index = index; this.words = words; }

LanguageSearchResult.prototype = { get categoryLink { // Based on getCategoryName in Module:languages. const categoryName = this.name.includes("Language") ? this.name : this.name + " language"; return makeWikiLink("Category:" + categoryName, this.name); },	get codeElement { const codeElement = document.createElement("code"); codeElement.textContent = this.code; return codeElement; }, };

LanguageSearchResult.prototype.print = function { const listItem = document.createElement("li");

for (const element of [		this.categoryLink,		document.createTextNode(" ("), this.codeElement, document.createTextNode(")")	]) listItem.appendChild(element); return listItem; };

function LanguageSearcher(storageKey, handleResults, resultSorter) { this.storageKey = storageKey; this.handleResults = handleResults; this.resultSorter = resultSorter; }

LanguageSearcher.prototype = { get storage { return mw.storage.get(this.storageKey); },	set storage (JSON) { mw.storage.set(this.storageKey, JSON); }, };

LanguageSearcher.prototype.getResults = function (query) { const results = []; query = query.toLowerCase; for (const [ name, code ] of Object.entries(window[this.storageKey])) { const lowerName = name.toLowerCase; let index = lowerName.indexOf(query); if (index === -1) index = code.indexOf(query); if (index !== -1) { const words = lowerName.split(/[- ]+/).concat(code.split("-")); results.push(new LanguageSearchResult(name, code, index, words)); }	}	return results; };

LanguageSearcher.defaultResultSorter = query => (result1, result2) => { // put results in the following groups: // 1. exact code matches if (result1.code === query || result2.code === query) return Number(result2.code === query); // 2. exact matches when "-pro" is added if (result1.code === query + "-pro" || result2.code === query + "-pro") return Number(result2.code === query + "-pro"); // 3. exact name matches if (result1.name === query || result2.name === query) return Number(result2.name === query); // 4. prefix matches if ((result1.index === 0) !== (result2.index === 0)) return result1.index - result2.index; // 5. whole word matches if (result1.words.includes(query) !== result2.words.includes(query)) return Number(result2.words.includes(query)); // within each group, alphabetize return result1.name > result2.name ? 1		: result1.name < result2.name ? -1		: 0; };

LanguageSearcher.prototype.handleQuery = function (query) { if (typeof query !== "string") throw new TypeError("Expected string"); const results = query !== "" ? this.getResults(query) : [];	if (query !== "") results.sort(this.resultSorter			? this.resultSorter(query)			: LanguageSearcher.defaultResultSorter(query)); this.handleResults(results); };

// return true if data was successfully converted from JSON LanguageSearcher.prototype.loadData = function (nameToCodeJSON) { if (nameToCodeJSON) { if (typeof nameToCodeJSON !== "string") throw new TypeError("Expected string"); try { const data = JSON.parse(nameToCodeJSON); if (typeof data !== "object") throw new TypeError("JSON should decode to an object"); window[this.storageKey] = data; return true; } catch (error) { console.log(error); }	}	return false; };

// name-to-code map process: // get JSON from Lua => save JSON in localStorage => save object as global variable LanguageSearcher.prototype.doSearch = function (query) { if (query === "" || window[this.storageKey] || this.loadData(this.storage)) { this.handleQuery(query); return; }	apiWrapper.expandTemplates(		"",		JSON => {			this.storage = JSON;			this.loadData(JSON);			this.handleQuery(query);		}); };

window.LanguageSearcher = LanguageSearcher;

});

//