Day 6 - Ajax Type Ahead

Introduction

image

Day 5 - Image Gallery

Introduction

On this very special day, I decided to do not one, but two exercises in a single day! Helps me give me a kind of jogging for front-end stuff.

img

Photo by Alvan Lee on Unsplash

And today’s exercise is going to depend heavily on CSS so make sure your CSS skills are up to the mark!

And without further ado, let’s go!

In today’s exercise, we’re going to arrange 5 archons from a game, Genshin Impact [played it a lot in the past] in a grid-like fashion. When we move our mouse over an image, it’ll immediately show some additional text.

Our final image will look like this :

alt text

Building the HTML

First, we’ll create the usual stuff with our boilerplate. Next, we add in a <div> [main panel], inside which are nested 5 other <div>. 5 image panels for 5 archons [on the date I’m typing this, Mavuika hasn’t been released yet. Don’t blame me if I don’t have her design yet].

alt text

Agh, our page looks not-so-nice. Let’s fix it up with CSS, hmm?

CSS

Did you know that you can also have CSS styles as snippets? I didn’t knew this earlier, but now that I do, I don’t have to type out my frequently used styles every time and instead just slap them in my stylesheet.

One such snippet is this one for body style :

"Retrieve body" :
{
	"prefix": "bd",
	"body" :
	[
		"@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');",
		"",
		"body",
		"{",
		"    font-family: 'Open Sans', monospace;",
    	"    font-size: 20px;",
    	"    margin: 0;",
    	"    padding: 0;",
		"}"
	],
	"description": "Create body style"
}

Now we shall simply add the usual flex style. Then we go back to our page…

alt text

Fuck yeah! Now it looks sick. But where are the images?

Adding image with vignette

We add the images using another style, background-image. Along with the images, we shall add a linear-gradient with its colours set to black [rgb(0, 0, 0)].

.image-five
{
    background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.9)), url("..\\images\\furina.png");
}

Our classes in the HTML page will look like this : flex and flex-column along with the image’s individual class.

<div class="image image-five flex flex-column">
    <p class="header-text quattrocento">FONTAINE</p>
    <p class="displayed-text cinzel">Animula Choragi</p>
    <p class="footer-text quattrocento">FURINA</p>
</div>

alt text

Not only are the images unevenly sized, there’s also a lack of sepia-ness in them…

This is when we introduce another class called before-change. We change the height of our image to 50vh [that’s how you get that square-box-like look] and add a slightly sepia filter.

.before-change
{
    height: 50vh;
    transition: all 0.8s ease;
    filter:sepia(10);
}
.after-change
{
    height: 100vh;
    transition: all 0.8s ease;
    filter:brightness(2);
}

Also define in another class called after-change. We’ll need it soon when we animate the page.

alt text

The page looks splendid! Now let’s animate it using JS.

JS

First, select the images using querySelectorAll().

Then add in a for-each loop that adds an event listener [triggering upon click]. This listener will call a function that you’ll soon define.

panels.forEach(image => image.addEventListener('click', toggleClass));

Yep. Now define a function that takes event as its argument [this means image will go in with the function]. In this function, assign a variable the value of event.target.

function toggleClass(event)
{
    let element = event.target;
    element.classList.toggle('after-change');
    element.classList.toggle('before-change');
}

What are we doing here? We simply toggle the two classes, before-change and after-change on and off when we click the image.

And voila

alt text

The final video can be fetched from day-five folder in assets. The folder containing it is named ‘video’.

Day 3 - Updating CSS Variables with JS

Introduction

Welcome back to today’s show where we mess around with CSS variables [please not the Sims version of it] using our shiny new tool, JS.

We’ll be using this painting, titled ‘The Champion’ painted by Sir Charles Lock Eastlake in 1824, for today’s exercise.

alt text

Photo by Birmingham Museums Trust on Unsplash

So let’s get started

We build our HTML file using the boilerplate we’d defined earlier in our previous tutorial. Then we add in 3 <label> elements with their respective <input> elements.

<label for="spacing">Spacing:</label>
<input type="range" name="spacing" min="1" max="20" value="1" data-sizing="rem">
<label for="blur">Blur: </label>
<input type="range" name="blur" min="0" max="5" value="1" data-sizing="rem">
<label for="base">Background: </label>
<input type="color" name="base" value="#CC7722">

Let’s understand what’s at hand :

  • type : Indicates the type of input we’re receiving
  • min : Minimum value
  • max : Maximum value
  • value : Increment / Decrement by what value
  • data-sizing : Unit used for values

You can safely ignore the lack of placeholder attribute error given by HTML.

CSS

Now here’s where we take some real care :

:root
{
    /* variables */
    --blur: 1rem;
    --spacing: 1rem;
    --base: #CC7722;
    /* styles */
    font-size: 20px;
}

These are the variables defined in the root part of CSS [note: root = <html>].

Then we use it in our styles :

.property
{
    padding: var(--spacing);
    background: var(--base);
    filter: blur(var(--blur));
}

