Autocomplete adresy může být velice užitečná funkce. Sice většinou každý známe svoji adresu, ale pokud si necháváme doručovat jinam nebo objednáváme dárek pro někoho, tak nám to může výrazně pomoci (zvláště u městských částí a PSČ). Při googlení samozřejmě na toto najdete nějaké pluginy, ty ale využívají Google Places API.
Zkusil jsem hledat jestli by nešlo využít nějak „našich“ Seznam map, které přeci jen adresní body v ČR zvládají lépe. Seznam nabízí mnoho příkladů a mezi nimi i našeptávač. S pomocí ukázkových kódů od seznamu a této diskuze se mi tak podařilo sestavit funkční kód, který našeptává ulice a po jejímž zadání včetně č.p. předvyplní město a PSČ. Na správném vyplnění PSČ mimo jiné závisí i zóny dopravy (pokud máme nastavené).

Do fucntions.php ve své child theme napíšeme tento kód
add_action('wp_head', 'lh_seznam_naseptavac_scripts');
function lh_seznam_naseptavac_scripts() {
if (is_checkout()) {
?>
<script type="text/javascript" src="https://api.mapy.cz/loader.js"></script>
<script type="text/javascript">Loader.load(null, {suggest: true});</script>
<?php
}
}
add_action('wp_footer', 'lh_seznam_naseptavac');
function lh_seznam_naseptavac() {
if (is_checkout()) {
wp_enqueue_script(
'lh-seznam-naseptavac',
get_stylesheet_directory_uri() . '/seznam.js',
array('jquery')
);
}
}
Kód nedělá nic jiného než, že načítá potřebné javascripty. Na úvod každé funkce je podmínka is_checkout(), která nám zajišťuje, že skripty načítáme pouze na stránce pokladny.
Důležitý soubor je seznam.js, který vlastně obsahuje vše ohledně našeptávání a předvyplňování. Jak už jsem psal vycházel jsem z kódu Romana Makudery z diskuze, na kterou odkazuji výše. Tímto moc děkuji. Níže popis některých důležitých částí kódu
let suggest = new SMap.Suggest(document.querySelector("#billing_address_1"), {
factory: (data, pos) => new MyItem(data, pos),
provider: new MyProvider()
});
Tímto vytváříme objekt našeptávače, jehož vstupní pole je billing_address_1. Tedy pole v pokladně WooCommerce pro fakturační adresu. Později v kódu vytvářím ještě jeden našeptávač pro shipping_address_1 (tedy doručovací adresu)
suggest.getProvider().updateParams(params => {
params.type = "street|address";
params.category = "address_cz, area_cz";
});
Tato část nám zase říká, že chceme našeptávat pouze ulice a konkrétní adresy (type = „street|address“) v ČR (category = „address_cz, area_cz“).
suggest.addListener("suggest", suggestData => {
data = suggestData.data.origData;
document.getElementById("billing_city").value = data.quarter;
document.getElementById("billing_postcode").value = data.zipCode;
jQuery('body').trigger('update_checkout');
});
V této části konečně doplníme město a psč dle našeho výběru v našeptávači. Obdobně pak pro shipping_city a shipping_postcode.
Soubor seznam.js bude ve stejném adresáři jako functions.php. Nyní by mělo vše fungovat:)
var data; | |
class MyItem extends SMap.SuggestItem { | |
/** | |
Upravime vytvareni polozky naseptavace - pridame info o cvrti pokude existuje | |
*/ | |
_create() { | |
let node = document.createElement("li"); | |
node.classList.add("item"); | |
let titlePart = document.createElement("span"); | |
titlePart.classList.add("text"); | |
let title = document.createElement("strong"); | |
title.innerHTML = this._data.title; | |
titlePart.appendChild(title); | |
// do prvniho radku naseptavace dame informaci o ctvrti; pokud neni, tak standardni vypis | |
let d = this._data.origData; | |
data = this._data.origData; | |
//console.log(d); | |
let popisek = d.quarter ? d.quarter + (d.ward && d.ward != d.municipality ? " - " + d.ward : "") : d.secondRow; | |
this._addRow(titlePart, popisek); | |
this._addRow(titlePart, this._data.thirdRow); | |
this._dom.node = node; | |
node.appendChild(this._createIcon()); | |
node.appendChild(titlePart); | |
} | |
} | |
class MyProvider extends SMap.SuggestProvider { | |
/** | |
Upravime ziskavani dat pro naseptavac - preposleme do suggest item vsechny puvodni data, | |
kde se prave muze vyskytovat ctvrt. | |
*/ | |
_processData() { | |
if (!this._responseData) | |
return; | |
let rawData = JSON.parse(this._responseData.data); | |
if (rawData.result && Array.isArray(rawData.result)) { | |
let resultsItems = rawData.result.map(item => { | |
let poiTypeId = item.userData.poiTypeId || 0; | |
let firstRow = (item.userData.suggestFirstRow || "").trim(); | |
let id = item.userData.id; | |
if (item.userData.source == "coor" && typeof id === "number") { | |
id = item.userData.longitude + "," + item.userData.latitude; | |
} | |
return { | |
coords: SMap.Coords.fromWGS84(item.userData.longitude, item.userData.latitude), | |
longitude: parseFloat(item.userData.longitude), | |
latitude: parseFloat(item.userData.latitude), | |
source: item.userData.source, | |
id: id, | |
title: firstRow, | |
secondRow: (item.userData.suggestSecondRow || "").trim(), | |
thirdRow: (item.userData.suggestThirdRow || "").trim(), | |
phrase: firstRow || item.sentence, | |
iconType: item.userData.iconType || "", | |
iconUrl: this._getIconUrl(poiTypeId), | |
poiTypeId: poiTypeId, | |
origData: item.userData // pridame si informaci o vsech datech | |
}; | |
}); | |
this._promise.fulfill(resultsItems); | |
} | |
this._promise = null; | |
this._request = null; | |
} | |
} | |
/** | |
Vytvoreni suggestu s vlastnim itemem a providerem | |
*/ | |
let suggest = new SMap.Suggest(document.querySelector("#billing_address_1"), { | |
factory: (data, pos) => new MyItem(data, pos), | |
provider: new MyProvider() | |
}); | |
// update dat pro našeptávač | |
suggest.getProvider().updateParams(params => { | |
params.type = "street|address"; | |
// omezeni na cr | |
params.category = "address_cz, area_cz"; | |
}); | |
suggest.addListener("suggest", suggestData => { | |
// vyber polozky z naseptavace | |
/*console.log(suggestData.phrase); | |
console.log(data); | |
console.log(data.zipCode);*/ | |
data = suggestData.data.origData; | |
document.getElementById("billing_city").value = data.quarter; | |
document.getElementById("billing_postcode").value = data.zipCode; | |
jQuery('body').trigger('update_checkout'); | |
}); | |
/*Dorucovaci adresa*/ | |
let suggest_shipping = new SMap.Suggest(document.querySelector("#shipping_address_1"), { | |
factory: (data, pos) => new MyItem(data, pos), | |
provider: new MyProvider() | |
}); | |
// update dat pro našeptávač | |
suggest_shipping.getProvider().updateParams(params => { | |
params.type = "street|address"; | |
// omezeni na cr | |
params.category = "address_cz, area_cz"; | |
}); | |
suggest_shipping.addListener("suggest", suggestData => { | |
// vyber polozky z naseptavace | |
// console.log(suggestData.phrase); | |
//console.log(suggestData.data); | |
data = suggestData.data.origData; | |
// console.log(data); | |
// console.log(data.zipCode); | |
document.getElementById("shipping_city").value = data.quarter; | |
document.getElementById("shipping_postcode").value = data.zipCode; | |
jQuery('body').trigger('update_checkout'); | |
}); |