0

I'm working with some code I've adapted from and there's something I don't quite understand the best way to do. I'm trying to streamline a bit of code with different sorting functions that are applying sorts for specific values to an array of list items.

At the moment the function does a compare based on a specific factor and then returns the values to sort.

I want to pass two additional variables with this array/sort call but I can't seem to work out the way to write this. At the moment I'm doing it in a nasty way by having global variables on the window, but I'd rather pass the variables directly.

Based on the code below, any ways to tighten & clean it up would be appreciated:

arr = [];
sort_func = $j(this).children(':selected').val();

$j('li.collectionItem').each(function(){
    arr.push(this);
});

if (sort_func == "a_z")
{
      window.dataType = 'alpha';
      window.bigFirst = false;
      arr.sort(sort_products);
}
else if (sort_func == "z_a")
{
      window.dataType = 'alpha';
      window.bigFirst = true;
      arr.sort(sort_products);
}


// custom sort functions
function sort_products(a, b)
{
  dataType = window.dataType;
  bigFirst = window.bigFirst;

  var compA = $j(a).data(dataType);
  var compB = $j(b).data(dataType);

  if (bigFirst == true)
  {
    return (compA > compB) ? -1 : (compA < compB ) ? 1 : 0;
  }
  else
  {
    return (compA < compB) ? -1 : (compA > compB ) ? 1 : 0;
  }
}

2 Answers 2

1

You can wrap original sort_products in another function, like this:

function sort_products(dataType, bigFirst)
{
  return function (a, b)
  {
    var compA = $j(a).data(dataType);
    var compB = $j(b).data(dataType);

    if (bigFirst == true)
    {
      return (compA > compB) ? -1 : (compA < compB ) ? 1 : 0;
    }
    else
    {
      return (compA < compB) ? -1 : (compA > compB ) ? 1 : 0;
    }
  }
}

And then you can use it like this:

if (sort_func == "a_z")
{
  arr.sort(sort_products('alpha', false));
}
else if (sort_func == "z_a")
{
  arr.sort(sort_products('alpha', true));
}
Sign up to request clarification or add additional context in comments.

Comments

1

I don't know how many elements you have, but it'd speed things up if you'd avoid making those jQuery (assuming that's what $j is) calls inside the comparator function.

var arr = []; // You really need to declare your variables!
var sort_func = $j(this).children(':selected').val();
var sortInfo = {
  'a_z': {type: 'alpha', ascending: true},
  'z_a': {type: 'alpha', ascending: false},
  // ... whatever the other types are
}[sort_func];

$j('li.collectionItem').each(function(){
  arr.push({ elem: this, key: $j(this).data(sortInfo.type) });
});

arr.sort(function(a, b) {
  return (sortInfo.ascending ? 1 : -1) *
    a.key > b.key ? 1 : a.key < b.key ? -1 : 0;
});

// transform the array into an array of just the DOM nodes
for (var i = 0; i < arr.length; ++i)
  arr[i] = arr[i].elem;

2 Comments

Thanks mate, good stuff in here. Agreed on scoping variables. Out of interest is this a speed or compliance issue?
@LetterAfterZ well it's mostly performance. The comparison routine will be called a large number of times, so making it as cheap as possible makes a difference for larger lists.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.