Google Maps need resizing after being “shown” with JavaScript/JQuery

If you have a Google Map on a page that, for example, starts off hidden and is shown using JavaScript (inc. JQuery or another library), it seems to only load the top left map tile. In order to fix this, you need to resize the map after showing it, using the following line:

google.maps.event.trigger(map, 'resize');    //map is your google.maps.Map object

This is mentioned in the resize event in the Map class documentation.

Javascript: array.indexOf() fix for IE8 and below

Just a quick note on how to deal with another one of the IE/Javascript deficiencies that make our lives so much easier(!) – IE from versions 8 backwards doesn’t support the indexOf() function for arrays, e.g.

var myArray = ['Apple','Banana','Orange'];
alert(myArray.indexOf('Orange'));  //alerts '2', but not in IE <=8

Thankfully, there are easy ways to fix this:

  1. the JQuery $.inArray() function, e.g.
    alert($.inArray('Orange',myArray);
  2. Defining the indexOf function (before you call it!) if it doesn’t exist – taken from MDN
    if (!Array.prototype.indexOf) {
      Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        'use strict';
        if (this == null) {
          throw new TypeError();
        }
        var n, k, t = Object(this),
            len = t.length >>> 0;
    
        if (len === 0) {
          return -1;
        }
        n = 0;
        if (arguments.length > 1) {
          n = Number(arguments[1]);
          if (n != n) { // shortcut for verifying if it's NaN
            n = 0;
          } else if (n != 0 && n != Infinity && n != -Infinity) {
            n = (n > 0 || -1) * Math.floor(Math.abs(n));
          }
        }
        if (n >= len) {
          return -1;
        }
        for (k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); k < len; k++) {
          if (k in t && t[k] === searchElement) {
            return k;
          }
        }
        return -1;
      };
    }

Stringify an Object in Javascript

I just Googled (other search engines are available) variations of “javascript convert object to JSON”, assuming that it would be something that is completely straightforward and easy to do, either with basic Javascript or using JQuery, which we have loaded in most of our applications anyway. It turns out basic Javascript can’t do it, and nor can JQuery (although Jquery does have the parseJSON function for parsing a JSON string – jQuery.parseJSON( json )). Thanfully, there is a simple way to do it, but it’s not quite as simple as I’d hoped, if you want to fully support all browsers.

The Simple Way (won’t work in IE7 or below))

JSON.stringify(yourObject);

All ‘modern’ browsers (see exactly which ones here: http://caniuse.com/json, but basically it’s everything except IE7 and below) natively support the JSON object, which allows you use JSON.stringify(object) to convert and object to a JSON string, and JSON.parse(string) to go back the other way. So if you’re not bothered about supporting old versions of IE, you can do it this way.

The marginally more complicated way (for full cross-browser compatibility)

json2.js (available here: https://github.com/douglascrockford/JSON-js) gives you the same stringify and parse functions as above, and is pretty small when minified. It seems to be the best option out there if you want to support the poor souls forced to (I really hoping no-one is choosing to) use IE7 or below.

Copying Arrays (and Objects) in Javascript

This is a bit of an amateur mistake, but I definitely wasn’t the first person to make it and I suspect I won’t be the last. I had a JavaScript array that I wanted to copy, then make some change to the copy, so that I could access the original and the modified copy. Therefore, being used to PHP, I did the following, assuming it would make a ‘proper’ copy of the original:

var original = [1,2,3];  //Define original array
var copy = original;     //Attempt to copy original
copy[2] = 4;             //Modify the copy
alert(original[2]);      //Hoped for 3, got 4

I’d created a reference to the original array, rather than a copy of it. As a result, updating the copy also updated the original.

So, how do I create a copy of an array, rather than a reference. Thankfully, the slice method makes this very easy:

var original = [1,2,3];        //Define original array
var copy = original.slice(0);  //Copy original using slice
copy[2] = 4;                   //Modify the copy
alert(original[2]);            //Got 3 this time

This works fine for simple, one-dimensional arrays, where the array contains only booleans, numbers or strings. If the array is multi-dimensional, i.e. it contains other arrays or objects, then only the top level array will be copied, the arrays/objects it contains will be referenced. Therefore, it is necessary to create a function to do this – this seems to be a good way to do: http://my.opera.com/GreyWyvern/blog/show.dml/1725165

Alternatively, use jQuery, and take advantage of the extend method:

var original = {team:"Arsenal"};               //Define original object
var copy = jQuery.extend(true, {}, original);  //Copy original using extend
copy.team = "Man Utd" ;                        //Modify the copy
alert(original.team);                          //Alerts Arsenal

Preventing IE from caching Ajax requests

We are increasingly using AJAX (Asynchronous JavaScript and XML) to deliver content on our pages, but often have problems due to Internet Explorer, every web developers favourite browser, caching AJAX requests. This means that the results presented are not updated when a new request is made to the same URL, even if the data has changed.

This is annoying, but does not go against the HTTP specification, which states that GET requests are cacheable, whereas POST results are not. AJAX requests seem to generally default to GET (JQuery certainly does), so IE caches them.

Therefore, the solution is to make sure that AJAX requests use POST rather than GET. In jQuery, you can do this by setting:

type: 'POST'

For Prototype, you can set:

method: 'get'

In the jQuery.ajax() method, there is also a ‘cache’ setting, which is true by default, but can be set to false, which prevents caching. It does this by appending a TIMESTAMP to the URL, so that each request is made to a different URL, so a cached result cannot be returned. If not using jQuery, an alternative to ensuring that your request is a POST request rather a GET request is to add a ‘cache-busting’ parameter, e.g. a timestamp, to the end of the request URL, e.g.:

var cacheBuster = new Date().getTime();  //Get timestamp
var url  = 'http://www.example.com/getdata?cb=' + cacheBuster;  //Add timestamp to URL