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


Archive for the ‘Javascript’ Category

jQuery listSplitter plugin

Monday, February 1st, 2010

A very short post to announce my third  jQuery plugin: listSplitter, which takes a long list of categorised items (where the categories can overlap) and creates a tabbed interface to show only one category at once. I haven’t done a demo yet (well, I have, buthaving teh same old problem transferring to the server as the server runs on UNIX while my laptop is Windows. I recently found out why this causes a problem, but no easy fix has presented itself) so you’ll just half to take my word for it, though before too many months have gone by I will use it as the basis for a new portfolio.

*edit: Here is a demo

And it can be used with jQuery themeroller, i.e. use the tool at jqueryui.com/themeroller, to design how it shoudl look, then after clicking “download theme” make sure you have ‘tabs’ ticked underneath widgets.

Immunodeficiency

Tuesday, January 26th, 2010

I just solved  a bug which stemmed from the fact I forgot that javascript is a referential language, i.e. if you have a variable and you set another variable equal to it then it doesn’t in general clone the original variable, but merely just points both variables towards the same underlying object. This only applies to Arrays and Objects though, and to prove it here is a little demo (it turns out you can embed javascript straight into wordpress posts now!)

Irritatingly, if you have a bug which is caused by forgetting this principle then this will also make it hard to debug because it also affects how firebug reports information to you. When you console.log() an object or an array, firebug does the same as javascript – it creates a reference to an underlying object in the DOM. So, if you’ve been logging an object repeatedly in order to pinpoint when a rogue change takes place firebug will consistently provide you with references to the object as it is after your script’s finished running – not much use.

However, there is an easy way out*. console has methods other than .log(), and possibly the most useful is console.dir(). console.dir() takes a snapshot of any object or array, printing out each of its properties without maintaining a reference to the underlying object, and therefore giving a you a snapshot of an object as it is at the time.

*And a hard way (console.log() the properties of an object individually), which is how I resolved my bug, before  looked into what other methods console had

Ternary gets a turn

Thursday, December 3rd, 2009

I’ve recently started using the ternary operator more. For those not in the know already, it’s a bit like shorthand for

if () {
} else {
}

but with a few similarities to other parts of the language too (NB this is based on the javascript implementation – other languages may differ slightly).

So, in the simplest case, instead of writing

if (statement)
{
   codeblock1
} else {
   codeblock2
}

we can write

(statement) ? codeblock1 : codeblock2 ;

which is a great way of cutting down on lines of code when each code block is only a single line. A few tricks to make using it more fulfilling are as follows.

The ternary operator can be split over two lines

So instead of

(statement) ? codeline1 : codeline2 ;

I mostly use

(statement) ? codeline1 :
              codeline2 ;

I find it more readable, as it really draws out the structure of what the code is doing. It also looks a bit like a switch statement (which, incidentally, I hear runs slow in javascript), which will come in useful later.

You can get rid of the brackets/parentheses

I tend to leave them in though as if the statement to be queried is long it would otherwise be easy to not notice that at the end of it comes a ?. The brackets remind you that what’s within is to be evaluated as true or false.

The ternary operator doesn’t have to start the line, and often shouldn’t

The following lines are equivalent:

(cetacean.mass > 1000) ? var family = 'whale' : var family = 'dolphin';
var family = (cetacean.mass > 1000) ? 'whale' : 'dolphin';

As you can see the second version results in less code, which is also easier to comprehend as the action of the line – assigning a value to a variable – is clear from the beginning of the line. As a rule of the thumb I put as little within the ternary operator as possible.

(As an aside the && and || operators – normally seen within if statements – can also be employed, using similar syntax, to assign values to variables. This is why I don’t think it’s fair to say that the ternary operator is just shorthand for if … else …, as it bears similarities to other bits of the language too. )

Sometimes the ternary operator can’t start the line

The only example I’ve come across so far is

return (cetacean.mass > 1000) ? 'whale' : 'dolphin';

Putting the return after the statement to be queried causes an error.

The ternary operator can be nested to emulate ‘else if’

First of all

if(statement1) {
  code1
} else if (statement2) {
  code2
} else if (statement3) {
  code3
} else {
  code4
}

Can be rewritten as

if(statement1) {
  code1
} else {
  if (statement2) {
    code2
  } else {
    if (statement3) {
      code3
    } else {
      code4
    }
  }
}

and so on for more statements.

But we know ifs can be rewritten using ternary, so it’s also equivalent to:

(statement1) ? code1: ((statement2) ?  code2 :( (statement3):?code3: code4));

which can unbelievably be rewritten on more lines as

(statement1) ? code1 :
(statement2) ? code2 :
(statement3):? code3 :
               code4 ;

So now you can construct very concise, relatively fast and, in my humble opinion, readable if … else …/switch statements. This is particularly valuable for defning  the value of a variable quickly, and based on a variety of conditions, eg:

var family = (cetacean.mass > 1000)             ? 'whale' :
             (cetacean.noseshape == 'cylinder') ? 'dolphin':
                                                  'porpoise';

Neat!

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.

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

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.

Where you headin’, luv?

Friday, August 21st, 2009

In previous posts I’ve covered the inherent difficulty of geocoding addresses and postcodes in the UK, specifically in order use the geocodes with Google maps. I learned a lot about the limitations of Google’s various geocoding services. To sum up the situation:

Previously I’d been geocoding large batches of addresses/postcodes, but having got the geocodes in order to plot points on the map, I wanted to add search functionality to the map, so that it would zoom in on a given address/postcode. I wanted it to be accurate for both addresses and postcodes, so using what I’d learned, I wrote a javascript function, geocodeUKAddress, which always returns the best geocode that Google can offer, so your website can be as reliable as a London cabbie (again, I can’t embed it here as javascript has a habit of breaking wordpress, though there must be some way to make it safe – I will research).

You will need to include the following in ther head of your webpage too

<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=your_api_key_here" type="text/javascript"></script>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>

I can’t take credit for the regular expression that recognises UK postcodes, but apart from that, it’s all my own work, which anyone can feel free to use. Unless you maybe work for Rupert Murdoch.