Natural sorting in JavaScript

If you only ever deal with English strings in your code, you can stop reading now. Unless you are curious and want to learn something new, then please stay. 😉

In languages like German, we have characters that don’t exist in the English alphabet. Some look similar to other characters, but some are extra. And in German we only have 4 of them, other languages have many more.

How strings are usually sorted

When you have an array of strings, there are different ways in how they are sorted. Let’s look at some examples:

console.log(['c', 'b', 'a', 'B', 'A', 'C'].sort())
// (6) ['A', 'B', 'C', 'a', 'b', 'c']

If you ever wrote some code and sorted it with a simple sorting function, you might be aware that many of them use the order of the characters in the ASCII table. That’s why we see the capital letters first, followed by the lower-case letters.

That might be just what we expect and want for English. But let’s throw in some German Umlaut into the array:

console.log(['ä', 'b', 'a', 'B', 'Ä', 'A'].sort())
// (6) ['A', 'B', 'a', 'b', 'Ä', 'ä']

Even if you don’t speak German and don’t know about the order of letters, this doesn’t look correct, right? The capital “Ä” comes after all other lower-case letters. Since the Umlauts are not part of the ASCII table (like most letters not include in “Basic Latin”), JavaScript is using their UTF-16 code unit values so sort them. These also represent each character with a number. The letter “Ä” for example has the numeric value 228, while “z” has 122, and that’s why it is ordered like above.

Using the Intl.Collator object for natural sorting

The solution for this is really very easy. The sort() function for an array can take a callback function as a parameter. This function get passed two values of the array. It should return a negative number, if the first value is smaller than the second one, return a positive number, if the opposite is true, or return 0, if both have the same value.

But we don’t have to write such a callback function for every language ourselves. Instead, we can use the Intl.Collator object. For our German umlaut example, the code would look like this:

console.log(['ä', 'b', 'a', 'B', 'Ä', 'A'].sort(new Intl.Collator('de').compare));
// (6) ['a', 'A', 'ä', 'Ä', 'b', 'B']

Not only do we now have our umlaut next to the similarly looking letters, we also get each lower-case letter followed by its capital letters. This is also what you would expect from a “dictionary sorting”.

Using the compare function directly

As mentioned earlier, the sort() function expects a callback that returns a negative, or positive number, or a 0. And this is exactly what the function does. We can explicitly call that function (and not only reference its name) and pass in two letters to compare:

new Intl.Collator('de').compare('ä', 'a')
// 1
new Intl.Collator('de').compare('a', 'ä')
// -1
new Intl.Collator('de').compare('a', 'a')
// 0

To demonstrate, that this function is not simply using a static list of numbers for each character, but really sorts by a specific language, here is a good example for that:

new Intl.Collator('de').compare('ä', 'z')
// -1
new Intl.Collator('sv').compare('ä', 'z')
// 1

The Swedish language, which I’m currently trying to learn, also has the “ä” letter. But it is sorted differently than a German umlaut, and you would find words starting with almost at the end of a Swedish dictionary (only followed by words starting with “ö”).

Using advanced options

There are some options you can also pass as an object to the sort() function, like in this example, when you want to have capital letters first:

console.log(
	['ä', 'b', 'a', 'B', 'Ä', 'A'].sort(
		new Intl.Collator(
			'de', 
			{
				caseFirst: 'upper'
			}
		).compare
	)
);
// (6) ['A', 'a', 'Ä', 'ä', 'B', 'b']

You can find some more options on the documentation page or a full list in the ECMA specification. There are even some wild “languages” like “de-u-co-phonebk“, to order an array like it would appear in a German phone book – in case you know what I am talking about. 😁

Bonus: Sorting number string

I don’t want to write about all options, but one might be really helpful in your code. If you even sorted an array with numbers as string, you know that alphanumeric sorting does not work:

console.log(['1', '2', '11', '101', '3'].sort());
// (5) ['1', '101', '11', '2', '3']

But with the option numeric, you get what you want (the first “language” parameter might not be important here):

console.log(
	['1', '2', '11', '101', '3'].sort(
		new Intl.Collator(
			'en',
			{
				numeric: true
			}
		).compare
	)
);
// (5) ['1', '2', '3', '11', '101']

Just what we wanted to have. 😊

Conclusion

Sorting strings by their natural order in a specific language can really make a big difference on how usable your code is (or if it would even break things, if done incorrectly). With the Intl.Collator object, this is made rather easy in JavaScript. Other programming languages don’t provide such a powerful tool for you.

