Categories
HTML JavaScript

Introduction to HTML Canvas

One way to display graphics is to use the img element in HTML. However, that only displays static images with a fixed URL. To draw and display dynamic graphics, we can use the HTML canvas element.


Creating a New Canvas

To create a new canvas element:

<canvas style='width: 200px; height: 200px'>
</canvas>

It looks like the img element, but it has no src or alt attributes. This is because it’s not a fixed image element.

We can style with CSS as we did above, with width , height , margin, border , padding , etc.

Fallback content

For browsers that don’t support canvas, we can supply fallback content by putting something inside. For example, we can write:

<canvas style='widthL 200px; height: 200px'>
  Your browser doesn't support canvas.
</canvas>

The closing tag </canvas> is required for canvas elements. If it’s not present, the rest of the document will be considered fallback content.


Rendering Context

The canvas element creates a fixed-size drawing surface that exposes one or more rendering contexts — entities to create and manipulate the content drawn.

The most basic is the 2D rendering context. There’s also a 3D rendering context for WebGL and OpenGL ES.

A canvas is initially blank. We have to access the rendering context and draw on it to display something. To do this, we can use the getContext() method of the canvas element. For 2D graphics, we specify '2d' into the getContext() method.

We access the canvas rendering context as follows:

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

Checking for Support

We can check for support for the canvas element by checking if the getContext method exists, as follows:

const canvas = document.querySelector('canvas');
if (canvas.getContext) {
  const ctx = canvas.getContext('2d');
}

This should be less of a concern these days since almost all modern browsers support the canvas element.


Basic Code

Put it together and we have the following code. The HTML:

<canvas>
  Your browser doesn't support canvas.
</canvas>

Then we can add the following CSS:

canvas {
  width: 200px;
  height: 200px;
  border: 1px solid black;
}

Finally, we have this JavaScript code:

const canvas = document.querySelector('canvas');
if (canvas.getContext) {
  const ctx = canvas.getContext('2d');
}

A Simple Drawing

The simple drawing is made up of basic 2D shapes, like rectangles. We create three rectangles with different background colors with the following code:

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(100, 0, 0)';
ctx.fillRect(5, 5, 40, 40);

ctx.fillStyle = 'rgba(0, 20, 100, 0.5)';
ctx.fillRect(10, 10, 50, 50);

ctx.fillStyle = 'rgba(20, 0, 200)';
ctx.fillRect(25, 25, 95, 90);

It works as follows. After we get the rendering context, we set the background color of the shape with the fillStyle property by setting it a string with the color value. Then we create a rectangle with the coordinates (5, 5) for the top left corner and (40, 40) for the bottom right corner.

The first two arguments are the x and y coordinates of the top-left corner, the last two are the width and height.

The first rectangle is:

ctx.fillStyle = 'rgb(100, 0, 0)';
ctx.fillRect(5, 5, 40, 40);

The color value rgb(100, 0, 0) represents a brownish color.

Likewise, we have:

ctx.fillStyle = 'rgba(0, 20, 100, 0.5)';
ctx.fillRect(10, 10, 50, 50);

This rectangle is to the right and lower than the first. It has a grayish color.

Finally, we have:

ctx.fillStyle = 'rgba(20, 0, 200)';
ctx.fillRect(25, 25, 95, 90);

This one is again to the right and lower than the second rectangle, in blue.

In the end, we get the following:

The drawing is finished once the page with the canvas element has loaded. The coordinates can be outside or inside the rectangle’s dimensions. If it exceeds the dimensions, we won’t see the stuff that’s drawn.

The canvas is useful to draw graphics, whether static or dynamic. We can create a canvas element in HTML, then we can get the canvas element in JavaScript and get the rendering context so we can draw items on it.

We can draw basic shapes on it. We can change the colors of the background with the fillStyle property of the context, then can call the fillRect on it to draw a rectangle.

It takes four arguments: The x, y coordinates of the top left corner for the first two arguments and the x, y coordinates for the bottom right corner for the last two elements.

