PageSourceSearch

https://ryanlukecross.github.io/weather/current-weather/javascript/functions.js

js ryanlukecross.github.io collected 2026-10-03 09:53:01 UTC 18,751 bytes, 520 lines download raw bytes

1/* *************************************
2 *  Weather Site JavaScript Functions
3 ************************************* */
4// Making sure the JS file is working //
5console.log('My JS is being Read.');
6
7// console.log('Header and Storage starting from functions.js');
8
9// Set global variable for custom header required by NWS API
10var idHeader = {
11   headers: {
12      "User-Agent": "Student Learning Project - [email protected]"
13   }
14};
15
16// Setup localStorage
17var storage = window.localStorage;
18
19
20// buildWC will just build the wind chill factor and change the innerHTML
21// console.log will help debug if needed
22function buildWC(speed, temp) {
23   console.log("Speed: " + speed + " Temp: " + temp);
24   // get the id of the element
25   const feelTemp = document.getElementById('feels');
26   // do fancy maths
27   let wc = 35.74 + 0.6215 * temp - 35.75 * Math.pow(speed, 0.16) + 0.4275 * temp * Math.pow(speed, 0.16);
28   // console.log(wc);
29   console.log("Wind Chill 1: " + wc);
30   wc = Math.floor(wc);
31   // determine the smallest temperature for the tinal result
32   wc = (wc > temp) ? temp : wc;
33   console.log("WIND CHILL: " + wc);
34   // change the HTML of 'feels' (const created earlier as feelTemp)
35   if (wc != null) {
36      feelTemp.innerHTML = wc;
37   }
38}
39
40// getCondition() will test a series of statements and determine what 
41// the weather condition should be defined as so we can change the picture
42// console.log will debug throughout
43function getCondition(statement) {
44   // Make them all lower case //
45   statement = statement.toLowerCase();
46   // console.log("statement passed to getCondition() is: " + statement);
47   // create an empty condition (I still don't get why let is preferred over var)
48   let condition = "";
49
50   // Start the if statement. Not necessarily neat, but still preferred over
51   // switch statements
52   if (statement == 'cloudy' ||
53      statement == 'overcast' ||
54      statement == 'mostly cloudy' ||
55      statement == 'gloomy') {
56      // Condition change
57      condition = 'clouds';
58      // console.log("Condition is: " + condition);
59      return condition;
60   } else if (statement == 'snow' ||
61      statement == 'snowy' ||
62      statement == 'snowing' ||
63      statement == 'flurries') {
64      // Condition change
65      condition = 'snow';
66      // console.log("Condition is: " + condition);
67      return condition;
68   } else if (statement == 'foggy' ||
69      statement == 'low visibility' ||
70      statement == 'smoggy' ||
71      statement == 'haze' ||
72      statement == 'hazey') {
73      // Condition change
74      condition = 'fog';
75      // console.log("Condition is: " + condition);
76      return condition;
77   } else if (statement == 'pouring' ||
78      statement == 'raining' ||
79      statement == 'raining cats and dogs' ||
80      statement == 'dumping buckets' ||
81      statement == 'rain' ||
82      statement == 'precipitation' ||
83      statement == 'high precipitation' ||
84      statement == 'wet weather') {
85      // Condition change
86      condition = 'rain';
87      // console.log("Condition is: " + condition);
88      return condition;
89   } else {
90      condition = 'clear';
91      // console.log("Condition is: " + condition);
92      return condition;
93   }
94}
95
96// changeSummaryImage() will simply change the element 'content' to have the
97// class of whatever weather factor we can determine using the getCondition()
98// function.
99function changeSummaryImage(condition) {
100   document.getElementById('content').setAttribute("class", condition);
101   document.getElementById('weather-picture').setAttribute("src", "images/" + condition + "-small.jpg");
102   document.getElementById('weather-picture').setAttribute("alt", condition + " weather condition image");
103   return 0;
104}
105
106// convertMeters() will take meters and turn them to feet and return an integer.
107function convertMeters(meters) {
108   let feet = meters * 3.28084;
109   feet = Math.round(feet);
110   return feet;
111}
112
113// setElevation is going to change the elevation to feet from meters
114function setElevation(feet) {
115   document.getElementById('elevation').innerHTML = feet;
116}
117
118// Convert, Format time to 12 hour format
119function format_time(hour) {
120   if (hour > 23) {
121      hour -= 24;
122   }
123   let amPM = (hour > 11) ? "pm" : "am";
124   if (hour > 12) {
125      hour -= 12;
126   }
127   if (hour == 0) {
128      hour = "12";
129   }
130   return hour + amPM;
131}
132
133// Build the hourly temperature list
134function buildHourlyData(nextHour, hourlyTemps) {
135   // Data comes from a JavaScript object of hourly temp name - value pairs
136   // Next hour should have a value between 0-23
137   // The hourlyTemps variable holds an array of temperatures
138   // Line 8 builds a list item showing the time for the next hour 
139   // and then the first element (value in index 0) from the hourly temps array
140   let hourlyListItems = '<li>' + format_time(nextHour) + ': ' + hourlyTemps[0] + '&deg;F</li>';
141   // Build the remaining list items using a for loop
142   for (let i = 1, x = hourlyTemps.length; i < x; i++) {
143      hourlyListItems += '<li>' + format_time(nextHour + i) + ': ' + hourlyTemps[i] + '&deg;F</li>';
144   }
145   // console.log('HourlyList is: ' + hourlyListItems);
146   return hourlyListItems;
147}
148
149/* ---------------------------------------------------------------- Locations Functions Below!! ------------------------------------------------------------ */
150
151let statusContainer = document.getElementById('status');
152let contentContainer = document.getElementById('main-content');
153
154
155// Gets location information from the NWS API
156function getLocation(locale) {
157   const URL = "https://api.weather.gov/points/" + locale;
158   // NWS User-Agent header (built above) will be the second parameter 
159   fetch(URL, idHeader)
160      .then(function (response) {
161         if (response.ok) {
162            return response.json();
163         }
164         throw new ERROR('Response not OK.');
165      })
166      .then(function (data) {
167         // Let's see what we got back
168         console.log('getLocation object:');
169         console.log(data);
170         // Store data to localstorage
171         storage.setItem("locName", data.properties.relativeLocation.properties.city);
172         storage.setItem("locState", data.properties.relativeLocation.properties.state);
173
174         // This is my API Key for the zipCodeAPI if I have time to do it: Yn3ypsoRugytpYooDNI7fUIXnsZB1ciuxPmmmssPnxLRFRFIIlQqBVE9erEaQ6Y1
175
176         let fullName = storage.getItem('locName') + ', ' + storage.getItem('locState');
177         storage.setItem("locFullName", fullName);
178
179         // Next, get the weather station ID before requesting current conditions 
180         // URL for station list is in the data object 
181         let stationsURL = data.properties.observationStations;
182         // Call the function to get the list of weather stations
183         getStationId(stationsURL);
184
185         let hourlyURL = data.properties.forecastHourly;
186         getHourly(hourlyURL);
187         let forecastURL = data.properties.forecast;
188         getForecast(forecastURL);
189
190         // Call the buildPage function
191         setTimeout(buildPage(), 5000);
192
193         // storage.setItem("reloadThing", 'Page has not been reloaded yet');
194
195         // while(storage.getItem('reloadThing') != 'Reloaded Page')
196         // {
197         //    storage.setItem('reloadThing', 'Reloaded Page');
198         //    setTimeout(location.reload(), 600);
199         //    console.log("---------------------- RELOAD ------------------");
200         // }
201
202      })
203      .catch(error => console.log('There was a getLocation error: ', error))
204} // end getLocation function
205
206// the getStationId() function gets weather station list and the nearest weather station ID from the NWS API
207function getStationId(stationsURL) {
208   // NWS User-Agent header (built above) will be the second parameter 
209   fetch(stationsURL, idHeader)
210      .then(function (response) {
211         if (response.ok) {
212            return response.json();
213         }
214         throw new ERROR('Response not OK.');
215      })
216      .then(function (data) {
217         // Let's see what we got back
218         console.log('getStationId object:');
219         console.log(data);
220
221         // Store station ID and elevation (in meters - will need to be converted to feet) 
222         let stationId = data.features[0].properties.stationIdentifier;
223         let stationElevation = data.features[0].properties.elevation.value;
224         console.log('Station and Elevation are: ' + stationId, stationElevation);
225
226         // Store data to localstorage 
227         storage.setItem("stationId", stationId);
228         storage.setItem("stationElevation", stationElevation);
229
230         // Request the Current Weather for this station 
231         getWeather(stationId);
232      })
233      .catch(error => console.log('There was a getStationId error: ', error))
234} // end getStationId function
235
236// Gets current weather information for a specific weather station from the NWS API
237function getWeather(stationId) {
238   // This is the URL for current observation data 
239   const URL = 'https://api.weather.gov/stations/' + stationId + '/observations/latest';
240   // NWS User-Agent header (built above) will be the second parameter 
241   fetch(URL, idHeader)
242      .then(function (response) {
243         if (response.ok) {
244            return response.json();
245         }
246         throw new ERROR('Response not OK.');
247      })
248      .then(function (data) {
249         // Are we done yet? No
250         let finished = false;
251
252         // Let's see what we got back
253         console.log('getWeather object:');
254         console.log(data);
255
256         let todd = data.properties.temperature.value;
257         storage.setItem("test", todd);
258
259
260         // ************ Get the content ******************************
261
262         // storage - text description
263         storage.setItem('textDescription', data.properties.textDescription);
264
265      })
266      .catch(error => console.log('There was a getWeather error: ', error))
267} // end getWeather function
268
269
270// Gets location information from the NWS API
271function getHourly(hourlyURL) {
272   // NWS User-Agent header (built above) will be the second parameter 
273   fetch(hourlyURL, idHeader)
274      .then(function (response) {
275         if (response.ok) {
276            return response.json();
277         }
278         throw new ERROR('Response not OK.');
279      })
280      .then(function (data) {
281         // Let's see what we got back
282         console.log('getHourly object:');
283         console.log(data);
284         // Get the hourly location
285
286         let hourly = [];
287         for (let i = 0; i < 13; i++) {
288            hourly[i] = data.properties.periods[i].temperature;
289         }
290
291         // wind direction, wind speed, current temperature, hourly - set to storage
292
293         storage.setItem('windDirection', data.properties.periods[0].windDirection);
294         storage.setItem('windSpeed', parseFloat(data.properties.periods[0].windSpeed));
295         storage.setItem('tempCurrent', data.properties.periods[0].temperature);
296         storage.setItem('tempHourly', hourly);
297
298
299      })
300      .catch(error => console.log('There was a getHourly error: ', error))
301} // end getHourly function
302
303// Gets location information from the NWS API
304function getForecast(URL) {
305   // NWS User-Agent header (built above) will be the second parameter 
306   fetch(URL, idHeader)
307      .then(function (response) {
308         if (response.ok) {
309            return response.json();
310         }
311         throw new ERROR('Response not OK.');
312      })
313      .then(function (data) {
314         // Let's see what we got back
315         console.log('getForecast object:');
316         console.log(data);
317
318         // high, low, icon, detailedForecast
319         storage.setItem('tempHigh', data.properties.periods[0].temperature);
320         storage.setItem('tempLow', data.properties.periods[1].temperature);
321
322      })
323      .catch(error => console.log('There was a getForecast error: ', error))
324} // end getForecast function
325
326
327function buildPage() {
328
329   // ************ Display the content ******************************
330
331   // // Set the page title to your current location's city and state
332   let pageTitle = document.getElementById('page-title');
333   let fullName = storage.getItem('locFullName');
334
335   // // Create a text node containing the full name 
336   let fullNameNode = document.createTextNode(fullName);
337   // // inserts the fullName value before any other content that might exist
338   pageTitle.insertBefore(fullNameNode, pageTitle.childNodes[0]);
339
340
341   // Set the Location information
342   // Get the h1 to display the city location
343   // The h1 in main h1 should now say "Greenville, SC"
344   document.getElementById('nameofcity').innerHTML = storage.getItem('locFullName');
345
346   // Feet to meters, to display
347   let feet = convertMeters(storage.getItem('stationElevation'));
348   setElevation(feet);
349   console.log("buildPage - Elevation in feet: " + feet);
350
351   // Lat and Lon (calculate sign and display properly)
352   let latitude = storage.getItem('geoLat');
353   let longitude = storage.getItem('geoLon');
354   signLat = getSign(true, latitude);
355   signLon = getSign(false, longitude);
356   if (latitude < 0) {
357      latitude *= -1;
358   }
359   if (longitude < 0) {
360      longitude *= -1;
361   }
362   document.getElementById('cord').innerHTML = Math.floor(latitude * 100) / 100 + "&#176; " + signLat + " " + Math.floor(longitude * 100) / 100 + "&#176; " + signLon;
363
364   // Set the temperature information
365   document.getElementById('high-temp').innerHTML = storage.getItem('tempHigh') + "&deg;F";
366   document.getElementById('low-temp').innerHTML = storage.getItem('tempLow') + "&deg;F";
367   document.getElementById('realtemp').innerHTML = storage.getItem('tempCurrent');
368   buildWC(storage.getItem('windSpeed'), storage.getItem('tempCurrent'));
369   console.log("buildPage - Windspeed and Temperature set (also called the buildWindChill() function)");
370
371   // Set the wind information
372   document.getElementById('mph').innerHTML = storage.getItem('windSpeed') + " mph";
373   document.getElementById('direction').innerHTML = "<strong>Direction: </strong>" + storage.getItem('windDirection') + "</p>";
374   document.getElementById('gusts').innerHTML =
375      "<strong>Gusts: </strong>" + (parseFloat(storage.getItem("windGusts")) > storage.getItem('windSpeed') ? parseFloat(storage.getItem("windGusts")) : storage.getItem('windSpeed')) + " mph</p>";
376   console.log("WIND DIRECTION FROM functions[369] " + storage.getItem("windDirection"));
377   windDial(storage.getItem('windDirection'));
378   console.log("Wind Direction: " + storage.getItem('windDirection'));
379
380   // Set the current conditions information
381   const sendCondition = getCondition(storage.getItem('textDescription'));
382   changeSummaryImage(sendCondition);
383   console.log("Weather Condition :" + sendCondition);
384   document.getElementById('loll').innerHTML = storage.getItem('textDescription');
385
386   // Set the hourly temperature information //
387   // Setting the nextHour to currentHour + 1
388   let date = new Date();
389   let nextHour = date.getHours() + 1;
390
391   document.getElementById('hourly-info').innerHTML = buildHourlyData(nextHour, storage.getItem('tempHourly').split(','));
392
393   // Clear everything and make it so that it all appears on the screen
394   document.getElementById('main-content').setAttribute('class', '');
395   document.getElementById('status').setAttribute('class', 'hide');
396   console.log("This should be the last thing I see");
397}
398
399/*-----------------------------------------------------------------------------------------------------------------------------------------------------------*/
400
401
402// changeSummaryImage() will simply change the element 'content' to have the
403// class of whatever weather factor we can determine using the getCondition()
404// function.
405function changeSummaryImage(condition) {
406   document.getElementById('content').setAttribute("class", condition);
407   document.getElementById('weather-picture').setAttribute("src", "images/" + condition + "-small.
407jpg");
408   document.getElementById('weather-picture').setAttribute("alt", condition + " weather condition image");
409   return 0;
410}
411
412// convertMeters() will take meters and turn them to feet and return an integer.
413function convertMeters(meters) {
414   let feet = meters * 3.28084;
415   feet = Math.round(feet);
416   return feet;
417}
418
419// setElevation is going to change the elevation to feet from meters
420function setElevation(feet) {
421   document.getElementById('elevation').innerHTML = feet;
422}
423
424// Convert, Format time to 12 hour format
425function format_time(hour) {
426   if (hour > 23) {
427      hour -= 24;
428   }
429   let amPM = (hour > 11) ? "pm" : "am";
430   if (hour > 12) {
431      hour -= 12;
432   }
433   if (hour == 0) {
434      hour = "12";
435   }
436   return hour + amPM;
437}
438
439function getSign(isLat, num) {
440   if (num > 0) {
441      if (isLat == true) {
442         return 'N';
443      } else {
444         return 'E';
445      }
446   } else {
447      if (isLat == true) {
448         return 'S';
449      } else {
450         return 'W';
451      }
452   }
453}
454
455
456
457
458// windDial is what will set the addribute of the dial class //
459function windDial(direction) {
460   // get the dial class
461   const dial = document.getElementById("dial");
462   // make sure the string is in all upper case characters
463   direction = direction.toUpperCase();
464
465   // Start the switch (gross)... console.log will help debug if needed
466   switch (direction) {
467      case "North":
468      case "N":
469         dial.setAttribute("class", "n");
470         // console.log('Wind Pointer Set to North.');
471         break;
472      case "NE":
473      case "NNE":
474      case "ENE":
475         dial.setAttribute("class", "ne");
476         // console.log('Wind Pointer Set to North East.');
477         break;
478      case "NW":
479      case "NNW":
480      case "WNW":
481         dial.setAttribute("class", "nw");
482         // console.log('Wind Pointer Set to North West.');
483         break;
484      case "South":
485      case "S":
486         dial.setAttribute("class", "s");
487         // console.log('Wind Pointer Set to South.');
488         break;
489      case "SE":
490      case "SSE":
491      case "ESE":
492         dial.setAttribute("class", "se");
493         // console.log('Wind Pointer Set to South East.');
494         break;
495      case "SW":
496      case "SSW":
497      case "WSW":
498         dial.setAttribute("class", "sw");
499         // console.log('Wind Pointer Set to South West');
500         break;
501      case "East":
502      case "E":
503         dial.setAttribute('class', "e");
504         // console.log('Wind Pointer Set to East.');
505         break;
506      case "West":
507      case "W":
508         // console.log("made it")
509         dial.setAttribute("class", "w");
510         // console.log('Wind Pointer Set to West.');
511         break;
512      default:
513         // console.log("Nothing Worked... direction: " + direction);
514   }
515}
516
517function celsiusToFahrenheit(degrees) {
518   degrees = parseFloat(degrees);
519   return (valNum - 32) / 1.8;
520}

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.