<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
    <title>Usability, etc.</title>
    <description>Making things easier to use through good design</description>
    <link>http://usabilityetc.com/</link>
    <atom:link href="http://usabilityetc.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 19 Jun 2016 15:48:53 +0100</pubDate>
    <lastBuildDate>Sun, 19 Jun 2016 15:48:53 +0100</lastBuildDate>
    <generator>Jekyll v3.1.6</generator>
    
        <item>
        <title>How to Create Leaflet Control and Layer Plugins</title>
        <description>&lt;p&gt;This post explains how to implement control and layer plugins for the &lt;a href=&quot;http://leafletjs.com&quot;&gt;Leaflet&lt;/a&gt; JavaScript mapping library. Although the Leaflet documentation has a &lt;a href=&quot;http://leafletjs.com/2013/06/28/leaflet-plugin-authoring-guide.html&quot;&gt;plugin authoring guide&lt;/a&gt;, the guide focuses on best practices for organising, presenting and demonstrating Leaflet plugin code. In this post, I focus on explaining the structure and lifecycle of Leaflet plugins. Template code for creating Leaflet control and layer plugins is &lt;a href=&quot;https://github.com/UsabilityEtc/leafletjs-plugin-templates&quot;&gt;available on GitHub&lt;/a&gt; under the MIT license.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;leaflet-control-plugins&quot;&gt;Leaflet Control Plugins&lt;/h2&gt;

&lt;p&gt;Leaflet control plugins add user interface controls that act on a Leaflet map or it’s layers. Two examples of Leaflet controls are the zoom control and the layers control shown at the top left and top right of the following Leaflet map:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/creating-leaflet-plugins/leaflet-controls.png&quot; alt=&quot;Leaflet JS map with zoom and layer controls&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;creating-a-leaflet-control-plugin&quot;&gt;Creating a Leaflet Control Plugin&lt;/h3&gt;

&lt;p&gt;Leaflet control plugins are JavaScript classes that extend the Leaflet &lt;code&gt;L.Control&lt;/code&gt; &lt;a href=&quot;http://leafletjs.com/reference.html#class&quot;&gt;class&lt;/a&gt;. A common naming convention is to add the name of the control plugin to Leaflet’s namespace, which is &lt;code&gt;L&lt;/code&gt;. The following code creates a control plugin with a class named &lt;code&gt;L.MyLeafletControl&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.MyLeafletControl = L.Control.extend({
  options: {
    position: &#39;topright&#39;
  },

  ...

}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;extend&lt;/code&gt; method of &lt;code&gt;L.Control&lt;/code&gt; takes a single object parameter that contains the properties and methods the plugin will add to the &lt;code&gt;L.Control&lt;/code&gt; subclass. Many control plugins have a set of default settings. In the code snippet above, the &lt;code&gt;options&lt;/code&gt; object contains a single &lt;code&gt;position&lt;/code&gt; setting with a default value of &lt;a href=&quot;http://leafletjs.com/reference.html#control-&#39;topright&#39;&quot;&gt;&lt;code&gt;topright&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The standard Leaflet plugin creation pattern is to implement a factory function that enables the creation of the plugin to be chained with other function calls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.myLeafletControl().addTo(map);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The common convention is to name the factory function after the class of the control plugin but make the first letter lower case.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.myLeafletControl = function(options) {
  return new L.MyLeafletControl(options);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;the-control-plugin-lifecycle&quot;&gt;The Control Plugin Lifecycle&lt;/h3&gt;