Simulate preferences in the browser

Before we get into some topics in the advent calendar, we need to learn about a browser feature. Therefore, I have changed the order of my planned topics on debugging a bit to have this one earlier.

In some of my next blog posts, I will talk about some CSS features, that can benefit certain people using your website. Almost 5 years ago, I had a blog post on how to “Recude motion on a website for better accessibility“. In this blog post, I’ve explained how you can change the settings in Windows 10 or Android 9, to simulate the reduced motion preference. But you might use a different operating system (like I use Manjaro Linux for work), where there is no quick setting, or you want to quickly toggle the setting. Fortunately, some browsers have such a toggle for you.

Setting preferences in Chrome

In Chrome (and other browsers based on the Chromium project like Edge) you can find most settings by clicking on the three vertical dots in the top right, then you choose “More tools” and open the “Rendering” tools:

Screenshot on how to open the "More tools > Rendering" settings.

This opens up another panel in the development tools. If you scroll down a bit, you will find these settings, you can use to simulate different preferences. In this example, I am setting prefers-reduced-motion to reduce:

Screenshot of the different rendering settings with the "prefers-reduced-motion" setting opened.

The only downside with this setting: as soon as you close the developer tool, the setting would reset to its default value. If you want to test a site with more vertical space available (since the two panels use a lot of height), I would suggest detaching the developer tools from the browser window.

We will need these settings in upcoming topics. But there are more options to simulate settings that will change the behavior and look of your site. If you want to quickly display your site with a dark color scheme, you don’t have to change your operating system to a dark color scheme or open up the rendering settings. Instead, you will find a nice toggle in the “Styles” section. Click on the “paint brush” icon and switch to the color scheme you want to test.

Screenshot of the opened toggle to switch the "prefers-color-scheme" setting.

Unfortuantey, just as with the rendering panel, the color scheme will switch back to the default value, as soon as you close the development tools.

Setting preferences in Edge

Even though Edge is based on Chromium and many development tool look exactly the same, you will not find the “More tools > Rendering” panel in Edge. Instead, you open up the dev tools first. On panels like “Elements” you will see the “Console” and “Issues” int the lower part. Here, you click on the “+” icon and choose the “Rendering Quick View”. It looks very similar to Chrome once opened.

Screenshot of the opened "Add tool to Quick View" panel in Edge.

You also have a quick toggle for the colors scheme in Edge with a “paint brush” icon, just as in Chrome.

Setting preferences in Firefox

In Firefox, the settings are not easily available. They are also located in different places. If you want to set the prefers-reduced-motion, you have to navigate to the URL about:config, then search for ui.prefersReducedMotion, add a boolean value and set it to false. For prefers-reduced-transparency however, you would search for layout.css.prefers-reduced-transparency.enabled and set this to true. That’s all very inconsistent and annoyingly not all in one place.

If we want to toggle the color scheme, we are more lucky. Firefox offers two buttons. With the “sun icon”, you can enforce the light color mode and with the “waxing crescent moon icon”, you can enforce the dark color mode.

Screenshot of the "Toggle dark color scheme" icon in Firefox.

Toggling one of them disables the other one. If you disable both, the default will be taken.

Bonus: faster toggle of preferences in Chromium browsers

I can’t tell you how to change the preferences in Safari, since I don’t use a Mac (or a simulates Safari often enough). But I have a nice little bonus tip for you. If you want to quickly change one of these preferences, you can use the “Run command” feature in Chromium browsers.

While the dev tools are open, hit “CTRL + SHIFT + P” (or “Command + Shift + P” on a Mac) and then search for a preference to toggle:

Screenshot of the "Run command" modal with a search for the term "prefer" showing "Emulate CSS prefers-color-scheme: dark" as the first matching command.

I haven’t found an equivalent feature in Firefox, but maybe one of you know it?

Conclusion

When developing a website that behaves or renders differently, depending on preferences set in the operating system, you should always test this. But you don’t have to change the settings of your operating system. Browser usually have options to emulate those.

If any of you knows better options for these settings in Firefox or an extension that would allow you to switch those more easily, please share your tips in the comments.

Display a progress bar on your site

If you implement some web application, where the indication of the current progress would improve the UX, a nice little progress bar can help. And there is an easy way to add one. When in the past, we would have used something like jQuery UI Progressbar, we can use a native HTML element.

The progress HTML element

If you think of how to create an element to visualize some progress on a website and which attributes it has, you might think about something similar to the range input we had in a previous blog post, but the element is much simpler:

<label for="progress-bar">Progress:</label>
<progress id="progress-bar" value="30" max="100">30 %</progress>

This is how the native <progress> HTML element looks like in Chrome with the code from above:

A label "Progress:" followed by the progress element with a 30% progress.

As you can see, the element is inline. And do you recognize something? Even though this is not a form element, it is combined with a label. This enhances its accessibility. Adding the value as a text node inside, this text will not be visible in the browser if the element is supported. So this is only needed, if you are dealing with really older browsers not supporting the element, to show this inline text instead.

Advanced usage of the element

Have you recognized, that we have not set a min attribute in the example? This attribute is not available, because the min value always defaults to 0.

But did you know, that you can also not use the value attribute and what would happen then? It might blow your mind a bit, but this is what would happen:

That’s right! You would get an animating progress bar. No JavaScript, no CSS animation, just a <progress> element without a value. And to make it even more amazing, you can use it with some attributes for an accessible progress indicator for a different region of the site. Here is an example from the documentation page:

<div aria-busy="true" aria-describedby="progress-bar">
  <!-- content is for this region is loading -->
</div>

<!-- ... -->

<progress id="progress-bar" aria-label="Content loading…"></progress>

If you are in a WordPress project, you can use the ProgressBar component. In WordPress Core, it seems to only be used for a “loading animation” progress bar like above. It does use the <progress> element, but again with some custom HTML markup replacing the browser default visualization, so it has the same styling in all browsers.

Conclusion

A progress bar can really improve the UX for a web application. If you need one, why not go with the native one. You can also style it a bit. More on that could be found in the linked documentation pages. If you add a <progress> element, please do make sure to also have a label with it. Not only does it help users with assistive technology, but indicating that the progress stands for helps any user.

Nested CSS without preprocessors

I don’t know when I’ve started using Sass but. My first blog post on that topic dates back to 2012. There are many features I love Sass for, and one of them is nesting.

What is nesting in Sass

A typical example for when nesting is really helpful is when dealing with CSS selectors of elements, that are usually children of other elements. Unordered lists used for navigation menus are a great example here:

nav {
	ul {
		list-style: none;

		ul {
			display: block;
		}
	}

	li {
		display: inline-block;
	}

	a {
		display: block;
		padding: 5px 10px;
	}
}

In this code, we have some child (or grandchild) nodes of a <nav> tag. By nesting them, and using a preprocessor like Sass, we get the following result in the compiled CSS:

nav ul {
  list-style: none;
}
nav ul ul {
  display: block;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 5px 10px;
}

Many of you will probably agree, that the Sass code is easier to write and change, as you don’t have to write the full CSS selector. Rearranging the nesting becomes really easy, compared to replacing the middle parts of long CSS selectors. The selectors I’ve chosen above are rather short. This is on purpose, as you should not nest too much, just because you can, or even worse, because it replicated your HTML. We probably don’t need a CSS selector like “nav ul li a“, since if we just want to style every link in the navigation, just having “nav a” is all we need.

How to use nesting without a preprocessor?

If you try to use that nicely nested code in a .css file, it might just work. No more need to use a preprocessor. But you might have to support a browser, that does not implement this new specification, and which doesn’t understand this syntax. For those browsers, all you have to do is adding an & before each nested selector. The code above changes to this:

nav {
	& ul {
		list-style: none;

		& ul {
			display: block;
		}
	}

	& li {
		display: inline-block;
	}

	& a {
		display: block;
		padding: 5px 10px;
	}
}

Fortunately, all major browsers have implemented this new specification, where you don’t have to add the & before the nested selectors. But they also support the old syntax. So if you want to be safe, you could still use this old syntax for some time. I can also highly recommend reading a bit more on CSS nesting in the documentation.

Conclusion

That’s it! Just use nesting as in Sass, Less and other preprocessors and modern browsers will understand your code. If you still use a preprocessor for other things like variables, they will still convert this syntax into the normal “long CSS selectors”.

With CSS custom properties (variables) and nesting, there are two of three features now native to CSS, I use a lot in Sass. The last one is “templating” using multiple files for different part/components. The rest like mixins are more “nice to have” for me, but not really essential.

Dynamic parameters in JavaScript

Many programming languages have this. Instead of defining all parameters for a function, you can pass any number of parameters into a function and then work with them.

Functions with static parameters

Before we get into dynamic parameters, let us introduce a function we can then work on. How about one adding two numbers?

