Marco Kühbauch_

Blog

Sometimes I write about new things I learned, things I'm interested in and things that bother me in my everyday life. Mostly about Frontend, mostly for myself as a learning process and always my own thoughts and my own opinion.

Go back to other Blog Posts

JavaScript30

JavaScript30 - what's that?


I just started the JavaScript30 Challenge by Wes Bos where you get to code 30 different projects and ideas with plain JavaScript.

No frameworks - no compilers - no libraries - no boilerplates.

The idea of JavaScript30 is either to code along as this is a video series or to build it by yourself and compare it with Wes' solution at the end.

I think this is a great idea if you are like me, lacking of ideas for JS projects, want to learn ES6 and level up your JS skills in general. The perfect challenge for your daily dose of JavaScript.

To support my learning process I will write about and explain several projects, how they work and what kind of parts of JavaScript play the important roles.

I'll update this post soon as I move forward through the other days of the JavaScript30 challenge.

Day 22 - Follow ALong Links


How does it work?


On Day 22 you learn to build follow along links. This means when you hover over a link, it will get highlighted. If you now hover over another link, this link won't get a new highlighting, instead the highlight will move from one link to another.

To achieve this you have to select every link element on the page first. Then you create a new span element, give it the class of highlight and add it into the DOM. This will be used later for the styling.

const triggers = document.querySelectorAll('a');
const highlight = document.createElement('span');
highlight.classList.add('highlight');
document.body.append(highlight);

Next you have to attach an event listener to all a elements which listens for the mouseenter event. When this is triggered a function is called which calls the getBoundingClientRect method on this.

This is the a element on which the user has entered his mouse. The getBoundingClientRect method returns the size of an element and its position relative to the viewport.

triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));

function highlightLink() {
  const linkCoords = this.getBoundingClientRect();
}

Now you can set the span element, which was created in the beginning, to the same width and height as the current a element.

highlight.style.width = linkCoords.width ;
highlight.style.height = linkCoords.height;

The same goes for positioning the highlight element dynamically on the x and y axis.

highlight.style.transform = `translate(${linkCoords.left}px, ${linkCoords.top}px)`;

This already looks pretty cool. But as soon as you scroll down the page, the highlighting element is not positioned correctly anymore.

To resolve this, you have to add the window.scrollY value of the top, and the window.scrollX value of the left in case you have horizontal scrolling. Wes also refactors the code a bit by putting the coord values into its own object.

const coords = {
  width: linkCoords.width,
  height: linkCoords.height,
  top: linkCoords.top + window.scrollY,
  left: linkCoords.left + window.scrollX
}

highlight.style.width = `${coords.width}px`;
highlight.style.height = `${coords.height}px`;
highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;

And this is how you build follow along links. Nice!

See the Pen Follow Along Links (JavaScript30 Day 22) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

Day 21 - Geolocation based Speedometer and Compass


How does it work?


Today Wes teaches about geolocation. For this he explains how to build a compass that shows the current direction you're facing and how fast you are travelling.

Therefore you will work with the Geolocation API. With the Geolocation method watchPosition() you can get data about the current position of a device, like latitude, longitude and speed.

navigator.geolocation.watchPosition((data) => {
  console.log(data);
});

So now you can work with that data and update your compass with the current speed of the user. You can also turn the compass in the right direction depending on the headings value.

speed.textContent = data.coords.speed;
arrow.style.transform = `rotate${data.heading}deg`;

The watchPosition() method also has an error callback function which is triggered, when the user declines access to his location. So you can use this function to inform the user, that the browser must be able to access his location in order to show the compass and the speed.

(err) => {
  console.log(err);
  alert('Hey! You have to allow that, to access your location.')
}

And here is the result:

See the Pen Geolocation based Speedometer and Compass (JavaScript30 Day 21) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

Day 20 - Native Speech Recognition


How does it work?


In this project Wes teaches how to use the native speech recognition. It is really cool that you are able to build youre own speech recognition without using any framework.

To start you have to set both, the original window.speechRecognition and the prefixed window.webkitSpeechrecognition as the same.

window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

Next you have to create a new SpeechRecognition object instance with the SpeechRecognition constructor and set the interimResults Property to true. Interim results are results that are not yet final. This allows you to view the text as you are speaking. You also have to actually start the speech recognition.

const recognition = new SpeechRecognition();
recognition.interimResults = true;
recognition.start();

The idea is to put every recognized speech into a new paragraph and add it to the document. Therefore you have to prepare everything.

let p = document.createElement('p');
const words = document.querySelector('.words');
words.appendChild(p);

