Monday, 27 January 2014

Sizing images for a responsive website, oh and retina too.

One of the issues with responsive sites is mixing the fluid width elements with fixed sized ones. I came across this problem recently, while adding a news feature (containing images) to a responsive site.

Here is my attempt at a no-compromises approach, where the image would always look great, regardless of the size of the screen.

Basic Implementation

Here's a summary of the basic idea:

The Server Resizes Images on the fly
This is key to making it work, and is not so frightening as I thought. As I'm currently in the .NET world, I came across a library called ImageResizer which is intended to do exactly this. The library claims to be almost as fast as the underlying GDI+ graphics operations, and can spit out your image in any shape or size you want, with nice cropping options.

Here's the basic idea. Create a service / web form which generates the image on a fly by resizing it and sending the result through the HTTP response. Here's an example in C#, but the principle is the same in Java.

var filename = Request("filename");
        var resizeSettings = ResizeSettings() {
            MaxWidth = Request("width"),
            MaxHeight = 261,
            Mode = FitMode.Crop
        };
        Response.ContentType = "image/jpeg";
        Response.Cache.SetCacheability(HttpCacheability.Public);
        Response.Cache.SetMaxAge(New TimeSpan(7, 0, 0, 0));
        GetImageService().GenerateThumbnails(filename, resizeSettings, Response.OutputStream);
        Response.Flush();

GetImageService() simply wraps image resizer and maps the filename to the image's actual location.

The Client decides the width of the image
The client needs to ask for an image in the right size. The image filename is generated dynamically by the Javascript. When the article model loads, the image filename is also returned. The client then adds parameters asking for the correct width.

I'm using Knockout JS on the front end, so its easy to encapsulate all this within a custom binding:

ko.bindingHandlers.dynamicImage = {
        init: function () {

        },
        update: function (element, valueAccessor) {
            var filename = ko.utils.unwrapObservable(valueAccessor()),
                width = Math.min(jQuery("main").width() || 600),
                height = defaultHeight,
                src = "article-image.aspx?" + jQuery.param({
                    filename: filename,
                    width: width,
                    height: height
                });

            jQuery(element)
                .css("background-image", "url(" + src + ")")
        }
    };
The knockout markup looks a bit like this:

<figure>
  <div class="article-image" data-bind="attr: { title: caption }, dynamicImage: filename">
    <span class="attribution" data-bind="text: attribution"></span>
  </div>
  <figcaption data-bind="text: caption"></figcaption>
</figure>


I'm using a background image within a <div>, rather than an <img> tag for a reason, see notes at the end.




A little CSS ensures the image appears as a correctly sized placeholder while the image loads.

.article-image {
    min-height: 261px;
    width: 100%;
    background-color: #eee;
    background-repeat: no-repeat;
}

The no-repeat will stop the image tiling if the user maximises or otherwise increases the size of their browser window.

News article on a desktop browser

On mobile devices

Enhancements

Supporting High Pixel Density "Retina" Screens
Server
It's not just iPhones anymore. Most android have high density screens to varying degrees, and my lovely Mac Pro has one too, so it seems worthwhile to get this right. Fortunately the generate-on-the-fly approach makes it very easy.

I modified the server script to accept another parameter "retina". If this is set to "true" then the requested width and height are doubled.

if (retina) {
   width *= 2
   height *= 2
   quality = 50
}

In addition, as people have noticed, you can also dramatically ramp down the JPEG quality setting on retina images. In my script it takes it down to 50, although you can probably go lower. This keeps the retina images on a par (or sometimes even smaller than) the 1:1 image sizes.

Front End
The image filename builder needs to send the retina request. It needs to know if it is a retina device. You can do this in various ways using Modernizr queries, but since the image change is fairly harmless in modern browsers, I think you can get away with:

var retina = window.devicePixelRatio && window.devicePixelRatio > 1;
...
src = "article-image.aspx?" + jQuery.param({
                    filename: filename,
                    width: width,
                    height: height,
                    retina: retina
                });

jQuery(element)
                .css("background-image", "url(" + src + ")")
                .css("background-size", width + "px " + height + "px");

Then it's just a case of ensuring the background size is maintained with an additional CSS property.

The advantage of this approach is that the browser only needs to download a single image.