&lt;p&gt;The following methods are called when a control plugin is added to a Leaflet map:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;initialize()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onAdd()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Leaflet calls the &lt;code&gt;initialize&lt;/code&gt; method when an instance of a control plugin is created with a call to &lt;code&gt;new&lt;/code&gt;. In the following &lt;code&gt;initialize&lt;/code&gt; method, we call &lt;code&gt;L.Util.setOptions&lt;/code&gt; to combine the values of the default settings (specified by the &lt;code&gt;options&lt;/code&gt; object parameter passed to the &lt;code&gt;L.Class.extend&lt;/code&gt; method) with the values of the settings for this instance of the control plugin, which are specified by the &lt;code&gt;options&lt;/code&gt; object passed as a parameter to the &lt;code&gt;initialize&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;initialize: function(options) {
  L.Util.setOptions(this, options);
  // Continue initializing the control plugin here.
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Any further set up code for the control plugin should be added to the &lt;code&gt;initialize&lt;/code&gt; method after the call to &lt;code&gt;setOptions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Leaflet calls the &lt;code&gt;onAdd&lt;/code&gt; method when the control is added to the map with the following method calls:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;control.addTo(map);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;map.addControl(control);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Control plugins are user interface elements that Leaflet displays on top of the map. The &lt;code&gt;onAdd&lt;/code&gt; method must return the DOM element that contains the user interface of the control. In the following example, we create a HTML &lt;code&gt;div&lt;/code&gt; element with a class of &lt;code&gt;my-leaflet-control&lt;/code&gt; to enable the control to be styled with CSS (1).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;onAdd: function(map) {
  var controlElementTag = &#39;div&#39;; // 1
  var controlElementClass = &#39;my-leaflet-control&#39;;
  var controlElement = L.DomUtil.create(controlElementTag, controlElementClass);

  // Continue implementing the control here.

  return controlElement; // 2
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After creating the &lt;code&gt;div&lt;/code&gt; container for the control, add any other code required to implement the control before returning the control DOM element (2).&lt;/p&gt;

&lt;p&gt;Leaflet calls a third control plugin method called &lt;code&gt;onRemove&lt;/code&gt; when the control is removed from the map:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;control.removeFrom(map);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;map.removeControl(control);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;onRemove&lt;/code&gt; method is the place to tear down your control by releasing resources and removing event listeners, etc.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;onRemove: function(map) {
  // Tear down the control.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;styling&quot;&gt;Styling&lt;/h3&gt;

&lt;p&gt;Leaflet control plugins can be styled with CSS like any other DOM element. Here we add style rules to the &lt;code&gt;my-leaflet-control&lt;/code&gt; CSS class that we added to the control’s container &lt;code&gt;div&lt;/code&gt; element in the &lt;code&gt;onAdd&lt;/code&gt; method above:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.my-leaflet-control {
  // Style the Leaflet control plugin here.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;leaflet-layer-plugins&quot;&gt;Leaflet Layer Plugins&lt;/h2&gt;

&lt;p&gt;Leaflet layer plugins enable Leaflet to display new types of layers.&lt;/p&gt;

&lt;h3 id=&quot;creating-a-leaflet-layer-plugin&quot;&gt;Creating a Leaflet Layer Plugin&lt;/h3&gt;

&lt;p&gt;Leaflet layer plugins are JavaScript classes that extend the Leaflet &lt;code&gt;L.Layer&lt;/code&gt; &lt;a href=&quot;http://leafletjs.com/reference.html#class&quot;&gt;class&lt;/a&gt;. A common naming convention is to add the name of the layer plugin to Leaflet’s namespace, which is &lt;code&gt;L&lt;/code&gt;. Here, let’s create a plugin control with a class named &lt;code&gt;L.MyLeafletLayer&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.MyLeafletLayer = L.Layer.extend({
  ...
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The standard Leaflet plugin creation pattern is to implement a factory function that enables the creation of the plugin to be chained with other function calls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.myLeafletLayer().addTo(map);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The common convention is to name the factory function after the class of the layer plugin but make the first letter lower case.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;L.myLeafletLayer = function(options) {
  return new L.MyLeafletLayer(options);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;the-layer-plugin-lifecycle&quot;&gt;The Layer Plugin Lifecycle&lt;/h3&gt;

&lt;p&gt;The following methods are called when a layer plugin is added to a Leaflet map:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;initialize()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;onAdd()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Leaflet calls the &lt;code&gt;initialize&lt;/code&gt; method when an instance of the layer plugin is created with a call to &lt;code&gt;new&lt;/code&gt;. A common layer plugin pattern is to pass the latitude and longitude position of the layer as a key/value pair of the &lt;code&gt;options&lt;/code&gt; parameter passed to the &lt;code&gt;initialize&lt;/code&gt; method. Recording the position of the layer (1) enables the plugin to update the layer correctly when responding to zoom events (described below).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  initialize: function(options) {
    this._latLng = options.latLng; // 1
    // Continue initializing the layer plugin here.
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Leaflet calls the &lt;code&gt;onAdd&lt;/code&gt; method when the layer is added to the map:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;layer.addTo(map);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;map.addControl(layer);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far, creating a Leaflet layer plugin has been very similar to creating a control plugin. The main difference between layer and control plugins is in the amount of work the &lt;code&gt;onAdd&lt;/code&gt; method needs to perform. A common pattern when implementing the &lt;code&gt;onAdd&lt;/code&gt; method of a layer plugin is to begin by retain a reference to the map to be able to use it when handling events (1).&lt;/p&gt;

&lt;p&gt;Next, the &lt;code&gt;onAdd&lt;/code&gt; method creates the DOM element that will contain the layer (2). Although it is common for Leaflet layer plugin authors to implement the layer as a DOM element, it is not a requirement. For example, Mike Bostock has a nice example of &lt;a href=&quot;https://bost.ocks.org/mike/leaflet/&quot;&gt;overlaying an SVG element on a Leaflet map&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Regardless of whether the layer is implemented as a DOM or SVG element, it is important to add the &lt;code&gt;leaflet-zoom-hide&lt;/code&gt; CSS class to the element (3). Leaflet hides elements with the &lt;code&gt;leaflet-zoom-hide&lt;/code&gt; class while the map is zooming to improve performance (3).&lt;/p&gt;

&lt;p&gt;Unlike a Leaflet control plugin, which is added to the map with a call to &lt;code&gt;map.addControl(control)&lt;/code&gt;, Leaflet layer plugins must explicitly add themselves to the overlay pane Leaflet makes available for plugins (4).&lt;/p&gt;

&lt;p&gt;After adding itself to a Leaflet map, a layer plugin must start listening for Leaflet’s &lt;code&gt;viewreset&lt;/code&gt; event (5). Leaflet generates a &lt;code&gt;viewreset&lt;/code&gt; event whenever the user zooms the map. The &lt;code&gt;_updatePosition&lt;/code&gt; method is our custom &lt;code&gt;viewreset&lt;/code&gt; event handler that is responsible for repositioning the layer as the map is zoomed.&lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;_updatePosition&lt;/code&gt; method performs the calculation for positioning the layer correctly on the map, we call it now to give the layer a correct initial position (6).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;onAdd: function(map) {
  this._map = map; // 1

  var layerElementTag = &#39;div&#39;; // 2
  var layerElementClasses = &#39;.my-leaflet-layer leaflet-zoom-hide&#39;; // 3
  this._layerElement = L.DomUtil.create(layerElementTag, layerElementClasses);

  // Continue implementing the layer here.

  map.getPanes().overlayPane.appendChild(this._layerElement); // 4
  map.on(&#39;viewreset&#39;, this._updatePosition, this); // 5
  this._updatePosition(); // 6
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Whenever the map is zoomed, the latitude and longitude position of the layer (set when the layer was created) will have different coordinates on the screen. To reposition the layer after a zoom, the &lt;code&gt;_updatePosition&lt;/code&gt; method first  recalculates the screen coordinates of the layer with the &lt;a href=&quot;http://leafletjs.com/reference.html#map-latlngtolayerpoint&quot;&gt;&lt;code&gt;latLngToLayerPoint&lt;/code&gt;&lt;/a&gt; method (1). Next, the screen coordinates of the layer’s DOM element are updated with the new screen coordinates (2).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;_updatePosition: function() {
  var position = this._map.latLngToLayerPoint(this._latLng); // 1
  L.DomUtil.setPosition(this._layerElement, position); // 2
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Leaflet calls a layer’s &lt;code&gt;onRemove&lt;/code&gt; method when the layer is removed from the map:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;layer.removeFrom(map)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;map.removeLayer(layer)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just like the &lt;code&gt;onRemove&lt;/code&gt; method of a Leaflet control plugin, &lt;code&gt;onRemove&lt;/code&gt; method of a layer plugin is the place to tear down a layer by releasing resources and removing event listeners. In addition, the layer should remove itself from Leaflet’s overlay pane (1) and stop listening for &lt;code&gt;viewreset&lt;/code&gt; events (2).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;onRemove: function(map) {
  map.getPanes().overlayPane.removeChild(this._layerElement); // 1
  map.off(&#39;viewreset&#39;, this._updatePosition, this); // 2
  // Continue tearing down the layer here.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;styling-1&quot;&gt;Styling&lt;/h3&gt;

&lt;p&gt;Leaflet layer plugins can be styled with CSS like any other DOM or SVG element. Here we add style rules to the &lt;code&gt;my-leaflet-layer&lt;/code&gt; CSS class that we added to the layer’s container &lt;code&gt;div&lt;/code&gt; element in the &lt;code&gt;onAdd&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.my-leaflet-layer {
  // Style the Leaflet layer plugin here.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;The Leaflet documentation has a &lt;a href=&quot;http://leafletjs.com/2013/06/28/leaflet-plugin-authoring-guide.html&quot;&gt;plugin authoring guide&lt;/a&gt; that explains best practices for organising, presenting and demonstrating Leaflet plugin code. The Leaflet &lt;a href=&quot;http://leafletjs.com/plugins.html&quot;&gt;plugins page&lt;/a&gt; provides a wide range of example plugins. Most Leaflet plugins are open source with source code available on GitHub.&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Jun 2016 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2016/06/how-to-create-leaflet-plugins/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2016/06/how-to-create-leaflet-plugins/</guid>
        
        
        </item>
    
        <item>
        <title>Improve your Code by Refactoring to Nouns and Verbs</title>
        <description>&lt;p&gt;To quote the refactoring pioneer, &lt;a href=&quot;http://martinfowler.com&quot; title=&quot;Visit Martin Fowler&#39;s webite&quot;&gt;Martin Fowler&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Improving the readability of your code will enhance its usability for your future self and for other developers. In this post I’ll teach you a technique I use when programming that will make your code read more like English. When your code reads more like English, you will need fewer comments to document your methods. Instead of explicitly writing comment blocks that describe what a method does, you will express those comments in the way you name your methods and in the way you compose your method calls.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;The basis of this refactoring technique is to think about your methods in terms of nouns and verbs. Noun methods return items to work on and verb methods perform operations on noun items. Each type of method should have a meaningful name that is itself a noun or a verb. In addition, adding prefixes like &lt;em&gt;in&lt;/em&gt; and suffixes like &lt;em&gt;of&lt;/em&gt; to method names can make your code read even more like English.&lt;/p&gt;

&lt;p&gt;Time for an example.&lt;/p&gt;

&lt;p&gt;In this post I’ll use a JavaScript example that uses jQuery to show and hide a search box user interface element. However, the code is very simple and you won’t need any experience with jQuery to follow along. Also, I’ll use the terms &lt;em&gt;method&lt;/em&gt; and &lt;em&gt;function&lt;/em&gt; interchangeably because this refactoring technique is applicable to any language with a function- or method-like language feature.&lt;/p&gt;

&lt;p&gt;The search box is a HTML input element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s start with a function that hides the search box by adding a CSS class called &lt;code&gt;hidden&lt;/code&gt;, which is defined as:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hidden&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Adding this class to a HTML element will hide the element and removing this class will show the element.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;hideSearchBox&lt;/code&gt; function adds the &lt;code&gt;hidden&lt;/code&gt; class to the search box by selecting the search box element with its ID using the jQuery selector &lt;code&gt;$(&quot;#search-box&quot;)&lt;/code&gt; and then calls the jQuery &lt;code&gt;addClass&lt;/code&gt; function on the search box element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hideSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The companion method &lt;code&gt;showSearchBox&lt;/code&gt; shows the search box by removing the &lt;code&gt;hidden&lt;/code&gt; class from the search box element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These two functions implement verbs (hiding and showing) on a noun (the search box element). Let’s start by factoring out the hide and show verbs into their own functions&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can then write the &lt;code&gt;hideSearchBox&lt;/code&gt; and &lt;code&gt;showSearchBox&lt;/code&gt; functions as:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hideSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we can factor out the search box element selector into its own noun function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;searchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#search-box&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can then rewrite the calls to &lt;code&gt;hideSearchBox&lt;/code&gt; and &lt;code&gt;showSearchBox&lt;/code&gt; from&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;hideSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;showSearchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that we’ve factored out the noun and the verbs, we’re starting to build up a language in our program for handling HTML elements. It’s now easy to show and hide other HTML elements by first creating a new noun function to return the element and then using the result of the new noun function as the parameter of the &lt;code&gt;show&lt;/code&gt; or &lt;code&gt;hide&lt;/code&gt; verb functions.&lt;/p&gt;

&lt;p&gt;Let’s look at another example where we can refactor a function that converts its single parameter from milliseconds into seconds.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inSeconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;milliseconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Although this function is pretty clear—it converts milliseconds to seconds by dividing by 1000—it contains the magic number of 1000. In other situations, the meaning of a magic number might not be obvious so we would document it with a comment. However, we can remove the need for the comment by refactoring the magic number into its own value function, &lt;code&gt;millisecondsPerSecond&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inSeconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;milliseconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;milliseconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;millisecondsPerSecond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;millisecondsPerSecond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By moving the magic number into its own function we’ve made the &lt;code&gt;inSeconds&lt;/code&gt; function crystal clear. Also, since the body of the &lt;code&gt;millisecondsPerSecond&lt;/code&gt; function is a single return statement, there is no need to document it further; the name of the function documents the return value of the function.&lt;/p&gt;

&lt;p&gt;By creating self-documenting value functions like &lt;code&gt;millisecondsPerSecond&lt;/code&gt;, you can also avoid cluttering your classes with instance variables, which also makes your code more readable. Additionally, wrapping values in functions enables you to override them in subclasses.&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;in&lt;/code&gt; prefix of the &lt;code&gt;inSeconds&lt;/code&gt; function above? Prefixing function names with prepositions like &lt;em&gt;in&lt;/em&gt; and &lt;em&gt;of&lt;/em&gt; also helps to build up English-like function calls. Another example of this is the &lt;code&gt;toggleAnimationOf&lt;/code&gt; function below, which uses &lt;code&gt;Of&lt;/code&gt; to connect the toggle verb with the element being toggled:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggleAnimationOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;animationDuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using the techniques I’ve shown you so far, we can build up more complex function calls that still reads very naturally:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;toggleAnimationOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inSeconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;searchBoxAnimationDelayInMillis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;searchBoxAnimationDelayInMillis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;By renaming your methods and functions as nouns and verbs and by refactoring your method and function calls, you can improve the usability of your code by making it easier to read by your future self and other developers. As a reminder, here are the noun and verb functions we used in this post:&lt;/p&gt;

&lt;table class=&quot;table&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;Nouns&lt;/th&gt;
    &lt;th&gt;Verbs&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;`searchBox()`&lt;/td&gt;&lt;td&gt;`hide()`&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;`millisecondsPerSecond()`&lt;/td&gt;&lt;td&gt;`show()`&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;`searchBoxAnimationDelay()`&lt;/td&gt;&lt;td&gt;`inSeconds()`&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;`toggleAnimationOf()`&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Finally, although I call this a refactoring technique, with practice you will be able to write code using nouns and verbs from the beginning.&lt;/p&gt;

&lt;h2 id=&quot;learn-more&quot;&gt;Learn More&lt;/h2&gt;

&lt;p&gt;When you build up a language of methods and functions within a program, you’ve created an internal &lt;a href=&quot;http://martinfowler.com/books/dsl.html&quot; title=&quot;Learn more about DSLs in Martin Fowler&#39;s book&quot;&gt;Domain Specific Language (DSL)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Learn more about improving your code by refactoring and how to write better code the first time round in &lt;strong&gt;Clean Code&lt;/strong&gt; by Bob Martin.&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Sep 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/09/improve-your-code-by-refactoring-to-nouns-and-verbs/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/09/improve-your-code-by-refactoring-to-nouns-and-verbs/</guid>
        
        
        </item>
    
        <item>
        <title>How to Access Your iCloud Drive Folder in the Terminal App</title>
        <description>&lt;p&gt;iCloud Drive is available as a folder in the Finder on Mac OS X Yosemite (10.10) and later. However, iCloud Drive doesn’t act like a normal Finder folder, which is problematic when you want to work with iCloud Drive in the Terminal app:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;iCloud Drive is not listed as a folder in your home folder&lt;/li&gt;
  &lt;li&gt;You can’t drag the iCloud Drive icon at the top of a Finder window onto the Terminal to copy and paste its path&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- more --&gt;

&lt;p&gt;Although seemingly inaccessible, iCloud Drive is squirrelled away by OS X in your Library folder:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;~/Library/Mobile\ Documents/com~apple~CloudDocs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The following command changes the current working folder to your iCloud Drive folder:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;cd ~/Library/Mobile\ Documents/com~apple~CloudDocs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That’s a lot to type each time you want to work with iCloud Drive on the command line. You can make life easier for yourself by setting up an alias in your Bash profile. Add the following line to your &lt;code&gt;.bash_profile&lt;/code&gt; file with a text editor:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;alias ic=&amp;#39;cd ~/Library/Mobile\ Documents/com~apple~CloudDocs&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since &lt;code&gt;.bash_profile&lt;/code&gt; is a hidden file, you won’t ordinarily see it listed in the Finder. Use the following command to open your &lt;code&gt;.bash_profile&lt;/code&gt; file in the default text editor:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;open ~/.bash_profile&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, to starting working with iCloud Drive on the command line, open Terminal and type:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;ic&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and you will be taken to your iCloud Drive folder. Although I’ve used the alias &lt;code&gt;ic&lt;/code&gt;, you can use whatever suites you.&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Jul 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/07/access-icloud-drive-folder-in-terminal/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/07/access-icloud-drive-folder-in-terminal/</guid>
        
        
        </item>
    
        <item>
        <title>Troubleshooting Twitter API Application Authentication Failures</title>
        <description>&lt;p&gt;All developers know the frustration of finding out that once functioning code no longer works. This can happen when your previously working Twitter API application no longer connects to the Twitter API because of an authentication failure. In this post I’ll show you how to solve a common cause of Twitter API application authentication failures.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;If you’re using &lt;a href=&quot;http://twitter4j.org/en/index.html&quot; title=&quot;Visit the Twitter4J website&quot;&gt;Twitter4J&lt;/a&gt; on the command line, for example, you’ll likely see something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;[Wed Jul 08 11:37:49 BST 2015]Establishing connection.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[Wed Jul 08 11:37:50 BST 2015]401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This output gives two possible explanations for the failure:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Your application is not using a valid consumer key/secret pair or a valid access token/secret pair&lt;/li&gt;
  &lt;li&gt;Your system clock is not in sync&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since your application was just working, it’s unlikely that the consumer key/secret pair or the access token/secret pair are at fault but it’s worth checking. You can find the consumer key/secret and access token/secret pairs for your application at &lt;a href=&quot;https://apps.twitter.com&quot;&gt;apps.twitter.com&lt;/a&gt; under the &lt;em&gt;Keys and Access Tokens&lt;/em&gt; tab for your application.&lt;/p&gt;

&lt;p&gt;I’ve found that a common cause of authentication failure is the system clock explanation: &lt;strong&gt;the Twitter API requires that the clock of the system on which you’re running your application must be in sync with Internet time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Synchronising your system’s clock is a simple matter of reaching out to an Internet time service. For example, use the following command to synchronise the Ubuntu system clock:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;sudo ntpdate ntp.ubuntu.com&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After updating your system’s clock, your Twitter API application will probably start working again.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Jul 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/07/twitter-api-application-authentication-troubleshooting/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/07/twitter-api-application-authentication-troubleshooting/</guid>
        
        
        </item>
    
        <item>
        <title>Compactly Visualizing Data with a Double-Ended Bar Chart</title>
        <description>&lt;p&gt;This post describes a &lt;strong&gt;double-ended bar chart&lt;/strong&gt; that compactly visualizes two numeric values in a single table cell. Visualizing a column of values with double-ended bar charts makes it easy to see trends and outliers in the data.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/double-ended-bar-chart/double-ended-bar-chart.png&quot; alt=&quot;The double-ended bar chart&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The double-ended bar chart was inspired by &lt;a href=&quot;https://www.google.co.uk/search?q=sparklines&amp;amp;tbm=isch&quot; title=&quot;View example sparklines on Google images&quot;&gt;sparklines&lt;/a&gt; and &lt;a href=&quot;https://www.google.com/search?q=double+sided+bar+chart&amp;amp;tbm=isch&quot; title=&quot;View example double-sided bar charts on Google images&quot;&gt;double-sided bar charts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sparklines&lt;/em&gt; are information-dense graphics often presented in table cells or next to accompanying text. Although many different sparkline styles have been developed, the most common kinds display bar and line charts that present the variable of interest on the vertical axis.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Double-sided bar charts&lt;/em&gt; display horizontal bars aligned on a central vertical axis. This type of chart typically compares the value of two variables, such as the number of male and female births on the horizontal axis over a number of years on the vertical axis.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;double-ended bar chart&lt;/strong&gt; combines the compact representation of a sparkline with the horizontal layout of the double-sided bar chart.&lt;/p&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;Although the double-ended bar chart can display any two numeric values, it was designed to compactly present the positive and negative sentiment in a &lt;a href=&quot;/projects/cosmos/one/&quot; title=&quot;Learn more about how COSMOS One uses the double-ended bar chart&quot;&gt;table of tweets&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/double-ended-bar-chart/tweets-table.png&quot; alt=&quot;A table of tweets sentiment presented by double-ended bar charts&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Sentiment_analysis&quot; title=&quot;Learn more about sentiment analysis at Wikipedia&quot;&gt;Sentiment analysis&lt;/a&gt; assigns a numeric value to a text by analysing the emotional content of the text.&lt;/p&gt;

&lt;p&gt;In this example, the sentiment scores were calculated by &lt;a href=&quot;http://sentistrength.wlv.ac.uk/&quot; title=&quot;Visit the SentiStrength website&quot;&gt;SentiStrength&lt;/a&gt;, which assigns two scores to a text. The positive score is an integer between 1 and 5 that represents the amount of happiness or positivity in the text; the greater the positive score, the greater the amount of happiness or positivity. In contrast, the negative sentiment score is an integer between -1 and -5 that represents the amount of sadness or negativity in the text; the smaller the negative score, the greater the amount of sadness or negativity.&lt;/p&gt;

&lt;h2 id=&quot;calculating-the-bar-lengths&quot;&gt;Calculating the Bar Lengths&lt;/h2&gt;

&lt;p&gt;The maximum width of both the left and right bars is half the width of the table cell. The width of each bar is the maximum width of the bar multiplied by the proportion of the bar’s value to the bar’s maximum value.&lt;/p&gt;

&lt;p&gt;For example, when displaying SentiStrength sentiment scores, the maximum value of both the left and right bars is 5. If the width of the table cell is 100 pixels, a positive sentiment score of 4 is represented by a bar with a width of 4 / 5 * 50 = 40 pixels. Similarly, a negative sentiment score of -3 is represented by a bar with a width of 3 / 5 * 50 = 30 pixels.&lt;/p&gt;

&lt;p&gt;In practice, adding a few pixels of padding around a double-ended bar chart visually separates it from the table cell borders and from it’s neighbouring cells.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;I implemented the double-ended bar chart in the above example as a custom table cell renderer for the Java Swing &lt;a href=&quot;http://docs.oracle.com/javase/tutorial/uiswing/components/table.html&quot;&gt;JTable&lt;/a&gt; component. The following diagram shows the Java class hierarchy of the double-ended bar chart.&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/assets/blog/double-ended-bar-chart/double-ended-bar-chart-java-class-hierarchy.png&quot; alt=&quot;The Java class hierarchy of the double-ended bar chart&quot; width=&quot;40%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GraphicTableCellRenderer&lt;/code&gt; class is the base class that extends the &lt;code&gt;JComponent&lt;/code&gt; class and implements the &lt;code&gt;TableCellRenderer&lt;/code&gt; interface. This class clips the contents of the &lt;code&gt;JComponent&lt;/code&gt; object to the bounds of the table cell.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DoubleBarChartTableCellRenderer&lt;/code&gt; class extends the &lt;code&gt;GraphicTableCellRenderer&lt;/code&gt; class to draw the double-ended bar chart within the clipped table cell bounds. This class has properties that specify the values represented by the left and right bars.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SentimentBarChartTableCellRenderer&lt;/code&gt; extends the &lt;code&gt;DoubleBarChartTableCellRenderer&lt;/code&gt; class and implements the &lt;code&gt;getTableCellRendererComponent&lt;/code&gt; method. This class takes the &lt;code&gt;Object&lt;/code&gt;-typed value parameter and casts it as object that contains the positive and negative sentiment scores that provide the values for the left and right bars.&lt;/p&gt;
</description>
        <pubDate>Tue, 30 Jun 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/06/double-ended-bar-chart/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/06/double-ended-bar-chart/</guid>
        
        
        </item>
    
        <item>
        <title>A Test for Identifying Categorical Data</title>
        <description>&lt;p&gt;This post describes a method for identifying whether a data set is composed of categorical values. Automatically identifying whether a data set contains categorical values enables applications to make use of such data without requiring users to supply this information.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Categorical data is composed of a limited number of possible values. For example, a table column representing gender would contain the text values &lt;em&gt;male&lt;/em&gt; and &lt;em&gt;female&lt;/em&gt;. This column contains categorical data because it holds only two values regardless of the number of rows. In contrast, a table column containing the text of a set of tweets does not contain categorical data because although some of the values might be repeated—as in the case of retweets—most of the values will be unique. Since repeated value can occur in non-categorical data, a test is required to differentiate between a data set composed of categorical values and a data set composed of non-categorical values that may contain repeats.&lt;/p&gt;

&lt;p&gt;The following algorithm provides a useful test for identifying categorical data:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Calculate the number of unique values in the data set.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Calculate the difference between the number of unique values in the data set and the total number of values in the data set.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Calculate the difference as a percentage of the total number of values in the data set.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If the percentage difference is 90% or more, then the data set is composed of categorical values.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the number of rows is less than around 50, then a lower threshold of 70% works well in practice.&lt;/p&gt;
</description>
        <pubDate>Wed, 27 May 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/05/identifying-categorical-data/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/05/identifying-categorical-data/</guid>
        
        
        </item>
    
        <item>
        <title>A Responsive YouTube Plugin for Jekyll</title>
        <description>&lt;p&gt;This post introduces a plugin I developed to embed responsive YouTube videos in Jekyll websites. &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; is a static website generator that is extended with &lt;a href=&quot;http://jekyllrb.com/docs/plugins/&quot;&gt;plugins&lt;/a&gt; written in Ruby. Responsive videos automatically adjust their dimensions to fit the HTML element in which they are embedded, even when the size of that element changes. Furthermore, the dimensions of responsive videos always maintain the aspect ratio.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;Download the &lt;code&gt;responsive-youtube-jekyll-tag.rb&lt;/code&gt; file from &lt;a href=&quot;https://github.com/UsabilityEtc/responsive-youtube-jekyll-tag&quot;&gt;GitHub&lt;/a&gt; and copy it into the &lt;code&gt;_plugins&lt;/code&gt; folder of your Jekyll website. If you are monitoring changes with &lt;code&gt;jekyll serve&lt;/code&gt; you will need to stop Jekyll and re-run &lt;code&gt;jekyll serve&lt;/code&gt; to make Jekyll notice the new plugin.&lt;/p&gt;

&lt;div class=&quot;alert alert-info&quot; role=&quot;alert&quot;&gt;
NOTE: &lt;strong&gt;The Responsive YouTube Jekyll plugin is for self-hosted Jekyll sites.&lt;/strong&gt; If you are &lt;a href=&quot;https://help.github.com/articles/using-jekyll-as-a-static-site-generator-with-github-pages/&quot;&gt;using Jekyll to host a website with GitHub Pages&lt;/a&gt;, this plugin will not work correctly. GitHub Pages does not run third-party Jekyll plugins for security reasons. However, you can use the Responsive YouTube Jekyll plugin with GitHub pages if you build your Jekyll website locally and push your website to GitHub, as described in this &lt;a href=&quot;http://www.sitepoint.com/jekyll-plugins-github/&quot;&gt;SitePoint&lt;/a&gt; article.
&lt;/div&gt;

&lt;h2 id=&quot;use&quot;&gt;Use&lt;/h2&gt;

&lt;p&gt;Responsive YouTube videos are included in a Jekyll post or page with a &lt;a href=&quot;http://liquidmarkup.org/&quot;&gt;Liquid&lt;/a&gt; tag and the unique ID of the video:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{ % youtube &lt;span class=&quot;nt&quot;&gt;&amp;lt;YOUTUBE&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;VIDEO&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;For example, to embed the video with the link https://www.youtube.com/watch?v=&lt;strong&gt;&lt;em&gt;tnq2gwBhvCc&lt;/em&gt;&lt;/strong&gt; use the following tag:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{ % youtube tnq2gwBhvCc %}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;tnq2gwBhvCc is the YouTube video ID.&lt;/p&gt;

&lt;p&gt;The plugin uses Twitter Bootstrap’s &lt;a href=&quot;http://getbootstrap.com/components/#responsive-embed&quot;&gt;responsive embed&lt;/a&gt; CSS and JavaScript to make YouTube videos responsive. The example liquid tag above will insert the following HTML and Bootstrap CSS classes into the post or page:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;embed-responsive embed-responsive-16by9&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;embed-responsive-item&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;560&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;315&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;https://www.youtube.com/embed/tnq2gwBhvCc&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;frameborder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;allowfullscreen=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which embeds the following video:&lt;/p&gt;

&lt;div class=&quot;embed-responsive embed-responsive-16by9&quot;&gt;
  &lt;iframe class=&quot;embed-responsive-item&quot; width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/tnq2gwBhvCc&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
  &lt;/iframe&gt;
&lt;/div&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;

&lt;p&gt;The Responsive YouTube Plugin for Jekyll is open source on &lt;a href=&quot;https://github.com/UsabilityEtc/responsive-youtube-jekyll-tag&quot;&gt;GitHub&lt;/a&gt; under the MIT License.&lt;/p&gt;
</description>
        <pubDate>Wed, 01 Apr 2015 00:00:00 +0100</pubDate>
        <link>http://usabilityetc.com/2015/04/responsive-youtube-jekyll-plugin/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/04/responsive-youtube-jekyll-plugin/</guid>
        
        
        </item>
    
        <item>
        <title>Designing a User Interface for Credit Card Expiry Dates</title>
        <description>&lt;p&gt;Designing a user interface for capturing credit card expiry dates is an interesting, multifaceted problem. To work though this problem, we need to ask three questions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;What default values should be used for the expiry date?&lt;/li&gt;
  &lt;li&gt;What are the opportunities for users to make errors when transcribing the expiry date from the card to the user interface?&lt;/li&gt;
  &lt;li&gt;How can we support data entry by reducing the cognitive load on users to help prevent errors?&lt;/li&gt;
&lt;/ol&gt;

&lt;!-- more --&gt;

&lt;p&gt;Two common user interface styles for collecting credit card expiry dates are a pair of text input boxes and a pair of dropdowns. Throughout this post, I’ll refer to these two styles as the &lt;em&gt;text box UI&lt;/em&gt; and the &lt;em&gt;dropdown UI&lt;/em&gt;.&lt;/p&gt;

&lt;table class=&quot;table&quot;&gt;
	&lt;tr&gt;
		&lt;th class=&quot;center&quot;&gt;Text Box UI&lt;/th&gt;
		&lt;th class=&quot;center&quot;&gt;Dropdown UI&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td class=&quot;center&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-text-box.png&quot; alt=&quot;The text box UI&quot; /&gt;&lt;/td&gt;
		&lt;td class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-name-year-4-dropdown.png&quot; alt=&quot;The dropdown UI&quot; /&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;

&lt;h2 id=&quot;what-should-the-default-value-be&quot;&gt;What should the default value be?&lt;/h2&gt;

&lt;p&gt;Providing reasonable defaults is a good user interface design guideline. Defaults both minimise the work required by users to enter data into software and explain the user interface by providing example values. Using this guideline, providing a default expiry date seems like a good approach.&lt;/p&gt;

&lt;p&gt;The default month can have one of twelve possible values. Although arbitrary, we may choose January because it’s the beginning of the year. In contrast, we need to put more thought into the default year. The oldest valid card will expire in the current year. If the current year is 2015, for example, there are no valid cards that expire in 2014 or before, so our default year value must be at least 2015. If we assume that credit cards have a maximum lifetime of five years, then the newest cards will expire in 2020. This gives a range of years from which to choose the default year: 2015, 2016, 2017, 2018, 2019 or 2020. Inevitably, though, the choice is still arbitrary since none of these years is any more likely to be correct than the others.&lt;/p&gt;

&lt;p&gt;Whichever default month and year value we choose, we’ll be correct for only a small number of users that happen to have cards that expire in that month and in that year. But isn’t it better to have a correct default value for some users than for none at all? As the saying goes: even a stopped clock is correct twice a day. Is there actually a disadvantage of providing a default value that only suits a minority of users? Actually, there are two disadvantages, both of which stem from the need for users to change the default value to the correct value.&lt;/p&gt;

&lt;p&gt;The first disadvantage of providing a default expiry date is that users must actually notice that the expiry date is incorrect. Since credit card entry form UIs generally ask for the credit card number before the expiry date, after entering the credit card number, users that see the default expiry date may assume that the UI has populated the expiry date based on the card number.&lt;/p&gt;

&lt;p&gt;The second disadvantage of providing a default expiry date is that users may have to perform extra work to replace the default value with the correct value. For example, the text box UI requires the user to replace the default text. This text replacement step can be mitigated if the default text is automatically highlighted when users click on the input box or tab into it; the default value will be replaced on the first keystroke. The dropdown UI fairs better in this case because choosing the correct value takes the same amount of work regardless of the current value.&lt;/p&gt;

&lt;p&gt;Based on this analysis, I would recommend not using default values that are actual months and years. Instead, use placeholder values that illustrate what data is required. However, before choosing the format of the placeholders, let’s look at the kind of errors users can make when entering expiry dates.&lt;/p&gt;

&lt;h2 id=&quot;opportunities-for-data-entry-errors&quot;&gt;Opportunities for Data Entry Errors&lt;/h2&gt;

&lt;p&gt;The data entry task is to accurately transcribe the month and year of the expiry date as printed on the card. Users can make syntactic and semantic errors when transcribing data from the credit card to the UI. Syntactic errors occur when users enter values that are not valid; semantic errors occur when users enter valid values that are not correct. The dropdown UI is able to prevent all syntactic errors because the only values available to choose from are valid. However, users can still make semantic errors when they enter the wrong month or the wrong year.&lt;/p&gt;

&lt;p&gt;The text box UI is more limited in its ability to prevent syntactic errors. For example, users can enter an invalid month, such as 60, which can occur when users transpose 06 for June. To prevent this kind of error, implementations of the text box UI could disallow users from entering any digit other than 0 or 1 as the first digit in the month input box. Since any positive year is valid, the year input box need only disallow users from entering a minus to prevent year syntax errors. Although the text box UI is able to prevent some syntactic errors, just like the dropdown UI, the text box UI is also unable to prevent semantic data entry errors.&lt;/p&gt;

&lt;p&gt;Although we can prevent syntactic errors by using the dropdown UI, we can’t prevent semantic errors. Therefore, we need to design a UI that supports a data entry task that will always be prone to error. To do that, we need to understand the underlying cause of the errors.&lt;/p&gt;

&lt;p&gt;Credit cards use a standard expiry date format of two month digits followed by two year digits (MM / YY). However, UIs for capturing expiry dates are far from standard. Whenever the UI differs from this format, there is an opportunity for users to make data entry errors.&lt;/p&gt;

&lt;p&gt;The following table lists each variation of the text box and dropdown UIs. The table also lists the translations that users must perform when transcribing the month and year digits from the card to the UI and the comparisons required to validate the transcription.&lt;/p&gt;

&lt;table class=&quot;table table-bordered&quot;&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;/td&gt;
		&lt;th class=&quot;center&quot; colspan=&quot;2&quot;&gt;Month&lt;/th&gt;
		&lt;th class=&quot;center&quot; colspan=&quot;2&quot;&gt;Year&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;th class=&quot;center bold&quot;&gt;User Interface&lt;/th&gt;
		&lt;td class=&quot;center bold&quot;&gt;Translation&lt;/td&gt;
		&lt;td class=&quot;center bold&quot;&gt;Validation&lt;/td&gt;
		&lt;td class=&quot;center bold&quot;&gt;Translation&lt;/td&gt;
		&lt;td class=&quot;center bold&quot;&gt;Validation&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-text-box.png&quot; alt=&quot;The text box UI&quot; width=&quot;175px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td class=&quot;center&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-4-text-box.png&quot; alt=&quot;The text box UI&quot; width=&quot;207px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
		&lt;td&gt;Enter the 20 prefix before entering the two year digits on the card&lt;/td&gt;
		&lt;td&gt;Compare the two year digits on the card with the last two digits in the year text box&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-dropdown.png&quot; alt=&quot;The text box UI&quot; width=&quot;301px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-4-dropdown.png&quot; alt=&quot;The text box UI&quot; width=&quot;301px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
		&lt;td&gt;Prefix the two year digits on the card with 20 before selecting the year
&lt;/td&gt;
		&lt;td&gt;Compare the two year digits on the card with the last two digits of the selected year option
&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-name-year-2-dropdown.png&quot; alt=&quot;The text box UI&quot; width=&quot;301px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;Map from month number on the card to month name in the UI
&lt;/td&gt;
		&lt;td&gt;Map from month number on the card to month name in the UI
&lt;/td&gt;
		&lt;td&gt;None&lt;/td&gt;
		&lt;td&gt;Direct&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-name-year-4-dropdown.png&quot; alt=&quot;The text box UI&quot; width=&quot;301px&quot; /&gt;&lt;/td&gt;
		&lt;td&gt;Map from month number on the card to month name in the UI
&lt;/td&gt;
		&lt;td&gt;Map from month number on the card to month name in the UI
&lt;/td&gt;
		&lt;td&gt;Prefix the two year digits on the card with 20 before selecting the year
&lt;/td&gt;
		&lt;td&gt;Compare the two year digits on the card with the last two digits of the selected year option
&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;

&lt;h2 id=&quot;supporting-the-data-entry-task&quot;&gt;Supporting the Data Entry Task&lt;/h2&gt;

&lt;p&gt;The greater the difference between the format of the expiry date on the card and the format of the expiry date in the UI, the greater the cognitive load on users when transcribing and validating their transcription. For example, the following form of the dropdown UI puts the greatest cognitive load on users because it has a different format than a credit card for both the month and year. Additionally, the month dropdown requires users to translate the number of the month on the card to the name of the month.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-name-year-4-dropdown.png&quot; alt=&quot;The text box UI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To support the data entry task, we need to reduce the cognitive load on users. The following forms of the text box and dropdown UIs both match the format of the expiry date on the card exactly. As a result, these UIs place the least cognitive load on users and reduce the likelihood of transcription and validation errors.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
	&lt;div class=&quot;col-md-6&quot;&gt;&lt;div class=&quot;center&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-text-box.png&quot; alt=&quot;The text box UI&quot; /&gt;&lt;/div&gt;&lt;/div&gt;
	&lt;div class=&quot;col-md-6&quot;&gt;&lt;div class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-dropdown.png&quot; alt=&quot;The text box UI&quot; /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;To support users when entering credit card expiry dates, I recommend using the following version of the dropdown UI with the default values of MM and YY for the month and year. This version requires no translation for either the month or the year and is able to prevent all syntactic errors.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/expiry-dates/month-2-year-2-placeholder-dropdown.png&quot; alt=&quot;The text box UI&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 22 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://usabilityetc.com/2015/03/credit-card-expiration-date-user-interface/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/03/credit-card-expiration-date-user-interface/</guid>
        
        
        </item>
    
        <item>
        <title>Using Transparency to Visualise Information Density</title>
        <description>&lt;p&gt;This posts explains how to use transparency to visualise information density. When visualising geocoded data points on a map, for example, it’s common to plot each location with a marker. When many data points are located in the same geographical area, the markers drawn later will overlay the markers drawn earlier. When the markers are opaque, it’s difficult to tell at a glance how many data points are located in each region. The following example shows geocoded tweets authored about the Boston marathon.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/information-density-visualisation/opaque-map-markers.png&quot; alt=&quot;Transparent map markers&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this example, it’s clear that the tweets follow the marathon’s route. However, it’s not clear where the greatest concentrations of tweeters are. Zooming into the map is one way to move the markers apart to reveal the markers underneath. However, this requires an extra interaction that can be avoided with transparency.&lt;/p&gt;

&lt;p&gt;When map markers are drawn in a transparent colour, the accumulation of pixels in the same map region increases the density of the marker color in that region. The viewer can see at a glance that areas with a deeper shade of colour represent more data points. The following example shows the same data drawn with transparency. The concentrations of tweeters are now clearly visible.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/information-density-visualisation/transparent-map-markers.png&quot; alt=&quot;Opaque map markers&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using transparency is a very simple technique that involves adding the alpha channel to the color. In the &lt;a href=&quot;http://www.w3.org/wiki/CSS/Properties/color/RGB&quot; title=&quot;Learn more about RGB at W3C&quot;&gt;RGB color model&lt;/a&gt;, each color is described with three components: red, green and blue. In the &lt;a href=&quot;http://www.w3.org/wiki/CSS/Properties/color/RGBA&quot; title=&quot;Learn more about RGBA at W3C&quot;&gt;RGBA color model&lt;/a&gt;, a fourth component, alpha, is added that controls the transparency of the color formed by the values of the red, green and blue components.&lt;/p&gt;

&lt;p&gt;The following example shows a Google map with a set of circular overlays centred on points of latitude and longitude. Although some circles have greater area than others, by drawing the circles in a transparent colour, the circles beneath other circles are not obscured and the overlapping pixels build up the color density.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/blog/information-density-visualisation/transparent-google-map-overlays.png&quot; alt=&quot;Transparent map markers&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To add transparency to &lt;a href=&quot;https://developers.google.com/maps/documentation/javascript/examples/circle-simple&quot; title=&quot;Learn more about Google map overlays&quot;&gt;Google map overlays&lt;/a&gt;, simply set the &lt;code&gt;fillOpacity&lt;/code&gt; property for the overlay. The value of the &lt;code&gt;fillOpacity&lt;/code&gt; property ranges from 0 to 1, where 0 is fully transparent (i.e. invisible) and 1 is fully opaque.&lt;/p&gt;

&lt;p&gt;The following code snippet shows how to create a red circular Google maps overlay with 35% opacity. The &lt;code&gt;fillColor&lt;/code&gt; property value of &lt;code&gt;#FF0000&lt;/code&gt; sets the color of the circle to red. The &lt;code&gt;fillOpacity&lt;/code&gt; property value of 0.35 sets the opacity to 35%.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Create a new circular Google Maps overlay&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;circle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;google&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Circle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;latLng&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;strokeOpacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;strokeWeight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;fillColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;#FF0000&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;fillOpacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Although 35% is a low opacity value, each circle must have a low opacity value to create the density effect when the pixels of one circle are drawn on top another circle.&lt;/p&gt;
</description>
        <pubDate>Mon, 09 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://usabilityetc.com/2015/03/information-density-visualisation/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/03/information-density-visualisation/</guid>
        
        
        <category>Visualisation</category>
        
        </item>
    
        <item>
        <title>Use Animation to Help Users Notice User Interface Changes</title>
        <description>&lt;p&gt;This post explains why you should use animation to help users notice changes in your user interface. When interacting with software, users focus on the task they want to perform, not on the software itself. As a result, some users just don’t notice UI changes that occur in one descrete step, even if they caused those changes. For example, I’ve been at usability tests where users didn’t realise that a sidebar pane was opening or closing even when those users repeatedly clicked on the toggle button to open and close the pane.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Whenever user actions causes changes in the state of your user interface, consider animating those changes. Don’t assume that users will notice changes in your UI, even if they interact with controls that initiate those changes. Animating UI changes gives users time to notice those changes happening. Animations don’t have to (and shouldn’t) last long; most of the animations I use last around 350 milliseconds.&lt;/p&gt;

&lt;p&gt;Three excellent opportunuties for animation are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;inserting and deleting data&lt;/li&gt;
  &lt;li&gt;disclosing and hiding controls&lt;/li&gt;
  &lt;li&gt;opening and closing panes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most smartphone and tablet users have seen insert and delete animations. Guesture-based interaction with animations on smaller screens provides an intimate interaction between user and device. However, animation is particularly important when this interaction intimacy does not exist, such as when users interact with native or web-based applications with a mouse on larger screen sizes. Often, the larger the screen size, the less likey users are to notice changes.&lt;/p&gt;

&lt;p&gt;The video below shows how smooth animation enables users to notice changes in the Xcode, OmniGraffle and Word applications on Max OS X. Notice that Word’s ribbon animation should be much smoother.&lt;/p&gt;

&lt;div class=&quot;embed-responsive embed-responsive-16by9&quot;&gt;
  &lt;iframe class=&quot;embed-responsive-item&quot; width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/tnq2gwBhvCc&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
  &lt;/iframe&gt;
&lt;/div&gt;

</description>
        <pubDate>Tue, 03 Feb 2015 00:00:00 +0000</pubDate>
        <link>http://usabilityetc.com/2015/02/animation-helps-users-notice-interface-changes/</link>
        <guid isPermaLink="true">http://usabilityetc.com/2015/02/animation-helps-users-notice-interface-changes/</guid>
        
        
        </item>
    
    </channel>
</rss>