In the next step you are listening for the result event. This event is fired when the speech recognition service returns a result.

This returns a SpeechRecognitionResultList which needs to be converted into an array. Then you have to map over the array and get the first element of it, and map over this element, get the first one again which holds the transcript of what you just said into your microphone and join it into one big string.

recognition.addEventListener('result', e => {
  const transcript = Array.from(e.results)
    .map(result => result[0])
    .map(result => result.transcript)
    .join('')
})

When you are finished speaking and start again, it doesn't work at this point. This is because the result event unbinds itself after you speak. Therefore you need to add another event listener which listens for the end event and then calls the function to start the speech recognition again.

recognition.addEventListener('end', recognition.start);

Now you can insert the speech recognition into the DOM by adding the transcript as textcontent of the paragraph.

p.textContent = transcript;

But as soon as you start speaking again, it gets overwritten. To prevent this you can use the isFinal method. As soon as this is true, a new paragraph is created and added into the DOM. So every spoken sentence gets added into its own paragraph.

if (e.result[0].isFinal) {
  p = document.createElement('p');
  const words = document.querySelector('.words');
}

And this is it, you're own native speech recognition. Try it out:

See the Pen Native Speech Recognition (JavaScript30 Day20 ) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

Day 19 - Unreal Webcam Fun


How does it work?


In project number 19 of the Javascript30 series Wes shows some cool ways to work with the webcam API, like taking pictures with your webcam and applying several filters.

To start, you need to access the users webcam. This can be achieved with the MediaDevices.getUserMedia() method. If the user agrees, it returns a promise that resolves to a MediaStream object and therefore allows the webcam access.

The MediaStream is then set as the resource of the video element using the srcObject property. Wes used the URL.createObject() method in his video but this is intented to be deprecated and removed and the srcObject property is the alternative implementation suggestion.

The video is then started with the play() method.

function getVideo() {
  navigator.mediaDevices.getUserMedia({video: true, audio: false})
  .then(MediaStream => {
    video.srcObject = MediaStream;
    video.play();
  })
  .catch(err => {
    console.error('Oh no!', err);
  })
}

getVideo();
shows the webcam image in your browser

To work more specifically with the video, you have to paint the video into the canvas element.

First you have to set the width and the height of the canvas equal to the width and the height of the video feed.

Then you have to set the canvas to draw an image from your video every 16 milliseconds.

Finally you need to add an eventlistener that fires when the user agent can play the media, using the canplay event.

So when the video element is piped correctly and is available, the paintToCanvas function is called.

function paintToCanvas() {
  const width = video.videoWidth;
  const height = video.videoHeight;
  canvas.width = width;
  canvas.height = height;

  return setInterval(() => {
    ctx.drawImage(video, 0, 0, width, height);
  }, 16)
}

video.addEventListener('canplay', paintToCanvas);

Now you have a replication of your webcam video on the canvas.

the video is replicated in the canvas

Next you want to have the abilitay to take a photo. Therefore you need to access the data from the canvas and output it as a jpg. Additionally you create a link and set the attributes of it to download the image.

function takePhoto() {
  // take the data out of the canvas
  const data = canvas.toDataURL('images/jpeg');
  const link = document.createElement('a');
  link.href = data;
  link.setAttribute('download', 'handsome');
  link.innerHTML= `<img src="${data}" alt="Handsome Man" />`
  strip.insertBefore(link, strip.firstChild);
}

Next up are the filters. The image data of the canvas gives us access to the rgba values of every pixel, which results in an array like this: [r1,g1,b1,a1,r2,g2,b2,a2,r3,g3,b3,a3,r4,g4,b4,a4]. The r1 stands for the red value of the first pixel.

So first you access the pixels of the image by altering the paintToCanvas function.

 function paintToCanvas() {
  const width = video.videoWidth;
  const height = video.videoHeight;
  canvas.width = width;
  canvas.height = height;

  return setInterval(() => {
    ctx.drawImage(video, 0, 0, width, height);
    // take the pixels out
    let pixels = ctx.getImageData(0, 0, width, height);
    // mess with them
    pixels = redEffect(pixels);
    // put them back
    ctx.putImageData(pixels, 0, 0);
  }, 16)
}

Then you alter the rgba values by iterating through them. The standard array methods are not available here, that's why you need to use a for loop.

The following creates a red filter.

function redEffect(pixels) {
  for (let i = 0; i < pixels.data.length; i += 4) {
    pixels.data[i + 0] = pixels.data[i + 0] + 50 // RED
    pixels.data[i + 1] = pixels.data[i + 1] - 500 // GREEN
    pixels.data[i + 2] = pixels.data[i + 2] * 0.5 // BLUE
  }
  return pixels;
}
a red filter is applied to the canvas

