// scrolling effect const scrollLimit = 150; window.onscroll = () => { // check if scrolled past limit if so add scrolled class to change background of nav if (document.body.scrollTop >= scrollLimit || document.documentElement.scrollTop >= scrollLimit) { document.querySelector("nav").classList.add("scrolled"); } else { document.querySelector("nav").classList.remove("scrolled"); } let current = ""; //id of current section scrolled to, set to "" if at top // go through all sections and find current section id scrolled to document.querySelectorAll("section").forEach((section) => { const sectionTop = section.offsetTop; if (window.pageYOffset >= sectionTop - 60) { current = section.getAttribute("id"); } }); // go through all nav links, remove active class and add it to the link whose href matches the current id scrolled // to document.querySelectorAll("nav ul li a").forEach((a) => { a.classList.remove("active"); if (a.href.includes(current) && current !== "") { a.classList.add("active"); } else if (current === "") { document.querySelector("nav ul li a").classList.add("active"); // at the top } }); }; // cv timeline data /** * getTimelineData function * Gets the timeline data from backend route and appends the data on to the timeline. */ function getTimelineData() { let dateOptions = { year: "numeric", month: "short" }; fetch("/api/timelineData/edu").then(res => { res.json().then(json => { if (res.ok) { json.forEach(item => { let timelineItem = document.createElement("div") timelineItem.classList.add("timelineItem"); timelineItem.innerHTML = `

${new Date(item["startPeriod"]).toLocaleString('en-gb', dateOptions)} - ${new Date(item["endPeriod"]).toLocaleString('en-gb', dateOptions)}

Grade: ${item["grade"]}

${item["course"]}

`; document.getElementById("edu").appendChild(timelineItem); }); } }) }); fetch("/api/timelineData/work").then(res => { res.json().then(json => { if (res.ok) { json.forEach(item => { let timelineItem = document.createElement("div") timelineItem.classList.add("timelineItem"); let endPeriod = item["endPeriod"] === "0000-00-00" ? "Present" : new Date(item["endPeriod"]).toLocaleString('en-gb', dateOptions); timelineItem.innerHTML = `

${new Date(item["startPeriod"]).toLocaleString('en-gb', dateOptions)} - ${endPeriod}

${item["companyName"]} - ${item["area"]}

${item["title"]}

`; document.getElementById("work").appendChild(timelineItem); }) } }) }) } /** * getProjectData function * Gets the project data from the backend route and appends the data on to the timeline. */ function getProjectData() { fetch("/api/projectData").then(res => { res.json().then(json => { if (res.ok) { for (let i = 0; i < 4; i++){ if (json[i]["isMainProject"] === 1) { document.getElementById("mainProj").innerHTML = `

${json[i]["title"]}

${json[i]["information"]}

View Project Git
`; continue; } document.querySelector("#otherProj div").innerHTML += `

${json[i]["title"]}

${json[i]["information"]}

View Project ${(json[i]["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git
`; } } }) }) } document.addEventListener('DOMContentLoaded', () => { // get timeline data and add it to the timeline getTimelineData(); // get projectData getProjectData(); // update the year in the footer document.getElementById("year").innerHTML = new Date().getFullYear().toString(); }); // contact error message document.querySelector("#contactError .close").addEventListener("click", () => document.querySelector("#contactError").classList.toggle("hidden")); document.querySelector("#goBackToTop").addEventListener("click", () => { window.scrollTo(0, 0); }); // contact form document.querySelector("#contactForm").addEventListener("submit", e => { e.preventDefault(); let contactData = new FormData(); contactData.append("fName", document.querySelector("#fName").value); contactData.append("lName", document.querySelector("#lName").value); contactData.append("email", document.querySelector("#email").value); contactData.append("subject", document.querySelector("#subject").value); contactData.append("message", document.querySelector("#message").value); const fields = ['#fName', '#lName', '#email', '#subject', '#message']; let invalid = false; fields.forEach(field => { const element = document.querySelector(field); if (element.value.length === 0) { element.classList.add("invalid"); invalid = true; } else { element.classList.remove("invalid") document.querySelector("#contactError").classList.remove("error"); } }); if (invalid) { // show error message document.querySelector("#contactError").classList.add("error"); document.querySelector("#contactError").classList.remove("hidden"); document.querySelector("#contactError div").innerText = "Please fill out all fields."; return; } fetch("/api/contact", { method: "POST", body: contactData }).then(res => { if(res.ok) { document.querySelector("#contactError").classList.remove("hidden"); document.querySelector("#contactError div").innerText = "Thanks for contacting me, I will get back to you as soon as possible."; } }); });