4

I have a line in a javascript function that sort an array of objects based on the order of another array of strings. This is working in firefox but not in IE and i don't know why. Here's what my data looks like going into the sort call, in IE7. (I'm using an array of three items just to illustrate the point here).

//cherry first then the rest in alphabetical order
originalData = ['cherry','apple','banana','clementine','nectarine','plum']

//data before sorting - note how clementine is second item - we wan to to to be after apple and banana
csub = [
  {"value":"cherry","data":["cherry"],"result":"cherry"},
  {"value":"clementine","data":["clementine"],"result":"clementine"},
  {"value":"apple","data":["apple"],"result":"apple"},
  {"value":"banana","data":["banana"],"result":"banana"},
  {"value":"nectarine","data":["nectarine"],"result":"nectarine"},
  {"value":"plum","data":["plum"],"result":"plum"}
]

//after sorting, csub has been rearranged but still isn't right: clementine is before banana. in FF it's in the right place.
csubSorted = [
  {"value":"cherry","data":["cherry"],"result":"cherry"},
  {"value":"apple","data":["apple"],"result":"apple"},
  {"value":"clementine","data":["clementine"],"result":"clementine"},
  {"value":"banana","data":["banana"],"result":"banana"},
  {"value":"nectarine","data":["nectarine"],"result":"nectarine"},
  {"value":"plum","data":["plum"],"result":"plum"}
]

Here's the actual sort code:

 csubSorted = csub.sort(function(a,b){ return (originalData.indexOf(a.value) > originalData.indexOf(b.value)); });

Can anyone see why this wouldn't work? Is the basic javascript sort function not cross-browser compatible? Can i do this a different way (eg with jquery) that would be cross-browser?

grateful for any advice - max

EDIT - this also fails to work in safari and chrome - in other words, it only seems to work in firefox.

SOLVED - thanks to Tim Down. I'd actually made my code simpler because i realised that the order that i needed was always "the first item in the returned array followed by the rest of the array sorted using .value". So, i changed my code thus:

  first = csub.shift();
  csubSorted = csub.sort(function(a,b){ 
    return (a.value > b.value); 
  });
  csubSorted.unshift(first);

But, it still wasn't working. Then Tim (below) pointed out that sort expects to get a -1, 0 or 1 back from the function, NOT true or false which is what my code was returning. Obviously firefox lets you get away with this, but the other browsers don't. All that was required was to 'translate' true or false into 1 and -1 (i don't worry about the case where both strings are the samae, effectively that will get returned as -1 which wouldn't make any difference to the sort order anyway):

  first = csub.shift();
  csubSorted = csub.sort(function(a,b){ 
    return (a.value > b.value ? 1 : -1); 
  });
  csubSorted.unshift(first);

Tim also told me that array.indexOf() isn't supported in IE which is annoying as even though i'm not using it here any more i am using it in other bits of code. Goddamit. Is there an API page somewhere which definitively lists only the cross-browser compatible javscript API?

Max Williams
  • 32,435
  • 31
  • 130
  • 197
  • you can debug your code on IE by uncheck the disable debugging.search for debugging in IE. – Salil Jun 02 '10 at 09:39

1 Answers1

9

First, there's no indexOfmethod of Array in IE <= 8. You'll need to write your own. Second, the comparison function passed to the sort() method of an Array should return a number rather than a Boolean.

var indexOf = (typeof Array.prototype.indexOf == "function") ?
    function(arr, val) {
        return arr.indexOf(val);
    } :

    function(arr, val) {
        for (var i = 0, len = arr.length; i < len; ++i) {
            if (typeof arr[i] != "undefined" && arr[i] === val) {
                return i;
            }
        }
        return -1;
    };

csubSorted = csub.sort(function(a,b){
    return indexOf(originalData, a.value) - indexOf(originalData, b.value);
});
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • This post explains how to add it: http://stackoverflow.com/questions/1744310/how-to-fix-array-indexof-in-javascript-for-ie-browsers – Koen Jun 02 '10 at 09:44
  • I provided my own simple version of `indexOf` that doesn't fully satisfy the spec but does the job here, and doesn't augment `Array.prototype`. – Tim Down Jun 02 '10 at 09:49
  • 5
    ahh - it was this "Second, the comparison function passed to the sort() method of an Array should return a number rather than a Boolean." that was screwing me up. I actually made my code simpler so i didn't need to do indexOf any more, but it still wasn't working. See original description for details. – Max Williams Jun 02 '10 at 10:17
  • 1
    Good spot on the Number vs Boolean for the sort function. +1 – ricosrealm Jul 01 '13 at 16:17