Use Lucida, Lose Your Readers

April 12, 2007

I’m sure, like me, you’ve come across sites which seem reasonably well designed but where the font looks all wonky and manky, as if it got rendered at a different size and scaled down using a nearest-neighbour transformation *. I came across one today and decided to get to the bottom of it. (For the record, it was for this interesting-sounding SEO tool.)

The cause? Not the use of <font> tags — though what the hell are they doing there? — per se, but their insistence on face="Lucida Sans". Strip them out, or bung in an accepted web font like Arial, and the lumpiness disappears.

Shame, really, ’cause Lucida Sans is a great font, but it clearly doesn’t scale well, or at least not the version installed with XP on my PC. (And no, it’s not the browser. IE6 & 7 make as much of a mess of it as Firefox does.)

Makes you wonder why the designer thought it worked. The stylesheet (yep — he or she did know about CSS) specifies an unusual body font size of 78.5% and if I could be bothered I reckon I could use this to figure out their monitor resolution. It must have been a lot of dots per inch, as there are certain high magnifications where the text looks as Charles Bigelow intended. 140% in IE7, for example.

So add this to the usual admonishments about specifying font sizes and the like: don’t be tempted to stray from standard web fonts or, SEO company or not, you may drive away visitors with unreadable text.

*My best guess is that this is exactly what’s going on.

The Flipside of Star-HTML

January 23, 2007

… is star-pipe-html

I was trying to work around a small Firefox bug today, which involved block elements which should have automatically filled the whole viewport but weren’t, due to some perfectly ordinaly right-floated images. (More investigation into this is required, but that’s a side-issue here.) Luckily, this is a fixed-width layout, so I tried feeding the width in, which cured the problem in FF, but blew up everything in both IE6 and 7. Opera carried on working just fine.

I could have just lived with the blemish in FF, but it would have bugged the hell out of me, so I started looking for a hack that could filter out all versions of IE. (I refuse to use conditional comments. I will not pollute my HTML.)

I came across this very useful Wikipedia page detailing CSS support in all major browser engines. Studying the Gecko and Trident columns I was surprised how much IE has caught up in selector support, but there are small differences, and one was an attribute selector I’d not come across before, the Namespace Selector. In fact the Wikipedia table gets the syntax wrong, but some further Googling turned up the syntax that Firefox (and Opera, Konqueror) accept:

ns|elt (where ns is an XML namespace and elt is an XHTML element).

I tried leaving the namespace blank (which is permitted), but

|html #secondaryContent li { width:660px }

wasn’t read by FF. First I thought I had the wrong day, the wrong browser or the wrong profession for my idea, but then I realised that this selects elements whose namespace is not specified. I had picked the very worst html element of all for that selector, the one which does carry a namespace. (At least it does in my doc, which begins:

<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

…etc, etc.)

The correct selector to select a body element with a namespace attribute (any namespace attribute) was…

*|html

So this is it; a nice, easy-to-remember filter to EXCLUDE ALL EXPLORER VERSIONS up to and including IE7. And not to be confused with our old favourite * html (space, not pipe), which we all know selects for IE6 and below. You could combine the two to make a high and low pass filter for IE7, thus:

p.styleme { color:red } /* IE7 */
* html p.styleme { color:blue } /* other IE */
*|html p.styleme { color:pink } /* FF, Opera, Konqueror, Safari */

According to the table, KHTML understands the namespace attribute selector, but WebCore does not, so it is an open question whether this filter will be seen by Safari. Can anyone confirm this? (Don’t have a Mac around here.)

As with all CSS hacks filters, caution is advised. In this case, I wanted to fix a small blemish in FF while avoiding a blow-up in the IE minefield. I’m comfortable in not knowing the exact behaviour in Safari, iCab and other minority browsers: it’s unlikely that feeding an element the width it ought to have anyway is going to have an adverse effect. But without careful thought, havoc could easily be wreaked. Nevertheless, I thought I’d share this, as in the right circumstances it could be quite useful.

UPDATE: The hack has been confirmed to work in Safari.

