barryvan

Archive for the ‘Javascript’ category

Web Directions 2014 Reflections

I’ve just returned from Web Directions 2014 in Sydney. Overall, it was a great experience, with some valuable take-aways. I’ve jotted down a few of my thoughts around the conference — and a few specific sessions — below. These are my “notes from notes” — I’ve drawn ideas from the notes I took during the conference to consolidate my understandings of the presentations.

This is very much non-exhaustive — I’ve elided a lot of stuff, skipped over whole talks (either because I want to ponder them further, or because I didn’t take notes or my notes are useless). I’ve focussed primarily on the technical talks, as I’ll use this post as a reference for myself on these areas at work. If I get a chance, I’ll write up my thoughts on the keynotes as well.

Emily Nakashima: The Operable front-end

@eanakashima

Emily, who works at GitHub, outlined exactly what “operability” is, and outlined some ways of achieving it.

Operability requires strategies for deployment, logging, monitoring, debugging, alerting, and scaling in production. That is, it’s the ability to detect, diagnose, and rectify problems, with the ability to push fixes into production. It’s important, therefore, to use dashboards and automation to ensure that everything that happens after a fix is ready to ship is as smooth and streamlined as possible.

Aside: if you fix a bug, you should look for similar error reports from other users. You’re now the expert in that bug, and are best-placed to respond. This ties in well with SEQTA’s, and my own, philosophy that developers should always always always be in a position to talk to clients, and doing so should be a routine part of their job.

JavaScript error monitoring is one of the most important pieces of the operability puzzle. A great idea is to add a listener for the error event on the window, which collects up various bits and pieces (URL, stack trace, time since load, event target — inc. xpath or CSS selector) and shoots them off to the server via AJAX. (Of course, you want to be careful not to try and send errors about your inability to send errors…) To make this really shine, stop swallowing errors (even though many frameworks advertise this as a “feature”) — in fact, make your own error classes and throw them!

Performance metrics are another part of the jigsaw. They can be synthetic (that is, measured in a carefully-controlled environment), or RUM (real-user metrics). Synthetic metrics should be part of the CI infrastructure; they’re primary utility is to catch performance regressions. RUM are arguably more useful, and should be tied to monitoring and alerts. RUM can be collected using the shiny new navigation timing API — but for single page applications (like the SEQTA Suite), you’ll need to record your own metrics — window.performance.mark and window.performance.measure APIs come in useful. An API which hasn’t yet landed — but is coming soon! — is the frame-timing API, which will help to catch jank issues (jank is where the framerate drops below 60fps).

Accessibility is often the “poor cousin”, often because it’s really hard to audit in tests or post-commit hooks etc. Emily has found that scanning the live DOM for accessibility issues, and throwing exceptions (to be caught in window.onerror) is a great way to check for these issues in live, dynamically-generated content. You’re looking for things like missing alt tags, or buttons without text content.

Useful tools:

  • New Relic
  • Errorception
  • Raygun
  • LogNormal
  • Google Analytics
  • Circonus
  • Whatever ops is using :)

Sarah Mei: Unpacking technical decisions

@sarahmei

Conway’s law:

organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations

Eric Raymond’s retelling:

If you have four groups working on a compiler, you’ll get a four-pass compiler.

Takeaway: most of the data we look at when considering a project is social, not technical data.

Mark Dalgleish: A state of change

@markdalgleish

Mark outlined the new Object.observe capabilities in ES6, which lets you track mutations on an object. The main thrust of his talk, though, was about mutability vs. immutability. Traditionally, functional languages have favoured immutable data-structures, as they’re easier to reason about and work with. Lots of JS frameworks are now moving towards representing the state of the application in a series of (immutable) objects; theoretically, this allows you to treat the DOM as a renderer doing its thing somewhere else — and therefore never actually pull anything out of it.