function sum( a, b ) {
	return a + b;
}

console.log( sum( 4, 5 ) ); // 9

Nothing special here, right? But what would happen if we just add more parameters to the function call?

console.log( sum( 4, 5, 6 ) ); // 9

Nothing would happen, since the function is only using the first two parameters. But you not get an error. JavaScript is simply not using the third parameter.

The arguments object

Even if we don’t use the third parameter, it is still available. But how can we use it, when we don’t have a parameter name for it? We can use the arguments object to get all the parameters, even if we haven’t even defined any parameter for the function:

function sum() {
  let total = 0;
  for (const number of arguments) {
    total += number;
  }
  return total;
}

console.log( sum( 4, 5 ) ); // 9
console.log( sum( 4, 5, 6 ) ); // 15

The arguments object works very much like an array. You can access the first parameter with arguments[0], etc. In our sum() function, we don’t even have any arguments at all, as mentioned before. But you can also combine defined and additional ones:

function someFunction( a, b ) {
	console.log( a ); // 4
	console.log( b ); // 5 
	console.log( arguments ); // [4, 5, 'a string', Array(2), ...]
}

someFunction( 4, 5, 'a string', [ 'an', 'array' ] );

The arguments object always contains all parameters passed to the function, even those with a name. The object has some other properties, you can read more about in the documentation.

The rest parameter

A more modern way to use dynamic parameters in JavaScript is the rest parameter. Let’s start with a simple example again. We implement our sum() function and use the rest parameter this time:

function sum( ...numbers ) {
	let total = 0;
	for ( const number of numbers ) {
		total += number;
	}
	return total;
}

console.log( sum( 4, 5 ) ); // 9
console.log( sum( 4, 5, 6 ) ); // 15

The only parameter here is “...numbers“, and this is the “rest parameter”. Another good example is this one:

function calc( operation, ...numbers ) {
	switch ( operation ) {
		case "sum":
			return numbers.reduce( ( total, num ) => total + num, 0 );
		case "multiply":
			return numbers.reduce( ( product, num ) => product * num, 1 );
		case "subtract":
			return numbers.reduce( ( difference, num ) => difference - num );
		case "divide":
			return numbers.reduce( ( quotient, num ) => quotient / num );
		default:
			console.error(`Invalid operation "${operation}"`);
			return;
	}
}

console.log( calc( "sum", 4, 5, 6 ) ); // 15
console.log( calc( "multiply", 4, 5, 6  ) ); // 120

Now the “rest” makes sense, right? We have some normal parameters, followed by the rest parameter, which contains all other parameter, or simply, the rest of the parameters. You can always only have one rest parameter, and it must be the last parameter. This example also shows a good use case for the console.error() function from our previous blog post.

Bonus: the arguments object used as the rest parameter

In our first example on the rest parameter, you wouldn’t even need to have the ...numbers parameter, since it’s the only parameter. You could just have used argument object in combination with the spread operator like this:

function sum() {
  let total = 0;
  const numbers = [...arguments]; // Convert arguments object to a real array
  for (const number of numbers) {
    total += number;
  }
  return total;
}

This conversion in line 3 is not really necessary, since the arguments object behaves very similar to an array, but nonetheless you can do it and might have a use case for this. But as soon as you have more (named) parameters, that probably wouldn’t work anymore.

Conclusion

A function with a fixed number of arguments might be too inflexible, especially, when you deal with arrays or lists. In these cases, the rest parameter or the arguments object can help to write some nice and short functions.

Advanced JavaScript debugging

In the very first advent calendar blog post this year, I’ve shown you how to “Getting started with JavaScript debugging“. Today, I want to show some more advanced techniques you can use to debug your code.

Different logging types

In the first blog post, we have only used console.log(), but there are more functions from the console object you can use:

console.debug('debug message');
console.info('info message');
console.log('log message');
console.error('error message');
console.warn('warn message');

And this is how they would look like in the Chrome Console:

The Chrome Console with the output of the four debugging methods info, log, error and warning.

The info and log method produce a similar output. The error and warning however are styled more prominent. Some of you might have noticed, that we only see 4 lines here. Where is the debug logging? This one might not be shown (by default) in your browser. In Chrome, you would click on the “Default levels” dropdown. Here, you can also activate “Verbose” to see the debug messages:

The Chrome Console with the output of debug method as well, after activating the "Verbose" debug level.

Since the debug output is also similar (in Chrome), you might not really need it. I would probably mainly use log, warning and error.

Using format strings and styling in messages

