Matthew Butt

ActionInvoker method sequence

Posted in development by bnathyuw on 26 October 2011

In one of the projects I’m playing with, I’m doing a bit of a hack over .NET MVC 3.

I’m providing my own implementation of IActionInvoker, currently by extending ControllerActionInvoker, and as part of this work, I’ve done a quick audit of the methods of this class, and the order they are called in.

I’m reproducing them here, in case it’s useful to anyone else:

  • InvokeAction
  • GetControllerAction
  • FindAction
  • GetFilters
  • InvokeAuthorizationFilters
  • GetParameterValues
  • InvokeActionMethodWithFilters
  • InvokeActionMethod
  • CreateActionResult
  • InvokeActionResultWithFilters
  • InvokeActionResult
Tagged with: , , ,

Dodecaphony and JavaScript

Posted in development, music by bnathyuw on 4 October 2011

Serial technique is highly algorithmic way of generating musical ideas, and lends itself well to programming. In this post I’m going to sketch out a few bits of JavaScript I’ve been using to explore some of the possibilities of this technique.

(For those unfamiliar with serialism, and the 12-tone technique in particular, it is a method for producing musical — typically pitch — material by taking a list of values as a starting point. Various transformations can then be applied to generate new sequences. The multiplicity of different sequences provides variation, whilst their relationships back to the original series can give a sense of repetition and unity in the resulting music.)

Let’s consider 12-tone serialism.

A prime row can be considered as a mapping function P from a position to a pitch.

If we have a row [0, 3, 5, 8, 11, 1, 6, 10, 4, 9, 2, 7], then we can define P as follows:

P(0) => 0 
P(1) => 3 
P(2) => 5 
P(3) => 8 
P(4) => 11 
P(5) => 1
P(6) => 6
P(7) => 10
P(8) => 4
P(9) => 9
P(10) => 2
P(11) => 7

On this basis, we can write a JavaScript function prime which will take an argument n and return the appropriate pitch class name. (You can play along by pasting the code samples into the JS console in your browser).

var prime = (function () {
  var p = [0, 3, 5, 8, 11, 1, 6, 10, 4, 9, 2, 7];
  return function(n) {
    return p[n % 12]; // if a value of 12 or above is given, start from 0 again
  };
}());
prime(1); // => 3

prime(4); // => 11

(I’ve used a module pattern here to instantiate the variable p just once, and keep it hidden from the external scope.)

I can also write another function getPitches which will take a mapping function and apply it to an array [0..11]:

var getPitches = (function () {
  var d = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  return function (callback) {
    return d.map(function(n) {
      return callback(n) % 12; // if the result is 12 or above, transpose down an octave
    });
  };
}()); 

getPitches(prime);
// => [0, 3, 5, 8, 11, 1, 6, 10, 4, 9, 2, 7]
// or
getPitches(function(n) { return prime(n); });
// => [0, 3, 5, 8, 11, 1, 6, 10, 4, 9, 2, 7]

We can now retrieve transformations of the row.

To get transpositions, re feed in prime(n) + x:

getPitches(function(n) { return prime(n) + 1; });
// => [1, 4, 6, 9, 0, 2, 7, 11, 5, 10, 3, 8]

getPitches(function(n) { return prime(n) + 4; });
// => [4, 7, 9, 0, 3, 5, 10, 2, 8, 1, 6, 11]

To get the Inversion row, we use 12 - prime(n):

getPitches(function(n) { return 12 - prime(n); });
// => [0, 9, 7, 4, 1, 11, 6, 2, 8, 3, 10, 5]

getPitches(function(n) { return 12 - prime(n) + 3; });
// => [3, 0, 10, 7, 4, 2, 9, 5, 11, 6, 1, 8]

To form the Retrograde we use prime(11 - n):

getPitches(function(n) { return prime(11 - n); });
// => [7, 2, 9, 4, 10, 6, 1, 11, 8, 5, 3, 0]

getPitches(function(n) { return prime(11 - n) + 3; });
// => [10, 5, 0, 7, 1, 9, 4, 2, 11, 8, 6, 3]

