From 6bd858b709329c323bcde07a39320f0d79c444dd Mon Sep 17 00:00:00 2001 From: Dauren777 Date: Fri, 19 Jun 2026 06:28:02 +0000 Subject: [PATCH] v8: district list via Overpass API + Nominatim fallback --- index.html | 81 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/index.html b/index.html index 8330ee1..e1571ce 100644 --- a/index.html +++ b/index.html @@ -157,56 +157,81 @@ function init(){ function onRegionChange(){ const name=document.getElementById('regionSelect').value; const r=REGIONS.find(x=>x.name===name); - if(!r){document.getElementById('districtSelect').innerHTML='';return;} + const sel=document.getElementById('districtSelect'); + sel.innerHTML=''; + if(!r){document.getElementById('locStatus').textContent='';return;} map.setView(r.center,9); - document.getElementById('locStatus').textContent='⏳ загрузка районов...'; - // Загружаем районы области через Nominatim - fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent('районы '+name+' области')+'&countrycodes=kz&limit=30') - .then(r=>r.json()).then(data=>{ - const sel=document.getElementById('districtSelect'); + document.getElementById('locStatus').textContent='⏳ районы...'; + // Overpass: ищем админ-границы 6-8 уровня внутри области + const q='[out:json];(area["name"="'+name+' область"]["admin_level"~"[46]"];)->.a;(rel(area.a)["admin_level"~"[678]"];);out tags;'; + fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q)) + .then(r=>r.json()) + .then(data=>{ + if(!data||!data.elements){document.getElementById('locStatus').textContent='нет данных';return;} const names=new Set(); - sel.innerHTML=''; - data.forEach(item=>{ - const match=item.display_name.match(/^([^,]+),\s*([^,]+)/); - if(match){ - let dname=match[1].trim(); - if(!dname.endsWith('район')&&!dname.endsWith('ауданы'))return; - dname=dname.replace(/\s*ауданы$/,'').replace(/\s*район$/,''); - if(!names.has(dname)){ - names.add(dname); - const o=document.createElement('option'); - o.value=dname; - o.textContent=dname+(dname.endsWith('ский')||dname.endsWith('ской')?' район':''); - sel.appendChild(o); - } - } + data.elements.forEach(el=>{ + if(!el.tags||!el.tags.name)return; + let n=el.tags.name.replace(/\s*ауданы$/,'').replace(/\s*районы$/,'').replace(/\s*район$/,'').trim(); + if(n&&!names.has(n))names.add(n); }); - document.getElementById('locStatus').textContent=''; - if(names.size===0)document.getElementById('locStatus').textContent='районы не найдены'; + const sorted=[...names].sort(); + sorted.forEach(n=>{ + const o=document.createElement('option'); + o.value=n; + o.textContent=n; + sel.appendChild(o); + }); + document.getElementById('locStatus').textContent=sorted.length?'✅ районы: '+sorted.length: '⚠ районы не найдены'; + if(sorted.length===0){ + // fallback: поищем через Nominatim + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' район')+'&countrycodes=kz&limit=20') + .then(r=>r.json()).then(data2=>{ + if(!data2.length)return; + data2.forEach(item=>{ + const nm=item.display_name.split(',')[0].trim(); + const o=document.createElement('option'); + o.value=nm;o.textContent=nm; + sel.appendChild(o); + }); + document.getElementById('locStatus').textContent='✅ через Nominatim: '+data2.length; + }); + } }); } function onDistrictSelect(){ searchLocation(); } function searchLocation(){ - const parts=[document.getElementById('regionSelect').value]; + const r=document.getElementById('regionSelect').value; const d=document.getElementById('districtSelect').value; const v=document.getElementById('villageInput').value.trim(); - if(d)parts.push(d+(d.endsWith('ский')||d.endsWith('ской')?' район':'')); + const parts=[]; + if(r)parts.push(r+' область'); + if(d)parts.push(d+' район'); if(v)parts.push(v); const q=parts.join(', '); - if(!q){showToast('Выберите область или введите село');return;} + if(!q||!v&&!d){showToast('Введите название села');return;} + // Если есть район но нет села — летим в центр района + if(!v&&d){ + document.getElementById('locStatus').textContent='⏳ поиск района...'; + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(d+' район '+r+' область')+'&countrycodes=kz&limit=5') + .then(r=>r.json()).then(data=>{ + if(!data.length){showToast('❌ Район не найден');document.getElementById('locStatus').textContent='';return;} + map.setView([data[0].lat,data[0].lon],11); + document.getElementById('locStatus').textContent='📍 '+data[0].display_name.split(',')[0]; + }); + return; + } document.getElementById('locStatus').textContent='⏳ поиск...'; fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(q)+'&countrycodes=kz&limit=8') .then(r=>r.json()).then(data=>{ - if(!data.length){showToast('❌ Не найдено: '+q);document.getElementById('locStatus').textContent='не найдено';return;} + if(!data.length){showToast('❌ Не найдено');document.getElementById('locStatus').textContent='не найдено';return;} const loc=data[0]; map.setView([loc.lat,loc.lon],16); const name=loc.display_name.split(',')[0]; showToast('📍 '+name); document.getElementById('villageInput').value=name; document.getElementById('locStatus').textContent=name; - // Автозагрузка OSM данных setTimeout(autoDetect,500); }); }