The debugging function accepts more than one parameter. If you just ass multiple strings, numbers, objects, etc., it would print each of them in one line separated by a space (for scalar types) or in multiple lines (for objects). But you can also use additional parameters for format strings and even styling.

Let’s begin with a format string. An example with a single %s placeholder for a string might look like this:

const code = 'Code';
console.log('%s is Poetry.', code);

And the output would be Code is poetry, as we would expect. But apart from the usual format string placeholder, you can use the %c placeholder. The very next parameter would be a CSS string, the following text would be styles with. Just like this:

console.log(
	'This is %csome green text, followed by %csome red and italic text.',
	'color: green;',
	'color: red; font-style: italic;',
);

If you have multiple %c placeholders, the styles our change to the next parameter and style any following text with these new styles. The output from the code above looks like this:

You can also combine the %c placeholders with any other usual placeholder. Why don’t you give it a try in your current browser console? But you can’t go too crazy. There are also a few CSS properties and values you can use in Firefox and Chrome.

More useful console debugging function

If you log a lot of messages, you can group them. You would start a new group by calling the console.group() function (with an optional label) and close the group with console.groupEnd(). You can even nest groups in groups, creating something like a “tree structure”.

There are some other instance methods you mind find useful in your debugging task, but one of them is really cool!

Measuring times in the console

The console object has some timing functions you can use for some easy performance checks. Here is an example using the console.time() function:

console.time("a timer label");
slowFunction(1000);
console.timeEnd("a timer label");

function slowFunction(milliseconds) {
	const start = Date.now();
	while (Date.now() - start < milliseconds) {
		// Simulating a long-running function
	}
}

The function “waits for one second” inside the while loop. The output in Chrome looks like this:

a timer label: 999.2578125 ms

Using the optional “label” as the first parameter, you can have multiple timers running. If you want to measure times in between, you can use console.timeLog() (with your label) to get “split times”.

Conclusion

While developing or analyzing some code, it can really help to log things to the browser console. If you have only used console.log() so far, make yourself familiar with the other useful methods.

But when it comes to finalizing your code, always make sure to remove those debugging methods. Some JavaScript compilers might even do that automatically, when you “build for production”.

The native HTML range input

Many of us have seen and used them. In the WordPress Block Editor, they are available for things like the font size of several blocks. This is how it looks for the core/paragraph block:

The "Typography" settings for the font size of a paragraph block, showing a number input on the left, and a range input on the right, with the numeric value in a tooltip below it.

When you use the range selector, it will show the current value under the “range thumb” and also updates it in the number input field left of it.

Options for the range input

The two most important attributes to the range input are probably the min and max attributes. So this is a basic example:

<input type="range" id="font-size" name="font-size" min="16" max="96" />
<label for="font-size">font size</label>

As always, don’t forget to have a <label> for your inputs. If you don’t set min, its default value will be 0 and for max it will be 100.

Another attribute you might want to use it step. This can be a decimal or floating-point value, like in this example:

<input type="range" id="font-size" name="font-size" min="16" max="96" step="4" />
<label for="font-size">font size</label>
<input type="range" id=">line-height" name="line-height" min="0" max="10" step="0.1" />
<label for="line-height">line height</label>

For some reason, WordPress is not using a range input, but only a number field. But it is also using a step width of “0.1” here.

On the documentation page, you will also find a rather crazy example for the step attribute, and it looks like this:

<input id="pi_input" type="range" min="0" max="3.14" step="any" />

If you use the value “any“, the input will really take “any floating-point” value in between min and max. Interestingly, if you use your keyboard to navigate to the range input, and then use the left/right cursor keys to move the thumb, you will get 100 discrete values. But if you use your mouse, you will get some random wild numbers in between.

Using the list attribute

In the last blog post on the HTML topic, we have already learned about the list attribute, and the range input also supports it. You can find some normal and creative examples in the documentation. In Chrome, using a list attribute lets the thumb “snap” to <option> values of the <datalist>, but you can still also have a value in between. In my opinion, you can best combine the list attribute with steps, as in this case, you only allow the selection of options in your <datalist>:

<label for="temp">Choose a comfortable temperature:</label><br />
<input type="range" id="temp" name="temp" list="markers" step="25" />

<datalist id="markers">
  <option value="0"></option>
  <option value="25"></option>
  <option value="50"></option>
  <option value="75"></option>
  <option value="100"></option>
</datalist>

This code shows an input without min/max values, but with an additional step="25" attribute. Also take a look at the example using labels.