Categories
HTML JavaScript

Introducing the Page Visibility API

Since most modern browsers are tabbed, it’s possible that a webpage may reside in a tab that stays in the background and not visible to the user.

The Page Visibility API can provide us with insight as to whether a page is visible to the user.

In this article, we’ll look at the Page Visibility API, its use cases, and how to use it.

Visibility Change Event

When a user minimizes the window or switches to another tab, the Page Visibility API sends a visibilitychange event to let listeners know that the state of the page has changed.

We can handle the event when it’s triggered and do something according to the visibility state. For example, we can pause the video when the page is hidden from view.

The visibility state of an iframe is the same as the parent document that the iframe is in. Hiding an iframe with CSS doesn’t trigger visibility events or change the state of the document contained within the iframe .

Use Cases

There’re many use cases for using the API. Some of them include the following:

  • pausing an image carousel when the page is hidden
  • stop polling the server for information when the page is hidden
  • prerendering a page to keep an accurate count of page views
  • switch off the sound when the page is not being viewed

Without the Page Visibility API, developers resort to imperfect solutions like listening to the blur or focus events of the window to help detect whether the page is visible or not.

They don’t tell if they’re hidden or not, just whether they’re in focus or not.

Policies that Help Background Page Performance

Most browsers do a few things to help save resources when a page isn’t in view.

requestAnimationFrame callback won’t be called to improve performance and battery life when a page is in the background.

setTimeout and other timers are throttles in the background or inactive tabs to improve performance.

Throttling is also done in browsers to limit CPU usage by background tabs.

Each background tab has its own time budget between -150ms and 50ms.

Browser windows are subjected to throttling after 30 seconds in Firefox and 10 seconds in Chrome.

Timer tasks are only permitted when the time budget is non-negative.

Once the timer’s code finishes running, the duration it takes to execute is subtracted from the time budget.

The budget regenerates at a rate of 10ms per second in both Firefox and Chrome.

Some processes ate exempt from throttling behavior. Tabs that are playing audio are considered foreground tabs and aren’t subject to throttling.

Code that uses real-time network connections goes unthrottled to prevent the closing of these connections.

IndexedDB processes are also left unthrottled to avoid timeouts.

The Page Visibility API can let us stop these things manually if we want to do so.

Using the Page Visibility API

The Page Visibility API is part of the document object.

We can use it by checking the document.hidden property or the document.visibilityState property. They’re both read-only.

To watch for changes in both, we can listen to the visibilitychange event.

To do this we can use the following example. Our example will pause a video when we switch to a different tab. First, we add the HTML code for the video as follows:

<video controls src='[https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4'](https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4%27)></video>

Then in our JavaScript code, we can listen to the visibilitychange event as follows:

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

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState !== 'visible') {
    video.pause();
  }
})

In our event listener callback, we pause the video when the visibilityState isn’t ‘visible’ , which means the user can’t see the tab either by navigating away from the tab or window, minimizing the window, or turned the screen off.

The alternative to this is to set the event handler to the onvisibilitychange property of document.

document.visibilityState can take on these 3 values:

  • visible — the page is visible to the user as a foreground tab
  • hidden — the page isn’t visible to the user, either because it’s in the background, or the minimized or the device’s screen is off.
  • prerender — the page is being prerendered and isn’t visible to the user. A document may start in this state, but will never switch to this state from any other state since it can only prerender once. Not all browsers support prerendering.
  • unloaded — the page is being unloaded from memory. Not all browsers support this.

Compatibility

This API has been supported for a while. Chrome since version 33 supports this API. Edge, Firefox, IE 10 or later, and Safari 7 or later all support this API. Mobile versions of these browsers also support this API.

The Page Visibility API is useful for detecting the visibility state of the page. We can listen to the visibilitychange event and then get the visibility state with document.visibilityState and so what we want with it.

Categories
JavaScript

How to Select and Manipulate DOM Elements

