-
Notifications
You must be signed in to change notification settings - Fork 12
feat: add hardcoded creators list with carousel UI #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,67 +1,70 @@ | ||||||||||
| 'use strict'; | ||||||||||
| "use strict"; | ||||||||||
|
|
||||||||||
| // load more content | ||||||||||
| function loadMore() { | ||||||||||
| const paragraphs = document.querySelectorAll('#projects_items .load_more'); | ||||||||||
| const paragraphs = document.querySelectorAll("#projects_items .load_more"); | ||||||||||
| for (let i = 0; i < paragraphs.length; i++) { | ||||||||||
| paragraphs[i].classList.add('show'); | ||||||||||
| paragraphs[i].classList.add("show"); | ||||||||||
| } | ||||||||||
| const hr = document.querySelectorAll('.line_hr'); | ||||||||||
| const hr = document.querySelectorAll(".line_hr"); | ||||||||||
| for (let i = 0; i < hr.length; i++) { | ||||||||||
| hr[i].classList.add('sh'); | ||||||||||
| hr[i].classList.add("sh"); | ||||||||||
| } | ||||||||||
| document.getElementById('load-more-button').style.display = 'none'; | ||||||||||
| document.getElementById('hide-button').style.display = 'block'; | ||||||||||
| document.getElementById("load-more-button").style.display = "none"; | ||||||||||
| document.getElementById("hide-button").style.display = "block"; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function hide() { | ||||||||||
| const paragraphs = document.querySelectorAll('#projects_items .load_more'); | ||||||||||
| const paragraphs = document.querySelectorAll("#projects_items .load_more"); | ||||||||||
| for (let i = 0; i < paragraphs.length; i++) { | ||||||||||
| paragraphs[i].classList.remove('show'); | ||||||||||
| paragraphs[i].classList.remove("show"); | ||||||||||
| } | ||||||||||
| const hr = document.querySelectorAll('.line_hr'); | ||||||||||
| const hr = document.querySelectorAll(".line_hr"); | ||||||||||
| for (let i = 0; i < hr.length; i++) { | ||||||||||
| hr[i].classList.remove('sh'); | ||||||||||
| hr[i].classList.remove("sh"); | ||||||||||
| } | ||||||||||
| document.getElementById('load-more-button').style.display = 'block'; | ||||||||||
| document.getElementById('hide-button').style.display = 'none'; | ||||||||||
| document.getElementById("load-more-button").style.display = "block"; | ||||||||||
| document.getElementById("hide-button").style.display = "none"; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const members_url = "https://api.github.com/orgs/move-fast-and-break-things/members"; | ||||||||||
| const members_url = | ||||||||||
| "https://api.github.com/orgs/move-fast-and-break-things/members"; | ||||||||||
|
|
||||||||||
| // fetch authors data | ||||||||||
| async function getAuthors(apiURL) { | ||||||||||
|
|
||||||||||
| const response = await fetch(apiURL); | ||||||||||
| if (!response.ok) { | ||||||||||
| throw new Error(`HTTP error! status: ${response.status}`); | ||||||||||
| } | ||||||||||
| const data = await response.json(); | ||||||||||
| return Promise.all(data.map(async (element) => { | ||||||||||
| const userResponse = await fetch(element.url); | ||||||||||
| if (!userResponse.ok) { | ||||||||||
| throw new Error(`HTTP error! status: ${userResponse.status}`); | ||||||||||
| } | ||||||||||
| const userData = await userResponse.json(); | ||||||||||
| return { | ||||||||||
| name: userData.name || userData.login, | ||||||||||
| bio: userData.bio, | ||||||||||
| avatar: userData.avatar_url, | ||||||||||
| html_url: userData.html_url, | ||||||||||
| }; | ||||||||||
| })); | ||||||||||
| return Promise.all( | ||||||||||
| data.map(async (element) => { | ||||||||||
| const userResponse = await fetch(element.url); | ||||||||||
| if (!userResponse.ok) { | ||||||||||
| throw new Error(`HTTP error! status: ${userResponse.status}`); | ||||||||||
| } | ||||||||||
| const userData = await userResponse.json(); | ||||||||||
| return { | ||||||||||
| name: userData.name || userData.login, | ||||||||||
| bio: userData.bio, | ||||||||||
| avatar: userData.avatar_url, | ||||||||||
| html_url: userData.html_url, | ||||||||||
| }; | ||||||||||
| }) | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // set authors in the DOM | ||||||||||
| async function setAuthors(apiURL) { | ||||||||||
| const authors = await getAuthors(apiURL); | ||||||||||
| const container = document.querySelector("#creators > div > div"); | ||||||||||
| const container = document.querySelector("#creators .persons"); | ||||||||||
| if (!container) { | ||||||||||
| throw new Error("Container element not found"); | ||||||||||
| } | ||||||||||
| authors.forEach(author => { | ||||||||||
| const personDiv = document.createElement('div'); | ||||||||||
| personDiv.className = 'person'; | ||||||||||
|
|
||||||||||
| authors.forEach((author) => { | ||||||||||
| const personDiv = document.createElement("div"); | ||||||||||
| personDiv.className = "person"; | ||||||||||
| personDiv.innerHTML = ` | ||||||||||
| <div class="name_and_img"> | ||||||||||
| <a href="${author.html_url}" class="tooltip" target="_blank"> | ||||||||||
|
|
@@ -70,36 +73,44 @@ async function setAuthors(apiURL) { | |||||||||
| </a> | ||||||||||
| </div> | ||||||||||
|
|
||||||||||
| <p class="about_person">${author.bio || 'No biography available'}</p> | ||||||||||
| <p class="about_person">${ | ||||||||||
| author.bio || "No biography available" | ||||||||||
| }</p> | ||||||||||
| `; | ||||||||||
| container.appendChild(personDiv); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| // set contributors in the DOM | ||||||||||
| async function setContributors(apiURL, element) { | ||||||||||
| try { | ||||||||||
| const contributors = await getAuthors(apiURL); | ||||||||||
| element.innerHTML = contributors.length === 0 ? "No developers found" : | ||||||||||
| contributors.map(contributor => ` | ||||||||||
| element.innerHTML = | ||||||||||
| contributors.length === 0 | ||||||||||
| ? "No developers found" | ||||||||||
| : contributors | ||||||||||
| .map( | ||||||||||
| (contributor) => ` | ||||||||||
| <span class="developer-name"> | ||||||||||
| <a href="${contributor.html_url}" class="tooltip" target="_blank"> | ||||||||||
| <img src="${contributor.avatar}" alt="${contributor.name}'s avatar" class="shining-image"> | ||||||||||
| <span class="tooltip-text">${contributor.name}</span> | ||||||||||
| </a> | ||||||||||
| </span> | ||||||||||
| `).join(''); | ||||||||||
| ` | ||||||||||
| ) | ||||||||||
| .join(""); | ||||||||||
| } catch (error) { | ||||||||||
| console.error("Error setting contributors:", error); | ||||||||||
| element.innerHTML = "Can't load the developer list. Check out the repository page to see all of the contributors 😅"; | ||||||||||
| element.innerHTML = | ||||||||||
| "Can't load the developer list. Check out the repository page to see all of the contributors 😅"; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // load all contributors | ||||||||||
| async function loadAllContributors() { | ||||||||||
| const developerLists = document.querySelectorAll(".developers-list"); | ||||||||||
| const promises = Array.from(developerLists).map(devList => { | ||||||||||
| const promises = Array.from(developerLists).map((devList) => { | ||||||||||
| const apiURL = devList.getAttribute("data-value"); | ||||||||||
| return setContributors(apiURL, devList); | ||||||||||
| }); | ||||||||||
|
|
@@ -108,29 +119,45 @@ async function loadAllContributors() { | |||||||||
|
|
||||||||||
| // Scroll-to-top functionality | ||||||||||
| function setupScrollToTop() { | ||||||||||
| const toTopButton = document.getElementById('toTop'); | ||||||||||
| const toTopButton = document.getElementById("toTop"); | ||||||||||
| if (!toTopButton) return; | ||||||||||
|
|
||||||||||
| window.addEventListener('scroll', () => { | ||||||||||
| window.addEventListener("scroll", () => { | ||||||||||
| if (window.scrollY > 100) { | ||||||||||
| toTopButton.style.display = 'block'; | ||||||||||
| toTopButton.style.display = "block"; | ||||||||||
| } else { | ||||||||||
| toTopButton.style.display = 'none'; | ||||||||||
| toTopButton.style.display = "none"; | ||||||||||
| } | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| toTopButton.addEventListener('click', (e) => { | ||||||||||
| toTopButton.addEventListener("click", (e) => { | ||||||||||
| e.preventDefault(); | ||||||||||
| window.scrollTo({ | ||||||||||
| top: 0, | ||||||||||
| behavior: 'smooth' | ||||||||||
| behavior: "smooth", | ||||||||||
| }); | ||||||||||
| }); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function initCarousel() { | ||||||||||
| const persons = document.querySelector(".persons"); | ||||||||||
| const nextBtn = document.querySelector(".carousel-btn.next"); | ||||||||||
| const prevBtn = document.querySelector(".carousel-btn.prev"); | ||||||||||
|
|
||||||||||
| if (!persons || !nextBtn || !prevBtn) return; | ||||||||||
|
|
||||||||||
| nextBtn.addEventListener("click", () => { | ||||||||||
| persons.scrollBy({ left: 260, behavior: "smooth" }); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| prevBtn.addEventListener("click", () => { | ||||||||||
| persons.scrollBy({ left: -260, behavior: "smooth" }); | ||||||||||
|
||||||||||
| }); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Wait for DOM content to be loaded before executing scripts | ||||||||||
| document.addEventListener('DOMContentLoaded', () => { | ||||||||||
| setAuthors(members_url).catch(console.error); | ||||||||||
| document.addEventListener("DOMContentLoaded", async () => { | ||||||||||
| loadAllContributors(); | ||||||||||
|
||||||||||
| loadAllContributors(); | |
| await loadAllContributors(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it makes sense to remove async added in this PR.
Also, it could make sense to add .catch(console.error) to loadAllContributors to prevent it crashing from calling initCarousel and setupScrollToTop.
| loadAllContributors(); | |
| loadAllContributors().catch(console.error); |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another issue is that clicking the left button when the carousel is in the leftmost position does nothing. Let's either disable/hide the button when the carousel is in the leftmost position or make the carousel cyclic and infinite. |

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scroll distance of 260 pixels is a magic number. Consider extracting this to a named constant (e.g.,
SCROLL_DISTANCE) to improve maintainability and make it easier to adjust the scroll behavior.