Styling of the range input

The styling would look very different, depending on your browser or operating system. Even though WordPress is using a range input, what you see is not the input itself. It is made “transparent” and lays above some custom HTML using multiple spans to create a UI element, that looks the same in all browsers. If you want to use that exact element, you can use the RangeControl component in your JavaScript code.

But even if you can’t style the range input exactly the same, there are some options to styles it, like changing the color of the bar and thumb:

input[type='range'] {
  height: 30px;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  height: 10px;
  background: red;
}
input[type='range']::-webkit-slider-thumb {
  position: relative;
  height: 30px;
  width: 30px;
  margin-top: -10px;
  background: green;
  border-radius: 50%;
}

This is only one example for Chrome/Webkit. It’s important to set many things to appearance: none, as otherwise the other styling changes would have no effect. These styles would result in a range input like this:

A label "Choose a comfortable temperature" with a range input below it. The input has a red background color (the range bar) and a green "thumb" (a circle to change the value).

You all know I’m not a designer, but I hope this illustrates the styling a bit. If you want to go really creative, take a look at the blog posts from CSS-Tricks, Smashing Magazine or W3Schools.

Conclusion

Range inputs can really make the UX of an online application better, since number inputs are not “as responsive” in some cases. And if you are not in the WordPress JavaScript ecosystem, using the native range input might be all you need.

Smooth scrolling using CSS

More than 9 years ago, I wrote a (German only) blog post about how to “improve JavaScript with scroll event handlers”. Back in the days, people would use a plugin like “WP-Smooth-Scroll” (it’s still around, but hasn’t been updated in 11 years). Smooth scrolling was often used in combination with a “scroll to top button”. The scroll effect was done with the scrollTop() function from jQuery. Nowadays, jQuery is not used as much. But scrolling with JavaScript is still around.

Scrolling a page with JavaScript

Beside “scroll to top buttons”, a website can also use “smooth scrolling” for anchors. If you want to see it in action, look no further than on the file wp-includes/js/admin-bar.js in WordPress core, where you will find this function:

/**
 * Scrolls to the top of the page.
 *
 * @since 3.4.0
 *
 * @param {Event} event The Click event.
 *
 * @return {void}
 */
function scrollToTop( event ) {
	// Only scroll when clicking on the wpadminbar, not on menus or submenus.
	if (
		event.target &&
		event.target.id !== 'wpadminbar' &&
		event.target.id !== 'wp-admin-bar-top-secondary'
	) {
		return;
	}

	try {
		window.scrollTo( {
			top: -32,
			left: 0,
			behavior: 'smooth'
		} );
	} catch ( er ) {
		window.scrollTo( 0, -32 );
	}
}

As you can see from the comment, this function has been around since WordPress 3.4, which was released in June 2012! The behavior: 'smooth' was added only later, since Firefox added it in 2015 and Chrome in 2017. But still today, you can click on the “Admin Bar” (on anything but a link) and the website will scroll up smoothly.

The issue with method

As we can see in the code above, the scrollTo() function takes an object with the exact scroll position in the viewport. For the WordPress “Admin Bar”, this is easy, since it sticks to the top of the page. But if we want to scroll to another element on the page using an anchor link, we need to calculate the position. And do you remember our last blog post on the CSS topic, “How to fix sticky headers“? If we want to make sure the scroll position is correct, we also need to take the scroll-margin-top offset into account.

An alternative JavaScript approach

There is another scrolling function, that is also around for many years: the scrollIntoView() function. With this one, we don’t have to calculate the position. We just select the element we want to scroll to and use this function on it:

const element = document.getElementById("some-anchor");
element.scrollIntoView();

The great thing about this one, is that you can even tell the function where to place the element. And it takes the scroll-margin-top or similar properties into account. There are some more examples on the documentation page. One of these other CSS properties is the one, I want to write about in this blog post.

The CSS scroll-behavior

Even without JavaScript, you can get a smooth scrolling by only using CSS. Just add the following to your page:

html {
	scroll-behavior: smooth;
}

Now, when you click on any anchor link, the site will “scroll smoothly” to that element. And since the browser knows exactly how to do that, we always get the perfect scroll position for that element.

Conclusion

Sure, you can use a function with 20 lines like in WordPress Core for a smooth scrolling effect. But you could also just use one CSS property and regular anchor links to get the same result. And I haven’t even told you about all the issues with JavaScript scrolling, like scrolling manual scrolling while the smooth scrolling is still animating, wrong position calculation due to lazy loading, etc. I hope this is enough to convince you for now. 😉

