Please visit my new campsite listing site ukcampingmap.co.uk


Archive for the ‘Computers and all that’ Category

What’s up, firebug?

Tuesday, December 1st, 2009

In the space of one day (in real-time, not blog-post-spacing time) I’ve found not one, but two incongruities in firebug’s error reporting.

The second is that if you mistakenly leave the src attribute of a script tag blank, i.e.

<script type="text/javascript" src="" ></script>

you will get the following (or similar) doctype error:

syntax error
I’m well aware this doesn’t make interesting reading, but it might help somebody spend less time than I did trying to resolve the issue.

This literally changes

Monday, November 30th, 2009

You should know that I’ve built up a lot of half-written posts recently, mostly about javascript, so this blog, as it emerges from semi-hibernation, is gonna get code-ier and more out of date as I work backwards.

So to begin at the end, I recently came across a bug which is far from obvious to track down. Look at the code below.

var MyClass = function() {
  this.a = 'dolphin';
  this.getA = function() {
    return this.a;
  }
}

myObject = new MyClass();
var callbacks = {callback1: myObject.getA}
newA = callbacks.callback1();

What will the value of newA be?

In my application, in which I used callbacks to store the callback functions for a series of custom-made dialog boxes, I was expecting the value to be a, but it isn’t. The reason for this is that callbacks is an object, and saving a function as a property of an object is, in effect, creating a method of that object, and methods of objects, when called using the ‘.’ syntax, will tend to have this refer to the object (not always, but normally). So in creating the callbacks object you inadvertently cause getA to fail as this no longer points to the myObject object, but to the callbacks object literal.

Fair enough. But what makes this error particularly difficult to track down is that firebug shows console.log(callbacks) to be an empty object. Why this is, I don’t know – it seems unlikely to me that the properties wouldn’t be created due to the value of this being reassigned, so maybe it’s a mistake in firebug ( a firebug-bug, if you will). A similar error occurs when using an array as callbacks instead of an object, but firebug reports that the function is stored in the array, and that it returns an undefined value, so it’s a lot easier to see what the problem is. But once the bug is found, the workaround for the array and the object is the same.

The method I’ve chosen is to define

var that = this;

at the top of the MyClass function, and anytime you use this but think it may be called in such a way that the context may change, substitute that for this. But this is far from perfect – you have to second guess when you will need to do this as it’s not always obvious, and you could easily miss an instance which doesn’t occur very often, but which is fatal when it does. Another solution is to use the prototype.apply method to explicitly set the context of the method, though it looks ugly and a bit indecipherable. On the other hand it is a lot more bulletproof.

I’m sure you’ll make the right decision.

(More sponge creature fun here)

But it works for me!!!

Monday, November 16th, 2009

The lines of javascript below, included at the top of your scripts, could save you a lifetime of confusing conversations with clients where they say an application doesn’t work and you can clearly see that it works on your laptop.

The difference is that you have firebug installed and they don’t, so for you console is defined, but for them it is not, so if you leave any references to it in the app it will throw an error for them. But this fixes that;

if(!console) {
 var console = {};
 console.log = function() {
   return null;
 };
}

A useful debugging method

Friday, October 30th, 2009

I’m always dismayed by the lack of debugging information out there. Yes, there is plenty of information on how to fix particular bugs, but very little on the more general heuristic processes for finding the source of a bug. This may be because debugging is, by its very nature, a thankless process of trial and error.

But nevertheless, I’ve just discovered for myself (though it may be common practice for others already) a technique for debugging when the bug lies within a function which runs numerous times without fail, but when fired on another particular occasion, fails. For example, you have one function which creates shopping basket items from all your user’s saved data at startup, but when you try and use the same function later to create another item based on user input, the function fails.

Putting some var_dump() [php] or console.log() [javascript] calls inside the function will result in reams of information being printed out, most of it useless as its produced by the successfully running first calls to the function. So what I now do is this:

Change

function myFunction(param1, param2, ..., paramN) {
    some = code;
    console.log(something);
    some = more(code);
}

to

myFunction(param1, param2, ..., paramN, test) {
    var some = code;
    if(test) {
        console.log(something);
    }
     some = more(code);
}

And change the function call that needs debugging from

myFunction(a, b, ... N)

to

myFunction(a, b, ... N, true)

Now you will only be shown the debugging messages when you need them. It’s particularly useful for javascript as the console area of firebug is so small so its good to limit messages to only those which are relevant.

Clever stuff with tables

Monday, September 28th, 2009

I’ve recently been getting to grips with the zend framework. I’ve been meaning to blog about it for a while, for there is much to discuss: appalling introductory tutorial, a class reference which for some reason is nowhere near as easy to use as others… but I will touch on all that some other time.

But I thought I should post this up before I forget. The site I’m working on at present has three kinds of users: superusers, teachers and students, with a separate database table for each kind. The tables for each could have been slightly different but I decided to make them all the same (with dummy entries in the few irrelevant columns, though later I may discover I can discard these). The reason for keeping the structure uniform was that I had an inkling that if I did I could use just one model in Zend to access all three tables… and the inkling was correct.