School of Rock Advent Calendar

December 4, 2006

Having failed, as usual, to find an advent calendar that meets my daughter’s exact specifications – not tacky, no low-grade chocolate – this is my (slightly late) offering to her. Fun moments from her favourite film, and no cloying, oily aftertaste.

Technically an online advent calendar could hardly be easier; in fact it took her brother and I as long to pick stills from the film as it did for me to code up, which I did using a small amount of css; an even smaller amount of HTML – a single image tag for the resizeable background, and an empty div to hold the images – plus a modicum of jQuery (with some popup assistance from Thickbox).

The jQuery code was mostly familiar territory for me: the images are scripted onto the page in a single loop, and - after the appropriate date - clickable to reveal the image (with attached thickbox link).

The only really interesting parts were the ‘random’ mapping so that images didn’t all appear in numerical order – achieved via a hard-coded mapping object, as there is apparently no way in javascript to fix a seed for the random number generator – and the use of cookies to remember which windows my daughter (or anyone else who cares to enjoy it) has opened, which pushed my envelope slightly. It seems incredible to me that all cookies get returned in one horrible, semicolon-delimited string (what would have been so bad about a string array?), but there you go.

Amazingly the two cookie handlers worked perfectly, although a bug in my mapping between jQ objects and DOM objects hid this for a while. This is always a tricky issue in OOP whenever you have two representations of the same thing, and the standard solution (attach a custom property - in this case .ref - to the DOM object holding the array index of the item which describes it) always feels a bit like a hack.

Anyway, for what it’s worth, here’s the code:

var windows = new Array;
var today = new Date;
var mapping = {
  1:17,
  2:22,
  …
  23:20,
  24:4
};
var folder = "school_of_rock";
$("body").ready(function() {
  for (var j=1; j<=24; j++) {
    var thing = document.createElement("div");
    thing.ref=mapping[j];
    windows[mapping[j]]=$(thing)
      .addClass("window")
      .appendTo("#picContainer")
      .html("<p>"+mapping[j]+"<\/p><img src='"+folder+"/"
        +mapping[j]+".jpeg' \/>")
      .bind("click", function() {
          $("body").focus();
          if (today.getDate()>=this.ref) {
            $(this)
              .find("img")
              .css("visibility", "visible")
              .wrap("<a href='"+folder+"/"+this.ref+".jpeg'
                class='thickbox'></a>");
            TB_init();
            setCookie(this.ref);
          } else {
            alert("Not yet!");
          }
          return;
      });
    //windows[j].get().ref=j;
    if(!readCookie(mapping[j])) {
      windows[mapping[j]].find("img").css("visibility", "hidden");
    } else {
      windows[mapping[j]].find("img").wrap("<a href='"+folder+"/"
         +mapping[j]+".jpeg' class='thickbox'></a>");
    }
  }
});
function setCookie(n) {
  document.cookie = "opened"+n+"=true; expires=Mon, 1 Jan
    2007 00:00:00 UTC; path=/";
}
function readCookie(n) {
  var where = document.cookie.indexOf("opened"+n);
  return (where!=-1);
}

It’s quite re-usable (I’m already thinking about the countdown for Christmas 2007). Ideally I would have scripted the background image into the page, so that only a single change in the folder variable would be neded to repurpose the entire thing. Oh, and if it hadn’t been so late at night, I would have added some animation to the window opening.

I should mention that since it has a target audience of (I)one, and I know which browser she uses (Flock), I have happily not had to think about how it looks in Internet Explorer, a situation of which I have taken full advantage. Since it uses percentage sizes and relative positioning, it’s fair bet IE6’s faulty positioning model will screw it up royally. If anyone else can be bothered to make it work I would be interested in seeing it.

Next year, she wants sound, too ;-)

Valid CSS Is Irrelevant

November 12, 2006

Someone recently posted on the css-d list (a useful place to learn more about practical CSS) a very ugly hack which proudly announced at the end “this hack is valid CSS3″. Well, great. Does that mean that whatever flaw in the target browser (in this case Safari) the hack was used to work around will bring other browsers to their knees when they catch up in CSS support? Not a great approach to web site building.