Labeled statement in JavaScript

You might now ask yourself: What?! That was also my first reaction, when I’ve heard about labeled statements. So what are they, and when can they be used?

Are they goto statements?

Many programming languages have goto statements. Some programming languages even only added them in later version, like PHP did with version 5.3, and this is how it would look like in PHP:

$array = [
	'one' => [ 1, 2, 3 ],
	'two' => [ 4, 5, 6 ],
];

foreach ( $array as $key => $numbers ) {
	foreach ( $numbers as $number ) {
		if ( $number === 4 ) {
			goto fourFound;
		}
	}
}

echo "There is no 4 in the array";
goto end;

fourFound:
printf( "There is a 4 in array '%s'", $key );

end:

In this example, we have two foreach loops. The code tries to and find a 4 in a two-dimensional array. As soon as a 4 is found, we can stop the loops and print the result. To leave the loop(s), this code is using a goto statement to “go to” line 17 to the label fourFound, where we print out the result. There is also a second goto at line 15, which would move to the end label. In any case, only one echo/printf function would be called.

Many experienced developers would see multiple ways to improve that code, but I hope it can demonstrate, how a goto in PHP (and many other languages work) works. But what are labeled statements in JavaScript? They are similar to the labels in PHP shown here, but there is no goto statement and those labels can only be used in combination with either the break or the continue keyword.

How to use continue and break in your code?

If you have a loop, you can break out of the loop, by using the break statement like this:

const numbers = [1, 2, 3, 4, 5, 6];

for (let i = 0; i < numbers.length; i++) {
	if (numbers[i] === 4) {
		console.log(`Found 4 at index ${i}`);
		break;
	}
}

This code would iterate through the numbers array, but as soon as it found the 4, it would “break out” of the array and not look at the other values.

The continue statement can be used to stop the current iteration and start with the next one. Like in this modified example:

for ( let i = 0; i < numbers.length; i++ ) {
	if ( numbers[i] % 2 !== 0 ) {
		continue;
	}
	if ( numbers[i] === 4 ) {
		console.log( `Found 4 at index ${i}` );
		break;
	}
}

In line 2, we check, if the current number is odd. If that’s the case, it can’t be the number 4 we are searching for. We then use the continue statement, to start with the next iteration, so the condition in line 5 would not be executed.

How to skip an “inner loop”?

Let’s take the first code example from PHP again and use the break statement instead of a goto statement:

$array = [
	'one' => [ 1, 2, 3 ],
	'two' => [ 4, 5, 6 ],
];

foreach ( $array as $key => $numbers ) {
	foreach ( $numbers as $number ) {
		if ( $number === 4 ) {
			break 2;
		}
	}
}

if ( $number === 4 ) {
	printf( "There is a 4 in array '%s'", $key );
} else {
	echo "There is no 4 in the array";
}

In PHP, you can use break 2 to not only exit the “inner loop”, but also the “outer loop”. So the number after break indicates how many “control structures” you want to break out from. Something similar is possible with continue 2, where the program would continue with the next iteration of the “outer loop”.

In JavaScript however, this is not possible. You cannot add any number after a break or continue statement. And that’s where labeled statements come into play.

Breaking out an inner loop in JavaScript

If we try to create the same code as above in JavaScript, we can use a labeled statement like in this code:

var array = {
	one: [1, 2, 3],
	two: [4, 5, 6],
};

outerLoop:
for ( var key in array ) {
	var numbers = array[key];
	for ( var i = 0; i < numbers.length; i++ ) {
		if ( numbers[i] === 4 ) {
			break outerLoop;
		}
	}
}

if ( numbers[i] === 4 ) {
	console.log( `there is a 4 in array ${key}'` );
} else {
	console.log( "There is no 4 in the array" );
}

The label does not need to be on its own line, it can also be in one line for the for loop. For better readability, I just formatted it like this.

If you prepend each loop with a label, you could also have use break statement to jump to any loop. The same is true for continue.

What should I use this for?

So should you use labeled statements? My advice would be similar to the one given by the xkcd comic on goto: Don’t use it!

If you end up writing some code that would profit from something like break 2, continue 2, or the JavaScript equivalent using a labeled statement, this would be a clear sign for me, that this piece of code should be refactored.

Instead of using a goto to jump out of a loop, put that loop inside a function and use return. And for nested loops, you can also use nested functions in loops.

