Categories
Express JavaScript Nodejs

Add Basic Authentication to an Express App

To add basic auth capabilities to an Express app, we can use the express-basic-auth package.

With it, we can check for a given username and password in the URL in our protected routes.

In this article, we’ll take a look at how to use it.

How to Install

express-basic-auth is available as a Node package, we can install it by running:

npm install express-basic-auth

Basic Usage

We can use it as follows:

const express = require('express');  
const basicAuth = require('express-basic-auth')  
const app = express();
app.use(basicAuth({  
    users: { 'admin': 'supersecret' }  
}))

app.get('/', (req, res) => {  
  res.send('authorized');  
});

app.listen(3000, () => console.log('server started'));

In the code above, we included the basicAuth middleware from express-basic-auth from in our app.

Then we can call app.use with an object that has the users property with the usernames as the keys and the corresponding passwords as the values.

Then if we make a GET request to a URL like:

https://admin:supersecret@ThistleDarkExponents--five-nine.repl.co

Then we’ll get the authorized response back since the username and password matches what we listed in the object in our app.

Otherwise, we’ll get a 401 response and a configurable body, which is empty by default.

Custom Authorization

We can also pass in our own authorizer function to check for credentials that we want.

We shouldn’t use standard string comparison with == or === when comparing user input with sercet credentials since it’ll make our app vulenrable to timing attacks.

Timing attacks are a side-channel attack where the attacker tries to compromise a system by analyzing the time taken to run cryptographic algorithms.

We should use the safeCompare method provided by the package instead.

Also, we should use bitwise logic operators instead of standard ones for the same reason.

For example, we can use the following:

const express = require('express');  
const basicAuth = require('express-basic-auth')  
const app = express();
app.use(basicAuth({  
  authorizer: (username, password) => {  
    const userMatches = basicAuth.safeCompare(username, 'admin')  
    const passwordMatches = basicAuth.safeCompare(password, 'supersecret')  
    return userMatches & passwordMatches  
  }  
}))

app.get('/', (req, res) => {  
  res.send('authorized');  
});

app.listen(3000, () => console.log('server started'));

In the code above, we have a function that calls safeCompare to match the username and password respectively and then use the AND bitwise operator to combine the 2 to make sure that both are true .

Async Authorization

We can set the authorizeAsync option to true and set a function with a cb parameter for the callback as the authorizer function to check credentials asynchronously:

const express = require('express');  
const basicAuth = require('express-basic-auth')  
const app = express();
app.use(basicAuth({  
  authorizer: (username, password, cb) => {  
    const userMatches = basicAuth.safeCompare(username, 'admin')  
    const passwordMatches = basicAuth.safeCompare(password, 'supersecret')  
    if (userMatches & passwordMatches)  
      return cb(null, true)  
    else  
      return cb(null, false)  
  },  
  authorizeAsync: true,  
}))

app.get('/', (req, res) => {  
  res.send('authorized');  
});

app.listen(3000, () => console.log('server started'));

We return the cb callback call instead of returning the result directly in our authorizer function.

Unauthorized Response Body

We can set the unauthorizedResponse property to a function that returns a response that we want to show when a credential check failed.

For example, we can write:

const express = require('express');  
const basicAuth = require('express-basic-auth')  
const app = express();  
app.use(basicAuth({  
  users: { 'admin': 'supersecret' },  
  unauthorizedResponse: (req) => {  
    return `unauthorized. ip: ${req.ip}`  
  }  
}))  
app.get('/', (req, res) => {  
  res.send('authorized');  
});  
app.listen(3000, () => console.log('server started'));

to return something like:

unauthorized. ip: ::ffff:172.18.0.1

when basic authentication fails.

The function we set unauthorizedResponse to takes the Express request object, so we can use any properties from there in the function.

Challenge

We can make browsers show a popup so that users can enter credentials for authentication by add a challenge: true option to the object.