Let’s add a heading on top that has the same colour as the painting’s border.

alt text

JS

Now let’s update the CSS variables with JS so they change with input.

First, we select all the <input> elements inside the <div>:

let input = document.querySelectorAll('.controls>input');

Next, we define a function that takes element as an argument.

We assign a variable the value of element.dataset.sizing || "" [data-sizing attribute in <input> -> dataset.sizing]. This means that we get the sizing unit for our further operations.

Then we use setProperty on the document itself [remember, root = <html> = document].

document.documentElement.style.setProperty("--" + element.name, element.value + suffixValue);

What we’re doing here is : setting up the --variableName : value format [or syntax] we’d do in :root in CSS. This one will receive the custom values we’d pass to it as input.

To pass the said input, we use a for-each loop. Inside it, we call the function with input, then add an event listener to call it when we move the buttons in the page :

input.forEach((input) =>
{
    updateVar(input);
    input.addEventListener("input", () => updateVar(input));
});

And voila!

alt text

[The video showcasing this website, as well as the source code is available in the repository].

Day 2 - Clock

Introduction

Welcome back to the 3rd day of the challenge! My exams have finally ended for now and this means I’ve enough free time to focus on side-projects such as this. Thinking of doing a piano-based keyboard-tapping [based on previous day’s exercise] soon. Anyways, today we’re gonna tackle another problem : building a clock.

image

Photo by Adrien Robert on Unsplash

So, let’s get buildin’

Let’s build a simple analog clock and link to current time using JS. This means the clock is going to run in real-time [no static!]. This clock will also have the appropriate Roman numeral assigned to each hour.

HTML Boilerplate

Last exercise, I must’ve told you about the ! snippet. If possible, review that part here.

What if I told you that you can edit the snippet and save yourself some work on adding <div class="container">, stylesheet, etc.?

"HTML Boilerplate":
	{
		"prefix": "!",
		"body":
		[
			"<!DOCTYPE html>",
      		"<html lang=\"en\">",
      		"<head>",
      		"    <meta charset=\"UTF-8\">",
      		"    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
      		"    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">",
      		"    <title>${1:Document}</title>",
			"    <link rel=\"stylesheet\" href=\"\">",
      		"</head>",
      		"<body>",
			"    <div class=\"container\">",
      		"    ${0}",
			"    </div>",
			"    <script src=\"\" defer></script>",
      		"</body>",
      		"</html>"
		],
		"description": "HTML Boilerplate"
	}

Simple, follow these steps :

  • Hit ctrl+shift+p to get the command palette. If not, go to View and then click Command Palette.
  • Type configure snippets and hit enter.
  • Now type html. You’ll get an option for html.json. Again hit enter.
  • Paste the above code in that file and save it.

Now let’s get back to business.

<div class="center clock round">
    <div class="clock-face round">
        <div class="hand hour-hand"></div>
        <div class="hand min-hand"></div>
        <div class="hand sec-hand"></div>
    </div>
</div>

With some CSS magic, we can make our clock look like this :

alt text

Get the CSS file for this website here!

Adding Roman Numerals

Let’s do something extra - adding Roman numerals to indicate the hour of the day. First, add <div>s for each number inside the HTML file.

<!--...-->
<div class="clock-face round">
    <div class="roman-num">
        <div class="number" style="--i:9;">I</div>
        <div class="number" style="--i:10;">II</div>
        <!--...-->
        <div class="number" style="--i:8;">XII</div>
    </div>
</div>
<!--...-->

Okay, why this unusual ordering? Why would the number I have the style for number IX and so on?

This is due to how transform works :

.roman-num
{
    top: 50%;
    left: 2%;
}
.number
{
    color:rgb(129, 123, 112);
    font-weight: bold;
    position: absolute;
    width: 2rem;
    height: 2rem;
    transform: rotate(calc(var(--i) * 30deg)) translate(8rem) rotate(calc(var(--i) * -30deg));
}

So, when we pass a value of 9 to our variable --i, it translates into this :

transform: rotate(calc(270deg)) translate(8rem) rotate(calc(270deg));
/* 9 * 30deg = 270deg */

270 degrees will mean the number is placed at the top [when starting from where IX would be]. Given the value changes in the variable, it means the numbers are placed at an interval of 30 degrees.

translate here simply means that the numbers are thrown out to the edge of the clock’s face from their original position in the center.

alt text

Updating time

Now let’s update the clock’s time using JS.

Day 1 - Drum Kit

Introduction

I am back after finally getting a website to post on [and after trying and switching from at least 3 themes due to various reasons]. Anyways, thanks to Hyde, we shall now focus on day one’s [our day two] challenge.

An image

Photo by Gabriel Barletta on Unsplash.

Wonder why the very first day of this challenge comes after the fourth day? It’s because I’m following up from The Odin Project. I assure you that from hereon, the challenge will be in the usual order [barring the 4th day, of course].

Anyways, let’s get buildin’

