function updateZoomText(){ if (map.getZoom() >=10){ document.getElementById("zoomalert").innerHTML = ""; return; } else{ // document.getElementById("cheapestinfo").innerHTML = ""; } zoomstr = "Click the Zoom in button " + (10-map.getZoom()).toString() + " more time"; if (10-map.getZoom() > 1){ zoomstr +="s"; } zoomstr+=" to see fuel prices"; document.getElementById("zoomalert").innerHTML = zoomstr ; } function getLastSelectedFuel(){ var fuel = localStorage.getItem('fuel'); if (fuel == null){ fuel = 1; localStorage.setItem('fuel',fuel); } return fuel; } function fuelSelectChange(name){ var fuel = document.getElementById(name).value; localStorage.setItem('fuel',fuel); addMarkers(json_response); updateListHtml(json_response); } function getFuelSelectHTML(){ var fuel = getLastSelectedFuel(); var fuelSelectHTML =""; fuelSelectHTML += " Only show island stations"; if (islandOnly) { document.getElementById("islandOnlyCheckbox").checked = true; } document.getElementById("islandOnlyOption").style.display = "block"; } else{ document.getElementById("islandOnlyOption").style.display = "none"; } } function highlightPrice(price,count){ markers.forEach((marker, index) => { }); } function getPricesToColoursArr(data){ var returnArr = []; smallest = data[0]; largest = data[data.length - 1]; var rg_delta = Math.abs(parseInt(190 / (largest - smallest))); var current_red ; var current_green ; for (var i = 0; i < data.length; i++) { this_price = data[i]; dist_from_base = this_price - smallest; current_green = 190 - (rg_delta * dist_from_base); current_red = rg_delta * dist_from_base; returnArr[i] = 'rgba('+current_red+', '+current_green+',' + 120 + ', 1)'; } returnArr[0] = 'rgba(0, 255, 0, 1)'; returnArr[data.length - 1] = 'rgba(255, 0, 0, 1)'; return returnArr; } function getPricesToColoursDict(data){ var returnDict = {}; smallest = data[0]; largest = data[data.length - 1]; var rg_delta = Math.abs(parseInt(190 / (largest - smallest))); var current_red ; var current_green ; for (var i = 0; i < data.length; i++) { this_price = data[i]; dist_from_base = this_price - smallest; current_green = 190 - (rg_delta * dist_from_base); current_red = rg_delta * dist_from_base; returnDict[this_price] = 'rgba('+current_red+', '+current_green+',' + 120 + ', 1)'; } returnDict[largest] = 'rgba(255, 0, 0, 1)'; returnDict[smallest] = 'rgba(0, 255, 0, 1)'; return returnDict; } function get_prices_dict_from_data(data) { var x_vals = []; var y_vals = []; var prices_dict = {}; hasIsland = false; for (var key in data) { if ((key !== "mins")&&(key !== "islandmins")) { if (data[key]['island'] == 1){ hasIsland = true; break; } } } var selectedFuel = getLastSelectedFuel(); for (var key in data) { if ((key !== "mins")&&(key !== "islandmins")){ if (!data[key]['island']) { if ((islandOnly)&&(hasIsland)){ continue; } } if (data[key]['fuel_prices'][selectedFuel] != 999999){ if (data[key]['fuel_prices'][selectedFuel] in prices_dict) { prices_dict[data[key]['fuel_prices'][selectedFuel]] += 1; } else{ prices_dict[data[key]['fuel_prices'][selectedFuel]] = 1; } } } } var sortedKeys = Object.keys(prices_dict).map(Number).sort((a, b) => a - b); var keyCount = 0; sortedKeys.forEach(key => { keyCount += 1; x_vals.push(key); if (prices_dict[key] >3) { prices_dict[key] = 4; } y_vals.push(prices_dict[key]); }); return [x_vals, y_vals, keyCount, sortedKeys]; } function addNerdMode(data){ if (typeof myChart !== 'undefined') { myChart.destroy(); } var fuelNames = ['','Unleaded (E10)','Old unleaded (E5)','Diesel (B7)','Super Diesel (SDV)']; var [x_vals, y_vals, keyCount,sortedKeys] = get_prices_dict_from_data(data); if (keyCount>2) { var chart_data = x_vals.map((k, i) => ({x: k, y: y_vals[i]})); var backgroundColrs = getPricesToColoursArr(sortedKeys); var borderColor = Array(x_vals.length).fill('rgba(10,10,10, 1)'); const ctx = document.getElementById('myChart').getContext('2d'); myChart = new Chart(ctx, { type: 'bar', data: { datasets: [{ label: 'Num of Stations at this price:', data: chart_data, backgroundColor: backgroundColrs, borderColor: borderColor, borderWidth: 1, barPercentage: 1, categoryPercentage: .9, borderRadius: 1, }] }, options: { maintainAspectRatio: false, scales: { x: { type: 'category', labels: x_vals, grid: { display: false // Hide horizontal grid lines if needed }, offset: true, title: { display: true, text: 'Prices', font: { size: 14 } } }, y: { // beginAtZero: true title: { display: true, text: 'Stations', font: { size: 14 } }, ticks: { callback: function(value, index, values) { if (value === 4) { return '3+'; } return value; } }, grid: { display: false // Hide horizontal grid lines if needed } } }, plugins: { legend: { display: false, }, tooltip: { callbacks: { title: (items) => { if (!items.length) { return ''; } const item = items[0]; return `Price: ${item.label}`; }, label: (item) => { const count = item.raw.y; if (count>3) { return `Num of stations at this price: 3+`; } return `Num of stations at this price: ${count}`; } } } }, onClick: (event, elements) => { if (elements.length > 0) { const element = elements[0]; const datasetIndex = element.datasetIndex; const index = element.index; const dataset = myChart.data.datasets[datasetIndex]; const data = dataset.data[index]; const price = data.x; const count = data.y; highlightPrice(price, count); } } } }); } } function getPrices(){ if (map.getZoom() >= 10){ var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); var minLat = southWest.lat; var minLong = southWest.lng; var maxLat = northEast.lat; var maxLong = northEast.lng; var url = '/stationsfromgeo?minLat=' + minLat + '&maxLat=' + maxLat + '&minLong=' + minLong + '&maxLong=' + maxLong + '&fuelType=' + getLastSelectedFuel(); document.getElementById('spinner').style.display = 'block'; fetch(url) .then(response => response.json()) .then(data => { document.getElementById('spinner').style.display = 'none'; json_response = data; check_to_show_island_only(json_response); addMarkers(json_response); listHtml = updateListHtml(json_response); addNerdMode(json_response); }) .catch(error => { console.error('Error:', error); }); } else{ updateZoomText(); } } function fetchAndColorSvg(svgContent, color, callback) { // Modify the SVG content to apply the desired color const coloredSvg = svgContent.replace(/gas-station-location`; svgContent = ''; // Color the SVG and create the custom icon fetchAndColorSvg(svgContent, customcolor, function(svgDataUrl) { var customIcon = L.icon({ iconSize: [40, 30], iconAnchor: [10, 10], iconUrl: svgDataUrl }); var fuelNames = ['', 'Unleaded (E10)', 'Old unleaded (E5)', 'Diesel (B7)', 'Super Diesel (SDV)']; if ((!(islandOnly)) || ((islandOnly) && (data[key]['island'] == 1) && (hasIsland)) || (islandOnly && !hasIsland)) { var title = chosenMins[selectedFuel] == data[key]['fuel_prices'][selectedFuel] ? data[key]['name'] + " - Cheapest for " + fuelNames[selectedFuel] + " in this area" : data[key]['name'] + ": " + (data[key]['fuel_prices'][selectedFuel] - chosenMins[selectedFuel]).toFixed(1) + "p per liter more expensive than cheapest in this area"; var zIndexOffset = chosenMins[selectedFuel] == data[key]['fuel_prices'][selectedFuel] ? 1000 : 0; // Green markers on top var stationMarker = L.marker([data[key]['latitude'], data[key]['longitude']], { icon: customIcon, title: title, zIndexOffset: zIndexOffset }).addTo(markersLayer); markers.push(stationMarker); (function(key) { stationMarker.on('click', function(e) { populateStationModal(data[key]); }); })(key); } }); } } } } function initMap(inlat,inlong,zoom = 13) { map = L.map('map').setView([inlat, inlong], zoom); markersLayer = new L.LayerGroup().addTo(map); L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 30, attribution: '© OpenStreetMap' }).addTo(map); var titleControl = L.control({ position: 'bottomright' }); var title="You can drag this map, and click +/- to zoom
Hover over a marker to see more info
Click a marker for more info
Click this box to hide it"; titleControl.onAdd = function(map) { var div = L.DomUtil.create('div', 'map-title'); div.innerHTML = '
' + title + '
'; div.style.backgroundColor = 'white'; div.style.padding = '5px'; div.style.borderRadius = '5px'; div.style.boxShadow = '0 0 15px rgba(0,0,0,0.2)'; div.style.cursor = 'pointer'; // Add cursor pointer to indicate it's clickable div.onclick = function() { removeTitleControl(); // Call the function to remove the control when clicked }; return div; }; titleControl.addTo(map); var titleControlRef = titleControl; getPrices(); map.on('zoomend', function(e) { markersLayer.clearLayers(); updateZoomText(); getPrices(); }); map.on('moveend', function(e) { markersLayer.clearLayers(); center = map.getCenter(); getPrices(); check_to_show_island_only(json_response); }); function removeTitleControl() { if (titleControlRef) { map.removeControl(titleControlRef); titleControlRef = null; // Clear the reference } } }