The next filter is the rgb split filter. For this you are iterating through the pixels again and moving them to either side, so you get a seperate image for the red, green and blue value slightly overlapping.

function rgbSplit(pixels) {
  for (let i = 0; i < pixels.data.length; i += 4) {
    pixels.data[i - 150] = pixels.data[i + 0]; // RED
    pixels.data[i + 100] = pixels.data[i + 1]; // GREEN
    pixels.data[i - 150] = pixels.data[i + 2]; // BLUE
  }
  return pixels;
}

Additionally you can add a global alpha to the canvas which shows a transparency ot the previous image over the current.

a rgba filter is applied to the canvas

The last effect is the green screen. There you use an object which is gonna hold the minimum and maximum green.

Wes explains the way a green screen works like this. Using a range you determine the minimum and maximum value and take them out. These range of special greens then don't occur on the image/video.

After that you have to select all the input sliders to get the values of these.

Then you loop over every single pixel again, figure out the red, green, blue and alpha value and than check if the values you get are in between the min and max values and take them out meaning setting them to transparent.

function greenScreen(pixels) {
  const levels = {};

  document.querySelectorAll('.rgb input').forEach((input) => {
    levels[input.name] = input.value;
  });

  for (i = 0; i < pixels.data.length; i+=4) {
    red = pixels.data[i + 0];
    green = pixels.data[i + 1];
    blue = pixels.data[i + 2];
    alpha = pixels.data[i + 3];

    if (red >= levels.rmin
    && green >= levels.gmin
    && blue >= levels.gmin
    && red <= levels.rmax
    && green <= levels.gmax
    && blue <= levels.bmax) {
      // take it out
      pixels.data[i + 3] = 0;
    }
  }
  return pixels;
}

That's it, a simple green screen filter.

You can play around with all the filter and effects on CodePen.

What did I learn? - What did I like?


In this project I learned about:

Day 18 - Tally String Times with Reduce


How does it work?


This project is about adding all time values of videos together, to give the user a total amount of how long all videos are.

To do this, Wes gives you an unordered list and every listitem inside this list has a data-time attribute with a speficic value. These should be added together.

First you have to select all the list items with the time values. But to work with the data-time values you need an array, not a NodeList, which is it by default.

To convert the NodeList into an array, you can use Array.from.

const timeNodes = Array.from(document.querySelectorAll('[data-time'));

Now you can map over all the listitems and just work with the data-time values by using the dataset property. This gives you only the data-time value into the array, instead of the whole listitem.

const seconds = timeNodes
  .map(node => node.dataset.time)

The data-time values are displayed as a string in minutes and seconds by default. But to add all values up, everything needs to be converted into seconds and reduced to one number. This is achieved in multiple steps.

First you need to map over the the values again, use the split method, to split up the minutes and the seconds seperated by a : and map everything again against the parseFloat function to return a floating number and not a string.

By using ES6 destructuring you can turn the splitted minutes and seconds values into variables in one line. Then the mins value is multiplied by 60 to transfer it into seconds and added to the seconds.

.map(timeCode => {
  const [mins, secs] = timeCode.split(':').map(parseFloat);
  return (mins * 60) + secs;
})

Now you converted every data-time value, formerly consisting of something like '4:56', into one single number of seconds.

Finally, everything needs to come down to one big number. For this the reduce method is useful.

.reduce((total, seconds) => total + seconds);

Now instead of showing the user one big number of seconds, it is better to transfer the seconds in a hours, minutes & seconds format again.

let secondsLeft = seconds;
const hours = Math.floor(secondsLeft / 3600);
secondsLeft = secondsLeft % 3600;

const mins = Math.floor(secondsLeft / 60);
secondsLeft = secondsLeft % 60;

Thats how you sum all the data-time values of videos.

What did I learn? - What did I like?


In this project I learned about:

  • you can use the map method multiple times on an array

Day 17 - Sorting band names without articles


How does it work?


Sorting band names without articles is a useful ability, which is used almost everywhere, where you can search for band names. You are given an array of band names and a few of them start with 'the' or 'a'. The idea now is to sort this array but to skip the articles.

JavaScript has the built in .sort() method which sorts the elements of an array in place and returns the array. You can pass it a compare function.

The array elements are then sorted according to the return value of the compare function. So if item a is less than item b, a is sorted to an index lower than b, meaning a comes first.

