How to use JSX without React

Did you know you can use JSX without React? If you don't know what JSX is, this except from DRAFT: JSX Specification located at https://github.com/facebook/jsx may help:
JSX is a XML-like syntax extension to ECMAScript without any defined semantics. It's NOT intended to be implemented by engines or browsers. It's NOT a proposal to incorporate JSX into the ECMAScript spec itself. It's intended to be used by various preprocessors (transpilers) to transform these tokens into standard ECMAScript.
JSX was made popular by React. Here's a simple example of what it looks like:
class ShoppingList extends React.Component
{
  render()
  {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}
What you should notice is that it appears like you're intermingling HTML with javascript (or esNext or Typescript or whatever). Some will argue with this and point out that the JSX syntax is just "syntactic sugar" for calls to javascript functions (like React.createElement for example). I'm not here to debate whether or not JSX is a good idea. Rather, I want to illustrate how it is possible to use JSX without React. Most people know that it's totally possibly to use React without JSX. But ask the reverse question (can you use JSX without React?), and you're typically met with puzzled looks and responses like "why would you want to do that?" and "that doesn't make any sense." A quick search using your favorite search engine turns up many a StackOverflow with folks indicating that you can't (or it doesn't make sense to try to) use JSX without React because the transpiled JSX boils down to React.createElement calls. Before we go any further, I should give credit to (and you should read) this post. You will learn something (I certainly did). That post comes with a link to a CodePen that shows how JSX can be used without React, by leveraging the Babel transpiler and specifying a pragma to tell the transpiler what function to inject for each node of the JSX code (hint, it doesn't have to be React.createElement).

Leveraging Typescript for JSX

I'm going to show you a different way to use JSX. Rather than Babel, I'm going to illustrate how you could do it with Typescript. I'll assume you're using VS Code for this, but you certainly don't have to. You do, however, need to have Typescript installed globally, and I will assume that you've got that part already taken care of. Fire up VS Code and then create a tsconfig.json file.
// tsconfig.json
{
    "compilerOptions":
    {
        "target": "es5",
        "jsx": "react",
        "jsxFactory": "hyperscript"
    }
}
The two options to pay attention to are "jsx":"react" and "jsxFactory":"hyperscript". As far as I know, for the jsx compiler option, you only have 3 options: preserve, react, or react-native. You don't want preserve as that would leave your JSX alone to be processed further down the road by something else. You don't really want react either, as we're not using React at all, but Typescript requires that you specify the jsx compiler option if you're also specifying the jsxFactory option, and since that one is critical for what we're doing, we're stuck with having to also include "jsx":"react" in tsconfig.json, but don't worry, we're still not using React at all; I promise! The option "jsxFactory":"hyperscript" is key. It tells Typescript to translate any JSX code it sees into function calls to the hyperscript function (which doesn't yet exist, but we'll write it shortly). It does not, by the way, have to be called "hyperscript". You can call your function anything you like. Choose "jsxFactory":"greatGooglyMoogly" for all I care, or "jsxFactory":"I_Love_The_Avett_Brothers". I'm going to stick with hyperscript for now.

A simple HTML file

Next, let's create an HTML file. This will be brain-dead simple. Just a plain vanilla HTML file that you can load in any browser locally.
<!-- index.html -->
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>JSX without React</title>
    </head>

    <body>
        <h1>I love the <a href="http://theavettbrothers.com">Avett Brothers!</a></h1>

        <script src="./example.js"></script>
    </body>
</html>
Right now of course, it's not going to do anything interesting, in part because example.js. doesn't yet exist. But we'll get there.

Creating the Typescript file

Create a new file, example.ts, and put the following code (or something reasonably similar if you prefer to make the example somewhat "your own.")
// example.ts
class Example
{
    static main(): void
    {
        alert('The Avett Brothers are the greatest!');
    }
}

Example.main();
Nothing earth-shattering here. We simply create a class, Example with a single, static method, main() that alerts a message. Still no JSX but fear not, we're getting closer. We need Typescript to compile (or transpile) this .ts file down to plain javascript for us. If you're using VS Code, you can configure a Typescript task runner. There are short-cuts to do this:
  1. Alt + Shift + P
  2. Type: 'task runner' (without the quotes)
  3. Choose 'Tasks: Configure Task Runner'
  4. Choose 'Typescript - tsconfig.json Compiles a Typescript project'
This will create a tasks.json file under a directory .vscode, which you could also do manually if you prefer. With that file in place, you should be able to press Ctrl + Shift + B to "build" or invoke the tsc compiler. Assuming it works, a new file should be generated, example.js, which means you can now load the index.html in your favorite browser, and (hopefully) see that it works.

What about JSX?

Ok, it's time. You want the ability to use JSX in your Typescript file, so let's (begin) to make this possible now. First, rename example.ts to example.tsx, so that Typescript knows you want it to parse TSX/JSX (JSX in a Typescript file is referred to as TSX). Next, let's write some TSX. Edit the example.tsx file and add the following:
let avettBros = (<div id="avettBros">
    <h1>The Amazing Avett Brothers</h1>
    <ul>
        <li>Scott</li>
        <li>Seth</li>
        <li>Bob</li>
        <li>Joe</li>
    </ul>
</div>);
What you will likely notice at this point are some red squiggly underlines on your HTML tags, indicating that something is wrong. Hover over one of them, and you'll see a message like in the following screenshot: "[ts] Cannot find name 'hyperscript'" [ts] Cannot find name 'hyperscript'. Hopefully this is an "ah ha" moment for you. Typescript recognizes what we're doing, and it's ready to parse the TSX and transpile it into function calls. Except that, we've told it to use the function hyperscript(...) instead of its default React.createElement(...), and that function doesn't (yet) exist. We can fix that. Add the following to your example.tsx file:
function hyperscript()
{
}
Build that and then take a look at the compiled example.js file. You should see something like this:
var avettBros = (hyperscript("div", { id: "avettBros" },
    hyperscript("h1", null, "The Amazing Avett Brothers"),
    hyperscript("ul", null,
        hyperscript("li", null, "Scott"),
        hyperscript("li", null, "Seth"),
        hyperscript("li", null, "Bob"),
        hyperscript("li", null, "Joe"))));
Our hyperscript function is being called for each node in our JSX code. Of course, our function does nothing at the moment. We need to fix that, but what should our hyperscript function do? Well, the ultimate goal is to find a way to render this JSX, and for that, we need DOM -- real DOM. But if you look for a moment and analyze what is being passed to the hyperscript function, you'll notice that it's a sufficient amount of information to build a virtual DOM. And with that, we can certainly turn it into real DOM, to be injected into the page. From a first-cursory look, it appears that what's being passed into our function is:
  • The name of an HTML tag, which will eventually become an element
  • A dictionary of key/value pairs representing that element's attributes
  • And one of more additional objects, passed as parameters, to be treated as the element's children
So using example.js's content as an illustration that would results in:
div with id 'avettBros'
 |-- h1 with text 'The Amazing Avett Brothers'
 |-- ul
 |---- li with text 'Scott'
 |---- li with text 'Seth'
 |---- li with text 'Bob'
 |---- li with text 'Joe'
The starting element is a DIV with id="avettBros" which has two children: an H1 (whose text content is "The Amazing Avett Brothers") and a UL. The UL of course, has additional children -- 4 of them: LI elements with text content representing the members of the band. Hopefully you're beginning to see how this could be turned into an object (a virtual DOM element, if you will) which can then be passed into a render(vdom) function (which we haven't written yet, but will soon) which creates an actual, real DOM, to be injected into the page.