There are plenty of things to optimize in the code above, not only the nested loops. With some modern JavaScript functions, it could look like this:

const array = {
	one: [1, 2, 3],
	two: [4, 5, 6],
};

function findTheFour(obj) {
	for (const property in obj) {
		if (obj[property].includes(4)) {
			return property;
		}
	}
	return null;
}

const found = findTheFour(array);
if ( found ) {
	console.log( `there is a 4 in array ${found}'` );
} else {
	console.log( "There is no 4 in the array" );
}

Isn’t that a lot easier to read? Using the includes() function for arrays, we can even safe the “inner loop”. And we do not need any labeled statement.

Conclusion

You may ask yourself why I’ve shown you this feature of JavaScript, and then advise against the usage of it. Well, there is code out there using it which you might not understand, if you have never seen labeled statements or goto in other programming languages. And I haven’t even shown you all the things you can do with it. So feel free to read the documentation on it, and maybe you do find a use case, where it can really benefit your code base, what ever case that might be.

Debugging arrays and objects in JavaScript with the console.table() function

In the first debugging blog post, we’ve learned about the console.log() method and how it works to debug scalar types or arrays. But there is a nicer way to log arrays or objects in the browser.

The console.table() function

As mentioned in the first blog post, the console object has some more useful functions, and today we want to take a look at the table() function.

Simple arrays

The function can be used to log arrays like this:

const colors = ["red", "green", "blue"];

console.table(colors);

This is the most basic example. We just use a one-dimensional (numerical) array. This is the result in the browser console:

Browser console, showing a table with "(index)" as the first column header and values ranging from 0-2, and "Value" as the second column header, with the color strings.

As you can see here, you get a table with two columns. The first one is the numerical “(index)” for the array, and the second one has the “Value” for each entry of the array. You will still always have the variable below the table, just as with console.log() and you can “expand” it here, to investigate it further.

Multidimensional arrays

The function can not only be used with simple one dimensional array, but you can also use it for multidimensional ones:

const names = [
	["Leia", "Organa"],
	["Luke", "Skywalker"],
	["Han", "Solo"],
];

console.table(names);

Now we have an array of (numerical) arrays and this is how it looks like in the console:

(index)01
0'Leia''Organa'
1'Luke''Skywalker'
2'Han''Solo'

We now have three columns. Since the “inner arrays” are numerical as well, we have column name “0” and “1” for them.

Logging objects

The function cannot only be used for arrays, but also for objects. The output depends on the structure of the objects.

Simple objects

Let’s create an object for one of the previous example:

function Person(firstName, lastName) {
	this.firstName = firstName;
	this.lastName = lastName;
}

const luke = new Person("Luke", "Skywalker");

console.table(luke);

And this is how that object would be logged into the browser console:

(index)Value
firstName'Luke'
lastName'Skywalker'

Logging arrays of objects

How about logging an array with multiple objects of the same type? Again, an example like before:

const leia = new Person("Leia", "Organa");
const luke = new Person("Luke", "Skywalker");
const han = new Person("Han", "Solo");

console.table([leia, luke, han]);

This is the resulting table for this array of objects:

(index)firstNamelastName
0'Leia''Organa'
1'Luke''Skywalker'
2'Han''Solo'

As many of you might have expected, the column names are now the property names of the objects.

Logging multidimensional objects

The previous example was using a numerical array. But how about an object of objects? Here is an example:

const family = {};

family.mother = new Person("Padmé", "Amidala");
family.father = new Person("Anakin", "Skywalker");
family.daughter = new Person("Leia", "Organa");
family.son = new Person("Luke", "Skywalker");

console.table(family);

And the result of this will look like this:

(index)firstNamelastName
mother'Padmé''Amidala'
father'Anakin''Skywalker'
daughter'Leia''Organa'
son'Luke''Skywalker'

That looks nice, right? Except for “(index)”, we have some good columns names and our index values also are not numerical anymore.

Logging only specific columns

The console.table() function has a second parameter columns, which is an array as well. It expects an array with the names of the columns/indices. So for our previous code, we could do this:

console.table(family, ["firstName"]);

And sure enough, this would be the logged results:

(index)firstName
mother'Padmé'
father'Anakin'
daughter'Leia'
son'Luke'

Pretty neat, isn’t it? This can be really useful when debugging some larger objects with multiple properties.

Conclusion

Even though you can use the generic console.log() function to debug and log arrays and objects, seeing them in a logged table, can make reading them a lot easier. You also don’t have to “expand” the tables.