In addition, we set the realm to identify the system to authenticate against and can be used to save credentials of the challenge by passing a static or a function that gets passed the request object and is expected to return the challenge:

const express = require('express');  
const basicAuth = require('express-basic-auth')  
const app = express();app.use(basicAuth({  
  users: { 'admin': 'supersecret' },  
  challenge: true,  
  realm: 'foo',  
}))

app.get('/', (req, res) => {  
  res.send('authorized');  
});

app.listen(3000, () => console.log('server started'));

With the code above, we should get a dialog box to enter the username and password when we load the / page.

Conclusion

Adding basic auth to an Express app is easy with the express-basic-auth package.

It lets us add a list of valid credentials or use a function to validate credentials.

We can also let users enter the username and password and display custom content when the user is unauthorized.

Categories
JavaScript Vue

How to Create Vue Directive

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to make our directives accept arguments and values to directives and use them in our code.

Dynamic Directive Arguments

We can pass in arguments and values to a directive and then get these values from the binding parameter.

For example, we can make a directive that takes an argument and value as follows:

src/index.js :

Vue.directive("position", {  
  bind(el, binding, vnode) {  
    const validPositions = ["relative", "fixed", "absolute"];  
    if (validPositions.includes(binding.arg)) {  
      el.style.position = binding.arg;  
      el.style.top = `${binding.value}px`;  
    }  
  }  
});

