If you'd want to make it more functional, let's first separate logic from effects (gathering user events and manipulating DOM). And then integrate them back.
Considering logic, it begins with some initial state:
// to make state checks more natural-language-like
const ON = true;
const OFF = false;
const initialState = {
firstGroup : ON,
secondGroup : OFF
}
Then we make function that takes previous state and "ACTIVATE_FIRST" or "ACTIVATE_SECOND" command to calculate the next state:
function processCommand (state, command) {
// in case there would be more than one command
switch (command) {
case "ACTIVATE_FIRST":
return {
firstGroup : ON,
secondGroup : OFF
}
case "ACTIVATE_SECOND":
return {
firstGroup : OFF,
secondGroup : ON
}
default:
throw new Error("Unknown command")
}
}
Then, given a stream of commands, starting with initialState
, apply reduce (in functional languages it is usually called left fold) RxJS operator to them - and you get stream of states. Conceptually it looks like this: commands -> process -> states
. It is your functional logic.
Then you need to connect logic with effects. First, using DOM selector subscribe to events from DOM elements and get two RxJS streams: first producing events that should yield "ACTIVATE_FIRST" command, and second for "ACTIVATE_SECOND". Then map these two streams to commands accordingly and merge into single stream of commands. It would be the left part of the stream chain or sources.
Then for the right part or sinks you should subscribe to a stream of states and finally write simple function that applies given state to DOM.
I don't give more details here, as it is the concept which is important, rather than details. Of course, for such a simple UX this seems like an overkill, but this approach scales great.
If you like it - have a look at CycleJS and Elm.