Useful Things You Missed in the JavaScript Window Object: documentURI, embeds, and fonts

John Au-Yeung - Jan 26 '20 - - Dev Community

Subscribe to my email list now at http://jauyeung.net/subscribe/

Follow me on Twitter at https://twitter.com/AuMayeung

Many more articles at https://medium.com/@hohanga

Even more articles at http://thewebdev.info/

The window object is a global object that has the properties pertaining to the current DOM document, which is the things that are in the tab of a browser.

In this article, we’ll look at some window.document object and how to use them, including the documentURI, embeds, and the fonts properties.

window.document.documentURI

The documentURI is a string property that returns the document location. It was originally a read/write property, but now it’s read-only. For example, if we have:

console.log(document.documentURI);

We get something like:

"https://developer.mozilla.org/en-US/docs/Web/API/Document/documentURI"

from the console.log output.

window.document.embeds

The embeds property is a read-only property that returns a list of embedded object elements within the document. For example, if we have the following embed element to add a video to our web page:

<embed type="video/webm" src="https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4" width="250" height="200">

Then in the script file, we can use write the following code to get our embed element:

console.log(document.embeds);

Then we get an HTMLCollection array-like object, which has our embed element for our video. An HTMLCollection object has an item method that lets us get the DOM element in the HTMLCollection object by its index. Also, since it’s an array-like object, we can use it with the for...of loop like in the following code:

for (const el of document.embeds) {  
  console.log(el);  
}

If we run the code above, we get back the embed elements that are in our web page. We can also get the properties of the embed element like in the following code:

for (const el of document.embeds) {  
  const {  
    height,  
    src,  
    type,  
    width  
  } = el;  
  console.log(height, src, type, width);  
}

We should get something like:

200 https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4 video/webm 250

if we have the embed element above. Those values are the same as the values of the attributes we passed in. We can replace the for...of by getting the element by index with the item method available to the HTMLCollection object instead:

console.log(document.embeds);  
for (let i = 0; i < document.embeds.length; i++) {  
  const {  
    height,  
    src,  
    type,  
    width  
  } = document.embeds.item(i);  
  console.log(height, src, type, width);  
}

window.document.fonts

The fonts property returns a FontFaceSet object that has various properties and events that let us handle the loading of fonts. For example, if we have the following code:

console.log(document.fonts);

We get the FontFaceSet object. The FontFaceSet object has the following properties. It has the status read-only property, which is a string, that indicates the loading status of the document’s fonts. The value can be 'loading' or 'loaded'.

Another property of the FontFaceSet is the ready read-only property, which is a promise which resolves once fonts are loaded and the layout operations are completed. For example, we can write the following to log ‘fonts loaded’ once all the fonts are loaded:

(async () => {  
  await document.fonts.ready;  
  console.log('fonts loaded');  
})()

The document.fonts property also has 3 events — the onloading event, onloadingdone event, and the onloadingerror event. The onloading event handler is called when the loading event is fired, which indicates that the font has started loading.

The onloadingdone event handler is called whenever an event of type loadingdone is fired, which means that the font face set has successfully loaded. The onloadingerror event handler is called whenever a loadingerror type is fired, which indicates that the error occurred while loading a font face set.

For example, we can use the event handlers like in the following code:

document.fonts.onloading = () => {
  console.log('Font is loading');
}
document.fonts.onloadingdone = () => {
  console.log('Font successfully loaded');
}
document.fonts.onloadingerror = () => {
  console.log('Error loading font');
}
(async () => {
  await document.fonts.load("12px Roboto", "A");
})();

And in the HTML file, we add:

<link href='https://fonts.googleapis.com/css?family=Roboto:400,700' rel='stylesheet' type='text/css'>

Then we should get ‘Font is loading’ and ‘Font successfully loaded’ logged when we run the code since we loaded the font from the Google Font CDN by first including the font in our web page with the link tag and then we attached the event listeners to the font loading events.

Then finally, we ran the document.fonts.load method which does the loading of the Roboto font, which will trigger the onloading event and onloadingdone event handlers since we have the font loaded from the Google CDN which should be available for loading.

