Source: main.js


"use strict";

// HAMBURGERMENY

//Visar meny vid klick av hamburgerikon i tablet och desktop
//Hämtar element för hamburge-ikonen
const hamburger = document.querySelector('.hamburger');
//Hämtar element för menynlistan i navbaren
const menu = document.querySelector('.navbar ul');

//Eventlyssnare som lyssnar på klick av hamburgaren
//Arrow-funktion som körs när det klickas
hamburger.addEventListener('click',
  //Arrow-funktion som körs när det klickas 
  () => {
    //Classlist hanterar klasser som finns i elementet
    //Toggle växlar synligheten beroende på om elementet har klassen show
    //CSS styr ul med "show" och om och hur menyn ska visas 
    menu.classList.toggle('show');
  });

///////////////////////////////////////////////////////////////////////////////////////

// ANIMATION 

//Trigger för animation på knapp (animation.html)

//Hämtar id för knapp
const animatedButton = document.querySelector('.animatedbutton');

//Händelselyssnare. Lyssnar på klick av knapp
if (animatedButton) {
  animatedButton.addEventListener('click', () => {
    animatedButton.classList.add('clicked');
  });
}

/////////////////////////////////////////////////////////////////////////////////////

// DIAGRAM (APEX)

import ApexCharts from "apexcharts";

/**
 * Globala variabler för mest sökta kurser och program
 * topCourses används för stapeldiagrammet
 * topPrograms används för cirkeldiagrammet
 * 
 * @typedef {Object} topResult
 * @property {string} name - Namn på kurs/program
 * @property {number} applicants - Antal sökande
*/
/** 
 * Array med de mest sökta kurserna (för stapeldiagrammet)
 * @type {topResult[]} */
let topCourses = [];
/** 
 * Array med de mest sökta programmen (för cirkeldiagrammet)
 * @type {topResult[]} */
let topPrograms = [];

/**
 * Tar fram statistik över mest sökta kurser och program
 * Funktion hämtar statistik från en extern källa. JSOn-fil.
 * Sorterar kurser och program efter antal sökande
 * Renderar diagram med Apexcharts.
 * 
 * @returns {void} Funktion returnerar inget värde men uppdaterar sidan med stapel och cirkeldiagram.
 */

async function getStatistics() {
  try {
    //Väntar in svar från url med kurser
    const response = await fetch(
      "https://mallarmiun.github.io/Frontend-baserad-webbutveckling/Moment%205%20-%20Dynamiska%20webbplatser/statistik_sokande_ht25.json"
    );
    /**
     * Variabel för att spara svar från fetch-anrop i JSON-format
     * statistics
     * 
     * @type {object[]}
     */
    const statistics = await response.json();

    /**
     * Variabler för arrayer att samla info om kurser och program
     * Data som används för att filtera fram topresultaten
     * courseStat för kursstatistik
     * programStat för programstatistik
     * 
     * @typedef {Object} allStat
     * @property {string} name - Namn på kurs/program
     * @property {number} applicants - Antal sökande
    */
    /** 
     * Array med statistik över kurser
     * @type {allStat[]} */
    const courseStat = [];
    /** 
     * Array med statistik över kurser
     * @type {allStat[]} */
    const programStat = [];


    for (let i = 0; i < statistics.length; i++) {
      if (statistics[i].type === "Kurs") {
        //pushar objekt med kursstatistik till array
        courseStat.push({
          name: statistics[i].name,
          applicants: Number(statistics[i].applicantsTotal.trim())
        });
      } else if (statistics[i].type === "Program") {
        //Pushar objekt med programstatistik till array
        programStat.push({
          name: statistics[i].name,
          applicants: Number(statistics[i].applicantsTotal.trim())
        });
      }
    }

    //Sortering av toppval

    //Sorterar i mest sökande kurser först
    courseStat.sort((a, b) => b.applicants - a.applicants);
    //Plockar ut de 6 första och lägger i array
    topCourses = courseStat.slice(0, 6);

    //...program
    programStat.sort((a, b) => b.applicants - a.applicants);
    //Lägger till top fem i array
    topPrograms = programStat.slice(0, 5);

    //RITAR UT DIAGRAM
    /**
     * Variabel för stapeldiagram
     * @type {HTMLElement}
     */
    const chartOne = document.querySelector(".barchart");

    if (chartOne) {
      let options = {
        chart: {
          type: 'bar',
          height: 700,
          width: '100%',
          toolbar: {
            show: false
          }
        },
        //plockar ut värden från objektet i topCourses(map)
        series: [{
          name: 'Antal sökande',
          data: topCourses.map(course => course.applicants)
        }],

        xaxis: {
          categories: topCourses.map(course => course.name)
        },
        colors: ['#621694'],
        tooltip: {
          theme: 'dark'
        }
      };

      let chart = new ApexCharts(chartOne, options);
      chart.render();
    }


    /**
     * Variabel för cirkeldiagram
     * @type {HTMLElement}
     */
    const chartTwo = document.querySelector(".piechart");

    if (chartTwo) {
      let options = {
        chart: {
          type: 'pie',
          height: 500,
        },
        //plockar ut värden från objektet i topPrograms(map)
        series: topPrograms.map(programs => programs.applicants),
        labels: topPrograms.map(programs => programs.name),
        colors: ['#800080', '#FF69B4', '#9233ff', '#340d7e', '#b936da']
      }

      let chart = new ApexCharts(chartTwo, options);
      chart.render();
    }

    //Felmeddelande som visas om datan inte läses in korrekt. eller annat fel
  } catch (error) {
    console.error("Fel vid hämtning av statistik", error);
  }

}

