Showing posts with label experimentation. Show all posts
Showing posts with label experimentation. Show all posts

Tuesday, November 6, 2018

A Journey of One Thousand Miles: Different styles and uses of progress indicators

One feature, common to nearly every process (and especially most processes in ecommerce), is something that indicates progress - a map, if you will, that shows your current location relative to the destination. Even our Instant Pot has a display that indicates when pressure builds and releases. But, just as every process is different, there should be different techniques that indicate the process and the current state.

One of the most common uses of progress indicators is in multi-page forms - that's certainly where I've had the most exposure to them. In general, they're intended to reduce cognitive load in a process, and they can either succeed or fail, often with significant results.

In the Web Accessibility Initiative section for multi-page forms, several different methods for identifying progress are put forward. The methods used to indicate progress for multi-page forms can be briefly described as (a) landmark content, (b) a progressbar, and (c) a step-by-step indicator - and I'll take each of them in turn to discuss how they might be used and whether or not they can, or should, apply to other types of progress.

Landmark Content

The use of landmark content to identify progress is almost always a good method, especially when - as the first approach identified by the WAI - updating the title element is used. As a general rule, assistive technology will announce changes to the page title. The other approach in the landmark content method, updating the main heading - i.e. the h1 element - is also a good approach as many users navigate using headings and it is, or at least should be, more visible than the page title. Rather than use one of these approaches, use both.

Of course, there are disadvantages to using this method. Neither approach - updating the page title or updating the main heading - is likely to be sufficient if the user has scrolled far enough. Updates are likely to be noticed only by users who have the main heading in their field of vision or are using assistive technology that announces changes. Also, both approaches in this method update content, so not all accessibility is improved - the user still must either read, or have assistive technology that will read, the updated content.

A Progressbar

A progressbar generated using a progress element with a value of 1 and a max of 3, as rendered by Chrome
Progressbar
(from a progress element, rendered in Chrome)
HTML5 offers a progress element that takes a max attribute and a value attribute to draw a visual representation. The progress element takes content, which must be updated, as in <progress max="7" value="1">Step 1 of 7</progress>. However, in some platforms, a progress bar is animated in a way that would violate the Web Content Authoring Guidelines Success Criterion 2.2.2, an A-level criterion.

Like several of the additions in HTML5, the progress element is not very accessible, so it's still recommended a better widget - one that uses the progressbar role with aria-valuemin, aria-valuemax, and aria-valuenow - be used, but be advised that automatic updates to the value in a progressbar role are not well-defined.

The progressbar, whether implemented using the HTML5 progress element or a widget that uses the progressbar role, may be sufficient if the progress reflected is proportional, such as a file transfer showing the number of bytes transferred. The interface is not well-suited to processes where one or more steps is larger, or takes more time, than others.

A Step-by-step Indicator

An ordered list as a step-by-step indicator
Step-by-step Indicator
The third method - a step-by-step indicator - can help users orient themselves in multiple ways. First, the user should be able to clearly see how much progress they've made, whether the progress within each segment is proportional or not. Second, the content should reflect not only steps already completed but the current step, and not-started, or upcoming, steps. In this method, there are three common approaches we can use, and each will apply to different cases.

Fixed-Journey Indicator

The basic step-by-step indicator presented for multi-page forms by the WAI is an ordered list, with list items that have visually hidden content to indicate which item is completed or current. This is likely sufficient, if the progress is a consecutive series of unidirectional steps under the control of the user - although the WAI example should be updated to reflect capabilities available in the ARIA states and properties.

Breadcrumbs

If, progress is bidirectional or the user may complete steps in a non-consecutive manner, the interface should be a navigational one which allows the user to choose the step they'd like to complete. This step-by-step indicator becomes more complex as it not only needs to include completed, current, and not-started states but also accessible navigation between the steps. This sort of navigational, step-by-step indicator is often called a breadcrumb because it's more than just a progress indicator.

This type of progress indicator should especially be used for multi-page forms if those forms cause legal commitments or financial transactions to occur or update user-provided data that has been stored to help meet WCAG Success Criterion 3.3.4 as it aids in the review, confirmation, and correction of information.

Status Indicator

The third type of step-by-step indicator is a status indicator. The status indicator is still, semantically, an ordered list, but a status may switch in a non-consecutive manner and the status is likely to be outside the control of the user. An example of this might be a payment transaction that moves from pending to authorizing to completed or a document retrieval that moves from requesting to receiving to received to loaded. In either of these cases, an intermediate step may be skipped, e.g., the payment may appear to move from pending to completed or the document may move from receiving to loaded.

This type of progress indicator is perhaps the most complex, because the user interface is not really a progress indicator but a status indicator (hence the name). The upcoming statuses need not be announced because their inclusion is likely to reduce cognitive accessibility - the user can do nothing to either prevent or encourage the move to that state. Further, announcing which of the items in the list is current lacks the context that the visual interface has, so identifying completed and current items is a little more complex.

It is also important to note that because this indicator is auto-updating and representing something outside the control of the user, it is critical that it only be used for those activities that are essential. If the interface is used for a part of an activity that is non-essential, the auto-update feature without the ability to pause, stop, or hide the update will violate WCAG Success Criterion 2.2.2, just as the HTML5 progress element would.

Conclusion

Any of the four different types of progress indicators - a progressbar, a fixed-journey indicator, breadcrumbs, or a status indicator - can be sufficient to describe process. While they have areas of overlap, each has a specific interface that leads to a design pattern and accessibility features.

In the very near future, I will be launching a gitbook called Think A11y that will be covering components like this, including HTML, CSS, and JavaScript, in an effort to put my accessibility resources in one location. This blog will still cover accessibility issues from time to time, but hopefully this new approach will make my electronic life a little easier to manage and share. In the meantime...

Happy coding.

Sunday, September 9, 2018

The Poor Babel Fish: The importance of clear communication and how to measure it

Meanwhile, the poor Babel fish, by effectively removing all barriers to communication between different races and cultures, has caused more and bloodier wars than anything else in the history of creation. ~ The Hitchhiker's Guide to the Galaxy
With all due respect to Mr. Adams, it wasn't the fault of the Babel fish, or the increased communication between different races and cultures that caused more and bloodier wars. In fact, we know that communicating clearly with each other is generally a good thing - as long as we have good intentions.

One of the few things those of us involved in building human/computer interfaces know for certain is that the cognitive load of the interface matters. The greater the cognitive load, the longer it takes someone to complete a process or read content on the web page. The longer it takes someone to complete a process, the less likely they are to complete the process. Larger e-commerce companies with large datasets, like PayPal and eBay, know how likely a person is to complete the checkout process given how long it takes them.

Cognitive load is also one of the most often overlooked elements of accessibility. We seldom spend time thinking about how difficult, or easy, it is to identify relevant items on a page and whether or not the content hierarchy is perceivable. We also seldom pay attention to how easy, or difficult, content is to read, which is yet another component of cognitive load.

Part of the avoidance of evaluating this last piece - how "readable" content is - is due to the fact that it's generally very difficult to assess "readability". In US English there are two formulas that can be used for evaluation: the Flesch Reading-Ease Score (FRES) and the Flesch-Kincaid Grade Level Formula. These two evaluative tools provide comparable scores for English language in other regions and have been pretty widely used; however, they do not apply to other languages.

The difficulty of assessing languages other than English presents unique challenges to assessing the accessibility of web pages with regard to internationalization. Because of my interest in both internationalization and accessibility, their convergence around another of my loves - language - makes this a very interesting topic for me...and, frankly, the main reason why I'm sharing this with you.

We tend to pay a lot of attention to the Flesch-Kincaid Grade Level Formula in the US, but that's not really a measure of accessibility, because it's not a measure of how easy or difficult it is to read, but a measure against a "typical" student's comprehension...and the whole idea of "typical" should be an anathema within the accessibility community. The Flesch Reading-Ease Score, on the other hand, is not a comparison of the content to other "typical" content, but a measure of the content itself, by analyzing the number of words and sentences and the number of syllables in the words used.

The number of syllables in word, in languages other than English, are not necessarily a measure of complexity, however. As a hypothetical example, if we compare the English (three syllable) phrase "take this drug" with the Spanish (nine syllable) phrase "tomar este medicamento", we get a FRES of 119.19 for English (which maps to roughly third grade, or an 8 year-old) and a FRES of -50.01 for Spanish, well beyond the reading ease of the Harvard Law Review. Even if we used the English phrase "take this medication", the FRES is still 34.59, a whopping 80 points greater than the Spanish phrase...or roughly the difference between fourth grade (US) and college graduate reading levels.

Granted, this is an extremely small, hypothetical example; however, there is simply no way to justify the difference between those two phrases. Even though many standards in the US specify readability requirements using the FRES, there must be a better way to calculate the readability, especially across languages.

If we look outside the US, and about ten years before the Flesch-Kincaid Grade Level Formula was developed, we find the Läsbarhetsindex. This formula is considerably easier to use than either Flesch-Kincaid readability tests - it's the number of words divided by the number of sentences plus the number of "long words" multiplied by one hundred and divided by the number of words. A "long word" in the Läsbarhetsindex is a word with more than 5 letters. The Läsbarhetsindex formula gives a score for "take this medication" of 36 and the score for "tomar este medicamento" is also 36.

While there is a general mapping of Läsbarhetsindex to educational levels in the author's native Sweden, such a mapping does not exist for other countries...which makes sense because every educational system is different. This, however, doesn't affect our use of this measure for accessibility, because as was mentioned before, for accessibility we need to evaluate the content, not necessarily compare the content to an educational level.

Although the definition of a "long word" may vary, depending on the language used, the remainder of the formula should work for measuring the readability of content for accessibility purposes.

To aid in your evaluation work, I've created a library that will soon be published via npm as roking-a11y. In the meantime - before it's published on npm - you can get the source in the roking-a11y repo on my GitHub profile.

I'm also looking into how else this can be used and extended. One of my plans is to perhaps modify the length of a "long word" based on a language code, and perhaps add guidance for specific score ranges. If you have ideas about how else this might be helpful, please leave a comment - I don't track issues or feature requests in GitHub. If you've done research in this area, I'd especially like to hear from you.

Happy coding.

Sunday, August 6, 2017

Get You Some Of That: Creating a button that allows you to save a document

This will be a quick, fun post to solve a relatively simple problem - saving a web page. Of course a person could use the native browser controls, but where's the fun in that?! So, here we go.

First, you'll want something that the user can activate to trigger the 'save'. We'll assume the user has JavaScript enabled, because this won't work otherwise. In reality, if you were going to add this to your page, you'd want to add the interface component using JavaScript so it wouldn't appear if it weren't going to work...but, like I said, we're going to just make that assumption to save a little time by adding <button type="button" onClick="saveAs()">Save As...</button> to our document.

Next, we add the following script to our document...


JavaScript

<script>   function saveAs() {     var downloader = document.createElement('a'),       blob = new Blob([document.body.innerHTML], {type: 'text/html'}),       name = window.prompt('Please enter a filename', document.title);     if (name) {       downloader.download = name;       downloader.href = window.URL.createObjectURL(blob);       downloader.onclick = function (e) {         e.target.parentNode.removeChild(e.target);       };       document.body.appendChild(downloader);       downloader.click();     }   } </script>


Now, when you click it will automatically download the document as an HTML document, easy peasy lemon squeazy.

Happy coding.

Tuesday, January 24, 2017

Don't Get Whomped by the Willow: easily building an object tree

One of the things I've needed to do on occasion is merge objects into a single tree based on a string that gives a position. It's not necessarily the easiest thing to do, because while it's possible to move down the hierarchy, that's only useful in reading the object, not in writing the object.

Rather than spend a lot of time discussing the theoretical, let's dive right in, working with an example.

Let's assume you have several objects, like so...


JavaScript - Defined Objects

