diff --git a/src/brazilian_zipcode/__init__.py b/src/brazilian_zipcode/__init__.py index d228e6d..47a3958 100644 --- a/src/brazilian_zipcode/__init__.py +++ b/src/brazilian_zipcode/__init__.py @@ -1,2 +1,3 @@ from .forms import BrazilianZipCodeField +from .widgets import AutoBrazilianZipCodeInput from .objects import BrazilianAddress diff --git a/src/brazilian_zipcode/static/getAddressInfo.js b/src/brazilian_zipcode/static/getAddressInfo.js new file mode 100644 index 0000000..cfb0a80 --- /dev/null +++ b/src/brazilian_zipcode/static/getAddressInfo.js @@ -0,0 +1,88 @@ +const zipcodeSelector = "[meta_id='meta_zipcode_info']"; +const saveButtonSelector = "[name='_save']" + +function isNumeric(str) { + if (typeof str != "string") return false + return !isNaN(str) && + !isNaN(parseFloat(str)) + } + +function onlyDigits(value) { + return value.replace(/\D/g, "") +}; + +function removeReadOnlyInput(label) { + const previousElement = document.querySelector(`[meta-id='${label}']`); + if (previousElement !== null) { + previousElement.remove(); + } +} + +function createReadOnlyInput(label, value) { + const input = document.querySelector(zipcodeSelector); + const parentDiv = input.parentNode.parentNode.parentNode; + + removeReadOnlyInput(label); + const div = document.createElement("div"); + div.classList.add("form-row"); + div.setAttribute("meta-id", label) + + const valueDiv = document.createElement("div"); + const labelElement = document.createElement("label"); + + labelElement.innerText = label + ":"; + labelElement.classList.add("required"); + div.appendChild(labelElement); + + valueDiv.classList.add("readonly"); + valueDiv.innerText = value; + div.appendChild(valueDiv); + + parentDiv.appendChild(div); +} + +function getAddressInfo(zipcode) { + const saveButton = document.querySelector(saveButtonSelector); + + fetch(`/api/address_info?zipcode=${zipcode}`).then((response) => { + if (response.status !== 200) { + saveButton.setAttribute('disabled', true) + removeReadOnlyInput("Rua"); + removeReadOnlyInput("Bairro"); + removeReadOnlyInput("Cidade"); + removeReadOnlyInput("UF"); + window.alert("CEP não encontrado ou serviço indisponível"); + return + } + response.json().then(data => { + createReadOnlyInput("Rua", data.street); + createReadOnlyInput("Bairro", data.district); + createReadOnlyInput("Cidade", data.city); + createReadOnlyInput("UF", data.state_initials); + }) + }) + saveButton.removeAttribute('disabled'); +}; + +function handleOnFocusOutEvent(event) { + var zipcode = event.target.value; + zipcode = onlyDigits(zipcode); + + const input = document.querySelector(zipcodeSelector); + input.value = zipcode; + + if (zipcode.length !== 8) { + return; + } + if (!isNumeric(zipcode)) { + return + } + getAddressInfo(zipcode); +}; + + + +$(document).ready(function () { + const input = document.querySelector(zipcodeMetaId); + input.addEventListener("focusout", handleOnFocusOutEvent) +}); \ No newline at end of file diff --git a/src/brazilian_zipcode/widgets.py b/src/brazilian_zipcode/widgets.py new file mode 100644 index 0000000..e39dffd --- /dev/null +++ b/src/brazilian_zipcode/widgets.py @@ -0,0 +1,13 @@ +from django.forms import widgets +from django.utils.safestring import mark_safe + + +class AutoBrazilianZipCodeInput(widgets.TextInput): + + def render(self, name, value, **attrs): + attrs['meta_id'] = 'meta_zipcode_info' + return super().render(name, value, attrs) + + + class Media: + js = ("getAddressInfo.js",)