Joywork/js/apify/core.js
2026-05-22 21:21:54 +03:00

200 lines
7.7 KiB
JavaScript

/*
The addressAutocomplete takes as parameters:
- a container element (div)
- callback to notify about address selection
- geocoder options:
- placeholder - placeholder text for an input element
- type - location type
*/
function addressAutocomplete(containerElement, inputElement, callback, options) {
// create input element
/* var inputElement = document.createElement("input");
inputElement.setAttribute("type", "text");
inputElement.setAttribute("placeholder", options.placeholder);
containerElement.appendChild(inputElement);*/
// add input field clear button
/*var clearButton = document.createElement("div");
clearButton.classList.add("clear-button");
addIcon(clearButton);
clearButton.addEventListener("click", (e) => {
e.stopPropagation();
inputElement.value = '';
callback(null);
clearButton.classList.remove("visible");
closeDropDownList();
});
containerElement.appendChild(clearButton);*/
/* Current autocomplete items data (GeoJSON.Feature) */
var currentItems;
/* Active request promise reject function. To be able to cancel the promise when a new request comes */
var currentPromiseReject;
/* Focused item in the autocomplete list. This variable is used to navigate with buttons */
var focusedItemIndex;
/* Execute a function when someone writes in the text field: */
inputElement.addEventListener("input", function(e) {
var currentValue = this.value;
/* Close any already open dropdown list */
closeDropDownList();
// Cancel previous request promise
if (currentPromiseReject) {
currentPromiseReject({
canceled: true
});
}
/*if (!currentValue) {
clearButton.classList.remove("visible");
return false;
}
// Show clearButton when there is a text
clearButton.classList.add("visible");*/
/* Create a new promise and send geocoding request */
var promise = new Promise((resolve, reject) => {
currentPromiseReject = reject;
var apiKey = "7332251a5f314825b02b9a6f5281715a";
var url = `https://api.geoapify.com/v1/geocode/autocomplete?filter=countrycode:az&text=${encodeURIComponent(currentValue)}&limit=5&apiKey=${apiKey}`;
if (options.type) {
url += `&type=${options.type}`;
}
fetch(url)
.then(response => {
// check if the call was successful
if (response.ok) {
response.json().then(data => resolve(data));
} else {
response.json().then(data => reject(data));
}
});
});
promise.then((data) => {
currentItems = data.features;
/*create a DIV element that will contain the items (values):*/
var autocompleteItemsElement = document.createElement("div");
autocompleteItemsElement.setAttribute("class", "autocomplete-items");
containerElement.appendChild(autocompleteItemsElement);
/* For each item in the results */
data.features.forEach((feature, index) => {
/* Create a DIV element for each element: */
var itemElement = document.createElement("DIV");
/* Set formatted address as item value */
itemElement.innerHTML = feature.properties.formatted;
/* Set the value for the autocomplete text field and notify: */
itemElement.addEventListener("click", function(e) {
inputElement.value = currentItems[index].properties.formatted;
callback(currentItems[index]);
/* Close the list of autocompleted values: */
closeDropDownList();
});
autocompleteItemsElement.appendChild(itemElement);
});
}, (err) => {
if (!err.canceled) {
console.log(err);
}
});
});
/* Add support for keyboard navigation */
inputElement.addEventListener("keydown", function(e) {
var autocompleteItemsElement = containerElement.querySelector(".autocomplete-items");
if (autocompleteItemsElement) {
var itemElements = autocompleteItemsElement.getElementsByTagName("div");
if (e.keyCode == 40) {
e.preventDefault();
/*If the arrow DOWN key is pressed, increase the focusedItemIndex variable:*/
focusedItemIndex = focusedItemIndex !== itemElements.length - 1 ? focusedItemIndex + 1 : 0;
/*and and make the current item more visible:*/
setActive(itemElements, focusedItemIndex);
} else if (e.keyCode == 38) {
e.preventDefault();
/*If the arrow UP key is pressed, decrease the focusedItemIndex variable:*/
focusedItemIndex = focusedItemIndex !== 0 ? focusedItemIndex - 1 : focusedItemIndex = (itemElements.length - 1);
/*and and make the current item more visible:*/
setActive(itemElements, focusedItemIndex);
} else if (e.keyCode == 13) {
/* If the ENTER key is pressed and value as selected, close the list*/
e.preventDefault();
if (focusedItemIndex > -1) {
closeDropDownList();
}
}
} else {
if (e.keyCode == 40) {
/* Open dropdown list again */
var event = document.createEvent('Event');
event.initEvent('input', true, true);
inputElement.dispatchEvent(event);
}
}
});
function setActive(items, index) {
if (!items || !items.length) return false;
for (var i = 0; i < items.length; i++) {
items[i].classList.remove("autocomplete-active");
}
/* Add class "autocomplete-active" to the active element*/
items[index].classList.add("autocomplete-active");
// Change input value and notify
inputElement.value = currentItems[index].properties.formatted;
callback(currentItems[index]);
}
function closeDropDownList() {
var autocompleteItemsElement = containerElement.querySelector(".autocomplete-items");
if (autocompleteItemsElement) {
containerElement.removeChild(autocompleteItemsElement);
}
focusedItemIndex = -1;
}
function addIcon(buttonElement) {
var svgElement = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
svgElement.setAttribute('viewBox', "0 0 24 24");
svgElement.setAttribute('height', "24");
var iconElement = document.createElementNS("http://www.w3.org/2000/svg", 'path');
iconElement.setAttribute("d", "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z");
iconElement.setAttribute('fill', 'currentColor');
svgElement.appendChild(iconElement);
buttonElement.appendChild(svgElement);
}
/* Close the autocomplete dropdown when the document is clicked.
Skip, when a user clicks on the input field */
document.addEventListener("click", function(e) {
if (e.target !== inputElement) {
closeDropDownList();
} else if (!containerElement.querySelector(".autocomplete-items")) {
// open dropdown list again
var event = document.createEvent('Event');
event.initEvent('input', true, true);
inputElement.dispatchEvent(event);
}
});
}