//Kallar på funktionen
getStatistics();

////////////////////////////////////////////////////////////////////////////

// KARTA //

/**
 * Funktion tillåter användare att söka plats som visas på kartan.
 * 
 * @param {string} location - Namn på plats som söks
 * @returns {void} Returnerar inget värde, men uppdaterar kartan med sökt plats
 */

async function searchLocation(location) {

  // Url till Nominatim. Parameter q tillåter fri text. Tar värdet av sökinput. encodeURI tillåter mellanslag och specialtecken
  const url = `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(location)}&format=json&`;

  try {
    // Hämtar svar från api
    const response = await fetch(url);

    /**
     * Variabel för array att samla data om sökt plats från hämtad data i JSON-format
     * 
     * @type {object[]}
     */
    const locationInfo = await response.json();


    /* If-sats som kontrollerar värdena från locationInfo
    parseFloat gör om textstängarna till "flytande" nummer
    */
    if (locationInfo.length > 0) {

      /**
       * Variabel som spar data från första träffen i arrayen från locationInfo och hämtar dess kordinater
       * latitude och longitude
       * 
       * @type {number} 
       */
      const latitude = parseFloat(locationInfo[0].lat);
      const longitude = parseFloat(locationInfo[0].lon);


      //bbox zoomar in på platsen och visar minsta och max lat och long för platsen som ska visas
      const bbox = `${longitude - 0.02},${latitude - 0.02},${longitude + 0.02},${latitude + 0.02}`;
      //Url som visar kartan i iframe från openstreetmap. Med bbox som inzoomat, och lat och long där markör sitter
      document.querySelector("#map").src = `https://www.openstreetmap.org/export/embed.html?bbox=${bbox}&marker=${latitude},${longitude}`;

      //Om plats inte kan hittas på kartan (visas för användare)
    } else {
      alert("Platsen kunde inte hittas.");
    }
    //Om något blir fel vid hämtning av datan
  } catch (error) {
    console.error("Fel vid hämtning av plats", error);
  }
}

/**
 * Hanterar sökfunktionen i sökformulätet
 * 
 * @param {SubmitEvent} showLocation - Händelsen som triggas vid klick av sök.
 * @returns {void} Returnerar inget värde. Stoppar sidan från att laddas om och kallar på searchLocation (visar plats på karta).
 */


//Eventlyssnare för vad som händer vid inmatning och sök i formuläret
document.querySelector("#searchinput").addEventListener("submit", function (showLocation) {

  // Gör så att sidan inte laddas om vid sök
  showLocation.preventDefault();
  // Hämtar värdet från inputfältet
  const location = document.querySelector("#search").value;

  // Kallar på funktionen
  searchLocation(location);
});