To make our web pages dynamic, we have to manipulate the elements on the page so that we can get the dynamic effects. The web browser’s standard library allows us to do this. There are multiple methods in the document object, which is the object which represents the items on our page. It has the whole DOM tree with all the elements we can get and then manipulate. In this article, we’ll look at a few methods to get elements from the page.

getElementsByClassName

The document.getElementsByClassName method lets us get a list of DOM objects on the page by their class name. Whatever object that has the given class will be returned by this method. It takes one argument which is a string with one or more class names separated by a space. It’s a method that’s part of any DOM element, which means it can also be called on elements that are returned by this method.

A NodeList object is returned, which is an array-like object. It has a length property and can be looped through by a for loop or a for...of loop, but array methods like forEach aren’t included in this object.

The simplest example would be getting the elements from the following HTML:

<p class='foo'>
  foo
</p>
<p class='foo'>
  bar
</p>

Then in our JavaScript code, we can get the elements with the foo class by writing the following:

const foo = document.getElementsByClassName('foo');

Once we have that we have access to the elements, so we can manipulate them by assigning values to its properties. For example, if we want to change the style, we can set the value of the properties in the style property.

We can write something like the following to set the color of the text of both elements with the foo class to red:

const foo = document.getElementsByClassName('foo');
for (const f of foo) {
  setTimeout(() => {
    f.style.color = 'red';
  }, 2000)
}

Also, we can pass in more than one class name to the method. They have to be separated by a space. It’ll select the elements with all the classes. For example, if we add a bar to the first p element as follows:

<p class='foo bar'>
  foo
</p>
<p class='foo'>
  bar
</p>

Then we can write the following to change the first p element’s text color to red after 2 seconds:

const foo = document.getElementsByClassName('foo bar');
for (const f of foo) {
  setTimeout(() => {
    f.style.color = 'red';
  }, 2000)
}

The style property has lots of properties. Pretty much any CSS option can be set by assigning a value to a property of the style property.

getElementsByTagName

We can select all the elements with the given tag name by using the document.getElementsByTagName method.

It accepts a string with the tag name and returns a NodeList object with all the elements with the given tag. As with any NodeList object, we can loop through by a for loop or a for...of loop, but array methods like forEach aren’t included in this object.

For example, we can write the following code to set all the p elements to red after 2 seconds given the following HTML code:

<p>
  foo
</p>
<p>
  foo
</p>
<div>
  baz
</div>

We can write:

const pElements = document.getElementsByTagName('p');
for (const p of pElements) {
  setTimeout(() => {
    p.style.color = 'red';
  }, 2000)

}

to set them to red since we passed in p to the method. We should get that the first 2 elements are red after 2 seconds. We can see that the div element stays black since it’s not a p element.

getElementsByTagNameNS

The getElementsByTagNameNS is very similar to the getElementsByTagName method, but it takes 2 arguments instead of one. The first is a string with the XML namespace of the HTML document, and the second is the same as getElementsByTagName ‘s first argument, which is the tag name.

The namespace is the XML namespace, which is part of the syntax for defining a web page with XHTML instead of HTML.

The return value is the same as getElementsByTagName , which is a NodedeList object with all the elements with the given tag and XML namespace.

For example, if we have the following HTML:

<html xmlns="[http://www.w3.org/1999/xhtml](http://www.w3.org/1999/xhtml)">
  <head>
    <title>Foo</title>
  </head>
  <body>
    <p>
      foo
    </p>
    <p>
      foo
    </p>
    <div>
      baz
    </div>
    <script src="main.js"></script>
  </body>
</html>

Then we can write the following JavaScript code in main.js to make the text of the p elements red after 2 seconds:

