1

I am looking to filter the elements of a select list according to latitude and longitude coordinates.

Indeed, I would like to display the 10 nearest cities according to a postal code. This is my form : https://jsfiddle.net/mycreatz/zhorw4qc/

In the first field, enter a postal code (example of French postal codes: 78310, 76110). In the second field, we display the name of the city and we get its coordinates (lat + lng). In the third field, I would like to filter the list according to the coordinates of the city to display the 10 closest results.

<input type="number"  placeholder="Code Postal" autocomplete="off" pattern="[0-9]{5}" maxlength="5" name="code_postal" id="code_postal"  />

<input name="city" list="output" maxlength="100" type="text"  placeholder="Ville" autocomplete="off" id="city" list="output"  />
                                    
<datalist id="output">                                  
</datalist>
 
<select id="filter" name="filter" >
   <option value="0" selected="" disabled="">Séléctionnez ville</option>
   <option value="city__0" data-lat="46.18330317" data-lng="5.20548105 ">01960 - Ville n°1</option>
   <option value="city__2" data-lat="49.5785983" data-lng="3.65402699 ">02000 - Ville n°3</option>
   <option value="city__4" data-lat="49.84820447" data-lng="3.2701833 ">02100 - Ville n°5</option>
   <option value="city__6" data-lat="49.3622495" data-lng="3.3264193 ">02200 - Ville n°7</option>
   <option value="city__8" data-lat="46.13107447" data-lng="3.42756482 ">03200 - Ville n°9</option>
   <option value="city__10" data-lat="43.82125316" data-lng="5.7939841 ">04100 - Ville n°11</option>
</select>

JQUERY CODE :

$(function() {
  // OnKeyDown Function
  $("#code_postal").keyup(function() {
    var zip_in = $(this);
    if ((zip_in.val().length == 5)) {
     
      // Make HTTP Request
      $.ajax({
        url: "//api-adresse.data.gouv.fr/search/?q=" + zip_in.val() + "&type=municipality&limit=30",
        cache: false,
        dataType: "json",
        type: "GET",
        success: function(result, success) {

          suggestions = [];
          for (ii in result['features']) {
            //city name + lat + lng
            suggestions.push([result['features'][ii]['properties']['name'], result['features'][ii]['geometry']['coordinates'][0], result['features'][ii]['geometry']['coordinates'][1]]);
           // console.log(suggestions);
          }
          jQuery.each(suggestions, function(i, val) {
            console.log(val);
            $("#output").append("<option value=\"" + val[0] + "\" data-lat=\"" + val[2] + "\"  data-lng=\"" + val[1] + "\">");
          });

        },

      });
    }
  });
});
Creatz
  • 49
  • 5

1 Answers1

0

Here is a solution that worked for me, it uses the Haversine function

jQuery($ => {
  let $filter = $('#filter');
  let $options = $filter.children('option:not([disabled])');
  let locations = $options.map((i, el) => [{
    lat: parseFloat(el.dataset.lat),
    lng: parseFloat(el.dataset.lng),
    value: el.value,
    text: el.textContent
  }]).get();
  $options.remove();

  $("#code_postal").on('keyup', function() {
    var $zip_in = $(this);
    if ($zip_in.val().length == 5) {
      $.ajax({
        url: '//api-adresse.data.gouv.fr/search/',
        data: {
          q: $zip_in.val(),
          type: 'municipality',
          limit: 30
        },
        cache: false,
        dataType: "json",
        type: "GET",
        success: function(data) {
          let suggestions = data.features.map(f => `<option value="${f.properties.name}" data-lat="${f.geometry.coordinates[1]}" data-lng="${f.geometry.coordinates[0]}" />`);
          $("#output").html(suggestions);
        }
      })
    }
  });

  $('#city').on('change', e => {
    // get distances
    let $option = $(`#output option[value="${e.target.value}"]`);
    let cityLocation = {
      lat: $option.data('lat'),
      lng: $option.data('lng')
    };

    let filteredLocations = [...locations];
    filteredLocations.forEach(loc => loc.distance = getDistance(loc, cityLocation) || 99999);
    filteredLocations = filteredLocations.sort((a, b) => a.distance - b.distance);
    let closestResults = filteredLocations.slice(0, 10);

    let resultHtml = closestResults.map(r => `<option value="${r.value}" data-lat="${r.lat}" data-lng="${r.lng}">${r.text}</option>`);
    $filter.html(resultHtml);
  });
});

