'use strict'; import { fetchData, url } from "./api.js"; import * as module from "./module.js"; const addEventOnElements = function (elements, eventType, callback) { for (const element of elements) element.addEventListener(eventType, callback); } const searchView = document.querySelector("[data-search-view]"); const searchTogglers = document.querySelectorAll("[data-search-toggler]"); const toggleSearch = () => searchView.classList.toggle("active"); addEventOnElements(searchTogglers, "click", toggleSearch); const searchField = document.querySelector("[data-search-field]"); const searchResult = document.querySelector("[data-search-result]"); let searchTimeout = null; const serachTimeoutDuration = 500; searchField.addEventListener("input", function () { searchTimeout ?? clearTimeout(searchTimeout); if (!searchField.value) { searchResult.classList.remove("active"); searchResult.innerHTML = ""; searchField.classList.remove("searching"); } else { searchField.classList.add("searching"); } if (searchField.value) { searchTimeout = setTimeout(() => { fetchData(url.geo(searchField.value), function (locations) { searchField.classList.remove("searching"); searchResult.classList.add("active"); searchResult.innerHTML = ` `; const /** {NodeList} | [] */ items = []; for (const { name, lat, lon, country, state } of locations) { const searchItem = document.createElement("li"); searchItem.classList.add("view-item"); searchItem.innerHTML = ` location_on

${name}

${state || ""} ${country}

`; searchResult.querySelector("[data-search-list]").appendChild(searchItem); items.push(searchItem.querySelector("[data-search-toggler]")); } addEventOnElements(items, "click", function () { toggleSearch(); searchResult.classList.remove("active"); }) }); }, serachTimeoutDuration); } }); const container = document.querySelector("[data-container]"); const loading = document.querySelector("[data-loading]"); const currentLocationBtn = document.querySelector("[data-current-location-btn]"); const errorContent = document.querySelector("[data-error-content]"); export const updateWeather = function (lat, lon) { loading.style.display = "grid"; container.style.overflowY = "hidden"; container.classList.remove("fade-in"); errorContent.style.display = "none"; const currentWeatherSection = document.querySelector("[data-current-weather]"); const highlightSection = document.querySelector("[data-highlights]"); const hourlySection = document.querySelector("[data-hourly-forecast]"); const forecastSection = document.querySelector("[data-5-day-forecast]"); currentWeatherSection.innerHTML = ""; highlightSection.innerHTML = ""; hourlySection.innerHTML = ""; forecastSection.innerHTML = ""; if (window.location.hash === "#/current-location") { currentLocationBtn.setAttribute("disabled", ""); } else { currentLocationBtn.removeAttribute("disabled"); } fetchData(url.currentWeather(lat, lon), function (currentWeather) { const { weather, dt: dateUnix, sys: { sunrise: sunriseUnixUTC, sunset: sunsetUnixUTC }, main: { temp, feels_like, pressure, humidity }, visibility, timezone } = currentWeather const [{ description, icon }] = weather; const card = document.createElement("div"); card.classList.add("card", "card-lg", "current-weather-card"); card.innerHTML = `

Now

${parseInt(temp)}°c

${description}

${description}

`; fetchData(url.reverseGeo(lat, lon), function ([{ name, country }]) { card.querySelector("[data-location]").innerHTML = `${name}, ${country}` }); currentWeatherSection.appendChild(card); fetchData(url.airPollution(lat, lon), function (airPollution) { const [{ main: { aqi }, components: { no2, o3, so2, pm2_5 } }] = airPollution.list; const card = document.createElement("div"); card.classList.add("card", "card-lg"); card.innerHTML = `

Todays Highlights

Air Quality Index

air
  • ${pm2_5.toPrecision(3)}

    PM2.5

  • ${so2.toPrecision(3)}

    SO2

  • ${no2.toPrecision(3)}

    NO2

  • ${o3.toPrecision(3)}

    O3

${module.aqiText[aqi].level}

Sunrise & Sunset

clear_day

Sunrise

${module.getTime(sunriseUnixUTC, timezone)}

clear_night

Sunset

${module.getTime(sunsetUnixUTC, timezone)}

Humidity

humidity_percentage

${humidity}%

Pressure

airwave

${pressure}hPa

Visibility

visibility

${visibility / 1000}km

Feels Like

thermostat

${parseInt(feels_like)}°c

`; highlightSection.appendChild(card); }); fetchData(url.forecast(lat, lon), function (forecast) { const { list: forecastList, city: { timezone } } = forecast; hourlySection.innerHTML = `

Today at

`; for (const [index, data] of forecastList.entries()) { if (index > 7) break; const { dt: dateTimeUnix, main: { temp }, weather, wind: { deg: windDirection, speed: windSpeed } } = data const [{ icon, description }] = weather const tempLi = document.createElement("li"); tempLi.classList.add("slider-item"); tempLi.innerHTML = `

${module.getHours(dateTimeUnix, timezone)}

${description}

${parseInt(temp)}°

`; hourlySection.querySelector("[data-temp]").appendChild(tempLi); const windLi = document.createElement("li"); windLi.classList.add("slider-item"); windLi.innerHTML = `

${module.getHours(dateTimeUnix, timezone)}

direction

${parseInt(module.mps_to_kmh(windSpeed))} km/h

`; hourlySection.querySelector("[data-wind]").appendChild(windLi); } forecastSection.innerHTML = `

5 Days Forecast

`; for (let i = 7, len = forecastList.length; i < len; i += 8) { const { main: { temp_max }, weather, dt_txt } = forecastList[i]; const [{ icon, description }] = weather const date = new Date(dt_txt); const li = document.createElement("li"); li.classList.add("card-item"); li.innerHTML = `
${description}

${parseInt(temp_max)}°

${date.getDate()} ${module.monthNames[date.getUTCMonth()]}

${module.weekDayNames[date.getUTCDay()]}

`; forecastSection.querySelector("[data-forecast-list]").appendChild(li); } loading.style.display = "none"; container.style.overflowY = "overlay"; container.classList.add("fade-in"); }); }); } export const error404 = () => errorContent.style.display = "flex";