diff --git a/README.md b/README.md index 0f57702..af383c5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -# HTML-CSS-JavaScript-projects-for-beginners - -This is the source code of the YouTube video (10 projects) https://www.youtube.com/watch?v=ePzOFu2xXUQ. - -Part 2 (16 projects) : https://youtu.be/EWv2jnhZErc - -NEW HTML CSS JavaScript Projects Interesting HTML CSS JavaScript projects Learn HTML, CSS, and JavaScript 2021 to create modern websites. Fun learning HTML, CSS, and JavaScript! - -I'm Sahand, a web developer in computer science. I've been doing this for over a decade. This course was created to share my knowledge and experience with you. Build simple websites using HTML, CSS, and JavaScript. Responsive web design employs HTML, CSS, and JavaScript. This is a skill you'll learn in this course. This new course teaches students how to install Visual Studio Code and its extensions. Then we start from scratch with each project. After finishing HTML, it's on to CSS and JavaScript. Building in HTML, CSS, or JavaScript is fine. This guide explains HTML, CSS, and JavaScript syntax. - -Every project is started from scratch and finished without using copied code. Then they are used on the project to ensure everyone understands. This program's exciting project-based curriculum includes building modern, super cool, and responsive websites! Let's get started learning HTML, CSS, and JavaScript. - -Contact me if you have any questions through my twitter: @codewithsahand. +# HTML CSS JavaScript Projects + +This is the source code of the website: 100 HTML CSS JavaScript Projects +
+ Visit 100jsprojects.com to preview the projects. + +
+
+

About

+

Hi there! I'm Sahand, a web developer with over a decade of experience. This course, "HTML CSS JavaScript Projects," was created to share my knowledge and experience with you. In this course, you'll learn how to build simple, responsive websites using HTML, CSS, and JavaScript.

+

In this course, you'll learn how to install Visual Studio Code and its extensions, and then we'll start from scratch with each project. After finishing HTML, we'll move on to CSS and JavaScript. Building in HTML, CSS, or JavaScript is fine, and this guide will explain HTML, CSS, and JavaScript syntax.

+

Each project in this course is started from scratch and finished without using copied code. Then, we'll go over the code together to ensure that everyone understands. This program's exciting project-based curriculum includes building modern, super cool, and responsive websites!

+

If you have any questions, please feel free to contact me through my email: codewithsahand@gmail.com

+ Visit my website +
diff --git a/projects/Navbar-project/index.html b/projects/Navbar-project/index.html deleted file mode 100644 index 4975da5..0000000 --- a/projects/Navbar-project/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - Sahand Ghavidel - - - - - - - - \ No newline at end of file diff --git a/projects/age-calculator/index.html b/projects/age-calculator/index.html new file mode 100644 index 0000000..7ef5c27 --- /dev/null +++ b/projects/age-calculator/index.html @@ -0,0 +1,23 @@ + + + + + + + Age Calculator + + + +
+

Age Calculator

+
+ + + +

Your age is 21 years old

