MediaWiki:Postal map.js
Jump to navigation
Jump to search
Nota: dopo aver pubblicato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.
- Firefox / Safari: tieni premuto il tasto delle maiuscole Shift e fai clic su Ricarica, oppure premi Ctrl-F5 o Ctrl-R (⌘-R su Mac)
- Google Chrome: premi Ctrl-Shift-R (⌘-Shift-R su un Mac)
- Internet Explorer / Edge: tieni premuto il tasto Ctrl e fai clic su Aggiorna, oppure premi Ctrl-F5
- Opera: premi Ctrl-F5.
// This was reverse-engineered from https://ark.gamepedia.com/Widget:SpawnMap
$( function () {
if ( !document.getElementById("postal-map") ) return; // Early exit
mw.loader.using('mediawiki.api').then(function() {
var api = new mw.Api();
var input = document.createElement("input");
input.setAttribute("id", "postal-input");
input.setAttribute("placeholder", "Delivery target");
api.get({
"action": "parse",
"format": "json",
"pageid": 252, // at time of writing, [[Postal_service/data.json]]
"prop": "wikitext",
"formatversion": "2"
}).then(function(data){
var targets = JSON.parse(data.parse.wikitext);
var $select = $('<select id="postal-dropdown">')
.append($('<option>').val('').text('Select a delivery target'))
.change(function () {
// when the dropdown updates, update the map and the input
showLocation($(this).val());
input.value = $(this).val();
});
// When the input updates, update the map and the dropdown
input.addEventListener("input", function (e) {
showLocation(this.value);
$select.val(this.value);
});
// Create the list of names
var names = []
Object.keys(targets).forEach(function(target){
names.push(String(target));
});
names.sort(function(a, b){return a.localeCompare(b);});
// Add the list of names to the dropdown menu
names.forEach(function(name) {
$select.append($('<option>').text(name));
});
// Add the input and dropdown menu to the legend
$('#legend-container').prepend($select);
$('#postal-autocomplete').prepend(input);
// start the autocomplete script
postalAutocomplete(input, names);
//Allows for use of # anchors in the url to start the map with that item selected
var urlHash = decodeURIComponent(window.location.hash);
if (urlHash) {
input.value = urlHash.substr(1);
showLocation(input.value);
}
function showLocation(name) {
var $mapContainer = $('#postal-map').find('#map-container');
// clear notes
var description = document.querySelector("#legend-container .description");
var locationLabel = document.querySelector("#legend-container .location");
description.innerHTML = "";
locationLabel.innerHTML = "";
// clear the map
$mapContainer.children('.delivery-target').remove();
if (!name || !(names.includes(name))){
// clear the # in the URL, but also keep the page from jumping back to the top
lastPos = $(window).scrollTop();
window.location.hash = '';
$(window).scrollTop(lastPos);
return;
}
else {
$mapContainer.children('.selected').removeClass('selected');
}
// draw point to the map
var $target = targets[name];
var pointSize = 10;
// Remove all spaces and question marks (for The Highbelow?) in the target's location so we can get a valid HTML id
// then find the map with that id and mark it as selected
$mapContainer.children('#' + $target.map.replace(/ |\?/g, '')).addClass('selected');
$mapContainer.prepend($('<div>').addClass('delivery-target')
.css({'left': 'calc(' + $target.x + '%' + ' - ' + (pointSize / 2) + 'px)',
'top': 'calc(' + $target.y + '%' + ' - ' + (pointSize / 2) + 'px)',
'width': pointSize,
'height': pointSize})
);
locationLabel.textContent = $target.map;
if ($target.note != undefined){
// send this through the parser so that we can allow valid wikitext while disallowing any other html
api.get({
"action": "parse",
"format": "json",
"text": $target.note,
"prop": "text",
"wrapoutputclass": "",
"disablelimitreport": 1,
"contentmodel": "wikitext",
"formatversion": "2"
}).then(function(data){
description.innerHTML = data.parse.text;
});
}
window.location.hash = name;
};
// autcomplete functionality was copied with modification from https://www.w3schools.com/howto/howto_js_autocomplete.asp
function postalAutocomplete(inp, arr) {
// the autocomplete function takes two arguments, the text field element and an array of possible autocompleted values:
var currentFocus;
// execute a function when someone writes in the text field:
inp.addEventListener("input", function(e) {
var a, b, i, val = this.value.toLowerCase();
var maxResults = 10;
// close any already open lists of autocompleted values
closeAllLists();
if (!val) { return false;}
currentFocus = -1;
// create a div element that will contain the items (values):
a = document.createElement("div");
a.setAttribute("id", "postal-autocomplete-list");
a.setAttribute("class", "postal-autocomplete-items");
// append the div element as a child of the autocomplete container:
this.parentNode.appendChild(a);
// bottomStart is going to point to the bottom element of the half of the list that contains
// the results that start with the input. We use this to sort this half of the list alphabetically
var bottomStart = null
// for each item in the array...
for (i = 0; i < arr.length; i++) {
var currentName = arr[i];
if(targets[currentName].normalized){
currentName = targets[currentName].normalized;
}
currentName = currentName.toLowerCase();
// check if the item starts with or contains the same letters as the text field value:
if (currentName.substr(0, val.length) == val || currentName.includes(val)) {
// create a div element for each matching element:
b = document.createElement("div");
// make the matching letters bold:
var index = currentName.indexOf(val);
b.appendChild( document.createTextNode( arr[ i ].substr( 0, index ) ) );
var strong = document.createElement( 'strong' );
strong.textContent = arr[ i ].substr( index, val.length );
b.appendChild( strong );
b.appendChild( document.createTextNode( arr[ i ].substr( index + val.length ) ) );
// insert an input field that will hold the current array item's value:
// Replace apostrophes with their html entity so they don't end the string
var input = document.createElement('input');
input.type = 'hidden';
input.value = arr[i];
b.appendChild(input);
// execute a function when someone clicks on the item value (DIV element):
b.addEventListener("click", function(e) {
// insert the value for the autocomplete text field:
inp.value = this.getElementsByTagName("input")[0].value;
showLocation(document.getElementById("postal-input").value);
// close the list of autocompleted values
closeAllLists();
});
// Add the suggestion to the list, prioritizing starting with over containing
if(index == 0) {
// if our input is at the start of the string
if(!bottomStart){
a.prepend(b);
bottomStart = b;
}
else {
bottomStart.insertAdjacentElement('afterend', b);
bottomStart = b;
}
}
else if (a.children.length <= maxResults) {
// if our input is within the string, but not at the start, and we haven't reached results cap
a.append(b);
}
// show no more than 10 suggestions at once
if(a.children.length > maxResults) {
a.lastChild.remove();
}
}
}
});
// execute a function when a key is pressed:
inp.addEventListener("keydown", function(e) {
var x = document.getElementById("postal-autocomplete-list");
if (x) x = x.getElementsByTagName("div");
if (e.keyCode == 40) {
// If the arrow DOWN key is pressed, increase the currentFocus variable:
currentFocus++;
// and make the current item more visible:
addActive(x);
} else if (e.keyCode == 38) {
//If the arrow UP key is pressed, decrease the currentFocus variable:
currentFocus--;
// and make the current item more visible:
addActive(x);
} else if (e.keyCode == 13) {
// If the ENTER key is pressed, prevent the form from being submitted,
e.preventDefault();
if (currentFocus > -1) {
// and simulate a click on the "active" item:
if (x) x[currentFocus].click();
}
}
});
function addActive(x) {
// classify an item as "active":
if (!x) return false;
//start by removing the "active" class on all items:
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
// add class "postal-autocomplete-active":
x[currentFocus].classList.add("postal-autocomplete-active");
}
function removeActive(x) {
// remove the "active" class from all autocomplete items:
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("postal-autocomplete-active");
}
}
function closeAllLists(elmnt) {
// close all autocomplete lists in the document, except the one passed as an argument:
var x = document.getElementsByClassName("postal-autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
// close the autocomplete when someone clicks in the document:
document.addEventListener("click", function (e) {
closeAllLists(e.target);
});
}
});
});
});