├── 1.accordion ├── index.html ├── main.js └── style.css ├── 10.modal ├── index.html ├── main.js └── style.css ├── 11.tic-tac-toe ├── index.html ├── main.js └── style.css ├── 12.fiilter-cards ├── index.html ├── main.js └── style.css ├── 13.qr-code-generator ├── index.html ├── main.js └── style.css ├── 14.scroll-to-top-bottom ├── index.html ├── main.js └── style.css ├── 15.button-ripple-effect ├── index.html ├── main.js └── style.css ├── 16.mutistep-progress-bar ├── index.html ├── main.js └── style.css ├── 17.scroll-indicator ├── index.html ├── main.js └── style.css ├── 18.tip-calculator ├── index.html ├── main.js └── style.css ├── 19.sticky-navbar ├── index.html ├── main.js └── style.css ├── 2.random-color-generator ├── index.html ├── main.js └── style.css ├── 20.random-image-generator ├── index.html ├── main.js └── style.css ├── 21.github-profile-finder ├── index.html ├── main.js └── style.css ├── 22.recipe-app ├── index.html ├── main.js └── style.css ├── 23.pagination ├── index.html ├── main.js └── style.css ├── 24.notes-app ├── index.html ├── main.js └── style.css ├── 3.star-rating ├── index.html ├── main.js └── style.css ├── 4.api-call ├── index.html ├── main.js └── style.css ├── 5.Image-Slider ├── index.html ├── main.js └── style.css ├── 6.load-more-button ├── index.html ├── main.js └── style.css ├── 7.light-dark-mode ├── index.html ├── main.js └── style.css ├── 8.random-quote-generator ├── index.html ├── main.js └── style.css └── 9.tabs ├── index.html ├── main.js └── style.css /1.accordion/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Accordion 7 | 14 | 15 | 16 | 17 |
18 |
19 |

Accordion