I am not anti-hack. Recently I resorted to an amazing filter: hack to get around an inheritance bug in IE6, and I use * html in pretty much every stylesheet I write. But normally I am compensating for some major lack of support in the still-unfortunately-widespread IE6 that other contemporary browsers have (eg no min-height). I think hacking for leading-edge browsers is a bad idea, and try to confine myself to hacks that can do no harm in the future (I don’t use the underscore hack, but it’s a safe one, as it’s unlikely new browsers will suddenly start supporting it.)

And as for “valid CSS” – I could care less. zoom:? filter:? Ok, if it works. Valid HTML - yes, please. That’s future-proofing. But isn’t CSS where we shunt all the complexity and ugliness that used to be in the markup? One day there may be an elegant and easy-to-understand layout language, but sadly CSS ain’t it.

In my view, as developers we are custodians of the information entrusted to us. In trying to make it appear on screen as intended we should add as little cruft to the markup as possible to achieve the desired look and feel. CSS and Javascript are tools to add visual appeal and functionality to the basic information. These need to be future-proofed too, of course, but we must accept that they are of secondary importance and some day they may be superceded.

Aiming for valid CSS is fine, and won’t it be nice when it’s all we need? But we mustn’t fool ourselves into thinking that if it validates we can’t have done anything wrong.

Solving Sudoku with Javascript

July 14, 2006

Like many people here in the UK I have been struck down with the Sudoku bug, and as a programmer wondered vaguely how I would go about mechanising the various techniques I’ve figured out for solving the little sods. A couple of days ago, tackling a particularly nasty one, I was forced to do something I normally avoid: picking one of the available options on a particular square and tracing the consequences. Then it struck me: this was the way to get a computer to solve the puzzle. I find it hurts my frontal lobes trying to hold all the possibilities in my head at once, but computers excel at this. Fill in the ones you can, then pick a possibility and go round again. You’ll either hit lucky or hit a brick wall. Recursion, here we come!

So I have developed my idea into a Sudoku solving web page. If you’re not interested in the technical details, but just want to solve a few sudoku puzzles, the sudoku solver is here.

Kind-of Extreme, Object Oriented Programming

I love javascript, and its loose typing is ideal in a scenario where a given square may contain a single number, a list of possibilities, or nothing. But I wanted to do proper OOP javascript. Some people still don’t seem to have got the message that this is possible, but here it is a real boon if not an absolute necessity, as my algorithm is intrinsically recursive.

After knocking up a nice-looking HTML form to gather and display the grid, I wrote my first bit of javascript, to be called by the form’s onsubmit attribute. It wasn’t much different to the final version quoted here:

function solve() {
  store = getTableData();
  var solution = solveTable(store);
  if (solution.getResult() != "solved") {
    alert("it appears this puzzle cannot be solved");
    return false;
  }
  populateForm(solution.getTable());
  return false;    //stop action being called
} 

A lot of wishful thinking, there, but I have some sympathy with the Extreme Programming philosophy, which in affect says: "just start coding". That’s how my mates and I used to knock programs together back in our ZX81 days, in any case. It’s the object-orientated part that come less easily to me, having begun with Sinclair BASIC, though I’m finally starting to think along those lines even when it comes to the non-obvious OOP likes of JS.

So what does this solveTable() function do, exactly? Well, the idea is that it scans through a table and returns another table in which every gap has been replaced by a list (javascript array) of possibilities for that square. It also needs a way of indicating whether the table has been solved (hurrah!) or if it led to a blind alley (boo!), as well as the most likely scenario that some but not all of the squares have been filled with a single number.

Classwork

I decided to create two classes (if one can properly call them than in JS, maybe object constructors is a better term): The first was Table - to hold the various intermediate grids and do stuff to them. Here is its constructor:

