Tag Soup: Using Custom Elements to Cover Elections and Beyond
What We Learned Testing Custom Elements in a News App
An election results board is in many ways the purest test for a news app: it combines a high-traffic, high-pressure breaking news page with the challenge of scraping data feeds from a range of sources (some well-organized, many much less so). Nobody in the Seattle Times newsroom was happier, or more relieved, when our results page performed almost flawlessly on election night. A brand-new Node-based application built on our news app template, it pulled results from the Washington Secretary of State and King County, parsed and merged them, then uploaded the results as static pages to Amazon S3.
I was relieved because there was always a worry that something would go wrong with the feeds or the build process, but also because our election page served as a testbed for custom elements in a news app. Part of an upcoming platform feature called Web Components, custom elements let developers define their own HTML tags, with complex behavior and lifecycle. I’d used them before as a part of an embedded web UI framework , but not on a general-public site. Based on our experience, I’m extremely excited about their potential. To see why, let’s take a quick tour of the Web Component concept, then look at how we leveraged them for the Seattle Times election results page, before seeing how they make it easy to create reusable and sharable newsroom tools.
A Brief Primer on Web Components
The Web Components spec attempts to achieve this by providing four new “building blocks:”
document.registerElement(), which creates new tags and extends existing tags with new features,
- Shadow DOM, which hides the internal structure of those elements from external styles and scripts,
<template>for stamping out fresh copies of HTML in each component, and
- HTML Imports, which provide a better mechanism for loading all the required resources.
Using the Web Component platform APIs, it’s possible to bundle up a complicated unit of functionality into a single declarative element, just like any other HTML tag. In many cases, browser developers have already been using these same tools, and they’re just exposing them to users: the
date input in Chrome and the
Google has a purpose-built component library called Polymer for this process, but it’s only available for IE10 and up, and our minimum-supported browser is IE9. So for creating custom elements at the Seattle Times, I set up an alternative scaffolding that only directly shims the
document.registerElement() method using Andrea Giammarchi’s library. For the other parts of the spec, we provide functional alternatives: ICanHaz.JS or Dot for templating, LESS for isolating element styles, and a Grunt build process for bundling all the dependencies up into a single package.
Our Savage Elements
As a committed front-end developer, I often shrug off complaints from other developers about the vagaries of HTML and CSS, but when it comes to SVG, I suspect I know how they feel. My experiences with it have been capricious and inconsistent from browser to browser (I’m probably doing something wrong). Still, for election maps SVG images are probably still the best option, so I decided to wrap them in a custom element that would contain and control their oddities, along with a small library (named Savage) for papering over the cracks in the SVG API.
If you view the source for our results page, you’ll notice the maps embedded for statewide races and ballot measures are contained in an unfamiliar element:
<svg-map>. Loading an SVG into the page is as easy as setting the
eachPath() attach to this promise to perform asynchronous rendering, such as when results are added to the state map.
In the source, you’ll also notice that the innards of some of our
<svg-map> elements are Handlebars templates, but these don’t appear directly in the output—what’s up with that? When an element is created for the first time, the component parses its
onhover method feeds data back to the template in response to the hover event.
I’ve enjoyed using custom elements in this project as a developer, but I think the real value comes from the way that they package up a discrete piece of UI in a way that can be used equally well by coders and non-coders in a newsroom. As a proof of concept, we’ve developed
<responsive-frame>, an alternative to the Pym.js library created by NPR. Pym is a great library, and we rely on it often (we’ve even published our own branch of it for bugfixes), but even as minimal as it is, its configuration burden is relatively high for non-coders: the parent page alone requires a placeholder div, a script import, and a configuration script that calls the Pym constructor with an ID and a URL. I think it can be made easier with web components. Using our custom element, embedding a child page is as simple as including the registration script and then writing:
On the other side, the child page can declare any element as the “container” for embedded content by using the
<responsive-child> element, or even just adding an
is attribute to extend an existing element. For example, we can target the
<body> of the child page this way:
That’s all the configuration needed! When the elements start up on each side of the embed, they negotiate a unique ID for each iframe, and then send messages across the boundary using a JSON-based protocol when either window is resized.
If you’d like to experiment with our responsive frame, you can take a look at the source code here, or install it from Bower as
component-responsive-frame. We’ve also used these new elements in our newest investigative piece, Sell Block.
A Call for Wider Adoption
<landline-map>, for example, or a
If you’re working on a newsroom tool that you think you might re-use, or open-source for others, I’d like to advocate for going the Web Component route. It’s not just something that we’re using at The Seattle Times: Google is pushing hard for Polymer-based components at this year’s Chrome Dev Summit, and Mozilla is using them with its Brick library in Firefox OS.
If you’re interested in getting started, feel free to build on our component template, which provides a framework for building elements and packaging them up for external use. We’d love to hear about projects that you build with it, or any bugs you might find!
Thomas Wilburn is a news developer for The Seattle Times.