The load method that we used above returns a promise and takes 2 string arguments. The first is the string that represents the font size and name using CSS value syntax as we have above.

The second argument is the text that limits the font loading to the characters in the string we have above. The range should be one of the characters in the text. The second argument is optional.

In addition to the load method, there are a few more methods in the document.fonts object. It includes the add method which adds a font to the font set.

It takes one argument, which is the FontFace object. We create the FontFace object by using the FontFace constructor, which takes 2 arguments.

The first argument is the string of the font face name, and the second argument is the URL of the font face, which should be expressed like URLs in the CSS code.

For example, to add a font to our document with the add method, we can write:

const fontFace = new FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)');
document.fonts.add(fontFace);

The FontFace object as a loaded property, which returns a promise that resolves when the font designated in the FontFace constructor is loaded. For example, we can write:

const fontFace = new FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)');
document.fonts.add(fontFace);
(async () => {
  await document.fonts.load("12px Bitter", "A");
  const loadedFontFace = await fontFace.loaded;
  console.log(loadedFontFace);
})()

In the code above, we added the Bitter font with the add method and use the load method to load the newly added font. Then at the end, we logged the font face, we get the properties of the FontFace object, which should have something like the following output:

display: "auto"  
family: "Bitter"  
featureSettings: "normal"  
loaded: Promise {<resolved>: FontFace}  
status: "loaded"  
stretch: "normal"  
style: "normal"  
unicodeRange: "U+0-10FFFF"  
variant: "normal"  
weight: "normal"

To check if a font has been loaded and is available, we can use the check method, which returns a boolean and takes up to 2 arguments.

The first is a string with the font name with its properties in CSS value syntax.

The second argument is the text that limits the font loading to the characters in the string we have above.

The range should be one of the characters in the text. The second argument is optional. For example, we can use it as in the following code:

console.log(document.fonts.check("12px Roboto", "a"));  
console.log(document.fonts.check("12px Arial", "a"));

The first console.log should output false since we didn’t load the Roboto font by writing any code. The second console.log should be true since it’s a font that is loaded without having to add any code to load it externally.

The clear method removes all the fonts from the font set. It takes no arguments. For example, we can use it as in the following code:

const fontFace = new FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)');
document.fonts.add(fontFace);
(async () => {
  await document.fonts.load("12px Bitter", "A");
  console.log(document.fonts.check("12px Bitter", "A"));
  const loadedFontFace = await fontFace.loaded;
  document.fonts.clear();
  console.log(document.fonts.check("12px Bitter", "A"));
})()

In the code above, we first load the font with the load method and then unloaded it with the clear method, so the first console.log should log true since loaded the font with the load method and the second one should log false since we called the clear method to unload it.

Finally, there’s the delete method which removes a font from the font set. It takes a FontFace object as its only argument. For example, we can use it as in the following code:

const fontFace = new FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)');
document.fonts.add(fontFace);
(async () => {
  await document.fonts.load("12px Bitter", "A");
  console.log(document.fonts.check("12px Bitter", "A"));
  const loadedFontFace = await fontFace.loaded;
  document.fonts.delete(loadedFontFace);
  console.log(document.fonts.check("12px Bitter", "A"));
})()

In the code above, we first load the font with the load method and then unloaded it with the delete method with the loadedFontFace passed in, so the first console.log should log true since loaded the font with the load method and the second one should log false since we called the delete method with the loadedFontFace passed in to unload it.

We continued from Part 5 of this series and looked at more properties of the window.document object which includes documentURI, embeds and the fonts properties. The documentURI property gets us the URL of the currently loaded document.

The embeds property get us all the embed DOM elements in our document and let us see the attributes. The fonts properties have many properties that let us get the status of the fonts we loaded, and it also has methods that let us load and unload fonts as we want them.

It also lets us check the status of the font you want to load. It’s very handy for loading custom fonts that aren’t normally built into operating systems and usable by browsers without loading.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .