Show contents

Chrome’s requestAutocomplete()

Another Google I/O, and another raft of awesome products. One announced API that I'm particularly excited about is requestAutocomplete(), a feature which is landing in Chrome Canary for Windows and Mobile (with OSX support coming shortly). What this API does, in a nutshell, is give you programatic access to autocomplete (or autofill) data.

Autocomplete was originally designed to make it quicker to fill out forms, but what if we could remove the forms altogether! Back in June I proposed just such an API - a way to programmatically retrieve autofill data stored in the browser. The proposal has evolved, improved, and is now going to be baked into future versions of Chrome.

1Zh85u4gzhhDkC6myiRAyO2SH1iRgCCbUoJ4O.png

What does it look like? Essentially it involves calling requestAutocomplete() on a form element. The form doesn't necessarily need to be shown to the user, but the browser uses it to detect which input types to autocomplete.

<button id="checkout">Checkout</button>  

<form id="payment" hidden>
  <input autocomplete="cc-name" name="myname">
  <input autocomplete="cc-number" name="ccnumber">
  <input autocomplete="cc-exp" name="ccexp">
</form>

<script>
  (function(){
    var form = document.getElementById('payment');
    var button = document.getElementById('checkout');

    if (!("requestAutocomplete" in form)) return;

    button.addEventListener('click', function(){
      form.requestAutocomplete();
    });

    form.addEventListener('autocomplete', function(){
      // The form contains the data. We could either submit it, or read the data
      form.submit();
    });
  }).call(this);
</script>

Once requestAutocomplete() has been called, a permissions info dialog will be displayed by Chrome, prompting the user to share their information with the page.

What does this mean in practice? It means that we can replace most forms with two-click signups and two-click payments, dramatically improving usability and conversion rates.

