Jekyll2017-06-20T00:10:16+00:00http://ryanmorr.com/Ryan MorrWeb developer based in Barrie, Ontario, Canada. I love to create dynamic web applications with a particular passion for JavaScript, Node.js, CSS, and HTML5.True Hash Maps in JavaScript2015-05-21T00:00:00+00:002015-05-21T00:00:00+00:00http://ryanmorr.com/true-hash-maps-in-javascript<p>Using an object literal as a simple means to storing key-value pairs is common place within JavaScript. However, an object literal is not a true hash map and therefore poses potential liabilities if used in the wrong manner. While JavaScript may not offer native hash maps (at least not cross-browser), there is a superior alternative to object literals to capture the desired functionality without the pitfalls.</p>
<h2 id="the-problem-with-object-literals">The Problem with Object Literals</h2>
<p>The problem resides in the prototype chain of object literals as the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype#Properties">properties and methods</a> inherited from the <code class="highlighter-rouge">Object</code> prototype can clash with the mechanisms used to assert the existence of a key. Take for instance the <code class="highlighter-rouge">toString</code> method, checking the existence of a key with the same name using the <code class="highlighter-rouge">in</code> operator will result in a false positive:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = {};
'toString' in map; // true
</pre>
</div>
<p>This happens because the <code class="highlighter-rouge">in</code> operator looks up the object’s prototype chain to find inherited properties, in this case the <code class="highlighter-rouge">toString</code> method. To resolve this, the <code class="highlighter-rouge">hasOwnProperty</code> method was conceived which only looks for the existence of a specified key as a direct property of an object:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = {};
map.hasOwnProperty('toString'); // false
</pre>
</div>
<p>This works fine until you encounter a key named “hasOwnProperty”. Overwriting this method would cause further attempts to invoke the <code class="highlighter-rouge">hasOwnProperty</code> method to result in unexpected behavior, most likely an error depending on the new value:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = {};
map.hasOwnProperty = 'foo';
map.hasOwnProperty('hasOwnproperty'); // TypeError
</pre>
</div>
<p>A quick fix for this is leveraging a generic object literal, one that hasn’t been tampered with, and executing it’s <code class="highlighter-rouge">hasOwnProperty</code> method in the context of your hash map:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = {};
map.hasOwnProperty = 'foo';
{}.hasOwnProperty.call(map, 'hasOwnproperty'); // true
</pre>
</div>
<p>This works without any issues, but nevertheless, the object still imposes restrictions on how it can be utilized. For instance, every time you wanted to enumerate the properties of the object within a <code class="highlighter-rouge">for ... in</code> loop, you would need to filter out the properties of the prototype chain:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = {};
var has = {}.hasOwnProperty;
for (var key in map) {
if (has.call(map, key)) {
// do something
}
}
</pre>
</div>
<p>This can become a bit tedious after awhile. Thankfully, there is a better way.</p>
<h2 id="bare-objects">Bare Objects</h2>
<p>The secret to creating a true hash map is loosing the prototype all together and the baggage that comes with it. To do this we can take advantage of the <code class="highlighter-rouge">Object.create</code> method <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.5">introduced in ES5</a>. What’s unique about this method is that you can explicitly define the prototype for a new object. For example, defining a plain object literal with a little more verbosity:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var obj = {};
// is equivalent to:
var obj = Object.create(Object.prototype);
</pre>
</div>
<p>In addition to defining a prototype of your choosing, you can also forgo a prototype completely by passing a <code class="highlighter-rouge">null</code> value in place of a prototype object:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
map instanceof Object; // false
Object.prototype.isPrototypeOf(map); // false
Object.getPrototypeOf(map); // null
</pre>
</div>
<p>These <em>bare</em> (aka <em>dictionary</em>) objects are ideal for hash maps because the absence of a <code class="highlighter-rouge">[[Prototype]]</code> removes the risk of name conflicts. Since the object is completely void of any methods or properties, it will resist any type of coercion, attempting to do so would result in an error:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
map + ""; // TypeError: Cannot convert object to primitive value
</pre>
</div>
<p>There is no primitive value or string representation because bare objects are not intended to be used for anything other than a key-value store, plain and simple. This serves to rationalize its distinct purpose. Keep in mind that the <code class="highlighter-rouge">hasOwnProperty</code> method is also lost to the bare object, which is okay because the <code class="highlighter-rouge">in</code> operator now works without any exceptions:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
'toString' in map; // false
</pre>
</div>
<p>Better yet, those tedious <code class="highlighter-rouge">for ... in</code> loops become much simpler. We can finally write a loop the way it was meant to be:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
for (var key in map) {
// do something
}
</pre>
</div>
<p>Despite the differences, for all intents and purposes, it still behaves much like an object literal. Properties can be accessed using dot or bracket notation, the object can be stringified, and the object can still be employed as the context of a method from the <code class="highlighter-rouge">Object</code> prototype:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
Object.defineProperties(map, {
'foo': {
value: 1,
enumerable: true
},
'bar': {
value: 2,
enumerable: false
}
});
map.foo; // 1
map['bar']; // 2
JSON.stringify(map); // {"foo":1}
{}.hasOwnProperty.call(map, 'foo'); // true
{}.propertyIsEnumerable.call(map, 'bar'); // false
</pre>
</div>
<p>Even different methods of type checking will indicate what you would expect from an object literal:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">var map = Object.create(null);
typeof map; // object
{}.toString.call(map); // [object Object]
{}.valueOf.call(map); // Object {}
</pre>
</div>
<p>All this makes it simple to replace object literals with bare objects and have them integrate nicely into a pre-existing application without forcing wide spread changes.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In the context of simple key-value stores, a bare object is the clear successor to object literals, helping to alleviate the quirks with a clearly defined purpose. For more fully-featured data structures, ES6 will introduce native hash maps in the form of the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map">Map</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set">Set</a> objects, among others. Until then, or even after, you should look to bare objects for all your basic hash map needs.</p>Using an object literal as a simple means to storing key-value pairs is common place within JavaScript. However, an object literal is not a true hash map and therefore poses potential liabilities if used in the wrong manner. While JavaScript may not offer native hash maps (at least not cross-browser), there is a superior alternative to object literals to capture the desired functionality without the pitfalls.Using Mutation Observers to Watch for Element Availability2015-03-16T00:00:00+00:002015-03-16T00:00:00+00:00http://ryanmorr.com/using-mutation-observers-to-watch-for-element-availability<p>Many developers have become accustomed to using some variant of a DOM ready method to signify when they can begin to traverse and manipulate the DOM. Or, better yet, placing the scripts at the bottom of the HTML to avoid blocking render while ensuring the DOM is loaded when the JavaScript is executed. However, in this day and age of dynamic web applications, it seems like a rather antiquated approach. The DOM is not static, it is alive and subject to manipulation long after the initial page load. Simply knowing when the DOM is ready, while still useful, does not encompass the entirely of the desired functionality. Instead, how about watching for when specific elements become available throughout the course of runtime? Well, I intend to offer a solution to support exactly that kind of functionality using <a href="https://developer.mozilla.org/en/docs/Web/API/MutationObserver">mutation observers</a> as the means to a more modern approach.</p>
<h2 id="mutation-observers">Mutation Observers</h2>
<p>The <a href="http://www.w3.org/TR/dom/#mutation-observers">W3C DOM4 specification</a> initially introduced mutation observers as a replacement for the deprecated <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events">mutation events</a>. The new specification essentially permits the same functionality, but with some added benefits. Most notably is that mutation observers are asynchronous, and will invoke the callback after a batch of changes rather than every single change. This allows mutation observers to operate in a more performant manner, one of the pitfalls of mutation events, <a href="http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html">among others</a>.</p>
<p>Mutations that can be observed include the addition and removal of child nodes, changes to attributes, and updates to text nodes. For the purposes of this article, we want to focus on the addition of elements into the DOM. For this, we need to create a new instance of <code class="highlighter-rouge">MutationObserver</code> passing the callback function as the only argument. Then we invoke the <code class="highlighter-rouge">observe</code> method with the element we want to be observed and a configuration object as the first and second arguments:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
var observer = new MutationObserver(callback);
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
</pre>
</div>
<p>The <code class="highlighter-rouge">childList</code> configuration option causes the observer to monitor the DOM for any nodes added or removed from the <code class="highlighter-rouge">documentElement</code>. The <code class="highlighter-rouge">subtree</code> option will additionally allow every child node of the <code class="highlighter-rouge">documentElement</code> to be monitored for these same changes. This gives us the means to detecting element insertion anywhere in the DOM, which bodes well for our purposes. The next step is to formulate the solution.</p>
<h2 id="watching-for-desired-element-availability">Watching for Desired Element Availability</h2>
<p>The solution supports detecting element readiness on the initial page load as well as elements dynamically appended to the DOM. The code in full is as follows:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
(function(win) {
'use strict';
var listeners = [],
doc = win.document,
MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
observer;
function ready(selector, fn) {
// Store the selector and callback to be monitored
listeners.push({
selector: selector,
fn: fn
});
if (!observer) {
// Watch for changes in the document
observer = new MutationObserver(check);
observer.observe(doc.documentElement, {
childList: true,
subtree: true
});
}
// Check if the element is currently in the DOM
check();
}
function check() {
// Check the DOM for elements matching a stored selector
for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
listener = listeners[i];
// Query for elements matching the specified selector
elements = doc.querySelectorAll(listener.selector);
for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
element = elements[j];
// Make sure the callback isn't invoked with the
// same element more than once
if (!element.ready) {
element.ready = true;
// Invoke the callback with the element
listener.fn.call(element, element);
}
}
}
}
// Expose `ready`
win.ready = ready;
})(this);
</pre>
</div>
<p>The <code class="highlighter-rouge">ready</code> function accepts a selector string as the first argument and the callback function as the second. Once ready, the callback is invoked, passing the element as the only parameter:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
ready('.foo', function(element) {
// do something
});
</pre>
</div>
<p>What is important to note here is that a <code class="highlighter-rouge">ready</code> invocation is not a one-off binding. Instead, the callback lives throughout the life of the page, and is invoked any time an element matching the selector string is added to the DOM. If multiple elements matching the selector are added at once, the callback is invoked in succession for each element in document order.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This serves as a more robust and forward-thinking approach to initializing DOM traversal and manipulation than your typical DOM ready methods. Despite growing <a href="http://caniuse.com/#feat=mutationobserver">browser support for mutation observers</a>, some browsers such as IE 10 and below lack support. While it may be too early for widespread adoption, it could be a small window into the future of DOM initialization via JavaScript. View full documentation and download the source for this project on <a href="https://github.com/ryanmorr/ready">GitHub</a>.</p>Many developers have become accustomed to using some variant of a DOM ready method to signify when they can begin to traverse and manipulate the DOM. Or, better yet, placing the scripts at the bottom of the HTML to avoid blocking render while ensuring the DOM is loaded when the JavaScript is executed. However, in this day and age of dynamic web applications, it seems like a rather antiquated approach. The DOM is not static, it is alive and subject to manipulation long after the initial page load. Simply knowing when the DOM is ready, while still useful, does not encompass the entirely of the desired functionality. Instead, how about watching for when specific elements become available throughout the course of runtime? Well, I intend to offer a solution to support exactly that kind of functionality using mutation observers as the means to a more modern approach.Abstract Away the Performance Faults of querySelectorAll2014-11-12T00:00:00+00:002014-11-12T00:00:00+00:00http://ryanmorr.com/abstract-away-the-performance-faults-of-queryselectorall<p>With the introduction of the <a href="http://www.w3.org/TR/selectors-api/">Selectors API</a> in HTML5, developers finally got a native means to selecting specific nodes without the need to traverse the DOM in tedious loops. The two new methods, <code class="highlighter-rouge">querySelector</code> and <code class="highlighter-rouge">querySelectorAll</code>, facilitate this functionality by querying the DOM via CSS selector strings. However, these new methods lack the performance of their closely related functions: <code class="highlighter-rouge">getElementById</code>, <code class="highlighter-rouge">getElementsByTagName</code>, and <code class="highlighter-rouge">getElementsByClassName</code>. This paired with the fact that effective CSS design should translate into an abundance of simple selectors that could be leveraged by one of these functions, and the unnecessary performance loss becomes much more apparent. For this article, I will be discussing the performance considerations for querying the DOM and interacting with the results, and offer a simple abstraction for an all-encompassing solution.</p>
<h2 id="performance-considerations">Performance Considerations</h2>
<p>To understand why <code class="highlighter-rouge">querySelectorAll</code> is slower than <code class="highlighter-rouge">getElementsByTagName</code> and <code class="highlighter-rouge">getElementsByClassName</code>, we have to dig into the internal mechanics that govern these functions. Consequently, the functions are actually handled very differently, returning different types of node lists. Both <code class="highlighter-rouge">getElementsByTagName</code> and <code class="highlighter-rouge">getElementsByClassName</code> return a <code class="highlighter-rouge">DynamicNodeList</code>, meaning it is <em>live</em> and changes to the DOM will be automatically reflected in the collection. Conversely, <code class="highlighter-rouge">querySelectorAll</code> returns a <code class="highlighter-rouge">StaticNodeList</code> that serves as a snapshot of the DOM unaffected by changes. Static node lists must <a href="http://trac.webkit.org/browser/trunk/WebCore/dom/SelectorNodeList.cpp?rev=41093#L61">collect the matched elements up-front</a> while live node lists do not. It is these pre-computations that directly attribute to the degradation in performance of <code class="highlighter-rouge">querySelectorAll</code>.</p>
<p>It is not until a live node list is accessed, is the collection actually populated, such as using the <a href="http://trac.webkit.org/browser/trunk/WebCore/dom/DynamicNodeList.cpp?rev=41093#L57">length property</a>. In fact, this is the reason why iterating over both live and static node lists will yield the opposite performance results. Live node lists actually <a href="http://jsperf.com/getelementsbytagname-a-0-vs-queryselector-a/7">prove slower</a> than static node lists because the DOM must be checked for changes for every element retrieved from the node list via the <code class="highlighter-rouge">item</code> method or bracket notation. However, iterations of live node lists will <a href="http://jsperf.com/nodelist-vs-array-iteration">perform better if first converted to an array</a>.</p>
<p>Even <code class="highlighter-rouge">querySelector</code> in comparison to <code class="highlighter-rouge">getElementById</code> results in a <a href="http://jsperf.com/getelementbyid-vs-queryselector">considerable drop-off in performance</a>. What’s interesting is that the <code class="highlighter-rouge">querySelector</code> function does in fact map to <code class="highlighter-rouge">getElementById</code> internally if the selector string is a singular ID selector. So why the loss in performance? It turns out that even after <code class="highlighter-rouge">getElementById</code> is called, <code class="highlighter-rouge">querySelector</code> <a href="http://trac.webkit.org/browser/trunk/WebCore/dom/Node.cpp?rev=41093#L1534">continues to validate the returned element</a> to ensure that it is in fact present in the DOM, a child element of the root element, and has the ID attribute. It would seem these additional hurdles are responsible for the performance hit.</p>
<h2 id="the-solution">The Solution</h2>
<p>The solution relies on leveraging the benefits of each function for each use case. This means improving performance for both DOM queries and iterations with the returned node list.</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
function query(selector, context) {
context = context || document;
// Redirect simple selectors to the more performant function
if (/^(#?[\w-]+|\.[\w-.]+)$/.test(selector)) {
switch (selector.charAt(0)) {
case '#':
// Handle ID-based selectors
return [context.getElementById(selector.substr(1))];
case '.':
// Handle class-based selectors
// Query by multiple classes by converting the selector
// string into single spaced class names
var classes = selector.substr(1).replace(/\./g, ' ');
return [].slice.call(context.getElementsByClassName(classes));
default:
// Handle tag-based selectors
return [].slice.call(context.getElementsByTagName(selector));
}
}
// Default to `querySelectorAll`
return [].slice.call(context.querySelectorAll(selector));
}
</pre>
</div>
<p>It works by first detecting a simple selector (anything that is solely an ID, class, or tag selector), then routing the selector string to the more performant function. Anything else is handled by <code class="highlighter-rouge">querySelectorAll</code>. The context of the query can be limited by providing a DOM element as an optional second argument. All of the following invocations would be interpreted as a simple selector and thus redirected to the faster method:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
query('#foo');
query('.foo');
query('.foo.bar');
query('div');
</pre>
</div>
<p>The results are then converted into an array before returned. This not only makes the result easier to work with by making available all the methods of the <code class="highlighter-rouge">Array</code> prototype, but also makes it static for faster iterations.</p>
<p>Initial benchmarks indicate a sufficient improvement for DOM queries that are purely an <a href="http://jsperf.com/queryselectorall-vs-custom-query-method/4">ID</a>, <a href="http://jsperf.com/queryselectorall-vs-custom-query-method/5">class</a>, or <a href="http://jsperf.com/queryselectorall-vs-custom-query-method/6">tag</a> selector. In comparison to live node lists, the same <a href="http://jsperf.com/queryselectorall-vs-custom-query-method/7">performance gains are evident for iterations</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Considering the usefulness of <code class="highlighter-rouge">querySelectorAll</code>, performance should be a concern, as any critical or frequently utilized code should be. However, despite its practicality, performance isn’t the only concern. I tend to agree with John Resig, of jQuery fame, who points out some <a href="http://ejohn.org/blog/thoughts-on-queryselectorall/">flaws in the Selectors API specification</a> when it was first created. Most notably is the element-rooted queries that match elements relative to the document and than filters them out based on whether or not the contextual element is an ancestor. This is completely absurd in my opinion as it directly impacts the reliability of <code class="highlighter-rouge">querySelectorAll</code> for complicated DOM trees and/or selector strings. This is another reason to rely primarily on simple selectors (ideally classes) to target the elements you intend to. Because of this, a simple abstraction such as the one above could prove highly beneficial to performance while also offering a more intuitive API for querying the DOM. For convenience, you can find the code on <a href="https://github.com/ryanmorr/query">GitHub</a>.</p>With the introduction of the Selectors API in HTML5, developers finally got a native means to selecting specific nodes without the need to traverse the DOM in tedious loops. The two new methods, querySelector and querySelectorAll, facilitate this functionality by querying the DOM via CSS selector strings. However, these new methods lack the performance of their closely related functions: getElementById, getElementsByTagName, and getElementsByClassName. This paired with the fact that effective CSS design should translate into an abundance of simple selectors that could be leveraged by one of these functions, and the unnecessary performance loss becomes much more apparent. For this article, I will be discussing the performance considerations for querying the DOM and interacting with the results, and offer a simple abstraction for an all-encompassing solution.Project Agnostic CSS Declaration Blocks2014-08-21T00:00:00+00:002014-08-21T00:00:00+00:00http://ryanmorr.com/project-agnostic-css-declaration-blocks<p>Low specificity is key to good fundamental CSS design. Avoiding overly specific selectors and grouping similar characteristics helps to modularize your stylesheets resulting in greater portability and reusability of declaration blocks. This serves as an effective means to decoupling your CSS from your HTML. For this article, I will be focusing on some useful project agnostic declaration blocks, many of which form the basis of my CSS boilerplate given the ease in which they can be applied to any project without being too specific to any one project.</p>
<h2 id="border-box">Border Box</h2>
<p>First <a href="http://www.paulirish.com/2012/box-sizing-border-box-ftw/">brought to light</a> by Paul Irish and later <a href="http://blog.teamtreehouse.com/box-sizing-secret-simple-css-layouts#comment-50223">improved upon</a> by Jonathan Neal, the following snippet helps to improve the default box model of the browser:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
</pre>
</div>
<p>Assigning the <code class="highlighter-rouge">box-sizing</code> property to <em>border-box</em> allows the padding and border to be contained within the declared width and height of an element. This better facilitates responsive design. Percentages in particular become much more predictable and simpler to use.</p>
<p>By universally inheriting the <code class="highlighter-rouge">box-sizing</code> property from the <code class="highlighter-rouge">html</code> element, we can maintain the same result as the original code by Paul Irish while also preserving inheritance. This allows elements to acquire their box-model directory from its parent element, making it easier to change the <code class="highlighter-rouge">box-sizing</code> for plugins that use a different box-model.</p>
<h2 id="clearfix">Clearfix</h2>
<p>If your looking for the latest iteration of the <em>clearfix</em>, check out the following courtesy of <a href="http://nicolasgallagher.com/micro-clearfix-hack/">Nicolas Gallagher</a>. It helps with float-based layouts by applying the class to a container element, allowing the container to stretch to accommodate the floating elements consistently between browsers:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.clearfix:before,
.clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
</pre>
</div>
<p>The value of <em>table</em> rather than <em>block</em> for the <code class="highlighter-rouge">display</code> property is necessary to prevent top-margin collapse of child elements when utilizing the <code class="highlighter-rouge">:before</code> pseudo-element. The <code class="highlighter-rouge">:after</code> pseudo-element is used to clear the floats. Additionally, it’s worth noting that the empty space assigned to the <code class="highlighter-rouge">content</code> property is not a typo and is instead required to resolve a bug associated with Opera.</p>
<h2 id="positioning">Positioning</h2>
<p>The next few declaration blocks are fairly common classes used to aid in design by providing an easy means to positioning elements, helping to align them left, right, and center:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.pull-right {
float: right !important;
}
.pull-left {
float: left !important;
}
.center-x {
display: block;
margin-right: auto;
margin-left: auto;
}
.center-xy {
margin: 0 auto;
display: table;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
</pre>
</div>
<p>The <code class="highlighter-rouge">center-xy</code> class in particular is a clever solution to center elements not just horizontally, but also vertically. This is a solution many developers have desired for quite some time now. Kudos to <a href="http://creative-punch.net/2014/01/center-vertically-horizontally-using-css3-transform/">Creative Punch</a> for its discovery.</p>
<h2 id="visibility">Visibility</h2>
<p>These helper classes, derived from the <a href="https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css#L116">HTML5 Boilerplate</a>, assist in managing visibility to both users and screen readers, while also offering an easy means to controlling visibility programmatically:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.show {
display: block !important;
}
.hide {
display: none !important;
visibility: hidden !important;
}
.invisible {
visibility: hidden;
}
.hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
</pre>
</div>
<p>The <code class="highlighter-rouge">hidden-accessible</code> class has the unique ability to mimic the effects of <code class="highlighter-rouge">display: none</code>, yet still be accessible to screen readers and web crawlers.</p>
<h2 id="disabling-elements">Disabling Elements</h2>
<p>The following declaration block sets the cursor to default, restricts mouse events, and fades the element into the background as a means of universally disabling anything from form fields to links to widgets in a consistent manner:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.disabled,
:disabled,
[disabled] {
cursor: default !important;
opacity: 0.6;
pointer-events: none;
-moz-user-input: disabled;
user-input: disabled;
-moz-user-focus: ignore;
user-focus: ignore;
}
</pre>
</div>
<p>The <code class="highlighter-rouge">user-input</code> property is used to restrict user input into a field, while the <code class="highlighter-rouge">user-focus</code> property is used to restrain keyboard focus, skipping the element in the tab order. However, both properties do not possess wide-spread browser support (currently only supported in Firefox) and are still just proposals for inclusion to the specification.</p>
<h2 id="image-replacement">Image Replacement</h2>
<p>The image replacement technique is used to visually hide descriptive text in favor of an image. This essentially allows you to provide a caption to an image available only to screen readers and web crawlers for better SEO:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.hide-text {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
</pre>
</div>
<p>The original technique set the <code class="highlighter-rouge">text-indent</code> property to -9999px in order to place the text well outside the viewport. However, the problem with this method was a performance hit caused by the browser drawing a giant 9999 pixel box off-screen.</p>
<p>The new technique discovered by <a href="http://scottkellum.com/">Scott Kellum</a> and first written about at <a href="http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/">Zeldman.com</a> addresses the performance issue. Instead, the text is simply indented beyond the width of its container, prevented from wrapping, and hides any overflow.</p>
<h2 id="responsive-images">Responsive Images</h2>
<p>This class borrowed from <a href="https://github.com/twbs/bootstrap/blob/master/dist/css/bootstrap.css#L932">Bootstrap</a> can make images responsive. This is ideal for mobile-friendly websites, allowing images to scale to fit its container element while still maintaining its aspect ratio:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.img-responsive {
display: block;
max-width: 100%;
height: auto;
}
</pre>
</div>
<p>The key to this class is setting the <code class="highlighter-rouge">max-width</code> property to <em>100%</em>. It allows the image to scale while also ensuring it does not scale larger than its original dimensions, preventing a reduction in the image’s quality.</p>
<h2 id="transitions">Transitions</h2>
<p>Now that CSS3 transitions are widely supported across browsers, we can move simple animations from JavaScript to CSS where they belong. The following class provides an easy means to making any element completely animated by altering its properties in CSS or JavaScript:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.transition {
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
</pre>
</div>
<p>You can also use these helper classes adapted from <a href="https://github.com/twbs/bootstrap/blob/master/dist/css/bootstrap.css#L3170">Bootstrap</a> for easy fading and collapsing/expanding of elements:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.fade {
opacity: 0;
-webkit-transition: opacity 0.15s linear;
transition: opacity 0.15s linear;
}
.fade.in {
opacity: 1;
}
.collapsing {
position: relative;
height: 0;
overflow: hidden;
-webkit-transition: height 0.35s ease;
transition: height 0.35s ease;
}
</pre>
</div>
<p>If your looking for a more comprehensive solution, you can check out <a href="https://github.com/daneden/animate.css">animate.css</a> which provides animations for just about everything you can think of.</p>
<h2 id="targeting-devices">Targeting Devices</h2>
<p>Another set of declaration blocks adopted from <a href="https://github.com/twbs/bootstrap/blob/master/dist/css/bootstrap.css#L6116">Bootstrap</a>, these classes and media queries help to hide and show certain elements targeted at phones, tablets, and desktops:</p>
<div class="code-block">
<pre class="prettyprint lang-css">
.visible-phone,
.visible-tablet,
.visible-desktop {
display: none !important;
}
.hidden-phone,
.hidden-tablet,
.hidden-desktop {
display: block !important;
}
/* Phones */
@media screen and (max-width: 37.5em) {
.visible-phone {
display: block !important;
}
.visible-desktop,
.visible-tablet,
.hidden-phone {
display: none !important;
}
}
/* Tablets */
@media screen and (min-width: 37.5em) and (max-width: 64em) {
.visible-tablet {
display: block !important;
}
.visible-desktop,
.visible-phone,
.hidden-tablet {
display: none !important;
}
}
/* Desktops */
@media screen and (min-width: 64em) {
.visible-desktop {
display: block !important;
}
.visible-phone,
.visible-tablet,
.hidden-desktop {
display: none !important;
}
}
</pre>
</div>
<p>I use <em>ems</em> for the breakpoints to <a href="http://blog.cloudfour.com/the-ems-have-it-proportional-media-queries-ftw/">better manage user zoom level</a> and prevent any awkwardly wrapped elements or other rendering issues. Exactly what you set your breakpoints to may depend on your project and supported devices.</p>
<h2 id="conclusion">Conclusion</h2>
<p>There you have it, a bunch of different helper classes and declaration blocks for a wide variety of purposes. This combined with some variant of a <a href="http://www.cssreset.com/">CSS reset</a> for a consistent baseline and a responsive grid system for easy layout scaffolding, you will have a good starting point for any new project.</p>Low specificity is key to good fundamental CSS design. Avoiding overly specific selectors and grouping similar characteristics helps to modularize your stylesheets resulting in greater portability and reusability of declaration blocks. This serves as an effective means to decoupling your CSS from your HTML. For this article, I will be focusing on some useful project agnostic declaration blocks, many of which form the basis of my CSS boilerplate given the ease in which they can be applied to any project without being too specific to any one project.Maintain Responsiveness by Capturing Unbound Action Events2014-05-16T00:00:00+00:002014-05-16T00:00:00+00:00http://ryanmorr.com/maintain-responsiveness-by-capturing-unbound-action-events<p>Responsiveness is critical for modern client-side applications. When a user clicks on something, they expect a result and some are not too keen on waiting. At the very least, a user’s actions should be acknowledged via a loading indicator or the like. The absolute worse case scenario is having nothing happen at all. This is often the case pre-initialization. The user interacts with a component without any effect or even error message because, unbeknownst to the user, the page is still in the process of initialization and event handlers had yet to be bound to their correlative elements. It’s an issue I have encountered on numerous occasions. A less technically inclined user may assume the site is broken, that makes for a bad first impression. For this article, I will be exploring a solution to this problem by way of capturing user triggered action events pre-initialization to maintain responsiveness.</p>
<h2 id="the-concept">The Concept</h2>
<p>Typically, progressive enhancement is the obvious answer to this problem and should still be instituted as a bulletproof fallback. However, if you wish to serve a highly dynamic application and want to limit page reloads or avoid them all together, than it may not be the ideal solution.</p>
<p>Progressive enhancement aside, there are two viable approaches you can take to resolve the problem. You could present the user with a loading mask until initialization has completed to inhibit interaction with the interface, such is the case with GMail. Or you can capture the action events, such as clicks and form submissions. The latter can be achieved by utilizing event delegation to listen for user triggered events that bubble up to the document element. This way the event can be handled immediately or queued for processing once the page has finished initializing while still acknowledging the user’s actions. All that is required is a means of distinguishing between events that should be intercepted by JavaScript and those that should not. It wouldn’t be to practical to prevent a hyperlink from following the link that otherwise shouldn’t be interrupted.</p>
<h2 id="introducing-actionoberver">Introducing ActionOberver</h2>
<p>The following solution, I’ve dubbed <code class="highlighter-rouge">ActionObserver</code>, observes click events and form submissions to capture user interactions. It is a simplified solution that could be easily expanded to include support for key events to detect user keystrokes, touch events to detect interactivity, or scroll events to handle dynamic progressive loading. The code in its most basic form looks like the following:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
(function(win){
'use strict';
var ActionObserver = {},
docElement = win.document.documentElement,
listeners = {};
// Listen for action events on the document when they bubble up
docElement.addEventListener('click', onEvent, false);
docElement.addEventListener('submit', onEvent, false);
// Handle action events (click, submit) on the document
function onEvent(e){
// Find the first ancestor element of the event target
// containing the data-observe attribute
var el = e.target.closest('[data-observe]'), key;
if(el){
if(el.nodeName.toLowerCase() === 'form' && e.type !== 'submit'){
return;
}
// Get the value of the data-observe attribute
// to find the callback function and invoke it
key = el.getAttribute('data-observe');
if(listeners.hasOwnProperty(key)){
listeners[key](e, el);
}
}
}
// Map a callback function to the element in
// which you would like to observe action events on
ActionObserver.bind = function(key, fn, ctx){
listeners[key] = fn.bind(ctx || win);
};
win.ActionObserver = ActionObserver;
})(this);
</pre>
</div>
<p>Browser support is good as well, only IE 8 and less does not support the bubbling of submit events to the document and therefore cannot be detected and captured.</p>
<h2 id="usage">Usage</h2>
<p>To start, add a <code class="highlighter-rouge">data-observe</code> attribute to any element on which you want to listen for action events. This helps to differentiate which events should be intercepted by <code class="highlighter-rouge">ActionObserver</code> and which should not. For example:</p>
<div class="code-block">
<pre class="prettyprint lang-html">
<!--Observe click events-->
<a href="#" data-observe="add">Add Item</a>
<!--Observe submit events-->
<form method="GET" action="#" data-observe="search">
<input type="search" name="search" />
<button type="submit">Submit</button>
</form>
</pre>
</div>
<p>Adding the <code class="highlighter-rouge">data-observe</code> attribute to a form will automatically capture submit events for that form. Adding the <code class="highlighter-rouge">data-observe</code> attribute to any other type of element will automatically observe click events.</p>
<p>The value of the <code class="highlighter-rouge">data-observe</code> attribute is the reference point in JavaScript to that element. Use the <code class="highlighter-rouge">ActionObserver.bind</code> method to attach a callback function that will be invoked when an action event is dispatched from the source element, passing the event object and the element as arguments:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
ActionObserver.bind('add', function(event, element){
// Process or queue request
});
ActionObserver.bind('search', function(event, element){
// Process or queue request
});
</pre>
</div>
<p>Ideally, you should inline the code in the head of the document for JavaScript rich applications. This will block rendering, but you can avoid the extra HTTP request and get instant notification of user requests before the DOM has finished loading or scripts have finished initializing. So it’s a bit of a trade-off. Check out the project on <a href="https://github.com/ryanmorr/action-observer">GitHub</a> for more information and the latest version of the code.</p>
<h2 id="lazy-loading--instantiation">Lazy Loading & Instantiation</h2>
<p>This solution is ideal for lazy loading and instantiation of components that are not immediately required for page load. If your a proponent of asynchronous module loading, you could use RequireJS to load the dependencies of a component once it is requested by the user. Take for instance the following:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
ActionObserver.bind('search', function(event, element){
require(['search', 'text!search.tpl'], function(search, template){
// Initialize component and process request
});
});
</pre>
</div>
<p>This approach allows you to limit the amount of HTTP requests for the initial page load to the bare essentials. Only when specific functionality is requested by the user via their interactions is the required resources automatically loaded and initialized.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Employing this technique allows you to place all your JavaScript at the bottom of the page to leverage increased rendering time and usability (specifically for above the fold content) without sacrificing responsiveness for JavaScript-based functionality. This makes for a user experience that is unobtrusive, consistent, but most importantly, responsive.</p>Responsiveness is critical for modern client-side applications. When a user clicks on something, they expect a result and some are not too keen on waiting. At the very least, a user’s actions should be acknowledged via a loading indicator or the like. The absolute worse case scenario is having nothing happen at all. This is often the case pre-initialization. The user interacts with a component without any effect or even error message because, unbeknownst to the user, the page is still in the process of initialization and event handlers had yet to be bound to their correlative elements. It’s an issue I have encountered on numerous occasions. A less technically inclined user may assume the site is broken, that makes for a bad first impression. For this article, I will be exploring a solution to this problem by way of capturing user triggered action events pre-initialization to maintain responsiveness.The State of Browser Detection2014-03-31T00:00:00+00:002014-03-31T00:00:00+00:00http://ryanmorr.com/the-state-of-browser-detection<p>Despite the progress client-side scripting has made in the last decade or so, it seems some bad practices are poised to never die. With the medium transitioning into a more mobile-centric world in recent years, an influx in bugs has many turning back to browser detection for a solution. History seems to repeat itself in this regard. It has long been my contention that browser detection should not and can not be relied upon. However, the validity of the use case has become difficult to dismiss, and the lack of an alternative leaves me with no other options and more than a little conflicted. For this article, I will be discussing the various facets of browser detection and offer some recommendations to maximize reliability.</p>
<h2 id="a-brief-overview">A Brief Overview</h2>
<p>Browser detection is the practice of attempting to identify the web browser a visitor is using. It’s purpose is to either impose or restrict execution of certain fragments of code to a particular browser in an effort to circumvent incompatibilities or leverage features associated with that specific browser. This exercise is not only restricted to the browser vendor, but also the version, operating system, rendering engine, and device.</p>
<p>There are two predominant approaches to browser detection. The most common method is by way of <em>user-agent sniffing</em>. This describes the parsing of the user-agent string contained in the <code class="highlighter-rouge">navigator.userAgent</code> property to extract the relevant browser data.</p>
<p>The other approach is in the form of <em>browser inference</em>, which is the identification of a particular browser or version based on the presence or absence of one or more unique objects. A common example of this would be inferring Internet Explorer based on the existence of the <code class="highlighter-rouge">ActiveXObject</code> object.</p>
<h2 id="early-history-of-browser-detection">Early History of Browser Detection</h2>
<p>Early on as JavaScript began to gain traction, it found itself torn between competing browsers. As a result, implementations featured notable inconsistencies, various bugs and quirks, and fickle web standards compliance. Many developers found themselves resorting to browser detection to help abstract away the incompatibilities. At the time, it was viewed as a justified solution to obtain cross-browser compatibility. However, at some point along the way, the practice became abused, quickly becoming common routine rather than a last resort, finding its way into scripts where simple object detection would suffice. JavaScript libraries would unnecessarily incorporate browser detection, adding a certain air of credibility to it. This all hindered the Web from progressing as fast as it could have, contributing in part to the long and overdue lifespan of IE6.</p>
<h2 id="assumptions-can-be-dangerous">Assumptions can be Dangerous</h2>
<p>Before I concede to browser detection, I would first like to remind or enlighten those less familiar as to why it is untrustworthy. The fundamental problem with browser detection is in its presumptuous nature. It’s a static identifier operating in an environment that is constantly evolving. Both the browser detect itself and the features/bugs associated with each browser are only as reliable as your knowledge of the browser environments you currently support at the time of implementation. This essentially boils down to nothing more than assumptions about every browser of every user that visits a page, and assuming the relationships between features/bugs and the associated browsers are correct affiliations. As the technology continues to evolve and new browsers and browser versions released, applications depending on browser detection will become fragile implementations at the mercy of the progression.</p>
<p>Additionally, user-agent sniffing poses an entirely new challenge in the form of <em>browser spoofing</em>. This is the practice of one browser attempting to <a href="http://webaim.org/blog/user-agent-string-history/">imitate another by polluting the user-agent string</a> with keywords that hint at the existence of different browser vendors, rendering engines, and operating systems. Add to this the fact that the user-agent string can be manipulated, with or without the user’s knowledge, and it becomes increasingly clear how unreliable this technique truly is. In essence, it amounts to nothing more than a best guess.</p>
<h2 id="feature-testing-is-the-answer">Feature Testing is the Answer</h2>
<p>There is no question that <em>feature testing</em> is the preferred means of detecting bugs and supported functionality of the browser, that debate was settled a long time ago. It is the logical concept of testing for the existence, and in some respects, the functionality of a feature before utilizing it in some capacity. It relies on what it knows about the browser environment during runtime rather than the assumed associations at the time of implementation. jQuery came to the same conclusion, <a href="http://blog.jquery.com/2009/01/14/jquery-1-3-released/">dropping browser detection</a> from the core library in favor of feature testing, finally acknowledging it as the more reliable approach. Given the possibility to form a meaningful test case, feature testing is the obvious answer. Of course this bears the question, what if there is no applicable feature test available? What if the feature/bug is undetectable?</p>
<h2 id="undetectables">Undetectables</h2>
<p>This is an instance of a bug beyond the scope of JavaScript, meaning the formation of any competent test case would be infeasible. The bug is simply undetectable, leaving only browser detection to single out the affected browsers. This forms the basis for the validity of the use case for browser detection, which speaks to its prevalence in scripts to this day.</p>
<p>This isn’t exactly a new problem, however, it does seem to be a growing problem since the emergence of mobile browsers. There are numerous <a href="https://github.com/Modernizr/Modernizr/wiki/Undetectables">undetectable bugs and quirks</a> to speak of. Perhaps the most notable due to its sheer usefulness in modern day web applications is fixed positioning. Its issues are <a href="http://remysharp.com/2012/05/24/issues-with-position-fixed-scrolling-on-ios/">well</a> <a href="http://bradfrostweb.com/blog/mobile/fixed-position/">documented</a> on both iOS and Android. The <a href="https://github.com/jquery/jquery-mobile/blob/f6d4e37fb22f9d5c7393b4ee98eb9ca1c836ebcf/js/support.js#L143-L173">browser detect required for determining fixed positioning support</a> is complicated to say the least, which speaks to the extent of the problem. It seems to be the nature of mobile development at this time, much like it was when desktop browsers were still in their infancy. At least the rationale for browser detection is of greater merit today than it was a decade ago.</p>
<h2 id="strengthening-browser-detection">Strengthening Browser Detection</h2>
<p>First and foremost, browser detection should always be a last resort. However, if it is your only option, you can employ the technique more safely, provided you take the proper steps to help mitigate the inherent risks in reliability.</p>
<p>One such step would be to employ a more direct form of browser inference. Rather than rely on an unrelated object, why not use a more relevant object to infer the browser, one that implies details about a specific user-agent. For example, using vendor prefixes to infer the rendering engine or other proprietary objects whose names hint at the vendor they belong to:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
if('chrome' in window){
// detect Chrome
}
if('opera' in window && ({}).toString.call(window.opera) === '[object Opera]'){
// detect Opera 14-
}
if('PalmSystem' in window){
// detect webOS
}
if('blackberry' in window){
// detect blackberry
}
if('MozAppearance' in document.documentElement.style){
// detect Mozilla
}
if('WebkitAppearance' in document.documentElement.style){
// detect WebKit
}
</pre>
</div>
<p>This serves as a much more straightforward means of identifying the browser. It is still an assumption, but it’s one I’m willing to depend on. I don’t necessarily see this as a replacement for user-agent sniffing, however, if utilized conjointly, it can help to fortify the detection process and reduce, if not eliminate, false positives and false negatives.</p>
<p>Additionally, <a href="http://msdn.microsoft.com/en-us/library/ms537512.ASPX">conditional comments</a> have long proved to be a reliable means of detecting Internet Explorer and different versions of IE. There is also the <a href="https://gist.github.com/scottjehl/358029">JavaScript equivalent</a> available, all but eliminating the requirement to sniff out old IE via user-agent sniffing or browser inference. Unfortunately, <a href="http://msdn.microsoft.com/en-us/library/ie/hh801214(v=vs.85).aspx">IE10 and later have dropped support for conditional comments</a>, which means you may be forced to turn back to the aforementioned and less desirable methods.</p>
<h2 id="optimal-implementation">Optimal Implementation</h2>
<p>Aside from the code that makes up the browser detect itself, how you implement it can be equally critical to reliability. Ideally, features should be employed in a fashion that does not inhibit the user’s experience in the event that the depending browser detect fails. This begins by adopting one of two fail-safe strategies; <em>progressive enhancement</em> or <em>graceful degradation</em>. Both concepts help to make a web site accessible to any browser, while providing improved aesthetics and/or usability for more capable browsers.</p>
<p>The difference between the two is in the approach. Progressive enhancement entails development in layers, using a bottom-up approach. Starting with a cross-browser base layer, features are added in successive layers to enhance the web site. Graceful degradation uses a top-down approach in which features are implemented with a fallback solution for nonsupporting browsers. Both strategies help to ensure a functional and legible site even under the worst case scenario, establishing a high level of consistency.</p>
<p>Be precise and target the specific version of a specific browser. Narrow the scope of your detection to the exact browsers you know are comprised of the feature/bug you are attempting to account for. This helps avert a wide reaching browser detect that is likely to break in the future. Also be sure to avoid browser detects based on assumptions about non-existent future versions of a browser. Instead, work off of what you know at the time and don’t try to guess the future. If the current version of a particular browser has a bug, do not assume that bug will be present in the next version. This serves to future proof your code.</p>
<h2 id="conclusion">Conclusion</h2>
<p>To put it bluntly, I suspect browser detection is here to stay. Bugs are inevitable, it is the nature of software. Unexpected defects and quirks will always necessitate the demand to identify specific browsers when feature testing is not applicable. The use case is valid. What needs to change is the method in which the browser is identified. At present, developers are forced to contend with the overly convoluted user-agent string that insists on misrepresenting itself. This makes for an unreliable technique to hinge critical functionality on. Regardless of how it is employed, if the browser detect is, in of itself, untrustworthy, than it’s a flawed approach. Yet, without a comparable alternative, developers have no where else to turn. This leaves two options; avoid the broken features completely or use browser detection. Not exactly an ideal position anyway you approach it. We need something better!</p>Despite the progress client-side scripting has made in the last decade or so, it seems some bad practices are poised to never die. With the medium transitioning into a more mobile-centric world in recent years, an influx in bugs has many turning back to browser detection for a solution. History seems to repeat itself in this regard. It has long been my contention that browser detection should not and can not be relied upon. However, the validity of the use case has become difficult to dismiss, and the lack of an alternative leaves me with no other options and more than a little conflicted. For this article, I will be discussing the various facets of browser detection and offer some recommendations to maximize reliability.Feature Testing CSS At-Rules2014-01-31T00:00:00+00:002014-01-31T00:00:00+00:00http://ryanmorr.com/feature-testing-css-at-rules<p>The <em>CSS Object Model (CSSOM)</em> is a <a href="http://dev.w3.org/csswg/cssom/">W3C specification</a> that defines APIs for CSS in JavaScript, encompassing all of what CSS has to offer. This has provided JavaScript a new window into CSS and all of its supported features that was not previously available. This bodes well for feature testing. This article will be specifically addressing the detection of at-rules and how we can leverage them in supported browsers while still providing a fallback solution for those that don’t.</p>
<h2 id="the-cssrule-interface">The CSSRule Interface</h2>
<p>Included in the CSSOM is the <code class="highlighter-rouge">CSSRule</code> <a href="https://developer.mozilla.org/en-US/docs/Web/API/CSSRule">interface</a> which represents a single CSS at-rule. It acts as a high level abstraction for every type of CSS rule (charset, media, font-face, etc.), defining methods and properties common to all rule interfaces.</p>
<p>Among the properties is a set of static <a href="http://wiki.csswg.org/spec/cssom-constants#cssom-constants">type constants</a> that corresponds with the more specialized interface specific to each type of rule. A rule instance’s type is contained in the <code class="highlighter-rouge">type</code> property that returns the associated type constant. These constants are what make feature testing rule support possible.</p>
<h2 id="feature-testing-at-rules">Feature Testing At-Rules</h2>
<p>To detect support for an at-rule, checking the existence of the associated type constant is all that is required. This infers the existence of the corresponding interface and therefore functionality. For example:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
// Is the @keyframes rule supported?
if('KEYFRAMES_RULE' in window.CSSRule){
// Do something
}
// Is the @font-face rule supported?
if('FONT_FACE_RULE' in window.CSSRule){
// Do something
}
// Is the @supports rule supported? (oh the irony)
if('SUPPORTS_RULE' in window.CSSRule){
// Do something
}
</pre>
</div>
<p>Unfortunately, like everything else, this approach does not escape the dark cloud of vendor prefixes. This means you will have to expand the detection process to account for that as well:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
if('KEYFRAMES_RULE' in window.CSSRule ||
'MOZ_KEYFRAMES_RULE' in window.CSSRule ||
'WEBKIT_KEYFRAMES_RULE' in window.CSSRule){
// Do something
}
</pre>
</div>
<p>An alternative approach would be to check for the existence of the rule specific interfaces themselves in the global object:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
// Does the keyframe interface exist?
if('CSSKeyframesRule' in window){
// Do something
}
</pre>
</div>
<p>It’s merely a matter of preference, both techniques are equally valid and will still require vendor prefixes when necessary.</p>
<p>The fact that the CSSOM is standardized bodes well for cross-browser consistency. As of today, all major browsers, with the exception of IE8 and less, support the CSS object model including the <code class="highlighter-rouge">CSSRule</code> interface and the type constants.</p>
<h2 id="a-complete-solution">A Complete Solution</h2>
<p>We can simplify this approach even further by wrapping the solution in a function and offer a more usable API that doesn’t require the vendor prefixes or a pre-existing knowledge of the CSSOM. The code is as follows:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
function isAtRuleSupported(rule) {
var support = false;
// Create an array of vendor prefixes
var prefixes = ['MOZ_', 'WEBKIT_', 'O_', 'MS_', ''], length = prefixes.length;
// Convert the rule to a form compatible with the `CSSRule` type constants
rule = rule.replace(/^@/, '').toUpperCase().split('-').join('_') + '_RULE';
while (!support && length--) {
// Starting with the unprefixed version, iterate over all the vendor
// prefixes to determine browser support
support = (prefixes[length] + rule) in window.CSSRule;
}
return support;
}
</pre>
</div>
<p>Usage is fairly straightforward, invoking <code class="highlighter-rouge">isAtRuleSupported</code> with only a string of the rule name in standard CSS notation.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Like most feature detects these days, this solution is about trying to employ new features where they are supported while still providing an alternative solution for non-supporting browsers to create a seamless experience. Progressive enhancement at its finest. You can find the latest version of this code on <a href="https://github.com/ryanmorr/is-at-rule-supported">GitHub</a>.</p>The CSS Object Model (CSSOM) is a W3C specification that defines APIs for CSS in JavaScript, encompassing all of what CSS has to offer. This has provided JavaScript a new window into CSS and all of its supported features that was not previously available. This bodes well for feature testing. This article will be specifically addressing the detection of at-rules and how we can leverage them in supported browsers while still providing a fallback solution for those that don’t.Exploring the Eternal Abyss of Null and Undefined2013-11-24T00:00:00+00:002013-11-24T00:00:00+00:00http://ryanmorr.com/exploring-the-eternal-abyss-of-null-and-undefined<p>When discussing primitive data types in JavaScript, most are aware of the basics, starting with <em>String</em>, <em>Number</em>, and <em>Boolean</em>. These primitives are fairly straightforward and function as you might expect. This article, however, will be focusing on the more unique primitive data types known as <em>Null</em> and <em>Undefined</em>; what makes them similar, dissimilar, and overall unusual.</p>
<h2 id="understanding-null-and-undefined">Understanding Null and Undefined</h2>
<p>In JavaScript, <code class="highlighter-rouge">null</code> is a literal and language keyword that represents no discernible object value. In other words, it’s an indication of “no value”. While similar, <code class="highlighter-rouge">undefined</code> actually represents the non-existence of a value. Both are completely immutable, have no properties or methods, and are incapable of property assignment. In fact, attempting to access or define a property will raise a <code class="highlighter-rouge">TypeError</code>. They are, as their names suggest, completely void of value.</p>
<p>The absence of value lends to their characterization as <em>falsy</em> values, meaning they evaluate to false when employed in the context of a conditional, such as an <code class="highlighter-rouge">if</code> statement. Comparing the two with other falsy values using an <em>equality operator</em> (==) reveals that they are not equal to anything except themselves:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
null == 0; // false
undefined == ""; // false
null == false; // false
undefined == false; // false
null == undefined; // true
</pre>
</div>
<p>Despite this and the other similarities, <code class="highlighter-rouge">null</code> and <code class="highlighter-rouge">undefined</code> are not equivalent. Each serve as the sole member of its own distinct type; <code class="highlighter-rouge">undefined</code> is of type <em>Undefined</em> and <code class="highlighter-rouge">null</code> is of type <em>Null</em>. Comparing the two with a <em>strict equality operator</em> (===), which equates both value and type, is enough to prove that:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
undefined === null; // false
</pre>
</div>
<p>This is an important distinction, both serve different purposes and justifiably so. To distinguish between the two, you may want to think of <code class="highlighter-rouge">undefined</code> as representing an unexpected absence of value and <code class="highlighter-rouge">null</code> as representing an expected absence of value.</p>
<h2 id="yielding-undefined">Yielding Undefined</h2>
<p>There are a number of ways of yielding an <code class="highlighter-rouge">undefined</code> value in code. It is typically encountered when attempting to access a value where no value exists. In this case, JavaScript, being the dynamic and weakly-typed language it is, will merely default to an <code class="highlighter-rouge">undefined</code> value rather than raise an error.</p>
<p>Any declared variable that has not been provided an initial value will have a default value of <code class="highlighter-rouge">undefined</code>:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
var foo; // defaults to undefined
</pre>
</div>
<p>An <code class="highlighter-rouge">undefined</code> value is issued when attempting to access an object property or an array item that does not exist:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
var array = [1, 2, 3];
var foo = array.foo; // foo property doesn't exist, returns undefined
var item = array[5]; // no item exists in the array at index 5, returns undefined
</pre>
</div>
<p>If a return statement is omitted from a function, <code class="highlighter-rouge">undefined</code> is returned instead:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
var value = (function(){})(); // returns undefined
</pre>
</div>
<p>An argument not supplied to a function invocation will result in an <code class="highlighter-rouge">undefined</code> parameter:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
(function(undefined){
// parameter is undefined
})();
</pre>
</div>
<p>The <code class="highlighter-rouge">void</code> operator can also be used to return an <code class="highlighter-rouge">undefined</code> value. Libraries such as <a href="https://github.com/jashkenas/underscore/blob/master/underscore.js#L1253-L1256">Underscore</a> employ it as a bulletproof means of type checking because it is immutable and can be relied upon to return <code class="highlighter-rouge">undefined</code> in any context:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
function isUndefined(obj){
return obj === void 0;
}
</pre>
</div>
<p>Lastly, <code class="highlighter-rouge">undefined</code> is a predefined global variable (not a keyword like <code class="highlighter-rouge">null</code>) that is initialized to the <code class="highlighter-rouge">undefined</code> value:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
'undefined' in window; // true
</pre>
</div>
<p>As of ECMAScript 5, this variable is <a href="http://es5.github.io/#x15.1.1.3">read-only</a> which was not the case previously.</p>
<h2 id="the-use-case-for-null">The Use Case for Null</h2>
<p>The use case for <code class="highlighter-rouge">null</code> is the primary aspect that sets it apart, because unlike <code class="highlighter-rouge">undefined</code>, <code class="highlighter-rouge">null</code> is regarded as more of an assignment value. This is precisely why the <code class="highlighter-rouge">typeof</code> operator returns <em>“object”</em> when employed in conjunction with a <code class="highlighter-rouge">null</code> value. The original rationale for this is that <code class="highlighter-rouge">null</code> was, and still is, commonly used as an empty reference where an object is expected, much like a placeholder. This behaviour associated with <code class="highlighter-rouge">typeof</code> has since been identified as a bug, and although a correction has been <a href="http://wiki.ecmascript.org/doku.php?id=proposals:typeof">proposed</a>, to this point it has been left unchanged for the purposes of backwards compatibility.</p>
<p>This use case is why the JavaScript environment never sets a value to <code class="highlighter-rouge">null</code>, it must be done programmatically. As the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null">documentation on MDN</a> puts it:</p>
<blockquote>
<p>In APIs, <code class="highlighter-rouge">null</code> is often retrieved in place where an object can be expected but no object is relevant.</p>
</blockquote>
<p>This is true for the DOM, which is language-independent and does not fall within the scope of the ECMAScript specification. Because it is an external API, attempting to retrieve a non-existent element returns a <code class="highlighter-rouge">null</code> value rather than <code class="highlighter-rouge">undefined</code>.</p>
<p>Generally, if you need to assign a non-value to a variable or property, pass it to a function, or return it from a function, <code class="highlighter-rouge">null</code> is almost always the best option. To put it simply, JavaScript uses <code class="highlighter-rouge">undefined</code> and programmers <strong>should</strong> use <code class="highlighter-rouge">null</code>.</p>
<p>Another viable use case for <code class="highlighter-rouge">null</code> that is also considered good practice is an explicit variable nullification (<code class="highlighter-rouge">object = null</code>) when a reference is no longer required. By assigning a <code class="highlighter-rouge">null</code> value, you are effectively purging the reference, and assuming the object is not referenced elsewhere in code, designating it for garbage collection, thus reclaiming memory.</p>
<h2 id="digging-deeper">Digging Deeper</h2>
<p>What makes <code class="highlighter-rouge">null</code> and <code class="highlighter-rouge">undefined</code> such black holes is not just in their behaviour, but also in the manner in which they are handled internally to the JavaScript environment. They do not seem to possess the same characteristics typically associated with other primitives or built-in objects.</p>
<p>As of ES5, the <code class="highlighter-rouge">Object.prototype.toString</code> method, which has become the de-facto standard for type checking, proves to be consistent in this regard for both <code class="highlighter-rouge">null</code> and <code class="highlighter-rouge">undefined</code>:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(undefined); // [object Undefined]
</pre>
</div>
<p>However, the <code class="highlighter-rouge">Object.prototype.toString</code> method is not actually retrieving the internal <code class="highlighter-rouge">[[Class]]</code> property of <code class="highlighter-rouge">null</code> or <code class="highlighter-rouge">undefined</code> to expose the constructors. According to the <a href="http://es5.github.io/#x15.2.4.2">specification</a>, the following steps are taken upon invocation:</p>
<blockquote>
<ol>
<li>If the this value is <code class="highlighter-rouge">undefined</code>, return <code class="highlighter-rouge">"[object Undefined]"</code>.</li>
<li>If the this value is <code class="highlighter-rouge">null</code>, return <code class="highlighter-rouge">"[object Null]"</code>.</li>
<li>Let O be the result of calling ToObject passing the this value as the argument.</li>
<li>Let class be the value of the [[Class]] internal property of O.</li>
<li>Return the String value that is the result of concatenating the three Strings <code class="highlighter-rouge">"[object "</code>, class, and <code class="highlighter-rouge">"]"</code>.</li>
</ol>
</blockquote>
<p>The method performs a simple string return if it detects <code class="highlighter-rouge">null</code> or <code class="highlighter-rouge">undefined</code> merely to uniform functionality with other objects. This is common throughout the specification, as most methods contain a simple catch and return when they encounter <code class="highlighter-rouge">null</code> and <code class="highlighter-rouge">undefined</code> values. In fact, there is no indication that they even contain any of the <a href="http://es5.github.io/#x8.6.2">internal properties</a> typically associated with every native object. It is as if they are not objects at all? I’m curious to know if an explicit programmatic definition actually exists internally to the JavaScript environment for either primitive? Perhaps someone more familiar with an implementation could weigh in.</p>
<h2 id="conclusion">Conclusion</h2>
<p>No matter how unusual these primitives appear to be, understanding <code class="highlighter-rouge">null</code> and <code class="highlighter-rouge">undefined</code>; the difference between them, and their distinct roles in JavaScript are fundamental to the language. It may not exactly make or break your application, however generally speaking, it can only prove beneficial in the long run for both development and debugging.</p>When discussing primitive data types in JavaScript, most are aware of the basics, starting with String, Number, and Boolean. These primitives are fairly straightforward and function as you might expect. This article, however, will be focusing on the more unique primitive data types known as Null and Undefined; what makes them similar, dissimilar, and overall unusual.Determine HTML5 Element Support in JavaScript2013-10-10T00:00:00+00:002013-10-10T00:00:00+00:00http://ryanmorr.com/determine-html5-element-support-in-javascript<p>The dawn of HTML5 brought about a whole bunch of new elments. However, like CSS3, the specification is still relatively new and many of the browsers are slow to adopt the new elements. Elements such as <code class="highlighter-rouge"><header></code>, <code class="highlighter-rouge"><footer></code>, <code class="highlighter-rouge"><nav></code>, <code class="highlighter-rouge"><section></code>, <code class="highlighter-rouge"><progress></code>, <code class="highlighter-rouge"><template></code>, <code class="highlighter-rouge"><aside></code>, <code class="highlighter-rouge"><article></code>, and <code class="highlighter-rouge"><canvas></code> do not possess widespread browser support just yet. Despite this level of inconsistent support, you should not be deterred from using these new tags, but it may be pertinent to be aware of their availability.</p>
<h2 id="html-interfaces">HTML Interfaces</h2>
<p>It is the <a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-011100101">standardization</a> of the <code class="highlighter-rouge">HTMLElement</code> object interface and the inherent hierarchy that makes it possible to reliably resolve an element’s type and therefore support. Included in the hierarchy is the <code class="highlighter-rouge">HTMLUnknownElement</code> interface which acts as a catch-all for invalid HTML elements. In other words, any element you define for which there is no associated interface in the <code class="highlighter-rouge">HTMLElement</code> hierarchy, will default to an instance of the generic <code class="highlighter-rouge">HTMLUnknownElement</code> interface. This is true whether you create the element via <code class="highlighter-rouge">document.createElement</code> or explicitly write it in your markup. This means we can leverage <code class="highlighter-rouge">Object.prototype.toString</code> to divulge an element’s internal <code class="highlighter-rouge">[[Class]]</code> property to ascertain if it is an unknown element:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
function isElementSupported(tag){
var element = document.createElement(tag);
return Object.prototype.toString.call(element) !== '[object HTMLUnknownElement]';
}
</pre>
</div>
<p>Browser support for the interface is good as well, according to <a href="https://developer.mozilla.org/en/docs/Web/API/HTMLUnknownElement">MDN</a>, the <code class="highlighter-rouge">HTMLUnknownElement</code> interface is implemented on all the stock desktop and mobile browsers. Unfortunately, it seems IE8 and less does not support this, instead implementing a <code class="highlighter-rouge">HTMLGenericElement</code> interface.</p>
<p>Bear in mind that it may still be prudent to employ more complicated feature tests to determine support for the actual functionality of an element, such as the case with support for specific formats and codecs of the video and audio elements.</p>
<h2 id="inconsistencies">Inconsistencies</h2>
<p>Unfortunately, there are <a href="http://kangax.github.io/jstests/html5_elements_interfaces_test/">inconsistencies</a> with some elements and their associated interfaces. Some elements that are actually supported (or at least reported to be), inherit from the <code class="highlighter-rouge">HTMLUnknownElement</code> interface. For example, according to <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time#Browser_compatibility">MDN</a> and <a href="http://caniuse.com/#feat=html5semantic">caniuse.com</a>, the <code class="highlighter-rouge">time</code> element has been supported in Chrome since version 33. Yet its internal <code class="highlighter-rouge">[[Class]]</code> property points to the <code class="highlighter-rouge">HTMLUnknownElement</code> interface instead of the <code class="highlighter-rouge">HTMLTimeElement</code> interface as it should. As such, the <code class="highlighter-rouge">datetime</code> attribute inherent to the <code class="highlighter-rouge">time</code> element doesn’t exist:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
'dateTime' in document.querySelector('time'); // false
</pre>
</div>
<p>All indications would suggest the <code class="highlighter-rouge">time</code> element does not exist in Chrome, despite what is being reported. In fact, even though the <code class="highlighter-rouge">HTMLTimeElement</code> interface is clearly defined within the <a href="http://www.w3.org/html/wg/drafts/html/master/#the-time-element">specification</a>, only Firefox 22+ has actually implemented it thus far. Opera had included it in version 11.50 only to remove it in version 15. It would seem the <code class="highlighter-rouge">time</code> element is in a state of limbo as different browsers decide how they want to implement it. Because of this, it may be too soon for the method above. However, moving forward, I would expect browsers to adhere to the specification and include the <code class="highlighter-rouge">HTMLTimeElement</code> interface.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Thanks to HTML interfaces, we can now learn from where elements are derived and the capabilities they inherit. Despite a few false negatives, I would expect this method to be a reliable solution for determining element support in the future, eliminating less reliable element inferences. You can see how your browser stacks up by viewing this <a href="http://codepen.io/ryanmorr/pen/EaWROJ">CodePen</a>. For the latest version of this code, please refer to the project on <a href="https://github.com/ryanmorr/is-element-supported">GitHub</a>.</p>The dawn of HTML5 brought about a whole bunch of new elments. However, like CSS3, the specification is still relatively new and many of the browsers are slow to adopt the new elements. Elements such as <header>, <footer>, <nav>, <section>, <progress>, <template>, <aside>, <article>, and <canvas> do not possess widespread browser support just yet. Despite this level of inconsistent support, you should not be deterred from using these new tags, but it may be pertinent to be aware of their availability.Reinventing the Try/Catch Block2013-09-23T00:00:00+00:002013-09-23T00:00:00+00:00http://ryanmorr.com/reinventing-the-try-catch-block<p>The try/catch block is a unique construct, both in how it works and what it is capable of. Fundamentally, it is able to isolate one or more statements to capture and suppress any runtime errors that may be encountered as a result of execution. It is such a powerful construct that in a perfect world you would want to wrap everything in a try/catch block to provide simple and effective error trapping. However, due to concerns in performance critical situations, employing the construct is often frowned upon. But what if I told you there was a means of emulating the try/catch block without the concern for performance? This article will be exploring just such a method.</p>
<h2 id="performance-implications-of-the-trycatch-block">Performance Implications of the Try/Catch Block</h2>
<p>What makes this construct unique is in the manner in which the catch block augments the scope chain. Rather than creating a new execution context and pushing it to the top of the execution stack, the catch block will actually create a new variable object and place it ahead of the activation object in the scope chain of the current execution context. This creates what is known as a <em>dynamic scope</em>, similar to the effect of the <code class="highlighter-rouge">with</code> statement, which lends to its bad reputation as well. As a result, the error object passed to the catch block does not exist outside of it, even within the same scope. It is created at the start of the catch clause and destroyed at the end of it. This type of manipulation of the scope chain is the primary contributor to the performance hit.</p>
<p>At this point you may be thinking that as long as an error is not raised than performance should not be affected, a fair assumption, but you’d be wrong. Some JavaScript engines, such as V8 (Chrome) do not optimize functions that make use of a try/catch block as the optimizing compiler will skip it when encountered. No matter what context you use a try/catch block in, there will always be an inherent performance hit, quite possibly a substantial one.</p>
<p>These limitations are well documented, for instance, look at the following test cases: <a href="http://jsperf.com/try-catch-block-performance-comparison">http://jsperf.com/try-catch-block-performance-comparison</a> and <a href="http://jsperf.com/try-catch-block-loop-performance-comparison">http://jsperf.com/try-catch-block-loop-performance-comparison</a>. The former confirms that not only is there up to a 90% loss in performance when no error even occurs, but the declination is significantly greater when an error is raised and control enters the catch block. The latter test case proves that the loss is compounded in loops, where most performance intensive operations typically occur.</p>
<h2 id="global-error-handling-using-windowonerror">Global Error Handling Using <code class="highlighter-rouge">window.onerror</code></h2>
<p>To find a suitable alternative, we require a reliable means of error notification. For this, there is really only one viable source in the browser we can turn to for error trapping, that being <code class="highlighter-rouge">window.onerror</code>. The question is, can we leverage the event as a means of closely mimicking the functionality of a try/catch block? The answer is yes… for the most part. The event is capable of detecting runtime errors including any errors that you explicitly throw yourself. We can also imitate the error suppression of a catch block by returning false from <code class="highlighter-rouge">window.onerror</code>, while returning true allows the error to propagate to the browser.</p>
<p>For a long time, despite the cross-browser support and somewhat consistent behavior, the <code class="highlighter-rouge">window.onerror</code> event was non-standard. However, this has changed as the <a href="https://html.spec.whatwg.org/multipage/webappapis.html#errorevent">event has been recently added to the spec</a>. This bodes well for the future and a more predictable API to depend on as browsers slowly adopt the convention defined by the specification.</p>
<h2 id="the-solution">The Solution</h2>
<p>In its simplest form, the solution involves temporarily reassigning the <code class="highlighter-rouge">window.onerror</code> event handler before invoking a “try” function. This allows us to reliably resolve the source of an error when one is encountered. At this point, the associated “catch” handler is invoked, passing the error object as the only argument:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
function tryCatch(tryFn, catchFn) {
// Cache current `onerror` callback
var prev = window.onerror;
// Define a new callback for global `onerror` events
window.onerror = function(msg, file, line, col, err) {
// Restore original `onerror` callback
window.onerror = prev;
// If the error object was not provided, than create it
var error = err || new Error();
// uniform error properties across browsers
error.message = msg;
error.fileName = file;
error.lineNumber = line;
error.columnNumber = col;
// Invoke the "catch" function passing the error object
var suppress = catchFn(error);
// If the callback returned false then allow the error to
// propagate to the browser, otherwise suppress it like a native
// try/catch block would
return suppress === false ? false : true;
};
// Invoke the "try" function
tryFn();
// Restore original `onerror` callback
window.onerror = prev;
}
</pre>
</div>
<p>The function, appropriately named <code class="highlighter-rouge">tryCatch</code>, allows us to wrap error-prone or sensitive code in a similar fashion as a try/catch block. The syntax is similar as well, the exception being the use of functions instead of block statements, such as the following:</p>
<div class="code-block">
<pre class="prettyprint lang-javascript">
tryCatch(function(){
// Try something
}, function(error){
// Handle the error
});
</pre>
</div>
<p>The error object passed to the callback has the added benefit of retaining the file name, line number, and column number of the location of the error, something that is widely inconsistent amongst browsers when employing a try/catch block. Additionally, if the error object is provided to the <code class="highlighter-rouge">window.onerror</code> callback as a parameter, the name, stack trace, and other properties will be available to further improve our ability to debug an error.</p>
<h2 id="performance-comparison">Performance Comparison</h2>
<p>When we measure the performance of this custom solution against a native try/catch block, we get some interesting results. Based on some preliminary tests, I found performance comparisons between the browsers fairly inconsistent. Firefox, IE, and Opera all showed improved performance using the <code class="highlighter-rouge">tryCatch</code> function as opposed to a native try/catch block, while the results were opposite for Chrome and Safari. However, when we avoid needlessly creating anonymous functions for every invocation of the <code class="highlighter-rouge">tryCatch</code> function and instead use predefined functions, performance reaches near native speeds in most browsers. Check out the results and try it yourself at: <a href="http://jsperf.com/native-try-catch-vs-custom-try-catch/7">http://jsperf.com/native-try-catch-vs-custom-try-catch/7</a>. The real advantages come inside loops, in this case performance increased dramatically in most browsers: <a href="http://jsperf.com/native-try-catch-vs-custom-trycatch-loop">http://jsperf.com/native-try-catch-vs-custom-trycatch-loop</a>.</p>
<h2 id="drawbacks">Drawbacks</h2>
<p>Despite some of the advantages to this approach, it is not without its caveats. One such disadvantage is when the “catch” handler is invoked in the case of an error and another error occurs within the handler, then both errors will propagate to the browser. This happens because control still hasn’t left the <code class="highlighter-rouge">window.onerror</code> event handler from the initial error, raising another error will stop execution and resort to the default behaviour. This makes nested <code class="highlighter-rouge">tryCatch</code> calls infeasible.</p>
<p>Another drawback inherent to <code class="highlighter-rouge">window.onerror</code> is that once an error is encountered, the browser will stop execution following the invocation of the event handler. Any code following the <code class="highlighter-rouge">tryCatch</code> call will be skipped as the interpreter will instead proceed to the next script block (<code class="highlighter-rouge"><script></script></code>) if it exists. This is unavoidable, only a catch block is capable of truly suppressing an error without halting execution. Of course, if no further execution is required than this drawback is irrelevant.</p>
<p>One concern that should be cleared up by the new specification are the question marks surrounding <code class="highlighter-rouge">window.onerror</code>. For example, it’s not even clear what errors trigger the event and which don’t. The official Mozilla documentation supports this:</p>
<blockquote>
<p>Note that some/many <code class="highlighter-rouge">error</code> events do not trigger <code class="highlighter-rouge">window.onerror</code>, you have to listen for them specifically.</p>
</blockquote>
<p>Unfortunately, Mozilla doesn’t get any more specific in terms of which errors are actually caught by <code class="highlighter-rouge">window.onerror</code>. According to the <a href="http://msdn.microsoft.com/en-us/library/ie/cc197053%28v=vs.85%29.aspx">Internet Explorer documentation</a>, the following errors trigger the event:</p>
<blockquote>
<ul>
<li>Run-time script error, such as an invalid object reference or security violation.</li>
<li>Error while downloading an object, such as an image.</li>
<li>Windows Internet Explorer 9. An error occurs while fetching media data.</li>
</ul>
</blockquote>
<p>This seems to be consistent with all browsers, and testing has yet to reveal an exception. That’s not bad, but the lack of a clear definition is a little troubling, therefore the question still remains.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The performance benefits of this function are debatable. However, one genuine benefit to this method is in the numerous opportunities for customization. The ability to tailor the <code class="highlighter-rouge">tryCatch</code> function for different use cases and meet various requirements you otherwise couldn’t achieve with a try/catch block.</p>
<p>You could look at it as a suitable median between a native try/catch block and a traditional <code class="highlighter-rouge">window.onerror</code> event handler. On one hand, you can mimic a try/catch block but gain the opportunity to enhance functionality while also proving more beneficial in performance critical situations in some circumstances. On the other hand, it can narrow the scope of a <code class="highlighter-rouge">window.onerror</code> event to specific fragments of code for more effective debugging. Kind of a best of both worlds solution.</p>
<p>Now let me be clear, I am absolutely NOT advocating that you replace all your try/catch blocks using this method. This is still very much in the experimental stage, relying on this method in any type of production environment would be premature. I would, however, encourage you to <a href="https://github.com/ryanmorr/try-catch">fork the code on Github</a>. Maybe you will find some practical use cases in a real world application.</p>The try/catch block is a unique construct, both in how it works and what it is capable of. Fundamentally, it is able to isolate one or more statements to capture and suppress any runtime errors that may be encountered as a result of execution. It is such a powerful construct that in a perfect world you would want to wrap everything in a try/catch block to provide simple and effective error trapping. However, due to concerns in performance critical situations, employing the construct is often frowned upon. But what if I told you there was a means of emulating the try/catch block without the concern for performance? This article will be exploring just such a method.