As with most filter methods is various languages, the filter for a javascript array is expected to return true if you want to keep the value in the array and false if you want to filter it out. Usually, that means that the filter method takes some comparison function that outputs a boolean result e.g. (x) => x >= 3. But it doesn’t have to be a comparison function it just has to be something that returns a true value or a false value. JS like many languages is fairly lax in what it considers a true value or false value. false, 0, undefined, and "" are all examples of “falsy” values which means JS will consider them false if they are encountered where it expects a boolean. Any non-zero, non-empty value is then taken to be true. So if your filter function returned “cucumber” for an element in some array that element would be kept in the array because “cucumber” is a non-zero, non-empty value.
In your specific case, it was never clear to me exactly what the range of possible values for your exit delay items is. Again, I assume they are switches, but I don’t know, so I never bothered to address the filter expression. But, the filter expression in general does not have to take this form and, in fact, in this case this form is probably complete overkill. But, just so you understand, here’s what’s going on.
In JS {...} defines an object. You’re using all sorts of object all the time in these widgets even if your not aware of it. Really object just means "some data structure with sub-parts that you can access individually by some name (“key”). JS is very flexible and the value that key points to can be any type of data structure itself, including another object with it’s own keys.
For example, items is a special kind of object in these widgets which holds data about the states of OH items and each item name is a “key” that allows you to access the state and formatted state for that item. There are two syntax options for using a key to get a value from an object. If you know the exact key then you can just use the dot notation: items.some_item_name. But sometimes the key you need is dynamic or has to be constructed from some other values. In that case you use the bracket notation: items["some_item" + suffixVariable].
The first part of your expression, {'ON':1,'-':1}, you are defining an object. This object has two keys: ‘ON’ and ‘-’. The value of the ON key is 1 and the same is true for the - key. If this object had a name, say filterObj, then we could use either of the notation options to get these values: filterObj.ON would return 1. However, in the widget expression we cannot make named variables, but that doesn’t matter we can still access the object directly and ({'ON':1,'-':1}).ON will also return 1. Your expression uses the [...] notation instead, because the key you are testing is dynamic: the state of some item. That’s OK, because the state of an item can possible evaluate to ON. So if some_item has ON for a state then ({'ON':1,'-':1})[items.some_item.state] will also return the value of the ON key (1). 1 is a non-zero, non-empty value so the filter expression evaluates to true and that array element is kept in the filtered array.
But, what happens if you try to access a key that isn’t defined in the object e.g. ({'ON':1,'-':1}).Walrus? That is, of course, undefined. But that’s OK, because undefined is one of our falsy values, so if this is a filter expression it will know to filter that element out of the array.
So, in the end your expression has the 1’s in it because the call to the object just has to return some non-zero, non-empty value. They could just as easily be 10, or 'Abraham Lincoln' but 1 is a little more concise. As for the - key, well, the items object is special. There’s a bunch of underlying code that prevents it from returning undefined. If you request the state of an item that doesn’t currently have a meaningful state you will get - as a result instead of undefined. So, that is a possible return value that you may or may not want to account for if you are using this object notation as your fitler.
Again, in this case, all of that is probably much more than you need. If your items really are just switches than all you are interested is is if they are ON or not ON. So your expression really could just be:
filter: items[loop.exitDelayCount.name.slice (0,10) + "_Partition_In_Exit_Delay"].state == 'ON`
Oops. You’re absolutely right and I should have caught that. A zero length array result means the repeater iterates zero times. Fortunately that only changes things a little. All this means is that 1) instead of filtering the exit delay items in the initial repeater you move the filter down to the second exit delay repeater and 2) you need to do a little more in the partition block to the status of the exit delay array.
The modified outline might look like this:
f7-block #Basic root element
f7-block #Title container
Label #Title
oh-repeater (all-exit-delay-items) #Loop through each Exit delay and DO NOT filter out any elements
f7-block #Rolling current state of partitions: Only display if all-exit-delay-items index =0 and if all elements in all-exit-delay-items ='OFF'
oh-repeater #Loop through each partition
Label #Some info about partition
f7-block #Scrolling list of Exit Delays: Only display if all-exit-delay-items index =0 and if any elements in all-exit-delay-items ='ON'
oh-repeater (exit-delay-info) #Reuse the (all-exit-delay-items array) and filter the array
Label #Some info about exit delay
As for the new checking you’ll need to use the JS array methods some() and every(). Both of these array methods take a function parameter. They then pass each element of the array into the function. The every() method returns true only if the test function returns true for ALL the elements, and the some() method returns true if the test function is true for ANY ONE of the array elements. So the expression to represent the statement in the outline that says “if all elements in all-exit-delay-items =‘OFF’” would look like this:
loop.all-exit-delay-items_source.every( (x) => items[x.name].state == 'OFF')
and the complimentary test would be:
loop.all-exit-delay-items_source.some( (x) => items[x.name].state == 'ON')