I’ve been thinking quite a bit lately about how Webmaker can take advantage of the work being done on Web Components and Custom Elements. I tasked Pomax with doing some research and prototyping, and the results have been encouraging. I wanted to say something about my current thinking and what we might do.
One of the successes we had with Popcorn.js was that it became really easy to create plugins that could take care of the complexities of working with third-party APIs and showing web content dynamically, and linearly in time based on media resources. Consider the Google Map plugin, which allows one to specify a location, map type, etc. and have a map dynamically load within the provided container div:
var p = Popcorn( "#video" )
.googlemap({
start: 5,
end: 15,
type: "ROADMAP",
target: "map",
lat: 43.665429,
lng: -79.403323
});
We’ve seen people make all kinds of plugins to simplify the use of more complex APIs like this. Often it means dynamically loading some script, setting up a div or iframe, adding an element with a particular class name or id, and applying some styles.
There are a few things I’ve always wanted to improve about it, though. First, how to properly combine a bunch of styles with a plugin. Currently a plugin like the googlemap one is just JavaScript. In reality, you almost always want a mix of JS and CSS, and doing CSS in script is not ideal; nor is having to manage the loading of two files per plugin (*.js, *.css). A second issue is that these plugins are tightly bound to Popcorn, which is fine if you’re time-based experiences, but not so good for a normal web page.
With custom elements, we can solve a lot of these problems. First, a custom element is a simple HTML file containing the definition of a new element, any associated styles, and scripts. I use it in my page by loading it via a link:
<link rel="component" href="webmaker-components.html">
I love the simplicity of this method of packaging and loading new elements. This file can include one ore more new elements, making it possible to do some server-side bundling for dynamic builds–imagine loading components a, b, c, and d via http://components.webmaker.org?c=a,b,c,d.
Now in your markup it’s possible to take our Google map from above, and rewrite it like so:
<webmaker-map start="5" end="15" location="Maruyama Zoo"> </webmaker-map>
Here content attributes on the custom webmaker-map element provide a way to indicate start and end times, and a location to pass thorugh to Google’s API. However, while I can specify timing info, I can also leave it off, indicating that the map should always be visible:
<webmaker-map location="Maruyama Zoo"></webmaker-map>
By moving the functionality of the Google Map plugin to a custom element, we’ve made it possible for it to be used in any web context or tool.
You can see this in action in Pomax’s demo page: first with timing info, second without as a static web page. View the source of both pages. First off, notice how little code there is, and more, how it’s all markup vs. script. You might be wondering why this works at all, since browser vendors are still defining and implementing the spec. You’ll see that this uses a polyfill to give us the ability to play with things now.
This model of providing functional-units to authors is also exciting in the way it lets us mix and match depending on the needs of the individual. For example, lets say you want to add comments to your page. One option would be to use Facebook’s comments plugin, another would be to use Disqus’s embed. Both can be wrapped into custom elements, and users can choose. I did just that for Facebook’s comments: code (view source) and demo (scroll to the bottom). Here I use
<facebook-comments></facebook-comments>
to add the functionality I want. No scripting of any kind, which means that this becomes accessible to so many more web makers, for whom coding is beyond their reach. Whenever we can reduce complexity like this, we should do it.
I think moving toward HTML-based custom elements vs. script-only plugins is going to make a huge difference. It’s going to mean that it’s easy to integrate with existing tools and workflows, easy to find and use them (they are just web pages, after all), and most of all, easier for non-devs to use all these amazing APIs and services, which require coding.
Pomax and Matt have already started work to convert Popcorn Maker to use this, and are making good progress. I’m looking forward to building more pieces of the Webmaker tools and gallery infrastructure using these same methods, and I’ll write more about or progress later when I have something to show.




Thought experiment: letting git normalize whitespace
I’m working across a lot of different repos these days, and while fixing a whitespace issue in one of my patches, I wondered if it would be possible to eliminate this altogether.
Working with git, we already have a version of what I want in terms of
core.autocrlf. You wrote this patch on Windows, I’m on OS X, and our server is Linux? No problem, we’ll just use Unix EOLs and have git automatically manage the line endings whenever we checkout or commit. In other words, when I checkout the code locally, I get a version of it customized to my environment. There’s a canonical version that git will store, but every developer can have something different in their editor.Now let’s go one step further. Imagine you need to add the following code, as I did today:
module.exports = function( req, res ) { res.json({ http: "okay" }); };How many arguments can you have about how to style that code? Come on, what would you r- in this? “Dave, no space between `(` and `req` please;” “Dave, you need to indent with 4-spaces not 2;” “Dave, you should just put that `res.json` all on one line.”
The truth is, there’s no right answer here. Of course there are famous examples of automatic semi-colon insertion causing havoc (
`return\n{`vs.`return {`), but let’s stick with my example code for a minute. Could we let git manage the whitespace here? Could we, in other words, take that code above, and when I commit, actually store this:module.exports=function(req,res){res.json({http:"okay"});};Now imagine that I’ve got a .gitstyle file in my tree, or I’ve somehow specified config options globally, and I can tell git how to style this code again when I check it out. Imagine you like 8-space indents and I like 2-spaces; imagine you’re allergic to spaces around arguments, and I love them; imagine your OCD demands that all variable declarations line up on the equal sign, and I’m happy to let them wind their way down my editor like a raindrop on a window. And, imagine we can both do what we like with the same code in the same tree! Imagine there’s no style guide, it’s easy if you try…
BUT DAVE, THIS CAN’T WORK BECAUSE <strong-reason />!!! Sure, there’s all sorts of things to work out. This is a thought experiment. I’m supposed to be grading final assignments right now, and I needed to procrastinate. But if this could work, it would be so, so useful!
Patches accepted (please use 2-space indents).