const sortedBands = bands.sort(a, b) {
  if (a > b) {
    return 1;
  } else {
    return -1;
  }
}

But what about skipping the articles? The .replace() method can be helpful in this case. You can pass it a regular expression which starts at the beginning of a string, replaces all a, the and an with an empty string and use the .trim() method to remove all white-space.

function strip(bandName) {
  return bandname.replace(/^(a |the |an)/i, '').trim();
}

To combine these two, you call this strip function on every item during the sorting. It is important that the strip function is only called inside the if statement, so the actual data will not be changed.

const sortedBands = bands.sort(a, b) {
  if (strip(a) > strip(b) {
    return 1;
  } else {
    return -1;
  }
}

You can make this code simpler and cleaner by using the ternary operator, an arrow function and the implicit return. So the result is just one line of code.

const sortedBands = bands.sort((a, b) => strip(a) > strip(b) ? 1 : -1);

Finally every band name gets added to the document as a list item.

document.querySelector('#bands').innerHTML =
  sortedBands
  .map(band =>
    `<li>${band}</li>`)
    .join( '');

That's all. A quick and easy way to sort an array of band names without articles.

What did I learn? - What did I like?


In this project I learned about:

Day 16 - CSS Text Shadow Mouse Move Effect


How does it work?


With the CSS text shadow property you can create cool effects. One is moving the text shadow around a word, depending on the users mouse movements. Wes teaches in this project, how this is achieved.

To start, you need to select the hero div and the h1 inside of it. Then you listen for a mousemove event, which calls the shadow function.

const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');

function shadow(e) {
// do something
}

hero.addEventListener('mousemove', shadow);

To make the text shadow of the hero div move, you need some specific data. First you need the width and the height of the hero div and the x and y offset of the event target, which is the current location of the mouse. You get these values by using ES6 destructuring.

const { offsetWidth: width, offsetHeight: height } = hero;
let { offsetX: x, offsetY: y } = e;

You need to watch out for a special behaviour now. When you hover over any children of the hero div, the width and the height of the child is used, instead of the width and height of the parent. To prevent this, you need to make sure to add the width and the height of the parent to the event targets offset left and top.

if (this !== e .target) {
x = x + e.target.offsetLeft;
y = y + e.target.offsetTop;
}

After that, you have to set a maximum amount of how far the text shadow should move.

const walk = 100; // 100px

Finally, you can calculate the shadow movements.

const xWalk = Math.round((x / width * walk) - (walk / 2));
const yWalk = Math.round((y / height * walk) - (walk / 2));

And add these values to the text-shadow property.

text.style.textShadow = `${xWalk}px ${yWalk}px 0 red`;

Now you built a cool text shadow mouse move effect. You can add as many text shadow values as you like.

See the Pen CSS Text Shadow Mouse Move Effect (JavaScript30 Day16) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • you can use offsetX and offsetY to get the current mouse position

Day 15 - Localstorage and Event Delegation


How does it work?


In this project you build a tapas menu to which you can add different menu items and toggle them.

The special thing about it is, that your changes will remain even after reloading the browser due to using localStorage. LocalStorage is a way to store data in the browser.

You also learn a lot about event delegation. Event delegation basically means, that you add an event listener to the parent element rather than to the child elements.

This is really useful, if the child elements get updated or rebuild regularly, like in this example. By adding the event listener to the parent, the event is also triggered on all the children.

See the Pen LocalStorage and Event Delegation (JavaScript30 Day15) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

Day 14 - Object and Arrays - Reference vs Copy


How does it work?


This example is about learning the differences of references and copying in JavaScript.

Imagine creating two variables, name and name2 and give the name variable the content of 'Marco'. Then you assign the second variable to the first. If you log both variables to the console, both will output 'Marco'.

let name = 'Marco';
let name2 = name;
console.log(name, name2); // Marco Marco

If you then update the original one, what is going to happen? Right, the second variable name2 stays the same and does not get updated.

name = 'Not Marco'
console.log(name, name2);// Not Marco Marco

So in general speaking the value of strings, numbers and booleans go into the original variable and if you change the original one, it is not going to update the other one.

This does not apply for arrays. If you change an array, the copy of this array will change as well, because it always points to the original one.

The same goes for the copied array. If you update this one, the original will also be updated because the copied array is a reference to the original array, not an actual copy.

const players = ['Marco', 'Sarah', 'Ryan', 'Poppy'];
const players1 = players;
players1[0] = 'Not Marco';
console.log(players, players1); // ['Not Marco', 'Sarah', 'Ryan', 'Poppy'] ['Not Marco', 'Sarah', 'Ryan', 'Poppy']

The solve this problem you need to make an actual copy of the array, rather than a reference. There are several methods to do this.

The slice() normally takes a beginIndex and endIndex as parameters und cuts out the content inbetween and returns a new array. But it can also be used to cut out the whole array to return a copy of it as a new array.

const players2 = players.slice()

.concat() is used to merge two arrays. In this case we merge a new, empty array with the original array which is given into the concat() method as parameter. concat then returns a new array instance with a copy of the original array.

const players3 = [].concat(players);

The ES6 spread operator is alreay used in the Day 06 - Ajax Type Ahead example. Basically you can create a new array and by using the spread syntax you can copy the content of the original array into this new array.

const players4 = [...players];

Finally it is also possible to use Array.from() to copy an Array.

const players5 = Array.from(players);

The same thing applies for objects aswell. So you also have to make an actual copy of an object, rather than a reference.

To achieve this for objects, you can use the Object.assign() method. There you take a blank object, fold in all of the properties of the original object, change or add properties and assign them to a new variable.

If you update this new object, the original will stay the same.

const person = {
  name: 'Marco',
  age: 26
}
const person2 = Object.assign({}, person, {name: 'Not Marco'})
console.log(person, person2); // {name: 'Marco', age: 26} {name: 'Not Marco', age: 26}

Another way to solve this is the spread syntax like used on an array before.

const person3 = [...person]

Unfortunalety spread syntax for objects is not part of the current JavaScript Specification. But at the time of writing this, it is a stage 4 proposal for ECMAScript.

Summary:


If you want to copy strings, numbers or booleans it is possible to just reassign the content of the original variable to a new one.

To copy arrays and objects you have to make an actual copy, rather than just a reference.

It is important to note, that the methods used here for cloning arrays and objects only make shallow copies, which means that the copy only goes one level deep. So if you have an object in an object or an multidimensional array you have to be careful.

If you make a copy of the object, then change the object inside the object, the original object will also be updated because the copy only goes one level deep.

What did I learn? - What did I like?


In this project I learned about:

  • the general differences between referencing and copying and how to achieve both for strings, numbers, booleans, arrays and objects

  • Object.assign()

Day 13 - Slide in on Scroll


How does it work?


This project is about sliding in images on a blog site as soon as you reach them while scrolling.

Because the scroll event listener is used in this example, Wes added a delay function to trigger the event only every 20 ms. Otherwise the event would be triggered on every scroll move which can be way too much, and cause bad performance.

So for this project you have to calculate a few things.

First, you have to find out, when the half of an image is visible. To do this, you can add the window.scrollY to the window.innerHeight and substract the height of the image divided by 2.

Second you have to find out, when the bottom of an image is visible. To calculate this you just add the offsetTop of an image to the height of the image.

Finally you can phrase the two conditions, when the image should slide in.

Everytime the value for the halfway visible image is greater than the offsetTop of an image and everytime the value for the visible image bottom is greater than the window.scrollY value the class of active is added to an image, which makes them appear with CSS.

To wrap up, it is pretty easy to make images slide in on a certain scroll point. The hard part is to make the right calculations, which can be confusing at first (at least for me).

See the Pen Slide in on Scroll (JavaScript30 Day 13) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • console.count

    logs the number of times that this particular call to count() has been called

  • window.scrollY

    returns the number of pixels the document is currently scrolled vertically

  • window.innerHeight

    height of the browser window viewport

  • offsetTop

    returns the distance of the current element to the top

Day 12 - Key Sequence Detection (KONAMI CODE)


How does it work?


This project is about building a key sequence detection. In the beginning a secret code is stored as a string inside a variable.

Everytime a user inputs something, the keyup event is fired and the input is stored into an array. The array is then spliced beginning at the end and the delete count consists of the array's length minus the secret codes length.

By doing this, the array will not go beyond the length of the secret code and will always contain the newest input.

Then you simply have to join the array, to turn it into a string and compare it with the secret code. If it is the same, bingo! You guessed the secret code! Maybe there is a secret easter egg on this website? Try it out!

const pressedArray = [];
const secretCode = 'marco';

function checkUserInput(e) {
  pressedArray.push(e.key);
  pressedArray.splice(-secretCode.length -1, pressedArray.length -secretCode.length);
  if (pressedArray.join('') === secretCode) {
    console.log('Success! You guessed the secret code!');
  }
}
window.addEventListener('keyup', checkUserInput);

What did I learn? - What did I like?


In this project I learned about:

  • You can listen permanently for the keyup event on the window object and by doing that log every user input

  • Cornify is a JS library to print unicorns and rainbows on to the screen, a nice way to add easter eggs into your website

Day 11 - Custom HTML5 Video Player


How does it work?


As the title says this exercise is about building a custom video player. In detail it consists of updating the play/pause button, enabling a skip function to skip 10 seconds back and 25 seconds forward, update the progress bar as the video continues and make it possible to drag the progress bar to jump to a specific position in the video.

What did I learn? - What did I like?


In this project I learned about:

  • What I liked most about this exercise, is the fact, that it is quite easy to hide the default HTML5 video controls and build your own controls.
  • play & pause

    There are specific play and pause events. These elements are based on HTMLMediaElement (generally audio or video) and receive this event after its media has been played or paused by calling the element's play() or pause() method.

Day 10 - Hold Shift To Check multiple Checkboxes


How does it work?


At Day 10 I learned about how to check multiple checkboxes holding the shift key. This is a very common pattern. Think about Gmail for example. You want to select multiple emails to delete them or mark them as red. You click the first one, you want do delete, hold shift and then click the last one you want to delete. What happens? Right, all the emails inbetween get selected aswell. Altough this seems very easy and nothing special it's not that easy to build.

See the Pen Hold Shift And Check Multiple Checkboxes (JavaScript30 Day10 ) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • the principle of setting a 'flag'

    This is used very often in JavaScript. You declare a variable at the beginning of a programm, pass it along and use it throughout to determine a specific state. In this exercise the inBetween variable is an example for that.

  • e.shiftkey

    This mouseevent indicates if the shift key was pressed.

Day 09 - 14 Must Known Dev Tools Tricks


How does it work?


This exercise is all about useful tricks for the developer tools of a browser. I've heard about most of them but also learned a lot new stuff.

What did I learn? - What did I like?


In this project I learned about:

  • break on attribute modifications

    If you inspect a HTML Element, then right click on it you can select break on -> attribute modification. Every time you click now on this element, and JavaScript code is executed, the JS is paused right there and shown in the dev tools.

  • console.group()

    With console.group() you can group a lot of console.log together. This comes in handy, when you are logging a lot of stuff about different array elements for example. Every array element is then grouped in a noticeable and helpful way.

  • console.time()

    This expression is useful when you are fetching data from an API. It logs the needed time to fetch the data into the console.

Day 08 - Fun with HTML Canvas


How does it work?


This exercise is all about playing with the HTML5 Canvas. The basics about drawing on the canvas and manipulating various values are explained and therefore several canvas specific terms are used.

For example you can set the strokeStyle, lineJoin, lineCap and lineWidth for the line you're drawing.

The basic principle for the drawing consists of a draw function and a flag. The flag is either set to true to enable the drawing, or set the false to prevent it.

The drawing is enabled by several mouse events. If the mousedown event and the mousemove event are active at the same time, the flag is set to true and the draw function gets executed. If the mouseup event or the mouseout event are fired, the drawing is disabled.

An important part plays the start point of the drawing. To prevent that the user is always starting at X = 0 and Y = 0, the current X and Y position of the mouse on the canvas on the mousedown event are used as starting point.

See the Pen Fun with HTML5 Canvas (JavaScript30 Day08) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • ES6 destructuring assignment

    This javascript expression makes it possible to unpack values from arrays, or properties from objects, into distinct variables

  • hsl

    Hsl colors get generetad by hue, saturation and lightness. Hue is a degree from 0 to 360. Saturation and lightness are percentage values from 0% to 100%.

Day 07 - Array Cardio Day 2


How does it work?


This exercise continues the Array Cardio Series. On Day 1 of this series I learned a lot about the filter(), map(), sort() and reduce() array methods.

Day 2 covers a lot more useful array methods.

See the Pen Array Cardio Day 2 (JavaScript30 Day 07) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • Array.prototype.some()

    Checks if at least one array element passes the test implemented by the provided function

  • Array.prototype.every()

    Checks if every element passes the test implemented by the provided function

  • Array.prototype.find()

    Returns the value of the first element which meets the conditions of the provided function

  • Array.prototype.findIndex()

    In comparison to find() this method returns the Index of the first element

  • Array.prototype.splice()

    Removes existing elements from an array. It gets a starting point, where the change to the array should start and a deleteCount, an integer indicating how many elements should be removed

  • Array.prototype.slice()

    In Comparison to splice(), this methods takes another approach. It returns a shallow copy of an array into a new array.

    So instead of deleting an array element, it takes the remaining elements into a new array. It takes begin and end values a parameters.

Day 06 - Ajax Type Ahead


How does it work?


The main functionality can be described as following: There are three variables, one which contains the data, one referencing the input element and one referencing the unordered list.

To get the data asynchronously the fetch API is used. The fetch method fetches the data resource and returns a promise containing the response in a response object.

The response is then converted to JSON and pushed to the cities array.

Event listeners on the form input listen for change or keyup events and then call a function which will display the matched data.

This displayMatches() function first calls another function which will be responsible for finding the matches.

The findMatches() accepts two parameters, the inputted text and the array, containing the data. It filters through the array using a new Regular Expression object.

This RegExp accepts the word to match and two flags, one for global, so it does not stop after the first match and for ignoring case.

Then the inputted text gets matched with the city or state properties of the object and returned.

Back in the displayMatches() function the matches now get replaced by a span with a specific class to highlight them and output them as specific HTML.

See the Pen Ajax Type Ahead (JavaScript30 Day06) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • fetch()

    The functionality of fetch was previousliy achieved through XMLHttpRequests.

    The fetch() method provides an easier way to fetch resources asynchronously across the network.

    It takes one argument (the path to the resource) and returns a promise containing the response. This response is the HTTP response, not the actual data.

  • Promise

    A Promise Object is used for asynchronous computations

  • Spread Syntax

    allows the usage of '...' where multiple arguments or multiple elements are expected

    Helpful Examples: https://hackernoon.com/javascript-the-spread-operator-a867a71668ca

  • RegExp

    creates a regular expression object for matching text with a pattern

    -g stands for global match; find all matches rather than stopping after the first match

    -i stands for ignore case

  • String.prototype.match()

    retrieves the matches when matching a string against a regular expression

  • String.prototype.replace()

    returns a new string with some or all matches of a pattern replaced by a replacement

Day 05 - Flexbox Panels Image Gallery


How does it work?


The Goal of this Project is to build a Panel Gallery with Flexbox. It consists of 5 different Images containing 3 paragraphs. Only the middle paragraph is shown by default. The others only appear with a cool bouncing effect if you click on the specific image.

See the Pen Flex Panels Image Gallery (JavaScript30 Day05) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • flex: 1

    I already used flex-grow a lot in recent project, but in this project I realised one more time how powerful it is. With flex: 1 you can easily make Items stretch simultaneously over the whole available space.

Day 04 - Array Cardio Day 1


How does it work?


The fourth Exercise of the JavaScript30 Challenge is all about Array Methods. With two sample Arrays given, consisting of Objects and Strings, the task is to get good and used to all the important array methods like filter(), map(), sort(), reduce() and so on.

I really liked this exercise because I have used all of these methods at least once but I can't remember them and I always have to look them up to remind myself, what are they used for and when they are useful.

See the Pen Array Cardio Day 1 (JavaScript30 Day 04) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this project I learned about:

  • Array.prototype

    the Array.Prototype property represents the prototype for the array constructor

    Array instances inherit from Array.prototype

    you can change the constructors prototype object to make changes to all Array instances

    So new methods and properties kann be added to extend all Array objects

  • Array.prototype.filter()

    creates a new array with all elements that pass the test, implemented by the provided function

  • console.table()

    displays tabular data as a table

    useful to display all array properties of an array element in the console

  • Array.prototype.map()

    creates a new array with the result of calling a function on every element on this array

    in comparison to filter(): map() returns always the same amount of array elements as you give it, while filter() only returns the ones who pass the test

  • Array.prototype.sort()

    sorts the elements of an array in place and returns the array

    if a compare function is not supplied, elements are sorted by converting them to strings and comparing strings in unicode code point order

    if a compare function is supplied the array elements are sorted according to the return value of the compare function

  • Array.prototype.reduce()

    applies a function against an accumulator and each element in the array to reduce it to a single value

  • Array.from()

    creates a new Array instance from an array-like or iterable object

    comes in handy when you want to use Array.prototype.map() on a nodelist

  • String.prototype.includes()

    returns true or false wether a string is found in another string or not

Day 03 - Playing with CSS Variables and JS


How does it work?


The idea is that you have two range inputs for spacing and blur and one color input. These Inputs are then live updated with CSS Variables and JS.

See the Pen Playing with CSS Variables and JS (JavaScript30 Day 03) by Marco Kühbauch (@Mkuehb) on CodePen.

What did I learn? - What did I like?


In this third project I learned about:

  • input type="color"

    provides a way to specify a color by using a visual color picker

  • CSS Variables Syntax

    Declaring: --spacing: 10px;

    Usage: padding: var(--spacing);

  • document.documentElement

    returns the element that is the root element of the document

  • Parameter vs. Argument

    I always get these two mixed up so here is the perfect definition to remember it forever:

    A parameter is a variable in a function definition. When a function is called, the arguments are the data you pass into the function's parameters.

    function myFunc(parameter) { // Do something... } myFunc(argument);

Day 02 - JS & CSS Clock


In this project the task consists of building a Clock by using only HTML/CSS/JS. You are given a HTML/CSS Template of a clock and you should use JavaScript to animate the hour-, minute- and second-hand.

See the Pen JS + CSS Clock (JavaScript30 Day 02) by Marco Kühbauch (@Mkuehb) on CodePen.

How does it work?


First up there is some CSS work to do. The clock hands need to be transformed to start at the top (12 o'clock) which is achieved using transform: rotate(90deg).

After that to start the animation at the end of the hands, the transform-origin property comes in handy. Its origin is 50%, which is the middle, so setting this value to 100% will animate the hands at their end, so the animation starts looking like a real clock.

The animation itself is achieved by using transition-timing-function: cubic-bezier. You can adjust the cubic-bezier curve in the Chrome Dev Tools to get the perfect clock-ticking.

The JavaScript which will make it work is pretty straightforward. A function setDate creates a new Date Object and transforms the hands by using the getSeconds, getMinutes and getHours functions.

The seconds, minutes and hours are divided by 60 (12 for the hours) to get the percentage and multiplied by 360 to get the degrees. But because the starting point of the clock was initally offset by 90 degrees, 90 has to be added to the calculation of the seconds, minutes and hours.

The calculated values then get added as a css transform rotate. Finally the setDate() function is called with a setInterval method to set a delay of 1 second so the hands get transformed every second.

What did I learn? - What did I like?


In this second project I learned about:

  • transform-origin: 100%

    lets you modify the origin for transformations of an element. the origin of the rotate() function is 50%, the centre of the rotation

  • transition-timing-function: cubic-bezier

    lets you animate the speed of the animation. with cubic-bezier you can define a little tick forth and back to adapt a real clock behaviour.

  • new Date()

    Creates a JavaScript Date instance

    getSeconds() returns the seconds from the specified date

    getMinutes() returns the minutes from the specified date

    getHours() returns the hours from the specified date

  • setInterval()

    This method calles a function with a fixed time delay

Day 01 - JavaScript Drum Kit


The first project lets you code a JS drum kit where you can play different drum sounds with your keyboard. Everytime you press one of the keys between A and L a specific drum sound gets played and a visual highlighting shows you, which key was pressed. You can find my solution over here. Have fun playing around with it!

How does it work?


You have 8 different sounds which are implemented as an a audio element with a specific data-key attribute. Every data-key attribute corresponds to the the unicode of the key which you are supposed to press. So for the a key you have the data-key of '65'.

Now the window element gets a keydown eventlistener which calls a function.

window.addEventListener('keydown', playSound);

So everytime a key is pressed this function - lets call it playSound()- fires.

The function playSound():

  • accepts the event element as a parameter
  • selects every audio element with the data-key of the pressed key by using ES6 Template literals
  • selects every element with the class of key and the data-key of the pressed key
  • stops if a pressed key is not one of the defined 8 ones
  • resets the time of every audio element so they can be played over and over again
  • actually plays the audio element with the .play() function
  • and adds a class of playing to the divs with the class of key. The playing class is used for a little animation as soon as a key is pressed

function playSound(e) {
  const audio = document .querySelector(`audio[data-key="${e.keyCode}"]`);
  const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);

  if (!audio) return;

audio.currentTime = 0; audio.play(); key.classList.add('playing'); }

Another function is there for removing the animation on the pressed key. It is fired by the transitionend event on every key.

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', removeTransition));

function removeTransition(e) {
  if (e.propertyName !== 'transform') return;
  this.classList.remove('playing');
}

It checks if the event element has a property of transform, which means it already has been animated and removes the playing class.

What did I learn? - What did I like?


So in this first project, the JavaScript Drum Kit, I learned about:

  • using custom data attributes

    custom data attributes allow you to store extra information on any HTML element

  • ES6 let and const

    const is used to store values that should never change in the life of a program
    let is used to store values that should change in the life of a program

  • ES6 Template Literals

    template literals allow you to use backtick -- ` -- to identify a string. So now multiline strings are possible without concatination and you can use embedded expressions

  • ES6 Arrow Functions

    arrow functions are the ES6 way to write functions and they introduce a shorter syntax