Giving the server a break
ImageResizer comes with various options for caching generated images, although you could roll your own too. Asking for images at arbitrary widths, however, may reduce cache hits though. Here are some suggestions:

  • Give your article a max width. I went for 600px, which in any case is about as wide as an article can be before readability starts to suffer. This limits the number of sizes that can be requested, and also allows you to resize images to 1200px upon upload, as this is the largest (retina) size that can be requested.
  • Round up your width requests to the nearest 50px, reducing the number of possible size requests. By placing your image inside a div with background-image, the browser will automatically crop and center the image if it is a little larger.



Sunday, 8 September 2013

A £100 Solar Light Challenge

There comes a time in every young man's life when he becomes, in fact, not so young anymore. At this point instinct takes over and before long the fellow has furnished himself with a shed, just as did generations before. Once all obvious enhancements anticipated by the shed manufacturer have been installed, the time comes to pimp the shed further.  The generation of electricity, a precursor to WiFi and therefore happiness, is a strong contender. Time for a challenge..

Hypothesis
That it is possible install a solar powered lighting system for less than £100, without using a kit.

(The kit constraint was easy, because most of them cost more than £100 anyway)

Literature Survey
Now, it has been a long while since I've done anything electrical, but a brief amount of research suggested I'd need the following:

  • A solar panel, obviously
  • Battery to store all the lovely power
  • A solar controller
  • Light switch
  • A high power LED
In the interests of efficiency, I decided not to trouble myself further with any theories of how these components might work together.

Method I
Although tempted to buy something enormous that would either improve or catastrophically degrade the structure of the shed roof, I opted for a 40W 12V solar panel on eBay (£41.99). It's a decent size, about the area of an iMac screen. It seemed like it ought to charge a few batteries.

I bought 10x super 2400mah AA batteries for that purpose (£16.95). Then a weatherproof switch (£6.20), and the solar controller for £8.95 (Total £74.09). The solar controller takes the current from the panel and charges the battery, as well as providing output for the lights. As you can see, it is fairly obvious what you're supposed to do with it:

The solar controller. Looks professional doesn't it? Good UX.
With the big ticket items bought, but with only about £25 left from the budget I headed off to Maplin electronics, where I hadn't been since school. How the UK high street is able to support a store which, as far as I can see, is simply an emporium of wonderful toys for people like me, I do not know. I am, nonetheless, very grateful for its continued existence and spent an endorphiny hour browsing the interesting things. I bought some more stuff:
  • A pack to hold the batteries together, £1.50
  • A hobby box for the battery. Unnecessary but it looked professional. £2.99
  • A couple of blocks of strip terminals for making hassle-free connections, £2.18
Remembering from tedious GCSE physics experiments that thicker cable has less resistance, and not wanting to squander the precious juice from the sun, I also bought:
  • 5m electric cable, conveniently red and black £6.95
Now, my little 12V system would struggle to illuminate even the most efficient of domestic energy saving lights, so I read somewhere that the best thing to do is to build your own bulb from an LED light.

This turned out to be a mistake.

Unawares, I went over to the components desk (surely the most awesome part of any Maplin store?) and bought the brightest looking 0.5W LED I could find (£3.09), a heat sink to stick it on (£1.50), and an LED lens (£1.49) to make it more light bulby. 

Total cost so far £93.79

Being a software developer who likes modular development (and not wanting to spend the next few hours standing on a chair), I cut out a piece of MDF to fit into a space above the door, and laid out
the pieces on top. The piece would slot onto the wall later.



An issue was identified after connecting the batteries to the controller. The controller display shows the battery charge level continuously with three LEDs, ironically draining the battery. Although appreciating that measurement naturally changes the state of things, I didn't want Heisenberg to leave me in the dark either. The best thing to do is to add a switch (£2.49) to be able to disconnect the battery from the controller when not needed.



At this point OCD took over and I decided to run all the cables round the back of the panel so the front would give the impression of competence by the installer and might even add valuable equity to the house.

Connecting all the cables together was straightforward. The next exciting stage was constructing the light bulb. This involved sticking the LED onto to the heat sink (the requirement of which should have been a warning), then soldering on a cable on either side, then sticking on the lens with a hot glue gun.


