let countryData = {};
let flatCountryData = [];
const IMAGE_PATH = 'https://robbieandrew.github.io/GCB2023/SVG/ctry/';
const IMAGE_TYPES = [
{ prefix: 's20_Coal_Oil_Gas_Cement', extension: 'svg'}
];
// Fetch the JSON data
fetch('https://robbieandrew.github.io/data/countryData.json')
.then(response => response.json())
.then(data => {
countryData = data;
flatCountryData = Object.entries(countryData).map(
([code, data]) => ({
mainName: code,
isoCode: data.isoCode,
variants: [code, data.isoCode, ...data.variants]
})
);
// Initialize autocomplete after data is loaded
autocomplete(document.getElementById("countryInput"));
})
.catch(error => console.error('Error loading country data:', error));
function addDownloadLink(svgObject) {
const container = svgObject.parentNode;
// Create the link
const downloadLink = document.createElement('a');
downloadLink.href = '#';
downloadLink.textContent = 'Download as PNG';
downloadLink.className = 'download-PNG';
// Add click event
downloadLink.addEventListener('click', (e) => {
e.preventDefault();
downloadSVGasPNG(svgObject);
});
// Append the link after the SVG object
container.appendChild(downloadLink);
}
function displayCountryImages(isoCode) {
const imageContainer = document.getElementById("countryImages");
imageContainer.innerHTML = ''; // Clear previous images
IMAGE_TYPES.forEach(({ prefix, extension }) => {
// if the file has extension svg, create an object, else create an img
const imageElement = extension === 'svg' ? document.createElement("object") : document.createElement("img");
imageElement.style.width = "600px";
imageElement.style.margin = "10px";
const imagePath = `${IMAGE_PATH}${prefix}_${isoCode}.${extension}`;
if (extension === 'svg') {
imageElement.data = imagePath;
imageElement.type = "image/svg+xml";
imageElement.className = "svg-object";
} else {
imageElement.src = imagePath;
imageElement.alt = `${isoCode} Image ${prefix}`;
}
imageElement.onerror = () => {
console.error(`Failed to load image: ${imagePath}`);
imageElement.remove(); // Remove the failed image from DOM
};
// Create a new div to wrap the image
const wrapperDiv = document.createElement("div");
wrapperDiv.className = "image-container";
wrapperDiv.appendChild(imageElement);
console.log(`Attempting to load: ${imagePath}`);
// Add the new element to the page inside the container
imageContainer.appendChild(wrapperDiv);
// Add a PNG download link for every SVG on the page
document.querySelectorAll('object[type="image/svg+xml"]').forEach(svgObject => {
svgObject.addEventListener('load', () => addDownloadLink(svgObject));
});
});
}
// Autocompletion code -----------------------------------------
/*function scoreMatch(variant, input) {
const lowerVariant = variant.toLowerCase();
const lowerInput = input.toLowerCase();
if (lowerVariant.startsWith(lowerInput)) {
return 100 - lowerVariant.length; // Prioritize shorter, exact matches
} else if (lowerVariant.includes(lowerInput)) {
return 50 - lowerVariant.indexOf(lowerInput); // Prioritize earlier matches
}
return 0; // No match
}*/
function scoreMatch(variant, input) {
const lowerVariant = variant.toLowerCase();
const lowerInput = input.toLowerCase();
if (lowerVariant === lowerInput) {
return 200; // Highest score for an exact match
}
if (lowerVariant.startsWith(lowerInput)) {
return 150 - lowerVariant.length; // Strong priority for matches that start with the input
} else if (lowerVariant.includes(lowerInput)) {
return 50 - lowerVariant.indexOf(lowerInput); // Lower priority for partial matches
}
return 0; // No match
}
// Reduce the number of times the search function is called, especially for fast typers
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function autocomplete(inp) {
const MAX_RESULTS = 10;
let currentFocus = -1;
const showResults = debounce((inputValue) => {
const listContainer = document.getElementById("autocomplete-list");
// Clear the list and hide it if the input is empty
if (!inputValue.trim()) {
listContainer.innerHTML = '';
listContainer.style.display = 'none';
return;
}
const lowerInput = inputValue.toLowerCase();
// Score and sort the matches
const scoredMatches = flatCountryData
.map(item => {
const bestVariantMatch = item.variants.reduce((best, variant) => {
const score = scoreMatch(variant, lowerInput);
return score > best.score ? { variant, score } : best;
}, { variant: '', score: -1 });
return { ...item, matchedVariant: bestVariantMatch.variant, score: bestVariantMatch.score };
})
.filter(item => item.score > 0)
.sort((a, b) => b.score - a.score)
.slice(0, MAX_RESULTS);
listContainer.innerHTML = '';
currentFocus = -1;
if (scoredMatches.length > 0) {
listContainer.style.display = 'block';
const fragment = document.createDocumentFragment();
scoredMatches.forEach((item, index) => {
const div = document.createElement("div");
div.setAttribute('data-index', index);
// Create main name element
const mainNameSpan = document.createElement('span');
mainNameSpan.style.fontWeight = 'bold';
// Highlight matching part in main name
const mainNameLower = item.mainName.toLowerCase();
const matchIndex = mainNameLower.indexOf(lowerInput);
if (matchIndex >= 0) {
const beforeMatch = item.mainName.substring(0, matchIndex);
const match = item.mainName.substr(matchIndex, inputValue.length);
const afterMatch = item.mainName.substring(matchIndex + inputValue.length);
mainNameSpan.innerHTML = `${beforeMatch}${match}${afterMatch}`;
} else {
mainNameSpan.textContent = item.mainName;
}
// Create variant element
const variantSpan = document.createElement('span');
variantSpan.style.fontSize = '0.8em';
variantSpan.style.color = '#666';
variantSpan.style.marginLeft = '0.5em';
// Highlight matching part in variant
const variantMatchIndex = item.matchedVariant.toLowerCase().indexOf(lowerInput);
if (variantMatchIndex >= 0) {
const beforeMatch = item.matchedVariant.substring(0, variantMatchIndex);
const match = item.matchedVariant.substr(variantMatchIndex, inputValue.length);
const afterMatch = item.matchedVariant.substring(variantMatchIndex + inputValue.length);
variantSpan.innerHTML = `(${beforeMatch}${match}${afterMatch})`;
} else {
variantSpan.textContent = `(${item.matchedVariant})`;
}
// Append both to the div
div.appendChild(mainNameSpan);
if (item.matchedVariant !== item.mainName.toLowerCase()) {
div.appendChild(variantSpan);
}
div.addEventListener("click", function() {
selectItem(item);
});
fragment.appendChild(div);
});
listContainer.appendChild(fragment);
} else if (inputValue) {
const noMatch = document.createElement("div");
noMatch.innerHTML = 'No matches found';
noMatch.style.padding = '10px';
noMatch.style.color = '#888';
noMatch.style.cursor = 'default';
listContainer.appendChild(noMatch);
}
}, 300);
function selectItem(item) {
inp.value = `${item.mainName} (${item.isoCode})`;
closeDropdown();
displayCountryImages(item.isoCode);
}
function closeDropdown() {
const listContainer = document.getElementById("autocomplete-list");
listContainer.innerHTML = '';
listContainer.style.display = 'none';
currentFocus = -1;
}
function addActive(x) {
if (!x) return false;
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
x[currentFocus].classList.add("autocomplete-active");
}
function removeActive(x) {
for (let i = 0; i < x.length; i++) {
x[i].classList.remove("autocomplete-active");
}
}
inp.addEventListener("input", function() {
showResults(this.value);
});
inp.addEventListener("keydown", function(e) {
const listContainer = document.getElementById("autocomplete-list");
let x = listContainer.getElementsByTagName("div");
if (e.key === "ArrowDown") {
currentFocus++;
addActive(x);
} else if (e.key === "ArrowUp") {
currentFocus--;
addActive(x);
} else if (e.key === "Enter") {
e.preventDefault();
if (currentFocus > -1) {
if (x) x[currentFocus].click();
} else if (x.length > 0) {
// If no item is focused, select the first item
x[0].click();
}
} else if (e.key === "Escape") {
closeDropdown();
}
});
document.addEventListener("click", function(e) {
if (e.target !== inp) {
closeDropdown();
}
});
inp.focus();
}
// Initialize
autocomplete(document.getElementById("countryInput"));