function Table(a) {
  //a is optional 9x9 array
  this.it = new Array(9); // (col, row)
  for (var k=0; k<9; k++) {
    this.it[k] = new Array(9);
  }
  if (a) {
    for (var j=0; j<9; j++) {
      for (var i=0; i<9; i++ ) {
        this.it[i][j] = a[i][j];
      }
    }
  }
}

To simulate a multidimensional array in javascript you have to intialise each element of an ‘outer’ array to itself be an (‘inner’) array. The optional initialisation array might turn out to be useful.

At first I had a syntax error in here where the third line read:

var it = new Array(9); // (col, row)

This project taught me that the var keyword can be problematic in ECMAScript languages like js. The above line looks directly analagous to a line of Java code, such as:

Array it = new Array(9);

but js ‘classes’ are a bit of a kludge, and the this keyword is required so that the new array gets attached to the instance of the object being constructed.

I also made simple getter and setter methods (agaist which the old, non-OOP self inside tries to rebel: "Why not just reach in and get the thing you need?", it rants).

Table.prototype.getDataAt = function(coord) {
  return this.it[coord[0]][coord[1]];
};
Table.prototype.setDataAt = function(coord, value) {
  this.it[coord[0]][coord[1]] = value;
};

I managed to screw these up at first, too, writing stuff like:

return this.it[coord[0], coord[1]];

Wake up, brain! No native multidimensional arrays in js!

The nature of the Table object is that changes are made ‘in place’. This is a key feature of my algorithm, so that the latest version of the grid, with any completed boxes, is always right there.

This next bit was my first real benefit of using OOP. Orignally I had three helper methods which found all the filled-in squares in a given element’s neighbouring column, row and 3x3 square, respectively. When I realised I could make them object methods, I no longer needed to keep track of which copy of the grid I was currently working with (a nightmarish task, which would still go on to cause a frustrating bug at the end).

Table.prototype.neighbourhoodCol = function(coord) {
  //iterate down column, so col number is fixed
  //returns a vector of other known numbers in the same column
  var retVect = new Array();
  var temp;
  for (var j=0; j<9; j++ ) {
    temp = this.it[coord[0]][j];
    if (typeof(temp) == "number") {
      retVect.push(temp);
    }
  }
  return retVect;
};
Table.prototype.neighbourhoodRow = function(coord) {
  //returns a vector of other known numbers in the same row
  var retVect = new Array();
  var temp;
  for (var i=0; i<9; i++ ) {
    temp = this.it[i][coord[1]];
    if (typeof(temp) == "number") {
      retVect.push(temp);
    }
  }
  return retVect;
};
Table.prototype.neighbourhoodSquare = function(coord) {
  //returns a vector of known numbers in the same 3x3 square
	
  //calc top left of square:
  var sqx = (Math.floor(coord[0]/3))*3;
  var sqy = (Math.floor(coord[1]/3))*3;
  var retVect = new Array();
  var temp;
  //iterate through square
  for (var j=0; j<3; j++) {
    for (var i=0; i<3; i++ ) {
      temp = this.it[sqx+i][sqy+j];
      if (typeof(temp) == "number") {
        retVect.push(temp);
      }
    }
  }
  return retVect;
};

At last, some sudoku-specific code! And it worked pretty much straight away, once I’d realised that typeof() returns "number" (with a small ‘n’) when passed a Number (big ‘n’).

push() is a very nice way of building an array of indeterminate length, just by shoving items onto the end in a stack-like way. Oh, and please forgive me for continually referring to single-dimensional arrays as ‘vectors’.

Rapid Response

The other class I needed was a responseObject which gets returned from the solveTable() method with various helpful bits of info, such as the current Table; a string to indicate success, failure or the need for another go round; and the coordinates of an undetermined element with the least number of possibilities, to cut down on the size of the search tree (really the only bit of optimisation I’ve done on this. I’m sure there’s bags more room for improvement.)

function responseObject(t, r, l) { //constructor
  this.obj = { "table":t, "result":r, "least":l };
}
responseObject.prototype.getTable = function() {
    return this.obj["table"];
};
responseObject.prototype.getResult = function() {
  return this.obj["result"];
};
responseObject.prototype.getLeastCoords = function() {
  return this.obj["least"];
};