The hyperscript function

Ok, so what should our hyperscript function do? What should it return? An object of course, but how? Well, we have pretty much everything we need, and a reasonable (but less-than-ideal first attempt might look like this):
function hyperscript(tagName, attributes)
{
   // gather all function params beyond the first two, into an array called children
   var children = Array.prototype.slice.call(arguments, 2);
   return { tagName: tagName, attributes: attributes, children: children }; 
}
I went old-school with that function for the benefit of anyone who might not yet be familiar with some of the newer, ESNext capabilities. We'll update it in a moment because (as you'll see shortly) some minor tweaks are needed anyway. In my example above, I've only used JSX to spit back some hard-coded HTML that I wrote. In reality, you'll probably be looping and building up this HTML rather than hard-coding it. For example:
class Example
{
    static bros:string[] = [ 'Scott', 'Seth', 'Bob', 'Joe' ];

    static listBros(): string[]
    {
        return Example.bros.map(bro => <li>{bro.toUpperCase()}</li>);
    }
}

let avettBros = (<div id="avettBros">
    <h1>The Amazing Avett Brothers<span>!</span></h1>
    <ul>
        <li>--start--</li>
        { Example.listBros() }
        <li>--end--</li>
    </ul>
</div>);
What you should notice here is that Example.listBros() doesn't actually return a virtual DOM object. It returns an array. An array of virtual DOM objects because bro => <li>{ bro.toUpperCase()</li> } is going to translate to hyperscript(..) calls. But it's still an array and not a virtual DOM object. This means that the children variable (the one defined in our hyperscript function as an array of all the function params beyond the first two) is going to be (in this case) a "mixed bag." In other words, some of the array items will be virtual DOM objects, others will be arrays themselves containing virtual DOM objects. But what we really want is a flattened array of virtual DOM objects. Here is what the children array of the virtual DOM object representing the UL will be as of right now:
// UL's children array
[ vdomObj, [ vdomObj, vdomObj, vdomObj, vdomObj ], vdomObj ]
See that array sandwiched between the first vdomObj (which would be <li>--start--</li>) and the last vdomObj (which would be <li>--end--</li>)? We want to flatten that into a non-nested array, something like:
// UL's children array
[ vdomObj, vdomObj, vdomObj, vdomObj, vdomObj, vdomObj ]
This is doable. We can flatten nested arrays (1 level nested arrays anyway) pretty easily. There's the old-school way, and the cool, new way. I'll start with old-school:
function hyperscript(tagName, attributes, children)
{
   var children = Array.prototype.slice.call(arguments, 2);
   children = Array.prototype.concat.apply([], children);
   return { tagName: tagName, attributes: attributes, children: children }; 
}
This is fine, but if you want to be like the cool kids, you'll use the new rest and spread elements. Rest is used to "gather up" into an array, the remaining elements in an expression, while Spread is used (often when calling a function but there are other applications as well) to "spread out" the elements of an array, as if you were passing the individual elements and not the array itself.
function hyperscript(tagName, attributes, ...children)
{
   children = [].concat(...children);
   return { tagName, attributes, children };
}
I sneaked a few other shortcuts in there as well. The return statement takes advantage of the ESNext features that let's you create objects whose properties are the same name as the variable. So in this case, it's the same as return { tagName: tagName, attributes: attributes, children: children }. I also used [].concat(...children) instead of Array.prototype.concat.apply([], children), because it's shorter, and, as previously explained, takes advantage of spread elements.

Rendering the Virtual DOM

Alright, it's time to render the virtual DOM we've created. For that, we need a render function. It'll have to be recursive. It could look like this.
function render(vdom)
{
    let dom:HTMLElement = document.createElement(vdom.tagName);
    for (let key of (vdom.attributes || {}))
    {
        dom.setAttribute(key, vdom.attributes[key]);
    }

    for (let child of vdom.children)
    {
        if (typeof child === 'string')
        {
            dom.appendChild(document.createTextNode(child));
        }
        else
        {
            dom.appendChild(render(child));
        }
    }
    return dom;
}
There are, of course ways to condense this code down and features of both esNext and Typescript that we could (should) be using here, but I've opted for mostly es5 style code, with just a little bit of Typescript thrown in. Hopefully this makes the code easier to understand for anyone who maybe hasn't yet caught up and started using tomorrow's javascript today. As far as recursive functions go, this one isn't too hard to understand. First, we create an element based on the tag name (vdom.tagName) we're given. Next, we add attributes to the element we created, based on the collection of given in vdom.attributes. Finally, we need to loop through vdom.children. If the child is just a plain 'ol string, life is easy. Just create a new text node and add it to our DOM element. Otherwise, we'll have to call render(child), in order to go through the rendering process on any sub-virtual DOM objects.

A full, working, example

