Script: Sorting top level projects alphabetically

Good shopping list : - )

JavaScript has a useful conditional operator

The best quick reference on JavaScript is the Mozilla documentation, and light will be shed on several of your questions by the page which describes JavaScript’s very useful conditional operator

condition ? expressionA : expressionB

which is similar to

if (condition) {
      statementA
} else {
      statementB
}

but has the advantage that it is itself an expression (i.e. it returns a useable value), rather than a statement which may do something useful, but doesn’t itself return a value that you can do anything useful with.

For example, the impression that blnDown is getting several different values arises, I think, from some expressions in that script which include the three-part Test ? ValueA : ValueB conditional operator. What is really happening there is that the value of blnDown is repeatedly being tested, in order to decide what the value of something else should be.

(blnDown doesn’t change after it is assigned at the very start – it just holds the user’s choice for the overall behaviour of the script – are we using this as a ‘move down’ script (blnDown = true) ? or as a ‘move up’ script (blnDown = false) ?

Experiment with .forEach(), and then with .map(), filter(), sort(), and finally with .reduce() and .reduceRight()

These are amongst the best things in JavaScript (built-in functions available for any array), they will save you from fussing with setting up loop variables, testing them and incrementing them – and will protect you from a lot of little bugs along the way. They may also give you new ideas for structuring your scripts a bit more solidly.

What they have in common is that they allow you to define a small function, which is then applied one by one to each item in a list/array, without your having to set up a loop and mess with iterator variables and their changing contents.

I would starting by experimenting in Script Editor with the examples in the relevant Mozilla pages:

When you only need the first match for a query

You asked about the lines:

	lstNow = oOutline.evaluateItemPath('//@' + strTag + '[0]');

	if (lstNow.length) {
		var oNow = lstNow[0],
        ...

Why restrict the harvest to the first item with + '[0]' when it would still work if we collected every match in lstNow ?

Well, we are only looking for one line (we want to know which line is tagged @now – if there are several we only want the first. We don’t need to know too much about what is going on ‘under the hood’ in the query system, but it seems reasonably prudent to guess that asking for a large harvest when we only need one item is possibly inefficient …

But as you suggest, the stakes are not high, and if there are unlikely to be many @now tags, you can drop it without having much to worry about : - )

I will pause there, because

  • making friends with the ‘ternary’ conditional operator, and
  • experimenting with applying functions to each array item with .forEach(), .map() etc gives you plenty to start with, and will probably change the focus of your questions :smile:

Though thinking about your question about this function:

      function chain(xs, f) {
        return [].concat.apply([], xs.map(f));
      }

perhaps worth adding this page to the list of things to experiment with:

( The short answer on the chain() function is that simply combining concat with map turns out to have all kinds of semi-magical applications and usefulnesses, but probably best to start by feeling completely at home with what each of them does on its own ).

Good luck !