diff --git a/index.html b/index.html index 955fc46..553fa06 100644 --- a/index.html +++ b/index.html @@ -163,48 +163,103 @@ function onRegionChange(){ const vsel=document.getElementById('villageSelect'); dsel.innerHTML=''; vsel.innerHTML=''; - districtList=[];regionRelId=null; + districtList=[]; if(!region){document.getElementById('locStatus').textContent='';return;} map.setView(region.center,9); const st=document.getElementById('locStatus'); - st.textContent='⏳ '+name+'...'; - // Пробуем найти регион через Nominatim (надёжнее всего) - fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' область')+'&countrycodes=kz&limit=3&type=administrative') + st.textContent='⏳ районы '+name+'...'; + // Ищем районы через Nominatim + const queries=[ + 'районы '+name+' области', + 'районы '+name+' облысы', + name+' район', + name+' аудан' + ]; + let done=false; + for(const q of queries){ + if(done)break; + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(q)+'&countrycodes=kz&limit=30&type=administrative') + .then(r=>r.json()) + .then(data=>{ + if(done||!data||!data.length)return; + done=true; + const seen=new Set(); + dsel.innerHTML=''; + data.forEach(item=>{ + let n=item.display_name.split(',')[0].trim(); + if(!n||seen.has(n)||n===name||n.toLowerCase().includes('город'))return; + seen.add(n); + const o=document.createElement('option'); + o.value=n;o.textContent=n; + dsel.appendChild(o); + districtList.push({name:n,lat:item.lat,lon:item.lon}); + }); + st.textContent='✅ '+seen.size+' районов'; + }); + } + // fallback если ничего не нашли + setTimeout(()=>{ + if(!done){ + dsel.innerHTML=''; + st.textContent='⚠ введите район вручную'; + } + },3000); +} + +function onDistrictSelect(){ + const dname=document.getElementById('districtSelect').value; + const vsel=document.getElementById('villageSelect'); + vsel.innerHTML=''; + if(!dname||!districtList.length){ + vsel.innerHTML=''; + return; + } + const dist=districtList.find(d=>d.name===dname); + if(!dist){ + vsel.innerHTML=''; + return; + } + st.textContent='⏳ сёла '+dname+'...'; + // Ищем сёла через Nominatim + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(dname+' район село')+'&countrycodes=kz&limit=50') .then(r=>r.json()) - .then(list=>{ - if(!list.length)return fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' облысы')+'&countrycodes=kz&limit=3&type=administrative').then(r=>r.json()); - return list; - }) - .then(list=>{ - if(!list||!list.length||!list[0].osm_id){st.textContent='⚠ регион не найден в Nominatim';return;} - const item=list[0]; - regionRelId=item.osm_id; - st.textContent='⏳ районы '+name+'...'; - // Ищем районы через Overpass: area(3600000000+osm_id) - const q='[out:json][timeout:20];area('+(3600000000+item.osm_id)+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7|8"];);out tags id;'; - return fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q)); - }) - .then(r=>r&&r.json()) .then(data=>{ - if(!data||!data.elements||!data.elements.length){ - st.textContent='⚠ районы не найдены через OSM'; - // fallback: через Nominatim - fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent('районы '+name+' области')+'&countrycodes=kz&limit=30') - .then(r=>r.json()).then(nom=>{ - dsel.innerHTML=''; - const seen=new Set(); - nom.forEach(item=>{ - let n=item.display_name.split(',')[0].trim(); - if(!n||seen.has(n)||n===name)return;seen.add(n); - const o=document.createElement('option'); - o.value=n;o.textContent=n; - dsel.appendChild(o); - districtList.push({name:n,osm_id:item.osm_id||0}); - }); - st.textContent='✅ Nominatim: '+seen.size; - }); + vsel.innerHTML=''; + if(!data||!data.length){ + vsel.innerHTML=''; + st.textContent='⚠ сёла не найдены'; return; } + const villages=[]; + data.forEach(item=>{ + if(item.type==='village'||item.type==='hamlet'||item.type==='town'||item.type==='settlement'){ + villages.push({name:item.display_name.split(',')[0].trim(),lat:item.lat,lon:item.lon}); + } + }); + villages.sort((a,b)=>a.name.localeCompare(b.name,'ru')); + villages.forEach(v=>{ + const o=document.createElement('option'); + o.value=v.name;o.dataset.lat=v.lat;o.dataset.lon=v.lon;o.textContent=v.name; + vsel.appendChild(o); + }); + st.textContent='✅ '+villages.length+' сёл'; + }) + .catch(()=>{ + vsel.innerHTML=''; + }); +} + +function onVillageSelect(){ + const vsel=document.getElementById('villageSelect'); + const opt=vsel.options[vsel.selectedIndex]; + if(!opt||!opt.dataset.lat)return; + const lat=parseFloat(opt.dataset.lat),lon=parseFloat(opt.dataset.lon); + if(!isNaN(lat)&&!isNaN(lon)){ + map.setView([lat,lon],16); + showToast('📍 '+opt.value); + setTimeout(autoDetect,500); + } +} const seen=new Map(); data.elements.forEach(el=>{ if(!el.tags||!el.tags.name)return;