(The discrepancy between subtracting from 12 for the Inversion and 11 for the Retrograde is because we expect the Inversion to start on the same pitch, while the Retrograde moves the starting pitch to the end.)

And of course we can get the Retrograde Inversion with 12 - prime(11 - n):

getPitches(function(n) { return 12 - prime(11 - n); });
// => [5, 10, 3, 8, 2, 6, 11, 1, 4, 7, 9, 0]

getPitches(function(n) { return 12 - prime(11 - n) + 3; });
// => [8, 1, 6, 11, 5, 9, 2, 4, 7, 10, 0, 3]

In addition to these transformations, we can rotate the row (so, for instance, we start with the third value in the series):

getPitches(function(n) { return prime(n + 2); });
// => [5, 8, 11, 1, 6, 10, 4, 9, 2, 7, 0, 3]

And we can also experiment with multiplication:

Multiplying the argument passed into prime viz prime(n * x will jumpt between elements in the original series. If the multiplier is a factor of 12, then we will get a result that repeats a subsequence of the original; if it’s not a factor, then we will get a reordering:

getPitches(function(n) { return prime(n * 2); });
// => [0, 5, 11, 6, 4, 2, 0, 5, 11, 6, 4, 2]

getPitches(function(n) { return prime(n * 3); });
// => [0, 8, 6, 9, 0, 8, 6, 9, 0, 8, 6, 9]

getPitches(function(n) { return prime(n * 4); });
// => [0, 11, 4, 0, 11, 4, 0, 11, 4, 0, 11, 4]

getPitches(function(n) { return prime(n * 5); });
// => [0, 1, 2, 8, 4, 3, 6, 7, 11, 9, 5, 10]

getPitches(function(n) { return prime(n * 6); });
// => [0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6]

getPitches(function(n) { return prime(n * 7); });
// => [0, 10, 5, 9, 11, 7, 6, 3, 4, 8, 2, 1]

getPitches(function(n) { return prime(n * 8); });
// => [0, 4, 11, 0, 4, 11, 0, 4, 11, 0, 4, 11]

getPitches(function(n) { return prime(n * 9); });
// => [0, 9, 6, 8, 0, 9, 6, 8, 0, 9, 6, 8]

getPitches(function(n) { return prime(n * 10); });
// => [0, 2, 4, 6, 11, 5, 0, 2, 4, 6, 11, 5]

getPitches(function(n) { return prime(n * 11); });
// => [0, 7, 2, 9, 4, 10, 6, 1, 11, 8, 5, 3]

getPitches(function(n) { return prime(n * 12); });
// => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Note the following properties of these series:

  1. Maps to 6 pitches, repeated twice
  2. Maps to 4 pitches, repeated thrice
  3. Maps to 3 pitches, repeated four times
  4. Remaps all pitches
  5. Maps to 2 pitches (the fact that they are 0 and 6 is a propert of the Prime row, rather than this ordering)
  6. Remaps all pitches, 0-based Retrograde of 5
  7. Maps to 3 pitches, 0-based Retrograde of 4
  8. Maps to 4 pitches, 0-based Retrograde of 3
  9. Maps to 6 pitches, 0-based Retrograde of 2
  10. 0-based Retrograde of Prime
  11. Degenerate case: maps to just one pitch

Feeding in prime(n) * x remaps the pitches, rather than their ordering:

getPitches(function(n) { return prime(n) * 2; });
// => [0, 6, 10, 4, 10, 2, 0, 8, 8, 6, 4, 2]

getPitches(function(n) { return prime(n) * 3; });
// => [0, 9, 3, 0, 9, 3, 6, 6, 0, 3, 6, 9]

getPitches(function(n) { return prime(n) * 4; });
// => [0, 0, 8, 8, 8, 4, 0, 4, 4, 0, 8, 4]

getPitches(function(n) { return prime(n) * 5; });
// => [0, 3, 1, 4, 7, 5, 6, 2, 8, 9, 10, 11]

getPitches(function(n) { return prime(n) * 6; });
// => [0, 6, 6, 0, 6, 6, 0, 0, 0, 6, 0, 6]

getPitches(function(n) { return prime(n) * 7; });
// => [0, 9, 11, 8, 5, 7, 6, 10, 4, 3, 2, 1]

getPitches(function(n) { return prime(n) * 8; });
// => [0, 0, 4, 4, 4, 8, 0, 8, 8, 0, 4, 8]

getPitches(function(n) { return prime(n) * 9; });
// => [0, 3, 9, 0, 3, 9, 6, 6, 0, 9, 6, 3]

getPitches(function(n) { return prime(n) * 10; });
// => [0, 6, 2, 8, 2, 10, 0, 4, 4, 6, 8, 10]

getPitches(function(n) { return prime(n) * 11; });
// => [0, 9, 7, 4, 1, 11, 6, 2, 8, 3, 10, 5]

getPitches(function(n) { return prime(n) * 12; });
// => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Note the pitch-sets that these values of x map to:

  1. Whole-tone scale
  2. Diminished 7th
  3. Augmented triad
  4. Full chromatic remapping
  5. Tritone
  6. Full chromatic remapping, Inversion of 5
  7. Augmented triad, Inversion of 4
  8. Diminished 7th, Inversion of 3
  9. Whole-tone scale, Inversion of 2
  10. Chromatic scale, Inversion of Prime
  11. Degenerate case: unison

From these two multiplicative transformations, we have new ways to define Inversion and Retrogression, and also a realm of other possible transformations. We can write something like this:

getPitches(function(n) { return prime(n * 5 + 8) * 7 + 4; });
// => [8, 1, 10, 5, 9, 7, 3, 2, 4, 11, 6, 0]

and know that the material is still explicitly derived from the original series.

These examples are just a few first examples of the generative power of a few simple lines of JavaScript. Next time I want to investigate what happens when you reflect the position/pitch axis, and introduce a way to deal with negative numbers, but this is enough for one evening!

HATEOAS Console: the beginning

Posted in development by bnathyuw on 18 September 2011

At 7digital we have 2 days’ innovation time every month. During this time we can work on our own pet projects. This post is about my current project.

You can find the source of this project at https://github.com/bnathyuw/Hateoas-Console

Introduction

RESTful web architecture is becoming increasingly influential in the design of both web services and web sites, but it is still very easy to produce half-hearted implementations of it, and the tools that exist don’t always help.

In this project, I want to address this problem by building a new REST console that will:

  • Reward good implementations by making it easy to take advantage of all their RESTful features;
  • Help improve less good implementations by exposing their shortcomings.

Basic principles of a RESTful interface

Richardson and Ruby (2007 pp. 79 ff.) present a good analysis of RESTful interface design. Drawing on Fielding (2000 s. 5), but with a focus on actual practice, they identify four key principles or Resource-Oriented Architecture:

  1. Addressability;
  2. Statelessness;
  3. Connectedness;
  4. Uniform Interface.

Addressability means that any resource in the application that a consumer could want to know about has at least one URI. This criterion is fairly coextensive with Fielding’s Identification of Resources requirement.

Statelessness means that every request should contain all the information needed for its processing. This overlaps with Fielding’s requirement that messages be self-descriptive, and that hypermedia be the representation of application state.

Connectedness means that each resource representation should give addresses of all related resources. The most effective way to ensure connectedness will often be to produce an entry-point resource, from which it is possible to navigate to all other resources. This furnishes the other part of Fielding’s requirement for hypermedia as the engine of application state.

Uniform Interface means that all resources can be manipulated in the same way. For web services, this almost invariably means using the HTTP verbs, viz DELETE, HEAD, GET, OPTIONS, POST, PUT &c. This principle supports Fielding’s self-description criterion, and specifies the means of manipulation of resources.

Most REST consoles are fairly successful in accommodating principles 1, 2 and 4, but fail significantly in accommodating principle 3. Under Fielding’s terminology, existing REST consoles give little support for hypermedia as the engine of application state (HATEOAS).

Existing REST consoles

There exist several good consoles for manually consuming RESTful services. These include:

Screenshot: Simple REST Client for Chrome
Simple REST Client for Chrome
Screen shot of REST Client for Firefox
REST Client for Firefox
Screenshot: apigee

apigee

All of these clients work on a similar model: you enter a URI in the address box, choose an HTTP verb and click a button to send the request. You also have the option of adding headers and a request body. The headers and content of the response are then displayed on screen for the user to inspect.

How these consoles support the REST principles

Addressability

Addressability is a core notion in these consoles: the address box is a primary part of the UI, and you have to enter something here in order to make a request.

Statelessness

Statelessness is perhaps the easiest of the four principles to achieve, as the consoles operate on a request-response model.

In fact, what is useful in a console is the very opposite of statelessness: the console should be able to remember your preferences so that you do not have to enter them for each request.

With a significant exception discussed below, all three consoles do a fair job of remembering your choice of headers from one request to another, which takes some of the burden off the user. Apigee and REST Client for Firefox are also able handle OAuth authentication, which is a nice feature.

Connectedness

None of the consoles deals successfully with connectedness. If you want to follow a link from the response, you have to copy the resource URI into the address box and submit another request.

Apigee differs from the other two consoles in having a side panel which lists the principle URI schemata for the service under test. This initially seems like a helpful feature, but has several unfortunate consequences:

  • Apigee uses WADL to create its directory of links. This encourages a return to the RPC-stle of service architecture, which thinks of a web service as being made up of a limited set of discrete endpoints, each with a particular purpose, rather than an unlimited network of interconnected resources which can be manipulated through a uniform interface.
  • As the endpoints are listed in the directory panel, it is less obvious when a resource does not contain links to related resources.
  • Apigee has no way of filling in variable parts of a URI. If, for instance, you click me/favourites/track_id (PUT), it enters https://api.soundcloud.com/me/favorites/{track_id}.json in the address box. You then have to replace {track_id} with the specific track ID you are interested in. This is of course no help if you don’t know which track you want to add to your favourites!
  • Each endpoint is listed with a .json suffix, no matter what format you have just requested. Also, any request headers you have filled in are forgotten when you click on a new endpoint.

These shortcomings not only make the console frustrating to use, but also encourage non-connected, RPC-style architectural decisions.

Uniform Interface

As with Addressability, the Uniform Interface is at the core of these consoles. The HTTP verb selector is prominent in each UI, and it is easy to switch from one to another.

Apigee supports GET, POST, DELETE and PUT, Simple REST Client for Chrome adds support for HEAD and OPTIONS, and REST Client for Firefox adds support for TRACE, as well as several more obscure verbs.

What none of these consoles does is make any attempt to figure out what representation of a resource should be submitted in a POST or PUT request body. This is particularly surprising in Apigee, as this information should be available in the API WADL document.

Conclusion

There are close points of comparison between a REST console and a web browser: each is designed to make requests from a particular URI using one of a small number of HTTP verbs, and then display a representation of that resource to the user. What makes a web browser so powerful — and indeed was one of the founding principles of the internet — is that the user can click on links to get from one page to another. When you the primacy of the clickable link to the success of browsers it becomes all the more puzzling that REST consoles do not implement this functionality.

The Project

Basic principles

The purpose of this project is to attempt to address some of the shortcomings of the currently available REST consoles, while retaining their good features:

  • The basic format of the existing consoles is successful: an address box, and verb chooser, and a send button;
  • Rendering all details of the response is also vital; REST Client for Firefox gives you choice of viewing raw and rendered data, which is a nice additional feature;
  • The client should support as wide as possible a range of HTTP verbs, encompassing at least GET, POST, PUT, DELETE, OPTIONS, HEAD;
  • The ability to remember headers is very useful and should be kept, especially when clicking on a link;
  • OAuth integration is a nice feature and worth implementing if possible;
  • It would be very useful for the console to make a reasonable attempt at figuring out the response body format for PUT and POST requests;
  • Reliance on a WADL document encourages unRESTful thinking and should be avoided.
  • All appropriate links in the response body should be identified, and it should be simple to make further requests and to explore the API by clicking on them.

Implementation decisions

I decided to implement this project in HTML and JavaScript, as this seemed the most portable platform. I am working on the assumption that the finished product will be a chrome extension, as this lets me make some simplifying assumptions about the capabilities of the browser environment, and may also help solve some security issues.

References

Site scans: a RESTful case study

Posted in development by bnathyuw on 18 September 2011

I’ve been thinking a lot recently about REST, resource design and addressability, so I was interested to read an article by Troy Hunt on the particular challenges of creating URLs that refer to other URLs.

Scenario

The scenario Troy describes is for a site that will perform a security scan of your website, and then show a report of the result. Addressability is an important concern, as once you have the results of the scan, you may want to forward them to other people.

Troy discusses two methods for including the URL to scan:

  1. Include it in the hierarchical part of the URL (ie, the part after http: and before ?, eg http://asafaweb.com/scan/troyhunt.com/Search)
  2. Include it in the query string, eg http://asafaweb.com/scan?url=troyhunt.com/Search.

He favours the second approach for practical reasons.

A RESTful approach

Troy’s article approaches this question from the point of view of addressability, rather than resource design, and makes a sensible recommendation given the basic premisses; however, the scenario he outlines presents a good opportunity to do a bit of resource design analysis, which can lead us to an even better answer.

First then, let’s think about the type of resource we’re dealing with.

I think it is fair to make a few assumptions about the scan resource and the application that generates it:

  • It will take some time to perform the scan;
  • It will take a fair amount of computing resources to perform the scan;
  • The scan will be accurate for the point in time at which it was created; a subsequent scan of the same URL may generate a different result;
  • It may be interesting to compare scans over time.

From these assumptions we can draw a few conclusions:

  • A scan is an expensive resource to create, and will have a series of different statuses over its lifetime; this means we are looking at a transactional resource model here;
  • As a URL can be scanned more than once, it is not on its own a sufficient identifier of any scan.

If we follow these conclusions, we can make a sketch of the process of performing a scan:

1. Trigger the scan

We make a POST request with the details of the scan we want:

POST http://asafaweb.com/scans
{ "url": "http://troyhunt.com/Search", "options": {…} }

Note that we are POSTing to /scans; this request will create resource subordinate to that collection. Also, as we are making a POST request, we can include further information about the scan we want, perhaps indicating which criteria we are interested in and what level of detail we require; I have indicated this possibility by including an options parameter.

The server responds not by showing us the results of the scan — they haven’t been produced yet —, but by telling us where to look for the results:

201 Created

http://asafaweb.com/scans/{xyz}

2. Check the scan URL

We can go and check this URL straight away by performing a GET:

GET http://asafaweb.com/scans/{xyz}

As the scan is still running, we don’t see the results, but rather a representation of a scan that is still in progress:

200 OK 
{ "scan": {
  "status": "in progress", 
  "url": "http://troyhunt.com/Search",
  "created": "2011-09-18 11:57:00.000",
  "options": {…}
} }

Indeed, if there are a large requests for scans, Troy may have to implement a queueing system, and our scan may have a status of "queued" until it can be processed; we could even cancel a scan by PUTting a representation with a status of "cancelled" to its URL, or perhaps simply by issuing a DELETE request.

3. Retrieve the scan

A little while later, the scan has completed. Perhaps we keep performing a GET on its URL until it’s done; perhaps we have submitted an email address in the initial POST, and have now received email notification that it is ready.

We perform another GET to see the results:

GET http://asafaweb.com/scans/{xyz}

And the server responds:

200 OK 
{ "scan": {
  "status": "complete",
  "url": "http://troyhunt.com/Search",
  "created": "2011-09-18 11:57:00.000",
  "options": {…},
  "results": {…}
} }

We can now send the URL http://asafaweb.com/scans/{xyz} to  other people, and they will see the same results. The server doesn’t have to rescan the site, so retrieving these results can be a quick, inexpensive operation.

4. Search for scans

Throughout this example, I have used {xyz} to indicate the unique identifier of the scan. I have deliberately not given details of what this identifier might be. However, as I said earlier, the URL to scan is not a sufficient identifier, as we want to allow the possibility of scanning the same URL more than once. This identifier could include the URL, but this may not be the ideal solution, both for the technical reasons that Troy indicates in his article, and because this will produce very long identifiers, where we could probably make do with short strings of characters.

The result of this is that we have a system that is eminently addressable, but which uses identifiers that bear an opaque relationship to the scanned URL, and fails the findability criterion. I can easily send a URL like http://asafaweb.com/scans/f72bw8 to a friend, but if they do not have that address, they have no way of guessing that this is the address of a scan of my site.

To remedy this, we can implement a search interface. We already have an address for the entire collection of scans, viz /scans, so  now we can just refine the response to a request of this URL with a query parameter:

GET http://asafaweb.com/scans?url=http://troyhunt.com/Search

The server can then respond with a listing of all the scans that meet these criteria:

200 OK
{ "scans": {
  "url": "http://troyhunt.com/Search",
  "results": [
    {
      "status": "complete",
      "created": "2011-09-18 11:57:00.000",
      "link": {
        href: "http://asafaweb.com/scans/f72bw8"
      }
    }, 
    {
      "status": "complete",
      "created": "2011-08-28 17:36:24.023",
      "link": {
        href: "http://asafaweb.com/scans/89ew2p"
      }
    }, 
  ]
} }

Each result has a link to its location, so all results can be retrieved at any time.

By recognising that our scans are resources that can be searched, and by providing a means to perform that search, we have restored findability to our interface. Also, the fact that our search criterion is a refinement of a more general request, and thus appears in the query string, means that we arrive at a very similar conclusion the one Troy reaches in his article, but this time for reasons based on resource design, rather than practicality.

Applicability to web sites

I have given all my examples in JSON, as it offers a concise and easy-to-read format for technical discussions. However, all of this discussion would work equally well with HTML web pages:

  1. The user fills in and submits a form to request a scan, and is redirected to the scan page;
  2. The scan page shows a message telling the user the scan is in progress;
  3. After a while a page refresh reveals the results of the scan, and the user can send the page URL to their contacts;
  4. The /scans page offers a search form into which the user can enter their URL and retrieve a list of all the dated scans for that location.

A couple of the implementation details will differ, because of the limited number of HTTP verbs and status codes that browsers can deal with, but the principles are exactly the same.

TPT mapping in Entity Framework CTP 5

Posted in development by bnathyuw on 13 February 2011

I’ve been working on a little project with MVC 3 and Entity Framework Code-First CTP (community technology preview) 5, and have been implementing TPT (type-per-table) inheritance for the various types of user in the system: Customers, Administrators &c.

Yesterday, I added an Administrator class to my model, and this happened:

Yellow screen of death: “The configured property 'Forename' is not a declared property on the entity 'Administrator'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.”

The exceptions message reads: The configured property ‘Forename’ is not a declared property on the entity ‘Administrator’. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

All very puzzling, as here is my User class:

public class User
{
	public int Id { get; set; }
	[Display(Name = "Forename"), Required]
	public string Forename { get; set; }
	[Display(Name = "Surname"), Required]
	public string Surname { get; set; }
}

and here is my Administrator class:

public class Administrator:User
{
}

(OK, the Administrator class isn’t terribly useful right now, but I’m just fleshing out the schema at the moment.)

Here, finally, is my Repository class, somewhat abbreviated:

public class Repository : DbContext
{
	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Entity().ToTable("Administrators");
		modelBuilder.Entity().ToTable("Customers");
	}
	public DbSet Administrators { get; set; }
	public DbSet Customers { get; set; }
	public DbSet Users { get; set; }
}

After some futile reading around, I finally decided to roll back to my previous working version, at which point the yellow screen of death disappeared. And it was at this point that the revelation came to me: one of the changes I had made was to alphabetise my DbSet properties, moving Users past Administrators and Customers.

So I went about adding the Administrator class again, but this time keeping the Users property above those for its subclasses:

public class Repository : DbContext
{
	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Entity().ToTable("Administrators");
		modelBuilder.Entity().ToTable("Customers");
	}
	// Declare superclass first
	public DbSet Users { get; set; }
	public DbSet Administrators { get; set; }
	public DbSet Customers { get; set; }
}