Ok, here's the TL;DR. A full, working example. I know, I know. The TL;DR should come in the beginning. But I put a lot of work into writing this. I want people to read it, not just skip to "the good part." 😉
// example.tsx
function hyperscript(nodeName, attributes, ...children)
{
    children = [].concat(...children);
    return { nodeName, attributes, children };
}

function render(vdom)
{
    let dom:HTMLElement = document.createElement(vdom.nodeName);
    for (let key of (vdom.attributes || {}))
    {
        dom.setAttribute(key, vdom.attributes[key]);
    }

    for (let child of vdom.children)
    {
        if (typeof child === 'string')
        {
            dom.appendChild(document.createTextNode(child));
        }
        else
        {
            dom.appendChild(render(child));
        }
    }
    return dom;
}


class Example
{
    static bros:string[] = [ 'Scott', 'Seth', 'Bob', 'Joe' ];
     
    static listBros(): string[]
    {
        return Example.bros.map(bro => <li>{bro.toUpperCase()}</li>);
    }
}
     
let avettBros = (<div id="avettBros">
    <h1>The Amazing Avett Brothers<span>!</span></h1>
    <ul>
        <li>--start--</li>
        { Example.listBros() }
        <li>--end--</li>
    </ul>
</div>);

var dom = render(avettBros);
document.body.appendChild(dom);
Now, I have of course, just sloppily thrown my hyperscript and render functions directly into the global space. But it shouldn't be too hard to think about you you could improve the organization here with separate files and using imports and exports. I'm not doing that here; that can be an exercise for the reader. I should also point out that this example doesn't cover the scenario where you can create components that return JSX/TSX and use those in your JSX/TSX expressions.
class Avetts
{
   constructor()
   {
      return (<h1>My name is Stephen, and I love the Avett Brothers!</h1>);
   }
}

let myApp = (<div id="myApp">
   <p>Welcome to my app</p>
   <Avetts />
   <p>This is the end of my app</p>
</div>);
To be clear, the above is NOT something that will work with our code, as it is currently written. It's not too hard to modify the code to support this though. But this post is already quite long. I'll leave the code in this post as-is for now and save enhancing it for another post. Zip download of fully working example Using the link above, download and extract the zip file; then open the folder in VS Code. Press Ctrl + Shift + B to make the Typescript compiler run and it should generate an example.js file. Then open index.html in a browser and you should (hopefully) see everything working.

A Final Note

I want to point out here (though I'd hope this is obvious) that what I'm demonstrating in this post is for illustration purposes only. What I'm offering here is NOT production-ready code for you to take and use in your project. I'm NOT suggesting that you should do something like this build your own framework, and I'm certainly not suggesting that you should dump React and start doing this (the idea illustrated here doesn't even come close to replicating the features of React). If you take nothing else away from this post, at least understand this: this blog post is meant for learning and nothing more. Please don't copy/paste this code and then come yelling at me when you find it isn't robust enough, doesn't meet your needs or is full of bugs. You've been forewarned!

Dealing with CSS Vendor Prefixes

The IE team recently posted what they're calling a best practice for dealing with vendor prefixes in modern browsers. After reading it, I thought I would post the solution used in Gimme, which I implemented as soon as I had to start dealing with vendor prefixes. I've yanked it out and posted it here as a stand-alone function called getStyleName(). You can use it when you want to set some element's style in Javascript. You always pass it the "standard" name (without any prefix) and it will do (or try to do) the right thing in the right browser. For instance:
var someElem = document.getElementById('foo');

// MozTransform in Mozilla, webkitTransform in webkit, etc...
someElem.style[getStyleName('transform')] = 'rotate(90deg)';
Here is the getStyleName function in full:
var getStyleName = function()
{
   var styleHash = {};
   var vendorPrefixes = [ 'O', 'ms', 'Moz', 'Webkit' ];

   return function(styleName, elem)
   {
      elem = elem || document.createElement('div');
      var s = styleHash[styleName];
      if (!s)
      {        
         // hope the browser supports the "official" (non-vendor-prefixed) style first
         var camStyle = camelize(styleName);
         
         // if not, then ask getVendorStyle for help -- it will try the various vendor prefixes seeking
         // one that works (if it doesn't find one, it will return an empty string, in which case we
         // revert back to originally passed in styleName)
         if (elem.style[camStyle] === undefined)
         {
            camStyle = getVendorStyle(camStyle, elem) || styleName;
         }

         // finally, store the camelized & vendor-specific (if applicable) value in the styleHash where key = styleName that was passed in
         s = styleHash[styleName] = camStyle;
      }
      return s;
   }

   function getVendorStyle(style, elem)
   {
      var s = camelize('-' + style);
      var i = vendorPrefixes.length;
      while (i--)
      {
         style = vendorPrefixes[i] + s;
         if (elem.style[style] !== undefined)
         {
            return style;
         }
      }
      return '';
   };

   function camelize(s)
   {
      return s.replace(/-(\w)/g, function(m, c)
      {
         return c.toUpperCase();
      });
   }
}();

True private variables in Javascript with prototype

Most folks know how to mimic public, private, and "privileged" variables in Javascript, but I think at some point, when getting familiar with prototypal inheritance, most scripters wonder if there is a way to access the private members (the ones created in a closure) of an instance within a function defined using prototype. There is really no good way to do this. Here's a simple prototype example:
function Cat(name, age)
{
   this.name = name;
   this.age = age;
}
Cat.prototype.introduce = function()
{
   alert('I am a cat. My name is ' + this.name + ', and I am ' + this.age + ' year(s) old.';
};

var c = new Cat('Garfield', 7);
c.introduce();
The introduce function was defined with .prototype so the this keyword in that context refers to the Cat instance in question. Using it, we can get at the .name and .age properties. But this also means that the introduce function isn't the only thing that has access to those properties. In fact, the whole world has access. They are, essentially, public properties.
alert(c.name);    // directly accessible
alert(c.age);     // directly accessible
 
What if you don't want that? What if you want to take the name that is passed into the constructor, modify it in some way (let's say, convert it to uppercase) and then offer read only access to it?
function Cat(name, age)
{
   this.name = name.toUpperCase();
}
Cat.prototype.getName = function()
{
   return this.name;
};