The fact that most people already have autofill data already in Chrome, and that Chrome is an evergreen browser automatically updating itself, should mean adoption of this API will be swift. Once businesses see improved conversion rate data (something we're working on demonstrating), then integrating with this API should be a no brainer. My hope is that other browser vendors will follow suit and also implement support.

You can find the preliminary API docs on chromium.org.

 
1,603
Kudos

Setting up Sublime Text 2

I recently decided it was finally time to part ways with TextMate, my trusty companion for these last few years, and start the hunt for a new editor. After a quick Twitter poll the unanimous advice was that I should try Sublime Text 2.

After a few weeks of using Sublime Text I can safely say that it's the best editor I've used. It's fast, extendable and hasn't ever crashed on me. That said, that no editor is perfect and Sublime Text does require a fair bit of initial configuration.


After you've downloaded & installed the editor, the first step to configuring Sublime Text 2 is to install the package manager. I'm hoping in future versions of the editor this package manager will come bundled, but for now it requires a separate installation. Run Sublime Text, Press ctrl ` (control backtick) to open the editor's console, and paste in the code listed here.

Once the manager is set up, you can install packages with ⌘⇧p (command shift p) and typing Install Package.

Theme - Soda

Sublime's initial look leaves a lot to be desired. However, luckily there's a beautiful theme called Soda. To install Soda, open the package manager (⌘⇧p), type 'Install Package ↵', and then 'Theme - Soda ↵'.

Screen Shot 2013-04-08 at 12.07.47 PM.png

To activate the theme, open Sublime's preferences ⌘, (command comma), which is a JSON file, and set the "theme" key to "Soda Light.sublime-theme" (Remember to check commas).

{
  "theme": "Soda Light.sublime-theme"
}

You may have to restart the editor, or at least open a new window, for the theme to activate.

Extending the editor

There are a few other packages to install:

Follow the same steps as before to install the packages, ⌘⇧p and "Install package".

Tabs & Spaces

The default indentation style uses tabs instead of spaces, and it's likely that you'll want to switch this (unless you solely program in a language where that's the convention, such as Go). Open Sublime's preferences (Settings - User or ⌘,) and add:

{
  "tab_size": 2,
  "translate_tabs_to_spaces": true
}

If you're anything like me, and dread trailing white space, then you should install the TrailingSpaces package. You'll need to change the default preferences for the plugin too. Open TrailingSpace's preferences (Preferences -> Package Settings -> TrailingSpaces -> Settings - User), and add:

{
  "trailing_spaces_include_current_line": false
}

Also add this to your global user preferences (⌘,):

 "trim_trailing_white_space_on_save": true

Key bindings

There's a key binding I used the whole time in TextMate: ⌘ ctrl r to reveal the currently opened file in the sidebar. You can add this to Sublime by opening the key bindings preferences (Preferences -> Key Bindings - User) and adding:

[
  {"keys": ["ctrl+super+r"], "command": "reveal_in_side_bar"}
]

Sublime's fuzzy search (⌘ t) is incredibly fast and convenient, and it's my primary way of navigating around my projects. As well as navigating by file name, you can go to a particular line in a file by typing :123 (colon line number) or to a particular method by typing #name (hash method name).

Command line

Surprisingly Sublime Text doesn't come with a easily accessible binary, since this is probably the primary way developers will open the editor. That said, you can easily add support by creating a symlink:

ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" /usr/bin/subl

I also use an alias in my ~/.bash_profile file, allowing me to easily open a directory from the terminal:

alias e='subl . &'

Icon

Sublime's default icon is fairly ugly, but there are a few replacements on Dribbble. One of my favorites is by Elliot Jackson. To install it, download the icns file and replace the application's icon:

$ mv ~/Downloads/st2.icns /Applications/Sublime\ Text\ 2.app/Contents/Resources/Sublime\ Text\ 2.icns 

sublime-text-2.png

Pasting

One suggestion from Jason Barry is to use 'Paste and Indent' for ⌘V instead of the standard 'Paste'. This adjusts your indentation to automatically match the context it's pasted in. To do this, put the following in your Key Bindings - User file:

[
  { "keys": ["super+v"], "command": "paste_and_indent" }, 
  { "keys": ["super+shift+v"], "command": "paste" } 
]

More packages

A few more packages you may find useful:

Conclusion

So that's a fair bit of setting up required for an editor, most of which you'd think would be the default configuration. Sublime Text 2 definitely needs a bit of polishing from a product perspective. The default website, icon, and theme are ugly to say the least, and it would be convenient to be able to install the editor through the App Store. A GUI for configuration would be a good idea as storing preferences in JSON files may appeal to programmers, but it definitely alienates designers.

That said it's early days for the editor, and the core framework has clearly been built extremely well. It's ridiculously fast, stable and very extendable. I love it and absolutely recommend you try it.

 
4,662
Kudos

Analyzing my DNA

I recently bought 23andme, a service which requires you to send off a DNA sample, and in return performs a series of interesting tests concerning your health and ancestry. I bought the test as a birthday present to myself, somewhat because I was interested in the results, but also because I wanted to treat it as a catalyst for learning more about the subject.


The first step in the process of getting your DNA analyzed by 23andme, is to put a substantial amount of saliva into to a specialized container they mail you. This saliva contains cheek cells, which is what 23andme use for genotyping. They don't need many cells, but the reason why they ask for so much saliva is so that it's harder to take someone else's DNA without their permission!

Then the DNA sample is mailed off to 23andme's laboratory where it's amplified through PCR, a process where the DNA is separated from the nucleus and replicated. Lastly it's put through a machine which, rather than sequence the whole genome, looking for specific SNPs. These SNPs are responsible for a lot of the biological differences between people, and variations influence a variety of traits such as height, eye color and disease susceptibility.


So now 23andme have analyzed about a million of your SNPs, it's time to draw some conclusions from the genotyping. Most of the health and trait reports are based on genetic association studies, taking a specific SNP and testing for associations with factors like eye color and diseases like Parkinson's. Furthermore, 23andme can correlate diseases and symptoms from all their users to specific SNPs, furthering research and understanding of how they affect our bodies.

Genetic associations are not a certainty that a specific SNP will have a specific outcome, but rather a probability. Correlations doesn't mean causation either, and while there may be an association, additional research is needed to show whether the factor has a causal effect.

There are a bunch of heritable genetic disorders that 23andme tests carrier status for, such as Cystic Fibrosis. While the gene for Cystic Fibrosis is recessive, if you mate with someone who also has the same recessive gene, then the likelihood is that your child will develop the disease is one quater. Other disorders like Huntington's are dominant, and only requires one parent to be a carrier. 23andme doesn't seem to do much testing of dominant genetic disorders, as it's likely that the parents are already aware of the issue.

Working out how SNP affects a phenotype trait is tricky. Most SNP changes have no effect, while other characteristics are due to environmental factors. One way of investigating this, is by studying identical twins. Since they have the exact same DNA, any differences between the two can be attributed to environmental factors. Some phenotypes like height are mostly influenced by your genetics (assuming you have a good nutrition), while others like freckles are more affected by the environment.

This difference between environmental and heritable traits is often called nature vs nuture, and can be fairly controversial at times. Take, for example, IQ. The effect that parents have upon their children's intelligence is in serious dispute and, while a neglectful and abusive upbringing can have an adverse effect, given a base minimum supportive parenting doesn't have have much of an influence on IQ. Studies have shown that identical twins who grow up in separate families have an IQ correlation of 0.74, while adoptive siblings have no more similar IQ than strangers.


I'm not going to talk about the more sensitive health information I gleaned from the report, as while President Bush signed the Genetic Information Nondiscrimination Act I'm still wary of how it could affect my insurance in the future. However, let's talk about a non sensitive trait, lactose intolerance. Lactose intolerance is fairly heritable and is influenced by an SNP near the LCT gene which encodes lactase, an enzyme required for digestion of milk.

Normally, the lactase enzyme is only produced in the first few years of a mammals life. However, certain European populations have a mutation that causes lactase to be produced throughout their lives. Dairy farming, which is widespread primarily in Europe, provided additional sources of nutrition to early inhabitants of Europe. Thus, it is thought, being able to drink milk throughout adulthood would have provided them with an evolutionary advantage.

My genotype for this SNP is AG, or adenine and guanine. This has been correlated with higher adult lactase levels. This allele is rarer in Africa and Asia, hence the high cases of lactose intolerance in those regions.

SNP: rs4988235 (A or G)
Alex's Genotype: AG
Gene: MCM6
Chromosome: 2

As I say, while this trait is heritable, it is also influenced by environmental characteristics such as the bacteria in your gut. In other words, having a AG genotype doesn't always mean you'll be lactose tolerant, and vice versa. It's all about probability, and in this case 23andme were correct - I am lactose tolerant, which is useful as I enjoy milk!


Calculating ancestry through DNA is an interesting process, because it turns out that the variations between you and your ancestor's DNA make it impossible to detect relations after a few generations or so. However the Y chromosome is passed down from father to son without much alteration, which means it makes a perfect candidate for looking into your past. Maternal descent is calculated from DNA found in the mitochondria, as this too is passed down unaltered from mother to child. Using these two pieces of information we can look hundreds of thousands of years into our past, as well as at our more recent history.

My ancestors, on both my mother's and father's side, are from Europe - mostly from the UK, Ireland and Scotland, with a little Spanish and German mix. My DNA is 2.9% neanderthal, which puts me in the top 91% of 23andme's members (not sure what conclusions to draw from that!). I'm also distantly related to Jesse James on my mother's side, and have found a previously unknown second cousin in Scotland.

Genetic family trees can be identified by looking at haplogroups, a set of genetic mutations that are shared by everyone in the group. The likelihood is that if you share a lot of specific genetic mutations with someone, than you're related. All haplogroups can be traced back to a mutation in a single individual.

For example, 8 percent of asian males are in the same haplogroup as Genghis Khan, and carry Y chromosomes that share many of the same SNPs. Y chromosomes aren't recombined when they're inherited, so genetic mutations in them act as markers, allowing geneticists to trace them back and predict in time the moment they occurred. Such a rapid spread of this particular mutation is unlikely to have happened by chance, and suggests that 0.5% of the world's population are descendants of Genghis Khan and his male relatives - quite a staggering amount.

Geneticists can trace back humans to a single male and female, a genetic “Adam and Eve”. What's fascinating is that while Adam lived about 142,000 years ago, Eve lived much earlier, about 200,000 years ago - they never met each other. Y-chromosomal Adam lived at a time close to the migration from Africa, and this turmoil could suggest a reason why so few males lineages survived.


Analyzing my DNA has given me a fascinating insight into my health and ancestry, and something I'd recommend to everyone. However, personally the best part of the whole process was learning more about DNA and how it effects us. It's a fascinating subject which is undergoing a lot of research.

On a separate note, 23andme's service is really commendable. Businesses that combine commercial products with scientific research and advances are close to my heart. Other examples of this kind of approach are SpaceX and Tesla.

 
1,162
Kudos

Abba - JavaScript a/b testing

Abba is a self-hosted a/b testing framework built to help improve conversion rates on your site.

Tuning signup and payment forms can have huge effects on your business, and it's a good idea to supplement design and copy changes with data on how differences actually effect conversion.

We built this tool for internal use at Stripe, and today we're open-sourcing it for everyone. The key design goal of Abba is to have a great JavaScript API (unlike some of the other a/b testing services out there). For example:

<script src="//localhost:4050/v1/abba.js"></script>

<script>
  Abba('test name')
    .control('test a', function(){
      // Show test a
      $("#test-a").show();
      $("#test-b").hide();
    })
    .variant('test b', function(){
      // Show test b
      $("#test-b").show();
      $("#test-a").hide();
     })
    .start();
</script>

<script>
  $('button.complete').click(function(){
    // Successful conversion, mark the test as complete
    Abba('test name').complete();
  });
</script>

Here we're setting up a control called test a, and a variant called test b. Sometimes the callback associated with the control will be invoked, and sometimes the variant's callback will be run. Stats are sent back to the analytics server, hosted by you, where they are displayed in an admin interface.

You can see conversion rates per day for a configurable time period and even slice data by browser type. The different variants can be weighted such that some appear more times than others. Lastly we calculate a z-score for the displayed conversion rates, indicating the statistical probability that a test's results are accurate.

See the GitHub project for the source and more information.

 
1,418
Kudos

Stripe Push Notifications

What's the best kind of Push Notification? One that tells you you've made more money of course.

Stripe Push is a little side-project that sends you Apple Push Notifications whenever you get a new charge or transfer via Stripe.

Screen Shot 2013-02-08 at 12.33.56 PM.png

You can configure what type of notifications you want to receive and their frequency. I've open sourced the Sinatra and Mac app behind it on GitHub.

Get it from the Mac App Store.

 
530
Kudos

Life TODO

Sitting in the top left of my browser's tabs, always open, is a Google Docs document titled TODO. This document essentially contains my current state and my aspired state. It contains everything I want to accomplish in the next few days, the next months, and in the longer term. It contains all my ideas and thoughts. Lastly, it contains my Bucket List - a list of experiences and aspirations I'd like to achieve while on this planet.

Creating a life TODO list is one the most useful things I've ever done. It doesn't need to be anything special, mine's just a series of bullet points in no particular order, but the very act of committing your goals and ideas to paper seems to make them that much more tangible and achievable.

It turns out that there have been numerous studies showing that writing down your goals has a measurable impact on actually achieving them. Dr. Gail Matthews from the Dominican University in California performed a study which concluded that those who committed their goals to paper, and shared them with a friend, were 33% more likely to achieve them than those that merely formulated goals.

Naturally this list is in constant flux, and as I grow older my priorities change. The essence is still there though and my initial hopes and ambitions aren't watered down or compromised. Putting my life goals next to my todo list forces me to see them every day.

Creating this list has provided me with a few things. Firstly, a sense of accomplishment. I can see my progress, and cross things off as I go along. This also helps me break down more overwhelming and ambitious tasks into smaller manageable pieces, thus completing more.

Secondly, it prevents distraction, and lets me focus on things that are truly important to me rather than mere diversions. As soon as I wake up I know my current state and what needs to be done.

Lastly, this list provides perspective. It pitches my current concerns against the bigger picture which, more often than not, trivializes them. It's a sounding board for future decisions and goals.

So perhaps making a Life TODO list can be your New Year's resolution. I realize this maybe old-hat to some of you, but having one has certainly helped me navigate life's turbulent waters.

 
1,425
Kudos

All you need to know about CSS Transitions

CSS3 transitions bring simple and elegant animations to web applications, but there's a lot more to the spec than first meets the eye.

In this post I'm going to delve into some of the more complicated parts of CSS transitions, from chaining and events to hardware acceleration and animation functions.

Letting the browser control animations sequences allows it to optimize performance and efficiency by altering the frame rate, minimizing paints and offloading some of the work to the GPU.

Browser support

CSS transitions are supported in practically every version of Firefox, Safari and Chrome. They're supported in IE 10 and onwards. If CSS animations aren't supported in a given browser, than the properties will be applied instantly, gracefully degrading.

Webkit based browsers (Safari and Chrome), still require -webkit prefixes for animations and gradients, but these are soon being removed.

Applying transitions

A simple way of applying transitions is with CSS pseudo-classes, such as :hover. Notice we're specifying the property name, the length of transition, and one of the default timing functions, linear [demo].

.element {
  height: 100px;
  transition: height 2s linear;
}

.element:hover {
  height: 200px;
}

When the :hover pseudo-class is activated, the height will be transitioned linearly from 100px to 200px over a period of 2 seconds.

duration is the only required item in the transition shorthand. The browser defaults to a timing function of ease, and a property of all, unless these are provided.

We don't want to be restricted to using psuedo-classes when it comes to activating transitions - clearly that's not very flexible. The solution is to programmatically add and remove classes [demo].

/* CSS */
.element {
  opacity: 0.0;
  transform: scale(0.95) translate3d(0,100%,0);
  transition: transform 400ms ease, opacity 400ms ease;
}

.element.active {
  opacity: 1.0;
  transform: scale(1.0) translate3d(0,0,0);
}

.element.inactive {
  opacity: 0.0;
  transform: scale(1) translate3d(0,0,0);
}

// JS with jQuery
var active = function(){
  $('.element').removeClass('inactive').addClass('active');
};

var inactive = function(){
  $('.element').removeClass('active').addClass('inactive');
};

In the example above, we've got two different transitions, the element slides up when activated, and fades out when deactivated. All the JavaScript does is toggle the two classes active and inactive.

Transitioning gradients

Not every CSS property can be transitioned, and the basic rule is that you can only transition through absolute values. For example, you can't transition between a height of 0px to auto. The browser can't calculate the intermediate transition values, so the property change is instant. Oli Studholme has conveniently provided a full list of transition support properties.

The other major property that can't be transitioned between is background gradients (although pure colors are supported). There's no technical reason behind this limitation, it's just taking a while for the browsers to implement support.

In the mean time, there are a few good workarounds. The first involves adding a transparency to the gradient, and then transitioning between background colors. For example [demo]:

.panel {
  background-color: #000;
  background-image: linear-gradient(rgba(255, 255, 0, 0.4), #FAFAFA);
  transition: background-color 400ms ease;
}

.panel:hover {
  background-color: #DDD;
}

If the gradient is continuous, you can transition the background-position as documented here. Otherwise, your last resort is to create two elements, one overlaid on top of the other, and transition their opacity [demo].

.element {  
  width: 100px;  
  height: 100px;  
  position: relative;
  background: linear-gradient(#C7D3DC,#5B798E);    
}  

.element .inner { 
  content: '';
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  background: linear-gradient(#DDD, #FAFAFA);          
  opacity: 0;
  transition: opacity 1s linear;
}

.element:hover .inner {
  opacity: 1;
}

The caveats to the latter approach are that it does require extra markup, and the inner div can catch pointer events. Pseudo elements, such as :before and :after would be an ideal use-case here, but unfortunately only Firefox supports pseudo element transitions. Eliott Sprehn is working on support for Webkit, which is coming soon.

Hardware acceleration

Transitioning certain properties, such as left and margin causes the browser to recalculating styles every frame. This is fairly expensive, and can lead to unnecessary re-paints, especially if you have a lot of elements on the screen. This is especially noticeable in less powerful devices, such as mobiles.

This solution is to offload the rendering to the GPU using CSS transformations. In simple terms, this turns the element into an image during the transition, avoiding any style recalculations which greatly increases performance. A simple way of forcing the browser to hardware render an element is to set the transformation's z axis, which you can do with translate3d:

transform: translate3d(0,0,0);

Now, this isn't a magic cure to performance problems, and comes with lots of issues of its own. You should only use hardware acceleration when it's required, and certainly not enable it on every element.

For example, hardware acceleration can cause subtle font issues, such as a font appearing to lose its weight. This is due to a bug where subpixel anti-aliasing isn't supported when an element is being hardware accelerated. You can see a clear difference between the two rendering modes:

antialiasing.png

The short-term fix, albeit controversial, is to disable subpixel anti-aliasing completely. However, be sure to understand the caveats in doing so.

  font-smoothing: antialiased;

In addition, different browsers use different hardware acceleration libraries, which can cause cross-browser problems. For example, whilst Chrome and Safari are both built on WebKit, Chrome uses Skia for graphics rendering while Safari uses CoreGraphics. The differences between the two are subtle, but real.

You can use Chrome's Inspector to Profile the page, showing all the repaints. Additionally you can show paint triangles in the Inspector's options, and even turn on Composited Render Layer Borders in about:flags to see which layers are operating on the GPU. The key is to reduce paints by batch updating the DOM, and move as much as possible to the GPU.

Painting

If you're having display issues between browsers with hardware acceleration, such as flickering or juddering, make sure you're not nestling elements with the transform3d() CSS property set. As a last resort, try having browser specific transformations.

It's worth noting that the translate3d hack is becoming less relevant. In fact recent builds of Chrome automatically use the GPU for opacity and 2d transitions. iOS6 Safari has explicitly disabled this trick, and requires yet more workarounds.

Clipping

To take advantage of GPU rendering, you'll need to avoid style recalculations by using CSS transformations rather than properties like width. What do you do though if you do need to animate an element's width? The solution is clipping.

In the example below, you can see a search box with two transition states. The second expanded state is hidden by a clipping element.

Clipping

To transition to the expanded width, all we need to is translate the X axis left. The key thing here is that we're using translate3d rather than altering the element's width [demo].

.clipped {
  overflow: hidden;
  position: relative;
}

.clipped .clip {
  right: 0px;
  width: 45px;
  height: 45px;
  background: url(/images/clip.png) no-repeat
}

input:focus {
  -webkit-transform: translate3d(-50px, 0, 0);
}

By ensuring that we're not recalculating the element's width every frame, the transition will a whole lot smoother and performant.

Timing functions

So far we've been using some of the browser's pre-defined timing functions: linear, ease, ease-in, ease-out and ease-in-out. For more complex timing functions we're going to have to write our own timing function by specifying four points along a cubic-bezier curve.

transition: -webkit-transform 1s cubic-bezier(.17,.67,.69,1.33);

Rather than guessing at values, it's often easier to either use a bunch of pre-defined curves, or play around with a graphing tool.

Cubic-bezier

Notice you can drag the values out of bounds and produce a bouncing transition, for example:

transition: all 600ms cubic‑bezier(0.175, 0.885, 0.32, 1.275);

Programmatic transitions

Writing transitions in CSS is all very well, but sometimes you need a bit more control, especially when it comes to chaining transitions. Luckily we can not only invoke transitions from JavaScript, but also define them.

CSS transitions take a magical all property which ensures that any property changes are transitioned. Let's see how to use this in practice [demo].

var defaults = {
  duration: 400,
  easing: ''
};

$.fn.transition = function (properties, options) {
  options = $.extend({}, defaults, options);
  properties['webkitTransition'] = 'all ' + options.duration + 'ms ' + options.easing;
  $(this).css(properties);
};

Now we have this jQuery function $.fn.transition, which we can use to programmatically invoke transitions.

$('.element').transition({background: 'red'});

Transition callback

The next step to chaining transitions is having transition end callbacks. You can achieve this in Webkit, by listening to the webkitTransitionEnd event. For other browsers, you'll need to do a bit of sniffing to find the right event name.

  var callback = function () {
    // ...
  }

  $(this).one('webkitTransitionEnd', callback)
  $(this).css(properties);

Be aware that sometimes this event doesn't fire, usually in the case when properties don't change or a paint isn't triggered. To ensure we always get a callback, let's set a timeout that'll trigger the event manually.

$.fn.emulateTransitionEnd = function(duration) {
  var called = false, $el = this;
  $(this).one('webkitTransitionEnd', function() { called = true; });
  var callback = function() { if (!called) $($el).trigger('webkitTransitionEnd'); };
  setTimeout(callback, duration);
};

Now we can invoke $.fn.emulateTransitionEnd() before we set the element's CSS to ensure our transition end callback is triggered [demo].

$(this).one('webkitTransitionEnd', callback);
$(this).emulateTransitionEnd(options.duration + 50);
$(this).css(properties);

Chaining transitions

So now we can programmatically apply transitions, getting callbacks when they finish, we can start queuing transitions. We could write our own queue to do this, but as we're using jQuery we might as well tap into the library's existing functionality.

jQuery provides two main functions to communicate with its queuing API, $.fn.queue(callback) and $.fn.dequeue(). The former adds a callback to the queue, while the latter executes the next item on the queue.

In other words we need to set our CSS transition inside a $.fn.queue callback, and then make sure we invoke $.fn.dequeue when the transition is complete [demo].

var $el = $(this);
$el.queue(function(){
  $el.one('webkitTransitionEnd', function(){
    $el.dequeue();
  });
  $el.css(properties);
});

That's example is fairly simple, but it lets us build up complex chained animations, and even use jQuery's delay() function; for example:

$('.element').transition({left: '20px'})
             .delay(200)
             .transition({background: 'red'});

Redrawing

Often when transitioning, you'll have two sets of CSS properties. The initial properties that the animation should start at, and the final set of properties the transition should end on.

$('.element').css({left: '10px'})
             .transition({left: '20px'});

However, you'll find that if you apply both sets of properties, one immediately after the other, then the browser tries to optimize the property changes, ignoring your initial properties and preventing a transition. Behind the scenes, browsers batch up property changes before painting which, while usually speeding up rendering, can sometimes have adverse affects.

The solution is to force a redraw between applying the two sets of properties. A simple method of doing this is just by accessing a DOM element's offsetHeight property, like so [demo]:

$.fn.redraw = function(){
  $(this).each(function(){
    var redraw = this.offsetHeight;
  });
};

This will work in most browsers, but I've had occasions in Android where this hasn't been enough. The alternative is to either use timeouts, or by toggling a class name.

$('.element').css({left: '10px'})
             .redraw()
             .transition({left: '20px'});

The future

Transitions are being actively worked on, and the next spec looks really promising. The proposals include a new JavaScript API focussing on addressing some of the existing limitations to transitions, and giving developers much more flexibility.

In fact, you can find a shim on the new API on GitHub. It involves instantiating a Animation constructor, passing in an element to animate, the properties to animate to, and various other options such as a delay.

var anim = new Animation(elem, { left: '100px' }, 3);
anim.play();

With this new API you can synchronize animations, provide custom timing functions, and get completion callbacks. This is truly exciting stuff!

Transitions

By now, you hopefully have a deeper understanding of CSS transitions, and how a simple API can be combined to produce complex and rich effects.

Most of the JavaScript examples come straight out of the source of GFX, a jQuery CSS transition library. As well as the core library, I've included a number of additional effects, such as slide in/out, explode in/out and 3d flipping.


Thanks to Paul Irish for reviewing this article.

Incidentally, I've been turning the contents of this post into a talk. If you know or organize a conference that would be suitable for this material, please do get in touch! Over the last year I spoke at six conferences, and I'm keen to do even more in 2013.

 
8,223
Kudos

Humble Beginnings

It's easy to forget the humble beginnings that great companies start from, and it's tempting to gloss over the fact that companies, now on the global stage, were once small projects with ugly designs and hacky implementations.

Rarely do people set out with grand visions to create a massively successful company, but rather their ideas evolve gradually. Twitter started out as a podcasting site, Flickr a multiplayer game, Youtube a dating website, Yelp a email recommendations service and PayPal was hell bent on transferring IOUs between Palm Pilots.

Not only did these companies pivot, they also renamed, rebranded and launched with terrible designs.

Twitter

Take, for example, Twitter. Here's a screenshot of one of their earliest designs before they could afford vowels:

Twitter Redesign

Luckily they then went on to do a redesign, but still a far cry from their current look. The first articles announcing Twitter lauded it as a sort of “group send” SMS application.


Facebook

How about Facebook? Well, they were originally called thefacebook.com (which still resolves), with a simple and ugly design that reminds me of most online forums. They've kept that recognizable blue, but my favorite part is the Mark Zuckerburg production tag line.

The Facebook


Youtube

Again, the ugly trend continues, and what at first glance looks like it could be the Youtube we know, reveals upon further inspection search fields to help you find not videos, but people. Specifically, people to date.

Youtube

It's interesting to see that their logo survived the pivot, but I guess it's a fairly generic design and message.


Stripe

While we are by no means comparable to the aforementioned companies, I thought it would be fun to include a look at Stripe's earlier days.

We first launched as /dev/payments, before re-branding to Stripe. Our first design was equally humble, the management interface was fairly janky, and it took about 45 days to receive your money.

Screen%20shot%202010-06-18%20at%2010.50.50%20AM.png


Humble

All of these successful tech companies were simple, humble and ugly when they first launched, but the one thing they all had in common is that they did something simple, and they did it well.

Simple in terms of product mind you, not necessarily technically. Video converting and streaming, for instance, are far from simple technologies, and let's not even get into the complexities of the payments industry. Technical difficulties though, were in service of product simplicity.

The key is to find a market with a small and easily definable problem to solve, but also a market large enough to accomodate further growth and disruption. Solving a specific problem will get your foot in the door, giving you leverage to throw it right open later down the line.

Being flexible is much more important than knowing the end game. Just come in, build something small, and grow it one step at a time. Everything starts from humble beginnings.


Thanks to Daniel Zarick for the inspiration behind this article.

 
1,273
Kudos

5 APIs that will transform the Web in 2013

It's incredibly exciting to see how the Web is evolving, and 2013 has a lot more in store. Over the next year, there are a number of technologies coming down the pipeline that have the potential to radically transform how we use and develop for the Web.

CSS Custom Filters

CSS filters are already in Chrome and Safari, and allow advanced styling as as blurring, warping and modifying the color intensities of elements. However, that's only the start of it. CSS Custom Filters let you write your own fragment and vertex shadows in GLSL, a language that has been integral to traditional 3D rendering over the past 10 years or so.

What this means in practice, is that you can create incredible effects. Combined with CSS transitions you can produce beautiful transformations, from page curls, to folding elements. The limit is your imagination!

So when can you use this? Adobe have been pioneering this technology, and Custom Filters are already available in Chrome under a flag. Expect to see them in Chrome early next year. For now, you can play with them in Canary.

Autocomplete API

This API has the potential to radically transform signups and payments on the web. Autocomplete was designed to make it easer to fill out forms, and there's even now a spec to hint inputs relate to which data.

However, autocomplete is treating the symptoms and not the disease. Back in June I proposed an API to programmatically retrieve autofill data stored in the browser. What this means in practice, is that we can replace most forms with one-click signups, and one-click payments, dramatically improving usability and conversion rates.

The Chrome team have been working on this idea, and in October submitted a proposal and patch to WebKit. This is incredibly exciting and, combined with Mozilla Persona, could revolutionize registration and payments on the web.

So when can you expect to see this in the wild? Well, while the behind the scenes work has been done, Chrome still needs to implement UI integration for it. I think we'll see this late next year.

Google Chrome Apps

What if I told you that Google had snuck an operating system across all your devices, including your laptop and cell phone. Rather than compete with Microsoft and Apple by building a separate OS, Google decided to build their own platform on top of the existing operating systems. This platform is called Chrome.

So step one is distribution, which Chrome has now been achieved with more than 350 million users. Step two is extending Chrome's APIs, giving developers greater access to the operating system and replacing the need for conventional desktops applications.

A few months ago, Google quietly released Chrome Packaged Apps, which let developers build desktop apps powered by Chrome. They can be installed with one-click from the Chrome Web Store, access system APIs such as USB, Bluetooth and UDP Sockets, and can be opened from desktop shortcuts. These apps are completely cross-platform, standalone and appear native to the untrained eye. In many ways, these hybrids combine the best the web and desktop worlds.

So what's the catch? Well, Chrome Apps aren't quite ready for prime time just yet, and the APIs are still in flux. For example, creating a custom drag bar is still tricky. I'd give them a few months to be production ready.

ECMAScript 6

ECMAScript 6 (ES6), the next version of JavaScript, has some exciting new additions that fix some of the language's ugly parts as well as provide some new features such as default parameters and restructuring.

Classes are also on the agenda, with full inheritance and mixins. Rather than emulating modules with CommonJS or AMD, ES6 makes them a first class citizen, inspired by a pythonesque import system.

One part of ES6 I'm particularly excited about, the part that can't be simulated by abstractions like CoffeeScript, is proxies. ES6 proxies let us dynamically look up function names at runtime, allowing functionality like Ruby's method_missing. This, combined with getters and setters, will enable all sorts of interesting DSLs and APIs.

ES6 generators are going to completely transform how we write asynchronous JavaScript. Instead of the callback spaghetti we're used to, we can call asynchronous functions with a synchronous API using the yield keyword. You can see an example of this in task.js.

spawn(function*() {
  var data = yield $.get(url);
  $('#result').html(data);
});

You may have seen a similar API in Ruby using Fibers. Personally callbacks have been a major annoyance to me when writing evented code in MVC Node apps, and I've been playing around with Node continuations with a library called Ace. I'm really glad these being made native to the language.

Much of ES6 is currently available in Chrome under the flag Experimental JavaScript. It'll be released early next year. You can also use ES6 in Node right now using the --harmony command line option.

Web Components

Web Components and the Shadow DOM just expose the way native elements are created internally in the browser. Using the API, you can define your own HTML elements, including style and behavior. Like native HTML elements, they can be embedded with a single tag.

Web Components are going to transform the way JavaScript libraries are written and distributed. They can be completely decoupled, easily integrated, and are the main reason why Jacob and I wrote the package manager Bower.

For example, I could write a useful map component, add it to a package manager, and another developer could integrate it into their application with a single tag. Components are decoupled from each other, and their internal HTML, CSS and JavaScript abstracted away behind a custom tag.

Web Components are available under the Enable experimental WebKit features flag in Chrome. For now, you can use this with this x-tags polyfill from Mozilla.

The Future

A common reaction to any discussion of new Web APIs is a denouncement that it may be many years before any of these can be used in the wild. However, I'm extremely optimistic for the future.

While many of these APIs will take some time to filter over to other browsers, the market share that WebKit wields will pressure other browser vendors to offer their own implementations. Indeed, it hasn't taken long for HTML5 features to become production viable. As for backwards compatibility, many of these APIs can be poly-filled, or progressively degraded.

The reason why the future is so bright is evergreen browsers, or browsers that automatically update in the background. It takes about 18 weeks for a new feature in Chrome's Canary to be rolled out to its ~350 million users. That's an incredibly fast adoption rate, and innovation is happening quicker than ever before.

2013 is going to be a big year for the web!

 
4,347
Kudos

Small

Looking down from his perch on the edge of space, Felix Baumgartner remarked:

Sometimes you have to be really high,
to see how small you really are.

It turns out that this feeling is a well documented phenomena dubbed the Overview effect. When a person gazes upon Earth from outer space, they have a profound sense of perspective, a realization of fragility, that humanity and all life as we know it is completely dependent on a single planet and its thin atmosphere.

It suddenly struck me that that tiny pea, pretty and blue, was the Earth. I put up my thumb and shut one eye, and my thumb blotted out the planet Earth. I didn't feel like a giant. I felt very, very small.
— Neil Armstrong

So while the first astronauts to the moon went as technicians, they came back as humanitarians. In the words of William Anders, “We came all this way to explore the moon, and the most important thing is that we discovered the Earth.”

The view of the Earth from the Moon fascinated me—a small disk, 240,000 miles away. It was hard to think that that little thing held so many problems, so many frustrations. Raging nationalistic interests, famines, wars, pestilence don't show from that distance.
— Frank Borman, Apollo 8

As Voyager 1 was approaching the edge of our Solar System, Carl Sagan convinced the team at NASA to rotate the probe and send one last photograph back. A photograph portraying the earth as a tiny blue dot contrasted against the emptiness of space.

Pale_Blue_Dot.png

This photograph wasn't taken for purely scientific reasons, but had a deeper significance which Sagan elaborated on in his book Pale Blue Dot:

There is perhaps no better a demonstration of the folly of human conceits than this distant image of our tiny world.

Look again at that dot. That's here, that's home, that's us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives. The Earth is a very small stage in a vast cosmic arena.

It's no coincidence that the word small is endemic to experiences of space. In all these quotes from astronauts, the word comes up time and time again. Compared against the vastness of space, all our quarrels, conceits and concerns fade away into insignifiance.

It's for this reason, the Overview effect, that I am extremely excited about the prospects of Space Tourism. With more people viewing the Earth from afar, perhaps the world will gain a little more perspective, and a better sense of proportion.

 
2,122
Kudos