let toRad = value => (value * Math.PI) / 180;

function getDistance(loc1, loc2) {
  var R = 6371; // km
  var dLat = toRad(loc2.lat - loc1.lat);
  var dLon = toRad(loc2.lng - loc1.lng);
  var lat1 = toRad(loc1.lat);
  var lat2 = toRad(loc2.lat);
  
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2); 
  
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c; // Distance in km
  return d;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number"  placeholder="Code Postal" autocomplete="off" pattern="[0-9]{5}" maxlength="5" name="code_postal" id="code_postal"  />
<input name="city" list="output" maxlength="100" type="text"  placeholder="Ville" autocomplete="off" id="city" list="output"  />
                                    
<datalist id="output">                                  
</datalist>
 
<select id="filter" name="filter" >
   <option value="0" selected="" disabled="">Séléctionnez ville</option>
   <option value="city__0" data-lat="46.18330317" data-lng="5.20548105 ">01960 - Ville n°1</option>
   <option value="city__2" data-lat="49.5785983" data-lng="3.65402699 ">02000 - Ville n°3</option>
   <option value="city__4" data-lat="49.84820447" data-lng="3.2701833 ">02100 - Ville n°5</option>
   <option value="city__6" data-lat="49.3622495" data-lng="3.3264193 ">02200 - Ville n°7</option>
   <option value="city__8" data-lat="46.13107447" data-lng="3.42756482 ">03200 - Ville n°9</option>
   <option value="city__10" data-lat="43.82125316" data-lng="5.7939841 ">04100 - Ville n°11</option>
   <option value="city__12" data-lat="44.54007793" data-lng="6.05599799 ">05000 - Ville n°13</option>
   <option value="city__14" data-lat="43.57434542" data-lng="7.01281231 ">06110 - Ville n°15</option>
   <option value="city__16" data-lat="43.63321441" data-lng="6.95423106 ">06130 - Ville n°17</option>
   <option value="city__18" data-lat="43.70603065" data-lng="7.29115078 ">06300 - Ville n°19</option>
   <option value="city__20" data-lat="43.77256111" data-lng="7.49744541 ">06500 - Ville n°21</option>
   <option value="city__22" data-lat="44.6177312" data-lng="4.4051379 ">07208 - Ville n°23</option>
   <option value="city__24" data-lat="49.74098534" data-lng="4.70307201 ">08000 - Ville n°25</option>
   <option value="city__26" data-lat="43.10705567" data-lng="1.629625 ">09100 - Ville n°27</option>
   <option value="city__28" data-lat="48.3293326" data-lng="4.0241359 ">10600 - Ville n°29</option>
   <option value="city__30" data-lat="43.20800132" data-lng="2.38493605 ">11020 - Ville n°31</option>
   <option value="city__32" data-lat="43.15951361" data-lng="2.98341214 ">11100 - Ville n°33</option>
   <option value="city__34" data-lat="44.0862123" data-lng="3.04874757 ">12100 - Ville n°35</option>
   <option value="city__36" data-lat="44.36946354" data-lng="2.58370426 ">12850 - Ville n°37</option>
   <option value="city__38" data-lat="43.2909353" data-lng="5.49023363 ">13011 - Ville n°39</option>
   <option value="city__40" data-lat="43.36007178" data-lng="5.33964131 ">13016 - Ville n°41</option>
   <option value="city__42" data-lat="43.665307" data-lng="4.64511987 ">13200 - Ville n°43</option>
   <option value="city__44" data-lat="43.50867064" data-lng="5.40300582 ">13290 - Ville n°45</option>
   <option value="city__46" data-lat="43.6198977" data-lng="5.0964584 ">13300 - Ville n°47</option>
   <option value="city__48" data-lat="43.42279845" data-lng="5.23683217 ">13730 - Ville n°49</option>
   <option value="city__50" data-lat="49.14314595" data-lng="0.28591055 ">14100 - Ville n°51</option>
   <option value="city__52" data-lat="49.22860392" data-lng="-0.36979865 ">14112 - Ville n°53</option>
   <option value="city__54" data-lat="49.2839357" data-lng="-0.68819343 ">14400 - Ville n°55</option>
   <option value="city__56" data-lat="44.91733326" data-lng="2.46213071 ">15000 - Ville n°57</option>
   <option value="city__58" data-lat="45.6799527" data-lng="-0.31023771 ">16100 - Ville n°59</option>
   <option value="city__60" data-lat="45.6878431" data-lng="0.1823239 ">16430 - Ville n°61</option>
   <option value="city__62" data-lat="45.72222373" data-lng="-0.63992679 ">17103 - Ville n°63</option>
   <option value="city__64" data-lat="46.12860443" data-lng="-1.10194505 ">17440 - Ville n°65</option>
   <option value="city__66" data-lat="45.63082444" data-lng="-0.98526189 ">17600 - Ville n°67</option>
   <option value="city__68" data-lat="47.0575964" data-lng="2.3579438 ">18000 - Ville n°69</option>
   <option value="city__70" data-lat="45.1528738" data-lng="1.5075823 ">19100 - Ville n°71</option>
   <option value="city__72" data-lat="41.94931584" data-lng="8.76689507 ">20186 - Ville n°73</option>
   <option value="city__74" data-lat="42.59312139" data-lng="9.43831996 ">20620 - Ville n°75</option>
   <option value="city__76" data-lat="47.29899532" data-lng="5.02310837 ">21000 - Ville n°77</option>
   <option value="city__78" data-lat="48.7640793" data-lng="-3.4764132 ">22300 - Ville n°79</option>
   <option value="city__80" data-lat="48.4896434" data-lng="-2.76449102 ">22950 - Ville n°81</option>
   <option value="city__82" data-lat="44.82807071" data-lng="0.47866853 ">24100 - Ville n°83</option>
   <option value="city__84" data-lat="45.135479" data-lng="0.6985333 ">24660 - Ville n°85</option>
   <option value="city__86" data-lat="47.242742" data-lng="5.992699 ">25000 - Ville n°87</option>
   <option value="city__88" data-lat="46.9022047" data-lng="6.33758578 ">25300 - Ville n°89</option>
   <option value="city__90" data-lat="44.94032804" data-lng="4.91413812 ">26000 - Ville n°91</option>
   <option value="city__92" data-lat="44.57074212" data-lng="4.73728621 ">26200 - Ville n°93</option>
   <option value="city__94" data-lat="49.24474661" data-lng="1.40783479 ">27700 - Ville n°95</option>
   <option value="city__96" data-lat="49.10946409" data-lng="1.45304246 ">27950 - Ville n°97</option>
   <option value="city__98" data-lat="48.7188887" data-lng="1.3745788 ">28500 - Ville n°99</option>
   <option value="city__100" data-lat="48.41672422" data-lng="1.45168601 ">28600 - Ville n°101</option>
   <option value="city__102" data-lat="47.9817658" data-lng="-4.03329141 ">29000 - Ville n°103</option>
   <option value="city__104" data-lat="48.41011109" data-lng="-4.4688167 ">29200 - Ville n°105</option>
   <option value="city__106" data-lat="44.1063806" data-lng="4.08875902 ">30100 - Ville n°107</option>
   <option value="city__108" data-lat="43.81985448" data-lng="4.3473611 ">30900 - Ville n°109</option>
   <option value="city__110" data-lat="43.4807415" data-lng="1.3355123 ">31600 - Ville n°111</option>
   <option value="city__112" data-lat="43.5519221" data-lng="1.5099327 ">31683 - Ville n°113</option>
   <option value="city__114" data-lat="43.11445178" data-lng="0.76226282 ">31800 - Ville n°115</option>
   <option value="city__116" data-lat="43.6635889" data-lng="0.6132001 ">32000 - Ville n°117</option>
   <option value="city__118" data-lat="44.7657542" data-lng="-0.5615994 ">33140 - Ville n°119</option>
   <option value="city__120" data-lat="44.61005673" data-lng="-1.12904236 ">33260 - Ville n°121</option>
   <option value="city__122" data-lat="44.86253083" data-lng="-0.58511853 ">33492 - Ville n°123</option>
   <option value="city__124" data-lat="43.63904299" data-lng="3.92840723 ">34170 - Ville n°125</option>
   <option value="city__126" data-lat="43.3441707" data-lng="3.2550207 ">34500 - Ville n°127</option>
   <option value="city__128" data-lat="48.6222952" data-lng="-1.9880426 ">35400 - Ville n°129</option>
   <option value="city__130" data-lat="48.11403627" data-lng="-1.59864903 ">35513 - Ville n°131</option>
   <option value="city__132" data-lat="46.797961" data-lng="1.729451 ">36000 - Ville n°133</option>
   <option value="city__134" data-lat="47.41763565" data-lng="0.69090658 ">37100 - Ville n°135</option>
   <option value="city__136" data-lat="45.15254382" data-lng="5.70759862 ">38130 - Ville n°137</option>
   <option value="city__138" data-lat="45.5019667" data-lng="4.85231922 ">38200 - Ville n°139</option>
   <option value="city__140" data-lat="45.59099212" data-lng="5.24343268 ">38300 - Ville n°141</option>
   <option value="city__142" data-lat="46.6750189" data-lng="5.53632955 ">39570 - Ville n°143</option>
   <option value="city__144" data-lat="43.8704103" data-lng="-0.4827539 ">40280 - Ville n°145</option>
   <option value="city__146" data-lat="43.74130935" data-lng="-1.01557946 ">40990 - Ville n°147</option>
   <option value="city__148" data-lat="47.6149368" data-lng="1.3319663 ">41000 - Ville n°149</option>
   <option value="city__150" data-lat="45.4584931" data-lng="4.3882291 ">42000 - Ville n°151</option>
   <option value="city__152" data-lat="46.01994634" data-lng="4.04603642 ">42300 - Ville n°153</option>
   <option value="city__154" data-lat="45.05246801" data-lng="3.95765137 ">43700 - Ville n°155</option>
   <option value="city__156" data-lat="47.25804683" data-lng="-2.26914938 ">44600 - Ville n°157</option>
   <option value="city__158" data-lat="47.2516784" data-lng="-1.6236077 ">44800 - Ville n°159</option>
   <option value="city__160" data-lat="47.917353" data-lng="1.90153659 ">45000 - Ville n°161</option>
   <option value="city__162" data-lat="47.9794598" data-lng="2.73342262 ">45200 - Ville n°163</option>
   <option value="city__164" data-lat="44.4313927" data-lng="1.4439598 ">46000 - Ville n°165</option>
   <option value="city__166" data-lat="44.219091" data-lng="0.585253 ">47450 - Ville n°167</option>
   <option value="city__168" data-lat="47.47030924" data-lng="-0.62234859 ">49070 - Ville n°169</option>
   <option value="city__170" data-lat="47.02779562" data-lng="-0.91552835 ">49300 - Ville n°171</option>
   <option value="city__172" data-lat="49.11530649" data-lng="-1.04367475 ">50000 - Ville n°173</option>
   <option value="city__174" data-lat="49.6361961" data-lng="-1.5890371 ">50110 - Ville n°175</option>
   <option value="city__176" data-lat="48.6907691" data-lng="-1.3550522 ">50300 - Ville n°177</option>
   <option value="city__178" data-lat="48.98092114" data-lng="4.35516715 ">51000 - Ville n°179</option>
   <option value="city__180" data-lat="49.23640018" data-lng="4.0844167 ">51100 - Ville n°181</option>
   <option value="city__182" data-lat="49.06326614" data-lng="3.9600424 ">51530 - Ville n°183</option>
   <option value="city__184" data-lat="48.10262717" data-lng="5.14496998 ">52000 - Ville n°185</option>
   <option value="city__186" data-lat="48.62662063" data-lng="4.96908828 ">52100 - Ville n°187</option>
   <option value="city__188" data-lat="48.05471008" data-lng="-0.79911717 ">53940 - Ville n°189</option>
   <option value="city__190" data-lat="49.51633642" data-lng="5.74064483 ">54400 - Ville n°191</option>
   <option value="city__192" data-lat="48.69122259" data-lng="6.13157918 ">54520 - Ville n°193</option>
   <option value="city__194" data-lat="49.1826143" data-lng="5.36892524 ">55430 - Ville n°195</option>
   <option value="city__196" data-lat="47.66326113" data-lng="-2.79200702 ">56000 - Ville n°197</option>
   <option value="city__198" data-lat="47.78096745" data-lng="-3.33983197 ">56600 - Ville n°199</option>
   <option value="city__200" data-lat="49.33884282" data-lng="6.15869515 ">57100 - Ville n°201</option>
   <option value="city__202" data-lat="49.11028757" data-lng="7.09836458 ">57200 - Ville n°203</option>
   <option value="city__204" data-lat="49.0611" data-lng="6.1184 ">57685 - Ville n°205</option>
   <option value="city__206" data-lat="47.0241309" data-lng="3.15030277 ">58640 - Ville n°207</option>
   <option value="city__208" data-lat="50.58490136" data-lng="3.08735271 ">59155 - Ville n°209</option>
   <option value="city__210" data-lat="50.64470858" data-lng="3.00785501 ">59160 - Ville n°211</option>
   <option value="city__212" data-lat="50.34353705" data-lng="3.11954401 ">59187 - Ville n°213</option>
   <option value="city__214" data-lat="50.74340032" data-lng="3.13427494 ">59223 - Ville n°215</option>
   <option value="city__216" data-lat="50.37367671" data-lng="3.51450375 ">59410 - Ville n°217</option>
   <option value="city__218" data-lat="50.13022845" data-lng="3.42446939 ">59540 - Ville n°219</option>
   <option value="city__220" data-lat="50.28043666" data-lng="3.96565995 ">59600 - Ville n°221</option>
   <option value="city__222" data-lat="51.02128366" data-lng="2.35892918 ">59640 - Ville n°223</option>
   <option value="city__224" data-lat="50.63873743" data-lng="3.12281966 ">59650 - Ville n°225</option>
   <option value="city__226" data-lat="49.4148362" data-lng="2.11494684 ">60000 - Ville n°227</option>
   <option value="city__228" data-lat="49.23142436" data-lng="2.46812858 ">60740 - Ville n°229</option>
   <option value="city__230" data-lat="49.4064729" data-lng="2.7770037 ">60880 - Ville n°231</option>
   <option value="city__232" data-lat="50.29742086" data-lng="2.7504636 ">62000 - Ville n°233</option>
   <option value="city__234" data-lat="50.73599942" data-lng="2.26554141 ">62219 - Ville n°235</option>
   <option value="city__236" data-lat="50.68597541" data-lng="1.6266337 ">62360 - Ville n°237</option>
   <option value="city__238" data-lat="50.5098" data-lng="2.68873 ">62700 - Ville n°239</option>
   <option value="city__240" data-lat="50.42694979" data-lng="2.78757424 ">62800 - Ville n°241</option>
   <option value="city__242" data-lat="45.77893791" data-lng="3.12199702 ">63016 - Ville n°243</option>
   <option value="city__244" data-lat="43.46734477" data-lng="-1.49289814 ">64100 - Ville n°245</option>
   <option value="city__246" data-lat="43.31658324" data-lng="-0.42393473 ">64140 - Ville n°247</option>
   <option value="city__248" data-lat="43.21832675" data-lng="0.08829727 ">65000 - Ville n°249</option>
   <option value="city__250" data-lat="42.66399599" data-lng="2.9045329 ">66000 - Ville n°251</option>
   <option value="city__252" data-lat="48.79559762" data-lng="7.80534201 ">67500 - Ville n°253</option>
   <option value="city__254" data-lat="48.50682227" data-lng="7.49637987 ">67560 - Ville n°255</option>
   <option value="city__256" data-lat="48.61833744" data-lng="7.72797688 ">67800 - Ville n°257</option>
   <option value="city__258" data-lat="48.11213415" data-lng="7.3784244 ">68000 - Ville n°259</option>
   <option value="city__260" data-lat="47.74949171" data-lng="7.30569086 ">68200 - Ville n°261</option>
   <option value="city__262" data-lat="45.71592372" data-lng="4.85047743 ">69190 - Ville n°263</option>
   <option value="city__264" data-lat="45.80758024" data-lng="4.87064519 ">69300 - Ville n°265</option>
   <option value="city__266" data-lat="45.74689085" data-lng="4.77274238 ">69340 - Ville n°267</option>
   <option value="city__268" data-lat="47.6371861" data-lng="6.14990026 ">70000 - Ville n°269</option>
   <option value="city__270" data-lat="46.28610955" data-lng="4.81256686 ">71000 - Ville n°271</option>
   <option value="city__272" data-lat="46.76922439" data-lng="4.86031294 ">71100 - Ville n°273</option>
   <option value="city__274" data-lat="46.6810369" data-lng="4.3618969 ">71300 - Ville n°275</option>
   <option value="city__276" data-lat="47.9679297" data-lng="0.1747753 ">72100 - Ville n°277</option>
   <option value="city__278" data-lat="45.66260961" data-lng="6.40910843 ">73200 - Ville n°279</option>
   <option value="city__280" data-lat="45.6076587" data-lng="5.887615 ">73290 - Ville n°281</option>
   <option value="city__282" data-lat="46.20073039" data-lng="6.26635615 ">74100 - Ville n°283</option>
   <option value="city__284" data-lat="46.3504523" data-lng="6.44352864 ">74200 - Ville n°285</option>
   <option value="city__286" data-lat="45.87796225" data-lng="6.08925029 ">74600 - Ville n°287</option>
   <option value="city__288" data-lat="45.9127041" data-lng="6.6518115 ">74700 - Ville n°289</option>
   <option value="city__290" data-lat="48.87481545" data-lng="2.37019994 ">75010 - Ville n°291</option>
   <option value="city__292" data-lat="48.83190002" data-lng="2.36304073 ">75013 - Ville n°293</option>
   <option value="city__294" data-lat="49.4471129" data-lng="1.0659275 ">76000 - Ville n°295</option>
   <option value="city__296" data-lat="49.49317925" data-lng="0.14565581 ">76600 - Ville n°297</option>
   <option value="city__298" data-lat="48.94679013" data-lng="2.87926555 ">77100 - Ville n°299</option>
   <option value="city__300" data-lat="48.803014" data-lng="3.0894925 ">77120 - Ville n°301</option>
   <option value="city__302" data-lat="48.55157574" data-lng="3.29823412 ">77160 - Ville n°303</option>
   <option value="city__304" data-lat="48.42250463" data-lng="2.77072191 ">77210 - Ville n°305</option>
   <option value="city__306" data-lat="48.56687607" data-lng="2.63382733 ">77240 - Ville n°307</option>
   <option value="city__308" data-lat="48.87940797" data-lng="2.6222211 ">77500 - Ville n°309</option>
   <option value="city__310" data-lat="48.8305114" data-lng="2.7102179 ">77600 - Ville n°311</option>
   <option value="city__312" data-lat="48.79784043" data-lng="2.0484661 ">78180 - Ville n°313</option>
   <option value="city__314" data-lat="48.9907009" data-lng="1.6781671 ">78200 - Ville n°315</option>
   <option value="city__316" data-lat="48.90809935" data-lng="2.04298821 ">78240 - Ville n°317</option>
   <option value="city__318" data-lat="48.75132263" data-lng="1.93210641 ">78310 - Ville n°319</option>
   <option value="city__320" data-lat="46.33443521" data-lng="-0.41520138 ">79000 - Ville n°321</option>
   <option value="city__322" data-lat="50.0992205" data-lng="1.8637767 ">80100 - Ville n°323</option>
   <option value="city__324" data-lat="49.87265791" data-lng="2.36904825 ">80330 - Ville n°325</option>
   <option value="city__326" data-lat="43.59058934" data-lng="2.26544689 ">81100 - Ville n°327</option>
   <option value="city__328" data-lat="43.960314" data-lng="2.166627 ">81380 - Ville n°329</option>
   <option value="city__330" data-lat="44.0375448" data-lng="1.3816704 ">82005 - Ville n°331</option>
   <option value="city__332" data-lat="43.1367124" data-lng="6.0251318 ">83130 - Ville n°333</option>
   <option value="city__334" data-lat="43.39991871" data-lng="6.04856958 ">83170 - Ville n°335</option>
   <option value="city__336" data-lat="43.4513294" data-lng="6.69159988 ">83480 - Ville n°337</option>
   <option value="city__338" data-lat="44.1226744" data-lng="4.8388427 ">84104 - Ville n°339</option>
   <option value="city__340" data-lat="43.97689297" data-lng="4.87374826 ">84130 - Ville n°341</option>
   <option value="city__342" data-lat="44.03470985" data-lng="5.0516966 ">84200 - Ville n°343</option>
   <option value="city__344" data-lat="46.71398428" data-lng="-1.42797589 ">85000 - Ville n°345</option>
   <option value="city__346" data-lat="46.85487452" data-lng="-1.90289169 ">85300 - Ville n°347</option>
   <option value="city__348" data-lat="46.6092017" data-lng="0.3205913 ">86000 - Ville n°349</option>
   <option value="city__350" data-lat="45.86824141" data-lng="1.26912145 ">87280 - Ville n°351</option>
   <option value="city__352" data-lat="48.21900066" data-lng="6.43677324 ">88150 - Ville n°353</option>
   <option value="city__354" data-lat="48.35413905" data-lng="5.68730042 ">88300 - Ville n°355</option>
   <option value="city__356" data-lat="47.81857776" data-lng="3.58433515 ">89000 - Ville n°357</option>
   <option value="city__358" data-lat="48.2051301" data-lng="3.2866158 ">89100 - Ville n°359</option>
   <option value="city__360" data-lat="47.6486581" data-lng="6.8860347 ">90160 - Ville n°361</option>
   <option value="city__362" data-lat="48.61044732" data-lng="2.45929988 ">91100 - Ville n°363</option>
   <option value="city__364" data-lat="48.6887528" data-lng="2.2057335 ">91140 - Ville n°365</option>
   <option value="city__366" data-lat="48.45641581" data-lng="2.17663348 ">91150 - Ville n°367</option>
   <option value="city__368" data-lat="48.64625137" data-lng="2.27103429 ">91310 - Ville n°369</option>
   <option value="city__370" data-lat="48.90581593" data-lng="2.23814873 ">92250 - Ville n°371</option>
   <option value="city__372" data-lat="48.90867152" data-lng="2.50099627 ">93320 - Ville n°373</option>
   <option value="city__374" data-lat="48.9586434" data-lng="2.5589641 ">93420 - Ville n°375</option>
   <option value="city__376" data-lat="48.738579" data-lng="2.447105 ">94190 - Ville n°377</option>
   <option value="city__378" data-lat="48.80732156" data-lng="2.36349624 ">94270 - Ville n°379</option>
   <option value="city__380" data-lat="48.84502535" data-lng="2.43617371 ">94300 - Ville n°381</option>
   <option value="city__382" data-lat="48.78126108" data-lng="2.57084432 ">94510 - Ville n°383</option>
   <option value="city__384" data-lat="48.95658653" data-lng="2.25665803 ">95100 - Ville n°385</option>
   <option value="city__386" data-lat="49.03391235" data-lng="2.11928039 ">95310 - Ville n°387</option>
   <option value="city__388" data-lat="48.98934047" data-lng="2.35924986 ">95410 - Ville n°389</option>
   <option value="city__390" data-lat="48.99710952" data-lng="2.41946463 ">95500 - Ville n°391</option>