var c = new Cat('Garfield', 7);
alert(c.getName());     // GARFIELD
c.name = 'STEPHEN';     // oops, should this be allowed?
alert(c.getName());     // STEPHEN, clearly not the kind of encapsulation we're going for
 
So how can we allow getName to have access to .name, but at the same time disallow access to .name outside of prototype defined functions? Well, as I said, you really can't. I mean, there's no good way. But there is a sort-of way.
DISCLAIMER: I am NOT recommending that you actually do what I'm about to demonstrate. At the same time, I am not telling you NOT to do it either. From a performance perspective, this is completely unvalidated (at least by me). So if you want to do something like this, best do your homework and figure out if it will offer you an acceptable level of performance -- I am not attempting to answer that for you.
Alright. With the disclaimer out of the way, here we go:
var Cat = function()
{
   var guid = 0;
   var privates = {};

   function cat(name, age)
   {
      this._$guid = guid++;
      privates[this._$guid] =
      {
         name: name,
         age: age
      };
   }
   cat.prototype.getName = function()
   {
      return privates[this._$guid].name;
   };
   cat.prototype.getAge = function()
   {
      return privates[this._$guid].age;
   };

   return cat;
}();

var cat1 = new Cat('Garfield', 7);
var cat2 = new Cat('Fluffy', 13);

alert(cat1.getName === cat2.getName);     // true
alert(cat1.name);          // oops, no dice (which is good)
alert(cat1.getName());           // Garfield
alert(cat2.age);           // oops, no dice
alert(cat2.getAge());            // 13
 
