1const options = { 2 enableHighAccuracy: false, 3 timeout: 5000, 4 maximumAge: Infinity, 5}; 6 7function getCurrentPositionSuccess(pos) { 8 const crd = pos.coords; 9 let lat = crd.latitude; 10 let long = crd.longitude; 11 if(window['testMode']) { 12 } 13 //const url = `/bridge.php?lat=${crd.latitude}&lng=${crd.longitude}`; 14 const url = `https://api.sunrisesunset.io/json?lat=${lat}&lng=${long}&date_start=2025-01-01&date_end=2025-12-31`; 15 fetch(url, { 16 /*mode: 'no-cors',*/ 17 method: 'get', 18 }) 19 .then(response => { 20 return response.json(); 21 }) 22 .then(data => { 23 localStorage.setItem("cachedSunnyData", JSON.stringify(data)); 24 document.getElementById('clearcache').style.display = 'block'; 25 draw(data); 26 }) 27 .catch(error => { 28 console.log(error); 29 clearLoader(); 30 showError(error.message); 31 }); 32} 33 34function clearCache() { 35 localStorage.removeItem("cachedSunnyData"); 36 location.reload(); 37} 38 39function usTimeStringToSeconds(timeString) { 40 let timeParts = timeString.split(/:| /); 41 let hours = parseInt(timeParts[0]); 42 let minutes = parseInt(timeParts[1]); 43 let seconds = parseInt(timeParts[2]); 44 let period = timeParts[3]; 45 46 // Convert hours to 24-hour format if it's PM 47 if (period === "PM" && hours < 12) { 48 hours += 12; 49 } 50 if (period === "AM" && hours == 12) { 51 hours += 12; 52 } 53 54 // Calculate the total seconds since midnight 55 return (hours * 3600) + (minutes * 60) + seconds; 56} 57 58function percentageOfDay(timeString) { 59 return Math.min(1, Math.max(0, usTimeStringToSeconds(timeString) / 86400)); 60} 61 62function clearLoader() { 63 let moonloader = document.getElementById('moonloader'); 64 if(!moonloader) return; 65 moonloader.parentNode.removeChild(moonloader); 66 let moonloadertext = document.getElementById('moonloadertext'); 67 moonloadertext.parentNode.removeChild(moonloadertext); 68} 69 70function showError(message) { 71 let errorDiv = document.createElement('div'); 72 errorDiv.classList.add('errorMessage'); 73 errorDiv.classList.add('shadow'); 74 errorDiv.textContent = `There was a problem loading data for your location. Maybe try again later?\n\nMessage: ${message}`; 75 document.body.appendChild(errorDiv); 76} 77 78function draw(data) { 79 let c = document.getElementById("timecanvas"); 80 let ctx = c.getContext("2d"); 81 ctx.clearRect(0, 0, c.width, c.height); 82 for (let i = 0; i < Math.min(365, data.results.length); i++) { 83 let day = data.results[i]; 84 /* 85 date -> "2024-01-01" 86 dawn -> "7:39:49 AM" 87 day_length -> "8:33:16" 88 dusk -> "5:23:59 PM" 89 first_light -> "6:23:54 AM" 90 golden_hour -> "3:56:49 PM" 91 last_light -> "6:39:54 PM" 92 solar_noon -> "12:31:54 PM" 93 sunrise -> "8:15:16 AM" 94 sunset -> "4:48:32 PM" 95 timezone -> "Europe/Zurich" 96 utc_offset -> 60 97 */ 98 99 let firstLight = percentageOfDay(day.first_light ? day.first_light : '0:01:00 AM'); 100 let sunrise = percentageOfDay(day.sunrise ? day.sunrise : '0:02:00 AM'); 101 let sunset = percentageOfDay(day.sunset ? day.sunset : '11:58:00 PM'); 102 let lastLight = percentageOfDay(day.last_light ? day.last_light : '11:59:00 PM'); 103 104 // Create gradient 105 var grd = ctx.createLinearGradient(0, 0, 400, 0); 106 grd.addColorStop(0, "black"); 107 if (day.first_light == null && day.sunrise == null && day.sunset == null && day.last_light == null) { 108 // 109 } else { 110 grd.addColorStop(firstLight > 0.5 ? 0 : firstLight, "black"); 111 grd.addColorStop(sunrise, "white"); 112 grd.addColorStop(sunset, "white"); 113 grd.addColorStop(lastLight < 0.5 ? 1 : lastLight, "black"); 114 } 115 grd.addColorStop(1, "black"); 116 117 // Fill with gradient 118 ctx.fillStyle = grd; 119 ctx.fillRect(0, i - 1, 400, i); 120 } 121 122 function toHours(timeString) { 123 let components = timeString.split(":"); 124 let hours = parseInt(components[0]); 125 hours += parseInt(components[1])/60; 126 return hours; 127 } 128 129 let getup = document.getElementById('getup').value; 130 let sleep = document.getElementById('sleep').value; 131 132 let sleepHours = toHours(sleep); 133 sleepHours = sleepHours==0?24:sleepHours; 134 ctx.fillStyle = 'rgba(47,111,255,0.3)'; 135 ctx.fillRect(0, 0, toHours(getup) / 24 * 400, 365); 136 ctx.fillRect(sleepHours / 24 * 400, 0, 400, 365); 137 138 let dataURL = c.toDataURL("image/png"); 139 let download = document.getElementById('download'); 140 download.href = dataURL; 141 download.style.display = 'block'; 142 143 document.getElementById('timepicker').style.opacity = 1; 144 145 clearLoader(); 146} 147function redraw() { 148 let cachedSunData = localStorage.getItem("cachedSunnyData"); 149 if (cachedSunData) { 150 try { 151 draw(JSON.parse(cachedSunData)); 152 document.getElementById('clearcache').style.display = 'block'; 153 } catch(e) { 154 localStorage.removeItem("cachedSunnyData"); 155 navigator.geolocation.getCurrentPosition(getCurrentPositionSuccess, showError, options); 156 } 157 } else { 158 navigator.geolocation.getCurrentPosition(getCurrentPositionSuccess, showError, options); 159 } 160} 161redraw();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.