new Vue({  
  el: "#app",  
  data: {  
    message: "Hello"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <p v-position:absolute="50">{{message}}</p>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we defined a positiion directive that takes an argument, which is accessed in the bind hook by using the binding parameter.

The binding parameter has an arg property to get the argument, which is absolute in index.html .

binding.value gets us the value, which is 50 in index.html .

Then we get the element that the directive is bound to with el and then we set the positioning of the element via the values from the binding parameter.

Accepting arguments and values make directives much more flexible than without arguments.

Function Shorthand

If we only have code in the bind and update hooks, then we can just pass in a function with the same signature as those hooks.

For example, we can shorten the example above to:

Vue.directive("position", (el, binding, vnode) => {  
  const validPositions = ["relative", "fixed", "absolute"];  
  if (validPositions.includes(binding.arg)) {  
    el.style.position = binding.arg;  
    el.style.top = `${binding.value}px`;  
  }  
});

They both do the same thing.

Object Literals

We can pass in an object literal as the value of a directive if our directive needs to accept multiple values.

For example, we can write the following code to accept an object’s properties’ values in our directive:

src/index.js:

Vue.directive("position", (el, binding, vnode) => {  
  const validPositions = ["relative", "fixed", "absolute"];  
  const { position, top } = binding.value;  
  if (validPositions.includes(position)) {  
    el.style.position = position;  
    el.style.top = top;  
  }  
});

new Vue({  
  el: "#app",  
  data: {  
    message: "Hello"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <p v-position="{ position: 'absolute', top: '50px' }">{{message}}</p>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The code above accepts an object with the position and top property and we take the object’s values and then set them as the style of the p element which the position directive is bound to.

A directive’s value can be any valid JavaScript expression.

Conclusion

Vue directives can take arguments and values. We can get argument values from the binding parameter of the bind hook via the binding.arg property.

To get the value passed to a directive, we can get it from the bind hook’s binding parameter via the binding.value property.

If our directive only has bind or update hooks, then we can shorten it to a function, which has the same signature as the bind or update hooks.

Categories
JavaScript Vue

Vue Components — Dynamic Slot Names and Shorthands

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at add dynamic slot names.

Dynamic Slot Names

Since Vue.js 2.6.0, we can pass in dynamic slot names with v-slot . For example, we can use it as follows:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user" name='first-name'></slot>  
    <slot v-bind:user="user" name='last-name'></slot>  
  </p>`  
});

new Vue({  
  el: "#app",  
  data: {  
    firstname: "first-name",  
    lastname: "last-name"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template v-slot:[firstname]="{ user }">  
          {{ user.firstName }}  
        </template>  
        <template v-slot:[lastname]="{ user }">  
          {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, firstname and lastname in data are set as the names of the slots in our root template.

Named Slots Shorthand

v-slot has a shorthand. We can shorten v-slot: to the symbol # . For example, we can rewrite our example as follows:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user" name='first-name'></slot>  
    <slot v-bind:user="user" name='last-name'></slot>  
  </p>`  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template #first-name="{ user }">  
          {{ user.firstName }}  
        </template>  
        <template #last-name="{ user }">  
          {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

For referencing the default slot, we have to write #default . For example, we write:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user"></slot>      
  </p>`  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template #default="{ user }">  
          {{ user.firstName }} {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Use with v-for

We can add a slot to provided fallback content in lists and allow us to change the content in the parent. For example, we can write the following:

src/index.js :

Vue.component("people", {  
  data() {  
    return {  
      persons: [  
        { name: "Joe", isAdult: true },  
        { name: "Jane", isAdult: false }  
      ]  
    };  
  },  
  template: `  
    <ul>    
      <li v-for='person of persons'>  
        <slot v-bind:person="person"></slot>      
      </li>  
    </ul>  
  `  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <people v-bind:persons="persons">  
        <template #default="{ person }">  
          {{person.name}}  
          <span v-if="person.isAdult"> - Adult</span>  
          <span v-else> - Child</span>  
        </template>  
      </people>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we have the people component with persons data. We rendered persons with v-for in the people component and make the entries available via v-bind :

<slot v-bind:person="person"></slot>

Then in the root template, we have:

<people v-bind:persons="persons">  
  <template #default="{ person }">  
    {{person.name}}  
    <span v-if="person.isAdult"> - Adult</span>  
    <span v-else> - Child</span>  
  </template>  
</people>

to get person from people and then provide a template to display the entries as we wish without modifying the people component.

Conclusion

Since Vue 2.6.0, we can use dynamic slot names instead of hard-coded ones.

Also, the shorthand for named slots is # . For default slots, we always have to write #default .

Finally, we can use it with v-for to let us define a template that can be used with each entry. We use v-bind on the entry of the array instead of the whole array and then we can access that data in the parent component and add a templarte to display data the way we like by defining it in the parent.

Categories
JavaScript TypeScript

Introduction to TypeScript Generics — Classes

One way to create reusable code is to create code that lets us use it with different data types as we see fit. TypeScript provides the generics construct to create reusable components where we can work with a variety of types with one piece of code. This allows devs to use these components by putting in their own types. In this article, we’ll look at the many ways to define generic classes and also validate properties by defining interfaces and the extends keyword and also force the code to only accept property names that are in an object by using the keyof keyword.

Defining a Generic Class

To define generic classes in TypeScript, we put the generic type marker in between the <> after the class name. We can have more than one type marker separated by a comma. Also, we can use the same type marker to mark the type of the function to let us change parameter and return type of methods within our class. For example, we can write the following code to define a generic class with a single generic type marker:

class GenericPerson<T> {    
  name: T;  
  getName: (name: T) => T;  
}let person = new GenericPerson<string>();  
person.name = 'Jane';  
person.getName = function(x) { return x; };

In the code above, we passed in the string type inside the <> . We can also change to any other type we want like number, boolean, or any interface like in the following code:

class GenericPerson<T> {    
  name: T;  
  getName: (name: T) => T;  
}let person = new GenericPerson<number>();  
person.name = 2;  
person.getName = function(x) { return x; };

We can also insert multiple types within the same class as in the following code:

class GenericPerson<T, U> {    
  name: T;  
  getName: (name: U) => U;  
}let person = new GenericPerson<string, number>();  
person.name = 'Jane';  
person.getName = function (x) { return x; };  
person.getName(2);

In the code above, T and U may or may not be different types. As long as we put them both in and that we pass in and assign data with the types we specified in the class definition, then the TypeScript compiler will accept it. The examples above are only useful for a limited amount of cases since we can’t reference any properties in our class definition since the TypeScript compiler doesn’t know what properties T or U contains.

To make the TypeScript compiler aware of the properties that may be used in our class definition, we can use an interface to list all the properties that can be used with the class and the use the extends keyword after the generic type marker to denote the that type may have the list of properties that are listed in the interface. For example, if we want to have different complex types in our class methods, we can write something like the following code:

interface PersonInterface {  
  name: string;  
  age: number;  
}

interface GreetingInterface {  
  toString(): string;  
}

class GenericPerson<T extends PersonInterface, U extends GreetingInterface> {    
  person: T;  
  greet(greeting: U): string {  
    return `${greeting.toString()} ${this.person.name}. You're ${this.person.age} years old`;  
  }  
}

let jane = new GenericPerson();  
jane.person = {  
  name: 'Jane',  
  age: 20  
};  
console.log(jane.greet('Hi'));

In the code above, we defined 2 interfaces, the PersonInterface and the GreetingInterface to denote the properties that can be referenced with T and U respectively. In the PersonInterface, we have the name and age properties listed so we can reference these properties for data with type T. For the data with U type we can call the toString method on it. Therefore, in our greet method, we can call toString on greeting since it has the U type and since this.person has the T type, we can get the name and age properties from it.

Then after the class definition, we can instantiate the class and then set values for the name and age properties on the jane object that we created. Then when we run console.log on jane.greet(‘Hi’) then we should see ‘Hi Jane. You’re 20 years old’ since we set the values for jane.person.

We can also put in the types explicitly when we instantiate the object to make the types more clear. Instead of what we have above, we can change it slightly and write the following code:

interface PersonInterface {  
  name: string;  
  age: number;  
}

interface GreetingInterface {  
  toString(): string;  
}

class GenericPerson<T extends PersonInterface, U extends GreetingInterface> {    
  person: T;  
  greet(greeting: U): string {  
    return `${greeting.toString()} ${this.person.name}. You're ${this.person.age} years old`;  
  }  
}

let jane = new GenericPerson<PersonInterface, string>();  
jane.person = {  
  name: 'Jane',  
  age: 20  
};  
console.log(jane.greet('Hi'));

The only difference is that we add the <PersonInterface, string> after new GenericPerson. Note that we can add interfaces or primitive types in between the brackets. TypeScript only cares that the type has the methods listed in the interface we defined. Now that the types are constrained by these generic types, we don’t have to worry about referencing any unexpected properties. For example, if we reference something that doesn’t exist like in the following code:

interface PersonInterface {  
  name: string;  
  age: number;  
}

interface GreetingInterface {  
  toString(): string;  
}

class GenericPerson<T extends PersonInterface, U extends GreetingInterface> {    
  person: T;  
  greet(greeting: U): string {  
    return `${greeting.foo()} ${this.person.name}. You're ${this.person.age} years old`;  
  }  
}

let jane = new GenericPerson<PersonInterface, string>();  
jane.person = {  
  name: 'Jane',  
  age: 20  
};  
console.log(jane.greet('Hi'));

We would get “Property ‘foo’ does not exist on type ‘U’.(2339)” since we didn’t list foo in our GreetingInterface .

Constraining Retrieval of Object Properties

TypeScript also provides a way to let us get the properties of an object safely with generics. We can use the keyof keyword to constrain the values of the than an object can take on to the key names of another object. For example, we can use the keyof keyword like in the following code:

function getProperty<T, K extends keyof T>(obj: T, key: K) {  
  return obj[key];  
}

let x = { foo: 1, bar: 2, baz: 3 };console.log(getProperty(x, "foo"));

In the code above, we constrain the generic marker K to only accept the keys of whatever object is passed in to obj as the valid values of key since K has the extends keyof T marker after K . This means that whatever keys the T type has, then the keys are valid values for K . With code like the ones above, we don’t have to worry about getting values for properties that don’t exist. So if we pass in a key name that doesn’t exist in obj , like in the following code:

getProperty(x, "a");

Then the TypeScript compiler will reject the code and give the error message “Argument of type ‘“a”’ is not assignable to parameter of type ‘“foo” | “bar” | “baz”’.(2345)“. This means that only 'foo' , 'bar' and 'baz' are valid values for key since it has the type K , which has the extends keyof T marker after it to constrain the valid uses to be the key names of obj .

We can define a generic class easily with TypeScript. To define generic classes in TypeScript, we put the generic type marker in between the <> after the class name. We can have more than one type marker separated by a comma. Also, we can use the same type marker to mark the type of the function to let us change parameter and return type of methods within our class. Also, we can use the extends keyword to define the properties that can be referenced with our data marked by generic types. We can use the keyof keyword to constrain the values of the than an object can take on to the key names of another object.

Categories
JavaScript

JavaScript Events Handlers — Keyboard and Load Events

In JavaScript, events are actions that happen in an app. They’re triggered by various things like inputs being entered, forms being submitted, and changes in an element like resizing, or errors that happen when an app is running, etc. We can assign an event handler to respond to these events.

Events that happen to DOM elements can be handled by assigning a handler to properties of the DOM object for the corresponding events. In this article, we’ll look at how to use the onkeydown and onkeypress properties of an editable input element, and the onload property for any DOM element. We will also look at the onloadeddata property for media elements like audio and video .

onkeydown

We can set an event handler function to the onkeydown property of an input DOM element to handle the keydown event. The keydown event is fired when any key is pressed down regardless of whether they produce a character value. The keydown event provides a code indicating which key is pressed, while the keypress event provides the character which is entered. For example, lowercase ‘a’ will be reported as keycode 65 with keydown , but the character code 97 will be reported by keypress . keypress is deprecated, so it shouldn’t be used in production code.

In Firefox, since version 65, the keydown event is also fired during IME composition, to improve cross-browser compatibility for Chinese, Japanese and Korean users. We can ignore the keydown event during IME composition, we can check the isComposing property of the event object that’s provided by the keydown event handler. For example, we can write:

const input = document.querySelector('input');

input.onkeydown =  event => {   
  if (event.isComposing || event.keyCode === 229) {  
    return;  
  }  
};

Whenever, we type in Chinese, Japanese or Korean, the isComposing property will have the value true and the keyCode property will have the value 229.

We can also use it to log the value of the key code that’s pressed by the user on the keyboard. We can first put the following HTML code:

<input type="text" id="input" required>  
<p id="log"></p>

Then in the corresponding JavaScript code, we can write the following code to attach the event handler function for the keydown event by setting the onkeydown property of our input element. The event handler function will log the key code of the key that was pressed.

const input = document.querySelector('input');  
const log = document.getElementById('log');

input.onkeydown =  e => {   
 log.textContent += ` ${e.code}`;  
};

We should get something like:

KeyE KeyR KeyF KeyG KeyT KeyG KeyT KeyG KeyH KeyH KeyF KeyV KeyG KeyB KeyG KeyB

in the element with the ID log .

onkeyup

The onkeyup property of an input element let us attach an event handler function to handle the keyup event. The keyup event is fired when the user releases a key that’s been previously pressed.

The keyup event provides a code indicating which key is pressed, while the keypress event provides the character which is entered. For example, lowercase ‘a’ will be reported as keycode 65 with keyup, but the character code 97 will be reported by keypress .

In Firefox, since version 65, the keyup event is also fired during IME composition, to improve cross-browser compatibility for Chinese, Japanese and Korean users. We can ignore the keyup event during IME composition, we can check the isComposing property of the event object that’s provided by the keyup event handler. For example, we can write:

const input = document.querySelector('input');

input.onkeyup =  event => {   
  if (event.isComposing || event.keyCode === 229) {  
    return;  
  }  
};

We can also use it to log the value of the key code that’s pressed by the user on the keyboard. We can first put the following HTML code:

<input type="text" id="input" required>  
<p id="log"></p>

Then in the corresponding JavaScript code, we can write the following code to attach the event handler function for the keydown event by setting the onkeydown property of our input element. The event handler function will log the key code of the key that was pressed.

const input = document.querySelector('input');  
const log = document.getElementById('log');input.onkeyup =  e => {   
 log.textContent += ` ${e.code}`;  
};

We should get something like:

KeyD KeyF KeyG KeyT KeyH KeyG KeyT

onload

The onload property of a DOM element let us set an event handler function to it to handle the load event, which is fired when any element is being loaded. It’s fired at the end of the document loading process. All of the objects in the documents should be in the DOM when the load event is fired, including all images, scripts, links and sub-frames.

There’re also the DOMContentLoaded and DOMFrameContentLoaded , which are fired after the DOM for the page has been loaded but don’t wait for the other resources to finishing loading.

For example, we can use it to run some code after the window or an img element loads by first writing the HTML code:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Onload</title>  
  </head>  
  <body>  
    <div>Text</div>  
    <img  
      src="https://images.unsplash.com/photo-1503066211613-c17ebc9daef0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80"  
    />  
    <script src="main.js"></script>  
  </body>  
</html>

Then we can write the corresponding JavaScript code:

const img = document.querySelector("img");

img.onload = () => {  
  console.log("img loaded");  
};

window.onload = () => {  
  console.log("window loaded");  
};

Then we should see:

img loaded  
window loaded

When we load the page.

onloadeddata

The loadeddata event is fired when the first frame of the media has finished loading. It’s applicable to media elements like audio and video . To handle this event, we can set the onloadeddata property of a media element to run an event handler function when this event is fired.

For example, we can also set the onloadeddata property the following code. First, we add the HTML code for the video element:

<video src='https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4'></video>

Then in the corresponding JavaScript code, we can set an event handler function with the following code:

const video = document.querySelector('video');

video.onloadeddata = () => {  
 console.log('video loaded');  
}

The event handler function also has an event object as the first parameter. We can add an event parameter as we do in the following code:

const video = document.querySelector('video');

video.onloadeddata = (event) => {  
 console.log(event);  
}

Which gets us something like:

bubbles: false  
​cancelBubble: false  
​cancelable: false  
​composed: true  
​currentTarget: null  
​defaultPrevented: false  
​detail: 0  
​eventPhase: 0  
​explicitOriginalTarget: <html>  
​isTrusted: true  
​layerX: 0  
​layerY: 0  
​originalTarget: HTMLDocument https://fiddle.jshell.net/_display/
​rangeOffset: 0  
​rangeParent: null  
​relatedTarget: null  
​returnValue: true  
​srcElement: HTMLDocument https://fiddle.jshell.net/_display/
​target: HTMLDocument https://fiddle.jshell.net/_display/
​timeStamp: 1463  
​type: "focus"  
​view: Window https://fiddle.jshell.net/_display/
​which: 0

The output above is the properties and the corresponding values of the Event object. To see more details about the Event object, we can look at the previous articles.

We can set an event handler function to the onkeydown property of an input DOM element to handle the keydown event. The keydown event is fired when any key is pressed down regardless of whether they produce a character value. The keydown event provides a code indicating which key is pressed. The onkeyup property of an input element let us attach an event handler function to handle the keyup event. The keyup event is fired when the user releases a key that’s been previously pressed. The event object provides the same information as the keydown event handler.

The onload property of a DOM element let us set an event handler function to it to handle the load event, which is fired when any element is being loaded. It’s fired at the end of the document loading process. All of the objects in the documents should be in the DOM when the load event is fired, including all images, scripts, links and sub-frames.

The loadeddata event is fired when the first frame of the media like audio and video has finished loading. To handle this event, we can set the onloadeddata property of a media element to run an event handler function when this event is fired.