Developing Feather-Weight Webservices with JavaScript

Pangrams in action

Handling PEBKAC

A first misuse of the service. Misusing code is generally easier than using it. If it can, it will happen.

Used incorrectly, without client setup script

<script type="text/javascript"
  src="http://elektrum.org/js/pangram.js"></script>

The result of this egregious behavior

Why does that seem to work correctly? Because we expected bad behavior and designed the service to account for it. It’s debatable what code should do when used improperly. We have three major options.

  1. Fail politely and silently. Deliver no output whatsoever while making sure to not throw any errors either.
  2. Fail verbally with feedback about the improper use and how to correct it.
  3. Don’t fail. Select reasonable default arguments to deliver regular output.

Which you choose has to do with your audience. If developers are your target, you should go with #2. No one likes mystery debugging.

If you expect non-techies will be the main users, #3 is probably good. It’s the one we chose for the pangrams. It has the advantage of making you look good even if the client bungles the usage, as well as giving the chance to assert your own choices. For a marketing related service/application this could be ideal.

#1 is probably the wrong choice. It allows your code to sit quietly in the dusty corners of HTML, nibbling bandwidth, skewing usage statistics and never doing anyone any good.

Book at 4 sizes with sphinx

<script type="text/javascript">
<!--
 pangram = 'sphinx';
 family = 'book';
 font = 'bookman old style';
 sizes = [ 8, 10, 12, 14 ];
 showSize = 1;
 showFace = 1;
//-->
</script>
<script type="text/javascript"
  src="http://elektrum.org/js/pangram.js"></script>

The result

ABC123 in sans-serif at tiny sizes

<script type="text/javascript"><!--
 pangram = 'abc123';
 family = 'sans';
 font = 'helvetica';
 sizes = [ 4, 6, 8, 10 ];
 showSize = 1;
 showFace = 0;
//--></script>
<script type="text/javascript"
  src="http://elektrum.org/js/pangram.js"></script>

The result

Huge ornate in one size, no extra info

<script type="text/javascript"><!--
 pangram = 'dutch';
 family = 'ornate';
 font = 'zapfino';
 sizes = [ 60 ];
 showSize = 0;
 showFace = 0;
//--></script>
<script type="text/javascript"
  src="http://elektrum.org/js/pangram.js"></script>

The result

Single line, monospace, 2 client determined, random sizes

<script type="text/javascript"><!--
 pangram = 'fox';
 family = 'mono';
 font = '';
 random_sizes = new Array();
 for ( i = 0; i < 2; i++ ) {
   random_sizes.push( Math.floor( Math.random() * 28 ) + 3 );
 }
 // we do an inline numeric sort
 sizes = random_sizes.sort( function(a,b){return a-b} );
 showSize = 1;
 showFace = 1;
//--></script>
<script type="text/javascript"
  src="http://elektrum.org/js/pangram.js"></script>

The result

Postmortem Evaluating the project

Good project. It required a bit of somewhat complicated CSS to look good and fit safely in pages. Note again that names like sizes are a terrible idea for globally visible variables.

There are other considerations a full type sample service would need, like showing different weights, normally only bold is available, and styles, normally only italic or normal. We should also de-duplicate the list of font families. For example, if family = 'book'; is set but we want to use font = 'garamond'; to move Garamond from 2nd choice, to first choice, the font names, if we turn on showFace, will read, “Garamond, Caslon, Garamond, Serif.”

We could add support for any number of layout issues via CSS; color, sizeType=pixel in lieu of points, or embedded style classes. We’ll save that for the second system and gauge its effect then1.

Another failure of the design is it fails to account for the possibility the user’s browser doesn’t support JavaScript or has it off. We should probably throw something like this into the client code.

Failsafe

<noscript>
<h3>JavaScript is not enabled in your browser</h3>
<p>
Sorry! The pangrams are unavailable without JavaScript. Visit
<a href="http://feather.elektrum.org/">http://feather.elektrum.org/</a>
for more information and help.
</p>
</noscript>

That might not be a good idea, though. More about that in the next chapter.

A UI problem becomes obvious when putting a page like this together. Because of the way these work, only one should be viewed on a page. The namespace is polluted by each set-up script so that any variables set in one carry over to all the following.

To get around that, we can put them in a specific order and reset all variables for each example after the first. This is awkward UI though and far from ideal.

Something that would be really nice in this case would be a way to pass scoped arguments to the service. Above, we had to set every variable, every call, even if it was just to turn it off because it was on in another version. We’d also love to move away from the dual script idiom if there is something simpler available. There is.

It’s a deceptively simple technique and one that we believe is generally, if not completely, unknown. Without further delay: Passing JavaScript arguments via the src attribute.

1 We hope that was amusing to at least one reader. More about second system effect at Wikipedia.
« Pangrams for typographers · Passing JS args via src »
Google
 
Web Developing Featherweight Web Services with JavaScript
This is version 0.57b of this manual. It is a beta version with some gaps. We are grateful for feedback.

The code is the manual has not yet been fully tested against Internet Explorer. Bug reports are welcome.
An Elektrum Press Online