The simplicity of OOP code belies its power. That looks like nothing. But it will come in very handy when that nasty bug I mentioned rears its antennae. Do note the object constructor literal:

this.obj = { "table":clonedTable, "result":r, "least":l };

ECMAScript objects are associative arrays (aka hashtables), where the index can be any string - one of the more powerful data structures. I love that this power is always there under the bonnet, should you ever need it, even when doing the most basic stuff.

The First of Many Solutions

So we have most of what we need for the long sought-after solveTable() function (not an object method, notice, as we need to recurse on it):

function solveTable(t) { //to be recursed, returns a responseObject
  var attempt = findPossibilities(t); //returns a responseObject
  if (attempt.getResult()=="solved") { return attempt.clone(); }
  if (attempt.getResult()=="failed") {
    return new responseObject(t, "failed", null);
  }
  var origT = attempt.getTable();
  var coord = attempt.getLeastCoords(); //this is a 2-vector
  var bestAttempt;
  var possArray = origT.getDataAt(coord);
  for (var i=0; i<possArray.length; i++ ) { //should have at least 2 entries
    var newT = origT.clone();
    newT.setDataAt(coord, possArray[i]);
    var attempt2 = solveTable(newT);
    if (attempt2.getResult() == "solved") { return attempt2.clone(); }
    if (attempt2.getResult() == "unsolved") {
      bestAttempt = attempt2.clone();
    } //not really best, just an attempt that didn’t fail
  }
  if (bestAttempt) { return bestAttempt.clone(); }
  else {
    return new responseObject(origT, "failed", null);
  }
}

Ok, ok - so I deferred most of the heavy lifting to findPossibilities(), but this is just for legibility, making it easier for me to think about the main recusion, which schematically goes:

solveTable():

  1. get possibilities
  2. if solved, return
  3. otherwise, iterate over possibilities at a single unsolved position (the one with least choices)
  4. run solveTable() on each
  5. return best attempt

It was as I was writing this that I had my first ely that there might be a problem with the working-in-place nature of the Table class. In order to differentiate the multiple grids produced by each attempt, I introduced a clone() method (below) which is called before the main loop is entered:

Table.prototype.clone = function() {
  return new Table(this.it);
};

Since each Table is modified in place, every time we embark on a new variation, a fresh copy must be made.

The findPossibilities() helper function, together with its sub-helpers union() and makeNegative(), adds up to a lot of code, but it just does the donkeywork of aggregating the three sets of possibilities, calculating the least unsolved coordinate, and making the appropriate responseObject.

function findPossibilities(inTable) {
  var outTable = inTable.clone();
  // we work in place, so make clone of original to work on
  var coord = new Array(2);
  var response = "solved";
  var least;
  var leastLength = 10;
  //var hashNew=0;
  for (var j=0; j<9; j++) {
    for (var i=0; i<9; i++ ) {
      coord = [i, j]; //col, row
      if (typeof(outTable.getDataAt(coord)) == "number") {
      continue; } // already filled in
      var nr = outTable.neighbourhoodRow(coord);
      var nc = outTable.neighbourhoodCol(coord);
      var ns = outTable.neighbourhoodSquare(coord);
      var nu = union(nr, union(nc, ns));
      //all known numbers it can’t be
      if (nu.length==9) { // gone wrong
        response="failed";
        break;
      }
      var un = makeNegative(nu);
      if (un.length==1) { // found entry, stored as a number
        outTable.setDataAt(coord, un[0]);
      } else {
        //hashNew+=un.length;
        outTable.setDataAt(coord, un);
        // otherwise store array of possibilities
        response = "unsolved";
        if (un.length < leastLength) {
          leastLength = un.length;
          least = coord;
        }
      }
    }
      //showTable(outTable);
    if (response=="failed") break;
  }
  return new responseObject(outTable, response, least);
}
function union(a, b) { //set theoretic union of two arrays
  if (!b || b.length==0) return a;
  if (!a || a.length==0) return b;
  var retVect = new Array();
  for (var i=0; i<a.length; i++) { //deep copy of a
    retVect.push(a[i]);
  }
  var tester;
  var gotIt;
  //manual scan through   for (var i=0; i<b.length; i++) {
    tester = b[i];
    gotIt = false;
    for (var j=0; j<a.length; j++) {
      if (a[j] == tester) {
        gotIt = true;
        break;
      }
    }
    if (gotIt) continue;
    retVect.push(tester);
  }
  return retVect;
  }
  function makeNegative(v) {
  var set = [1, 2, 3, 4, 5, 6, 7, 8, 9 ];
  for (var i=0; i<v.length; i++) {
    set[v[i]-1] = null; // put null in place of found number
  }
  var retVect= new Array();
  for (var i=0; i<9; i++) { // accumulate non-null entries
    if (set[i]) { retVect.push(set[i]); }
  }
  return retVect;
}

