Factmint Charts WordPress plugin

We, at Factmint, have just released a WordPress plugin to create data visualizations in a WordPress blog. So, I thought I’s give it a go:

Top ten countries by GDP

source wikipedia

Country GDP
United States 16768100
China 9181204
Japan 4898532
Germany 3730261
France 2678455
United Kingdom 2267456
Brazil 2243854
Italy 2149485
Russia 2096774
India 2047811

The plugin is here, if people are interested.

Shadow DOM: encapsulation for semantic markup

There was a post on CSS-Tricks recently about SVG icons vs font icons. One of the criteria for judgement was semantics (is an or tag better than a inline symbols or :before pseudo class?) Another post on the same site discussed events and targets with inline SVG.

For me, both the issue of semantics and difficulties of handling complex DOM (i.e. the event target problem) are part of the broader topic of encapsulation. That is, you (probably) don’t really want to use SVG to create a button, you just want a button that looks like a filing cabinet icon. Let me expand upon that:

If you want a button that allows the user to select a file the obvious starting point would be a form input:



file type input

file type input, rendered in Chrome

This has a number of merits:

  • It’s simple
  • It’s semantically very accurate, as it allows input of type file
  • The browser does the hard work

The last point is particularly important; as is, with no JavaScript, the browser will render a button, when a user clicks the button a file-system explorer will open and when an enclosing form is posted the reference to the file will be set correctly.

