DEV Community

Aishwarya Mali
Aishwarya Mali

Posted on

#JavaScriptmas 2023 Day 7 to 12

Welcome back! If you've been following along, we've already solved challenges of Days 1 to 6 in our journey. Now, buckle up as we dive headfirst into the next leg of this adventure Days 7 to 12. Let's start.

Day 7: Xmas Present wishlist

Task

  • Add items to wishlist array.
  • Iterate over the wishlist array.
  • Display your wishlist on the page.
  • Style the wishlist with CSS.

Stretch Goals

  • Provide a way to add / remove wishlist items.
  • Make each array an object with item's name, description, and a link to where it can be purchased
const wishlist = [
  {
      name: "Books",
      description: "I love to read so need more books!",
      link: "https://www.amazon.in/"
  },
  {
      name: "Headphone",
      description: "Nirvanaa 751 ANC Wireless Headphone",
      link: "https://www.boat-lifestyle.com/products/nirvana-751-anc-headphone"
  }
];

function renderList(list){
    let listEl = ""
    list.map((list, index) =>{
        listEl += `
        <div class='wishlist-box'>
            <div>
                <h2><a href='${list.link}' target='_blank'>${list.name}</a></h2>
                <p>${list.description}</p>
            </div>
            <div class="delete" onclick="deleteWish(${index})">❌</div>
        </div>
        `
    })
    wishlistEl.innerHTML = listEl
}

renderList(wishlist)

addWishBtn.addEventListener('click', function(){
    if(!wishNameInput.value || !wishDescriptionInput.value || !wishLinkInput.value) return
    const newWish = {
        name: wishNameInput.value,
        description: wishDescriptionInput.value,
        link: wishLinkInput.value
    }
    wishlist.push(newWish)
    renderList(wishlist)
    wishNameInput.value = wishDescriptionInput.value = wishLinkInput.value = ""
})

function deleteWish(index){
    wishlist.splice(index, 1)
    renderList(wishlist)
}
Enter fullscreen mode Exit fullscreen mode
  • First, created an array of objects called wishlist and rendered this object using the map() method on the UI.
  • For the Add Wish button, first checked if there is a value in the inputs. If not, the process is terminated. If there is a value, added all the values to a new object and pushed this object to the wishlist array. Finally, cleared all the inputs.
  • Lastly, for deleteWish, get the index of the item we wished to delete. Based on that index, use the splice method to remove that item from the array and update the UI.

Check my scrim here.

Day 8: Animated Progress Bar

HTML

<div class="progress-bar">
  <div class="progress-status"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

.progress-bar,
.progress-status {
  height: 30px;
  background: var(--progressbar-bg);
  border-radius: 50px;
  width: 100%;
}

.progress-bar {
  position: relative;
}

.progress-status {
  position: absolute;
  top: 0;
  animation: progress 5s infinite;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}

@keyframes progress {
  0% {
    width: 0%;
    background-color: var(--start);
  }
  50% {
    width: 50%;
    background-color: var(--middle);
  }
  100% {
    width: 100%;
    background-color: var(--finish);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • First, positioned the progress-status div on the progress-bar using position:absolute.
  • For the progress-status, applied animation: progress 5s infinite; to call the keyframe "progress" infinitely.
  • In the keyframe, defined animations starting at 0%, reaching 50%, and finishing at 100%.
  • To ensure smooth operation, used animation-timing-function: linear. Without this, the progress bar starts correctly but then slows down at 50% and restarts again after that.

Check my scrim here.

Day 9: AI Christmas E-card

Task

  • When a user hits submit, dialogModal should be hidden.
  • Use the inputted text to generate an image for the e-card using an AI model.
  • Render the image to imageContainer.
formSubmit.addEventListener('submit', function(e){
    e.preventDefault()
    dialogModal.close();
    image.style.display = "none"
    loadingText.style.display = "block"
    if(!userInput.value) return

    query({"inputs": userInput.value}).then(async(response) => {
        const src = await blobToBase64(response)
        loadingText.style.display = "none"
        image.src = src
        image.style.display = "block"
    });

})

async function query(data) {
    const response = await fetch(
        "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0",
        {
            headers: { Authorization: `Bearer ${process.env.HUGGING_FACE_API_KEY}` },
            method: "POST",
            body: JSON.stringify(data),
        }
    );
    const result = await response.blob();
    return result;
}


function blobToBase64(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = function () {
            const base64String = reader.result;
            resolve(base64String);
        };
        reader.onerror = function (error) {
            reject(error);
        };
        reader.readAsDataURL(blob);
    });
}
Enter fullscreen mode Exit fullscreen mode
  • I used huggingface for this challenge. You can find the documentation here.
  • When the form is submitted we use the given description as input to call the function that will return a blob of image. This blob is then converted to Base64 using the blobToBase64 function.
  • The function uses the FileReader object, which is part of the web platform's File API, to read the contents of the Blob.
  • It sets up an onload event handler, which will be triggered when the reading operation is successfully completed.
  • Inside the onload handler, it converts the read content to a Base64-encoded string and resolves the Promise with that string.
  • If there is an error during the reading operation, the onerror event handler is triggered, and the Promise is rejected with the error.
  • Finally, we append this image to UI.

Check my scrim here.

Day 10: Rockin' Around

Task

  • Add code to make the youtube player play the new YouTube song
const player = document.getElementById("player")

function playSong(id) {
  const youtubeSrc = `https://www.youtube.com/embed/${id}?autoplay=1`
  player.src = youtubeSrc
}
Enter fullscreen mode Exit fullscreen mode
  • The code creates a URL for a YouTube video using a template literal. It takes a video ID and constructs a YouTube video URL with the format.
  • At the end, assigned this URL to the player's src.

Check my scrim here.

Day 11: Flag Challenge

Task

  • Create Switzerland Flag in CSS

HTML

<div class="flag flag-swiss">
 <div class="cross cross1"></div>
 <div class="cross cross2"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

.flag{
    width: 300px;
    height: 300px;
    background: var(--red);
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: repeat(5, 1fr);
}

.cross{
    background: var(--white);
}

.cross1{
    grid-row: 2/5;
    grid-column: 3/4;
}

.cross2{
    grid-row: 3/4;
    grid-column: 2/5;
}
Enter fullscreen mode Exit fullscreen mode
  • I used grid` for this challenge, defining the height and width of the div and setting its display property to grid.

CSS Grid structure

  • The grid is defined with 5 rows and 5 columns, each set to 1fr
  • Based on the image above, I have positioned .cross1, .cross2 accordingly using grid-row and grid-column.

Check my scrim here.

Day 12: Santa's Gift Sorter

Task

  • Help santa by sorting the gifts array into alphabetical order and reverse alphabetical order.
const xmasGifts = ['guitar 🎸', 'skates ⛸️', 'bear 🧸', 'magnet 🧲', 'laptop 💻', 'games console 🎮', 'jewellery 💍', 'kite 🪁'];

const sortedAZ = [...xmasGifts].sort();
console.log('A-Z: ', sortedAZ);

const sortedZA = [...xmasGifts].sort().reverse();
console.log('Z-A: ', sortedZA);
Enter fullscreen mode Exit fullscreen mode
  • For sorting into alphabetical order, we have used sort() method
  • For sorting in reverse alphabetical order, we have first used sort() and then used reverse().

Check my scrim here.

Would love to hear your thoughts. Stay tuned for the next iteration of this series.

Top comments (0)