+
+
+ + + + \ No newline at end of file diff --git a/projects/age-calculator/index.js b/projects/age-calculator/index.js new file mode 100644 index 0000000..b2888ee --- /dev/null +++ b/projects/age-calculator/index.js @@ -0,0 +1,31 @@ +const btnEl = document.getElementById("btn"); +const birthdayEl = document.getElementById("birthday"); +const resultEl = document.getElementById("result"); + +function calculateAge() { + const birthdayValue = birthdayEl.value; + if (birthdayValue === "") { + alert("Please enter your birthday"); + } else { + const age = getAge(birthdayValue); + resultEl.innerText = `Your age is ${age} ${age > 1 ? "years" : "year"} old`; + } +} + +function getAge(birthdayValue) { + const currentDate = new Date(); + const birthdayDate = new Date(birthdayValue); + let age = currentDate.getFullYear() - birthdayDate.getFullYear(); + const month = currentDate.getMonth() - birthdayDate.getMonth(); + + if ( + month < 0 || + (month === 0 && currentDate.getDate() < birthdayDate.getDate()) + ) { + age--; + } + + return age; +} + +btnEl.addEventListener("click", calculateAge); diff --git a/projects/age-calculator/style.css b/projects/age-calculator/style.css new file mode 100644 index 0000000..0229675 --- /dev/null +++ b/projects/age-calculator/style.css @@ -0,0 +1,63 @@ +body { + margin: 0; + padding: 20px; + font-family: "Montserrat", sans-serif; + background-color: #f7f7f7; +} + +.container { + background-color: white; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + padding: 20px; + max-width: 600px; + margin: 0 auto; + border-radius: 5px; + margin-top: 50px; +} + +h1 { + font-size: 36px; + text-align: center; + margin-top: 0; + margin-bottom: 20px; +} + +.form { + display: flex; + flex-direction: column; + align-items: center; +} + +label { + font-weight: bold; + margin-bottom: 10px; +} + +input { + padding: 8px; + border: 1px solid #ccc; + border-radius: 5px; + width: 100%; + max-width: 300px; +} + +button { + background-color: #007bff; + color: white; + border: none; + padding: 10px 20px; + border-radius: 5px; + margin-top: 10px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #0062cc; +} + +#result { + margin-top: 20px; + font-size: 24px; + font-weight: bold; +} diff --git a/projects/amine-pics-generator/index.html b/projects/amine-pics-generator/index.html new file mode 100644 index 0000000..0cb6e43 --- /dev/null +++ b/projects/amine-pics-generator/index.html @@ -0,0 +1,21 @@ + + + + + + + Anime Pics Generator + + + +
+

Anime Pics Generator

+ +
+ +

Anime Name

+
+
+ + + \ No newline at end of file diff --git a/projects/amine-pics-generator/index.js b/projects/amine-pics-generator/index.js new file mode 100644 index 0000000..ab0dfe5 --- /dev/null +++ b/projects/amine-pics-generator/index.js @@ -0,0 +1,25 @@ +const btnEl = document.getElementById("btn"); +const animeContainerEl = document.querySelector(".anime-container"); +const animeImgEl = document.querySelector(".anime-img"); +const amineNameEl = document.querySelector(".anime-name"); + +btnEl.addEventListener("click", async function () { + try { + btnEl.disabled = true; + btnEl.innerText = "Loading..."; + amineNameEl.innerText = "Updating..."; + animeImgEl.src = "spinner.svg"; + const response = await fetch("https://api.catboys.com/img"); + const data = await response.json(); + btnEl.disabled = false; + btnEl.innerText = "Get Anime"; + animeContainerEl.style.display = "block"; + animeImgEl.src = data.url; + amineNameEl.innerText = data.artist; + } catch (error) { + console.log(error); + btnEl.disabled = false; + btnEl.innerText = "Get Anime"; + amineNameEl.innerText = "An error happened, please try again"; + } +}); diff --git a/projects/amine-pics-generator/spinner.svg b/projects/amine-pics-generator/spinner.svg new file mode 100644 index 0000000..fd9b80a --- /dev/null +++ b/projects/amine-pics-generator/spinner.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/projects/amine-pics-generator/style.css b/projects/amine-pics-generator/style.css new file mode 100644 index 0000000..077c804 --- /dev/null +++ b/projects/amine-pics-generator/style.css @@ -0,0 +1,56 @@ +body{ + margin: 0; + background: linear-gradient(to right, lightblue, yellow); + display: flex; + height: 100vh; + justify-content: center; + align-items: center; + font-family: 'Courier New', Courier, monospace; +} + +.container{ + background: aliceblue; + border-radius: 10px; + box-shadow: 0 10px 20px rgba(0,0,0,0.3); + text-align: center; + padding: 10px; + width: 450px; + margin: 5px; +} + +.btn{ + background-color: green; + color: aliceblue; + padding: 10px 30px; + font-size: 16px; + margin-bottom: 30px; + border-radius: 6px; + cursor: pointer; + +} + +.btn:disabled{ + background-color: gray; + cursor: not-allowed; +} + +.anime-img{ + height: 300px; + width: 300px; + border-radius: 50%; + border: 3px solid green; +} + +.anime-name{ + margin: 20px; + background-color: green; + color: aliceblue; + padding: 10px; + border-radius: 6px; + font-size: 17px; + font-weight: 600; +} + +.anime-container{ + display: none; +} \ No newline at end of file diff --git a/projects/background-video-project/background-video.mp4 b/projects/background-video/background-video.mp4 similarity index 100% rename from projects/background-video-project/background-video.mp4 rename to projects/background-video/background-video.mp4 diff --git a/projects/background-video-project/index.html b/projects/background-video/index.html similarity index 100% rename from projects/background-video-project/index.html rename to projects/background-video/index.html diff --git a/projects/background-video-project/index.js b/projects/background-video/index.js similarity index 100% rename from projects/background-video-project/index.js rename to projects/background-video/index.js diff --git a/projects/background-video-project/preloader.gif b/projects/background-video/preloader.gif similarity index 100% rename from projects/background-video-project/preloader.gif rename to projects/background-video/preloader.gif diff --git a/projects/background-video-project/styles.css b/projects/background-video/styles.css similarity index 100% rename from projects/background-video-project/styles.css rename to projects/background-video/styles.css diff --git a/projects/basic-calculator/index.html b/projects/basic-calculator/index.html new file mode 100644 index 0000000..432ea60 --- /dev/null +++ b/projects/basic-calculator/index.html @@ -0,0 +1,35 @@ + + + + + + + Basic Calculator + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+
+ + + \ No newline at end of file diff --git a/projects/basic-calculator/index.js b/projects/basic-calculator/index.js new file mode 100644 index 0000000..40fa6e8 --- /dev/null +++ b/projects/basic-calculator/index.js @@ -0,0 +1,29 @@ +const buttonsEl = document.querySelectorAll("button"); + +const inputFieldEl = document.getElementById("result"); + +for (let i = 0; i < buttonsEl.length; i++) { + buttonsEl[i].addEventListener("click", () => { + const buttonValue = buttonsEl[i].textContent; + if (buttonValue === "C") { + clearResult(); + } else if (buttonValue === "=") { + calculateResult(); + } else { + appendValue(buttonValue); + } + }); +} + +function clearResult() { + inputFieldEl.value = ""; +} + +function calculateResult() { + inputFieldEl.value = eval(inputFieldEl.value); +} + +function appendValue(buttonValue) { + inputFieldEl.value += buttonValue; + // inputFieldEl.value = inputFieldEl.value + buttonValue; +} diff --git a/projects/basic-calculator/style.css b/projects/basic-calculator/style.css new file mode 100644 index 0000000..baf4abd --- /dev/null +++ b/projects/basic-calculator/style.css @@ -0,0 +1,68 @@ +* { + box-sizing: border-box; + margin: 0; +} + +.calculator { + background-color: #f2f2f2; + padding: 20px; + max-width: 400px; + margin: 0 auto; + border: solid 1px #ccc; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); + border-radius: 5px; + margin-top: 40px; +} + +#result{ + width: 100%; + padding: 10px; + font-size: 24px; + border: none; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) inset; + border-radius: 5px; +} + +.buttons{ + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-gap: 10px; + margin-top: 20px; +} + +button{ + padding: 10px; + font-size: 24px; + border: none; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; + +} + +button:hover{ + background-color: #ddd; +} + +.clear{ + background-color: #ff4136; + color: #fff; +} + +.number, .decimal{ + background-color: #fff; + color: #333; + +} + +.operator{ + background-color: #0074d9; + color: #fff; +} + +.equals{ + background-color: #01ff70; + grid-row: span 3; + color: #fff; +} \ No newline at end of file diff --git a/projects/bmi-calculator/index.html b/projects/bmi-calculator/index.html new file mode 100644 index 0000000..fd167fe --- /dev/null +++ b/projects/bmi-calculator/index.html @@ -0,0 +1,23 @@ + + + + + + + BMI Calculator + + + +
+

Body Mass Index (BMI) Calculator

+ Your Height (cm): + + Your Weight (kg): + + + +

Weight Condition:

+
+ + + \ No newline at end of file diff --git a/projects/bmi-calculator/index.js b/projects/bmi-calculator/index.js new file mode 100644 index 0000000..b798ee0 --- /dev/null +++ b/projects/bmi-calculator/index.js @@ -0,0 +1,24 @@ +const btnEl = document.getElementById("btn"); +const bmiInputEl = document.getElementById("bmi-result"); +const weightConditionEl = document.getElementById("weight-condition"); + +function calculateBMI() { + const heightValue = document.getElementById("height").value / 100; + const weightValue = document.getElementById("weight").value; + + const bmiValue = weightValue / (heightValue * heightValue); + + bmiInputEl.value = bmiValue; + + if (bmiValue < 18.5) { + weightConditionEl.innerText = "Under weight"; + } else if (bmiValue >= 18.5 && bmiValue <= 24.9) { + weightConditionEl.innerText = "Normal weight"; + } else if (bmiValue >= 25 && bmiValue <= 29.9) { + weightConditionEl.innerText = "Overweight"; + } else if (bmiValue >= 30) { + weightConditionEl.innerText = "Obesity"; + } +} + +btnEl.addEventListener("click", calculateBMI); diff --git a/projects/bmi-calculator/style.css b/projects/bmi-calculator/style.css new file mode 100644 index 0000000..7d94328 --- /dev/null +++ b/projects/bmi-calculator/style.css @@ -0,0 +1,52 @@ +body{ + margin: 0; + background: linear-gradient(to left bottom, lightgreen, lightblue); + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + font-family: 'Courier New', Courier, monospace; +} + +.container{ + background: rgba(255,255,255, .3); + padding: 20px; + display: flex; + flex-direction: column; + border-radius: 5px; + box-shadow: 0 10px 10px rgba(0,0,0,.3); + margin: 5px; +} + +.heading{ + font-size: 30px; +} + +.input{ + padding: 10px 20px; + font-size: 18px; + background: rgba(255,255,255, .4); + border-color: rgba(255,255,255, .5); + margin: 10px; +} + +.btn{ + background-color: lightgreen; + border: none; + padding: 10px 20px; + border-radius: 5px; + margin: 10px; + font-size: 20px; + box-shadow: 0 0 4px rgba(0,0,0,.3); + cursor: pointer; +} + +.btn:hover{ + box-shadow: 0 0 8px rgba(0,0,0,.3); + transition: all 300ms ease; +} + +.info-text{ + font-size: 20px; + font-weight: 500; +} \ No newline at end of file diff --git a/projects/currency-converter/index.html b/projects/currency-converter/index.html new file mode 100644 index 0000000..c3bc553 --- /dev/null +++ b/projects/currency-converter/index.html @@ -0,0 +1,41 @@ + + + + + + + Currency Converter + + + +
+

Currency Converter

+
+ + +
+
+ + +
+

1 USD = 138.5802 JPY

+
+ + + \ No newline at end of file diff --git a/projects/currency-converter/index.js b/projects/currency-converter/index.js new file mode 100644 index 0000000..7514ce1 --- /dev/null +++ b/projects/currency-converter/index.js @@ -0,0 +1,33 @@ +const currencyFirstEl = document.getElementById("currency-first"); + +const worthFirstEl = document.getElementById("worth-first"); + +const currencySecondEl = document.getElementById("currency-second"); + +const worthSecondEl = document.getElementById("worth-second"); + +const exchangeRateEl = document.getElementById("exchange-rate"); + +updateRate() + +function updateRate() { + fetch( + `https://v6.exchangerate-api.com/v6/5f9d1c87f7250159c9c9b17d/latest/${currencyFirstEl.value}` + ) + .then((res) => res.json()) + .then((data) => { + const rate = data.conversion_rates[currencySecondEl.value]; + console.log(rate); + exchangeRateEl.innerText = `1 ${currencyFirstEl.value} = ${ + rate + " " + currencySecondEl.value + }`; + + worthSecondEl.value = (worthFirstEl.value * rate).toFixed(2) + }); +} + +currencyFirstEl.addEventListener("change", updateRate); + +currencySecondEl.addEventListener("change", updateRate); + +worthFirstEl.addEventListener("input", updateRate); diff --git a/projects/currency-converter/style.css b/projects/currency-converter/style.css new file mode 100644 index 0000000..eb02a2b --- /dev/null +++ b/projects/currency-converter/style.css @@ -0,0 +1,47 @@ +body{ + background-color: yellow; + display: flex; + height: 100vh; + justify-content: center; + align-items: center; + font-family: 'Courier New', Courier, monospace; + margin: 0; + padding: 0; +} + +.container{ + background-color: darkcyan; + color: aliceblue; + padding: 10px; + border-radius: 5px; + text-align: center; +} + + +.currency-container{ + padding: 20px; + display: flex; + justify-content: space-between; +} + +.currency-container select{ + padding: 10px; +} + +.currency-container input{ + border: 0; + background: transparent; + font-size: 25px; + text-align: right; + color: aliceblue; +} + +.exchange-rate{ + font-size: 16px; + font-weight: 600; +} + +select:focus, +input:focus{ + outline: 0; +} \ No newline at end of file diff --git a/projects/dad-jokes-generator/index.html b/projects/dad-jokes-generator/index.html new file mode 100644 index 0000000..8693912 --- /dev/null +++ b/projects/dad-jokes-generator/index.html @@ -0,0 +1,18 @@ + + + + + + + Dad Jokes Generator + + + +
+

Dad Joke Generator

+

Dad Joke

+ +
+ + + \ No newline at end of file diff --git a/projects/dad-jokes-generator/index.js b/projects/dad-jokes-generator/index.js new file mode 100644 index 0000000..12d9337 --- /dev/null +++ b/projects/dad-jokes-generator/index.js @@ -0,0 +1,36 @@ +const btnEl = document.getElementById("btn"); +const jokeEl = document.getElementById("joke"); + +const apiKey = "4kqGcJx8uDXo3XIskcbzokAz7rN8nWJs3PL9Mcll"; + +const options = { + method: "GET", + headers: { + "X-Api-Key": apiKey, + }, +}; + +const apiURL = "https://api.api-ninjas.com/v1/dadjokes?limit=1"; + +async function getJoke() { + try { + jokeEl.innerText = "Updating..."; + btnEl.disabled = true; + btnEl.innerText = "Loading..."; + const response = await fetch(apiURL, options); + const data = await response.json(); + + btnEl.disabled = false; + btnEl.innerText = "Tell me a joke"; + + jokeEl.innerText = data[0].joke; + } catch (error) { + jokeEl.innerText = "An error happened, try again later"; + btnEl.disabled = false; + btnEl.innerText = "Tell me a joke"; + console.log(error); + } +} + +btnEl.addEventListener("click", getJoke); + diff --git a/projects/dad-jokes-generator/style.css b/projects/dad-jokes-generator/style.css new file mode 100644 index 0000000..1b55a53 --- /dev/null +++ b/projects/dad-jokes-generator/style.css @@ -0,0 +1,52 @@ +body{ + margin: 0; + background: linear-gradient(to left bottom, lightblue, lightpink, lightblue); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + font-family: monospace; +} + +.container{ + background-color: rgba(255,255,255,.3); + padding: 20px; + box-shadow: 0 6px 10px rgba(0,0,0,.3); + border-radius: 15px; + width: 85%; + text-align: center; + color: darkgreen; +} + +.heading{ + font-size: 35px; + font-weight: 200; + font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; + text-shadow: 5px 5px 2px rgba(0,0,0,.3); + letter-spacing: 2px; +} + +.joke{ + font-size: 25px; + font-weight: 500; + margin: 40px +} + +.btn{ + font-size: 18px; + font-weight: 700; + border-radius: 5px; + cursor: pointer; + padding: 10px; + background-color: rgba(255,255,255,.3); + border-color: rgba(255,255,255,.6); + text-transform: uppercase; + width: 300px; + color: darkgreen; +} + +.btn:hover{ + background-color: rgba(255,255,255,.5); + box-shadow: 0 4px 4px rgba(0,0,0,.3); + transition: all 300ms ease; +} \ No newline at end of file diff --git a/projects/dice-roll-simulator/index.html b/projects/dice-roll-simulator/index.html new file mode 100644 index 0000000..edf81b5 --- /dev/null +++ b/projects/dice-roll-simulator/index.html @@ -0,0 +1,20 @@ + + + + + + + Dice Roll Simulator + + + +

Dice Roll Simulator

+
+ + + + + diff --git a/projects/dice-roll-simulator/index.js b/projects/dice-roll-simulator/index.js new file mode 100644 index 0000000..8deecde --- /dev/null +++ b/projects/dice-roll-simulator/index.js @@ -0,0 +1,53 @@ +const buttonEl = document.getElementById("roll-button"); + +const diceEl = document.getElementById("dice"); + +const rollHistoryEl = document.getElementById("roll-history"); + +let historyList = []; + +function rollDice() { + const rollResult = Math.floor(Math.random() * 6) + 1; + const diceFace = getDiceFace(rollResult); + diceEl.innerHTML = diceFace; + historyList.push(rollResult); + updateRollHistory(); +} + +function updateRollHistory() { + rollHistoryEl.innerHTML = ""; + for (let i = 0; i < historyList.length; i++) { + const listItem = document.createElement("li"); + listItem.innerHTML = `Roll ${i + 1}: ${getDiceFace( + historyList[i] + )}`; + rollHistoryEl.appendChild(listItem); + } +} + +function getDiceFace(rollResult) { + switch (rollResult) { + case 1: + return "⚀"; + case 2: + return "⚁"; + case 3: + return "⚂"; + case 4: + return "⚃"; + case 5: + return "⚄"; + case 6: + return "⚅"; + default: + return ""; + } +} + +buttonEl.addEventListener("click", () => { + diceEl.classList.add("roll-animation"); + setTimeout(() => { + diceEl.classList.remove("roll-animation"); + rollDice(); + }, 1000); +}); diff --git a/projects/dice-roll-simulator/style.css b/projects/dice-roll-simulator/style.css new file mode 100644 index 0000000..439ab24 --- /dev/null +++ b/projects/dice-roll-simulator/style.css @@ -0,0 +1,70 @@ +body { + font-family: "Open Sans", sans-serif; + text-align: center; + margin: 0; +} + +h1 { + font-size: 3rem; + margin-top: 2rem; +} + +.dice { + font-size: 7rem; + margin: 5px; + animation-duration: 1s; + animation-fill-mode: forwards; +} + +.roll-animation { + animation-name: roll; +} + +@keyframes roll { + 0% { + transform: rotateY(0deg) rotateX(0deg); + } + + 100% { + transform: rotateY(720deg) rotateX(720deg); + } +} + +button { + background-color: #47a5c4; + color: white; + font-size: 1.5rem; + padding: 1rem 2rem; + border: none; + border-radius: 1rem; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #2e8baf; +} + +ul { + list-style: none; + padding: 0; + max-width: 600px; + margin: 2rem auto; +} + +li { + font-size: 1.5rem; + padding: 0.5rem; + margin: 0.5rem; + background-color: #f2f2f2; + border-radius: 0.5rem; + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3); + display: flex; + justify-content: space-between; + align-items: center; +} + +li span { + font-size: 3rem; + margin-right: 1rem; +} diff --git a/projects/double-landing-page/style.css b/projects/double-landing-page/style.css index 5a62c04..0d37d66 100644 --- a/projects/double-landing-page/style.css +++ b/projects/double-landing-page/style.css @@ -11,7 +11,7 @@ body { h1 { font-size: 100px; color: aliceblue; - backdrop-filter: brightness(0.5); + background-color: rgba(0, 0, 0, 0.3); letter-spacing: 4px; } diff --git a/projects/english-dictionary/index.html b/projects/english-dictionary/index.html new file mode 100644 index 0000000..47f6806 --- /dev/null +++ b/projects/english-dictionary/index.html @@ -0,0 +1,23 @@ + + + + + + + English Dictionary + + + +
+

English Dictionary

+ +

Type a word and press enter

+
+

Word Title: ___

+

Meaning: ___

+ +
+
+ + + diff --git a/projects/english-dictionary/index.js b/projects/english-dictionary/index.js new file mode 100644 index 0000000..8a93219 --- /dev/null +++ b/projects/english-dictionary/index.js @@ -0,0 +1,40 @@ +const inputEl = document.getElementById("input"); +const infoTextEl = document.getElementById("info-text"); +const meaningContainerEl = document.getElementById("meaning-container"); +const titleEl = document.getElementById("title"); +const meaningEl = document.getElementById("meaning"); +const audioEl = document.getElementById("audio"); + +async function fetchAPI(word) { + try { + infoTextEl.style.display = "block"; + meaningContainerEl.style.display = "none"; + infoTextEl.innerText = `Searching the meaning of "${word}"`; + const url = `https://api.dictionaryapi.dev/api/v2/entries/en/${word}`; + const result = await fetch(url).then((res) => res.json()); + + if (result.title) { + meaningContainerEl.style.display = "block"; + infoTextEl.style.display = "none"; + titleEl.innerText = word; + meaningEl.innerText = "N/A"; + audioEl.style.display = "none"; + } else { + infoTextEl.style.display = "none"; + meaningContainerEl.style.display = "block"; + audioEl.style.display = "inline-flex"; + titleEl.innerText = result[0].word; + meaningEl.innerText = result[0].meanings[0].definitions[0].definition; + audioEl.src = result[0].phonetics[0].audio; + } + } catch (error) { + console.log(error); + infoTextEl.innerText = `an error happened, try again later`; + } +} + +inputEl.addEventListener("keyup", (e) => { + if (e.target.value && e.key === "Enter") { + fetchAPI(e.target.value); + } +}); diff --git a/projects/english-dictionary/style.css b/projects/english-dictionary/style.css new file mode 100644 index 0000000..59fa822 --- /dev/null +++ b/projects/english-dictionary/style.css @@ -0,0 +1,40 @@ +body{ + margin: 0; + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + background-color: salmon; + font-family: 'Courier New', Courier, monospace; +} + +.container{ + background-color: rgba(255,255,255, .3); + padding: 28px; + border-radius: 7px; + box-shadow: 0 10px 10px rgba(0,0,0,.3); + width: 90%; + margin: 10px; + max-width: 450px; + text-align: center; + font-size: 18px; + font-weight: 500; +} + +.heading{ + font-size: 28px; +} + +.input{ + height: 53px; + width: 300px; + background-color: rgba(255,255,255, .6); + border-color: rgba(255,255,255, .4); + font-size: 16px; + padding: 0 42px; + border-radius: 5px; +} + +.meaning-container{ + display: none; +} \ No newline at end of file diff --git a/projects/feedback-ui/index.html b/projects/feedback-ui/index.html new file mode 100644 index 0000000..3101d24 --- /dev/null +++ b/projects/feedback-ui/index.html @@ -0,0 +1,31 @@ + + + + + + + Feedback UI + + + +
+

Feedback UI

+
+
+ + Unhappy +
+
+ + Neutral +
+
+ + Satisfied +
+
+ +
+ + + diff --git a/projects/feedback-ui/index.js b/projects/feedback-ui/index.js new file mode 100644 index 0000000..5bf81a0 --- /dev/null +++ b/projects/feedback-ui/index.js @@ -0,0 +1,34 @@ +const ratingEls = document.querySelectorAll(".rating"); +const btnEl = document.getElementById("btn"); + +const containerEl = document.getElementById("container"); + +let selectedRating = ""; + +ratingEls.forEach((ratingEl) => { + ratingEl.addEventListener("click", (event) => { + removeActive(); + selectedRating = + event.target.innerText || event.target.parentNode.innerText; + event.target.classList.add("active"); + event.target.parentNode.classList.add("active"); + }); +}); + +btnEl.addEventListener("click", () => { + if (selectedRating !== "") { + containerEl.innerHTML = ` + Thank you! +
+
+ Feedback: ${selectedRating} +

We'll use your feedback to improve our customer support.

+ `; + } +}); + +function removeActive() { + ratingEls.forEach((ratingEl) => { + ratingEl.classList.remove("active"); + }); +} diff --git a/projects/feedback-ui/style.css b/projects/feedback-ui/style.css new file mode 100644 index 0000000..7e1c812 --- /dev/null +++ b/projects/feedback-ui/style.css @@ -0,0 +1,70 @@ +body { + margin: 0; + background-color: lightcyan; + color: darkgreen; + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + font-family: monospace; +} + +.container { + background: rgba(255, 255, 255, 0.3); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3); + border-radius: 10px; + padding: 20px; + width: 85%; + max-width: 400px; + text-align: center; + font-size: 20px; +} + +.heading { + margin: 5px; + font-size: 30px; +} + +.ratings-container { + display: flex; + padding: 20px 0; +} + +.rating { + cursor: pointer; + padding: 10px; + margin: 10px 5px; +} + +.rating:hover, +.rating.active +{ + background: darkseagreen; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + color: aliceblue; + transition: all 300ms ease; +} + +.btn { + background-color: darkcyan; + color: aliceblue; + border: 0; + margin: 10px; + border-radius: 4px; + padding: 12px 30px; + cursor: pointer; +} + +.btn:hover { + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3); + transition: all 300ms ease; +} + +.btn:active { + transform: scale(0.96); +} + +.rating img { + width: 40px; +} diff --git a/projects/image-search-app/index.html b/projects/image-search-app/index.html new file mode 100644 index 0000000..47214ed --- /dev/null +++ b/projects/image-search-app/index.html @@ -0,0 +1,57 @@ + + + + + + + Image Search App + + + +

Image Search App

+
+ + +
+
+ +
+ + + + diff --git a/projects/image-search-app/index.js b/projects/image-search-app/index.js new file mode 100644 index 0000000..87a94e1 --- /dev/null +++ b/projects/image-search-app/index.js @@ -0,0 +1,54 @@ +const accessKey = "RZEIOVfPhS7vMLkFdd2TSKGFBS4o9_FmcV1Nje3FSjw"; + +const formEl = document.querySelector("form"); +const searchInputEl = document.getElementById("search-input"); +const searchResultsEl = document.querySelector(".search-results"); +const showMoreButtonEl = document.getElementById("show-more-button"); + +let inputData = ""; +let page = 1; + +async function searchImages() { + inputData = searchInputEl.value; + const url = `https://api.unsplash.com/search/photos?page=${page}&query=${inputData}&client_id=${accessKey}`; + + const response = await fetch(url); + const data = await response.json(); + if (page === 1) { + searchResultsEl.innerHTML = ""; + } + + const results = data.results; + + results.map((result) => { + const imageWrapper = document.createElement("div"); + imageWrapper.classList.add("search-result"); + const image = document.createElement("img"); + image.src = result.urls.small; + image.alt = result.alt_description; + const imageLink = document.createElement("a"); + imageLink.href = result.links.html; + imageLink.target = "_blank"; + imageLink.textContent = result.alt_description; + + imageWrapper.appendChild(image); + imageWrapper.appendChild(imageLink); + searchResultsEl.appendChild(imageWrapper); + }); + + page++; + + if (page > 1) { + showMoreButtonEl.style.display = "block"; + } +} + +formEl.addEventListener("submit", (event) => { + event.preventDefault(); + page = 1; + searchImages(); +}); + +showMoreButtonEl.addEventListener("click", () => { + searchImages(); +}); diff --git a/projects/image-search-app/style.css b/projects/image-search-app/style.css new file mode 100644 index 0000000..875a68a --- /dev/null +++ b/projects/image-search-app/style.css @@ -0,0 +1,125 @@ +body { + background-color: #f9f9f9; + font-family: Arial, Helvetica, sans-serif; + line-height: 1.6; + margin: 0; +} + +h1 { + font-size: 36px; + font-weight: bold; + text-align: center; + margin-top: 40px; + margin-bottom: 60px; +} + +form { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 60px; +} + +#search-input { + width: 60%; + max-width: 400px; + padding: 10px 20px; + border: none; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + border-radius: 5px; + font-size: 18px; + color: #333; +} + +#search-button { + padding: 10px 20px; + background-color: #4caf50; + color: white; + border: none; + font-size: 18px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + cursor: pointer; + border-radius: 5px; + transition: background-color 0.3s ease-in-out; +} + +#search-button:hover { + background-color: #3e8e41; +} + +.search-results { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +.search-result { + margin-bottom: 60px; + width: 30%; + border-radius: 5px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + overflow: hidden; +} + +.search-result:hover img { + transform: scale(1.05); +} + +.search-result img { + width: 100%; + height: 200px; + object-fit: cover; + transition: transform 0.3s ease-in-out; +} +.search-result a { + padding: 10px; + display: block; + color: #333; + text-decoration: none; + transition: background-color 0.3s ease-in-out; +} + +.search-result:hover a { + background-color: rgba(0, 0, 0, 0.1); +} + +#show-more-button { + background-color: #008cba; + border: none; + color: white; + padding: 10px 20px; + display: block; + margin: 20px auto; + text-align: center; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease-in-out; + display: none; +} + +#show-more-button:hover { + background-color: #0077b5; +} + +@media screen and (max-width: 768px) { + .search-result { + width: 45%; + } +} +@media screen and (max-width: 480px) { + .search-result { + width: 100%; + } + + form { + flex-direction: column; + } + + #search-input { + margin-bottom: 20px; + width: 85%; + } +} diff --git a/projects/loan-calculator/index.html b/projects/loan-calculator/index.html new file mode 100644 index 0000000..8285844 --- /dev/null +++ b/projects/loan-calculator/index.html @@ -0,0 +1,27 @@ + + + + + + + Loan Calculator + + + +
+

Loan Calculator

+

Loan Amount $ + +

+

Interest Rate % + +

+

Months to pay + +

+

Monthly Payment:

+
+ + + + \ No newline at end of file diff --git a/projects/loan-calculator/index.js b/projects/loan-calculator/index.js new file mode 100644 index 0000000..fb038fe --- /dev/null +++ b/projects/loan-calculator/index.js @@ -0,0 +1,15 @@ +function calculateLoan() { + loanAmountValue = document.getElementById("loan-amount").value; + + interestRateValue = document.getElementById("interest-rate").value; + + MonthsToPayValue = document.getElementById("months-to-pay").value; + + interest = (loanAmountValue * (interestRateValue * 0.01)) / MonthsToPayValue; + + monthlyPayment = (loanAmountValue / MonthsToPayValue + interest).toFixed(2); + + document.getElementById( + "payment" + ).innerHTML = `Monthly Payment: ${monthlyPayment}`; +} diff --git a/projects/loan-calculator/style.css b/projects/loan-calculator/style.css new file mode 100644 index 0000000..6ca571b --- /dev/null +++ b/projects/loan-calculator/style.css @@ -0,0 +1,27 @@ +body{ + padding: 0; + margin: 0; + display: flex; + height: 100vh; + justify-content: center; + align-items: center; + font-family: 'Courier New', Courier, monospace; +} + +.container{ + background: darkcyan; + color: aliceblue; + padding: 20px; + border-radius: 10px; +} + +.input{ + width: 100%; + font-size: 20px; + height: 30px; +} + +.payment{ + font-weight: 600; + font-size: 20px; +} \ No newline at end of file diff --git a/projects/music-player/index.html b/projects/music-player/index.html new file mode 100644 index 0000000..20b6976 --- /dev/null +++ b/projects/music-player/index.html @@ -0,0 +1,34 @@ + + + + Music Player + + + +
+

Music Player

+
+ +
+ + +
+
+
+
+
+ +
+ + + diff --git a/projects/music-player/pause.png b/projects/music-player/pause.png new file mode 100644 index 0000000..3c877cc Binary files /dev/null and b/projects/music-player/pause.png differ diff --git a/projects/music-player/play.png b/projects/music-player/play.png new file mode 100644 index 0000000..7019bf1 Binary files /dev/null and b/projects/music-player/play.png differ diff --git a/projects/music-player/script.js b/projects/music-player/script.js new file mode 100644 index 0000000..c037a17 --- /dev/null +++ b/projects/music-player/script.js @@ -0,0 +1,90 @@ +const playlist = [ + { title: "Song 1", src: "songs/song1.m4a" }, + { title: "Song 2", src: "songs/song2.m4a" }, + { title: "Song 3", src: "songs/song3.m4a" }, +]; + +const links = document.querySelectorAll(".playlist__item a"); + +links.forEach((link) => { + link.addEventListener("click", function (e) { + e.preventDefault(); + const source = this.getAttribute("data-src"); + document.querySelector("#player").setAttribute("src", source); + playSong(); + + // Remove active class from all links + links.forEach((link) => { + link.classList.remove("active-song"); + }); + + // Add active class to clicked link + this.classList.add("active-song"); + }); +}); + +function playSong() { + const player = document.querySelector("#player"); + const playButton = document.querySelector(".player__button--play"); + const pauseButton = document.querySelector(".player__button--pause"); + const progressBar = document.querySelector(".player__progress-bar"); + + if (player.paused) { + player.play(); + playButton.classList.remove("active"); + pauseButton.classList.add("active"); + } else { + player.pause(); + playButton.classList.add("active"); + pauseButton.classList.remove("active"); + } + + player.addEventListener("timeupdate", function () { + const progress = (player.currentTime / player.duration) * 100; + progressBar.style.width = `${progress}%`; + }); + + progressBar.addEventListener("click", function (e) { + const progressWidth = this.offsetWidth; + const clickedWidth = e.offsetX; + const percent = (clickedWidth / progressWidth) * 100; + player.currentTime = (player.duration / 100) * percent; + progressBar.style.width = `${percent}%`; + }); +} + +function playFirstSong() { + const firstSong = playlist[0].src; + document.querySelector("#player").setAttribute("src", firstSong); + playSong(); +} + +const playButton = document.querySelector(".player__button--play"); +const pauseButton = document.querySelector(".player__button--pause"); + +playButton.addEventListener("click", function () { + const player = document.querySelector("#player"); + player.play(); + playButton.classList.remove("active"); + pauseButton.classList.add("active"); +}); + +pauseButton.addEventListener("click", function () { + const player = document.querySelector("#player"); + player.pause(); + playButton.classList.add("active"); + pauseButton.classList.remove("active"); +}); + +const player = document.querySelector("#player"); +player.addEventListener("play", function () { + playButton.classList.remove("active"); + pauseButton.classList.add("active"); +}); + +player.addEventListener("pause", function () { + playButton.classList.add("active"); + pauseButton.classList.remove("active"); +}); + +playFirstSong(); diff --git a/projects/music-player/songs/song1.m4a b/projects/music-player/songs/song1.m4a new file mode 100644 index 0000000..90842b1 Binary files /dev/null and b/projects/music-player/songs/song1.m4a differ diff --git a/projects/music-player/songs/song2.m4a b/projects/music-player/songs/song2.m4a new file mode 100644 index 0000000..13c7c3d Binary files /dev/null and b/projects/music-player/songs/song2.m4a differ diff --git a/projects/music-player/songs/song3.m4a b/projects/music-player/songs/song3.m4a new file mode 100644 index 0000000..02ba7a4 Binary files /dev/null and b/projects/music-player/songs/song3.m4a differ diff --git a/projects/music-player/style.css b/projects/music-player/style.css new file mode 100644 index 0000000..038d0b1 --- /dev/null +++ b/projects/music-player/style.css @@ -0,0 +1,90 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: Arial, sans-serif; + background-color: #f2f2f2; +} + +.container { + max-width: 600px; + margin: 0 auto; + padding: 0 20px; +} + +.title { + text-align: center; + margin-top: 50px; + margin-bottom: 50px; +} + +.player { + margin-bottom: 50px; +} + +.player__controls { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + +.player__button { + width: 50px; + height: 50px; + background-color: #fff; + border: none; + cursor: pointer; + margin-right: 10px; + background-image: url("play.png"); + background-repeat: no-repeat; + background-position: center; + background-size: 60%; +} + +.player__button--pause { + background-image: url("pause.png"); +} + +.player__button.active { + background-color: #0074d9; + color: #fff; +} + +.player__progress { + height: 5px; + background-color: #f5f5f5; + position: relative; +} + +.player__progress-bar { + position: absolute; + top: 0; + left: 0; + height: 100%; + background-color: #0074d9; + width: 0%; +} + +.playlist__item { + margin-bottom: 10px; +} + +.playlist__item a { + display: block; + padding: 10px; + background-color: #fff; + color: #333; + text-decoration: none; +} + +.playlist__item a:hover { + background-color: #f5f5f5; +} + +.playlist__item a.active-song { + background-color: #0074d9; + color: #fff; +} diff --git a/projects/navbar/index.html b/projects/navbar/index.html new file mode 100644 index 0000000..78fd71b --- /dev/null +++ b/projects/navbar/index.html @@ -0,0 +1,38 @@ + + + + + + + Navbar project + + + + + + + + diff --git a/projects/Navbar-project/index.js b/projects/navbar/index.js similarity index 100% rename from projects/Navbar-project/index.js rename to projects/navbar/index.js diff --git a/projects/Navbar-project/logo.svg b/projects/navbar/logo.svg similarity index 100% rename from projects/Navbar-project/logo.svg rename to projects/navbar/logo.svg diff --git a/projects/Navbar-project/styles.css b/projects/navbar/styles.css similarity index 100% rename from projects/Navbar-project/styles.css rename to projects/navbar/styles.css diff --git a/projects/new-year-countdown/index.html b/projects/new-year-countdown/index.html index c4c0578..3638291 100644 --- a/projects/new-year-countdown/index.html +++ b/projects/new-year-countdown/index.html @@ -9,7 +9,7 @@

Countdown to New Year

-
2022
+
2024
00
00
diff --git a/projects/new-year-countdown/index.js b/projects/new-year-countdown/index.js index 1a89f36..3ee8cd0 100644 --- a/projects/new-year-countdown/index.js +++ b/projects/new-year-countdown/index.js @@ -3,7 +3,7 @@ const hourEl = document.getElementById("hour"); const minuteEl = document.getElementById("minute"); const secondEl = document.getElementById("second"); -const newYearTime = new Date("Jan 1, 2022 00:00:00").getTime(); +const newYearTime = new Date("Jan 1, 2024 00:00:00").getTime(); updateCountdown(); diff --git a/projects/note-app/index.html b/projects/note-app/index.html new file mode 100644 index 0000000..f61a1bd --- /dev/null +++ b/projects/note-app/index.html @@ -0,0 +1,25 @@ + + + + + + + Document + + + +

Note App

+

Double click on a note to remove it

+
+ + + +
+ + + diff --git a/projects/note-app/index.js b/projects/note-app/index.js new file mode 100644 index 0000000..c3b33e9 --- /dev/null +++ b/projects/note-app/index.js @@ -0,0 +1,64 @@ +const btnEl = document.getElementById("btn"); +const appEl = document.getElementById("app"); + +getNotes().forEach((note) => { + const noteEl = createNoteEl(note.id, note.content); + appEl.insertBefore(noteEl, btnEl); +}); + +function createNoteEl(id, content) { + const element = document.createElement("textarea"); + element.classList.add("note"); + element.placeholder = "Empty Note"; + element.value = content; + + element.addEventListener("dblclick", () => { + const warning = confirm("Do you want to delete this note?"); + if (warning) { + deleteNote(id, element); + } + }); + + element.addEventListener("input", () => { + updateNote(id, element.value); + }); + + return element; +} + +function deleteNote(id, element) { + const notes = getNotes().filter((note)=>note.id != id) + saveNote(notes) + appEl.removeChild(element) +} + +function updateNote(id, content) { + const notes = getNotes(); + const target = notes.filter((note) => note.id == id)[0]; + target.content = content; + saveNote(notes); +} + +function addNote() { + const notes = getNotes(); + const noteObj = { + id: Math.floor(Math.random() * 100000), + content: "", + }; + const noteEl = createNoteEl(noteObj.id, noteObj.content); + appEl.insertBefore(noteEl, btnEl); + + notes.push(noteObj); + + saveNote(notes); +} + +function saveNote(notes) { + localStorage.setItem("note-app", JSON.stringify(notes)); +} + +function getNotes() { + return JSON.parse(localStorage.getItem("note-app") || "[]"); +} + +btnEl.addEventListener("click", addNote); diff --git a/projects/note-app/style.css b/projects/note-app/style.css new file mode 100644 index 0000000..47154de --- /dev/null +++ b/projects/note-app/style.css @@ -0,0 +1,68 @@ +body { + margin: 0; + background: linear-gradient(to left, lightblue, lightgreen); + font-family: "Courier New", Courier, monospace; +} + +.heading { + color: darkblue; + text-align: center; + padding-top: 10px; + font-size: 35px; +} + +.info-text { + text-align: center; + color: darkblue; + font-size: 18px; +} + +.app { + display: grid; + grid-template-columns: repeat(auto-fill, 300px); + gap: 40px; + justify-content: center; + padding: 50px; +} + +.note { + padding: 17px; + border-radius: 15px; + resize: none; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); + font-size: 18px; + height: 200px; + color: darkblue; + border: none; + outline: none; + background: rgba(255, 255, 255, 0.1); + box-sizing: border-box; +} + +.note::placeholder { + color: gray; + opacity: 30%; +} + +.note:hover, +.note:focus { + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + transition: all 300ms ease; +} + +.btn{ + height: 200px; + border-color: rgba(255, 255, 255, 0.37); + background: rgba(255, 255, 255, 0.27); + border-radius: 15px; + font-size: 70px; + font-weight: 700; + color: rgba(0, 0, 0, 0.3); + cursor: pointer; +} + +.btn:hover{ + background: rgba(255, 255, 255, 0.55); + color: rgba(0, 0, 0, 0.6); + transition: all 300ms ease; +} diff --git a/projects/photo-gallery/index.html b/projects/photo-gallery/index.html new file mode 100644 index 0000000..f0a8e39 --- /dev/null +++ b/projects/photo-gallery/index.html @@ -0,0 +1,33 @@ + + + + + + + Photo Gallery + + + +
+

Photo Gallery

+

Enter the number of photos

+ + Error Message + + +
+ + + diff --git a/projects/photo-gallery/index.js b/projects/photo-gallery/index.js new file mode 100644 index 0000000..024848b --- /dev/null +++ b/projects/photo-gallery/index.js @@ -0,0 +1,48 @@ +const btnEl = document.getElementById("btn"); +const errorMessageEl = document.getElementById("errorMessage"); +const galleryEl = document.getElementById("gallery"); + +async function fetchImage() { + const inputValue = document.getElementById("input").value; + + if (inputValue > 10 || inputValue < 1) { + errorMessageEl.style.display = "block"; + errorMessageEl.innerText = "Number should be between 0 and 11"; + return; + } + + imgs = ""; + + try { + btnEl.style.display = "none"; + const loading = ``; + galleryEl.innerHTML = loading; + await fetch( + `https://api.unsplash.com/photos?per_page=${inputValue}&page=${Math.round( + Math.random() * 1000 + )}&client_id=B8S3zB8gCPVCvzpAhCRdfXg_aki8PZM_q5pAyzDUvlc` + ).then((res) => + res.json().then((data) => { + if (data) { + data.forEach((pic) => { + imgs += ` + image + `; + galleryEl.style.display = "block"; + galleryEl.innerHTML = imgs; + btnEl.style.display = "block"; + errorMessageEl.style.display = "none"; + }); + } + }) + ); + } catch (error) { + console.log(error); + errorMessageEl.style.display = "block"; + errorMessageEl.innerHTML = "An error happened, try again later"; + btnEl.style.display = "block"; + galleryEl.style.display = "none"; + } +} + +btnEl.addEventListener("click", fetchImage); diff --git a/projects/photo-gallery/spinner.svg b/projects/photo-gallery/spinner.svg new file mode 100644 index 0000000..c59456b --- /dev/null +++ b/projects/photo-gallery/spinner.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/projects/photo-gallery/styles.css b/projects/photo-gallery/styles.css new file mode 100644 index 0000000..c4270f4 --- /dev/null +++ b/projects/photo-gallery/styles.css @@ -0,0 +1,75 @@ + +body{ + margin: 0; + font-family: 'Courier New', Courier, monospace; + background: linear-gradient(to bottom, lightgreen, lightblue); + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + text-align: center; +} + +.container{ + background-color: aliceblue; + padding: 20px; + border-radius: 5px; + box-shadow: 0 10px 20px rgba(0,0,0,0.3); + width: 90%; + margin: 10px; + display: flex; + flex-direction: column; + text-align: center; + justify-content: center; + align-items: center; +} + +h2{ + font-weight: 400; +} + +.input{ + padding: 20px 10px; + font-size: 18px; + background-color: white; + border-radius: 5px; + text-align: center; + width: 100px; +} + +.errorMessage{ + color: red; + font-weight: 600; + margin: 10px; + display: none; +} + +.btn{ + text-transform: uppercase; + width: 250px; + height: 45px; + margin: 20px 0; + font-size: 18px; + border-radius: 5px; + background-color: black; + color: aliceblue; + +} + +.btn:hover{ + color: aliceblue; + background-color: green; + cursor: pointer; + transition: background-color 300ms ease-in-out; +} +.gallery img{ + width: 400px; + height: 250px; + object-fit: cover; + border-radius: 5px; + margin: 5px; +} + +.gallery{ + display: none; +} \ No newline at end of file diff --git a/projects/pomodoro-timer/index.html b/projects/pomodoro-timer/index.html new file mode 100644 index 0000000..7cfe584 --- /dev/null +++ b/projects/pomodoro-timer/index.html @@ -0,0 +1,22 @@ + + + + + + + Pomodoro Timer + + + +
+

Pomodoro Timer

+

25:00

+
+ + + +
+
+ + + \ No newline at end of file diff --git a/projects/pomodoro-timer/index.js b/projects/pomodoro-timer/index.js new file mode 100644 index 0000000..22b4ede --- /dev/null +++ b/projects/pomodoro-timer/index.js @@ -0,0 +1,42 @@ +const startEl = document.getElementById("start"); +const stopEl = document.getElementById("stop"); +const resetEl = document.getElementById("reset"); +const timerEl = document.getElementById("timer"); + +let interval; +let timeLeft = 1500; + +function updateTimer() { + let minutes = Math.floor(timeLeft / 60); + let seconds = timeLeft % 60; + let formattedTime = `${minutes.toString().padStart(2, "0")}:${seconds + .toString() + .padStart(2, "0")}`; + + timerEl.innerHTML = formattedTime; +} + +function startTimer() { + interval = setInterval(() => { + timeLeft--; + updateTimer(); + if (timeLeft === 0) { + clearInterval(interval); + alert("Time's up!"); + timeLeft = 1500; + updateTimer(); + } + }, 1000); +} +function stopTimer() { + clearInterval(interval); +} +function resetTimer() { + clearInterval(interval); + timeLeft = 1500; + updateTimer(); +} + +startEl.addEventListener("click", startTimer); +stopEl.addEventListener("click", stopTimer); +resetEl.addEventListener("click", resetTimer); diff --git a/projects/pomodoro-timer/style.css b/projects/pomodoro-timer/style.css new file mode 100644 index 0000000..0e6970b --- /dev/null +++ b/projects/pomodoro-timer/style.css @@ -0,0 +1,47 @@ +.container { + margin: 0 auto; + max-width: 400px; + text-align: center; + padding: 20px; + font-family: "Roboto", sans-serif; +} + +.title { + font-size: 36px; + margin-bottom: 10px; + color: #2c3e50; +} + +.timer { + font-size: 72px; + color: #2c3e50; +} + +button { + font-size: 18px; + padding: 10px 20px; + margin: 10px; + color: white; + + border: none; + border-radius: 4px; + cursor: pointer; + text-transform: uppercase; + transition: opacity 0.3s ease-in-out; +} + +button:hover { + opacity: 0.7; +} + +#start { + background-color: #27ae60; +} + +#stop { + background-color: #c0392b; +} + +#reset { + background-color: #7f8c8d; +} diff --git a/projects/Q&A-section/app.js b/projects/q-and-a-section/app.js similarity index 100% rename from projects/Q&A-section/app.js rename to projects/q-and-a-section/app.js diff --git a/projects/Q&A-section/index.html b/projects/q-and-a-section/index.html similarity index 100% rename from projects/Q&A-section/index.html rename to projects/q-and-a-section/index.html diff --git a/projects/Q&A-section/styles.css b/projects/q-and-a-section/styles.css similarity index 100% rename from projects/Q&A-section/styles.css rename to projects/q-and-a-section/styles.css diff --git a/projects/random-emoji/index.html b/projects/random-emoji/index.html new file mode 100644 index 0000000..74b24cc --- /dev/null +++ b/projects/random-emoji/index.html @@ -0,0 +1,18 @@ + + + + + + + + Random Emoji + + +

Random Emoji

+
+ +

Emoji Name

+
+ + + \ No newline at end of file diff --git a/projects/random-emoji/index.js b/projects/random-emoji/index.js new file mode 100644 index 0000000..a768eb0 --- /dev/null +++ b/projects/random-emoji/index.js @@ -0,0 +1,27 @@ +const btnEl = document.getElementById("btn"); +const emojiNameEl = document.getElementById("emoji-name"); + +const emoji = []; + +async function getEmoji() { + let response = await fetch( + "https://emoji-api.com/emojis?access_key=773b58f681fb786fafdb8392e8b8a75ddc177fd1" + ); + + data = await response.json(); + + for (let i = 0; i < 1500; i++) { + emoji.push({ + emojiName: data[i].character, + emojiCode: data[i].unicodeName, + }); + } +} + +getEmoji(); + +btnEl.addEventListener("click", () => { + const randomNum = Math.floor(Math.random() * emoji.length); + btnEl.innerText = emoji[randomNum].emojiName; + emojiNameEl.innerText = emoji[randomNum].emojiCode; +}); diff --git a/projects/random-emoji/style.css b/projects/random-emoji/style.css new file mode 100644 index 0000000..37b110b --- /dev/null +++ b/projects/random-emoji/style.css @@ -0,0 +1,41 @@ +body{ + padding: 0; + margin: 0; + background: salmon; + display: flex; + flex-direction: column; + justify-content: center; + height: 100vh; + align-items: center; + font-family: 'Courier New', Courier, monospace; +} + +h2{ + font-size: 2rem; + color: aliceblue; +} + +.section{ + text-align: center; +} + +.btn{ + font-size: 5rem; + border: none; + background: rgb(255,255,255,.2); + border-radius: 10px; + padding: 15px; + filter: grayscale(); + transition: filter .2s ease-in-out; + cursor: pointer; + +} + +.btn:hover{ + filter: grayscale(0); +} + +.emoji-name{ + font-weight: 600; + color: darkblue; +} \ No newline at end of file diff --git a/projects/random-quote-generator/index.html b/projects/random-quote-generator/index.html new file mode 100644 index 0000000..04cd199 --- /dev/null +++ b/projects/random-quote-generator/index.html @@ -0,0 +1,25 @@ + + + + + + + Random Quote Generator + + + + +
+

Random Quote Generator

+

+ + Quote + + +

+

~ Author

+ +
+ + + \ No newline at end of file diff --git a/projects/random-quote-generator/index.js b/projects/random-quote-generator/index.js new file mode 100644 index 0000000..801cc29 --- /dev/null +++ b/projects/random-quote-generator/index.js @@ -0,0 +1,33 @@ +const btnEl = document.getElementById("btn"); +const quoteEl = document.getElementById("quote"); +const authorEl = document.getElementById("author"); + +const apiURL = "https://api.quotable.io/random"; + +async function getQuote() { + try { + btnEl.innerText = "Loading..."; + btnEl.disabled = true; + quoteEl.innerText = "Updating..."; + authorEl.innerText = "Updating..."; + const response = await fetch(apiURL); + const data = await response.json(); + const quoteContent = data.content; + const quoteAuthor = data.author; + quoteEl.innerText = quoteContent; + authorEl.innerText = "~ " + quoteAuthor; + btnEl.innerText = "Get a quote"; + btnEl.disabled = false; + console.log(data); + } catch (error) { + console.log(error); + quoteEl.innerText = "An error happened, try again later"; + authorEl.innerText = "An error happened"; + btnEl.innerText = "Get a quote"; + btnEl.disabled = false; + } +} + +getQuote() + +btnEl.addEventListener("click", getQuote); diff --git a/projects/random-quote-generator/style.css b/projects/random-quote-generator/style.css new file mode 100644 index 0000000..e67e3f5 --- /dev/null +++ b/projects/random-quote-generator/style.css @@ -0,0 +1,54 @@ +body { + margin: 0; + display: flex; + min-height: 100vh; + justify-content: center; + align-items: center; + font-family: "Courier New", Courier, monospace; + background: linear-gradient(to left bottom, lightgreen, lightblue); +} + +.container { + background-color: rgba(255, 255, 255, 0.1); + box-shadow: 0 6px 10px rgba(0, 0, 0, 0.3); + padding: 30px; + border-radius: 15px; + width: 90%; + margin: 10px; + text-align: center; +} + +.heading { + font-size: 35px; + font-weight: 700; +} + +.quote { + font-size: 30px; + font-weight: 600; +} + +.author { + font-size: 25px; + margin: 10px; + font-style: italic; +} + +.btn { + font-size: 18px; + border-radius: 5px; + cursor: pointer; + padding: 10px; + margin-top: 15px; + background-color: rgba(255, 255, 255, 0.3); + border-color: rgba(255, 255, 255, 0.6); + text-transform: uppercase; + width: 300px; +} + +.btn:hover{ + background-color: rgba(255,255,255,.6); + box-shadow: 0 4px 4px rgba(0,0,0,.3); + transition: all 300ms ease-in-out; + color: green; +} diff --git a/projects/recipe-book-app/index.html b/projects/recipe-book-app/index.html new file mode 100644 index 0000000..b93360d --- /dev/null +++ b/projects/recipe-book-app/index.html @@ -0,0 +1,57 @@ + + + + + + + Document + + + +
+

Recipe Book App

+
+ +
+ +
+ + + diff --git a/projects/recipe-book-app/index.js b/projects/recipe-book-app/index.js new file mode 100644 index 0000000..d35b3b8 --- /dev/null +++ b/projects/recipe-book-app/index.js @@ -0,0 +1,50 @@ +const API_KEY = "275d58779ccf4e22af03e792e8819fff"; +const recipeListEl = document.getElementById("recipe-list"); + +function displayRecipes(recipes) { + recipeListEl.innerHTML = ""; + recipes.forEach((recipe) => { + const recipeItemEl = document.createElement("li"); + recipeItemEl.classList.add("recipe-item"); + recipeImageEl = document.createElement("img"); + recipeImageEl.src = recipe.image; + recipeImageEl.alt = "recipe image"; + + recipeTitleEl = document.createElement("h2"); + recipeTitleEl.innerText = recipe.title; + + recipeIngredientsEl = document.createElement("p"); + recipeIngredientsEl.innerHTML = ` + Ingredients: ${recipe.extendedIngredients + .map((ingredient) => ingredient.original) + .join(", ")} + `; + + recipeLinkEl = document.createElement("a"); + recipeLinkEl.href = recipe.sourceUrl; + recipeLinkEl.innerText = "View Recipe"; + + recipeItemEl.appendChild(recipeImageEl); + recipeItemEl.appendChild(recipeTitleEl); + recipeItemEl.appendChild(recipeIngredientsEl); + recipeItemEl.appendChild(recipeLinkEl); + recipeListEl.appendChild(recipeItemEl); + }); +} + +async function getRecipes() { + const response = await fetch( + `https://api.spoonacular.com/recipes/random?number=10&apiKey=${API_KEY}` + ); + + const data = await response.json(); + + return data.recipes; +} + +async function init() { + const recipes = await getRecipes(); + displayRecipes(recipes); +} + +init(); diff --git a/projects/recipe-book-app/style.css b/projects/recipe-book-app/style.css new file mode 100644 index 0000000..9e56d02 --- /dev/null +++ b/projects/recipe-book-app/style.css @@ -0,0 +1,104 @@ +body { + margin: 0; + padding: 0; + font-family: Arial, sans-serif; +} + +header { + background: #0c2461; + color: #fff; + padding: 20px; + text-align: center; +} + +h1 { + margin: 0; + font-size: 36px; +} + +.container { + margin: 0 auto; + max-width: 1200px; + padding: 20px; +} + +.recipe-list { + list-style: none; + margin: 0; + padding: 0; +} + +.recipe-item { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + border-radius: 5px; + overflow: hidden; +} + +.recipe-item img { + width: 150px; + height: 150px; + object-fit: cover; +} + +.recipe-item h2 { + margin: 0; + font-size: 20px; + padding: 10px; + min-width: 200px; +} + +.recipe-item p { + margin: 0; + padding: 10px; + color: #777; +} + +.recipe-item a { + background: #0c2461; + color: #fff; + min-width: 150px; + padding: 10px; + text-decoration: none; + text-transform: uppercase; + font-size: 14px; + transition: background 0.3s ease; +} + +.recipe-item a:hover { + background: #1e3799; +} + +@media screen and (max-width: 768px) { + .container { + max-width: 90%; + } + .recipe-item { + flex-direction: column; + } + + .recipe-item img { + width: 100%; + height: auto; + margin-bottom: 10px; + } + + .recipe-item h2 { + font-size: 20px; + padding: 0; + margin-bottom: 10px; + } + + .recipe-item p { + font-size: 14px; + margin-bottom: 10px; + } + + .recipe-item a { + width: 100%; + text-align: center; + } +} diff --git a/projects/rock-paper-scissors-game/index.html b/projects/rock-paper-scissors-game/index.html new file mode 100644 index 0000000..c458606 --- /dev/null +++ b/projects/rock-paper-scissors-game/index.html @@ -0,0 +1,25 @@ + + + + + + + Rock Paper Scissors Game + + + +

Rock Paper Scissors Game

+

Choose your move:

+
+ + + +
+

+

+ Your score: 0 + Computer score: 0 +

+ + + \ No newline at end of file diff --git a/projects/rock-paper-scissors-game/index.js b/projects/rock-paper-scissors-game/index.js new file mode 100644 index 0000000..4944f3e --- /dev/null +++ b/projects/rock-paper-scissors-game/index.js @@ -0,0 +1,42 @@ +const buttons = document.querySelectorAll("button"); + +const resultEl = document.getElementById("result"); + +const playerScoreEl = document.getElementById("user-score"); + +const computerScoreEl = document.getElementById("computer-score"); + +let playerScore = 0; +let computerScore = 0; + +buttons.forEach((button) => { + button.addEventListener("click", () => { + const result = playRound(button.id, computerPlay()); + resultEl.textContent = result; + + }); +}); + +function computerPlay() { + const choices = ["rock", "paper", "scissors"]; + const randomChoice = Math.floor(Math.random() * choices.length); + return choices[randomChoice]; +} + +function playRound(playerSelection, computerSelection) { + if (playerSelection === computerSelection) { + return "It's a tie!"; + } else if ( + (playerSelection === "rock" && computerSelection === "scissors") || + (playerSelection === "paper" && computerSelection === "rock") || + (playerSelection === "scissors" && computerSelection === "paper") + ) { + playerScore++; + playerScoreEl.textContent = playerScore; + return "You win! " + playerSelection + " beats " + computerSelection; + } else { + computerScore++; + computerScoreEl.textContent = computerScore; + return "You lose! " + computerSelection + " beats " + playerSelection; + } +} diff --git a/projects/rock-paper-scissors-game/style.css b/projects/rock-paper-scissors-game/style.css new file mode 100644 index 0000000..940eff4 --- /dev/null +++ b/projects/rock-paper-scissors-game/style.css @@ -0,0 +1,58 @@ +body { + background-color: #f1f1f1; + font-family: "Arial", sans-serif; + margin: 0; + padding: 0; +} + +h1 { + font-size: 2rem; + text-align: center; + padding-top: 100px; +} + +p { + font-size: 1.5rem; + font-weight: 600; + text-align: center; + margin-bottom: 0.5rem; +} + +.buttons { + display: flex; + justify-content: center; +} + +button { + border: none; + font-size: 3rem; + margin: 0 0.5rem; + padding: 0.5rem; + cursor: pointer; + border-radius: 5px; + transition: all 0.3s ease-in-out; +} + +button:hover { + opacity: 0.7; +} + +#rock { + background-color: #ff0000; +} + +#paper { + background-color: #2196f3; +} + +#scissors { + background-color: #4caf50; +} + +#user-score { + color: #2196f3; +} + +#computer-score { + color: #ff0000; +} diff --git a/projects/Sidebar-project/index.html b/projects/sidebar/index.html similarity index 100% rename from projects/Sidebar-project/index.html rename to projects/sidebar/index.html diff --git a/projects/Sidebar-project/index.js b/projects/sidebar/index.js similarity index 100% rename from projects/Sidebar-project/index.js rename to projects/sidebar/index.js diff --git a/projects/Sidebar-project/logo.svg b/projects/sidebar/logo.svg similarity index 100% rename from projects/Sidebar-project/logo.svg rename to projects/sidebar/logo.svg diff --git a/projects/Sidebar-project/styles.css b/projects/sidebar/styles.css similarity index 100% rename from projects/Sidebar-project/styles.css rename to projects/sidebar/styles.css diff --git a/projects/stopwatch/index.html b/projects/stopwatch/index.html new file mode 100644 index 0000000..05d8b2b --- /dev/null +++ b/projects/stopwatch/index.html @@ -0,0 +1,20 @@ + + + + + + + Stopwatch + + + + +
00:00:00
+
+ + + +
+ + + \ No newline at end of file diff --git a/projects/stopwatch/index.js b/projects/stopwatch/index.js new file mode 100644 index 0000000..0cbd647 --- /dev/null +++ b/projects/stopwatch/index.js @@ -0,0 +1,54 @@ +const timerEl = document.getElementById("timer"); +const startButtonEl = document.getElementById("start"); +const stopButtonEl = document.getElementById("stop"); +const resetButtonEl = document.getElementById("reset"); + +let startTime = 0; +let elapsedTime = 0; +let timerInterval; + +function startTimer() { + startTime = Date.now() - elapsedTime; + + timerInterval = setInterval(() => { + elapsedTime = Date.now() - startTime; + timerEl.textContent = formatTime(elapsedTime); + }, 10); + + startButtonEl.disabled = true; + stopButtonEl.disabled = false; +} + +function formatTime(elapsedTime) { + const milliseconds = Math.floor((elapsedTime % 1000) / 10); + const seconds = Math.floor((elapsedTime % (1000 * 60)) / 1000); + const minutes = Math.floor((elapsedTime % (1000 * 60 * 60)) / (1000 * 60)); + const hours = Math.floor(elapsedTime / (1000 * 60 * 60)); + return ( + (hours ? (hours > 9 ? hours : "0" + hours) : "00") + + ":" + + (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + + ":" + + (seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") + + "." + + (milliseconds > 9 ? milliseconds : "0" + milliseconds) + ); +} +function stopTimer() { + clearInterval(timerInterval); + startButtonEl.disabled = false; + stopButtonEl.disabled = true; +} +function resetTimer() { + clearInterval(timerInterval); + + elapsedTime = 0; + timerEl.textContent = "00:00:00"; + + startButtonEl.disabled = false; + stopButtonEl.disabled = true; +} + +startButtonEl.addEventListener("click", startTimer); +stopButtonEl.addEventListener("click", stopTimer); +resetButtonEl.addEventListener("click", resetTimer); diff --git a/projects/stopwatch/style.css b/projects/stopwatch/style.css new file mode 100644 index 0000000..cf0859d --- /dev/null +++ b/projects/stopwatch/style.css @@ -0,0 +1,61 @@ +body { + background-color: #f0f0f0; + font-family: "Poppins", sans-serif; + display: flex; + flex-direction: column; + justify-content: center; + min-height: 100vh; + overflow: hidden; + align-items: center; +} + +#timer { + font-size: 7rem; + font-weight: 700; + text-shadow: 2px 2px #f8a5c2; + color: #f92672; + width: 600px; + text-align: center; + margin: 40px auto; +} + +#buttons { + display: flex; + justify-content: center; +} + +button { + background-color: #f92672; + color: white; + border: none; + font-size: 2rem; + font-weight: bold; + padding: 1.5rem 4rem; + margin: 1rem; + border-radius: 30px; + cursor: pointer; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3); + transition: all 0.2s; +} + +button:hover { + background-color: #f44583; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5); +} + +button[disabled] { + opacity: 0.5; + cursor: default; +} + +@media (max-width: 800px) { + #timer { + font-size: 4rem; + width: 350px; + } + + button { + font-size: 1.5rem; + padding: 1rem 2rem; + } +} diff --git a/projects/temperature-converter/index.html b/projects/temperature-converter/index.html new file mode 100644 index 0000000..dd23f99 --- /dev/null +++ b/projects/temperature-converter/index.html @@ -0,0 +1,49 @@ + + + + + + + Temperature Converter + + + +
+

Temperature Converter

+
+ + +
+
+ + +
+
+ + +
+
+ + + diff --git a/projects/temperature-converter/index.js b/projects/temperature-converter/index.js new file mode 100644 index 0000000..e2dfcf3 --- /dev/null +++ b/projects/temperature-converter/index.js @@ -0,0 +1,24 @@ +const celsiusEl = document.getElementById("celsius"); +const fahrenheitEl = document.getElementById("fahrenheit"); +const kelvinEl = document.getElementById("kelvin"); + +function computeTemp(event) { + const currentValue = +event.target.value; + + switch (event.target.name) { + case "celsius": + kelvinEl.value = (currentValue + 273.32).toFixed(2); + fahrenheitEl.value = (currentValue * 1.8 + 32).toFixed(2); + break; + case "fahrenheit": + celsiusEl.value = ((currentValue - 32) / 1.8).toFixed(2); + kelvinEl.value = ((currentValue - 32) / 1.8 + 273.32).toFixed(2); + break; + case "kelvin": + celsiusEl.value = (currentValue - 273.32).toFixed(2); + fahrenheitEl.value = ((currentValue - 273.32) * 1.8 + 32).toFixed(2); + break; + default: + break; + } +} diff --git a/projects/temperature-converter/style.css b/projects/temperature-converter/style.css new file mode 100644 index 0000000..ea02485 --- /dev/null +++ b/projects/temperature-converter/style.css @@ -0,0 +1,51 @@ +body { + margin: 0; + background: linear-gradient(to left bottom, lightgreen, lightblue); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + font-family: monospace; + color: darkcyan; +} + +.container { + background: rgba(255, 255, 255, 0.3); + padding: 20px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); + border-radius: 10px; + width: 85%; + max-width: 450px; + min-width: 350px; + display: flex; + flex-direction: column; + align-items: center; +} + +.heading { + font-size: 32px; +} + +.temp-container { + width: 100%; + padding: 15px; + font-weight: bold; + font-size: 18px; +} + +.input { + width: 220px; + font-family: monospace; + padding: 5px; + float: right; + outline: none; + background: rgba(255, 255, 255, 0.3); + border-color: rgba(255, 255, 255, 0.5); + color: darkgreen; + font-size: 18px; +} + + +.input::placeholder{ + color: darkgray; +} diff --git a/projects/tip-calculator/index.html b/projects/tip-calculator/index.html new file mode 100644 index 0000000..029457b --- /dev/null +++ b/projects/tip-calculator/index.html @@ -0,0 +1,28 @@ + + + + + + + Tip Calculator + + + +
+

Tip Calculator

+

Enter the bill amount and tip percentage to calculate the total.

+ + +
+ + +
+ +
+ + + +
+ + + \ No newline at end of file diff --git a/projects/tip-calculator/index.js b/projects/tip-calculator/index.js new file mode 100644 index 0000000..98cb079 --- /dev/null +++ b/projects/tip-calculator/index.js @@ -0,0 +1,13 @@ +const btnEl = document.getElementById("calculate"); +const billInput = document.getElementById("bill"); +const tipInput = document.getElementById("tip"); +const totalSpan = document.getElementById("total"); + +function calculateTotal() { + const billValue = billInput.value; + const tipValue = tipInput.value; + const totalValue = billValue * (1 + tipValue / 100); + totalSpan.innerText = totalValue.toFixed(2); +} + +btnEl.addEventListener("click", calculateTotal); diff --git a/projects/tip-calculator/style.css b/projects/tip-calculator/style.css new file mode 100644 index 0000000..786e129 --- /dev/null +++ b/projects/tip-calculator/style.css @@ -0,0 +1,53 @@ +* { + box-sizing: border-box; +} + +body { + background-color: #f2f2f2; + font-family: "Helvetica", sans-serif; +} + +.container { + background-color: white; + max-width: 600px; + margin: 100px auto; + padding: 20px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + border-radius: 10px; +} + +h1 { + margin-top: 0; + text-align: center; +} + +input { + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; + margin: 10px 0; + width: 100%; +} + +button { + background-color: #4caf50; + color: white; + padding: 10px; + border: none; + cursor: pointer; + margin: 10px 0; + width: 100%; + font-size: 18px; + text-transform: uppercase; + transition: background-color 0.2s ease; +} + +button:hover { + background-color: #45a049; +} + +#total { + font-size: 24px; + font-weight: bold; + margin-top: 10px; +} diff --git a/projects/weather-app/index.html b/projects/weather-app/index.html new file mode 100644 index 0000000..7fe9e3a --- /dev/null +++ b/projects/weather-app/index.html @@ -0,0 +1,32 @@ + + + + + + + Weather App + + + +
+

Weather App

+
+ + +
+
+
+ +
+
+
+
+ +
+
+
+ + + diff --git a/projects/weather-app/index.js b/projects/weather-app/index.js new file mode 100644 index 0000000..f773a49 --- /dev/null +++ b/projects/weather-app/index.js @@ -0,0 +1,58 @@ +const apikey = "46f80a02ecae410460d59960ded6e1c6"; + +const weatherDataEl = document.getElementById("weather-data"); + +const cityInputEl = document.getElementById("city-input"); + +const formEl = document.querySelector("form"); + +formEl.addEventListener("submit", (event) => { + event.preventDefault(); + const cityValue = cityInputEl.value; + getWeatherData(cityValue); +}); + +async function getWeatherData(cityValue) { + try { + const response = await fetch( + `https://api.openweathermap.org/data/2.5/weather?q=${cityValue}&appid=${apikey}&units=metric` + ); + + if (!response.ok) { + throw new Error("Network response was not ok"); + } + + const data = await response.json(); + + const temperature = Math.round(data.main.temp); + + const description = data.weather[0].description; + + const icon = data.weather[0].icon; + + const details = [ + `Feels like: ${Math.round(data.main.feels_like)}`, + `Humidity: ${data.main.humidity}%`, + `Wind speed: ${data.wind.speed} m/s`, + ]; + + weatherDataEl.querySelector( + ".icon" + ).innerHTML = `Weather Icon`; + weatherDataEl.querySelector( + ".temperature" + ).textContent = `${temperature}°C`; + weatherDataEl.querySelector(".description").textContent = description; + + weatherDataEl.querySelector(".details").innerHTML = details + .map((detail) => `
${detail}
`) + .join(""); + } catch (error) { + weatherDataEl.querySelector(".icon").innerHTML = ""; + weatherDataEl.querySelector(".temperature").textContent = ""; + weatherDataEl.querySelector(".description").textContent = + "An error happened, please try again later"; + + weatherDataEl.querySelector(".details").innerHTML = ""; + } +} diff --git a/projects/weather-app/style.css b/projects/weather-app/style.css new file mode 100644 index 0000000..2030f24 --- /dev/null +++ b/projects/weather-app/style.css @@ -0,0 +1,94 @@ +body { + margin: 0; + font-family: "Montserrat", sans-serif; + background-color: #f7f7f7; +} + +.container { + background-color: #fff; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.2); + margin: 0 auto; + margin-top: 50px; + text-align: center; + max-width: 600px; + border-radius: 5px; + padding: 20px; +} + +form { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; +} + +form input[type="text"] { + padding: 10px; + border: none; + outline: none; + font-size: 18px; + width: 60%; +} + +form input[type="submit"] { + background-color: #007bff; + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 5px; + font-size: 18px; + cursor: pointer; + outline: none; + transition: background-color 0.3s ease; +} + +form input[type="submit"]:hover { + background-color: #0062cc; +} + +.icon img { + width: 100px; + height: 100px; + background-size: contain; + background-repeat: no-repeat; + background-position: center center; +} + +.temperature { + font-size: 48px; + font-weight: bold; + margin: 20px 0; +} + +.description{ + font-size: 24px; + margin-bottom: 20px; +} + +.details{ + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; +} + +.details > div{ + padding: 20px; + background-color: #f1f1f1; + margin: 10px; + flex: 1; + border-radius: 5px; + text-align: center; + min-height: 45px; +} + +@media (max-width: 768px){ + form { + flex-direction: column; + } + + form input[type="text"]{ + width: 100%; + margin-bottom: 10px; + } +} diff --git a/projects/weight-converter/index.html b/projects/weight-converter/index.html new file mode 100644 index 0000000..d441ffd --- /dev/null +++ b/projects/weight-converter/index.html @@ -0,0 +1,22 @@ + + + + + + + Weight Converter + + + +
+

Weight Converter

+
+ + +
+

Your weight in kg is:

+

+
+ + + \ No newline at end of file diff --git a/projects/weight-converter/index.js b/projects/weight-converter/index.js new file mode 100644 index 0000000..faf2a44 --- /dev/null +++ b/projects/weight-converter/index.js @@ -0,0 +1,24 @@ +const inputEl = document.getElementById("input"); +const errorEl = document.getElementById("error"); +const resultEl = document.getElementById("result"); +let errorTime; +let resultTime; +function updateResults() { + if (inputEl.value <= 0 || isNaN(inputEl.value)) { + errorEl.innerText = "Please enter a valid number!"; + clearTimeout(errorTime); + errorTime = setTimeout(() => { + errorEl.innerText = ""; + inputEl.value = ""; + }, 2000); + } else { + resultEl.innerText = (+inputEl.value / 2.2).toFixed(2); + clearTimeout(resultTime); + resultTime = setTimeout(() => { + resultEl.innerText = ""; + inputEl.value = ""; + }, 10000); + } +} + +inputEl.addEventListener("input", updateResults); diff --git a/projects/weight-converter/style.css b/projects/weight-converter/style.css new file mode 100644 index 0000000..e69936b --- /dev/null +++ b/projects/weight-converter/style.css @@ -0,0 +1,42 @@ +body{ + margin: 0; + background: linear-gradient(to left top, yellow, lightblue, yellow); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + font-family: 'Courier New', Courier, monospace; + color: darkcyan; +} + +.container{ + background: rgba(255,255,255,0.3); + padding: 20px; + box-shadow: 0 4px 10px rgba(0,0,0,.3); + border-radius: 10px; + width: 85%; + max-width: 450px; +} + +.input-container{ + display: flex; + justify-content: space-between; + align-items: center; + font-size: 18px; + font-weight: 700; +} + +.input{ + padding: 10px; + width: 70%; + background: rgba(255,255,255,0.3); + border-color: rgba(255,255,255,0.5); + font-size: 18px; + border-radius: 10px; + color: darkgreen; + outline: none; +} + +.error{ + color: red; +} \ No newline at end of file