Source for those who are curious : Drum Kit - Wes Bos

Tech used : JS DOM

Today we’re building a drum-kit. The cover image of this post shows one as an example in case you don’t know what a drum-kit is.

Our drum-kit site will do the following things when you press one of the displayed keys :

  • Plays the sound associated with the key you press.
  • Makes the displayed key bigger [i.e. it pops up with a jig] and applies a border around it.

Getting ready

We’ll use the boilerplate provided by VSCODE by pressing ! and hitting enter. Then we attach the stylesheet and external JS.

After that, we’re creating a <div> with a set of <div> nested inside it.

Now we need to attach the audio files to our elements. For this, we’ll be using this website to get the key-codes for our letters.

What is this key-code stuff?

Let’s take a look at the code for one of our keys:

<div data-key="KeyA" class="key">
    <kbd>A</kbd>
    <span class="sound-info">boom</span>
</div>

Normally, we’d place the <audio> tag inside the <div> and then try to work with the button. This usually won’t work. So, what I’m doing here is to create my own attribute [like a DIY attribute] named key and use that alongside this :

<audio data-key="KeyA" src="day-one\boom.wav"></audio>

This is helpful for linking events using JS [using our class here, actually], which we’ll see soon.

The video must’ve shown the attribute data-key=65 I presume? I’m sorry, but that’s depreciated. The best way to get keys for JS DOM is to use Key alongside the key name.

Adding CSS

There are 2 ways to do the CSS for this page.

One is to add the styles to each element using their class selector. Very simple to work with.

The other is to have many tiny class-selectors, each serving a purpose. Makes the code modular. This method is usually preferred in web dev [this is why you see a hundred different classes for an element when you open up inspect element].

<div data-key="KeyA" class="key flex flex-column box padding">
    <kbd>A</kbd>
    <span class="sound-info smaller-font">BOOM</span>
</div>

Ultimately, it’s your choice - bundle ‘em up into one big class, or split into many tiny classes. Both are okay.

Makes the displayed key bigger [i.e. it pops up with a jig] and applies a border around it.

This effect can be done using a CSS class. JS DOM will add this class to the key the moment the key is pressed. Here we can define border stuff, box-shadows, etc.

The key has a class as well. It has this transition style which enables this animation.

/* before transition */
.box 
{
    transition:all 0.05s;
    color: white;
    border: 0.1rem solid whitesmoke;
    background: rgb(41,23,9);
    background: linear-gradient(180deg, rgba(41,23,9,1) 0%, rgba(36,29,43,0.10452843246673671) 100%);
}
/* during transition */
.trans
{
    transform: scale(1.3);
    border-width: 0.2rem;
    background: rgb(164, 147, 133);
    background: linear-gradient(180deg, rgba(41,23,9,1) 20%, rgba(36,29,43,0.10452843246673671) 80%);
}

Now if you’re wondering what I’ve changed, I’ve :

  • Increased the border width
  • Changed the linear gradient background as well as the background colour.
  • Added a transform style that will make the boxes grow 1.3x their OG size.

transition:all makes the every element coming under the selector get the transition effect.

Adding JS

If you’re using external JS, ensure that your <script> tag has a defer attribute in it. It ensures your scripts are loaded AFTER the html is parsed.

We’ll focus on listening to a key-down event [when user presses down a key in their keyboard].

We already know that the keys in our keyboard have key-codes assigned to each.

function addAudioWhenKeyDown(e)
{
    console.log(e);
}
window.addEventListener('keydown', addAudioWhenKeyDown);

Using this, we can get the key and key-code from the console tab.

function addAudioWhenKeyDown(e)
{
    let audio = document.querySelector(`audio[data-key=${e.code}]`);
    console.log(audio);
    audio.currentTime = 0;
    audio.play();
}

e.keyCode is depreciated. Better use e.code instead.

Now our audio file are playing smoothly! We’ve added audio.currentTime so that when you press the key multiple times, the audio rewinds back from the beginning and plays as many times instead of delaying.

At times, you may get null along with a TypeError. This is because that key doesn’t have an audio file assigned to it! To prevent that unnecessary message, add if (!audio) return; to your function definition.

function addAudioWhenKeyDown(e)
{
    //...
    let key = document.querySelector(`.key[data-key="${e.code}"]`);
    //...
    console.log(key);
    key.classList.add('trans');
}
//<div class="key flex flex-column box padding" data-key="KeyC">

Our transition effect is working well. However, there is a problem - we can’t revert back to normal without refreshing the page.

So, we need to add yet another event listener to remove the class from the keys :

window.addEventListener('keyup', removeTransitionEffect);

function removeTransitionEffect(e)
{
    let keyDone = document.querySelector(`.key[data-key="${e.code}"]`);
    keyDone.classList.remove('trans'); 
}

alt text

Background image by Aleksandr Popov from Unsplash

Aaaand we’re done! The files are enclosed in the repository, and thank you for reading till the end! See ya next time with a brand new walkthrough.