Friday, August 02, 2013

Coffee and UX

Sometimes, user interface changes can result in unexpected user experience impact.

The office coffee machine broke down last week, and was promptly replaced.

From this

it became this

Essentially it is the same machine, but instead of having analog knobs, it has a number of buttons.

The problem is: not everyone has the same taste in coffee

Whereas before, regardless of whether the previous person likes a strong espresso or a watered-down coffee, I could always go up to the machine and twist the two knobs (controlling strength and volume) without thinking to get my perfect coffee, now I have to click, on average, six times before the machine understands what I want!

I am thinking: user test your product in real-life situation...

Mandrill Template Manager

As a product manager, I am a fan of the Mandrill service. With its template support, we can iterate on email content and layout with relative ease. However, to generate templates, there are a number of steps involved in the workflow, which can be quite manual and errors can easily occur:

  • combining different html files (header, footer, etc) together to build the complete html
  • inlining css
  • generating the plain text
  • copy and pasting final html and plain text into Mandrill
So I set out to create a PHP library to automate all these for me. Check it out here:

I decided to keep the core PHP class quite simple. For examples, it handles strings instead of files. However, I have provided a example which illustrates how to effectively use the PHP class, working with mustache templates, css files, config files, etc.

Hope you find it useful, and I look forward to hearing some feedback.

P.S. I got to learn quite a bit about the excellent Composer tool, which I highly recommend.

Wednesday, July 17, 2013

Giving my singlespeed some TLC

Having put my steel-frame singlespeed through a season of abuse, I have not really given it as much love as it deserves recently. Last week, one of the rear spokes snapped and I decided to use the opportunity to replace both wheels (both from a previous bike, with rusty spokes)

I have a spare front wheel I bought from Gumtree for 15 quid a while ago. It is laced to a Quando track hub but its 3/8 inch axle turned out to be too big for both my road bike and my singlespeed, so it has just been sitting in the corner gathering dust.

For the rear, I found an eBay shop selling a Raleigh Tru Build wheel (Omega rim) with an unbranded flipflop hub for just under 40 quid.

The rear wheel arrived yesterday and I could not wait to get my hands dirty. It involved two things I had never tried before:
  • filing the front (steel) dropouts to fit the 3/8 inch axle
  • removing the singlespeed freewheel from my old wheel do that I could install it on the new wheel

Filing the front dropouts

With a round metal file, I started filing the back (forward-facing) side of the dropouts. I was being very cautious at first, but I soon found out that I was not really taking any bit of metal off. With a bit more courage and a lot more patience, I finally managed to take off the 1mm needed to slot the front wheel in. Just remember to file each fork-end bit by but in turn to make sure that you don't accidentally take off too much on one side, and end up with a misaligned wheel!

Removing the freewheel

I borrowed the singlespeed freewheel removal tool from my friend. I have neither a vice or a workbench at home, so I had to resort to using a spanner. It turned out to be an absolute nightmare. Making sure that I got the direction right (anti-clockwise to undo), I kept whacking the spanner arm for 20 minutes until the freewheel came loose. Putting it on the new wheel was no problem, as the freewheel is meant to be self-fastening as you pedal.

I covered the spoke holes on both rims with Velox cloth tapes, and spaced out the rear hub with a couple of hardware-store washers on each side (being an old road frame, the rear end is 126mm wide, as opposed to 120mm). The chainline (pretty standard 42mm) ended up being pretty straight.

End result:

Note the use of washers as spacers

Again using washers as spacers

Perfect chainline!

Tuesday, April 30, 2013

Phishing inside an iframe

Working on a new version of the Mendeley Web Importer bookmarklet recently, I took a look at a number of similar web importing tools (bookmarklets and extensions) out there, e.g. Pocket, Evernote, Instapaper.

Evernote is a great product. I am a massive fan, and their web clipper is great. However, I am not keen on their decision to enable login inside the bookmarklet iframe:

I have created this simple demo page to illustrate why. Try saving the page using the Evernote bookmarklet.

There is no clever cross domain iframe hackery involved. All I am doing is checking for the Evernote iframe, and setting its src attribute to point instead to my faked login page which can potentially be used to capture victims' logins - all with just a tiny bit of basic Javascript.