I hadn't soldered anything for years. Now I can pretend I have a robot helper.

The finished bulb. Professional but doomed.


A fan of unit testing, I decided to test out the light before attaching the solar panel (the batteries were already fully charged). The LED lit up brighter than the sun for an instant, then dispatched itself to the great LED socket in the sky. I didn't think very hard about this, and ran out to buy a bigger 1W bulb. (£4.09).

This took my budget to £100.37

Close enough, I thought. And it would have been if the 1W bulb hadn't blown in exactly the same inevitable way as the 0.5W bulb. I should have paid more attention in the tedious physics lessons.

It turns out that 10 x 2400mAh batteries at 1.2V can readily produce a lot more than 1W for an instant. What you need, I learned, is a 2W LED driver, which manages the current to the LED, which changes continuously as the LED operates. To be safe, I bought a 3W LED (£5.99) to match. Now everything seemed to work OK, albeit at £15.35 over budget.

No point crying over blown LEDs, so I moved on to the exciting and manly phase of installing the solar panel on the roof. I drilled a decent hole in the roof, just under the top layer of roofing felt (still watertight, hah), then attached a baton for the panel to rest on, allowing gravity to take care of its adhesion to the roof (a decision to be regretted as soon as the wind picks up, no doubt). And here it is:



And what's this? The controller lights up like a Christmas tree, the charge light also illuminated. What epic success.


Analysis
The smugness subsided when I tried out the light properly. Ouch. After two minutes the light and heat sink was too hot to touch. Afraid it would burn out (perhaps taking the tinder dry shed with it) I switched it off. Not many of my planned shed projects will take less than two minutes. In any case, I don't want my precious solar juice wasted heating the back of the light.

Method II
The budget in tatters, I returned to eBay and found an exciting alternative:


The car lights arrive. 4 LEDs in each, with connectors and adjustible brackets. Bargain.
With the £100 challenge failed, I decided to try and make it look as professional as possible and the car lights and spotlight turned out to be just the ticket. But first it's time to massacre the spot light..

Turns out there's simply a latch in there you can pop out with a screwdriver, but hacking it out is its own reward.

By chance the car LED lights were a perfect size, and with another connection and a bit of hot glue I had a low energy adjustible spotlight that looked like, well, a proper light.


Compared with the high power LED, the light is rather clinical in nature. But it burns as cold as it looks and seems to last as long as I need it for. The batteries are sufficient to run both of them at the same time with no dimming. 

Success at last.


Conclusion
So there you have it. A working solar system, admittedly for more than £100. But, I console myself, if I hadn't wasted time and money on the high power LEDs light dead end, it would have been possible to do the whole lot for just about under £100. Well, £105.17. Still not quite within the budget, but on a good day on eBay..

Nonetheless, the trial and error is much more fun than deciphering instructions on a kit. Part of the fun, as with software, is to be able to say "I made that." Then, returning six months later, cringing inwardly, and think "What on earth was I thinking when I did that?"



Thursday, 31 January 2013

EU Cookie Disclaimers: A Review

In the wake of another confusing announcement by the ICO (the body responsible for information about cookie legislation in the UK) that they won't ask users for explicit consent to use cookies, perhaps it's time to take a look back at what effect the law has had in the last couple of years. Putting to one side the controversy surrounding the legislation itself, it is interesting to survey the way different sites have reacted, and the solutions they came up with.

The Giant Header

This approach has been adopted by the BBC. A big orange and grey banner pushes down the rest of the content with a big continue button. Because it is so enormous, it assumes you didn't miss it and dismisses itself on any subsequent pages

Channel 4 has gone for a very similar approach, this time in shiny silver. Annoyingly it insists on the close button being clicked, so continues to interrupt your viewing until you put the lawyers out of their misery. TFL does the same, presumably on the basis that TFL customers are already accustomed to inconvenience.

An enjoyable example is the aesthetic abberation atop the Unison website, where a gigantic purple banner greets you. At least they are kind enough to only show it once.

  • Technical Achievement: 6/10
  • Legal Paranoia: 8/10
  • User Friendliness: 4/10

The Animated Foldout

For some reason, some organisations opted to animate their legal notices. One can only imagine the bitter UX tears..