I sent Mark a couple of tweets about using Object.observe to “fake” immutability (and avoid using massive chunks of memory and causing GC pauses), and caught up with him after the talk to discuss this a bit further. Mark noted that he’d also wondered this, but hadn’t yet had a road-to-Damascus epiphany. We chatted about the fact that if the browser (or the DOM) were to introduce truly immutable data-structures, it could then become the engine’s problem to optimise memory — and the engine could do this much more easily than could be done in JS, and more efficiently, too.

Sarah Maddox: Bitrot in the documentation

@sarahmaddox

Technical documentation inevitably suffers from broken links, outdated information, pure fiction, and information overload — caused by changes to the environment, updates to the documentation platform, last-minute changes to the software being documented, and plain-old human error (which, strictly speaking, encompasses all of the above). Sarah outlined some ways of overcoming this:

  • Automated testing of code samples, to detect breakages in the samples, but also breaking changes in the API.
  • Doc reviews in the engineering team’s procedures — that is, making the definition of “done” include documentation. To facilitate this, use the same issue tracker, same review tools, and include the technical writers in the code reviews.
  • Collaborative spot testing sessions.

Jeremiah Lee: Elements of API excellence

@jeremiahlee

The single most important point that Jeremiah made (in my view) was that APIs are built for human beings, and that they should therefore be treated as a UX problem. In other words, if you want to build good APIs, you need to understand the people who will use those APIs.

An excellent API should therefore be:

  • Functional: it should do what it says on the tin;
  • Reliable: it should be available, scalable, stable, and secure;
  • Usable: it should be intuitive, testable, and provide corrective guidance; and
  • Pleasurable: the API should become the means by which great things can be done.

To build excellent APIs that have, at their foundation, a really solid UX, we should make use of the same tools used by graphical UX work. One of these tools is the concept of “personas”. A persona is a descriptive representation of the people who will use the product — and the context in which they operate. By constructing personas, we make visible our assumptions about our users, and provide a frame of reference for the entire team. Personas should, of course, be validated and built around user interviews and surveys — that is, real people.

There are some key aspects of the people who will use our APIs that need to play into the personas we build:

  • Their relationship with the product;
  • The platform and programming language they’re working in;
  • Their experience and skill level;
  • Their English proficiency;
  • The motivation behind the integration work they’re doing;
  • The resources they have available; and
  • Their role within their organisation.

Ensuring that the APIs we build actually do work, and are usable, we need to undertake testing. We should test both passively and actively.

Passive testing involves looking at pieces of data such as support requests, and answering questions like “where are users asking for help?”, “what concepts are frequently misunderstood?”, and “what errors are hit often?”. We should look at API usage during an integration, extracting data such as the time between app registration and first request, the first requests and errors encountered, and the time between start of integration and production. We should also look at API usage after integration to find out information about which endpoints are actually used, and how — this will help to answer questions around what the integration is trying to achieve. It also makes it easier to track down antipattern usage of the API.

Active testing is, by its nature, going to be used more infrequently. For existing APIs, you can take the “dumb pair programmer” approach — basically, go sit with someone working against the API and silently observe what they’re doing. Look for things like interactions with their team (how do they talk about us?), how we fit into their application, how they approach the integration, what problems they encounter (and how they go about solving those), and how they test the integration.

For new APIs, we can build throw-away prototypes, or a mock API (a simple façade over an existing API, or a fully-mocked API). In either case, there should be just enough functionality to be useful, and it should be fully-documented. Put together a well-defined project, ready for an integration, and get an outsider (who lacks insider assumptions) to build the project. You can go to the extent of recording their face and the screen as they work to see how they react; alternatively, or additionally, have them commit their work regularly (every 10m or so) so that it can be tracked. This allows you to then track emotional responses, and see how long tasks took to complete. It also helps to see where the process can be made more affirming, and how errors can better be handled.

The secret to machines talking to machines is to speak human first.

API versioning was brought up in the questions afterwards, and Jeremiah noted his repugnance for such schemes. A recommendation he had, though, was to maintain the two versions for a period of time, and allow developers to “opt in” to the new version when they’re ready: this is the approach taken by Facebook.

Determining a table cell’s x and y position/index