and as if by magic the application started working again.

Moral

When implementing TPT inheritance in CTP 5, declare the superclass DbSet property before its subclasses.

Tagged with: , , , ,

A clock

Posted in development by bnathyuw on 17 October 2010

Peer and I have spent today building HTML / JavaScript clocks.

I thought I would create an analogue clock, but with a few alterations to make it an interesting project; I was also keen to avoid using any image files, so radial gradients seemed like a good option. Because we’re using the client-side time, this experiment does use JavaScript; also, as I’ve used gradient backgrounds, this will only work in Mozilla and Webkit browsers.

Here’s the result:

Cell clock screenshot at 17:34

http://playground.matthewbutt.com/clock.htm

Addendum: you can see Peer’s clock at http://www.curiouspixels.co.uk/peersclock/

Tagged with: , , , ,

jQuery / IE strangeness

Posted in development by bnathyuw on 22 September 2010

Just discovered that jQuery.live doesn’t work with change events in IE. Now I know that I can stop banging my head against the wall and rewrite my code to use jQuery.change instead.

i10

Posted in development by bnathyuw on 2 April 2010

The other week, during some time we had off work, Peer and I went to did a cultural expedition to the two Tates to see the Henry Moore, Chris Ofili and van Doesburg exhibitions. The last of these gave us the most inspiration: Peer was transfixed by the animated films, and I found plenty of typography and print design to keep me excited.

