Currently there is one pattern that is extremely repetitive in your code: "if (some condition), add this class". You could probably instead do something like this:
var classes = [
i < s && 'before',
i > s && 'after',
i === s && 'active',
i === s - 1 && 'previous',
i === s + 1 && 'next'
].filter(x => x)
The first part of that code, var classes = [...]
, creates an array that looks something like [false, false, 'active', false, false]
, by conditionally adding items. For example, suppose i
is 3 and s
is also 3. When JavaScript evaluates i === s && 'active'
, it sees that i (3) === s (3)
, so it moves on to the next value, which is 'active'
, and sticks that inside the array. When it evaluates i === s + 1 && 'next'
, it sees that i (3)
is not the same as s + 1 (4)
, so it immediately takes false and adds it to the list.
Then, we use filter
to get rid of those false
items, so we get an array more like ['active']
. Basically, filter takes a function and passes each in the array item one by one to it; when the function returns a truthy value, it keeps the item, and otherwise, it removes the item. The function we passed is an arrow function; it just returns the value that is passed to it. You could replace it with function(x) { return x }
and it would be functionally the same.
(I sometimes use .filter(Boolean)
instead of .filter(x => x)
. Boolean can be used as a function to convert a value into a boolean (according to the "truthy" link above) - if you've seen !!x
syntax before, it does the same thing. I find .filter(Boolean)
more syntactic: "keep items that are truthy (like a boolean)". But it's entirely unnecessary because filter
itself automatically checks if your function's returned value is truthy. So if you use it is just a matter of taste!)
Another option is to just get rid of the unnecessary braces and semicolons, like this:
if (i < s) classes.push('before')
if (i > s) classes.push('after')
// ..and so on.
It's certainly a bit more verbose, but you might prefer it anyways!