These last two functions are pretty ugly, but they get the job done. JS doesn’t have any set-theoretic functions as far as I know, and I only did one term of computer science, so my union() function looks amateurish even to me. If anyone knows a more elegant solution, please leave a comment. makeNegative() is another sudoku-specific piece of code, figuring out what’s left once you eliminate the numbers it can’t be.

What’s Bugging You?

Putting in the so-dull-they’re-left-as-exercises-for-the-reader getTableData() and populateForm() functions enabled testing to begin, but even aided by the wonderful Firebug extension to Firefox, and my custom trace() function:

function trace(s) {
  var tr = document.getElementById("trace");
  var para = document.createElement("p");
  tr.appendChild(para);
  para.innerHTML=s;
}

with its accompanying html:

<div id="trace" style="position:absolute; right:0; top:0; width:400px;
height:100%; border:1px solid pink; overflow:auto;
font-size:12px; line-height:11px; margin:0; padding:0"></div>

it seemed I couldn’t iron out every bug. Most of the time it would loop endlessly, or return "failed", but occasionally it would appear to solve the puzzle correctly, apart from one stray, wrong digit! Only by a thorough mental re-examination of the algorithm was I able to convince myself that it was sound, and must always return a valid result if properly implemented.

Well-positioned trace() calls and, particularly, use of a special showTable() helper:

function showTable(t) {
  var temp;
  for (var j=0; j<9; j++) {
  var g = "";
  for (var i=0; i<9; i++ ) {
    temp = t.getDataAt([i,j]);
    g+=((temp) ? temp : ".")+" ";
  }
  trace("<pre>"+g+"</pre>");
  }
}

showed that things progressed normally until a “failed” state was found (ie a position had no possibilities at all), and the depth-first search had to backtrack up the recursion stack. At which point it seemed data corruption occurred; in other words, because the Tables are being passed by reference, subsequent iterations were accessing old data, causing mayhem. Armed with this, I made two changes which to my slight shock instantly fixed all the problems:

I introduced a clone() method to the responseObject,

responseObject.prototype.clone = function() {
  return new responseObject(this.getTable(), this.getResult(),
  this.getLeastCoords());
}

invoking it whenever such an object was passed back. I also modified the responseObject constructor so that a clone of the Table is passed, not the original.

function responseObject(t, r, l) { //constructor
  var clonedTable = t.clone();
  this.obj = { "table":clonedTable, "result":r, "least":l };
}

Whether both of these are necessary, I’m not sure. Recursion still makes my brain hurt, especially when coupled with pass-by-reference and OOP.

I’m not sure if the resulting page will be useful to many people as an actual tool, though my daughter suggested it could be used for creating your own sudoku puzzles (by typing in a few random digits and seeing if a solution exists). At the moment, however, my algorithm cannot detect whether the solution it finds is unique. In fact, because it advances by guesswork, it can ’solve’ the empty grid. Still, for what it’s worth, here it is. I hope I have illuminated some useful javascript nooks along the way.

Get free blog up and running in minutes with Blogsome | Theme designs available here