</select>

(Calculate distance between two latitude-longitude points? (Haversine formula))

jQuery($ => {
  let $filter = $('#filter');
  let $options = $filter.children('option:not([disabled])');
  let locations = $options.map((i, el) => [{
    lat: parseFloat(el.dataset.lat),
    lng: parseFloat(el.dataset.lng),
    value: el.value,
    text: el.textContent
  }]).get();
  $options.remove();

  $("#code_postal").on('keyup', function() {
    var $zip_in = $(this);
    if ($zip_in.val().length == 5) {
      $.ajax({
        url: '//api-adresse.data.gouv.fr/search/',
        data: {
          q: $zip_in.val(),
          type: 'municipality',
          limit: 30
        },
        cache: false,
        dataType: "json",
        type: "GET",
        success: function(data) {
          let suggestions = data.features.map(f => `<option value="${f.properties.name}" data-lat="${f.geometry.coordinates[1]}" data-lng="${f.geometry.coordinates[0]}" />`);
          $("#output").html(suggestions);
        }
      })
    }
  });

  $('#city').on('change', e => {
    // get distances
    let $option = $(`#output option[value="${e.target.value}"]`);
    let cityLocation = {
      lat: $option.data('lat'),
      lng: $option.data('lng')
    };

    let filteredLocations = [...locations];
    filteredLocations.forEach(loc => loc.distance = getDistance(loc, cityLocation) || 99999);
    filteredLocations = filteredLocations.sort((a, b) => a.distance - b.distance);
    let closestResults = filteredLocations.slice(0, 10);

    let resultHtml = closestResults.map(r => `<option value="${r.value}" data-lat="${r.lat}" data-lng="${r.lng}">${r.text}</option>`);
    $filter.html(resultHtml);
  });
});

let toRad = value => (value * Math.PI) / 180;

function getDistance(loc1, loc2) {
  var R = 6371; // km
  var dLat = toRad(loc2.lat - loc1.lat);
  var dLon = toRad(loc2.lng - loc1.lng);
  var lat1 = toRad(loc1.lat);
  var lat2 = toRad(loc2.lat);
  
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2); 
  
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c; // Distance in km
  return d;
}
Creatz
  • 49
  • 5