var json0 = {       cgi_var_name: 'field',       label: 'value (Level 0)'     },     json1 = {       cgi_var_name: 'root',       label: 'root (Level 1)',       structure: 'root'     },     json3 = {       label: 'bar (Level 3)';       cgi_var_name: 'bar';       structure: 'root ~ foo ~ bar'     },     json2 = {       label: 'foo (Level 2)';       cgi_var_name: 'foo';       structure': 'root ~ foo'     },     json4 = {       label: 'snafu (Level 4)',       cgi_var_name: 'snafu',       structure: 'root ~ foo ~ bar ~ snafu'     };


...and you want to merge them into a single object, like so...


JSON - Our "merged object" goal

{   cgi_var_name:'field',   label:'value (Level 0)',   root: {     foo: {       cgi_var_name:'foo',       label:'foo (Level 2)',       bar: {         cgi_var_name:'bar',         label:'bar (Level 3)',         snafu: {           cgi_var_name:'snafu',           label:'snafu (Level 4)'         }       }     }   } }


Why might you want to do this?

One case might be that your ReST API is parsing JSON and expects an object that is further manipulated and processed before being returned. Unfortunately, an HTML FORM object is flat - which means your [insert your favorite framework here] representation likely is as well. For example, you could stringify your Angular scope object, but unless you've built a mechanism to handle it, it would never pass a tree to the API.

In order to merge these five objects (json0..json4) into a single congruent object, we have to climb both up the tree and down it...and here's how...


JavaScript - objMerge

function objMerge(field, path, base) {   var keys = field[path] ? field[path].split('~') : [ ],     ndx = keys.length - 1,     idx = 0,     deep = 0,     merge,     obj = { },     o = { };   for (idx = 0; idx < keys.length; idx += 1) {     keys[idx] = keys[idx].replace(/^\s*|\s*$/g, '');   }   obj[field.cgi_var_name] = field.label;   while (ndx > -1) {     if (base instanceof Object) {       merge = JSON.parse(JSON.stringify(base || { }));       for (idx = 0; idx < Math.min(ndx + 1, keys.length); idx += 1) {         if (merge.hasOwnProperty(keys[idx])) {           merge = merge[keys[idx]];         } else {           break;         }       }       idx -= 1;     }     if (idx === ndx) {       o = { };       o[keys[ndx]] = Object.assign({ }, merge, obj);       obj = o;     } else {       o = { };       o[keys[ndx].replace(/^\s*|\s*$/g, '')] = obj;       obj = o;     }     ndx -= 1;   }   return Object.assign({ }, base, obj); }


As you can see, we start fairly simply by splitting the structure into keys (the delimiter in line 2 isn't really important - it could be anything) and in lines 10-12 we trim those key strings. At this point, I'm going to need to call out line 14 - this is where I have special code tied directly to the object structure in my example, and for this reason you will need to modify this section. If, for example, you wished to merge complete objects rather than simply a few properties of the object, change line 14 to obj = field.

From there, we move on to the meat of the function. We can only build an object from a child up to the parent, because we only know about the child we're working with at any one minute. The problem is that we don't know if our current child has any siblings. Which means that before we define the parent, we have to look for it in the base object - which is what the code does in lines 16 to 27. The code loops through the 'lineage' looking for the keys in the order they're defined in our structure. If it finds the appropriately named ancestor, it tracks it as a good branch (or relevant level) and continues on to the next level.

Once we've identified whether or not we have a relevant branch, we can then either merge our child into the identified parent (using Object.assign) or declare a new parent for our child (lines 29 through 37). Once that is done, we go to the next level up and repeat the process.

Wrapping all this in a function means that I can write code that merges two objects into a single ancestor object relatively easily. Using the example code, I can call the function and pass in the object I want to merge, the name of the property that contains the path to the node where the object should be merged, and the object the object should be merged with, like so...



var scope = { }; scope = objMerge(json0, 'structure', scope); scope = objMerge(json1, 'structure', scope); scope = objMerge(json2, 'structure', scope); scope = objMerge(json3, 'structure', scope); scope = objMerge(json4, 'structure', scope);


...and the objects are merged, returning, in the final step, an object as described in the "merged object" JSON that describes our goal.

As usual, there are several ways in which this could be easily modified to meet other designs. For example, there is no reason the path string needs to be in the object being merged - it could easily exist outside the object - and the merge candidate identifying loop (lines 16 through 27) could be modified to identify another merge point. This example is intended to demonstrate how to merge two objects at different points on identical paths.

If you simply have two objects that need to be merged, you could attempt to merge them using Object.assign - but that doesn't always work the way you'd anticipate. A better option is to use code like this...


JavaScript Object Merger

function merge(source, base) {   var prop;   for (prop in source)     if (source.hasOwnProperty(prop)) {       if (base.hasOwnProperty(prop)) {         base[prop] = merge(source[prop], base[prop]);       } else {         base[prop] = JSON.parse(JSON.stringify(source[prop]));       }     }   }   return base; }


This function - merge - will loop through all the properties of the source object and if the property exists in the base object will recursively call itself to set the value.

Since all the code is present in this post, you should, as always, feel free to use this as you will, keeping in mind that you should always, as they say, "trust and verify"...and

Happy coding.

Wednesday, October 26, 2016

Visualize world data automagically

Several years ago I started a project writing a plug-in for D3.js to combine the map projections with data markers. That project became the earth plug-in (which you can get in my d3-plugins repo – https://github.com/hrobertking/d3-plugins). Although it's been fully functional for a while, I've recently made a few changes to it that enable it to go a little further, so I thought this would be a good opportunity to write a (hopefully) brief post to explain a little better what it can do.

For this post, I'm going to describe hypothetical scenarios that will almost certainly never occur in real life, but scenarios that, hopefully, will be similar to real-life scenarios you can imagine. Also, since I have been a strong advocate – dare I say 'evangelist' – of Progressive Enhancement and a few other UI engineering topics for many years, this post will have a specific structure and make a few assumptions without going too deeply into the case for Progressive Enhancement or other topics, such as accessibility. Even though those topics are important and seldom, even in my own blog posts, get the attention they deserve, they're not the focus here.

That all being said, let's start with the task at hand – developing an interesting page that shows data points scattered across the globe. For our example, we'll use the world's busiest airports...but it could as easily be something else, like sales data or web traffic.

The most descriptive thing we can do with the data is to put it in a table, which also happens to be the best approach for accessibility issues. So we have a table something like this...


HTML for our example

<table class="earth-viz" id="busiest-airports">   <caption>10 of the world's busiest airports</caption>   <thead>     <tr>       <th>Country</th>       <th>City</th>       <th>Activity</th>       <th>Name</th>       <th>Latitude</th>       <th>Longitude</th>       <th>Size</th>     </tr>   </thead>   <tbody>     <tr>       <td>US</td>       <td>ATL</td>       <td>68343</td>       <td>Hartsfield Jackson Atlanta International</td>       <td>33.636719</td>       <td>-84.428067</td>       <td>16</td>     </tr>     <tr>       <td>US</td>       <td>ORD</td>       <td>59692</td>       <td>Chicago O'Hare International</td>       <td>41.978603</td>       <td>-87.904842</td>       <td>14</td>     </tr>     <tr>       <td>US</td>       <td>DFW</td>       <td>56496</td>       <td>Dallas Fort Worth International</td>       <td>32.896828</td>       <td>-97.037997</td>       <td>12</td>     </tr>     <tr>       <td>US</td>       <td>LAX</td>       <td>51396</td>       <td>Los Angeles International</td>       <td>33.942536</td>       <td>-118.408075</td>       <td>10</td>     </tr>     <tr>       <td>CN</td>       <td>PEK</td>       <td>48226</td>       <td>Capital International</td>       <td>40.080111</td>       <td>116.584556</td>       <td>10</td>     </tr>     <tr>       <td>US</td>       <td>CLT</td>       <td>44583</td>       <td>Charlotte Douglas International</td>       <td>35.214</td>       <td>-80.943139</td>       <td>8</td>     </tr>     <tr>       <td>US</td>       <td>DEN</td>       <td>44438</td>       <td>Denver International</td>       <td>39.861656</td>       <td>-104.673178</td>       <td>8</td>     </tr>     <tr>       <td>US</td>       <td>LAS</td>       <td>41164</td>       <td>McCarran International</td>       <td>36.080056</td>       <td>-115.15225</td>       <td>6</td>     </tr>     <tr>       <td>US</td>       <td>IAH</td>       <td>39808</td>       <td>George Bush Intercontinental</td>       <td>29.984433</td>       <td>-95.341442</td>       <td>6</td>     </tr>     <tr>       <td>GB</td>       <td>LHR</td>       <td>37680</td>       <td>London Heathrow</td>       <td>51.4775</td>       <td>-0.461389</td>       <td>4</td>     </tr>   </tbody> </table>


...and we can add all the standard accessibility information to describe it and we can make the 'relative size' column a simple rank or we can scale the number, as I've done here, or, for example, scale it so it reflects a percentage of total volume.

Note that the longitude and latitude columns here are important for the visualization even if they're not important to the reader. If you decide to hide them from the reader (and AT), they still need to be present in the code.

As you'll notice at this point, this is not unlike code you might push on a daily (or more frequently) basis – which is the point. At this juncture, you would, of course, add CSS to style the table...perhaps to hide the longitude and latitude columns. After getting the table styled as you want it, it's time to add the JavaScript.

Here you'll add the D3.js geo libraries – I use d3.v3.min.js for the core, d3.geo.projection.v0.min.js, and topojson.v1.min.js – and my earth plug-in library. With the enhancements made earlier this month, that's all you have to do. The plug-in will pull the marker information using the class earth-viz and generate the visualization. If you want the visualization rendered in another part of the page (rather than where the table is placed), you can still use the constructor to call the plug-in explicitly.

One other change is that you can call the constructor with either some or all four parameters – visualizationElement, projection, visualizationWidth, and markerDataTable – or use can use a config object { data:<marker-data-table>, element:<visualization-element>, style:<projection>, width:<visualization-width> }. This change is stylistic only – there is no functional difference, it's only purpose is to allow greater flexibility so that engineers using it can maintain consistent coding practices.

Of course, calling the constructor is entirely optional now as long as the markup contains the key class, so if you're displaying static information, that's really all there is to it – you need do nothing more. If your visualization needs to be updated, or if you're just interested to learn more, keep reading.

The second major change in the most recent version is that the visualization object is maintained in the window scope, and can be accessed at any point after it's been created. The name of the window property is the same as the visualization ID (i.e., the ID of the marker table with '-earth-viz' added to the end). This means that with our example,the visualization is accessible by referencing window['busiest-airports-earth-viz'].

When this is tied to the ability to get the marker table id directly from the visualization, this makes it remarkably easy to hook updates to the visualization to updates to the table, by simply calling the parseMarkerData function something like... window['busiest-airports-earth-viz'].parseMarkerData('busiest-airports');. If you already have a timed refresh of the data that is updating the table (along with all the accessibility hooks that announce the live data), simply add this into the callback and your visualization is updated on the data refresh.

I know this has been a quick jaunt through a fairly powerful plug-in, but hopefully it's explained a bit about the newest features. As always –

Happy coding.

Friday, August 26, 2016

Free Rum

People have asked me what has helped me debug nasty, not-so-easily-reproduced bugs and nearly always the answer is "exhaustive testing"...but what about when it isn't. Ok, most of the time it really is exhaustive testing. Of course, I make it a habit to write code to handle all different data types even when I'm 99.999% sure it will always only be one data type, because when you have 100M+ users using your code daily you'd be surprised how often 0.001% is.

So, how do we debug issues that seem to only occur 0.001% of the time? Obviously we're not talking about those use cases that fall into within the "normal" range, we're talking about outliers - or what I refer to as the oddball case. Here we're talking about those times when all our unit tests pass and still our code fails in the "real world" where there are a few cases - extreme corner cases, admittedly - when users are experiencing a "sub-par visit". These instances can easily bore a hole into our confidence (and ego...it's a little bit ego), leaving us scratching our head in confusion and frustration. What do we do then?

As with any good pirate, the answer is RUM, and lots of it!

Go ahead, start making your own pirate references and talk like a pirate...I'll wait...and I'm pretty sure I can hear you singing....
"Fifteen men on the dead man's chest —
...Yo-ho-ho, and a bottle of rum!
Drink and the devil had done for the rest —
...Yo-ho-ho, and a bottle of rum!"
Robert Louis Stevenson, Treasure Island

Of course in our case RUM does not refer to the pirate's beverage of choice but refers, instead, to Real-time (or sometimes Real) User Monitoring. The emphasis here, obviously, is on user monitoring, not testing or assuming what might be happening, and it's different than synthetic user monitoring, which is a simulation (and typically done as part of a comprehensive testing plan) because it uses real people in real-world situations.

This last point - that it uses real people in real-world situations - cannot be stressed enough. Why? Because, in the specific situation this post addresses, our software engineering has begun to move away from how people have evolved. People typically solve problems in a linear manner - it's how we've evolved. C came about because A and B happened. We make our selections in a store, go to the checkout, and pay. We don't suddenly jump out of line to go to the bank and apply for a credit card and expect to return to our place in the line with our basket full of our selections. For a very long time, our software matched this model exactly, or very nearly so. Oh, we might have a decision point where we would loop back into a process, but it was still a linear process. Most of the time, this works well, but as anyone who's stood in a queue hoping to order food only to find the customer ahead of them hasn't quite decided what they want knows, sometimes there are problems with synchronous, single-thread experiences.

We tried to resolve the synchronous, single-thread problem by adding threads. This often works alright, for the most part, but as we discovered, multiple blocked threads are not really any more productive. The answer, then, was an asynchronous (non-blocking) approach. Now, here we are, years later often suffering in callback hell and struggling to debug software because our linear, synchronous experience no longer applies to development of asynchronous systems...and as was mentioned earlier, that's why RUM enters our toolkit.

There are, of course, many ways to implement (or pour) RUM. If you're running any one of several traditional web servers, IIS or Apache, for example, Splunk is a good choice. I've written a proxy server for a Splunk app and reviewed a couple Splunk references - Splunk Developer's Guide and Learning Splunk Web Framework - so I'm not without respect; however, the downside of Splunk is that it can become expensive. For this reason alone, even if your operation uses Splunk in the production environment you may choose to forego it as a support for research and development.

As a no-cost alternative, however, you can pour your own RUM if you're using a node.js server. That's right, I said it - no-cost and RUM together - FREE RUM - (part of) every pirate's dream. Since it's relatively easy to do, and as long as you don't do something really boneheaded, you can build it securely, hoist the Jolly Roger, talk like a pirate, and follow the map below. Be warned, I'm not pointing out all the dangers (like how you can expose private or confidential information) - there are a few (fairly obvious) pitfalls, but this should be enough to get you in the general area of the treasure you seek (and I should add that you can find a more complete example/prototype in my rum github repo - https://github.com/hrobertking/rum).

First, you'll need to assemble a crew and put them on a ship. Do that by installing the socket.io module, adding it to your server module, and binding it to your httpServer instance.


Server-side JavaScript (Socket instantiation)

var server = http.createServer(handler),     io = require('socket.io')(server);

You should note that the server need not be the native node.js server, it can be an extension of the node.js httpServer object - e.g., an Express instance.

Now that you have a crew and ship, decide when you'll raise the Jolly Roger - do that by emitting an event through the socket and passing an object into the event, e.g., io.emit(event_type, event_object);.

The event type is a string literal so it can be named (nearly) anything and you can emit different events at different times, as in the example below.


Server-side JavaScript (Event Handlers)

var msg = {   id: unique_id(),   req: request,   res: response };   msg.req.on('end', function() {     msg.action = 'request';     io.emit('message', msg);   });   msg.res.on('finish', function() {     msg.action = 'response';     io.emit('message', msg);       if (msg.res.statusCode !== 200) {       io.emit('http error', msg);     }   });


Now put the spyglass to your eye and scan the horizon. Your spyglass is going to be a static page that uses the socket.io client script (https://cdn.socket.io/socket.io-1.3.5.js) and instantiates a socket. That socket will then be monitored and your event handlers will run when the event comes over the socket.


Your 'spyglass' document

<!DOCTYPE html> <html lang="en">   <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">     <style type="text/css">       .request { background-color:red; }       .response { background-color:yellow; }       .request.response { background-color:green; }     </style>   </head>   <body>     <script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>     <script>       var socket = io();             socket.on('message', function(obj) {           var node = document.getElementById(obj.id), cls;           if (!node) {             node = document.createElement('div');             node.id = obj.id;             document.body.appendChild(node);           }           cls = node.className.split(' ');           cls.push(obj.action);           node.className = cls.join(' ');           node.innerHTML = '<p>' + obj.req.url + '</p>';         });             socket.on('http error', function(obj) {           var node = document.getElementById(obj.id);           node.className += 'http-error';           node.innerHTML += '<p>' + obj.res.statusCode + '</p>';         });     </script>   </body> </html>


Now, as you watch the 'spyglass' document in your browser, when the 'io' events are fired on the node.js httpServer they will be handled in the handlers specified in the spyglass.

Now you have insight into the important pieces of code, not as you test them (because you can get that elsewhere, like the Chrome dev tools), but as others use them, and it's debugging in those real-world situations that takes our development to the next level in our drive for results. Now, go get some pirate booty.

Happy coding.

Monday, February 22, 2016

A Modern Menu

I've been exploring a little, stretching my coding muscles again to see just how easy it would be to write an accessible navigation menu that slides out from the left on mobile but lies horizontally on a wide(r) screen. Now, let me begin by saying that writing one is easy...but writing a progressive, fully semantic version is not necessarily so. This post, however, will explain just that - how to write a progressively enhanced, fully semantic version that is accessible.

Rather than bore everyone with tedious code listings (yes, I'll have a few), I'm going to link to the proof-of-concept that will also have fully commented code, and here I'll give a general overview as well as a few things you'll want to notice along the way.

If this is your first foray into accessible coding, do yourself a favor and get the WAVE Evaluation Tool extension for Google Chrome, and if you're not already using the Mobile/Responsive Web Design Tester extension, get that as well.

As always, we first start with the markup and do the things we would normally do - add the lang attribute to the HTML tag, add a descriptive TITLE to the HEAD, and add a descriptive H1 to the BODY. Here's where I start my navigational menu code...inside the H1. In addition to using the H1 as a banner, I'm adding a 'button' that will toggle the navigation menu (note that this is only for mobile devices). Since this is only a visual interface for the menu, I'm not adding anything to it - no ARIA role labels. The 'button' span is empty, so without ARIA labels or role, accessibility technology will ignore it (as it should). After the H1, I'll add the actual menu...but more on that in a couple of paragraphs.

The user interface for mobile users, when the navigation menu is closed, will show a button that will display a hamburger symbol and when it's open it will display the x typically used on close buttons.

Note that I'm not actually using a BUTTON tag but a SPAN tag that acts like a button...and the primary reason for this is because the icon displayed inside the button is controlled using CSS and that's really impossible to do when you use a BUTTON tag. By attaching an event listener to the click event on the button SPAN, I add (or remove) opened to (or from) the H1 tag. The opened H1 and an adjacent sibling selector for the menu will control whether the menu is seen or not. If you want to use a different device to toggle the menu, feel free - and simply change the CSS so that the 'opened' class is attached to the menu. Since the content is not in the markup, I don't need any ARIA attributes like aria-hidden even though it's a control for the visual interface...and because the button in the H1 is only used on mobile, I wrap the styling in a media query using a mobile breakpoint.


HTML
<body>   <h1>     <span class="banner">Responsive Navigation Menu</span>     <span class="mobile-only button open close"></span>   </h1>   <div class="menu-overlay">


CSS
@media screen and (max-width:480px) {   h1 > .banner {     float:left;     height:1.65em;     line-height:1.65em;     width:80%;   }   h1 > .button {     border-radius:0.1em;     border:0.01em solid #ccc;     cursor:pointer;     display:inline-block;     font-size:1.25em;     font-weight:800;     height:1.1em;     padding:0.1em;     position:static;     width:1.1em;   }   h1 > .button.open.close::after {     content:"\2261";     cursor:pointer;     display:inline-block;     font-size:1.5em;     line-height:0.75em;     text-align:center;     width:0.75em;   }   h1.opened > .button.open.close::after {     content:"\00D7";   }

Now that we have the H1 set, I'm going to add the navigation menu to the page. I'm choosing to add the navigation menu before the content because (1) it's easier to style that way and (2) when the links are at the top it's easier for someone to jump to another location before all the other content is read - and they don't have to take extra steps, like using their AT to step through a bunch of landmarks.

HTML
  </h1>   <div class="menu-overlay">     <ul id="main-menu" role="navigation">       <li class="item">         <a href="?menu-item-1">Menu Item 1</a>         <span class="indicator"></span>       </li>       <li>         <a href="?menu-item-2">           Menu Item 2         </a>         <ul class="submenu">           <li class="item">             <a href="?menu-item-2.menu-item-A">               Menu Item A             </a>           </li>           <li class="item">             </a href="?menu-item-2.menu-item-B">               Menu Item B             </a>           </li>         </ul>         <span class="indicator"></span>       </li>     </ul>   </div>

There are a few things of note in the code. First, I've added a ARIA role (navigation) to the list. Rather than go into detail here about what a navigation role means, I'll instead point you to the W3 page about ARIA roles. Second, this example uses a sub-menu, which will become important when we talk about the CSS and the JavaScript. Additionally, I've identified LI items that contain menu items as items, which enables me to add LI tags that are used as separators. Each clickable item is wrapped in an anchor (A) tag, which allows me to leave sub-menu headers in tags that aren't automatically identified as clickable, e.g., SPAN. Finally, there is a SPAN tag with the class indicator regardless of whether or not there is a sub-menu. This enables a sub-menu visual indicator, which is not needed by accessibility technology, which will read the submenu because it's hidden using clip rather than a technique that would render the sub-menu invisible to AT.

CSS
ul[role="navigation"] > .item > .submenu {   background-color:#fff;   border-top:none;   border:1px solid #ccc;   box-sizing:border-box;   clip:rect(0, 0, 0, 0);   color:#333;   left:0;   list-style-type:none;   margin:0 -1px;   padding:0.5em;   position:absolute;   right:0;   transition:clip 1s;   z-index:3; }


There are a few things of note about the CSS. First, the style rules for the sub-menu will drop the sub-menu below the primary menu and make it appear as wide as the primary menu. Although this approach is not ideal, we're going to fix it using JavaScript - which will hit most users and those who don't have JavaScript running (or those who have a page with borked JavaScript) will still have access to the navigation menu. If you're coding for a mobile device and are using a toggle button, you might want to consider how users will get to the menu if their JavaScript is borked - you might even consider using a focus or hover pseudoclass.

Second, the initial value of the margin-left and margin-right is the border-width on the primary menu (ul[role="navigation"]) multiplied by -1. This extends the left and right border to the full width of the primary menu.

Third, by setting the position to absolute, we can change the left and right values and the menu will become more like a drop-down menu (remember that I said we'd fix the width of the menu with JavaScript just two paragraphs ago - well here it is, the initMenu function does it).

JavaScript
function initMenu(menu) {   var contained,       count,       index,       items,       mnu_item;   items = menu.getElementsByTagName('li');   count = items.length - 1;   while (count > -1) {     mnu_item = items.item(count);     contained = mnu_item.childNodes;     index = contained.length - 1;     while (index > -1) {       if ((/\bsubmenu\b/).test(contained.item(index).className)) {         contained.item(index).style.left = mnu_item.offsetLeft + 'px';         contained.item(index).style.margin = '0';         contained.item(index).style.right = 'auto';         break;       }       index -= 1;     }     count -= 1;   } }

Now, simply add a call to your JavaScript function to initialize the menu - something like initMenu(document.getElementById('main-menu')); - and you're done. The initMenu function will set the left position of the sub-menu UL to the left position of its LI container, will set the right value to auto (which shortens the width) and adjusts the margin so that everything lines up neatly.

So that's it. One last note - although I generally use a 'mobile first' approach (making the style sheet for mobile and then writing a media query for everything else) I didn't do it that way this time because the styles are different enough that they're difficult to re-use. In the proof of concept I've linked both stylesheets, but in your production code you might want to pursue an adaptive approach so only the mobile stylesheet is downloaded for mobile devices to minimize the payload - on the other hand, the stylesheets are pretty light as they are so it might not matter. Oh...and this is the proof of concept.

Happy coding.



Wednesday, March 18, 2015

Measuring Time

My previous post, on sychronized tasks, started me thinking - for long running processes, it would be nice if we had some way of estimating how much time is required or what time a process might complete. Given that most of my development is in Bash, I cobbled together a tool that will do some rough calculations and give that information. In my sample version (shown below) a few of the variables are hard-coded, but if you set up process logging, you should be able to pull most of your information from there. On to the code...

REC_TOTALD="100000"
STARTED=$(date -d '2015-03-17 17:30:00' '+%F %T.%N %Z')

diff () {
    printf '%s' $(( $(date -u -d"$CURRENT" +%s) -
        $(date -u -d"$STARTED" +%s)))
}

REC_FAILED=`grep FAILURE output.log | wc -l`
REC_PASSED=`grep SUCCESS output.log | wc -l`
REC_COMPLT=$((REC_FAILED + REC_PASSED))
REC_PERCNT=$((REC_COMPLT * 10000 / REC_TOTALD)) # percent as 4 decimals

CURRENT=$(date '+%F %T.%N %Z')
MINUTES=$(( $(diff) / 60 ))
EST_TIME=$((( $(diff) * 10000 / 60 ) / REC_PERCNT))
ETA=$(date -d "$STARTED+$EST_TIME minutes" '+%F %T')

echo ""
echo "   STARTED: $(date -d "$STARTED" '+%F %T')"
echo "   CURRENT: $(date -d "$CURRENT" '+%F %T')"
echo ""
printf "    QUEUED: %6d records\n" $REC_TOTALD
printf "    FAILED: %6d\n" $REC_FAILED
printf "    PASSED: %6d\n" $REC_PASSED
printf " COMPLETED: %6d\n" $REC_COMPLT
echo ""
echo "   PERCENT: $((REC_PERCNT / 100)).$((REC_PERCNT - ((REC_PERCNT / 100) * 100)))%"
echo "   ELAPSED: $((MINUTES / 60)):$((MINUTES % 60))"
echo "       ETR: $((EST_TIME / 60)):$((EST_TIME % 60))"
echo "       ETA: $ETA"
echo ""

Now a little explanation so you know what I'm doing here. First, I'm setting the number of items I'm going to process - in this case 100K. When each item in the queue is processed, I log its completion with a status that says either SUCCESS or FAILURE. The simple mathematics need no explanation, but I should note that since I'm writing a shell script that it doesn't do floating point, so everything is multiplied by a large enough number to make my precision available in integer form. This will basically output something like this...

   STARTED: 2015-03-17 07:30:00
   CURRENT: 2015-03-18 17:00:00

    QUEUED: 100000 records
    FAILED:    100
    PASSED:  99000
 COMPLETED:  99100

   PERCENT: 99.10%
   ELAPSED: 23:30
       ETR: 00:43
       ETA: 2015-03-18 17:43:00

Simple and relatively precise. Of course it's operating under the assumption that each action takes roughly the same amount of time...which it may or may not. There are a lot of variables that go into that assumption - CPU load being one of the most important.

If you decide to use this, feel free to clean up the script - you may want to use printf for the ELASPED and ETR output to zero-pad the minutes and seconds, for example. You might also want to extend it by adding the ability to pass a command-line argument that contains the process name and have it look up the process, get the elapsed time and calculate the start time using something like ps -eo pid,cmd,etime and the diff function that's in the example - of course you'd want to modify the function too so that it will accept parameters and then modify the diff calls in the remainder of the example to pass in the parameters...and of course you'd want to be able to pass in the number of records somehow - maybe by passing in a process log file that has the number of items in the queue...and possibly contains the start time - or you could read the create time of the log file, either negating the need to pull the time using ps. The possibilities abound for crafting a tool that is a nearly perfect fit for your situation.

Once you've built your tool, you can then use it to keep everyone up-to-date on just when you believe the process will be done. They can then be free to go about their business and not bother looking for an email or checking in - all of that reduces multi-tasking, which we all know is a good thing.

Happy coding.

Wednesday, March 4, 2015

Time is a river of events, and strong is its current

Time is a river of events, and strong is its current;
no sooner is a thing brought to sight than it is swept by
and another takes its place, and this too will be swept away.
~ Marcus Aurelias ~
It is doubtful that one can survive in today's software engineering environment without an understanding of asynchronous, event-driven development, and that's especially true for web developers. It's seems a little difficult to believe, but we've had AJAX for more than 10 years, and for the last 6 years or so we've had a very powerful asynchronous server-side tool in nodejs.

Is being asynchronous all it's cracked up to be, however? You may be asking yourself, if I'm just building a tool that does one thing, and I know the order in which the tasks need to be done, why not just use synchronous code...and that is a really good question. Let's take a hypothetical journey and see how easily we navigate this river of time using a real-time approach.

Let's say I am building a website. To keep costs low and security high, I'm going open-source and using Apache as my web server and I'm using Apache Sling™ to manage my content. Now I can easily build a single website and get it working without a problem; however, my use case requires that I set up thousands of 'child' sites - one for each of my local offices. Since this is a hypothetical, we don't need to bother with what sort of product is being offered - it could be an educational institution with satellite offices or a religious institution, for example - we just need to serve each local 'office' as it presents different hours, a different location, and offers slightly different services.

I can roll this whole parent-child monster out by creating the right architecture - a master template with child templates and specialized content. Doing this manually is feasible on a very small scale, but quickly becomes something that cannot be managed easily. One possible solution to this dilemma is for each office to be responsible for building their own custom site using the master site we set up; however, a significant amount of education and pre-configuration would be required to make this option a reality, as each office will need either dedicated attention or an in-house 'expert'.

Luckily for us, Apache Sling is itself built on a ReSTful framework, so all we need to do is gather the data for each of the offices and then use curl or some other utility to generate the correct HTTP commands to create the site, pass in the data to update all the special values, and voilà - we build a website in less time than a human can even react to a signal. Easy, right? Not so fast.

When a person is using the interface to create the website, then going through and changing the content, there is a lower limit on the time it takes to perform those activities. Assuming the web server responded instantaneously (which we know is a fantasy itself), there still would be a response and hundreds of milliseconds between requests. What happens when a tool, like a team of paddlers in a raft, issue the HTTP requests too quickly, purely asynchronously without waiting for a response? There are a few possibilities - the web server starts seeing your attempts at creating and updating content as a DoS attack and responds accordingly, or it doesn't respond distinctly to a DoS attack and is overwhelmed, or we have a race condition between the requests. All of these possibilities leave you without a site at the end of the process, and possibly with a non-functional web server. As a Dungeon Master might say, "the stronger and faster among you paddled fiercely, spinning your boat in circles as the strong current of time washed away your boat".

What is needed in this case, is a tour guide who can tell those who are propelling the boat when to paddle and where. Let me demonstrate this idea by addressing the hypothetical situation by building a nodejs application that will create the website, then update the content, and finally, declare success. In order to do this, I'm going to use the asynchronous request (initiated by request method in the http library) to enable our "tour guide" and navigate the hazards by emitting an event (using the EventEmitter from the events library) after we've handled the response.

But...but...but...I heard that building anything synchronous in nodejs is wrong, and this sounds synchronous. Yes, in the application sense this basically turns asynchronous commands into a synchronous process, but only somewhat, as it's really more a synchronized process, not synchronous. After all, our tour guide doesn't need to know what else is going on downstream or what's going on under the water or what other rivers are like - they only need to know how to navigate this hazard on this river to get out safely on the other side.

Beside the fact that this is more a synchronized process than synchronous, we must admit that many things in the real world rely on being at least somewhat synchronous. For example, how can we know if we can update a profile unless we know the profile exists or is created or how can we know if we can ship a product unless we know we have it? We can't. Does that mean for all of these synchronous activities we cannot use nodejs? Poppycock. Yes, there is great power that comes with asynchronous processes - but that perception of power is because we assume the processes can be run in parallel. I could insert the old joke here about nine women having a baby in one month, but we all know the reality - we all recognize that there are some processes that cannot be run in parallel.

Another way to look at this is that sometimes, we lose focus and forget that while our single boat is navigating the river there are other boats and other rivers. If you're really concerned about performance, build your app in such a way that all boats on the river travel the river safely at the same time, even if each boat has to navigate from point to point.

Back to our hypothetical...a simplified portion of the code for this might look like...

function doNextStep(response) {
  if (response.status_code === 200) {
    switch (response.step) {
      case 1:
        doStep2();
        break;
      case 2:
        doStep3();
        break;
    }
  }
}
function doStep1() {
  // create the site
  destination.step = 1;
  sendRequest({host:myhost, path:'/bin/wcmcommand', port:4502}, destination);
}
function doStep2() {
  // update the site
  branch_data.step = 2;
  sendRequest({host:myhost, path:'/' + childsite, port:4502}, branch_data);
}
function doStep3() {
  // log the results
  logResults(branchData);
}

function sendRequest(options, data) {
  var req = http.request(options, function(res) {
    var body = '';
    res.on('data', function(chunk) {
        body += chunk;
      });
    res.on('end', function(err) {
        try {
          data.response = JSON.parse(body);
          emitter.emit('step_done', data);
        } catch(err) {
          console.log(err);
        }
      });
  });
  req.write(data);
}

emitter.on('step_done', doNextStep);

Of course you could use something like a timeout to build in human-like reaction times, and that might work for most of the situations, but the problem here is generally not on the end issuing the HTTP requests, it's with the end receiving the requests and processing them. We need something that watches for the response instead of waiting for a response, and this is why the callbacks on the asynchronous methods were built. Like a tour guide, the emitter calls out each time we've gotten a response and are ready to address another hazard as we've finished with the last.

In this example, we've created a river of events that our tour guide navigates, and in our hypothetical, synchronized process, it would be conceivable that we could set up a nice website in less than 200ms. The difference in speed of a (long) 200ms synchronized process compared to a human doing the same task makes me care less about whether or not something meets my anti-synchronous ideology.

Happy coding.

Monday, February 2, 2015

An Experiment in Design

While I was been between contracts, I was able to pursue a project that I've had in mind for a while, as well as spending some quality time with my child. After finishing the project - or at least this iteration of it - I thought I'd sit down and put a few thoughts together about it, because I any project or task can teach us something, if we're willing to look for the lesson and learn.

A little about the project

I have a 2002 Honda Rebel, and as much as I love the bike overall, there are a few design features that I just don't care for - a good example is the battery box cover and the matching air filter cover

You can see the chrome trimmed white plastic battery box cover on the bike in the picture to the to the right under the seat/fuel tank.

There's nothing terribly awful about the covers, they just stick out too far and are too plain for me - and I'd like a little more of the machine to show through. For the battery box cover, the solution was simple - remove the plastic cover and expose the battery and paint the black plastic liner white. That the metal frame that keeps the battery liner in place is black is a bonus, because I think makes a better contrast than chrome. For the air filter cover; however, the solution is a little more tricky, because the cover is not held in place with multiple screws, but by pins that extend out of the OEM air filter cover and rest in receivers on the white/chrome cover - but I was sure I wanted to change that as well.

What I did

After considering a number of options - among them fabricating a metal replacement or drafting and 3D printing a part - I settled on what I considered to be the most cost-effective and forgiving - polymer clay.

I started the process by creating a template using the existing air filter cover and then working the polymer clay into the correct shape. After the piece was the correct shape, I cured the clay according the manufacturer's instructions. Once the clay was cured, I took it to the bike and trimmed and filed it into the best fit possible. Once I knew it fit, I put ink on the receiving nuts inside the air filter compartment and pressed the plate onto the nuts and then made the holes in the correct position. To make sure I won't have to repeat many of the steps in this process, I used the completed part to make a permanent template that I also annotated with specific dimensions so I can more easily duplicate the process in the future - that's the image you see to the right (which in its original form is 8.5"x11" - you can get a PDF copy by contacting me).


Once the part was completed, I selected an image and began the process of transferring it to the part. I had originally tried transferring the image to the polymer clay the normal way using a transfer sheet; however, that did not work well (I assume because of the size of the image). Since that didn't work, I switched to the old-school method, masking off portions of the part and painting the unmasked portions. Because the image I chose is one that's typically political graffiti, I chose to skip the airbrush that would have given a "too polished" look and instead used a paintbrush. I also considered only masking the top, bottom, and inside borders and using a dry brush, but wanted the image to be really clear.

Again, I'm keeping costs on a near-zero level, so I'm using Testor™ brand enamel, which turned out better than I expected on the polymer clay, and was way better on the budget than a $20 can of orange paint that I'd use once to cover a few square centimeters and then wait for it to fall off the shelf and spray random items in the garage. I don't know about you, but I prefer to not have random items partially spray-painted orange - or green for that matter, even though green is a better color than orange.

At this point, I added the motto (Tiocfaidh ár Lá) under the graphic, but I was very dissatisfied with how it looked overall at that point. I didn't, however, let this one minor failure set me back - I simply repainted that section and moved on.

After the piece was painted and dry, the next thing I needed to address was the bolts used to install the cover. The OEM bolts fit the OEM cover - which is about 15mm from the top of the housing to the outside of the cover. Since my part is only about 10mm thick, the OEM bolts were about 5mm too long. A quick trip to the hardware store for M6 x 16 x 1.0 bolts and I was back to the project. A few sprays from the white Rustoleum™ on the bolts and washers, a little time to let them dry, and I was back in the garage bolting the part down with the now-white bolts.

Although the fuel tank and the cover are different shades of white, the difference is not nearly as noticeable in person as it is in the photo where the flash was pointed right at the newly-fabricated, freshly-painted part.

What did I learn and how does it apply elsewhere?

First, before I started this project, I only knew that I was dissatisfied with a couple of features on my bike - I had no idea what options there were. As I searched in vain for an aftermarket theme-based kit or even parts I could use to mod the bike, I began to get a little discouraged. There are standard accessories - floorboards, saddlebags, grips, windshields, and so forth - but nothing that would allow you to take a bike from boring, off-the-showroom-floor standard to an interesting, showcase, theme bike in a weekend (or two) of work. Without the encouragement an easy solution offers, we often settle for mass-market produced, mildly interesting designs, when we can have more. We need to recognize more often that making our mark is usually easier than we think it is and is always worth the attempt, even if we fail. I still think it would be cool if there were aftermarket theme-based kits...maybe when I win the lottery and can pursue all my hobbies with abandon, there will be and we can all express ourselves a little easier.

Second, I mentioned that I was able to spend some quality time with my child - that was because she was right beside me during much of this little project. I did not allow her to handle the paint, but she was able to hand me tools while I took off the OEM covers and help keep track of the handful of little bolts, she also helped condition the clay and helped with the first fitting, and eagerly expressed her joy when seeing that what didn't really look like anything at the beginning (while I was cutting out the image for the center panel) was recognizable when it was complete. She didn't really have an idea of what the "big picture" was, she just trusted that her contribution was valuable and valued - which it was. It's worth noting that the small encouragement in her joy meant mountains to me - it's easier to face challenges or the threat of failure when your teammates are so encouraging. In a lot of ways, as engineers we're unlike my daughter, but we need to be more like her. Sometimes we see only bits and pieces of a project, but that does not mean we should think one contribution or another is less valuable; all contributions are valuable and deserve recognition - even if the contribution is that we're "just part of the team". We don't always see how things fit together until they do, but making judgments about which are the most valuable pieces before we understand the puzzle invites assumption.

Finally, as I told my wife, this was something of an experiment. I wondered if I could easily, inexpensively modify my bike in a way that I liked. I had a few things going against me - I'd never modified a vehicle before, I'd never fabricated a part before, I have no CAD skills, I don't have a workshop full of tools, I don't...I'd never...all the negativity was nearly overwhelming. I did it anyway. Overall, I consider the experiment successful. I spent less than $15, took less than 5 hours all together (though it was broken up into 5-year-old attention span sized pieces), and was more than mildly pleased with the result. Along the way, I learned a few things - I know I'm very likely to change the design at some point, and I very likely to even change my approach - but by being willing to set aside the negativity while still realizing that I may fail, and realizing that "failing" would be OK because I would have learned how not to do something, I made things better - I like the new look better and I like the new feel of the bike too, made it my own, and it's now like no other.

Get out there. Try something different. Make your mark. Above all, ride safe.