const pElements = document.getElementsByTagNameNS('[http://www.w3.org/1999/xhtml'](http://www.w3.org/1999/xhtml%27), 'p');

for (const p of pElements) {
  setTimeout(() => {
    p.style.color = 'red';
  }, 2000)

}

We have to name the HTML file with the .xhtml extension to make it this method work since it’s only used for XHTML documents.

Photo by Will Smith on Unsplash

getElementById

The document.getElementById method lets us get a DOM object on the page by ID. We can use it by passing in a string with the ID of the element that we want to select. Since there can only be one element with a given ID per page, it’ll only get one element and return that.

For example, if we have the following HTML:

<p id='foo'>
  foo
</p>

Then we can set the color to red after 2 seconds by writing the following code:

const foo = document.getElementById('foo');
setTimeout(() => {
  foo.style.color = 'red';
}, 2000)

querySelector

Selecting elements to manipulate are clumsy with the methods above since we can only select elements by ID or class name. With the querySelector method, we can use any CSS selector to select an element.

It takes one argument which is a string with the CSS selector for the elements that we want to select. It returns an element object that is the first element that is selected by the CSS selector. It’ll throw a syntax error if the selector we pass in is invalid.

Special characters must be escaped with a backslash.

For example, if we have the following input:

<input type='text'>

Then we want to set a value to it by writing the following code:

const input = document.querySelector('input[type="text"]');

input.value = 'abc';

We can escape special characters in CSS selectors like in the following example. If we have an input with the ID abc , which has the special character slash:

<input type='text' id="abc">

Then we can change its values like in the following code:

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

input.value = 'abc';

Notice that we have 4 slashes to represent the slash character in the string.

If our element has a colon in the selector, like:

<input type='text' id="ab:c">

Then we can write:

const input = document.querySelector('#ab:c');

input.value = 'abc';

The colon is escaped by adding 2 slashes before it.

querySelectorAll

Like the querySelector method, the querySelectorAll takes a CSS selector string for the elements that we want to select. However, it returns a NodeList object with all the elements that match the CSS selector.

For example, if we can write the following HTML code:

<p class='foo'>
  foo
</p>
<p class='foo'>
  foo
</p>
<p class='baz'>
  baz
</p>

Then we can select all the elements with the class .foo and set the text to red after 2 seconds by writing the following code:

const fooElements = document.querySelectorAll('.foo');

for (const f of fooElements) {
  setTimeout(() => {
    f.style.color = 'red';
  }, 2000)
}

Using the Methods Above with Non-Document Elements

We can use all these methods on non-document DOM objects. For example, if we have the following HTML code:

<div id='bar'>
  <p class='foo'>
    foo
  </p>
  <p class='foo'>
    foo
  </p>
  <p class='baz'>
    baz
  </p>
</div>

Then we can select the bar element with any method and, which returns the bar element DOM object. Then we can use any method include the same one as we use before to select another element in the returned object.

For example, with the above HTML, we can write the following to select all the p elements with the class foo and set their text to red after 2 seconds:

const fooElements = document.querySelector('#bar').querySelectorAll('.foo');

for (const f of fooElements) {
  setTimeout(() => {
    f.style.color = 'red';
  }, 2000)
}

If we replace querySelector with some method that returns NodeList objects, then we’ve to loop through them with the for or for...of loop or get theme element by index.

Most of the methods above are very useful for getting DOM elements and manipulating them. However, we can probably ignore getElementByTagNameNS since we don’t write XHTML files much anymore since HTML 5 was released.

Categories
TypeScript

Great New Features Released with TypeScript 3.5

TypeScript is improving every day. We keep getting new features with every release. In this article, we’ll look at the new stuff that was released with TypeScript 3.5.

New features include speed improvements to incremental builds, new Omit helper type, better excess property checks in union types, and type inference for the composition of constructors.

Speed Improvements

With the --incremental build mode, subsequent builds are faster because of the caching of references, file locations, and other build related data.

Omit Helper Type

The Omit helper type was introduced in TypeScript 3.5 to let us create a new type from existing types by excluding some properties from the original.

For example, given the Person type defined in the following code:

type Person = {
    name: string;
    age: number;
    address: string;
};

We can create a new type without the address property by using Omit:

type NewPerson = Omit<Person, "address">;

Which is the same as:

type NewPerson = {
    name: string;
    age: number;
}

Better Excess Property Checks in Union Types

Before TypeScript 3.5, excess property checks didn’t catch properties in some cases. If we have a union type, then TypeScript versions before 3.5 allows a property with the same name as the type of a union type but with a different type than what’s specified in the type definition.

For example, if we have:

type Person = {
    name: string;
    age: number;
};

type Address = {
    address: string;
}

const person: Person | Address = {
    name: 'Joe',
    age: 1,
    address: true
};

We can set address to something that’s not a string, which isn’t something that should be allowed.

This has been fixed in TypeScript 3.5. Now address has to be a string since it’s specified to be a string.

The --allowUmdGlobalAccess Flag

UMD global declarations files can now be referenced in TypeScript 3.5 using the new --allowUmdGlobalAccess flag.

It adds more flexibility for mixing and matching 3rd party libraries. Now the globals that libraries declare can be consumed, even from within modules.

Smarter Union Type Checking

We would get an error with the following union type definition and variable assignment before TypeScript 3.5:

type Foo = { done: boolean, value: string }
type Bar =
    | { done: false, value: string }
    | { done: true, value: string };

declare let source: Foo;
declare let target: Bar;

target = source;

Before 3.5, done would be recognized as having a literal type with the value instead of the boolean type.

Now it recognizes the type for the done field as being boolean. This now works boolean can only be true or false .

Higher-Order Type Inference From Generic Constructors

When we compose generic constructors as we do in the following function:

function composeConstructors<T, U, V>(
    F: new (x: T) => U, G: new (y: U) => V): (x: T) => V {
    return x => new G(new F(x))
}

TypeScript 3.5 can infer the type T , U , and V by inferring the chain of types that are formed from the composition.

If we have the following code:

class Foo<T> {
    value: T;
    constructor(value: T) {
        this.value = value;
    }
}

class Bar<U> {
    value: U;
    constructor(value: U) {
        this.value = value;
    }
}

let f = composeConstructors(Foo, Bar);
let a = f('foo');

Now we’ll get that a has the type Bar<Foo<string>> . Versions before 3.5 has the type Bar<{}> for a .

TypeScript 3.5 is smarter now. It can infer types formed by the composition of constructors.

With TypeScript 3.5, it’s smarter and faster. It can infer types formed by the composition of constructors by going through the chain of composition.

Excess property checks are checked for union types, which didn’t happen in earlier versions.

Also, we have the -- allowUmdGlobalAccess flag to run access global variables from UMD modules.

Finally, we have the Omit type for creating a new type from existing types with some properties removed.

Categories
TypeScript

Great New Features Released with TypeScript 3.4

TypeScript is improving every day. We keep getting new features with every release. In this article, we’ll look at the new stuff that’s released with TypeScript 3.4.

New features include better type inference for higher-order generic functions. changes to readonly types and faster builds with the --increment flag, and more.

New Features in TypeScript 3.4

–incremental Flag

To speed up builds after the first build, the --incremental flag of the TypeScript compiler will let us build only based on what’s changed.

We can add the option to tsconfig.json of our project to get this feature, under the compilerOptions section, as follows:

{
    "compilerOptions": {
        "incremental": true,
        "outDir": "./lib"
    },
    "include": ["./src"]
}

It works by looking for the .tsbuildinfo which is created with the first build. If it doesn’t exist, then it’ll be generated. It’ll use this file to know what has been built and what has not.

It can be safely deleted and not impact our build. We can name the file with a different name by adding a tsBuildInfoFile option to the compilerOptions section tsconfig.json as follows:

{
    "compilerOptions": {
        "incremental": true,
        "tsBuildInfoFile": "./front-end-app",
        "outDir": "./lib"
    },
    "include": ["./src"]
}

For composite projects, which has composite flag set to true in tsconfig.json, references between different projects can also be built incrementally. These projects will always generate a .tsbuildinfo files.

When the outFile option is used, then the build information file name will be based on the output file’s name. For example, if the output file is foo.js then the build information file will be foo.tsbuildinfo.

Higher-Order Type Inference in Generic Functions

When we have functions that take other functions as parameters, we’ll get type inference for the types of functions that are passed in and returned.

For example, if we have a function that composes multiple functions to return a new function as follows:

function compose<A, B, C, D>(
    f: (arg: A) => B,
    g: (arg: B) => C,
    h: (arg: C) => D
): (arg: A) => D {
    return x => h(g(f(x)));
}

When we fill in the types for the generic markers as follows:

function compose<A, B, C, D>(
    f: (arg: A) => B,
    g: (arg: B) => C,
    h: (arg: C) => D
): (arg: A) => D {
    return x => h(g(f(x)));
}

interface Employee {
    name: string;
}

const getName = (employee) => employee.name;
const splitString = (name) => name.split('');
const getLength = (name) => name.length;

const fn = compose(getName, splitString, getLength)

Then we can call the fn function by writing:

const len: number = fn(<Employee>{ name: 'Joe' });

TypeScript 3.4 or later is smart enough to go through the chain of function calls and infer the types of each function automatically and the return type of the function returned from compose.

It can infer that fn returns a number.

TypeScript versions older than 3.4 will infer the empty object type and we get errors with the assignment expression above.

ReadonlyArray and readonly tuples

Using read-only array types is now easier with TypeScript 3.4. We can now declare a read-only array with the readonly keyword.

For example, if we want a read-only string array, we can write:

const strArr: readonly string[] = ['a', 'b', 'c'];

Now we have an array that we can’t push to, change entries or anything else that modifies the array.

This is much more compact compared to the ReadOnlyArray<string> type.

With TypeScript 3.4, we have the new read-only tuple type. We can declare a read-only tuple as follows:

const strTuple: readonly [string, string] = ['foo', 'bar'];

The readonly modifier on mapped types will convert to array-like types to their corresponding readonly counterparts.

For example, if we have the type:

type ReadOnly<T> = {
    readonly [K in keyof T]: T[K]
}

Then when we pass in a type into the generic type placeholder of Readonly as follows:

type foo = Readonly<{foo: number, bar: string}>;

We get that the foo type is:

type foo = {
    readonly foo: number;
    readonly bar: string;
}

As we can see, both fields have become readonly , which isn’t the case before TypeScript 3.4.

We can also use mapped types to remove the readonly modifier from all the fields. To do this, we add a - before the readonly modifier.

For example, we can write:

type Writable<T> = {
    -readonly [K in keyof T]: T[K]
}

interface Foo{
    readonly foo: string;
    readonly bar: number;
}

type foo = Writable<Foo>;

Then we get:

type WriteFoo = {
    foo: string;
    bar: number;
}

For the type foo .

The readonly modifier can only be used for syntax on array types and tuple types. It can’t be used on anything else.

Photo by Erin Wilson on Unsplash

Const Assertions

A constructor called const assertions is introduced with TypeScript 3.4. When we use it, we signal that literal types can’t change to a type that’s wider in scope, like going from 1 to string . Objects literals get readonly properties. Array literals become readonly tuples.

For example, the following is valid:

let x: 'foo' = "foo" as const;

We get that x is type 'foo' when we inspect its type.

Another example would be a number array:

let x = [1, 2] as const;

When we hover over x , we get that the type is readonly [1, 2] .

Conclusion

With TypeScript 3.4, we have multiple changes for read-only types, including using the readonly keyword to declare read-only arrays and tuples.

Also, we can add and remove the readonly modifier with mapped types with the readonly and -readonly modifiers before the index signature or field name.

The const assertion is for converting a value into a read-only entity.

High order generic functions that let us compose multiple functions together to return a new composed function also have smarter type inference than in earlier versions.

Finally, we have the --incremental flag to create incremental builds, which makes code build faster on subsequent builds.