var activeFlag = 'active'; var darkThemeFlag = 'dark'; var darkThemeIconFlag = 'dark-mode-icon'; var hashAttribute = 'data-hash'; var homePageHash = 'home'; var lightThemeFlag = 'light'; var lightThemeIconFlag = 'light-mode-icon'; var themeAttribute = 'data-theme'; var themeFlag = 'theme'; var themeIconFlag = 'theme-icon'; var themeSwitchFlag = 'theme-switch'; function hookupPage() { hookupPageLocalStorage(); hookupNav(); hookupThemeSwitch(); hookupScroll(); // hookupProjectThumbnails(); hookupProjectDetailButtons(); hookupGitHubContributionsCalendar(); } function hookupPageLocalStorage() { let pageLocalStorage = getPageLocalStorage(); // Colour theme let theme = pageLocalStorage[themeFlag]; if (!theme) { let prefersDark = window.matchMedia(`(prefers-color-scheme: ${darkThemeFlag})`).matches; theme = prefersDark ? darkThemeFlag : lightThemeFlag; } setPageTheme(theme); } function getPageLocalStorage() { let pageHash = getPageHash(); let pageLocalStorage = localStorage.getItem(pageHash); let decodedPageLocalStorage; if (pageLocalStorage) { decodedPageLocalStorage = JSON.parse(pageLocalStorage); } else { decodedPageLocalStorage = {}; } return decodedPageLocalStorage; } function getPageHash() { return document.documentElement.getAttribute(hashAttribute) || homePageHash; } function setPageTheme(theme) { document.documentElement.setAttribute(themeAttribute, theme); let pageLocalStorage = getPageLocalStorage(); pageLocalStorage[themeFlag] = theme; setPageLocalStorage(pageLocalStorage); } function setPageLocalStorage(pageLocalStorage) { let pageHash = getPageHash(); localStorage.setItem(pageHash, JSON.stringify(pageLocalStorage)); } function hookupNav() { hookupNavLinks(); // Google Translate feature hooked up by plugin call } function hookupNavLinks() { document.querySelectorAll('nav a').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const section = document.querySelector(this.getAttribute('href')); section.scrollIntoView({ behavior: 'smooth' }); }); }); } function hookupThemeSwitch() { makeLightThemeIcon(); /* let themeSwitch = document.querySelector('#' + themeSwitchId); themeSwitch.addEventListener('click', function() { let theme = document.documentElement.getAttribute(themeAttribute); let newTheme = theme === darkThemeFlag ? lightThemeFlag : darkThemeFlag; setPageTheme(newTheme); }); */ let themeSwitch = getThemeSwitchButton(); themeSwitch.addEventListener('click', function() { let theme = getPageTheme(); let newTheme = theme === darkThemeFlag ? lightThemeFlag : darkThemeFlag; setPageTheme(newTheme); }); } function makeLightThemeIcon() { let themeSwitch = getThemeSwitchButton(); const backgroundRadius = 500; const sunRadius = 250; // const sunColour = "var(--text-colour)"; // "var(--text-background-colour)"; // const backgroundColour = "var(--secondary-colour)"; // Create the SVG element const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("xmlns", "http://www.w3.org/2000/svg"); svg.setAttribute("viewBox", "0 0 1000 1000"); svg.classList.add(themeIconFlag); svg.classList.add(lightThemeIconFlag); // Create the background circle const background = document.createElementNS("http://www.w3.org/2000/svg", "circle"); background.setAttribute("cx", backgroundRadius); background.setAttribute("cy", backgroundRadius); background.setAttribute("r", backgroundRadius); // background.setAttribute("fill", backgroundColour); background.setAttribute("class", "background"); // Create the sun body const sunBody = document.createElementNS("http://www.w3.org/2000/svg", "circle"); sunBody.setAttribute("cx", backgroundRadius); sunBody.setAttribute("cy", backgroundRadius); sunBody.setAttribute("r", sunRadius); // sunBody.setAttribute("fill", sunColour); sunBody.setAttribute("class", "sun"); // Add background and sun body to the SVG svg.appendChild(background); svg.appendChild(sunBody); // Parameters for rays const centerX = 500; const centerY = 500; const numberOfRays = 8; const rayRadialSpacing = 75; const innerRadius = sunRadius + rayRadialSpacing; // Where the sun body ends const outerRadius = sunRadius + rayRadialSpacing + (backgroundRadius - sunRadius - rayRadialSpacing) * 0.5; // Where the rays extend to const strokeWidth = 75; // Create rays using a loop and trigonometry for (let i = 0; i < numberOfRays; i++) { // Calculate angle in radians const angle = (i * 2 * Math.PI) / numberOfRays; // Calculate start point (inner circle) const startX = centerX + innerRadius * Math.cos(angle); const startY = centerY + innerRadius * Math.sin(angle); // Calculate end point (outer radius) const endX = centerX + outerRadius * Math.cos(angle); const endY = centerY + outerRadius * Math.sin(angle); // Create the line element const line = document.createElementNS("http://www.w3.org/2000/svg", "line"); line.setAttribute("x1", startX); line.setAttribute("y1", startY); line.setAttribute("x2", endX); line.setAttribute("y2", endY); // line.setAttribute("stroke", sunColour); line.setAttribute("class", "sun"); line.setAttribute("stroke-width", strokeWidth); line.setAttribute("stroke-linecap", "round"); // Append the line to the SVG svg.appendChild(line); } // Append the completed SVG to the container themeSwitch.appendChild(svg); } function getThemeSwitchButton() { return document.querySelector('button.' + themeSwitchFlag); } function getPageTheme() { return document.documentElement.getAttribute(themeAttribute); } function hookupScroll() { window.addEventListener('scroll', function() { const sections = document.querySelectorAll('section'); const navLinks = document.querySelectorAll('nav a'); let current = ''; sections.forEach(section => { const sectionTop = section.offsetTop; if (scrollY >= sectionTop - 60) { current = section.getAttribute('id'); } }); navLinks.forEach(link => { link.classList.remove(activeFlag); if (link.getAttribute('href').substring(1) === current) { link.classList.add(activeFlag); } }); }); } /* function hookupProjectThumbnails() { let demoButtonSelector = '.project-links .button'; document.querySelectorAll(demoButtonSelector).forEach(demoButton => { let projectName = getProjectNameFromDemoButton(demoButton); demoButton.addEventListener('mouseover', function() { let projectName = getProjectNameFromDemoButton(this); let thumbnailContainer = getProjectThumbnailContainer(projectName); thumbnailContainer.classList.add(activeFlag); }); demoButton.addEventListener('mouseout', function() { let projectName = getProjectNameFromDemoButton(this); let thumbnailContainer = getProjectThumbnailContainer(projectName); thumbnailContainer.classList.remove(activeFlag); }); }); } function getProjectNameFromDemoButton(demoButton) { let projectName = demoButton.getAttribute('data-project'); return projectName; } function getProjectThumbnailContainer(projectName) { let container = document.querySelector(`div.project-thumbnail[data-project="${projectName}"]`); return container; } */ function hookupProjectDetailButtons() { let detailButtonSelector = '.project-detail-button'; document.querySelectorAll(detailButtonSelector).forEach(detailButton => { detailButton.addEventListener('click', function() { let projectDetailContainer = this.parentElement.querySelector('.project-detail-container'); let wasActive = projectDetailContainer.classList.contains(activeFlag); if (wasActive) { projectDetailContainer.classList.remove(activeFlag); detailButton.innerText = 'Show Details'; } else { projectDetailContainer.classList.add(activeFlag); detailButton.innerText = 'Hide Details'; } }); }); } function hookupGitHubContributionsCalendar() { // Basic implementation // e - statistics are all 0 // GitHubCalendar(".github-calendar", "Teddy-1024"); // Or with responsive option enabled: // e - statistics are all 0 // GitHubCalendar(".github-calendar", "Teddy-1024", { responsive: true }); /* // Or with proxy option enabled: // e - statistics are all 0 GitHubCalendar(".github-calendar", "Teddy-1024", { responsive: true, proxy: function(username) { return fetch(`https://cors-anywhere.herokuapp.com/https://github.com/users/${username}/contributions`) .then(response => response.text()); } }); */ new Promise((resolve) => { GitHubCalendar(".github-calendar", "Teddy-1024"); const checkLoaded = () => { const calendar = document.querySelector('.github-calendar .js-calendar-graph-table'); if (calendar) { resolve(); } else { setTimeout(checkLoaded, 100); } }; checkLoaded(); }) .then(() => { const scrollableElement = document.querySelector('.github-calendar .js-calendar-graph-table'); scrollableElement.scrollLeft = scrollableElement.scrollWidth - scrollableElement.clientWidth; }) ; /* const scrollableElement = document.querySelector('.github-calendar .js-calendar-graph-table'); scrollableElement.scrollLeft = scrollableElement.scrollWidth - scrollableElement.clientWidth; */ }