Tap Forms JavaScript Scripting 102
Forms, Records, Fields, Values
by T. L. Ford

Section 7: Sorting

Suppose we want to sort the animal names in our report that listed them? If you are familiar with SQL, this section is how you are going to do the equivalent of an ORDER BY clause.

SQL
SELECT * FROM tbl ORDER BY fld;

In Tap Forms, we can sort arrays using JavaScript's array.sort() function. While there are several nuanced syntaxes for this that you can easily find if you search the Internet for "JavaScript array sort", we're going to focus on the following one, as it can apply to any array sort that you are likely to do in Tap Forms. If you already know JavaScript, use whatever you want.

ourArray.sort(function(a, b){
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  // a == b
  return 0;
});

This syntax is somewhat confusing at first glance because we are passing a comparison function to the .sort() function.

This is the sort method of the array object:

ourArray.sort(function(a, b){
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  // a == b
  return 0;
});

This is the comparison function:

ourArray.sort(function(a, b){
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  // a == b
  return 0;
}
);

The arbitrarily named parameters to the comparison function (a and b) will represent two elements in your array list, whatever those elements are - strings, numbers, field objects, record objects, etc.

ourArray.sort(function(a, b){
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  // a == b
  return 0;
});

If the comparison function returns -1, a will appear before b in the sorted array. If the function returns 1, a will appear after b in the sorted array. If the function returns 0, both elements will be next to each other in the sorted array.

ourArray.sort(function(a, b){
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  // a == b
  return 0;
});

Tip: To sort your array backwards (descending), just swap -1 and 1 on the return values.

Let's look at some simple examples.

Sorting simple numbers more efficiently.

// Ascending
numbersArray.sort((a, b) => a - b);  
// Descending
numbersArray.sort((a, b) => b - a);

This works because it returns positive, negative, or zero. This syntax is an inline function shorthand syntax. JavaScript shorthand is an art form - copy/paste and modify variable names until you want to read the mountain of documentation on different ways to do things and why certain things work.

For everything else, use the longer version (or just stick to the longer version).

Sorting strings.

Uppercase gets sorted before lowercase. 2

We can get around this by converting the strings to the same case using JavaScript's toLowerCase() string method.

It's not very consistent for uppercase or lowercase, so let's fix that by changing it so if the converted case is the same, sort by the original case.

But what if we want the lowercase versions first? Reverse the 1 and -1 for the return values for matching elements.

That's great for numbers and strings, but what if we want to sort record objects by a field's value? Remember that a and b represent any 2 elements of your array. This means that a and b can also be record objects.

Let's modify our animal names report to sort the names.

We add the sort function, get the animal names from our record fields, and run the report from the pulldown. It creates a report record and goes to it.

But suppose we want to name one of our animals 'Fluffy'? That could be a cat or a dog, so now we want to sort by animal kind and then the name.

Let's sort by animal kind and, if they are the same animal kind, by their name. While we're at it, let's rename some of our variables to more accurately reflect their data for easier debugging/reading later. We'll also have to update our report_string concatenation.

That looks good. Except... let's not repeat the "Cat:" and "Dog:" every row. Let's modify that logic a bit.

We run our new code and our report is now pretty!

Let's look at how that code works.

In SQL:
GROUP BY fld

This defines our report_string variable and sets its value to the string "All Animal Names Sorted\n".

This defines a variable current_kind and set its value to an empty string (that's what "" is called in programmer-speak). We're going to use this to decide if we need to add the animal kind header or not.

Here's our loop. The rescue_animals_records array is already sorted. You remember from Tap Forms JavaScript Scripting 101 or your other programming experience how a for loop works.

We get the animal kind (cat or dog) from the current record. The current record has "Cat" as the value in its Animal Kind field. If we wanted to verify this, we could use a console.log(animal_kind); to see it.

We get the animal name from the current record. We could do a console.log(animal_name); if we wanted to see which animal we were on.

Here's where our new logic starts to get interesting. We compare the current_kind, which is "", to the animal_kind of the current record, which is "Cat". These are not the same, so we are going to add a header for Cat.

But first, we're going to update our current_kind variable to this record's Animal Kind so we wont reprint a header until there's a different value for animal_kind. This sets our our current_kind variable to "Cat".

Here we add our header text to report_string.

We add the current record's Animal Name to our report_string variable and we loop.

The loop repeats, adding only the animal name, until the animal_kind variable value changes, and then it adds another header, this time "Dog", and the names of the dogs are added.

We could also split our data into Cats and Dogs with filters.

2 Uppercase gets sorted before lowercase because these are comparing binary values as if they were numbers. See the ASCII Chart; each letter has a corresponding number. A capital 'A' is 65. A lowercase 'a' is 97. 65 < 97, so 'A' is sorted before 'a'. Back to paragraph.

NEXT - Section 8: Filtering