I do not want to come across as an arsehole highlighting this potential security issue. What I really want to do is to remind developers out there the importance of the browser's address bar. Internet security is built upon SSL, and when the https:// and the hostnames are hidden from the users, you can be putting your users at risk. Of course, like all phishing attacks, you cannot stop malicious attackers from faking your login page, but the point is, by avoiding such bad practice, you are making your users much less susceptible to such attacks.

Sunday, April 14, 2013

A Great Day in Harlem - an interactive version

I have always been fascinated by A Great Day in Harlem. Having recently put up a print at home, I wanted to find out who's who in the photo. I did some googling and thought why not create an interactive version. I found this excellent jQuery plugin for converting html image map into something that can actually look pretty sexy, and voila: check out!

Tuesday, April 09, 2013

Javascript Random List Splitter

We had to run an on-boarding email A/B test the other day by randomly splitting thousands of new signups into sub-lists to send out as different campaigns.

This prompted me to write this little JS tool for splitting delimited list (comma, tab, newline and semi-colon) back at home. Enjoy!

Note that the split does not guarantee that each list will receive the same number of items

Sunday, March 03, 2013

London Sewing Machine Museum

What I love about London is all its quirky little-known museums. This weekend, I discovered the London Sewing Machine Museum in Tooting thanks to IanVisits. Housed in an unremarkable warehouse on the busy Balham High Street (308 Balham High Street SW17 7AA) a short walk from the Tooting underground station, this museum is free but is only open on the first Saturday of every month. With its amazing collection of beautifully restored sewing machines from the Victorian era to the Art Deco era, you don't have to know anything about sewing machines to love this place. And yes, what an excuse to get the camera out, after months of winter hibernation!

Thursday, January 03, 2013

what's new - a look at the Javascript "new" operator

Happy new year!

Over the years, I have developed a love-hate relationship with Javascript. Every now and then, I would have some kind of epiphany and be completely in awe of the beauty of the language, only to be struck a few months later by the realisation that I lack understanding in some of the most fundamental concepts of the language. This, I believe, is because, coming from a traditional OO background, I just followed all those "classical inheritance" examples, and never really questioned what is actually going on underneath in this inherently classless language.

Some time ago, I was trying to understand Object.create() more, especially how it differs from calling new Foo(). I got depressed pretty quickly as I was struck again by one of those "I thought I knew it all" moments.

I am not going to actually discuss the difference between Object.create() and new Foo() here. There are plenty of informative articles on the web which explain this topic very well. Instead I am going to just focus on the semantic of the new operator.

Jumping from one blog post to another, I came across this very short and simple article: Here, it states that when you call

 var o = new Foo();  

Javascript actually does this (note the "or something like that" disclaimer):

 var o = new Object();  
 o.[[Prototype]] = Foo.prototype;  

I particularly like this snippet because, while new Foo() is such a widely used language construct, these three lines contain some of the most crucial Javascript concepts which often get overlooked or misconceived by many "classical hierarchists".

  • Foo, the constructor function, is simply a standard function in Javascript. Every function in Javascript has a property called prototype.
  • This prototype property is completely different from the [[Prototype]] prototype that all Javascript objects have.
  • An object's [[Prototype]] prototype points to the object that the current object inherits its states (properties) from.
  • The (constructor) function's prototype property points to the object that the newly constructed object will inherit its states (properties) from. This establishes the newly constructed object's prototype chain. Javascript looks up an object's property by following the prototype chain until a property with the matching name is found.
  • Therefore, changes to the prototype object's state will be reflected in the inheriting object even after object creation. On the other hand, when a property is being set on an object, the property will be created on the object itself.
  • By default, the prototype object itself has a constructor property, which is why the constructor function can be invoked on the newly created object itself. Incidentally, this means we can be sure that "this" in a constructor function always refer to the newly created object. If you are not familiar with how the late binding of "this" works in Javascript, just google for it.

Next time you extend a "class" in Javascript by specifying Car.prototype = new Vehicle(); (or Car.prototype = Object.create(Vehicle.prototype); which is actually slightly different), think about what is happening underneath, how the prototype chain is being established, and what it actually looks like, etc.

Finally, I must give a shout out to Angus Croll for his excellent article: If I had not come across this, I would probably still be none the wiser!