Channel 5 have gone for a thin banner which folds down. Given the advertising takeover graphics and the rest of the site, the jQuery animation isn't really up to the task of animating the banner down smoothly - on my PC at least - so it comes down in a distinctly jagged manner. It also neatly covers up prime real estate which probably annoys advertisers.

MoneySavingExpert perform a similar trick, but its so silky smooth you miss it when it isn't there. Nationwide are kind enough to wait a few seconds before showing the banner, and it politely dismisses itself after being viewed once.

  • Technical Achievement: 8/10
  • Legal Paranoia: 8/10
  • User Friendliness: 3/10

The Modal Model

The FT went all out and decided to present their cookie legalese in a modal dialog. It won't dissappear until you click the close button. The Church of England has gone for a similar idea, although as Christians they are merciful enough to show it once only.

When I first checked the Greenpeace site in December, they appeared not to use cookies so didn't need a disclaimer at all. As of January they have opted for the most elaborate modal dialog of all - a gigantic box with two accept buttons, a friendly cartoon and a blurred out background (alas an image; not some great feat of Canvas/WebGL).

  • Technical Achievement: 7/10
  • Legal Paranoia: 10/10
  • User Friendliness: 1/10

The Minimal Viable Product

The majority of commercial companies have, unsurprisingly, decided not to confront their users' initial experience with take-it-or-leave-it messages. Fortunately the legislation is delightfully vague when it comes to deciding how to present these disclaimers. Big companies whose lawyers took a look at the rules have generally judged a cookie notice in the footer to be perfectly adequate and entirely within the rules. Indeed most reputable sites published cookie information within the privacy section long before it became mandatory.

Sites with a simple static link in the footer include Debenhams, NatWest, Facebook, the pretty new itv.com, Lloydstsb.com, and Halifax, Veolia and Tesco and M&S.
  • Technical Achievement: 1/10
  • Legal Paranoia: 2/10
  • User Friendliness: 10/10

The Bigger Picturers

Duchy Originals doesn't appear to publish a cookie policy - as least one that I could find - despite using Google Analytics. This is ironic, since they are the only organisation here which produces actual cookies. Never mind, the British public trusts Waitrose and Prince of Wales implicitly. Long live the King!
  • Technical Achievement: N/A
  • Legal Paranoia: 0/10
  • User Friendliness: 10/10

Tuesday, 29 January 2013

Replacing C2A0 Spaces in JavaScript

I've been doing some work recently with input entered into a contenteditable="true" element, rather than a plain old text input box. This allows me to do some nice styling on the inputted text, but can cause unwanted side effects.

One of these is the appearance of the C2A0 character, otherwise known as the non-breaking space. When typing a space within a content editable, some browsers will insert &nbsp; instead of a normal ASCII 32 space character.

Here's some code that shows what happens

// suppose this is the content editable..
var element = document.createElement("div");
// and you just typed a space
element.innerHTML="&nbsp;"

// we get the text to send to the server
var text = element.innerText; 
// on Chrome text will a string that looks like " "
// on Firefox you'll get undefined
// and on IE you'll get an ASCII 32 space!
// so on some browsers..
text == " "; // returns false
The difference becomes obvious when you encode it:
encodeURIComponent(" "); // returns "+"
encodeURIComponent(text); // returns "%C2%A0"
To get around this problem, I wrote the following.
This uses jQuery for brevity. It also yields consistent results across different browsers.