It took a little debugging and investigation of the Zend_DB_Abstract class, so for the benefit of others, to have a model that works for a number of tables simply start your class defininition as follows:

class Model_DbTable_GenericName extends Zend_Db_Table_Abstract
{
   protected $_name = '';

   public function __construct($type,$config = array()) {
     parent::__construct($config = array());
     $this->_name = $type;
   }
   ⋮
}

And to instantiate a DB model use the following:

$Data = new Model_DbTable_GenericName('specifictablename');

Whether or not your tables have to have exactly the same structure depends on how you define all your functions for interacting with the data – you might need to use conditionals if some tables have more or less columns than others.

Html 5 will kill us all

Saturday, September 26th, 2009

Being a font-end web developer is looking very interesting/scary at the moment. The web is awash with talk of html 5, how we should all be taking advantage of it now, and the various tools by Google and others for making it possible despite what internet explorer fails to implement.

It is, quite literally, mental!*

The last year of my web life has seen me learn more stuff (php, javascript, jQuery, Google Maps, Zend framework and more), more quickly than ever before, and there’s still a load of things uncompleted on my to-do list, Flash being the most prominent hole in my arsenal…

…until now.

My firefox has about 20 tabs open, most of them containing information about my industry that wasn’t very relevant until a few weeks ago. Now, if I’m to keep touting myself as a front-end developer of any quality I will have to learn about:

  • Vector graphics and animation, which will mean getting to grips with Adobe Illustrator and some vector graphics oriented javascript libraries which make working with Scalable vector graphics and the canvas element easier
  • The not inconsequential lengthening of the list of tags available for use in markup
  • Consider using  lot more javascript libraries as my approach to getting websites to work in ie, which runs contrary to what I’ve always done before.
  • And many more things, essentially revolving around the fact that so many things that designers would always have liked to do on websites have suddenly become feasible.

On the bright side though, SVG and canvas combined with some other subtler features of html 5 could make Flash relatively obsolete, which increases the value of the time I’ve spent learning javascript. The project I’m about to start working on was initially conceived as a Flash game, but as there’s very little animation involved I was able to propose writing it as a javascript game instead. With html 5′s new features there will be very little to elevate Flash above javascript any more in any context. Html 5 can even natively embed video.

Everything’s going to be alright.**

*I’ve been watching peep show this morning and feel constant urges to write a bit like Super Hans or Jeremy.

** or Mark

What is this?

Wednesday, September 23rd, 2009

It can’t be for real, surely. Not even Microsoft is this naff.

On the bright side though, it does mean my wait to get a new laptop is nearly over; no way was i gonna get one with Vista installed.
O

Saving my neck

Wednesday, September 23rd, 2009

I don’t want to end up like the giraffe in the picture: a crick-necked invalid with blotchy skin. As I grow older the blotchy skin is probably inevitable, but the crooked neck/back is avoidable I hope.

The trouble is that for a living I do a mixture of two things:

  1. Bent double over a laptop, twisting my fingers at unreasonable angles in order to reach a keyboard shortcut
  2. Bent double over a guitar, twisting my fingers at unreasonable angles in order to reach a wicked chord

Both these activities lead to my back muscles being tensed in an uncomfortable position, with little movement to get blood flowing to the muscles. As an added bonus, my finger muscles are also generally making the same kind of not particularly relaxed movements every day.

So what’s the antidote to all this physical self-abuse?

The idea I’m trying at the moment is juggling.

I’ve been able to juggle for a little over a year, and several of my friends are fanatical about it (working for little while in a backpackers hostel in Amsterdam is a surefire way to get people to help/force you to pick up the basics), but I hadn’t done very much since the first months when I first picked it up.

Recently, however, I realised that juggling is the antithesis of the activities that are determined to wreck my spine:

  • Rather than crouching forward, to juggle you really need to stand quite upright; if you lean forward you end up throwing the balls forward, which eventually leads to either dropping them or running after them into traffic or something.
  • More related to guitar playing this, but juggling requires very relaxed, fluid movements of the arms and shoulders. While fluidity is essential to playing rhythm guitar well, it’s impossible to avoid tensing up somewhat during the pacy irish reels we play – there simply isn’t enough time between beats to led your arm lollop along. So juggling should hopefully help counteract the stiffness I’ve been getting in my upper back.
  • Despite the fact that you’re constantly grasping in the air to catch a ball, juggling requires you to relax your hand muscles too. Catching a ball when you juggle isn’t about holding it tightly; if anything, it’s closer to forming a cup shape for the ball to nestle into.

So, that’s the summary of why I think juggling might help. I’ll keep you posted on whether or not it is the miracle cure I’ve been looking for.

Not the village idiot any more

Saturday, September 12th, 2009

I’m starting to find that when I ask javascript questions on forums similar to