So, now you decide you want to use an icon (this oneĀ http://iconmonstr.com/archive-7-icon/) instead of the boring “Choose file” button. How might one go about that? Well, it’s not as simple as adding an image inside the input tag: inputs are void elements so cannot have children. You could just use an img tag and maybe give it a sensible class:



That would look fine but you would definitely have less semantic code and you would need to implement all of the file input functionality yourself (or hack it).

There is a better solution (at least there will be when support improves): Shadow DOM. Shadow DOM, for those who don’t know, allows encapsulation through “functional boundaries in a document tree”. What does that mean? Well, in our example, it would allow us to encapsulate the DOM tree for the nice looking SVG icon (and other stuff if we wanted) as a kind of widget which we can inject into our page under another element – in this case an input – without changing the functionality or semantics of that element.

Consider this simple case:


var button = document.querySelector('input[type="file"]');
var shadowDom = button.webkitCreateShadowRoot();
shadowDom.innerHTML = "<div>Hello from the other side</div>";

See the Pen gHEei by chrismichaelscott (@chrismichaelscott) on CodePen.

It might, upon first glance, appear to be a long winded way of changing some HTML but that isn’t what has happened. If you were to inspect element the input would still be an input, no sign of a div at all. More importantly, if you click on the message a file-system explorer dialogue opens; if you post a form the attachment is set. So what happened, then?

The shadowDom variable in the JavaScript is the point of separation, the “functional boundary”. From the outside, you still have an input, you’ve not changed that at all. However, because we set the inner HTML of the shadow root the browser knows that there is more underneath, and renders that content.

Let’s go back to the icon we want to use for our file input. We can now use the shadow DOM to make a file input render like an image:

var button = document.querySelector('input[type="file"]');
var shadowDom = button.webkitCreateShadowRoot();
shadowDom.innerHTML = "<img src="https://s3-eu-west-1.amazonaws.com/chrisscott/codepen/iconmonstr-archive-7-icon.svg" alt="Select file"></img>";

See the Pen jiqoh by chrismichaelscott (@chrismichaelscott) on CodePen.

Pretty cool, but we can make this much nicer to look at – both from a user’s perspective and the code. Remember that Shadow DOM is a form of encapsulation: so CSS defined for the document cannot affect the encapsulated tree (this is one of the main reasons for Shadow DOM but a different discussion). So how can one style the Shadow DOM? HTML5 allows us to define template elements. These elements are not rendered but the parts of the DOM tree under them can be used as templates. If we define a template we can include a style tag within it. Then, the entire content of the template can be used to define the Shadow DOM. Also, for cleanliness, the template can be defined in the head and kept out of the way:

var buttons = document.querySelectorAll('input[type="file"]');
var fileButtonTemplate = document.getElementById("file-button-template");
for (var x = 0; x < buttons.length; x++) {
  var shadowRoot = buttons[x].webkitCreateShadowRoot();
  shadowRoot.appendChild(fileButtonTemplate.content);
}

See the Pen jghes by chrismichaelscott (@chrismichaelscott) on CodePen.

So that’s it! A nice looking scalable vector icon which has all of the functionality of a native file input, is completely semantic and doesn’t feature transparent inputs absolutely positioned over styled content.

Graceful Degradation

Fortunately, Shadow DOM (used in this way, at least) degrades really nicely. The JavaScript could be improved to catch exceptions but functionally this should play well with older (not bleeding edge) browsers. That is, if the browser doesn’t support element.createShadowRoot() then nothing happens, the old file input is left as is. In fact, this is arguably better than using an SVG icon straight up as SVG isn’t supported by older browsers (IE 8 and backwards) and an SVG tag will not degrade nicely.

3D Rendering to SVG

I was on holiday last week, in the Sierra Nevada mountains in Andalusia, Spain. Some people like to read books on holiday, I undertake projects. So, as I was sitting by the pool, I developed a 3D rendering engine in Javascript. Each to their own, hey?

I’d been thinking about this for a little while. A rendering engine was an enticing project and I anticipated some interesting complexities. I had decided that I would use SVG as the medium. As with 2D drawings, HTML5 Canvas seems to get all the attention for 3D drawings (WebGL) but, in both cases, there are pros and cons of each technology. Notable reasons for choosing SVG may be:

  • As SVG is vector based it will be very fast for simple drawings that are animated (as, from a Javascript point of view, you only need move points, not redraw the canvas)
  • If you need to interact with the components, SVG elements natively support mouse events (like mouseover)

So, first off, here’s the result. I’ll explain how it works afterwards.

Use cases

As mentioned above, there are a number of good reasons to use a vector drawing. A use case which immediately springs to mind is architectural drawings. The drawings need not be vastly complex, certainly in terms of fairly regular shapes and textures. Also, a developer could add interactive elements to an application so that hovering over a wall or joist would show you the materials, etc. That would be much more difficult with WebGL or similar as the hover events aren’t there to help.

How it works

The maths behind the engine is fairly simple but quite fun. First, a camera is created, which consists of a point in space and a rectangular plane at some point in front of it. The plane is, in effect, the lens of the camera and I refer to the point as the origin. Then, to plot a point the following algorithm is ran:

  1. A vector is constructed from the point being plotted to the camera’s origin
  2. The point that the vector intercepts the lens is calculated
  3. The intercept point is converted into a 2D co-ordinate, relative to the lens
  4. That co-ordinate is scaled up to the screen and a point is plotted there

So, to draw a plane one merely needs to convert four points in space to be four co-ordinates on screen, then an SVG path can be used to join the dots.

A bit more detail

The interesting part of this project is projecting the point to be plotted onto the lens. I had an idea of how this would work: I wanted to exploit the fact that the dot-product of two vectors at a right angle is always 0. Moreover, a decrease in the dot product implies that the angle is closer to a right angle.

So, take any two points on the lens, La and Lb, which could be corners and a second vector, v, from the camera origin to the point being plotted; then, there exists some λ which minimizes α:

LaLbLaλv=α

Pictorially, that is:

Therefore, λ minimizes α as λ v approaches the intersect between v and the lens plane. To find the value of λ I simply implemented a “split the difference” algorithm. That is, try λ equal to 0.5; is that better than λ equal to 1? Then try 0.25 and 0.75, which is best? Ect, ect.

Once you have the vector λ v it is quite easy to map the point onto the screen using a bit of trig’ and some vector maths. Then you’re there. If you want more details, best check out the code on my Github page.

The future of the project

This was never meant to be a production library, just a proof of concept. I think that a robust SVG-based rendering engine could have a number of sound use cases but it would take a lot more time than I have available to get to the point where this could be used in production. A number of challenges, just off the top of my head, include:

  • textures – difficult to transform in 3D if you’re using SVG
  • lighting – this could be implemented using dot products between the normal of the plane and a vector from the plane’s centre to a point of light
  • z-index of polygons – i.e. if the example above were opaque, the closest planes should be visible above the farthest ones.

I’d love to know what other people think and if there is any work in this direction already…

Filter Effects for Raphael

I’ve been working lately on an extension to Raphael.js which lets you quickly add Filter Effects – something which I’ve wanted to see in Raphael for a long time. I’m not going to do a big write up just yet but here’s an example of what’s on offer:

You can find out about the project on it’s homepage.

About me

Contrary to the massive "Chris Scott" at the top of the page, I'm not a (complete) ego-maniac. I just liked the font and couldn't think of anything more interesting to say.

I'm a passionate developer and entrepreneur. My company Factmint provides an elastic RDF triplestore and a suite of Data Visualization tools, so I largely talk about those things.

Fork me on GitHub

GitHub Octocat

chrismichaelscott @ GitHub

  • Status updating...