20 |
21 |
22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /1.accordion/main.js: -------------------------------------------------------------------------------- 1 | const data = [ 2 | { 3 | id: "1", 4 | question: "What are accordion components?", 5 | answer: 6 | "Accordion components are user interface elements used for organizing and presenting content in a collapsible manner. They typically consist of a header, content, and an expand/collapse action.", 7 | }, 8 | { 9 | id: "2", 10 | question: "What are they used for?", 11 | answer: 12 | "They are commonly employed in various contexts, including FAQs, product descriptions, navigation menus, settings panels, and data tables, to save screen space and provide a structured and user-friendly interface for presenting information or options.", 13 | }, 14 | { 15 | id: "3", 16 | question: "Accordion as a musical instrument", 17 | answer: 18 | "The accordion is a musical instrument with a keyboard and bellows. It produces sound by air passing over reeds when the player expands or compresses the bellows, used in various music genres.", 19 | }, 20 | { 21 | id: "4", 22 | question: "Can I create an accordion component with a different framework?", 23 | answer: 24 | "Yes of course, it is very possible to create an accordion component with another framework.", 25 | }, 26 | ]; 27 | 28 | const accordionWrapper = document.querySelector(".accordion"); 29 | 30 | function createAccordionData() { 31 | accordionWrapper.innerHTML = data 32 | .map( 33 | (dataItem) => ` 34 |
35 |
36 |

${dataItem.question}

37 | 38 |
39 |
40 |

${dataItem.answer}

41 |
42 |
43 | ` 44 | ) 45 | .join(" "); 46 | } 47 | 48 | createAccordionData(); 49 | 50 | const getAccordionTitles = document.querySelectorAll(".accordion_title"); 51 | 52 | console.log("===================================="); 53 | console.log(getAccordionTitles); 54 | console.log("===================================="); 55 | 56 | getAccordionTitles.forEach((currentItem) => { 57 | currentItem.addEventListener("click", (event) => { 58 | if (currentItem.classList.contains("active")) { 59 | currentItem.classList.remove("active"); 60 | } else { 61 | let getAlreadyAddedActiveClasses = document.querySelectorAll(".active"); 62 | 63 | getAlreadyAddedActiveClasses.forEach((currentActiveItem) => { 64 | currentActiveItem.classList.remove("active"); 65 | }); 66 | 67 | currentItem.classList.add("active"); 68 | } 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /1.accordion/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | background-color: #7cf9e5; 9 | } 10 | 11 | .section { 12 | min-height: 100vh; 13 | padding-top: 100px; 14 | } 15 | 16 | .container { 17 | max-width: 1440px; 18 | margin-left: auto; 19 | margin-right: auto; 20 | padding-left: 20px; 21 | padding-right: 20px; 22 | } 23 | 24 | h1 { 25 | font-size: 40px; 26 | margin-bottom: 50px; 27 | color: rgb(52, 63, 2); 28 | text-align: center; 29 | } 30 | 31 | .accordion{ 32 | max-width: 700px; 33 | margin: auto; 34 | } 35 | 36 | .accordion_item { 37 | border: 1px solid rgb(255, 0, 85); 38 | padding: 20px; 39 | } 40 | 41 | .accordion_title{ 42 | display: flex; 43 | align-items: center; 44 | gap: 10px; 45 | padding-bottom: 30px; 46 | } 47 | 48 | .accordion_title h3 { 49 | flex: 1; 50 | font-size: 25px; 51 | } 52 | 53 | .accordion_title i{ 54 | font-size: 30px; 55 | cursor: pointer; 56 | } 57 | 58 | .accordion_content{ 59 | display: none; 60 | } 61 | 62 | .accordion_title.active + .accordion_content { 63 | display: block; 64 | padding-top: 20px; 65 | } 66 | 67 | .accordion_content p{ 68 | font-size: 20px; 69 | color: rgb(117, 49, 0); 70 | } 71 | 72 | .accordion_title.active i { 73 | transform: rotate(180deg); 74 | } 75 | 76 | .accordion_title.active { 77 | border-bottom: 2px solid red; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /10.modal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Modal 7 | 8 | 9 | 10 | 11 | 12 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /10.modal/main.js: -------------------------------------------------------------------------------- 1 | const openModalBtn = document.querySelector(".openModal"); 2 | const modalBackground = document.querySelector(".modal-background"); 3 | const closeIcon = document.querySelector(".close-icon"); 4 | const closeBtn = document.querySelector(".close"); 5 | 6 | openModalBtn.addEventListener("click", () => { 7 | modalBackground.style.display = "block"; 8 | }); 9 | 10 | closeIcon.addEventListener("click", () => { 11 | modalBackground.style.display = "none"; 12 | }); 13 | 14 | closeBtn.addEventListener("click", () => { 15 | modalBackground.style.display = "none"; 16 | }); 17 | 18 | window.addEventListener("click", (event) => { 19 | console.log(event.target); 20 | if (event.target === modalBackground) { 21 | modalBackground.style.display = "none"; 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /10.modal/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | .modal-background { 8 | display: none; 9 | background-color: rgba(0, 0, 0, 0.2); 10 | position: fixed; 11 | top: 0; 12 | left: 0; 13 | width: 100%; 14 | height: 100%; 15 | z-index: 1; 16 | } 17 | 18 | .modal { 19 | background-color: #fff; 20 | position: absolute; 21 | top: 50%; 22 | left: 50%; 23 | transform: translate(-50%, -50%); 24 | width: 400px; 25 | padding: 20px; 26 | border-radius: 8px; 27 | display: flex; 28 | flex-direction: column; 29 | gap: 20px; 30 | animation-name: animateModal; 31 | animation-duration: .5s; 32 | } 33 | 34 | 35 | 36 | @keyframes animateModal { 37 | from { 38 | top: -200px; 39 | opacity: 0; 40 | } 41 | 42 | to { 43 | top: 50%; 44 | opacity: 1; 45 | } 46 | } 47 | 48 | button{ 49 | padding: 10px 20px; 50 | border: none; 51 | background-color: yellow; 52 | font-size: 18px; 53 | font-weight: bold; 54 | cursor: pointer; 55 | } 56 | body { 57 | text-align: center; 58 | } 59 | -------------------------------------------------------------------------------- /11.tic-tac-toe/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Tic Tac Toe 7 | 8 | 9 | 10 |

Tic Tac Toe

11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |

23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /11.tic-tac-toe/main.js: -------------------------------------------------------------------------------- 1 | const board = document.querySelector(".board"); 2 | const squares = document.querySelectorAll(".square"); 3 | const message = document.querySelector(".message"); 4 | const restartBtn = document.querySelector(".restart-button"); 5 | const players = ["X", "O"]; 6 | 7 | let currentPlayer = players[0]; 8 | 9 | message.textContent = `X's turn`; 10 | 11 | const winningPatterns = [ 12 | [0, 1, 2], 13 | [3, 4, 5], 14 | [6, 7, 8], 15 | [0, 3, 6], 16 | [1, 4, 7], 17 | [2, 5, 8], 18 | [0, 4, 8], 19 | [2, 4, 6], 20 | ]; 21 | 22 | for (let i = 0; i < squares.length; i++) { 23 | squares[i].addEventListener("click", () => { 24 | if (squares[i].textContent !== "" || checkWinner(currentPlayer)) { 25 | return; 26 | } 27 | 28 | squares[i].textContent = currentPlayer; 29 | 30 | if (checkWinner(currentPlayer)) { 31 | message.textContent = `Game Over. ${currentPlayer} wins the game ! Please restart`; 32 | return; 33 | } 34 | 35 | if (checkTieResult()) { 36 | message.textContent = `Game tied ! Please restart`; 37 | return; 38 | } 39 | 40 | currentPlayer = currentPlayer === players[0] ? players[1] : players[0]; 41 | 42 | if (currentPlayer === players[0]) { 43 | message.textContent = `X's Turn`; 44 | } else { 45 | message.textContent = `O's Turn`; 46 | } 47 | }); 48 | } 49 | 50 | function checkWinner(currentPlayer) { 51 | for (let i = 0; i < winningPatterns.length; i++) { 52 | const [a, b, c] = winningPatterns[i]; 53 | 54 | if ( 55 | squares[a].textContent === currentPlayer && 56 | squares[b].textContent === currentPlayer && 57 | squares[c].textContent === currentPlayer 58 | ) { 59 | return true; 60 | } 61 | } 62 | 63 | return false; 64 | } 65 | 66 | function checkTieResult() { 67 | for (let i = 0; i < squares.length; i++) { 68 | if (squares[i].textContent === "") { 69 | return false; 70 | } 71 | } 72 | 73 | return true; 74 | } 75 | 76 | function restartGame() { 77 | for (let i = 0; i < squares.length; i++) { 78 | squares[i].textContent = ""; 79 | } 80 | 81 | message.textContent = `X's turn`; 82 | currentPlayer = players[0]; 83 | } 84 | 85 | restartBtn.addEventListener("click", () => { 86 | restartGame(); 87 | }); 88 | -------------------------------------------------------------------------------- /11.tic-tac-toe/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | h1{ 8 | text-align: center; 9 | } 10 | 11 | .board{ 12 | margin-left: auto; 13 | margin-right: auto; 14 | width: 450px; 15 | height: 450px; 16 | display: grid; 17 | grid-template-columns: repeat(3,1fr); 18 | gap: 5px; 19 | margin-top: 30px; 20 | margin-bottom: 30px; 21 | } 22 | 23 | .square{ 24 | width: 145px; 25 | height: 145px; 26 | border: 1px solid rgb(111, 12, 165); 27 | background-color: #f5f5f5; 28 | font-size: 40px; 29 | display: flex; 30 | justify-content: center; 31 | align-items: center; 32 | cursor: pointer; 33 | } 34 | 35 | .restart-button { 36 | display: block; 37 | margin-left: auto; 38 | margin-right: auto; 39 | padding: 12px 20px; 40 | border: 2px solid #000; 41 | background-color: yellow; 42 | font-weight: bold; 43 | font-size: 18px; 44 | cursor: pointer; 45 | } 46 | 47 | .message { 48 | text-align: center; 49 | margin-bottom: 30px; 50 | font-size: 40px; 51 | font-weight: bolder; 52 | } -------------------------------------------------------------------------------- /12.fiilter-cards/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Card Filtering Functionality 7 | 8 | 9 | 10 |

Filter Cards By Category

11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /12.fiilter-cards/main.js: -------------------------------------------------------------------------------- 1 | const categories = ["All", "Men", "Women", "Kids"]; 2 | const content = [ 3 | { 4 | id: "Men", 5 | label: "Men Shirt 1", 6 | }, 7 | { 8 | id: "Men", 9 | label: "Men Shirt 2", 10 | }, 11 | { 12 | id: "Men", 13 | label: "Men Shirt 3", 14 | }, 15 | { 16 | id: "Men", 17 | label: "Men Shirt 4", 18 | }, 19 | { 20 | id: "Men", 21 | label: "Men Shirt 5", 22 | }, 23 | { 24 | id: "Women", 25 | label: "Women Shirt 1", 26 | }, 27 | { 28 | id: "Women", 29 | label: "Women Shirt 2", 30 | }, 31 | { 32 | id: "Women", 33 | label: "Women Shirt 3", 34 | }, 35 | { 36 | id: "Women", 37 | label: "Women Shirt 4", 38 | }, 39 | { 40 | id: "Women", 41 | label: "Women Shirt 5", 42 | }, 43 | { 44 | id: "Kids", 45 | label: "Kids Shirt 3", 46 | }, 47 | { 48 | id: "Kids", 49 | label: "Kids Shirt 4", 50 | }, 51 | { 52 | id: "Kids", 53 | label: "Kids Shirt 5", 54 | }, 55 | { 56 | id: "Kids", 57 | label: "Kids Shirt 10", 58 | }, 59 | { 60 | id: "Kids", 61 | label: "Kids Shirt 20", 62 | }, 63 | ]; 64 | 65 | const filterButtons = document.querySelector(".filter-buttons-wrapper"); 66 | const contentWrapper = document.querySelector(".content-wrapper"); 67 | 68 | function createCategory() { 69 | categories.forEach((category) => { 70 | const buttonEle = document.createElement("button"); 71 | buttonEle.innerText = category; 72 | buttonEle.classList.add("filter-button"); 73 | buttonEle.setAttribute("data-filter", category); 74 | 75 | filterButtons.appendChild(buttonEle); 76 | }); 77 | } 78 | 79 | function createContent() { 80 | content.forEach((contentItem) => { 81 | const singleContentItem = document.createElement("div"); 82 | singleContentItem.classList.add("card", contentItem.id); 83 | singleContentItem.textContent = contentItem.label; 84 | 85 | contentWrapper.appendChild(singleContentItem); 86 | }); 87 | } 88 | 89 | createCategory(); 90 | createContent(); 91 | 92 | const allFilterButtons = document.querySelectorAll(".filter-button"); 93 | const allCards = document.querySelectorAll(".card"); 94 | 95 | function filterCardsByCategory(extractCurrentCategory, allCards) { 96 | allCards.forEach((item) => { 97 | const isShowAllCards = extractCurrentCategory.toLowerCase() === "all"; 98 | const isItemFiltered = !item.classList.contains(extractCurrentCategory); 99 | 100 | if (isItemFiltered && !isShowAllCards) { 101 | item.classList.add("hide"); 102 | } else { 103 | item.classList.remove("hide"); 104 | } 105 | }); 106 | } 107 | 108 | allFilterButtons.forEach((singleFilterbuttonItem) => { 109 | singleFilterbuttonItem.addEventListener("click", () => { 110 | const extractCurrentCategory = singleFilterbuttonItem.dataset.filter; 111 | 112 | console.log(extractCurrentCategory); 113 | filterCardsByCategory(extractCurrentCategory, allCards); 114 | }); 115 | }); 116 | -------------------------------------------------------------------------------- /12.fiilter-cards/style.css: -------------------------------------------------------------------------------- 1 | 2 | *{ 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | padding: 15px; 10 | } 11 | 12 | .filter-buttons-wrapper { 13 | display: flex; 14 | gap: 10px; 15 | margin: 20px 0px; 16 | } 17 | 18 | .filter-buttons-wrapper button { 19 | padding: 12px 20px; 20 | font-size: 20px; 21 | font-weight: bold; 22 | border: none; 23 | background-color: rgb(255, 157, 0); 24 | cursor: pointer; 25 | } 26 | 27 | .content-wrapper{ 28 | display: flex; 29 | flex-wrap: wrap; 30 | gap: 10px; 31 | } 32 | 33 | .content-wrapper .card { 34 | width: 32%; 35 | padding: 30px; 36 | background-color: rgb(0, 251, 255); 37 | font-size: 30px; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | .hide { 45 | display: none; 46 | } -------------------------------------------------------------------------------- /13.qr-code-generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QR Code Generator 7 | 8 | 9 | 10 |

QR Code generator

11 | 12 | 13 |
14 |

15 | 16 | 17 | 18 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /13.qr-code-generator/main.js: -------------------------------------------------------------------------------- 1 | const qrContainer = document.querySelector(".qr-container"); 2 | const qrTextInput = document.querySelector(".qr-text"); 3 | const generateQrCodebtn = document.querySelector(".generate-qr-code-btn"); 4 | const errorMessageText = document.querySelector(".error-message-text"); 5 | 6 | generateQrCodebtn.addEventListener("click", () => { 7 | validateInputField(); 8 | }); 9 | 10 | function validateInputField() { 11 | console.log(qrTextInput.value); 12 | 13 | if (qrTextInput.value.trim().length > 0) { 14 | generateQrCode(); 15 | } else { 16 | qrContainer.innerHTML = ""; 17 | errorMessageText.textContent = 18 | "Enter text and use some URL to generate QR Code"; 19 | } 20 | } 21 | 22 | function generateQrCode() { 23 | qrContainer.innerHTML = ""; 24 | new QRCode(qrContainer, { 25 | text: qrTextInput.value, 26 | height: 400, 27 | width: 400, 28 | colorLight: "#fff", 29 | colorDark: "#000", 30 | }); 31 | 32 | qrTextInput.value = ""; 33 | errorMessageText.textContent = ""; 34 | } 35 | -------------------------------------------------------------------------------- /13.qr-code-generator/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0px; 3 | padding: 0px; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 25px; 9 | text-align: center; 10 | } 11 | 12 | .qr-text{ 13 | padding: 10px 20px; 14 | width: 400px; 15 | border: 2px solid red; 16 | margin: 20px 0px; 17 | font-size: 20px; 18 | } 19 | 20 | .generate-qr-code-btn{ 21 | padding: 10px 20px; 22 | font-size: 20px; 23 | font-weight: bold; 24 | color: yellow; 25 | border: none; 26 | cursor: pointer; 27 | background-color: #000; 28 | } 29 | 30 | .qr-container{ 31 | display: flex; 32 | justify-content: center; 33 | margin-bottom: 30px; 34 | } 35 | 36 | .error-message-text{ 37 | font-size: 30px; 38 | margin-bottom: 30px; 39 | } -------------------------------------------------------------------------------- /14.scroll-to-top-bottom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Scroll to Top and Bottom 7 | 8 | 9 | 10 |

Scroll to Top and Bottom

11 | 12 |
Loading Data ! Please wait.
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /14.scroll-to-top-bottom/main.js: -------------------------------------------------------------------------------- 1 | const usersList = document.querySelector(".users-list"); 2 | const loader = document.querySelector(".loader"); 3 | const scrollToTopButton = document.querySelector(".scroll-to-top-button"); 4 | const scrollToBottomButton = document.querySelector('.scroll-to-bottom-button') 5 | 6 | function showLoader() { 7 | loader.classList.add("show-loader"); 8 | usersList.classList.add("hide-users-list"); 9 | } 10 | 11 | function removeLoader() { 12 | loader.classList.remove("show-loader"); 13 | usersList.classList.remove("hide-users-list"); 14 | } 15 | 16 | async function fetchUsersList() { 17 | showLoader(); 18 | 19 | const response = await fetch("https://dummyjson.com/users?limit=100", { 20 | method: "GET", 21 | }); 22 | 23 | const result = await response.json(); 24 | 25 | if (result && result.users) displayUsersList(result.users); 26 | 27 | console.log(result); 28 | 29 | removeLoader(); 30 | } 31 | 32 | function displayUsersList(getUsers) { 33 | console.log(getUsers); 34 | 35 | usersList.innerHTML = getUsers 36 | .map( 37 | (userItem) => ` 38 |
  • 39 |

    ${userItem.firstName} ${userItem.lastName}

    40 |
  • 41 | ` 42 | ) 43 | .join(" "); 44 | } 45 | 46 | fetchUsersList(); 47 | 48 | scrollToTopButton.addEventListener("click", () => { 49 | 50 | window.scrollTo({ 51 | top : 0, 52 | behavior: 'smooth' 53 | }) 54 | }); 55 | 56 | 57 | scrollToBottomButton.addEventListener('click', ()=>{ 58 | console.log(document.body.scrollHeight); 59 | 60 | window.scrollTo({ 61 | top: document.body.scrollHeight, 62 | behavior: 'smooth' 63 | }) 64 | }) -------------------------------------------------------------------------------- /14.scroll-to-top-bottom/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | .loader{ 6 | display: none; 7 | } 8 | 9 | .loader.show-loader{ 10 | display: block; 11 | } 12 | 13 | .users-list.hide-users-list{ 14 | display: none; 15 | } -------------------------------------------------------------------------------- /15.button-ripple-effect/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Button Ripple Effect 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /15.button-ripple-effect/main.js: -------------------------------------------------------------------------------- 1 | const getAllButtons = document.querySelectorAll(".ripple-effect"); 2 | 3 | getAllButtons.forEach((btn) => { 4 | btn.addEventListener("click", (event) => { 5 | console.log( 6 | event.clientX, 7 | event.target.offsetLeft, 8 | event.clientY, 9 | event.target.offsetTop 10 | ); 11 | 12 | let xCoordinateValue = event.clientX - event.target.offsetLeft; 13 | let yCoordinateValue = event.clientY - event.target.offsetTop; 14 | 15 | let rippleElement = document.createElement("span"); 16 | rippleElement.style.left = `${xCoordinateValue}px`; 17 | rippleElement.style.top = `${yCoordinateValue}px`; 18 | 19 | btn.appendChild(rippleElement); 20 | 21 | window.setTimeout(() => { 22 | rippleElement.remove(); 23 | }, 500); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /15.button-ripple-effect/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | height: 100vh; 12 | background-color: rgb(114, 246, 206); 13 | } 14 | 15 | .ripple-effect { 16 | position: relative; 17 | padding: 15px 35px; 18 | display: inline-block; 19 | margin: 10px; 20 | font-size: 20px; 21 | letter-spacing: 3px; 22 | border-radius: 40px; 23 | cursor: pointer; 24 | overflow: hidden; 25 | background: linear-gradient(90deg, rgb(208, 255, 0), rgb(249, 13, 202)); 26 | color: #fff; 27 | font-weight: bold; 28 | } 29 | 30 | .ripple-effect.secondary { 31 | background: linear-gradient(90deg, rgb(212, 0, 255), rgb(0, 238, 111)); 32 | } 33 | 34 | .ripple-effect > span { 35 | position: absolute; 36 | background-color: rgba(255, 255, 255, 0.4); 37 | transform: translate(-50%, -50%); 38 | pointer-events: none; 39 | border-radius: 50%; 40 | animation: rippleEffectAnimation 1s linear infinite; 41 | } 42 | 43 | @keyframes rippleEffectAnimation { 44 | 0% { 45 | height: 0; 46 | width: 0; 47 | } 48 | 49 | 100% { 50 | height: 500px; 51 | width: 500px; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /16.mutistep-progress-bar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Multi step Progress Bar 7 | 14 | 15 | 16 | 17 |

    Multi step progress bar

    18 |
    19 |
    20 |
    21 |
    22 | 23 |

    Facebook

    24 |
    25 |
    26 | 27 |

    Linkedin

    28 |
    29 |
    30 | 31 |

    Instagram

    32 |
    33 |
    34 | 35 |

    twitter

    36 |
    37 |
    38 | 39 | 40 |
    41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /16.mutistep-progress-bar/main.js: -------------------------------------------------------------------------------- 1 | const progress = document.querySelector(".progress"); 2 | const prevBtn = document.querySelector(".prev-btn"); 3 | const nextBtn = document.querySelector(".next-btn"); 4 | const iconsWrapper = document.querySelectorAll(".icon-wrapper"); 5 | 6 | let currentSelectedStep = 1; 7 | 8 | nextBtn.addEventListener("click", () => { 9 | if (currentSelectedStep < iconsWrapper.length) { 10 | currentSelectedStep++; 11 | } 12 | 13 | handleUpdateStep(); 14 | }); 15 | 16 | prevBtn.addEventListener("click", () => { 17 | if (currentSelectedStep > 1) { 18 | currentSelectedStep--; 19 | } 20 | 21 | handleUpdateStep(); 22 | }); 23 | 24 | function handleUpdateStep() { 25 | iconsWrapper.forEach((item, index) => { 26 | if (index < currentSelectedStep) { 27 | item.classList.add("active"); 28 | } else { 29 | item.classList.remove("active"); 30 | } 31 | }); 32 | 33 | progress.style.width = 34 | ((currentSelectedStep - 1) / (iconsWrapper.length - 1)) * 100 + "%"; 35 | 36 | if (currentSelectedStep === 1) { 37 | prevBtn.disabled = true; 38 | } else if (currentSelectedStep === iconsWrapper.length) { 39 | nextBtn.disabled = true; 40 | } else { 41 | prevBtn.disabled = false; 42 | nextBtn.disabled= false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /16.mutistep-progress-bar/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | height: 100vh; 12 | font-size: 18px; 13 | background-color: #ddd; 14 | flex-direction: column; 15 | } 16 | 17 | h1 { 18 | margin-bottom: 80px; 19 | } 20 | 21 | .container { 22 | text-align: center; 23 | } 24 | 25 | .progress-container { 26 | display: flex; 27 | justify-content: space-between; 28 | position: relative; 29 | margin-bottom: 40px; 30 | max-width: 100%; 31 | width: 350px; 32 | } 33 | 34 | .progress-container::before { 35 | content: ""; 36 | background-color: #9f0404; 37 | position: absolute; 38 | top: 50%; 39 | left: 0%; 40 | transform: translateY(-50%); 41 | height: 5px; 42 | width: 100%; 43 | z-index: -1; 44 | } 45 | 46 | .progress { 47 | background-color: rgb(240, 255, 32); 48 | position: absolute; 49 | top: 50%; 50 | left: 0; 51 | transform: translateY(-50%); 52 | height: 5px; 53 | width: 0%; 54 | z-index: -1; 55 | } 56 | 57 | .icon-wrapper { 58 | background-color: rgb(97, 1, 135); 59 | border-radius: 50%; 60 | height: 15px; 61 | width: 15px; 62 | display: flex; 63 | align-items: center; 64 | justify-content: center; 65 | border: 3px solid #fff; 66 | } 67 | 68 | .icon-wrapper i { 69 | position: absolute; 70 | font-size: 25px; 71 | bottom: 25px; 72 | } 73 | 74 | .icon-wrapper .label { 75 | position: absolute; 76 | font-size: 20px; 77 | bottom: -30px; 78 | font-weight: bold; 79 | } 80 | 81 | .prev-btn, 82 | .next-btn { 83 | font-size: 20px; 84 | padding: 12px 20px; 85 | background-color: rgba(32, 32, 236, 0.923); 86 | color: #fff; 87 | border-radius: 30px; 88 | border: none; 89 | cursor: pointer; 90 | } 91 | 92 | .prev-btn:disabled, 93 | .next-btn:disabled { 94 | opacity: 0.65; 95 | cursor: not-allowed; 96 | } 97 | -------------------------------------------------------------------------------- /17.scroll-indicator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Scroll Indicator 7 | 8 | 9 | 10 |
    11 |

    Scroll Indicator

    12 |
    13 |
    14 |
    15 |
    16 |
    17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /17.scroll-indicator/main.js: -------------------------------------------------------------------------------- 1 | const postListContainer = document.querySelector(".posts-container"); 2 | const progressBar = document.querySelector(".progress-bar"); 3 | 4 | function fetchListOfPosts() { 5 | fetch("https://dummyjson.com/posts", { 6 | method: "GET", 7 | }) 8 | .then((response) => response.json()) 9 | .then((result) => displayPostList(result.posts)); 10 | } 11 | 12 | function displayPostList(getPosts) { 13 | getPosts.forEach((postItem) => { 14 | const postItemWrapper = document.createElement("div"); 15 | postItemWrapper.classList.add("post-item-wrapper"); 16 | 17 | const postTitle = document.createElement("label"); 18 | postTitle.textContent = postItem.title; 19 | 20 | const postBody = document.createElement("p"); 21 | postBody.textContent = postItem.body; 22 | 23 | const postTags = document.createElement("div"); 24 | postTags.textContent = postItem.tags.map((tagItem) => tagItem).join(","); 25 | postTags.classList.add("post-tags"); 26 | 27 | postItemWrapper.appendChild(postTitle); 28 | postItemWrapper.appendChild(postBody); 29 | postItemWrapper.appendChild(postTags); 30 | 31 | postListContainer.appendChild(postItemWrapper); 32 | }); 33 | } 34 | 35 | fetchListOfPosts(); 36 | 37 | window.onscroll = function () { 38 | handleScroll(); 39 | }; 40 | 41 | function handleScroll() { 42 | const getScrollFromTop = 43 | document.body.scrollTop || document.documentElement.scrollTop; 44 | const height = 45 | document.documentElement.scrollHeight - 46 | document.documentElement.clientHeight; 47 | 48 | const howMuchPercentageAlreadyScrolled = (getScrollFromTop / height) * 100; 49 | progressBar.style.width = `${howMuchPercentageAlreadyScrolled}%`; 50 | } 51 | -------------------------------------------------------------------------------- /17.scroll-indicator/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 0px 25px; 9 | } 10 | 11 | .top-section{ 12 | position: fixed; 13 | top: 0px; 14 | z-index: 1; 15 | width: 100%; 16 | background-color: rgb(248, 228, 184); 17 | padding: 10px 0px; 18 | } 19 | 20 | .top-section h1 { 21 | text-align: center; 22 | } 23 | 24 | .progress-container{ 25 | width: 100%; 26 | height: 10px; 27 | background-color: rgb(0, 9, 6); 28 | } 29 | 30 | .progress-bar{ 31 | height: 10px; 32 | background-color: yellow; 33 | width: 0%; 34 | } 35 | 36 | .posts-container{ 37 | margin: 40px auto 0px auto; 38 | padding-top: 40px; 39 | display: flex; 40 | flex-direction: column; 41 | gap: 20px; 42 | } 43 | 44 | .post-item-wrapper{ 45 | padding: 15px; 46 | display: flex; 47 | flex-direction: column; 48 | gap: 10px; 49 | border: 2px solid black; 50 | color: #fff; 51 | background: linear-gradient(90deg, rgb(32, 59, 19), rgb(255, 0, 119)); 52 | } -------------------------------------------------------------------------------- /18.tip-calculator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Tip Calculator 7 | 8 | 9 | 10 |

    Tip Calculator

    11 |
    12 |
    13 | 14 | 20 |
    21 |
    22 | 23 | 24 | 25 |
    26 |
    27 | 28 | 29 | 30 |
    31 |
    32 | 33 | 34 | 35 |
    36 | 37 |
    38 | 39 | 40 |
    41 |
    42 | 43 | 44 |
    45 |
    46 | 47 | 48 |
    49 |
    50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /18.tip-calculator/main.js: -------------------------------------------------------------------------------- 1 | const generateBillButton = document.querySelector(".generate-bill"); 2 | const billAmount = document.querySelector(".bill-amount"); 3 | const discountPercentage = document.querySelector(".discount-percentage"); 4 | const tipsPercentage = document.querySelector(".tip-percentage"); 5 | const noOfCustomers = document.querySelector(".no-of-customers"); 6 | const totalTipPaid = document.querySelector(".total-tip-paid"); 7 | const totalAmountToPay = document.querySelector(".total-amount-to-pay"); 8 | const totalTipPercentageValue = document.querySelector(".tip-value") 9 | const discountPercentageValue = document.querySelector(".discount-value") 10 | const totalNoOfCustomersValue = document.querySelector(".no-of-customers-value") 11 | const eachCustomerToPay = document.querySelector('.each-customer-to-pay'); 12 | 13 | function calculateBill() { 14 | console.log( 15 | billAmount.value, 16 | tipsPercentage.value, 17 | discountPercentage.value, 18 | noOfCustomers.value 19 | ); 20 | 21 | const billAmountAfterDiscountPercentage = 22 | billAmount.value - (discountPercentage.value * billAmount.value) / 100; 23 | 24 | const getTipAmount = 25 | billAmountAfterDiscountPercentage * (tipsPercentage.value / 100); 26 | const totalBill = billAmountAfterDiscountPercentage + getTipAmount; 27 | const eachCustomerToPayAmount = totalBill / noOfCustomers.value; 28 | 29 | totalTipPaid.textContent = getTipAmount; 30 | totalAmountToPay.textContent = totalBill; 31 | totalTipPercentageValue.textContent = tipsPercentage.value; 32 | discountPercentageValue.textContent = discountPercentage.value; 33 | totalNoOfCustomersValue.textContent = noOfCustomers.value; 34 | eachCustomerToPay.textContent = eachCustomerToPayAmount 35 | } 36 | 37 | generateBillButton.addEventListener("click", calculateBill); 38 | -------------------------------------------------------------------------------- /18.tip-calculator/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 0px 15px; 9 | display: flex; 10 | flex-direction: column; 11 | min-height: 100vh; 12 | align-items: center; 13 | justify-content: center; 14 | gap: 30px; 15 | background-color: #ddd; 16 | } 17 | 18 | h1 { 19 | font-size: 50px; 20 | font-weight: bolder; 21 | } 22 | 23 | .form-wrapper{ 24 | display: flex; 25 | flex-direction: column; 26 | gap: 10px; 27 | background-color: rgb(143, 8, 170); 28 | padding: 20px; 29 | border-radius: 12px; 30 | 31 | color: #ffffff; 32 | } 33 | 34 | .input-wrapper { 35 | display: flex; 36 | justify-content: space-between; 37 | gap: 10px; 38 | } 39 | 40 | .input-wrapper label , .result-wrapper label { 41 | font-size: 20px; 42 | } 43 | 44 | button { 45 | padding: 12px 20px; 46 | border: none; 47 | background-color: rgb(211, 211, 50); 48 | font-size: 20px; 49 | cursor: pointer; 50 | color: #000000; 51 | letter-spacing: 2px; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /19.sticky-navbar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sticky Navbar 7 | 8 | 9 | 10 |
    11 |

    Sticky Navbar Example

    12 |
    13 | 20 |
    21 |
    22 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima 23 | dolores, nam minus beatae eveniet id est cum cupiditate expedita 24 | temporibus. Illum totam corrupti itaque in dolor cum suscipit recusandae 25 | sint! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repellat 26 | officiis perferendis, obcaecati sint dolorem quasi aliquid a doloremque 27 | voluptates saepe at modi rem sapiente qui? Facere nostrum vel quidem 28 | laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. 29 | Quibusdam vitae inventore dicta harum dignissimos ut a laudantium, id 30 | explicabo saepe, enim similique sit in rem numquam, alias aperiam 31 | asperiores sed? Lorem ipsum dolor sit, amet consectetur adipisicing 32 | elit. Dicta porro cupiditate laboriosam culpa? Necessitatibus voluptas 33 | iure molestiae nostrum debitis quae eaque quisquam fugiat? Ullam 34 | pariatur impedit consectetur ipsa et cupiditate? Lorem ipsum dolor sit 35 | amet consectetur adipisicing elit. Laudantium ipsa sit excepturi debitis 36 | ducimus illo mollitia optio ex sint rerum quo neque sunt, modi 37 | voluptatem fuga quibusdam quas nisi error? 38 |
    39 |
    40 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima 41 | dolores, nam minus beatae eveniet id est cum cupiditate expedita 42 | temporibus. Illum totam corrupti itaque in dolor cum suscipit recusandae 43 | sint! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repellat 44 | officiis perferendis, obcaecati sint dolorem quasi aliquid a doloremque 45 | voluptates saepe at modi rem sapiente qui? Facere nostrum vel quidem 46 | laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. 47 | Quibusdam vitae inventore dicta harum dignissimos ut a laudantium, id 48 | explicabo saepe, enim similique sit in rem numquam, alias aperiam 49 | asperiores sed? Lorem ipsum dolor sit, amet consectetur adipisicing 50 | elit. Dicta porro cupiditate laboriosam culpa? Necessitatibus voluptas 51 | iure molestiae nostrum debitis quae eaque quisquam fugiat? Ullam 52 | pariatur impedit consectetur ipsa et cupiditate? Lorem ipsum dolor sit 53 | amet consectetur adipisicing elit. Laudantium ipsa sit excepturi debitis 54 | ducimus illo mollitia optio ex sint rerum quo neque sunt, modi 55 | voluptatem fuga quibusdam quas nisi error? 56 |
    57 |
    58 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima 59 | dolores, nam minus beatae eveniet id est cum cupiditate expedita 60 | temporibus. Illum totam corrupti itaque in dolor cum suscipit recusandae 61 | sint! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repellat 62 | officiis perferendis, obcaecati sint dolorem quasi aliquid a doloremque 63 | voluptates saepe at modi rem sapiente qui? Facere nostrum vel quidem 64 | laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. 65 | Quibusdam vitae inventore dicta harum dignissimos ut a laudantium, id 66 | explicabo saepe, enim similique sit in rem numquam, alias aperiam 67 | asperiores sed? Lorem ipsum dolor sit, amet consectetur adipisicing 68 | elit. Dicta porro cupiditate laboriosam culpa? Necessitatibus voluptas 69 | iure molestiae nostrum debitis quae eaque quisquam fugiat? Ullam 70 | pariatur impedit consectetur ipsa et cupiditate? Lorem ipsum dolor sit 71 | amet consectetur adipisicing elit. Laudantium ipsa sit excepturi debitis 72 | ducimus illo mollitia optio ex sint rerum quo neque sunt, modi 73 | voluptatem fuga quibusdam quas nisi error? 74 |
    75 |
    76 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima 77 | dolores, nam minus beatae eveniet id est cum cupiditate expedita 78 | temporibus. Illum totam corrupti itaque in dolor cum suscipit recusandae 79 | sint! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repellat 80 | officiis perferendis, obcaecati sint dolorem quasi aliquid a doloremque 81 | voluptates saepe at modi rem sapiente qui? Facere nostrum vel quidem 82 | laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. 83 | Quibusdam vitae inventore dicta harum dignissimos ut a laudantium, id 84 | explicabo saepe, enim similique sit in rem numquam, alias aperiam 85 | asperiores sed? Lorem ipsum dolor sit, amet consectetur adipisicing 86 | elit. Dicta porro cupiditate laboriosam culpa? Necessitatibus voluptas 87 | iure molestiae nostrum debitis quae eaque quisquam fugiat? Ullam 88 | pariatur impedit consectetur ipsa et cupiditate? Lorem ipsum dolor sit 89 | amet consectetur adipisicing elit. Laudantium ipsa sit excepturi debitis 90 | ducimus illo mollitia optio ex sint rerum quo neque sunt, modi 91 | voluptatem fuga quibusdam quas nisi error? 92 |
    93 |
    94 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Minima 95 | dolores, nam minus beatae eveniet id est cum cupiditate expedita 96 | temporibus. Illum totam corrupti itaque in dolor cum suscipit recusandae 97 | sint! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repellat 98 | officiis perferendis, obcaecati sint dolorem quasi aliquid a doloremque 99 | voluptates saepe at modi rem sapiente qui? Facere nostrum vel quidem 100 | laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. 101 | Quibusdam vitae inventore dicta harum dignissimos ut a laudantium, id 102 | explicabo saepe, enim similique sit in rem numquam, alias aperiam 103 | asperiores sed? Lorem ipsum dolor sit, amet consectetur adipisicing 104 | elit. Dicta porro cupiditate laboriosam culpa? Necessitatibus voluptas 105 | iure molestiae nostrum debitis quae eaque quisquam fugiat? Ullam 106 | pariatur impedit consectetur ipsa et cupiditate? Lorem ipsum dolor sit 107 | amet consectetur adipisicing elit. Laudantium ipsa sit excepturi debitis 108 | ducimus illo mollitia optio ex sint rerum quo neque sunt, modi 109 | voluptatem fuga quibusdam quas nisi error? 110 |
    111 |
    112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /19.sticky-navbar/main.js: -------------------------------------------------------------------------------- 1 | const navbar = document.querySelector(".navbar"); 2 | let navTop = navbar.offsetTop; 3 | 4 | window.onscroll = function () { 5 | handleStickyNavbarOnScroll(); 6 | }; 7 | 8 | function handleStickyNavbarOnScroll() { 9 | if (window.scrollY >= navTop) navbar.classList.add("fix-navbar"); 10 | else navbar.classList.remove("fix-navbar"); 11 | } 12 | -------------------------------------------------------------------------------- /19.sticky-navbar/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0px; 3 | padding: 0px; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | background-color: #cbc7c7; 9 | padding: 15px; 10 | } 11 | 12 | .header { 13 | background-color: #eee; 14 | padding: 50px; 15 | text-align: center; 16 | } 17 | 18 | .navbar{ 19 | overflow: hidden; 20 | background-color: #000; 21 | display: flex; 22 | gap: 15px; 23 | padding: 15px; 24 | } 25 | 26 | .navbar a{ 27 | 28 | color: #f1f1f1; 29 | font-size: 20px; 30 | padding: 5px 15px; 31 | text-decoration: none; 32 | cursor: pointer; 33 | } 34 | 35 | .navbar a:hover { 36 | background-color: #fff; 37 | color: #000000; 38 | } 39 | 40 | .content{ 41 | padding: 20px 0px; 42 | display: flex; 43 | flex-direction: column; 44 | gap: 40px; 45 | font-size: 30px; 46 | } 47 | 48 | .fix-navbar { 49 | position: fixed; 50 | top: 0; 51 | width: 100%; 52 | } 53 | -------------------------------------------------------------------------------- /2.random-color-generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Random Color Generator 7 | 8 | 9 | 10 |
    11 |
    12 |

    #ffffff

    13 | 14 | 15 |
    16 |
    17 |

    rgb(255,255,255)

    18 |
    19 | 20 | 21 |
    22 |
    23 | 24 | 25 |
    26 |
    27 | 28 | 29 |
    30 | 31 | 32 | 33 |
    34 |
    35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2.random-color-generator/main.js: -------------------------------------------------------------------------------- 1 | const hexBtn = document.querySelector(".hex-btn"); 2 | const hexColorValue = document.querySelector(".hex-color-value"); 3 | const hexColorContainer = document.querySelector(".hex-color-container"); 4 | const hexCopyBtn = document.querySelector(".hex-copy-color"); 5 | // Create Random HEX color 6 | 7 | hexBtn.addEventListener("click", () => { 8 | let characterSet = "0123456789ABCDEF"; 9 | let hexColorOutput = ""; 10 | 11 | for (let i = 0, charSetLength = characterSet.length; i < 6; ++i) { 12 | hexColorOutput += characterSet.charAt( 13 | Math.floor(Math.random() * charSetLength) 14 | ); 15 | } 16 | 17 | hexColorValue.textContent = `#${hexColorOutput}`; 18 | hexColorContainer.style.backgroundColor = `#${hexColorOutput}`; 19 | hexBtn.style.color = `#${hexColorOutput}`; 20 | }); 21 | 22 | // RGB Color generator 23 | const rgbBtn = document.querySelector(".rgb-btn"); 24 | const getRedInputRange = document.querySelector("#red"); 25 | const getGreenInputRange = document.querySelector("#green"); 26 | const getBlueInputRange = document.querySelector("#blue"); 27 | const rgbColorContainer = document.querySelector(".rgb-color-container"); 28 | const rgbCopyBtn = document.querySelector(".rgb-copy-color"); 29 | const rgbColorValue = document.querySelector(".rgb-color-value"); 30 | 31 | rgbBtn.addEventListener("click", () => { 32 | let extractRedValue = getRedInputRange.value; 33 | let extractGreenValue = getGreenInputRange.value; 34 | let extractBlueValue = getBlueInputRange.value; 35 | 36 | rgbColorValue.textContent = `rgb(${extractRedValue}, ${extractGreenValue}, ${extractBlueValue})`; 37 | rgbColorContainer.style.backgroundColor = `rgb(${extractRedValue}, ${extractGreenValue}, ${extractBlueValue})`; 38 | rgbBtn.style.color = `rgb(${extractRedValue}, ${extractGreenValue}, ${extractBlueValue})`; 39 | }); 40 | 41 | function copyHexColorToClipBoard() { 42 | navigator.clipboard.writeText(hexColorValue.textContent); 43 | alert("Hex Color is copied to clipboard"); 44 | } 45 | 46 | hexCopyBtn.addEventListener("click", copyHexColorToClipBoard); 47 | 48 | function copyRgbColorToClipboard() { 49 | navigator.clipboard.writeText(rgbColorValue.textContent); 50 | alert("RGB Color is copied to clipboard"); 51 | } 52 | 53 | rgbCopyBtn.addEventListener("click", copyRgbColorToClipboard); 54 | -------------------------------------------------------------------------------- /2.random-color-generator/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 20px; 9 | font-size: 20px; 10 | } 11 | 12 | .random-color-generator-container{ 13 | display: flex; 14 | gap: 10px; 15 | } 16 | 17 | .hex-color-container, .rgb-color-container{ 18 | min-height: 100vh; 19 | flex: 1; 20 | } 21 | 22 | .hex-color-container button { 23 | padding: 12px 20px; 24 | cursor: pointer; 25 | font-size: 18px; 26 | font-weight: bold; 27 | background-color: rgb(230, 246, 127); 28 | } 29 | 30 | .rgb-color-container{ 31 | display: flex; 32 | flex-direction: column; 33 | gap: 20px; 34 | } 35 | 36 | .hex-color-container { 37 | background-color: green; 38 | padding: 20px; 39 | display: flex; 40 | justify-content: center; 41 | align-items: center; 42 | flex-direction: column; 43 | gap: 30px; 44 | } 45 | 46 | .hex-color-value , .rgb-color-value { 47 | font-size: 30px; 48 | font-weight: bold; 49 | color: #fff; 50 | } 51 | 52 | .rgb-color-container { 53 | background-color: rgb(0, 255, 247); 54 | padding: 20px; 55 | display: flex; 56 | justify-content: center; 57 | align-items: center; 58 | } 59 | 60 | .rgb-color-container button { 61 | padding: 12px 20px; 62 | cursor: pointer; 63 | font-size: 18px; 64 | font-weight: bold; 65 | background-color: rgb(208, 48, 125); 66 | color: #fff; 67 | } -------------------------------------------------------------------------------- /20.random-image-generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Random Image Generator 7 | 8 | 9 | 10 |

    Random Image Generator

    11 |
    12 | 13 |
    14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /20.random-image-generator/main.js: -------------------------------------------------------------------------------- 1 | const imagesWrapper = document.querySelector(".images-wrapper"); 2 | const loadMoreImagesBtn = document.querySelector(".load-more-images"); 3 | let count = 1; 4 | 5 | function fetchRandomImages(getCount) { 6 | for (let i = getCount; i <= getCount + 4; i++) { 7 | let imgElement = document.createElement("img"); 8 | imgElement.src = `https://picsum.photos/300?random=${i}`; 9 | imagesWrapper.appendChild(imgElement); 10 | } 11 | } 12 | 13 | fetchRandomImages(count); 14 | 15 | loadMoreImagesBtn.addEventListener("click", () => { 16 | fetchRandomImages((count += 5)); 17 | }); 18 | -------------------------------------------------------------------------------- /20.random-image-generator/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/25-javascript-projects-for-interview-2024-part1/5a92a555865f20ea162f52986f0729e17f8c3254/20.random-image-generator/style.css -------------------------------------------------------------------------------- /21.github-profile-finder/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Github Profile Finder 7 | 8 | 9 | 10 |

    Github Profile Finder

    11 |
    12 | 13 | 14 |
    15 |

    Loading Data ! Please Wait

    16 |
    17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /21.github-profile-finder/main.js: -------------------------------------------------------------------------------- 1 | const searchInput = document.querySelector(".search-input"); 2 | const searchBtn = document.querySelector(".search-btn"); 3 | const BASE_URL = "https://api.github.com/users/"; 4 | const githubProfileDetails = document.querySelector(".github-profile-details"); 5 | const loader = document.querySelector(".loading-text"); 6 | 7 | function showLoader() { 8 | loader.classList.add("show"); 9 | githubProfileDetails.classList.add("hide"); 10 | } 11 | 12 | function removeLoader() { 13 | loader.classList.remove("show"); 14 | githubProfileDetails.classList.remove("hide"); 15 | } 16 | 17 | async function fetchGithubProfileDetails() { 18 | showLoader() 19 | const response = await fetch(`${BASE_URL}${searchInput.value}`); 20 | const result = await response.json(); 21 | 22 | console.log(result); 23 | 24 | if (result) { 25 | removeLoader() 26 | displayProfileDetails(result); 27 | searchInput.value = '' 28 | } 29 | } 30 | 31 | function displayProfileDetails(getProfileDetails) { 32 | const { login, avatar_url, public_repos, followers, following } = 33 | getProfileDetails; 34 | githubProfileDetails.innerHTML = ` 35 |

    ${login}

    36 | ${login} 37 |

    Repos :${public_repos}

    38 |

    Followers :${followers}

    39 |

    Following :${following}

    40 | `; 41 | } 42 | 43 | searchBtn.addEventListener("click", fetchGithubProfileDetails); 44 | -------------------------------------------------------------------------------- /21.github-profile-finder/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | .loading-text{ 6 | display: none; 7 | } 8 | 9 | .loading-text.show { 10 | display: block; 11 | } 12 | 13 | .github-profile-details.hide { 14 | display: none; 15 | } -------------------------------------------------------------------------------- /22.recipe-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Recipe App 7 | 8 | 9 | 10 |

    Recipe App

    11 |
    12 |
    13 |
    14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /22.recipe-app/main.js: -------------------------------------------------------------------------------- 1 | const recipeListContainer = document.querySelector(".recipe-list"); 2 | const loader = document.querySelector(".loader"); 3 | const recipeDetails = document.querySelector(".recipe-details"); 4 | 5 | function showLoader(){ 6 | loader.classList.add('show'); 7 | recipeListContainer.classList.add('hide'); 8 | } 9 | 10 | function removeLoader(){ 11 | loader.classList.remove('show'); 12 | recipeListContainer.classList.remove('hide'); 13 | } 14 | 15 | async function fetchListOfRecipes() { 16 | showLoader() 17 | const response = await fetch("https://dummyjson.com/recipes", { 18 | method: "GET", 19 | }); 20 | 21 | const result = await response.json(); 22 | if (result && result.recipes && result.recipes.length > 0) { 23 | removeLoader() 24 | displayRecipeList(result.recipes); 25 | 26 | } 27 | console.log(result); 28 | } 29 | 30 | function displayRecipeList(getRecipeList) { 31 | getRecipeList.forEach((recipeItem) => { 32 | const { name, id, image, cuisine, ingredients, mealType, rating } = 33 | recipeItem; 34 | const recipeItemWrapper = document.createElement("div"); 35 | recipeItemWrapper.classList.add("recipe-item"); 36 | 37 | // name 38 | const recipeName = document.createElement("p"); 39 | recipeName.textContent = name; 40 | recipeName.classList.add("recipe-name"); 41 | 42 | // image 43 | const recipeImg = document.createElement("img"); 44 | recipeImg.src = image; 45 | recipeImg.classList.add("recipe-image"); 46 | 47 | //cuisine 48 | const recipeCuisine = document.createElement("p"); 49 | recipeCuisine.textContent = cuisine; 50 | recipeCuisine.classList.add("recipe-cuisine"); 51 | 52 | //ingredients 53 | const recipeIngredients = document.createElement("div"); 54 | recipeIngredients.textContent = ingredients.map((item) => item).join(","); 55 | recipeIngredients.classList.add("recipe-ingredients"); 56 | 57 | // mealType 58 | const recipeMealType = document.createElement("p"); 59 | recipeMealType.textContent = mealType; 60 | recipeMealType.classList.add("recipe-meal-type"); 61 | 62 | //rating 63 | const recipeRating = document.createElement("p"); 64 | recipeRating.textContent = rating; 65 | recipeRating.classList.add("recipe-rating"); 66 | 67 | // recipe details button 68 | const recipeDetailsButton = document.createElement("button"); 69 | recipeDetailsButton.classList.add("recipe-details-button"); 70 | recipeDetailsButton.innerText = "Recipe Details"; 71 | recipeDetailsButton.addEventListener("click", () => 72 | handleRecipeDetails(id) 73 | ); 74 | 75 | recipeItemWrapper.appendChild(recipeImg); 76 | recipeItemWrapper.appendChild(recipeName); 77 | recipeItemWrapper.appendChild(recipeCuisine); 78 | recipeItemWrapper.appendChild(recipeIngredients); 79 | recipeItemWrapper.appendChild(recipeMealType); 80 | recipeItemWrapper.appendChild(recipeRating); 81 | recipeItemWrapper.appendChild(recipeDetailsButton); 82 | 83 | recipeListContainer.appendChild(recipeItemWrapper); 84 | }); 85 | } 86 | 87 | fetchListOfRecipes(); 88 | 89 | async function handleRecipeDetails(getId) { 90 | const response = await fetch(`https://dummyjson.com/recipes/${getId}`); 91 | const result = await response.json(); 92 | 93 | if (result) { 94 | window.scrollTo({ 95 | top: document.body.scrollHeight, 96 | behavior: "smooth", 97 | }); 98 | 99 | displayRecipeDetailsData(result); 100 | } 101 | } 102 | 103 | function displayRecipeDetailsData(getRecipeData) { 104 | recipeDetails.innerHTML = ` 105 |

    You are now seeing the details of the following recipe

    106 |

    ${getRecipeData.name}

    107 | `; 108 | } 109 | -------------------------------------------------------------------------------- /22.recipe-app/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 15px; 9 | } 10 | 11 | h1 { 12 | margin-bottom: 40px; 13 | } 14 | 15 | .recipe-list { 16 | display: grid; 17 | grid-template-columns: repeat(4, 1fr); 18 | gap: 15px; 19 | } 20 | 21 | .recipe-list .recipe-item { 22 | display: flex; 23 | flex-direction: column; 24 | gap: 15px; 25 | padding: 20px; 26 | color: #fff; 27 | border: 2px solid rgb(253, 52, 243); 28 | background: linear-gradient(150deg, #39ef74, #4600f1 100%); 29 | } 30 | 31 | .recipe-list .recipe-item .recipe-image { 32 | width: 100%; 33 | height: 100%; 34 | object-fit: cover; 35 | } 36 | 37 | .recipe-list .recipe-item .recipe-name { 38 | font-size: 30px; 39 | font-weight: bolder; 40 | } 41 | 42 | .recipe-list .recipe-item .recipe-cuisine { 43 | font-size: 18px; 44 | color: #ffdeb8; 45 | } 46 | 47 | .recipe-list .recipe-item .recipe-ingredients { 48 | font-size: 16px; 49 | font-weight: bold; 50 | } 51 | 52 | .recipe-list .recipe-item .recipe-meal-type, 53 | .recipe-list .recipe-item .recipe-rating { 54 | font-size: 22px; 55 | color: #c1fdd4; 56 | } 57 | 58 | .recipe-list .recipe-item .recipe-details-button { 59 | padding: 12px 20px; 60 | border: none; 61 | font-size: 25px; 62 | background-color: rgb(242, 242, 117); 63 | font-weight: bold; 64 | letter-spacing: 2px; 65 | cursor: pointer; 66 | } 67 | 68 | .loader { 69 | display: none; 70 | } 71 | 72 | .recipe-list.hide { 73 | display: none; 74 | } 75 | 76 | .loader.show { 77 | display: block; 78 | border: 3px solid rgba(255, 255, 255, 0.4); 79 | border-radius: 50%; 80 | width: 50px; 81 | height: 50px; 82 | position: absolute; 83 | border-top: 3px solid red; 84 | top: 50%; 85 | left: 50%; 86 | transform: translate(-50%, -50%); 87 | animation: animateLoader 1s linear infinite; 88 | } 89 | 90 | @keyframes animateLoader { 91 | 0% { 92 | transform: rotate(0deg); 93 | } 94 | 95 | 100% { 96 | transform: rotate(360deg); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /23.pagination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pagination 7 | 8 | 9 | 10 |

    Pagination Using JavaScript

    11 | 12 |
    13 | 14 |
    15 | 16 |
    17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /23.pagination/main.js: -------------------------------------------------------------------------------- 1 | const paginationListWrapper = document.querySelector(".pagination-list"); 2 | 3 | function createDummyData() { 4 | for (let i = 1; i <= 100; i++) { 5 | const li = document.createElement("li"); 6 | li.textContent = `Card ${i}`; 7 | paginationListWrapper.appendChild(li); 8 | } 9 | } 10 | 11 | createDummyData(); 12 | 13 | const extractAllListItems = document.querySelectorAll("li"); 14 | const paginationNumbers = document.querySelector(".pagination-numbers"); 15 | const previousButton = document.querySelector(".prev-btn"); 16 | const nextButton = document.querySelector(".next-btn"); 17 | 18 | let paginationLimit = 10; 19 | let pageCount = Math.ceil(extractAllListItems.length / paginationLimit); 20 | let currentPage = 1; 21 | 22 | function createPageNumber(getCurrentIndex) { 23 | const pageNumber = document.createElement("button"); 24 | pageNumber.classList.add("pagination-number"); 25 | pageNumber.textContent = getCurrentIndex; 26 | pageNumber.setAttribute("page-index", getCurrentIndex); 27 | 28 | paginationNumbers.appendChild(pageNumber); 29 | } 30 | 31 | function createPaginationNumbers() { 32 | for (let i = 1; i <= pageCount; i++) { 33 | createPageNumber(i); 34 | } 35 | } 36 | 37 | function handleActiveCurrentPageNumber() { 38 | document.querySelectorAll(".pagination-number").forEach((button) => { 39 | button.classList.remove("active-state"); 40 | const getCurrentPageIndex = Number(button.getAttribute("page-index")); 41 | 42 | if (getCurrentPageIndex === currentPage) { 43 | button.classList.add("active-state"); 44 | } 45 | }); 46 | } 47 | 48 | function handleDisableButton(getBtn) { 49 | getBtn.classList.add("disabled"); 50 | getBtn.setAttribute("disabled", "true"); 51 | } 52 | 53 | function handleEnableButton(getBtn) { 54 | getBtn.classList.remove("disabled"); 55 | getBtn.removeAttribute("disabled"); 56 | } 57 | 58 | function handlePaginationButtonStatus() { 59 | console.log(currentPage); 60 | if (currentPage === 1) { 61 | handleDisableButton(previousButton); 62 | } else { 63 | handleEnableButton(previousButton); 64 | } 65 | 66 | if (pageCount === currentPage) { 67 | handleDisableButton(nextButton); 68 | } else { 69 | handleEnableButton(nextButton); 70 | } 71 | } 72 | 73 | function handleCurrentPage(getCurrentPageNumber) { 74 | currentPage = getCurrentPageNumber; 75 | 76 | handleActiveCurrentPageNumber(); 77 | handlePaginationButtonStatus(); 78 | 79 | const getPreviousRange = (getCurrentPageNumber - 1) * paginationLimit; 80 | const getCurrentrange = getCurrentPageNumber * paginationLimit; 81 | 82 | extractAllListItems.forEach((listItem, index) => { 83 | listItem.classList.add("hide-list-item"); 84 | 85 | if (index >= getPreviousRange && index < getCurrentrange) { 86 | listItem.classList.remove("hide-list-item"); 87 | } 88 | }); 89 | } 90 | 91 | createPaginationNumbers(); 92 | handleCurrentPage(1); 93 | 94 | previousButton.addEventListener("click", () => { 95 | handleCurrentPage(currentPage - 1); 96 | }); 97 | 98 | nextButton.addEventListener("click", () => { 99 | handleCurrentPage(currentPage + 1); 100 | }); 101 | 102 | document.querySelectorAll(".pagination-number").forEach((button) => { 103 | const getCurrentPageIndex = Number(button.getAttribute("page-index")); 104 | 105 | if (getCurrentPageIndex) { 106 | button.addEventListener("click", () => { 107 | handleCurrentPage(getCurrentPageIndex); 108 | }); 109 | } 110 | }); 111 | -------------------------------------------------------------------------------- /23.pagination/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 10px 15px; 9 | } 10 | 11 | h1 { 12 | margin-bottom: 30px; 13 | } 14 | 15 | .pagination-list{ 16 | display: grid; 17 | grid-template-columns: repeat(3,1fr); 18 | gap: 10px; 19 | list-style: none; 20 | } 21 | 22 | .pagination-list li{ 23 | 24 | background-color: rgb(255, 242, 0); 25 | padding: 20px; 26 | font-size: 20px; 27 | font-weight: bold; 28 | } 29 | 30 | .pagination-list li.hide-list-item{ 31 | display: none; 32 | } 33 | 34 | .pagination-container{ 35 | display: flex; 36 | margin-top: 30px; 37 | justify-content: center; 38 | gap: 25px 39 | } 40 | 41 | .pagination-container button { 42 | padding: 12px 18px; 43 | font-size: 20px; 44 | background-color: #000; 45 | font-weight: bolder; 46 | color: #fff; 47 | border: none; 48 | cursor: pointer; 49 | } 50 | 51 | .pagination-numbers{ 52 | display: flex; 53 | gap: 10px; 54 | } 55 | 56 | .pagination-container button.disabled{ 57 | opacity: 0.65; 58 | cursor: not-allowed; 59 | } 60 | 61 | .pagination-numbers button.active-state{ 62 | background-color: rgb(0, 255, 51); 63 | color: #000; 64 | } -------------------------------------------------------------------------------- /24.notes-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Notes App 7 | 8 | 9 | 10 |
    11 |

    Notes App

    12 |
    13 | 20 | 21 |
    22 |

    23 | 24 |
    25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /24.notes-app/main.js: -------------------------------------------------------------------------------- 1 | const inputBox = document.querySelector(".input"); 2 | const addButton = document.querySelector(".addBtn"); 3 | const notesListWrapper = document.querySelector(".notes-list-wrapper"); 4 | const errorMessageText = document.querySelector(".error-message-text"); 5 | 6 | let currentEditedNote = null; 7 | // creating/adding new note 8 | 9 | function createNewNoteItem(getCurrentNote) { 10 | const li = document.createElement("li"); 11 | const p = document.createElement("p"); 12 | 13 | p.textContent = getCurrentNote; 14 | li.appendChild(p); 15 | 16 | const editBtn = document.createElement("button"); 17 | editBtn.innerText = "Edit"; 18 | editBtn.classList.add("btn", "editBtn"); 19 | li.appendChild(editBtn); 20 | 21 | const deleteBtn = document.createElement("button"); 22 | deleteBtn.innerText = "Delete"; 23 | deleteBtn.classList.add("btn", "deleteBtn"); 24 | li.appendChild(deleteBtn); 25 | 26 | return li; 27 | } 28 | 29 | function saveNotesToStroage(getCurrentNote) { 30 | let notesList; 31 | 32 | if (localStorage.getItem("notes") === null) { 33 | notesList = []; 34 | } else { 35 | notesList = JSON.parse(localStorage.getItem("notes")); 36 | } 37 | 38 | notesList.push(getCurrentNote); 39 | localStorage.setItem("notes", JSON.stringify(notesList)); 40 | } 41 | 42 | function addNewNote() { 43 | const extractInputText = inputBox.value.trim(); 44 | if (extractInputText.length <= 0) { 45 | errorMessageText.textContent = 46 | "Input can not be empty ! You must write some note to proceed"; 47 | return false; 48 | } 49 | 50 | console.log(addButton.innerText); 51 | if (addButton.innerText === "Edit Note") { 52 | handleEditCurrentNote( 53 | currentEditedNote.target.previousElementSibling.innerHTML 54 | ); 55 | currentEditedNote.target.previousElementSibling.innerHTML = 56 | extractInputText; 57 | addButton.innerText = "Add Note"; 58 | inputBox.value = ""; 59 | errorMessageText.textContent = '' 60 | } else { 61 | const newNoteItem = createNewNoteItem(extractInputText); 62 | notesListWrapper.appendChild(newNoteItem); 63 | inputBox.value = ""; 64 | errorMessageText.textContent = '' 65 | 66 | saveNotesToStroage(extractInputText); 67 | } 68 | } 69 | 70 | function fetchAllNotes() { 71 | let notesList; 72 | if (localStorage.getItem("notes" === null)) { 73 | notesList = []; 74 | } else { 75 | notesList = JSON.parse(localStorage.getItem("notes")); 76 | 77 | notesList.forEach((noteItem) => { 78 | const extractLi = createNewNoteItem(noteItem); 79 | notesListWrapper.appendChild(extractLi); 80 | }); 81 | } 82 | 83 | console.log(notesList); 84 | } 85 | 86 | function handleEditCurrentNote(currentNote) { 87 | let notes = JSON.parse(localStorage.getItem("notes")); 88 | let index = notes.indexOf(currentNote); 89 | 90 | notes[index] = inputBox.value; 91 | localStorage.setItem("notes", JSON.stringify(notes)); 92 | } 93 | 94 | function handleDeleteNotes(currentNote) { 95 | let notesList; 96 | if (localStorage.getItem("notes") === null) { 97 | notesList = []; 98 | } else { 99 | notesList = JSON.parse(localStorage.getItem("notes")); 100 | } 101 | 102 | let currentNoteText = currentNote.children[0].innerHTML; 103 | let index = notesList.indexOf(currentNoteText); 104 | 105 | notesList.splice(index, 1); 106 | localStorage.setItem("notes", JSON.stringify(notesList)); 107 | } 108 | 109 | function handleEditOrDeleteNote(event) { 110 | console.log(event.target.previousElementSibling, event.target.innerHTML); 111 | 112 | if (event.target.innerHTML === "Delete") { 113 | notesListWrapper.removeChild(event.target.parentElement); 114 | handleDeleteNotes(event.target.parentElement); 115 | 116 | console.log(event.target.parentElement); 117 | } 118 | 119 | if (event.target.innerHTML === "Edit") { 120 | console.log(event.target.previousElementSibling.innerHTML); 121 | inputBox.value = event.target.previousElementSibling.innerHTML; 122 | inputBox.focus(); 123 | addButton.innerText = "Edit Note"; 124 | currentEditedNote = event; 125 | } 126 | } 127 | 128 | document.addEventListener("DOMContentLoaded", fetchAllNotes); 129 | addButton.addEventListener("click", addNewNote); 130 | notesListWrapper.addEventListener("click", handleEditOrDeleteNote); 131 | -------------------------------------------------------------------------------- /24.notes-app/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0px; 3 | padding: 0px; 4 | box-sizing: border-box; 5 | } 6 | 7 | body{ 8 | padding: 15px; 9 | background-color: rgb(79, 0, 216); 10 | } 11 | 12 | h1, p { 13 | color: #fff; 14 | } 15 | 16 | h1 { 17 | margin-bottom: 30px; 18 | } 19 | 20 | .container { 21 | display: flex; 22 | flex-direction: column; 23 | justify-content: center; 24 | align-items: center; 25 | margin-top: 30px; 26 | } 27 | 28 | .input-container { 29 | width: 100%; 30 | max-width: 450px; 31 | padding: 20px; 32 | display: flex; 33 | gap: 15px; 34 | } 35 | 36 | .input-container input { 37 | border: none; 38 | outline: none; 39 | padding: 12px; 40 | border-radius: 8px; 41 | font-size: 16px; 42 | } 43 | 44 | .input-container button { 45 | background-color: #fbff28; 46 | color: #000; 47 | font-size: 18px; 48 | font-weight: bold; 49 | border: 1px solid #000; 50 | cursor: pointer; 51 | padding: 12px 24px; 52 | border-radius: 8px; 53 | } 54 | 55 | ul { 56 | width: 450px; 57 | list-style: none; 58 | } 59 | 60 | ul li { 61 | cursor: pointer; 62 | margin-bottom: 15px; 63 | padding: 6px 12px; 64 | background-color: #f7a604; 65 | border-radius: 8px; 66 | display: flex; 67 | justify-content: center; 68 | align-items: center; 69 | gap: 15px; 70 | } 71 | 72 | ul li p{ 73 | font-size: 20px; 74 | } 75 | 76 | ul li button { 77 | padding: 10px 15px; 78 | background-color: #fbff28; 79 | color: #000; 80 | font-size: 18px; 81 | font-weight: bold; 82 | cursor: pointer; 83 | border-radius: 8px; 84 | border: none; 85 | } 86 | 87 | .deleteBtn { 88 | background-color: rgb(198, 0, 228); 89 | color: #fff; 90 | } -------------------------------------------------------------------------------- /3.star-rating/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Star rating component 7 | 14 | 15 | 16 | 17 |
    18 |

    Star rating component

    19 |
    20 | 21 | 22 | 23 | 24 | 25 |
    26 |
    27 |

    Selected rating value is :

    28 |

    0

    29 |
    30 |
    31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /3.star-rating/main.js: -------------------------------------------------------------------------------- 1 | const stars = document.querySelectorAll(".fa-star-o"); 2 | const selectedRatingValueText = document.querySelector( 3 | ".selected-rating-value" 4 | ); 5 | 6 | let currentTotalSelectedStars = -1; 7 | 8 | stars.forEach((starItem, index) => { 9 | starItem.dataset.rating = index + 1; 10 | starItem.addEventListener("mouseover", handleMouseOver); 11 | starItem.addEventListener("click", handleOnClick); 12 | starItem.addEventListener("mouseleave", handleMouseLeave); 13 | }); 14 | 15 | function handleMouseOver(event) { 16 | const currentRatingValue = event.target.dataset.rating; 17 | if (!currentRatingValue) return; 18 | else handleUpdateRatingState(currentRatingValue); 19 | } 20 | 21 | function handleUpdateRatingState(getCurrentRatingValue) { 22 | for (let i = 0; i < 5; i++) { 23 | if (i < getCurrentRatingValue) { 24 | stars[i].classList.replace("fa-star-o", "fa-star"); 25 | } else { 26 | stars[i].classList.replace("fa-star", "fa-star-o"); 27 | } 28 | } 29 | } 30 | 31 | function handleOnClick(event){ 32 | const currentRatingValue = event.target.dataset.rating; 33 | currentTotalSelectedStars = currentRatingValue; 34 | handleUpdateRatingState(currentTotalSelectedStars) 35 | selectedRatingValueText.textContent = currentTotalSelectedStars 36 | } 37 | 38 | function handleMouseLeave(){ 39 | handleUpdateRatingState(currentTotalSelectedStars) 40 | } 41 | -------------------------------------------------------------------------------- /3.star-rating/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 15px; 9 | text-align: center; 10 | } 11 | 12 | .container{ 13 | position: absolute; 14 | width: 100%; 15 | top: 50%; 16 | left: 50%; 17 | transform: translate(-50%,-50%); 18 | } 19 | 20 | .star-rating-container{ 21 | display: flex; 22 | justify-content: center; 23 | align-items: center; 24 | margin-top: 30px; 25 | margin-bottom: 30px; 26 | } 27 | 28 | .fa-star-o::before { 29 | content: '\f006'; 30 | font-size: 50px; 31 | } 32 | 33 | .selected-rating-container{ 34 | display: flex; 35 | gap: 10px; 36 | justify-content: center; 37 | } 38 | 39 | .selected-rating-container p{ 40 | font-size: 20px; 41 | font-weight: bold; 42 | } 43 | 44 | .fa-star:hover { 45 | cursor: pointer; 46 | } 47 | 48 | .fa-star::before { 49 | content: '\f005'; 50 | color: rgb(243, 243, 86); 51 | font-size: 50px; 52 | } -------------------------------------------------------------------------------- /4.api-call/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Api Call Example 7 | 8 | 9 | 10 |
    11 |

    API Call Example

    12 |
    13 | 14 |
    15 | 16 | 17 | -------------------------------------------------------------------------------- /4.api-call/main.js: -------------------------------------------------------------------------------- 1 | const postsListContainer = document.querySelector(".posts-list-container"); 2 | 3 | //fetch using XHR 4 | 5 | function fetchUsingXHR() { 6 | const xhr = new XMLHttpRequest(); 7 | xhr.open("GET", "https://jsonplaceholder.typicode.com/posts"); 8 | xhr.responseType = "json"; 9 | xhr.send(); 10 | 11 | xhr.onload = () => { 12 | if (xhr.status === 200) { 13 | displayResults(xhr.response); 14 | } else { 15 | console.log("Some Error ocurred"); 16 | } 17 | }; 18 | } 19 | 20 | function fetchUsingFetchMethod() { 21 | const fetchRequest = fetch("https://jsonplaceholder.typicode.com/posts", { 22 | method: "GET", 23 | }); 24 | 25 | fetchRequest 26 | .then((response) => response.json()) 27 | .then((result) => displayResults(result)) 28 | .catch((e) => console.log(e)); 29 | } 30 | 31 | async function fetchUsingAsynCAwaitMethod(){ 32 | 33 | const response = await fetch("https://jsonplaceholder.typicode.com/posts", { 34 | method: "GET", 35 | }); 36 | 37 | const result = await response.json(); 38 | displayResults(result) 39 | 40 | console.log('===================================='); 41 | console.log(result); 42 | console.log('===================================='); 43 | } 44 | 45 | function helperMethod(method, url){ 46 | const promise = new Promise((resolve,reject)=> { 47 | const xhr = new XMLHttpRequest(); 48 | xhr.open(method,url); 49 | xhr.responseType = 'json'; 50 | xhr.send(); 51 | 52 | xhr.onload = ()=> { 53 | if(xhr.status === 200){ 54 | resolve(xhr.response) 55 | } else { 56 | reject(xhr.response) 57 | } 58 | } 59 | }) 60 | 61 | return promise; 62 | } 63 | 64 | async function fetchUsingXHRAndAsyncAwait(){ 65 | 66 | const response = await helperMethod('GET', "https://jsonplaceholder.typicode.com/posts"); 67 | displayResults(response) 68 | console.log('===================================='); 69 | console.log(response); 70 | console.log('===================================='); 71 | } 72 | 73 | function displayResults(posts) { 74 | postsListContainer.innerHTML = posts 75 | .map( 76 | (postItem) => ` 77 |
    78 |

    ${postItem.title}

    79 |

    ${postItem.body}

    80 |
    81 | ` 82 | ) 83 | .join(" "); 84 | } 85 | 86 | // fetchUsingXHR(); 87 | //fetchUsingFetchMethod(); 88 | //fetchUsingAsynCAwaitMethod(); 89 | fetchUsingXHRAndAsyncAwait() 90 | -------------------------------------------------------------------------------- /4.api-call/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 15px; 9 | } 10 | 11 | h1 { 12 | font-size: 40px; 13 | margin-bottom: 30px; 14 | } 15 | 16 | .posts-list-container{ 17 | display: flex; 18 | flex-direction: column; 19 | gap: 20px; 20 | } 21 | 22 | .post-item { 23 | display: flex; 24 | flex-direction: column; 25 | gap: 10px; 26 | border: 1px solid rgb(0, 255, 98); 27 | padding: 10px; 28 | background-color: rgb(86, 14, 164); 29 | } 30 | 31 | .post-item h3 { 32 | color: #fff; 33 | font-size: 20px; 34 | } 35 | 36 | .post-item p{ 37 | font-size: 18px; 38 | color: #fff; 39 | } -------------------------------------------------------------------------------- /5.Image-Slider/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Image Slider Example 7 | 8 | 9 | 10 |

    Image Slider Example

    11 |
    12 | 13 |
    14 | 15 |
    16 | 17 |
    18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /5.Image-Slider/main.js: -------------------------------------------------------------------------------- 1 | const slider = document.querySelector(".slider"); 2 | const dotsContainer = document.querySelector(".dots-container"); 3 | 4 | async function fetchListOfImages() { 5 | try { 6 | const response = await fetch( 7 | "https://picsum.photos/v2/list?page=1&limit=10", 8 | { 9 | method: "GET", 10 | } 11 | ); 12 | 13 | const imagesList = await response.json(); 14 | if (imagesList && imagesList.length > 0) displayImages(imagesList); 15 | } catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | 20 | function displayImages(getImagesList) { 21 | slider.innerHTML = getImagesList 22 | .map( 23 | (item) => ` 24 |
    25 | ${item.id} 26 |
    27 | ` 28 | ) 29 | .join(" "); 30 | 31 | dotsContainer.innerHTML = getImagesList 32 | .map( 33 | (item, index) => ` 34 | 35 | ` 36 | ) 37 | .join(" "); 38 | } 39 | 40 | fetchListOfImages(); 41 | 42 | // slider functionality begins 43 | 44 | setTimeout(() => { 45 | const slides = document.querySelectorAll(".slide"); 46 | const prevBtn = document.querySelector(".prev"); 47 | const nextBtn = document.querySelector(".next"); 48 | let currentSlide = 0; 49 | 50 | function activeDot(slide) { 51 | document 52 | .querySelectorAll(".dot") 53 | .forEach((dotItem) => dotItem.classList.remove("active")); 54 | document 55 | .querySelector(`.dot[data-slide="${slide}"]`) 56 | .classList.add("active"); 57 | } 58 | 59 | function changeCurrentSlide(currentSlide) { 60 | slides.forEach( 61 | (slideItem, index) => 62 | (slideItem.style.transform = `translateX(${ 63 | 100 * (index - currentSlide) 64 | }%)`) 65 | ); 66 | } 67 | 68 | changeCurrentSlide(currentSlide) 69 | 70 | nextBtn.addEventListener("click", () => { 71 | currentSlide++; 72 | 73 | if (slides.length - 1 < currentSlide) { 74 | currentSlide = 0; 75 | } 76 | 77 | changeCurrentSlide(currentSlide); 78 | activeDot(currentSlide); 79 | }); 80 | 81 | prevBtn.addEventListener("click", () => { 82 | currentSlide--; 83 | 84 | if (0 > currentSlide) { 85 | currentSlide = slides.length - 1; 86 | } 87 | 88 | changeCurrentSlide(currentSlide); 89 | activeDot(currentSlide); 90 | }); 91 | 92 | dotsContainer.addEventListener("click", (event) => { 93 | if(event.target.classList.contains('dot')){ 94 | const currentSlide = event.target.dataset.slide 95 | changeCurrentSlide(currentSlide) 96 | activeDot(currentSlide) 97 | } 98 | }); 99 | }, 1000); 100 | -------------------------------------------------------------------------------- /5.Image-Slider/style.css: -------------------------------------------------------------------------------- 1 | 2 | *{ 3 | margin: 0px; 4 | box-sizing: border-box; 5 | padding: 0px; 6 | } 7 | 8 | html { 9 | font-size: 1rem; 10 | } 11 | 12 | body { 13 | width: 100%; 14 | height: 100%; 15 | background-color: rgb(136, 0, 255); 16 | padding: 15px; 17 | } 18 | 19 | h1 { 20 | color: rgb(255, 242, 0); 21 | margin-bottom: 30px; 22 | } 23 | 24 | .slider { 25 | position: relative; 26 | max-width: 45rem; 27 | height: 25rem; 28 | margin: 0 auto; 29 | overflow: hidden; 30 | } 31 | 32 | .slide{ 33 | position: absolute; 34 | top: 0; 35 | width: 100%; 36 | height: 25rem; 37 | display: flex; 38 | justify-content: center; 39 | align-items: center; 40 | } 41 | 42 | .slide img{ 43 | width: 100%; 44 | height: 100%; 45 | object-fit: cover; 46 | } 47 | 48 | .bottom-container { 49 | display: flex; 50 | justify-content: space-between; 51 | padding: 0px 20px; 52 | margin-top: 30px; 53 | } 54 | 55 | .bottom-container button { 56 | padding: 10px 30px; 57 | background-color: rgb(255, 242, 0); 58 | border: none; 59 | font-size: 18px; 60 | letter-spacing: 2px; 61 | cursor: pointer; 62 | } 63 | 64 | .dots-container { 65 | display: flex; 66 | gap: 10px; 67 | justify-content: center; 68 | align-items: center; 69 | } 70 | 71 | .dots-container .dot{ 72 | width: 40px; 73 | height: 15px; 74 | border-radius: 8px; 75 | background-color: #ffffff; 76 | cursor: pointer; 77 | } 78 | 79 | .dots-container .dot.active { 80 | background-color: #000; 81 | } -------------------------------------------------------------------------------- /6.load-more-button/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Load More Button API 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /6.load-more-button/main.js: -------------------------------------------------------------------------------- 1 | const productsContainer = document.querySelector(".products-container"); 2 | const loadMoreBtn = document.querySelector(".load-more-btn"); 3 | 4 | let currentStep = 0; 5 | 6 | async function fetchListOfProducts(getCurrentStep) { 7 | try { 8 | const response = await fetch( 9 | `https://dummyjson.com/products?limit=10&skip=${ 10 | getCurrentStep === 0 ? 0 : getCurrentStep * 10 11 | }`, 12 | { 13 | method: "GET", 14 | } 15 | ); 16 | 17 | const result = await response.json(); 18 | console.log(result); 19 | if (result && result.products) displayProducts(result.products); 20 | } catch (e) { 21 | console.log(e); 22 | } 23 | } 24 | 25 | function displayProducts(productList) { 26 | console.log(productList); 27 | 28 | productList.forEach((productItem) => { 29 | const productItemWrapper = document.createElement("div"); 30 | const productTitle = document.createElement("p"); 31 | const productThumbnail = document.createElement("img"); 32 | const productDescription = document.createElement("p"); 33 | const productPrice = document.createElement("p"); 34 | 35 | productTitle.textContent = productItem.title; 36 | productDescription.textContent = productItem.description; 37 | productThumbnail.src = productItem.thumbnail; 38 | productPrice.textContent = productItem.price; 39 | 40 | productItemWrapper.classList.add("product-item-wrapper"); 41 | productTitle.classList.add("product-title"); 42 | productThumbnail.classList.add("product-img"); 43 | productPrice.classList.add("product-price"); 44 | productDescription.classList.add("product-desc"); 45 | 46 | productItemWrapper.appendChild(productThumbnail); 47 | productItemWrapper.appendChild(productTitle); 48 | productItemWrapper.appendChild(productPrice); 49 | productItemWrapper.appendChild(productDescription); 50 | 51 | productsContainer.appendChild(productItemWrapper); 52 | }); 53 | 54 | if (productsContainer.children.length === 100) { 55 | loadMoreBtn.setAttribute("disabled", "true"); 56 | } 57 | 58 | console.log(productsContainer.children.length); 59 | } 60 | 61 | fetchListOfProducts(currentStep); 62 | 63 | loadMoreBtn.addEventListener("click", () => { 64 | fetchListOfProducts((currentStep += 1)); 65 | }); 66 | -------------------------------------------------------------------------------- /6.load-more-button/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | padding: 15px; 9 | line-height: 1.5; 10 | } 11 | 12 | .products-container { 13 | display: flex; 14 | flex-wrap: wrap; 15 | gap: 10px; 16 | } 17 | 18 | .products-container .product-item-wrapper{ 19 | width: 32%; 20 | height: 400px; 21 | } 22 | 23 | .product-item-wrapper img { 24 | width: 100%; 25 | height: 200px; 26 | object-fit: cover; 27 | } 28 | 29 | .product-item-wrapper{ 30 | padding: 15px; 31 | border: 2px solid rgb(220, 220, 20); 32 | background-color: rgb(212, 0, 255); 33 | } 34 | 35 | .product-item-wrapper .product-title{ 36 | font-size: 20px; 37 | font-weight: bold; 38 | color: #fff; 39 | } 40 | 41 | .product-item-wrapper .product-price{ 42 | font-size: 30px; 43 | font-weight: bolder; 44 | color: #fff; 45 | } 46 | 47 | .product-item-wrapper .product-desc{ 48 | width: 80%; 49 | overflow: hidden; 50 | text-overflow: ellipsis; 51 | white-space: nowrap; 52 | font-size: 18px; 53 | color: #060606; 54 | font-weight: bold; 55 | } 56 | 57 | .load-more-btn{ 58 | padding: 10px 30px; 59 | border: none; 60 | background-color: rgb(255, 255, 119); 61 | font-size: 25px; 62 | cursor: pointer; 63 | margin-top: 30px; 64 | 65 | } 66 | 67 | .load-more-btn:disabled { 68 | cursor: not-allowed; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /7.light-dark-mode/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Light and Dark Mode Toggle 7 | 8 | 9 | 10 |
    11 |

    Light and Dark Toggle

    12 | 13 |
    14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /7.light-dark-mode/main.js: -------------------------------------------------------------------------------- 1 | const changeThemeBtn = document.querySelector(".change-theme-btn"); 2 | const body = document.querySelector("body"); 3 | 4 | // changeThemeBtn.addEventListener('click', ()=> { 5 | // if(body.classList.contains('light')){ 6 | // body.classList.remove('light') 7 | // body.classList.add('dark') 8 | 9 | // } else { 10 | // body.classList.remove('dark') 11 | // body.classList.add('light') 12 | // } 13 | 14 | // if(changeThemeBtn.classList.contains('light')){ 15 | // changeThemeBtn.classList.remove('light') 16 | // changeThemeBtn.classList.add('dark') 17 | 18 | // } else { 19 | // changeThemeBtn.classList.remove('dark') 20 | // changeThemeBtn.classList.add('light') 21 | // } 22 | 23 | // }) 24 | 25 | changeThemeBtn.addEventListener("click", () => { 26 | console.log(body.getAttribute("data-theme")); 27 | if (body.getAttribute("data-theme") === "dark") { 28 | body.setAttribute("data-theme", 'blue'); 29 | } else { 30 | body.setAttribute("data-theme", "dark"); 31 | } 32 | 33 | if (changeThemeBtn.getAttribute("data-theme") === "dark") { 34 | changeThemeBtn.setAttribute("data-theme", 'blue'); 35 | } else { 36 | changeThemeBtn.setAttribute("data-theme", "dark"); 37 | } 38 | // changeThemeBtn.setAttribute("data-theme", "dark"); 39 | }); 40 | -------------------------------------------------------------------------------- /7.light-dark-mode/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | :root { 8 | --bg-color : #000; 9 | --text-color : #fff; 10 | --btn-bg-color : #f6ee03; 11 | --btn-text-color : #000; 12 | } 13 | 14 | [data-theme = "dark"]{ 15 | --bg-color : #fff; 16 | --text-color : #000; 17 | --btn-bg-color : #000; 18 | --btn-text-color : #f6ee03; 19 | } 20 | 21 | [data-theme = "blue"]{ 22 | --bg-color : #0430f6; 23 | --text-color : #b50c0c; 24 | --btn-bg-color : #7b016f; 25 | --btn-text-color : #f6ad03; 26 | } 27 | 28 | body { 29 | background-color: var(--bg-color); 30 | } 31 | 32 | .container .change-theme-btn{ 33 | background-color: var(--btn-bg-color) ; 34 | color: var(--btn-text-color); 35 | padding: 12px 20px; 36 | border: none; 37 | cursor: pointer; 38 | font-size: 22px; 39 | } 40 | 41 | /* body.light { 42 | background-color: rgba(255, 0, 234, 0.867); 43 | } 44 | 45 | body.dark { 46 | background-color: rgb(255, 128, 0); 47 | } */ 48 | 49 | .container{ 50 | width: 100%; 51 | min-height: 100vh; 52 | display: flex; 53 | justify-content: center; 54 | align-items: center; 55 | flex-direction: column; 56 | gap: 25px; 57 | } 58 | 59 | .container h1 { 60 | color: #fff; 61 | } 62 | 63 | /* .container .change-theme-btn.light { 64 | padding: 12px 20px; 65 | border: none; 66 | background-color: #000; 67 | font-size: 20px; 68 | cursor: pointer; 69 | color: #fff; 70 | } 71 | 72 | .container .change-theme-btn.dark{ 73 | color: #000; 74 | background-color: #fff; 75 | padding: 12px 20px; 76 | border: none; 77 | font-size: 20px; 78 | cursor: pointer; 79 | } */ -------------------------------------------------------------------------------- /8.random-quote-generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Random Quote Generator 7 | 8 | 9 | 10 |
    11 |

    Random Quote Generator

    12 | 13 |

    Loading Data ! Please wait.

    14 |
    15 |
    16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /8.random-quote-generator/main.js: -------------------------------------------------------------------------------- 1 | const quoteWrapper = document.querySelector(".quote-wrapper"); 2 | const refreshButton = document.querySelector(".refresh-button"); 3 | const loaderText = document.querySelector(".loader"); 4 | 5 | function showLoader() { 6 | loaderText.classList.add("show"); 7 | quoteWrapper.classList.add("hide"); 8 | } 9 | 10 | function removeLoader() { 11 | loaderText.classList.remove("show"); 12 | quoteWrapper.classList.remove("hide"); 13 | } 14 | 15 | function fetchRandomQuote() { 16 | showLoader() 17 | fetch("https://api.quotable.io/quotes/random") 18 | .then((response) => response.json()) 19 | .then((result) => { 20 | if(result){ 21 | removeLoader() 22 | displayQuote(result[0]) 23 | } 24 | }) 25 | .catch((e) => console.log(e)); 26 | } 27 | 28 | function displayQuote(getQuote) { 29 | console.log(getQuote); 30 | quoteWrapper.innerHTML = ` 31 |
    32 |

    ${getQuote.author}

    33 |

    ${getQuote.content}

    34 |

    ${getQuote.dateAdded}

    35 |

    ${getQuote.tags[0]}

    36 |
    37 | `; 38 | } 39 | 40 | fetchRandomQuote(); 41 | 42 | refreshButton.addEventListener("click", () => { 43 | fetchRandomQuote(); 44 | }); 45 | -------------------------------------------------------------------------------- /8.random-quote-generator/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | .container{ 8 | width: 100%; 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | flex-direction: column; 13 | gap: 15px; 14 | min-height: 100vh; 15 | } 16 | 17 | .quote-wrapper .quote-item{ 18 | display: flex; 19 | flex-direction: column; 20 | gap: 10px; 21 | border: 2px solid red; 22 | padding: 20px; 23 | background-color: rgb(74, 1, 119); 24 | } 25 | 26 | .refresh-button { 27 | padding: 12px 20px; 28 | background-color: yellow; 29 | font-size: 20px; 30 | font-weight: bold; 31 | border: none; 32 | cursor: pointer; 33 | 34 | } 35 | 36 | .quote-wrapper .quote-item p{ 37 | color: #fff; 38 | font-size: 18px; 39 | } 40 | 41 | .loader{ 42 | font-size: 30px; 43 | font-weight: bolder; 44 | display: none; 45 | } 46 | 47 | .loader.show{ 48 | display: block; 49 | } 50 | 51 | .quote-wrapper.hide { 52 | display: none; 53 | } -------------------------------------------------------------------------------- /9.tabs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Custom Tabs 7 | 8 | 9 | 10 |

    Custom Tabs

    11 |
    12 |
    13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 |

    This is the Home Section

    21 |

    This is the Services Section

    22 |

    This is the Projects Section

    23 |

    This is the Portfolio Section

    24 |

    This is the Contact Section

    25 | 26 |
    27 |
    28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /9.tabs/main.js: -------------------------------------------------------------------------------- 1 | const tabContainer = document.querySelector(".container"); 2 | const tabButtons = document.querySelectorAll(".tab-button"); 3 | const tabContents = document.querySelectorAll(".content"); 4 | 5 | tabContainer.addEventListener("click", (event) => { 6 | console.log(event.target.dataset); 7 | const currentId = event.target.dataset.id; 8 | 9 | if (currentId) { 10 | tabButtons.forEach((btn) => { 11 | btn.classList.remove("active"); 12 | }); 13 | 14 | event.target.classList.add("active"); 15 | 16 | tabContents.forEach((content) => { 17 | content.classList.remove("active"); 18 | }); 19 | 20 | const currentElement = document.getElementById(currentId); 21 | currentElement.classList.add("active"); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /9.tabs/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body{ 8 | text-align: center; 9 | background-color: #d4dbea; 10 | } 11 | 12 | h1{ 13 | font-size: 50px; 14 | color: rgb(115, 0, 255); 15 | margin-bottom: 40px; 16 | } 17 | 18 | .button-wrapper{ 19 | display: flex; 20 | justify-content: center; 21 | align-items: center; 22 | gap: 15px; 23 | } 24 | 25 | .button-wrapper button { 26 | border: none; 27 | padding: 12px 20px; 28 | background-color: #073dab; 29 | color: #fff; 30 | font-weight: bold; 31 | letter-spacing: 3px; 32 | font-size: 18px; 33 | cursor: pointer; 34 | } 35 | 36 | .button-wrapper button.active { 37 | background-color: #000; 38 | } 39 | 40 | .content{ 41 | display: none; 42 | font-size: 20px; 43 | font-weight: bolder; 44 | margin-top: 50px; 45 | } 46 | 47 | .content.active { 48 | display: block; 49 | } 50 | --------------------------------------------------------------------------------