(function() {
    var nbsp = jQuery("
&nbsp;
").text(); return { getText: function(element) { return jQuery(element).text().replace(nbsp, " "); } } })();
Hope it helps somebody.

Thursday, 22 November 2012

iFrames in 2012. Really?

It is fashionable for web programmers to hate iFrames. I very recently heard some reasons why you might wish to use one. For a social widget placed on a CMS driven page the benefits of an iFrame were:
  • CSS sandboxing
    Iframed content is guaranteed to be unaffected by any styles on the parent page.
  • JS sandboxing
    Similarly, iframes don't inherit a polluted global scope or adjustments to object prototypes.
  • Cross Domain Simplicity
    If the social service runs off a different domain to the parent website, the iframe content (if also hosted on the other domain) will not suffer any cross domain issues.
Let's have a look at each benefit in turn, starting with CSS sandboxing.

The primary purpose of CSS is that it cascades. This is what it was designed for and is generally a good thing. This is easily worked around by making selectors more specific, usually by prepending a classname as a namespace in front of the rules.

However, iframe content that ignores the parent site's CSS required the creation of another set of rules which are separate but in all likelihood highly similar. Any changes to the design or UX of the main site will require developers making changes in two places. 

JS Sandboxing. The main app may have a bunch of stuff sitting on the global scope. It may also have done some things to the prototypes of common objects like Array. This pattern doesn't appeal to everybody, but there is no obligation to use any prototypal enhancements. If the parent app is doing something literally insane on an object prototype then its probably best to tell the developers, rather than working around the problem. 

Things are also messier if the iframe needs to communicate with its parent, even with window.postMessage. Primitives may be passed easily enough, but object instances or events will confuse IE7.

Cross domain issues. Adding a rewrite rule in the Apache / server on nginx etc to point to the other service from the main domain(s) is the way to go. iframes are notorious for introducing their own cross domain issues.

There are some good reasons to use iframes, particularly for serving content/adverts on third party sites over which there is genuinely no control (the HTML5 folks went so far as to reestablish the iframe in the spec: http://dev.w3.org/html5/spec/single-page.html#the-iframe-element). 

In short, if the integration takes place within a single organisation, these benefits only increase the technical debt for everybody. Code may be more complex and harder to maintain. The user's browser will consume more memory due to double evaluations. Sizing and scrolling inconsistencies may crop up across different mobile platforms. iframes are unfashionable for good reason.

Sunday, 9 September 2012

Assertable Pattern: Fluent BDD style test assertions in Pure Java

I'm a fan of expressing unit test logic in terms of behaviour rather than a series of assertions which imply that behaviour. My long term favourite pattern of expressing behaviour has been to use the given, when, then style, for instance:

given(some prior state)
when(something occurs)
then(this should have happened)

Unfortunately, as a static and strongly typed language, Java doesn't make it easy to express things in these terms and you can quite quickly get tied in knots trying to express yourself fluently. For this reason a number of frameworks like EasyB provide an abstraction over the top of the programming language in order to do this easily - and provide a means for non programmers to write tests.

However, the downside is that this logic must at some point be connected to the underlying language, and so you can get into the situations where you're writing Java/Java-like code in a non .java file. At which point your IDE doesn't know what is going on and syntax highlighting - let alone refactorings - no longer work. This is the worst of both worlds.

Therefore, I try to stick with pure Java. Because I don't like asserts, I write what I call "Assertable" classes, which make the assertions, but express them in a more natural way. When combined with a few chained function calls, you can start to make things fairly reasonable.

Suppose I have a bean called "Field" with a couple of getters on it, which I want to test. I can do a bit of assertion in the classic JUnit style:

assertEquals("The field should be required", true, field.isRequired());
assertEquals("The field should not be visible", false, field.isVisible());

I can keep going like this, but a few copy and pastes down the line and my test is a mess, and reading the thing is just so exhausting.

In this case I like to write a nice helper class, which:

  • Doesn't use the word assert - because non-programmers don't use words like that.
  • Is chainable, so you can avoid repetition.
  • Splits the expectation from the test, so you can modify your checks easily.
  • Sits in a different file, so its internal ugliness is hidden and its functions can be reused.
  • Provides helpful failure messages

My FieldAssertable class can be used in a test like this:

thenThe(field)
        .shouldBe().required()
        .shouldNotBe().visible();

This is still Java, but a non Java programmer can read and understand it, and my tests look cleverer.

Here is an implementation of FieldAssertable:

public class FieldAssertable {

  private Field field;
  private boolean booleanExpectation;

  public FieldAssertable(Field field) {
    this.field = field;
  }

  public FieldAssertable shouldBe() {
    this.booleanExpectation = true;
    return this;
  }

  public FieldAssertable shouldNotBe() {
    this.booleanExpectation = false;
    return this;
  }

  public FieldAssertable required() {
    assertEquals(
        getNiceFailureMessage("required"),
        this.booleanExpectation,
        field.isRequired());
    return this;
  }

  public FieldAssertable visible() {
    assertEquals(
        getNiceFailureMessage("visible"),
        this.booleanExpectation,
        field.isVisible());
    return this;
  }

  private String getNiceFailureMessage(String property) {
    return "Field `" + field.getId() + "` " +
           (this.booleanExpectation ? "should be " : "should not be ") +
           property;
  }

}

To finish, I add a means of accessing the Assertable without needing to know its name - using a method that can be statically imported into your test.

public static FieldAssertable thenThe(Field f) {
  return new FieldAssertable(f);
}

This doesn't solve the problem of allowing non-programmers to write acceptance tests (although I think that is always difficult, even with a framework), and it does still require an amount of OO hoop jumping, but it works for me, and it might work for you.

Sunday, 15 April 2012

Gaussian / Normal Functions in JavaScript

Recently I've been indulging myself writing a small game in JavaScript. It didn't take long before I realised I'd need to use some Gaussian / Normal functions to get what I wanted. Firstly, I wanted my AI players and monsters to behave in a non-deterministic manner while tending towards a given decision. Secondly, I wanted to produce animations with a decent easing function.

The former, I decided, relied upon being able to generate random numbers in JavaScript that are not uniformly distributed (noise), but are normally distributed: being more likely to cluster around a distribution defined by a mean and standard deviation. There is good support for this in Java, but JavaScript only supports the uniform random numbers between 0 and 1.

Gaussian Random Numbers in JavaScript

You can use the Box Muller Transform to transform two uniform random numbers into two normally distributed random numbers. There is a subtlety about caching the second number for later use, which can be done neatly in JavaScript.

   /**
     * Returns a Gaussian Random Number around a normal distribution defined by the mean
     * and standard deviation parameters.
     *
     * Uses the algorithm used in Java's random class, which in turn comes from
     * Donald Knuth's implementation of the Box–Muller transform.
     *
     * @param {Number} [mean = 0.0] The mean value, default 0.0
     * @param {Number} [standardDeviation = 1.0] The standard deviation, default 1.0
     * @return {Number} A random number
     */
    Math.randomGaussian = function(mean, standardDeviation) {

        mean = defaultTo(mean, 0.0);
        standardDeviation = defaultTo(standardDeviation, 1.0);

        if (Math.randomGaussian.nextGaussian !== undefined) {
            var nextGaussian = Math.randomGaussian.nextGaussian;
            delete Math.randomGaussian.nextGaussian;
            return (nextGaussian * standardDeviation) + mean;
        } else {
            var v1, v2, s, multiplier;
            do {
                v1 = 2 * Math.random() - 1; // between -1 and 1
                v2 = 2 * Math.random() - 1; // between -1 and 1
                s = v1 * v1 + v2 * v2;
            } while (s >= 1 || s == 0);
            multiplier = Math.sqrt(-2 * Math.log(s) / s);
            Math.randomGaussian.nextGaussian = v2 * multiplier;
            return (v1 * multiplier * standardDeviation) + mean;
        }

    };

Gaussian Probability Density Function in JavaScript

The second function here returns a probability density function for a given shape of distribution which I found handy in my animations. By changing the mean and standard deviation, it becomes really easy to make one thing happen after another, and everything is nice and smooth due to the nature of the bell curves. The function below returns a probability density function which returns the value of the distribution at x.

/**
     * Returns a normal probability density function for the given parameters.
     * The function will return the probability for given values of X
     *
     * @param {Number} [mean = 0] The center of the peak, usually at X = 0
     * @param {Number} [standardDeviation = 1.0] The width / standard deviation of the peak
     * @param {Number} [maxHeight = 1.0] The maximum height of the peak, usually 1
     * @returns {Function} A function that will return the value of the distribution at given values of X
     */
    Math.getGaussianFunction = function(mean, standardDeviation, maxHeight) {

        mean = defaultTo(mean, 0.0);
        standardDeviation = defaultTo(standardDeviation, 1.0);
        maxHeight = defaultTo(maxHeight, 1.0);

        return function getNormal(x) {
            return maxHeight * Math.pow(Math.E, -Math.pow(x - mean, 2) / (2 * (standardDeviation * standardDeviation)));
        }
    };

You can find the complete, up-to-date file here on GitHub