Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS sort works in Firefox but not IE - can't work out why

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?

like image 944
Max Williams Avatar asked Jan 21 '23 23:01

Max Williams


1 Answers

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);
});
like image 54
Tim Down Avatar answered Feb 01 '23 11:02

Tim Down