So here’s a quick attempt to reproduce one of the designs; it’s César Domela’s cover for the 4th edition of i10:

And here’s my attempt:

i10 as a web page

http://playground.matthewbutt.com/i10.htm

No terribly exciting techniques in this one: just web fonts and some use of nth-child.

Acknowledgments

Books

Fonts

Tagged with: , , ,

Constructivism Part III

Posted in development by bnathyuw on 22 February 2010

Today’s study is the cover of Generation X’s 1977 single, Your Generation:

Black, red and grey construction with 'Generation X' in bold white text

Here is my version:

http://playground.matthewbutt.com/generation.htm

Please forgive any inconsistencies in the font rendering: I couldn’t find an open-licensed font with quite the right geometry, so I fell back on Helvetica, which may render unpredictably on different platforms.

This composition uses a handful of blocks with multiple backgrounds:

  • The upper part of the image, which looks a little like the Polydor logo, is a pseudo-element with four backgrounds, from top to bottom:
    • The small red circle
    • A white masking area, which covers the lower halves of:
    • The large black circle
    • The red block on the side.
  • The title strip is actually an h1 (‘Generation’) with a span inside (‘X’). The stripes are hand-coded linear gradients, and the cross-hatching in the small square is two repeating gradient stripes laid on top of each other.
  • The red triangle is another pseudo-element, with a single, angled gradient background.

The key lesson from this exercise was how tricky it can be to get webkit gradients right. The -webkit-gradient syntax is much less intuitive than the -moz-xxx-gradient syntaxes, and the repeated gradient declaration is also something of a fiddle. As to angling the red triangle, I couldn’t be bothered with more trig, so I just used trial and error.

Acknowledgments

Books

Tagged with: , , , ,

CSS Seesaw

Posted in development by bnathyuw on 19 February 2010

It’s Friday night, so not a big one tonight.

I thought I would have a quick play with CSS transitions, and nothing seemed a better demonstration than a seesaw.

Here it is (warning: this only works in Webkit browsers at the time of writing):

A red seesaw with a black ball on it, all balanced on a black pivot

http://playground.matthewbutt.com/seesaw.htm

This little animation uses two transitions: one to tip the seesaw back and forth, and the other to roll the ball from one end to the other. There were only two slightly complex matters here: I needed to brush up on my A-level trig to get all the distances right, and a little sleight of hand was in order to create the triangular pivot (fire up Firebug if you want to see how I did it).

There are a few small bugs: poor aliasing, and a ghost top border on the seesaw element, but they can wait for another day.

And now, goodnight!

Follow

Get every new post delivered to your Inbox.