I’ve been using such and such a method to achieve something, but there must be a better way. What is it?

Then the answer that comes back is quite frequently (though far from always)

Your method is probably the best way.

Which is a nice feeling. As I’m a self-taught programmer I’ve always been very aware that most people I work with have studied and worked as programmers for years and years, and inevitably* have picked up a lot of tricks along the way… and that try as I might I can’t just learn these from a book or a website (though I’ll give it my best shot); it’s just a matter of building up years of experience, banging up against this or that obstacle and learning from other programmers.

So, considering that a year ago I didn’t know javascript, or any programming language, I’m pretty pleased that I can confidently lay claim to not being a complete moron any more.

*though it’s surprising how many exceptions to this rule there are.

My jQuery plugin writing tips

Wednesday, September 2nd, 2009

I’ve now written two jQuery plugins, and have a pretty good idea for a third. As you might expect, I’ve learned quite a few things along the way. When I started there was a lot I didn’t know about javascript and jQuery. There still is, but one thing that struck me is that there are a lot of great tutorials on writing jQuery plugins out there but none of them individually captures all the things that took my plugins from being nice ideas with mediocre implementations to being something I’m proud of.

So here is my definitive combination of them all, together with one or two of my own contributions (a bit scant on detail, but follow the links for more info).

1. Build a good test page

My test page for any given plugin has 3 instances of a type of element the plugin is suppose to effect. eg a list. They are marked up as follows:

<ul class="single" >...</ul>
<ul class="multiple" >...</ul>
<ul class="multiple" >...</ul>

And I run the following script in the document head

$(document).ready(function() {
  $('.single').myPlugin();
  $('.multiple').myPlugin();
});

This will make sure your plugin works when called more than once on a page, and when one instance affects more than one element. For testing your code for speed the same page with various bits of html copied lots of times does the trick.

2. Follow jQuery’s recommended tutorial

It really is very good, and covers most important points. The other items on the list are either little tweaks that I think make the code neater or, in just one or two cases (highlighted in red), things its missed out. Read the tutorial

3. Make sure your plugin won’t conflict with other javascript libraries

The most effective way to do this is to wrap your whole plugin in a function where $ is its parameter, and then call it on jQuery, like so:

(function($) {
  $.fn.pluginName = function(options) { ... };
})(jQuery);

More info

4. Make your plugin’s settings changeable, both when the plugin is called, and by tweaking the default settings

The way to do this is to set up your plugin’s defaults as a JSON which is a public property of the plugin object. So within your plugin add these lines (where options is the name of the JSON passed to the plugin as a parameter).

this.defaults = {parameter:'value', ...};
options = $.extend(defaults,options);

More info

5. Make sure your plugin keeps track of DOM elements effectively

Structure your code as follows in order to make sure your variables are accessible to the right instances of the plugin, but aren’t stored in memory longer than they need to be.

$.fn.pluginName = function(options) {
  var constructor1, constructor2, ...;//elements that are used only when the plugIn is constructing instances of itself at the start and play no role in handling later events;
  return this.each(function() {
     var tracker1, tracker2, ...;//elements that are important for events and other later changes. Also, if your plugin's constructor involves some AJAX it may be best to put all variables in here
     subFunction() {
	//this should always be able to call the variables it needs, in particular access the right DOM elements
     }
  });
};

6. Optimise, opimise, optimise

You never know how demanding the website using your plugin is going to be: how many times is it going to be called on one page; will the dom objects (eg sorting a list of items) it has to handle be a lot bigger than the ones you’ve tested it on. My crossSelect plugin was, I discovered, before version 4/5, really sluggish on lists larger than about 20 items.

So I found a great list of techniques to optimise your code, the most pertinent to writing plugins I have put below:

  • Make sure your optimisations are optimisations

    To keep track of whether your optimisations are having the desired effect, run your plugin on a page full of huge elements for it to process and then use firebug to measure the time it takes.

  • Don’t over-query the DOM

    jQuery is principallya tool for accessing and manipulating the DOM, but it doesn’t pay to do this too often as your code will be a lot quicker if you keep it to a minimum. Techniques for avoiding this include:

    • store DOM elements you know you will have to access a few times in variables (but be careful – see point 5)
    • Add new DOM elements as html, . So instead of
      $('selector').append('<ul>');
      for(i=0;i<limit;i++)
      {
        $('selector > ul').append('<li>'+i-th text+'<li>');
      }

      use

      string = '<ul>';
      for(i=0;i<limit;i++)
      {
        string+='<li>'+i-th text+'<li>';
      }
      $('selector').append(string);

      The improvement in speed of code is astounding.

    • Use contexts. A lot. It will both reduce code size (as shown below) and speed up the code (because jQuery only has to search a subset of the DOM). So instead of
      var theContainer = $('selector');
      $(theContainer).children('ul').children('li').aMethod();

      use

      var theContainer = $('selector');
      $('ul>li', theContainer).aMethod();

And that’s yer lot. Please let me know if you have any comments or suggested additions.