When working with HTML tables, we often want to extract the column and row index for a particular cell. Easy enough, surely — just use row.rowIndex and cell.colIndex, right? Well, no.

The spanner in the works

…is the presence of cells that span rows or columns (apologies for the terrible pun). For example, in the following table:

a b c d
e f g
h i j
k l m n

the column index of cell “g” is reported by the browser to be 2 — when in fact it should be 4!

The solution

Fortunately, there is a solution. The code below is based on this very old example by Matt Kruse. I updated it, tidied it up, and MooTools-ified it.

Usage

Simply call “getCellCoords” on the (header) cell you’re interested in. This will return an object containing “x” and “y” members — the column and row index, respectively.

The code

You can also grab this gist.

Element.implement({
	getCellCoords: function() {
		if (this.get('tag') !== 'td' && this.get('tag') !== 'th') return null;
		
		var result = {};
		
		// The y-coord is simply the number of <tr> elements that precede our parent, plus our parent.
		result.y = this.getParent('tr').getAllPrevious('tr').length;
		
/* 	The x-coord is a little more difficult. We can't simply count up the number of preceding cells:
		
	+----------+-------------+
	| (a)      | (b)         |
	+          +------+------+
	|          | (c)  | (d)  |
	+          |      +------+
	|          |      | (e)  |
	+----------+------+------+
	
To get the x coord of cell (e), we need to include cells (a) and (c), but they're not in the same row as us. We also can't just use the first row, as it may have horizontally-spanned elements included.
	
Thus this rather complex looking bit of code. Basically, we build a map of the table in memory, so that we can then "read off" the location of the cell. We short-circuit when we process "this", though.
	
See also comments on http://bytes.com/topic/javascript/answers/519470-misleading-cellindex-values-rowspan-colspan and source of http://www.javascripttoolbox.com/temp/table_cellindex.html .
*/
		
		var rows = this.getParents('tr !> thead > tr'),
				matrix = [],
				row = null,
				cells = null,
				cell = null,
				colspan = null,
				rowspan = null,
				rowIndex = null,
				colIndex = null;
		
		result.x = null;
		for (var i = 0; i < rows.length && result.x === null; i++) {
			matrix[i] = matrix[i] || [];
			row = rows[i];
			cells = row.getChildren('td, th');
			
			for (var j = 0; j < cells.length && result.x === null; j++) {
				cell = cells[j];
				colspan = cell.get('colspan') || 1;
				rowspan = cell.get('rowspan') || 1;
				
				rowIndex = row.rowIndex;
				matrix[rowIndex] = matrix[rowIndex] || [];
				
				colIndex = null;
				for (var l = 0; l <= matrix[rowIndex].length && colIndex === null; l++) {
					if (!matrix[rowIndex][l]) colIndex = l;
				}
				
				if (cell === this) { // Short circuit if possible.
					result.x = colIndex;
					break;
				}
				
				for (var k = rowIndex; k < rowIndex + rowspan; k++) {
					for (var l = colIndex; l < colIndex + colspan; l++) {
						matrix[k] = matrix[k] || [];
						matrix[k][l] = 1;
					}
				}
			}
		}
		
		return result;
	}
});

TrackPerformer step-by-step

I’ve had a request to put together a guide explaining exactly how to build a performance using TrackPerformer. This post will walk you through the process, from preparation to presentation.

Please note that this guide assumes you are working with an Impulse Tracker or OpenMPT module; if you are not, you will have a bit more work to do.

Ingredients

To build your performance, you will need the following items:

  • The original module file (IT or MPTM format)
  • The exported audio file (preferably in OGG, MP3, and M4A formats, for maximum cross-browser compatibility)
  • A copy of the ModReader source (which you can download from GitHub)
  • A copy of the TrackPerformer source (which you can also download from GitHub)
  • A decent plain text editor (not Word) — I recommed Komodo IDE or Komodo Edit.
  • A recent and decent web browser — Firefox, Chrome, or Opera work best.

With these in hand, you’re ready to get going!

Method

1. Set up

