diff options
author | JeremyJamesL <jeremyluscombe@gmail.com> | 2024-12-07 16:50:21 +0000 |
---|---|---|
committer | JeremyJamesL <jeremyluscombe@gmail.com> | 2024-12-07 16:50:21 +0000 |
commit | 8be068158fb27e3ab53d262c29ccf9c628fd939c (patch) | |
tree | 3bd5262cba7464df5f7f1a690db1f7d0d924959e | |
parent | 622e35c4b3f8889993d191e07a2858fc6b67922d (diff) |
📦 NEW: MVC
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | image.png | bin | 0 -> 110158 bytes | |||
-rw-r--r-- | index.html | 6 | ||||
-rw-r--r-- | src/main.js | 150 | ||||
-rw-r--r-- | src/refactor.js | 91 |
5 files changed, 185 insertions, 65 deletions
@@ -15,6 +15,7 @@ Current searches for pubs in the UK are a bit rubbish. This takes inspiration fr 7. Query Algolia with the bounds 8. Limit response fields, we only really need the geoloc 9. Remove all markers when looking the markers +10. Debounce the query ## To do: @@ -23,3 +24,5 @@ Current searches for pubs in the UK are a bit rubbish. This takes inspiration fr [] Change search client to just [] Don't return \_highlightResult? [] Run search on first load + + diff --git a/image.png b/image.png Binary files differnew file mode 100644 index 0000000..16f8a59 --- /dev/null +++ b/image.png @@ -51,6 +51,10 @@ <header class="py-2"> <div class="container"> <h1>London Pubs - Algolia Map Search</h1> + <div> + Shape can be <span class="rectangle">Rectangular</span> or a + <span class="polygon">Polygon</span> + </div> </div> </header> @@ -67,6 +71,6 @@ <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyCtS6CiOrG95FhroSUdDJJokItndcMkrgc", v: "weekly"});</script> - <script type="module" src="/src/main.js"></script> + <script type="module" src="/src/refactor.js"></script> </body> </html> diff --git a/src/main.js b/src/main.js index c8e7122..19716e6 100644 --- a/src/main.js +++ b/src/main.js @@ -1,41 +1,20 @@ import { algoliasearch } from "algoliasearch"; -import { info } from "autoprefixer"; -import instantsearch from "instantsearch.js"; -import { searchBox, hits, configure } from "instantsearch.js/es/widgets"; const MAPS_KEY = "AIzaSyCtS6CiOrG95FhroSUdDJJokItndcMkrgc"; const ALGOLIA_KEY = "9fb3db0222f7b5aef0e2b30791ee6201"; const INDEX_NAME = "pubfinder"; const client = algoliasearch("YSWWVAX5RB", ALGOLIA_KEY); +// Elements +const polygonSelect = document.querySelector(".polygon"); +const rectangleSelect = document.querySelector(".rectangle"); + let markers = []; +let map; const algolia_params = { hitsPerPage: 1000, }; -// const search = instantsearch({ -// indexName: INDEX_NAME, -// searchClient, -// // onStateChange({ uiState, setUiState }) { -// // setUiState(uiState); -// // }, -// // probably want to set initial search state depending on the rectangle coords -// }); - -// cons - -// search.addWidgets([ -// searchBox({ -// container: "#searchbox", -// }), -// hits({ -// container: "#hits", -// }), -// configure({}), -// ]); - -let map; - const initialPolygonCoords = [ { lat: 51.555519, lng: -0.215208 }, { lat: 51.526021, lng: -0.021665 }, @@ -52,13 +31,12 @@ const london_bounds = { }; function removeMarkers() { - console.log("hi"); for (let i = 0; i < markers.length; i++) { markers[i].setMap(null); } } -async function initMap() { +async function initMap(shape) { const position = { lat: 51.508616, lng: -0.125319 }; const { Map, Polygon, Rectangle, InfoWindow } = @@ -80,52 +58,96 @@ async function initMap() { }, }); - const rectangle = new Rectangle({ - bounds: london_bounds, - editable: true, - draggable: true, - }); - - rectangle.setMap(map); - - rectangle.addListener("bounds_changed", async function () { + function handleBoundsChange(activeShape) { + console.log("happening"); removeMarkers(); - const { south, west, north, east } = rectangle.getBounds()?.toJSON(); + const { south, west, north, east } = activeShape.getBounds()?.toJSON(); const algolia_bounds = [north, east, south, west]; - const res = await client.searchSingleIndex({ - indexName: INDEX_NAME, - searchParams: { - ...algolia_params, - insideBoundingBox: [algolia_bounds], - attributesToRetrieve: ["_geoloc", "name"], - }, - }); - - res.hits.forEach((hit) => { - console.log("hitting again"); - const marker = new AdvancedMarkerElement({ - map: map, - position: { - lat: hit._geoloc.lat, - lng: hit._geoloc.lng, + function debounce(func, delay) { + let timer; + return function (...args) { + const context = this; + clearTimeout(timer); + timer = setTimeout(() => { + func.apply(context, args); + }, delay); + }; + } + + async function getSearch() { + const res = await client.searchSingleIndex({ + indexName: INDEX_NAME, + searchParams: { + ...algolia_params, + insideBoundingBox: [algolia_bounds], + attributesToRetrieve: ["_geoloc", "name"], }, }); - const window = new InfoWindow({ - content: hit.name, - }); + res.hits.forEach((hit) => { + const marker = new AdvancedMarkerElement({ + map: map, + position: { + lat: hit._geoloc.lat, + lng: hit._geoloc.lng, + }, + }); - marker.addListener("click", function () { - window.open({ - anchor: marker, - map, + const window = new InfoWindow({ + content: hit.name, }); + + marker.addListener("click", function () { + window.open({ + anchor: marker, + map, + }); + }); + + markers.push(marker); }); + } - markers.push(marker); + const doAll = debounce(getSearch, 500); + doAll(); + } + + if (shape === "rectangular") { + console.log("doing"); + const rectangle = new Rectangle({ + bounds: london_bounds, + editable: true, + draggable: true, }); - }); + + rectangle.setMap(map); + rectangle.addListener("bounds_changed", handleBoundsChange(rectangle)); + } else if (shape === "polygonular") { + const polygon = new Polygon({ + paths: initialPolygonCoords, + strokeColor: "#FF0000", + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: "#FF0000", + fillOpacity: 0.35, + editable: true, + draggable: true, + }); + + polygon.setMap(map); + polygon.addListener("bounds_changed", handleBoundsChange(polygon)); + } } -initMap(); +[rectangleSelect, polygonSelect].forEach((el) => { + el.addEventListener("click", function (e) { + if (e.target.classList.contains("rectangle")) { + initMap("rectangular"); + } else { + initMap("polygonular"); + } + }); +}); + +initMap("rectangular"); diff --git a/src/refactor.js b/src/refactor.js new file mode 100644 index 0000000..90c5c35 --- /dev/null +++ b/src/refactor.js @@ -0,0 +1,91 @@ +import { algoliasearch } from "algoliasearch"; +const ALGOLIA_KEY = "9fb3db0222f7b5aef0e2b30791ee6201"; +const INDEX_NAME = "pubfinder"; +const client = algoliasearch("YSWWVAX5RB", ALGOLIA_KEY); + +const algolia_params = { + hitsPerPage: 1000, +}; + +const dataController = (function () { + const londonBounds = { + north: 51.532, + south: 51.478, + east: -0.072, + west: -0.16, + }; + + const maxMapSpace = { + north: 51.74, + south: 51.27, + west: -0.51, + east: 0.23, + }; + + const centralPosition = { lat: 51.508616, lng: -0.125319 }; + + return { + londonBounds, + centralPosition, + maxMapSpace, + getSearchResults: async function () { + const res = await client.searchSingleIndex({ + indexName: INDEX_NAME, + searchParams: { + ...algolia_params, + insideBoundingBox: [londonBounds], + attributesToRetrieve: ["_geoloc", "name"], + }, + }); + }, + }; +})(); + +const interfaceController = (function () { + let markers = []; + let map; + return { + generateMap: async function (bounds, position, maxSpace) { + const { Map, Polygon, Rectangle, InfoWindow } = + await google.maps.importLibrary("maps"); + const { AdvancedMarkerElement } = await google.maps.importLibrary( + "marker" + ); + map = new Map(document.getElementById("map"), { + zoom: 4, + center: position, + mapId: "pub_map", + restriction: { + latLngBounds: maxSpace, + strictBounds: true, + }, + }); + + const rectangle = new Rectangle({ + bounds: bounds, + editable: true, + draggable: true, + }); + + rectangle.setMap(map); + }, + }; +})(); + +const controller = (function (dataCTRL, uiCTRL) { + const initialSetup = function () { + const londonBounds = dataCTRL.londonBounds; + const centralPoint = dataCTRL.centralPosition; + const mapBounds = dataCTRL.maxMapSpace; + uiCTRL.generateMap(londonBounds, centralPoint, mapBounds); + dataCTRL.getSearchResults(); + }; + + return { + init: function () { + initialSetup(); + }, + }; +})(dataController, interfaceController); + +controller.init(); |