Luca Ongaro

Web Engineer

Luca Ongaro Hi! I’m Luca Ongaro, a Web Engineer from Italy currently living in Berlin. This is my blog, where I like to share random experiments and the results of some of my tinkering with Web technologies.

Non-primitive Properties, CoffeeScript Inheritance and Class Macros

JavaScript’s prototypal inheritance paradigm is easy to understand, but can lead to nasty surprises when it comes to non-primitive properties. While the issue I discuss here is purely a JavaScript one, the fact that the awesome CoffeeScript syntax make it so easy to implement classes and extend them leads developers to run more frequently into this kind of situations.

The Issue with Non-Primitive Properties

The issue can occur whenever we have a CoffeeScript class (or JavaScript constructor) with a property which is not of a primitive type (basically anything which is not number, string, boolean, null nor undefined). For example, let’s have a class with an Array property:

1
2
class Person
  needs: ["eat", "drink", "breath"]

Now let’s create two instances, and let’s modify this non-primitive property on one of them:

1
2
3
4
5
6
7
8
9
10
11
12
guy   = new Person
maker = new Person

maker.needs.push "create"

console.log maker.needs
# => ["eat", "drink", "breath", "create"]
# Ok, looks good

console.log guy.needs
# => ["eat", "drink", "breath", "create"]
# Wait... what? `guy` got the "create" need added too?!?

Changing one instance led to unwanted changes to other instances too! This issue occurs because the needs property is stored in the shared [[Prototype]].

Note that if we overwritten the property on one instance everything would have been fine, since the overwritten value would live on that particular instance only. But if we only modify the property, it stays in the [[Prototype]] and the changes are shared among instances. This is why this issue can only occur with non-primitive properties: primitives are immutable.

Polyfilling the Details Tag

A common feature in many UIs is a widget that can be hidden or shown by clicking on some handle. Some examples are “accordions” or collapsible/expandable sections and navigation menus. Usually the interactivity is achieved with some JavaScript code that toggles the display property of some elements when a handle is clicked.

HTML5 adds two new tags that can theoretically be used to achieve the same effect without any JavaScript code: the details and the summary tags. Here is an excerpt from the HTML5 spec:

The details element represents a disclosure widget from which the user can obtain additional information or controls. […]

The first summary element child of the element, if any, represents the summary or legend of the details. If there is no child summary element, the user agent should provide its own legend (e.g. “Details”).

The rest of the element’s contents represents the additional information or controls.

The open content attribute is a boolean attribute. If present, it indicates that both the summary and the additional information is to be shown to the user. If the attribute is absent, only the summary is to be shown.

In other words, details is a block-level tag with a boolean open attribute that controls its visibility, and it usually have a nested summary tag that is always visible and represent the “handle” that toggles the open attribute, and thus the visibility, on and off.

Cool, isn’t it? Well, unfortunately support is currently quite poor, as at the moment only WebKit seems to properly implement it. The big question is: can we easily polyfill it and start using it in the real world?

Easy Two-Way Data Binding in JavaScript

Two-way data binding refers to the ability to bind changes to an object’s properties to changes in the UI, and viceversa. In other words, if we have a user object with a name property, whenever we assign a new value to user.name the UI should show the new name. In the same way, if the UI includes an input field for the user’s name, entering a value should cause the name property of the user object to be changed accordingly.

Many popular client-side JavaScript frameworks like Ember.js, Angular.js or KnockoutJS advertise two-way data binding among their top features. This doesn’t mean that it is too hard to implement it from scratch, nor that adopting one of those frameworks is the only option when this kind of functionality is needed. The underlying idea is in fact quite basic, and can be condensed into a 3-point action plan:

  1. We need a way to specify which UI elements are bound to which properties
  2. We need to monitor changes on the properties and on the UI elements
  3. We need to propagate any change to all bound objects and elements

DOM Selection Without jQuery

jQuery is so easy to use that sometimes we end up relying on it even for tasks that could be easily achieved using the native browser APIs. While there is nothing wrong with using jQuery, going native makes our code more portable, future proof and often more performant.

DOM selection is an example of something often performed with jQuery, but straightforward enough to achieve without any external library.

The Selectors API

The HTML5 Selectors API has been around for quite some time now, and it is supported in all modern browsers and in IE down to version 8. Its implementation is based on the querySelector family of methods, that includes four members:

  • document.querySelector( selector ) takes a CSS selector string and returns the first DOM element that matches the selector, or null if no match is found.

  • element.querySelector( selector ) does the same, but searching only among the descendants of element.

  • document.querySelectorAll( selector ) takes a CSS selector string and returns a non-live NodeList of all the DOM elements matching the selector. If no element matches the selector, an empty list is returned.

  • element.querySelectorAll( selector ) does the same as its counterpart defined on document, but again searching only among the descendants of element.