If you haven’t already, extract TrackPerformer to the folder of your choice. When you do so, you’ll notice that there are several sub-directories: “Examples”, “Source”, and “Utilities”. Create a new directory, called “Performances”.

Copy the file “template.html” from the “Examples” directory, renaming it to the name of your track.

Next, copy your exported audio files into the “Performances” directory; ensure that they all have the same file name (bar the extension).

Create a new, blank file, with a “.js” extension and named the same as your track. Load this file in your editor.

Finally, load the HTML file in your editor, and add a <script> tag just before the closing </head> tag that references your JS file. For example, if your JS file was named “purple.js”, you would type:

<script type="text/javascript" src="purple.js"></script>

 2. Conversion

The next step is to convert your file into a format that TrackPerformer understands. This means noting down when every note is played, and by which instrument. It also means extracting information such as the tempo, time signature, and song title.Fortunately, if you’re using an IT or MPTM module, the ModReader utility is able to perform this (rather tedious) step for you.

If you are not using a format that ModReader is able to convert, you will need to complete this step manually. If your file can be opened in OpenMPT, it is possible to use a JavaScript macro in Komodo IDE/Edit to facilitate this; otherwise, you will need to craft the entire lot by hand.

If you have not already done so, extract the ModReader zip file to a suitable location. Then, in your web browser, load the “index.html” file from that location.

Select the file you would like to convert. Note that ModReader does all of its processing on your computer — it doesn’t send your file anywhere, and won’t change its contents, either.

All going according to plan, there should now be a lot more text on-screen. Copy everything between the dashed lines (not including the lines), and paste it into your performance’s JS file. This is the TrackPerformer-compatible version of your module,in a format known as JSON.

3. Write some JavaScript

As I said earlier, ModReader gives you a JSON representation of your track, which is great. However, we need to now pass this representation through to TrackPerformer. To do this, we need to write some JavaScript to go around this JSON representation. Edit your JS file so that it looks something like this:

window.addEvent('domready', function() {
	var controller = window.controller = new barryvan.tp.Controller({
		background: 'rgba(230,230,230,0.5)',
		meta: {
			colour: 'rgba(0,0,0,0.5)',
			visible: false
		}
	}, $('container') || document.body);
	controller.perform({
		title: 'Foo bar baz'
		/* the rest of the track... */
	});
});

What we’re doing here is creating a new Controller, and telling it to perform the track.

4. Make some noise

The next step is to point TrackPerformer at the MP3, OGG, and M4A exports of the music. To do this, find the line in your JS file that reads

"audio": ""

. In the empty quotes, put in the filename of your audio (without any extension). If your audio is on the web, put in the full URL (again, without the extension). Your JS file will now look something like this:

{
	/* snip */
	"audio": "mice"
	/* snip */
}

Now, load up your HTML file in your web browser. You should be able to listen to your track. Next up, we’ll add a performer.

5. Add a performer

Each instrument in your piece can have zero or more performers assigned to it. There are a variety of performers that you can use, each of which offers a unique visual representation of your music. Each performer has a variety of options which affect its function and appearance. These include colour, size, position, vitality, and many others.

Each performer is defined in a code block that looks something like this:

{
	performer: barryvan.tp.performer.Oscillator,
	options: {
		colour: '#f00',
		stepSize: 10,
		sustain: true,
		middle: 58
	}
}