First, I alert cat1.getName === cat2.getName to illustrate that prototype really is being used here. The instances cat1 and cat2 share the implementation of the getName function (they don't each get their own -- something that would have been true had we used the closure model exclusively). Second, you'll notice that I do not have direct access to .name or .age. So this seems to do what we want. Now, more alert readers will no doubt have noticed that I cheated. I'm still using the this keyword from within my prototype defined functions, getName and getAge. This is so that I can access the instances GUID (._$guid). The GUID is, of course, nothing more than counter, but it serves as a way to track the created instances. Using it, we can get access to property bag in the privates hash that "belongs to" the particular Cat instance we're interested in. But there is a flaw here, of course. The ._$guid, despite its marginally cryptic name, is completely unprotected. That is, the whole world has access to it. So one could really hork things badly if he decided to do something like:
var garfield = new Cat('Garfield', 7);
var fluffy = new Cat('Fluffy', 10);

fluffy._$guid = 0;
alert(fluffy.getName());      // Garfield, oops!  this is NOT good
Now, in this example, I chose a valid GUID (that of Garfield), but I could have just as easily chosen an invalid GUID, which would have caused a script error. Of course, the script error is easily preventable by ensuring that the ._$guid actually exists as a key in the privates hash before attempting to access it, but this does nothing to ensure the integrity of the data, and that's a problem. Turns out though, that we can add a bit more code. A bit of code that involves a check prior to accessing data from the privates hash to ensure that the instance's _$guid hasn't been tampered with. If it has, we throw an exception and refuse to go any further. Here's the revision:
var Cat = function()
{
   var guid = 0;
   var privates = {};
   var check = {};

   function cat(name, age)
   {
      this._$guid = guid++;
      check[this._$guid] = this;
      privates[this._$guid] =
      {
         name: name,
         age: age
      };
      
   }
   cat.prototype.getName = function()
   {
      if (check[this._$guid] !== this)
      {
         throw 'Oops, looks like this instances has been tampered with.';
      }
      return privates[this._$guid].name;
   };
   cat.prototype.getAge = function()
   {
      if (check[this._$guid] !== this)
      {
         throw 'Oops, looks like this instances has been tampered with.';
      }
      return privates[this._$guid].age;
   };

   return cat;
}();


var fluffy = new Cat('Fluffy', 7);
var snowball = new Cat('Snowball', 12);
var garfield = new Cat('Garfield', 9);

alert(fluffy.getName());      // Fluffy
alert(snowball.getName());    // Snowball
alert(garfield.getName());    // Garfield
fluffy._$guid = 2;
alert(fluffy.getName());      // Throws an exception, b/c fluffy's _$guid was modified
I even created a nice illustration to help you visualize this 🙂 Visualization of private variables using prototype in Javascript As you can plainly see, the keys in the privates hash correspond to the ._$guid property of Cat instance. In other words, if you match up an instance's ._$guid with a key in the privates hash, you'll have access to that instance's collection of member variables. You'll also notice that the keys in the check hash match the keys in the privates hash. However, they don't point to a property bag, they point to an actual Cat instance. In the getName function, we have access to the instance (through the use of the this keyword), and we can use that to perform a check. If an instance's public ._$guid has been tampered with, then looking in the check hash for that $_guid will result in accessing a Cat instance that isn't equal (identical) to this. In that case, we can throw an exception. Otherwise, we go ahead and access and entry from the privates hash, and this gives us access to the current Cat's members. Before closing, I want to once again make clear that I am most definitely NOT recommending that you use this model, but neither am I discouraging the use of it (I'm a little bit annoying that way, I know). It's simply untested in terms of memory and speed performance. Whether or not this yields anything that would constitute acceptable performance, I do not know and have not attempted to determine. I imagine there could be some scenarios in which it is probably okay. And I imagine there are other scenarios in which it might be a nightmare, but I'm only guessing on both counts. If you decide to experiment with this, definitely report back here with your findings for all to see. Happy scripting!

Dependency Injection / Dependency Management (part 1)

I'm not an expert when it comes to dependency injection, but I do know a little. My team uses Unity in one of its projects, so I have some exposure. Recently, I started work on a project (hoping to eventually release it as OSS) on a Dependency Injection (like) / Dependency Management framework for the client (that is, written in Javascript). Since it was (is) a fun project for me, I thought I might blog about some of the more interesting parts of what I've done. Dependency Resolution: One of the key parts of Dependency Injection is dependency resolution. That is, if I need an instance of something, say, a Foo, and if creating a Foo requires an instance of say, a Bar, then my DI framework ought to resolve the Bar for me on its way towards creating my Foo.
var registration =
{
   Foo: { className: 'Stephen.Stchur.Foo', params: [ 'Bar' ] },
   Bar: { className: 'Stephen.Stchur.Bar' }
}

// obviously, code for Container, not show here (yet)
var c = new Container(registration);
var f = c.instance('Foo')// container "knows" Foo needs Bar; it takes care of it for us
So what I'm focusing on in this blog post is the comment above: "container 'knows' Foo need Bar; it takes care of it for us. In a future post, I'll be talking more about the management part (involving not only resolving types on demand, but also downloading dependencies and groups of dependencies prior to resolution). But for now, let's just assume that all dependencies needed to create anything/everything have already been preloaded. So how does the container know that Foo needs a Bar? Well, it's not too hard to figure out if you look at the registration. It's just a dictionary of key/value pairs, where the value is a simple object literal containing a couple properties:
  1. className - required, the fully qualified name of the thing that the container will eventually be creating instances of
  2. params - optional, an array of string keys that map to other values in the registration dictionary
Container knows that Foo needs a Bar because that was explicitly spelled out in the registration when we defined:
Foo: { className: 'Stephen.Stchur.Foo', params: [ 'Bar' ] }
The params array tells the container everything it needs to know. So what does the code that actually implements this type resolution look like? Glad you asked. Code below, explanation to follow:
function Container(reg)
{
    function instance(factoryName)
    {
        var params = reg[factoryName].params;
        var i = params.length;    
        while (i--)
        {
            var f = reg[params[i]];
            if (f)
            {
                params[i] = instance(params[i]);
            }
        }

        return create(reg[factoryName].className, params)
    }
    this.instance = instance;

    function create(type, params)
    {
        var constructor = new Function('return ' + type)();
        var inst = new constructor();
        inst.init && inst.init.apply(inst, params);
        return inst;
    }
}

var c = new Container(registration);
var f = c.instance('Foo');
Now this is not actually the code used in the project I'm working on. It's actually rather different, but this will suffice for now. One thing to note is that I'm really not performing any sort of safety checks here. If you ask the container for an instance of something that hasn't been registered, it will not fail gracefully (and it really should). But that's an easy change and not really the focus here. There isn't a ton code that requires explanation here, except for a couple pieces. The first piece that I suspect will raise some eyebrows is:
var constructor = new Function('return ' + type)();
Now let me say right off the bat that I'm not claiming this is the best way to do it (certainly it's not the only way). Essentially, this is just a confusing way of doing:
var constructor = eval(type);
So why not just do that? Well, I'm not saying you can't, but a lot of people have a hard-line stance against using eval. Also, in some browsers, eval was much slower than using new Function(..). However, in other browsers, eval was faster (sometime nominally, sometimes significantly). Finally, there is another option in this case: you can split the type string on the dot, and actually attempt to access the parts as properties. It would ultimately translate to something like:
var constructor = window['Stephen']['Stchur']['Foo];
Of course, you wouldn't hard code it like that, you'd split the string and loop, but I trust you get the idea. For simple cases, this actually turns out to be quite fast, so it's something to consider. But also worth considering is that fact that, for small numbers of repeated executions, it matters very little which method you choose. And if you cache the resolved constructor once you get it, it matters even less. Anyway, I used new Function(..) in this post, because I think it's an interesting way to accomplish the task (not necessarily the best, but chances are you haven't seen it before, so you learned something, and that's what this blog is all about -- spreading knowledge and learning). If you're unfamiliar with Function (capital F) in Javascript, allow me to explain. Function in Javascript is a constructor that takes a string and returns you a function whose logic is whatever string-code you passed into it. For example:
var sayHello = new Function('alert("hello there");');
sayHello();       // alerts "hello there"
It's not too hard then to see how we've leveraged Function in our case. We created a function whose job it is to return a reference to function named, type. That is, if type = "Foo" then this code:
var constructor = new Function('return ' + type)
Will result in the variable constructor, pointing to the function, Foo (so it essentially is Foo). Another way of thinking about it is that the implementation of the function we've create is:
return Foo;
And when you execute that function, what you get back is a reference to the function Foo, which is the constructor you care about. Great! Now what? Well, now we should invoke the constructor. Unfortunately, things fall a part a little bit here (but only a little). There isn't really a great way to invoke a constructor with the new keyword and at the same time pass in an array of params to be used as the individual arguments to that constructor. More clever Javascript Ninjas will give you creative solutions. You can create an empty object, and then call .apply on the constructor, passing in the object you created as the this object and the items in whatever array you pass in will becomes the individual arguments to the constructor. This however, won't result in an object that actually is an instance of your constructor.
function Cat(name, age)
{
    this.description = 'furry';
    this.name = name;
    this.age = age;
}
var c = {};
Cat.apply(c, [ 'Garfield', 10 ]);
c instanceof Cat; // false 🙁
You can carry this further though. You can set the native prototype of your c object to be Cat's prototype:

var c = {};
c.__proto__ = Cat.prototype;
c instanceof Cat; // true 🙂
However, support for __proto__ is not so good in several older versions of a certain, still-fairly-popular-but-I-have-no-idea-why browser (I'm a Firefox guy myself). It's worth pointing out here that your temptation to try c.prototype = Cat.prototype will not work, but I'm not going to get into why. This isn't a post about prototype in Javascript. If you care to, you could iterate Cat's prototype and manually copy over all the properties. Then your object would satisfy as a Cat if you're okay with duck typing. But it still wouldn't actually be a Cat. Well, if you're only targeting browsers that support __proto__, then that's an option. If you don't care about your object actually being a true instance of the thing you're creating, then you can use .apply and copy over the prototype. Or, if you have some magic pixie dust that I don't have, then I suppose that's an option too (please share). Short of any of those things, your other option is to mandate some sort of a convention. Two conventions come to mind that are simply and work well.
  1. Mandate that all constructors be able to successfully execute, parameterless. And then automatically call (if it exists) some special initialization function (I like .init) that take all the params that really matter.
  2. Mandate that all constructors take only a single param - an array of values needed to construct the instance.
I chose option 1 for the sample code in this post. I like it better than option 2 because I have a Chocolate Lab named Guinness (that didn't make any sense). Moving on... With the instantiation out of the way, the only remaining bit of code might be the resolution of the params. First we grab a reference to the array of params, as defined by this factory's definition in the registration:
var params = reg[factoryName].params;
We then loop through it (backwards, because that's how I roll), and pull out each value, assigning it to the variable, f. We assume that f points to a valid, registered, factory. If not, we leave the value alone (this isn't particular useful right now, but in a future blog post, you'll see the code reworked a bit so that the .instance function can accept arbitrary values to be used as other arguments in constructing your object). Now if f does point to a valid, registered factory, then we go ahead and resolve it. Resursively. By calling .instanace again. This is important, in case of the params, are factories that take other params that are factories. Once we've resolved a param though, we can actually just have the result "take over" what was in the original params array at the index originally.
params[i] = instance(params[i]);
In this way, the right value will be in the right place in the params array when it finally gets plumbed through to the call to inst.init.apply(inst, params) Makes perfect sense right? Honestly, I think it's harder to speak/write about than it is to just understand. It's not super complicated. It will get more complicated though. But that's for a future blog post. In the mean time, here's a full, copy/pastable bit of code that actually works.
var Stephen =
{
    Stchur:
    {
        Foo: function()
        {
            this.desc = 'foo!';
        },

        Bar: function()
        {
            this.desc = 'bar!';
            this.init = function(f) { this.myFoo = f; };
        },

        Baz: function()
        {
            this.desc = 'baz!';
            this.init = function(f, b)
            {
                this.myFoo = f;
                this.myBar = b;
            };
        }
    }
};

var registration =
{
    Foo: { className: 'Stephen.Stchur.Foo' },
    Bar: { className: 'Stephen.Stchur.Bar', params: ['Foo'] },
    Baz: { className: 'Stephen.Stchur.Baz', params: ['Foo','Bar'] }
};

function Container(reg)
{
    function instance(factoryName)
    {
        var params = reg[factoryName].params || [];
        var i = params.length;    
        while (i--)
        {
            var f = reg[params[i]];
            if (f)
            {
                params[i] = instance(params[i]);
            }
        }

        return create(reg[factoryName].className, params)
    }
    this.instance = instance;

    function create(type, params)
    {
        var constructor = new Function('return ' + type)();
        var inst = new constructor();
        inst.init && inst.init.apply(inst, params);
        return inst;
    }
}

var c = new Container(registration);
var f = c.instance('Baz');
Look for part 2 coming soon. Happy scripting!

Javascript Quiz

Inspired by some Javascript questions I was asked recently by a few co-workers, I decided to put together what started out a little reference/cheat-sheet, but which ultimately took the form of a Javascript Quiz. It's meant to be fun and informative. You keep track of your own answers (if you want to); no one ever has to know what you got right or wrong. I should mentioned that I did NOT test this in all browsers. I'm a Firefox guy, so that's where I do most of my testing and development for little one-off personal projects like this. I did take a quick pass with IE8 and Chrome, but I did NOT test with IE6 or IE7 or Safari. If something doesn't work in one of those browsers, feel free to let me know, but bear in mind that there is a strong possibility that I will not care in the least 😀 And of course, there's always multiple ways to solve a problem. I do not claim any sort of authority with any of the answers I've provided. If you dislike an answer of feel you have a better one, good for you 😉 Anyway, here it is: http://blog.stchur.com/blogcode/jsquiz Enjoy!

Programmatically clicking a link in Javascript

More accurately, this would be called actuating a link (i.e. the process of setting the link's behavior into motion, if you will.) In other words, you have a link:
<a id = 'bingLink' href = "http://www.bing.com">Bing</a>
And you want to programmatically make that link do its thing. This usually means having the browser navigate to the URL specified link's href attribute (though, it can also mean executing some click handler if one happens to be specified on said link.) To be honest, I don't think there are a ton of real-world uses for this, but there are a few. And depending on your needs, it may not be trivial to accomplish this in a cross-browser fashion. For example:
var myLink = document.getElementById('myLink');
myLink.click();
The above will do the trick in IE, because IE supports .click() on links. Most other browsers don't though, so that's not an all-encompassing solution. One (partial) solution in non-IE browsers might be to read the href attribute from a given link and then use Javascript to make the browser navigate to to the URL specified by href that way:
function actuateLink(link)
{
     window.location.href = link.href;
}
This is not a complete solution for a couple of reasons:
  1. Navigating by setting window.location.href blows away the document.referrer property.
  2. Any click event handler wired to the link will not execute.
For anyone who has read my post about Re-routing events in Javascript post, you'll know that it is possible to simulate an event though the use of .dispatchEvent(..). Here's a brief refresher of the part most relevant to this discussion:
var myEvt = document.createEvent('MouseEvents');
myEvt.initEvent(
   'click'      // event type
   ,true      // can bubble?
   ,true      // cancelable?
);
document.getElementById('myLink').dispatchEvent(myEvt);
This approach will ensure that any click event handlers will fire as desired (though, it's worth nothing that you'd have to handle mousedown, mouseup, keydown, keypress etc... separately,) but it does NOT actuate the link! This might surprise you. Dispatching a click event to a link doesn't actually cause the browser to navigate to the URL specified by that link's href property. This actually isn't shocking to me, personally. A little surprising, but not shocking. Anyway, one option is to dispatch the click event and then use window.location.href. This should achieve (some of) the desired effect, but again, the document.referrer will not be preserved if you do this. Also, if the event handler prevents the default action, this method will not honor the code that prevents the default action (i.e. the link will navigate despite the code that attempts to prevent it from doing so.) You can work around the window.location.href problem by creating a <form> element, settings its action attribute to that of the link's href attribute and then submitting the form through myForm.submit(), but the problem regarding preventing the default action remains.

A 95% Solution

Is there a 100% perfect solution to this problem? Probably, but I'm not 100% perfect. I'm only 95% perfect, so I give you my 95% solution:
function actuateLink(link)
{
   var allowDefaultAction = true;
      
   if (link.click)
   {
      link.click();
      return;
   }
   else if (document.createEvent)
   {
      var e = document.createEvent('MouseEvents');
      e.initEvent(
         'click'     // event type
         ,true      // can bubble?
         ,true      // cancelable?
      );
      allowDefaultAction = link.dispatchEvent(e);           
   }
         
   if (allowDefaultAction)       
   {
      var f = document.createElement('form');
      f.action = link.href;
      document.body.appendChild(f);
      f.submit();
   }
}
To use it:
actuateLink(document.getElementById('bingLink'));
This code is self explanatory, right? If .click() is available, let's use that. If not, let's try to do a W3C-style create and dispatch event. Then, in order to maintain the document.referrer property, we'll use a form submission, but we only want to submit that form if the event handler (if there is one) for the click event doesn't explicitly prevent the default action. This isn't a 100% perfect solution because, actuating a link in this manner is only going to invoke click handlers and navigate to the URL of the link's href attribute (if appropriate to do so.) It isn't going to invoke handlers for any other types of events. And I'm not about to create and dispatch every possible kind of event. Besides, I think we can all agree that click is by far the most common scenario. So there ya go. Programmatically clicking (or more accurately, actuating) a link with Javascript. Enjoy! (Tested: Firefox 3.5.7, IE8, Opera 10.01, Safari/Win 4.0.3, Chrome 3)

Fetch (a stand-alone CSS querying engine)

I've started work on a new side-project called Fetch. It's a stand-alone CSS querying engine, designed to be super lightweight and offer high performance across all modern browsers. It's still very much in development and the source is a bit sloppy, but it currently weighs in at only 2.5k compressed and gzipped and (in Firefox3) either outperforms or is on par with all other major Javascript libraries out there*. It's definitely not ready for production use, but when it is, it will become the new CSS querying engine for Gimme and will also be available as a stand-alone library, which will be extensible (so you can add your own rules) and which will also be guaranteed to play nicely with other libraries by not adding to the prototype of any native objects and only introducing one single global variable (fetch). For anyone interested, the current (i.e. sloppy) source is available on CodePlex: fetch.js. As I said, it's not ready for prime time and the code is sloppy (and probably buggy). Consider yourself warned. * Fetch was not compared with libraries that use XPath or querySelectorAll, because it uses neither, but rather is a pure Javascript implementation. Upon release, it will take advantage of querySelectorAll where appropriate, but will not use XPath.

The Ultimate addEvent(..) function

Two articles in particular that I've written on this blog have garnered a lot of positive feedback.

  1. Fixing IE's attachEvent Failures
  2. mouseenter and mouseleave Events for Firefox (and other Non-IE Browsers)

As time has gone on, I've seen mention of these articles pop up in programming forums here and there, and they still receive comments from time to time, which lets me know that people are still getting something out of them.

Unfortunately, the code in them is a tad dated. I've learned more and improved my code since I originally wrote them, and while these improvements have made their way into my Javascript Library, I know that the majority of people are just grabbing the code directly from the blog entries.

So I've decided to post an update: a sort of fusion between these two blog entries which offers functionality for addressing all of the issues discussed in the aforementioned entries (and then some).

I consider this new function the "Ultimate addEvent Function" because I really believe it addresses the large majority of cross-browser issues that people face when dealing with events in Javascript. And furthermore, this function goes beyond anything that any other Javascript library provides (at least as far as I know).

So without further ado, I offer to you:

sstchur's Ultimate addEvent(..) function!

var xb = {};
(function()
{
   var GUIDCounter = 0;
   var evtHash = {};
   var pseudoEvents =
   {
      'mouseenter': function(_fn, _useCapture, _listening)
      {
         var f = mouseEnter(_fn);
         _listening ?
            xb.addEvent(this, 'mouseover', f, _useCapture, false) :
            xb.removeEvent(this, 'mouseover', f, _useCapture, false);
         f = null;      
      },
      
      'mouseleave': function(_fn, _useCapture, _listening)
      {
         var f = mouseEnter(_fn);
         _listening ?
            xb.addEvent(this, 'mouseout', f, _useCapture, false) :
            xb.removeEvent(this, 'mouseout', f, _useCapture, false);
         f = null;      
      }
   };
   
   xb.Helper =
   {
      getObjectGUID: getObjectGUID,
      storeHandler: storeHandler,
      retrieveHandler: retrieveHandler,
      isAnAncestorOf: isAnAncestorOf,
      mouseEnter: mouseEnter
   }
   
   xb.addEvent = function()
   {
      if (typeof document.addEventListener !== 'undefined')
      {
         return w3c_addEvent;
      }
      else if (typeof document.attachEvent !== 'undefined')
      {
         return ie_addEvent;
      }
      else
      {
         // no modern event support I guess 🙁
         // (you could use DOM 0 here if you really wanted to)
         return function() {};
      }
      
      function w3c_addEvent(_elem, _evtName, _fn, _useCapture, _directCall)
      {
         var eventFn = pseudoEvents[_evtName];
                  
         if (typeof eventFn === 'function' && _directCall !== false)
         {
            eventFn.call(_elem, _fn, _useCapture, true);
         }
         else
         {
            _elem.addEventListener(_evtName, _fn, _useCapture);
         }
      }
      
      function ie_addEvent(_elem, _evtName, _fn, _useCapture, _directCall)
      {
         var eventFn = pseudoEvents[_evtName];
               
         if (typeof eventFn === 'function' && _directCall !== false)
         {
            eventFn.call(_elem, _fn, _useCapture, true);
         }
         else
         {
            // create a key to identify this element/event/function combination
            var key = generateHandlerKey(_elem, _evtName, _fn);
            
            // if this element/event/combo has already been wired up, just return
            var f = evtHash[key];
            if (typeof f !== 'undefined')
            {
               return;
            }
            
            // create a helper function to fix IE's lack of standards support
            f = function(e)
            {
               // map .target to .srcElement
               e.target = e.srcElement;
               
               // map .relatedTarget to either .toElement or .fromElement
               if (_evtName == 'mouseover') { e.relatedTarget = e.fromElement; }
               else if (_evtName == 'mouseout') { e.relatedTarget = e.toElement; }
                  
               e.preventDefault = function() { e.returnValue = false; };
               e.stopPropagation = function() { e.cancelBubble = true; };

               // call the actual function, using entity (the element) as the 'this' object
               _fn.call(_elem, e);
               
               // null out these properties to prevent memory leaks
               e.target = null;
               e.relatedTarget = null;
               e.preventDefault = null;
               e.stopPropagation = null;
               e = null;
            };
            
            // add the helper function to the event hash
            evtHash[key] = f;

            // hook up the event (IE style)
            _elem.attachEvent('on' + _evtName, f);
            
            key = null;
            f = null;
         }
      }
   }();

   xb.defineEvent = function(_evtName, _logicFn)
   {
      pseudoEvents[_evtName] = _logicFn;
   };

   
   // Helper Functions
   function storeHandler(_key, _handler)
   {
      evtHash[_key] = _handler;
   }
   
   function retrieveHandler(_key)
   {
      return evtHash[_key];
   }
   
   function generateHandlerKey(_elem, _evtName, _handler)
   {
      return '{' + getObjectGUID(_elem) + '/' + _evtName + '/' + getObjectGUID(_handler) + '}'
   }
   
   function isAnAncestorOf(_ancestor, _descendant, _generation)
   {
      if (_ancestor === _descendant) { return false; }
      
      var gen = 0;
      while (_descendant && _descendant != _ancestor)
      {
         gen++;
         _descendant = _descendant.parentNode;
      }
      
      _generation = _generation || gen;
      return _descendant === _ancestor && _generation === gen;    
   }
   
   function mouseEnter(_fn)
   { 
      var key = xb.Helper.getObjectGUID(_fn);
      var f = evtHash[key];
      if (typeof f === 'undefined')
      {
         f = evtHash[key] = function(_evt)
         {
            var relTarget = _evt.relatedTarget;
            if (this === relTarget || isAnAncestorOf(this, relTarget)) { return; }
      
            _fn.call(this, _evt);
         };
      }
      return f;   
   }
   
   function getObjectGUID(_elem)
   {
      if (_elem === window)
      {
         return 'theWindow';
      }
      else if (_elem === document)
      {
         return 'theDocument';
      }
      else if (typeof _elem.uniqueID !== 'undefined')
      {
         return _elem.uniqueID;
      }

      var ex = '__$$GUID$$__';
      if (typeof _elem[ex] === 'undefined')
      {
         _elem[ex] = ex + GUIDCounter++;
      }
      return _elem[ex];
   }

})();
 
The code above, as is, won't work "out of the box" because (for the sake of brevity) I have not included the xb.removeEvent(..) function. Fear not however. There will be a link to a download of the full source code, complete with both xb.addEvent(..) and xb.removeEvent(..) at the end of this post.

Commentary

So some of you may be wondering: "Why another addEvent function. Haven't we been through this?" We have, but I think you'll find that this version does more than any other addEvent function you've seen. For example:

  • Works in all browsers that matter
  • Ensures one event wire up for any given element/event/handler combination (this is mostly for IE)
  • Forces IE to honor the this keyword from within event handler functions
  • Normalizes the wire up mechanism in all browsers (no need to include the "on" prefix for IE)
  • Forces IE to recognize the following properties/methods on event objects: .stopPropagation(), .preventDefault(), .target, .relatedTarget
  • Enhances Non-IE browsers to support mouseenter and mouseleave events
  • Provides an extension mechanism so developers can write their own custom events that plug right in ('mousewheel' or 'DOMContentReady' for example)

Given all that the Ultimate addEvent function does, it's not surprising that it has a bit of length to it. But it isn't super long, and I think it's well worth it.

Usage

Using the function(s) is just as easy as you'd expect:

var myDiv = document.getElementById('myDiv');
xb.addEvent(myDiv, 'click', clickHandler);

function clickHandler(e)




{
   alert('The this keywords works (even in IE!): ' + this.id);
}

Extending Functionality

Since I mentioned that it was possible to extend the Ultimate addEvent function with custom events that plug right in, I figure I'd better offer an example. Actually, there already is an example built right into it. Both the mouseenter and mouseleave events utilize the extension mechanism internally, but for demonstration purposes, let's go ahead and add a mousewheel event:

// Extend the Ultimate addEvent function to recognize a "mousewheel" event
xb.defineEvent('mousewheel', function(_fn, _useCapture, _listening)
{
   // event name for IE, Opera and Safari
   var evtName = 'mousewheel';

   // hander for IE, Opera, and Safari
   var f = _fn;
   
   // if we're dealing with a Gecko browser, the event name
   // and handler need some adjustment
   var ua = navigator.userAgent.toLowerCase();
   if (ua.indexOf('khtml') === -1 && ua.indexOf('gecko') !== -1)
   {
      evtName = 'DOMMouseScroll';
      f = mouseWheel(_fn);
   }

   // _listening represents whether this is an event attachment or detachment
   // that 5th parameter?  Don't worry about it; just always use false
   _listening ? xb.addEvent(this, evtName, f, _useCapture, false) : xb.removeEvent(this, evtName, f, _useCapture, false);
});

// Helper function for dealing with mousewheel in Gecko browsers
function mouseWheel(_fn)
{
   var key = xb.Helper.getObjectGUID(_fn);
   var f = xb.Helper.retrieveHandler(key);
   if (typeof f === 'undefined')
   {
      f = function(_evt)
      {
         _evt.wheelDelta = -(_evt.detail);
         _fn.call(this, _evt);
         _evt.wheelDelta = null;
      };
      xb.Helper.storeHandler(key, f);
   }
   return f;
}

I'm glossing over some details here because I don't want this post to get bogged down in something that it isn't really about, but I trust you get the idea.

Most of this code actually comes from the The Gimme Javascript Library. If you're using Gimme in any of your web pages, you already have all of this functionality for free. The syntax is a touch different, but all the capabilities are the same.

And if you happen to be the author of a Live Maps Mashup, you already have Gimme, as the latest version shipped with the most recent Virtual Earth MapControl.

Complete Source

As promised, here is the complete source, including both xb.addEvent(..) and xb.removeEvent(..)

Enjoy! And please don't hesitate to send your feedback, both good and bad (I'm very willing to address issues or try to make requested enhancements).