The block above means that we want an Oscillator (performer: barryvan.tp.performer.Oscillator). We have set some of its options (options: { … }) such that it is bright red (colour: ‘#f00′), that a semitone is 10 pixels in size (stepSize: 10), and that its middle note (vertically centred in the performance) is 58 (middle: 58), or A#4.

If you look at your JS file, you should see a section labelled “instruments”, which will look something like this:

"instruments": [
	{
		"name": "Melody",
		"performers": []
	}
]

Put the performer’s code block between the [], like so:

"instruments": [
	{
		"name": "Melody",
		"performers": [{
			performer: barryvan.tp.performer.Oscillator,
			options: {
				colour: '#f00',
				stepSize: 10,
				sustain: true,
				middle: 58
			}
		}]
	}
]

Now, if you reload your performance in your web browser, you should have something on-screen. You can add more performers to the other instruments in your piece in the same way. If you want more than one performer for the same instrument, you can simply place a comma after the closing brace of the performer block, and start the next one.

6. Add some filters (optional)

Filters can manipulate the entire presentation. They can, for example, shift pixels around, draw a grid, or simply calculate the framerate.

Filters are applied to each frame of the animation, and can be applied before or after the performers have been processed. Filters that are processed at the start of each frame go under “prefilters”; those processed at the end of each frame are entered under “postfilters”.

Let’s shift some pixels around using the “Pick” filter. Like performers, filters are defined in a block of code:

{
	filter: barryvan.tp.filter.Pick,
	options: {
		fuzz: 2
	}
}

We’ll add this into the “prefilters” section:

"prefilters": []

becomes

"prefilters": [{
	filter: barryvan.tp.filter.Pick,
	options: {
		fuzz: 2
	}
}]

If you reload your performance in your web browser, things should look a little more fuzzy.

Filters can have a huge impact on the overall “feel” of your performance. They can soften the performers’ hard edges, and give the entire performance a more natural appearance.

7. Present

Once you’ve added more performers, adjusted colours, and fiddled with the CSS on your HTML file, you’re ready to take to the stage. Simply upload the “Source” directory and your performance to your webserver (making sure to keep relative paths intact), and publish the URL. You don’t need to do anything on the server: TrackPerformer is entirely client-side.

8. Ask questions

If you run into problems, or have a question, don’t hesitate to leave a comment or raise an issue on GitHub. You’re also more than welcome to fork the project, and build your own performers and filters — if they’re pulled back into the main TrackPerformer tree, then everyone else can use them, too!

Appendix

A. Converting notes to numbers

Notes are in the range C-0 to B-9, and are numbered from 0 to 119. To find the number for a particular note, use this formula: x = note + (octave * 12). In this formula, the note C is 0, C# is 1, D is 2, and so on.

B. TrackPerformer Wiki: performers, formats, etc.

The TrackPerformer Wiki has details on all of the performers, the performance format, the filters that are available, and the controller options.

TrackPerformer update

I’ve added in some really exciting new features to my TrackPerformer project, as well as three new performances: We Three Kings, Carol of the Bells, and Joy to the World.

Filters

It’s now possible to add filters, or effects, into the processing chain. These filters can be applied before any performers (pre-filters) or after all performers (post-filters). At the moment, the included filters are:

  • FPS: Calculates the average framerate across the performance, optionally displaying it in a DOM element.
  • Grid: Draws a grid to the canvas. The grid may be a simple intersection grid (points), or lines. Both the X and Y axes may be independently configured.
  • Pick: Probably the most interesting (and processor-intensive) part of TrackPerformer. The Pick filter will randomly swap a pixel with one of its neighbours. It’s used at full intensity on both We three Kings and Joy to the World, and, when toned down a little for Carol of the Bells, provides a softening, organic effect.

I’ve got some ideas for more filters down the track… The only difficulty is keeping performance acceptable: manipulation of the canvas pixel by pixel is quite slow in current browsers.

Performers

There are a couple of new performers, and some minor updates to some of the existing ones. The Oscillator performer, in particular, is rapidly becoming the most flexible and useful of the performers.

  • There’s a new ShimmerGrid performer, which is great for adding texture and movement to the entire canvas. You can see it in action particularly well on Joy to the World.
  • The Swarm performer can now draw its particles as knots (like the SignalTracker), as well as as dots.
  • The Oscillator now has the ability to draw sustained notes, and to increase the longevity of notes. Take a look at Carol of the Bells to see these new options in use.
  • Notes can now be filtered based not only on their pitch, but also their velocity (volume).

There are a couple of other changes here and there, but these are the main ones.

We Three Kings

The three new example tracks are all taken from We Three Kings, my new Christmas remix album. Why not go and have a listen?