States / DisplayStateManager

Arguably, DisplayStateManager is the state manager that will be most useful when you write components. It allows you to declare which elements are visible and which elements are hidden on the page based on the current state of the component those states are defined in. All display state declarations inside this.state array must be preceeded by the two elements - "display", { ...options }.

DisplayStateManager works slightly different - in principle - from StateActionManager. There are three main things to remember:

  1. All transitions are in transitions and the default action is to either show or hide the listed entities. show(), hide(), showPart() andhidePart() behaviors specific to your component (if they differ) or to children components are used to perform these transitions. If you don't specify it explicitly, the default in transition will be to show the listed entities.
  2. The out transition to any state is the opposite of the default in transition and it's applied to all entities that were not matched to the newly entered state. For instance, if the default in transition is to show entities then we simply hide all other entities except for the ones that are supposed to be shown for the current state.
  3. Any entity that's not listed at all is considered to be exempt from transitions and its visibility is defined by either stylesheets or in some other parts of the code unrelated to DisplayStateManager. In other words, if it's not listed, it's not DisplayStateManager's job to manage its visibility.

Entity is a term used here to refer to either component part or component child (another component) with a specific role. Both types of entities can be easily managed by DisplayStateManager. You list those entity names in the transition (second) element of the state declaration array:

this.states = [
  "display", {}, // <-- everything that follows after this line will be processed by DisplayStateManager
  [{ first_sign_in: true }, "accept_cookies,tos,tour_link"]
  //                        |--------------^--------------|
  //                                entities list
];

In this example, we assume user has an attribute called first_sign_in which is somehow set to true only when it's the first time user signs in. And we want to show this user a few things before they can proceed: first - the most annoyingly stupid "This website uses cookies" notification, second - we want to ask the user to agree to Terms Of Use by showing them an entity that contains the AGREE button. And, finally, we also want to show the user a link to the tour of the website features.

The entities listed - "accept_cookies", "tos", "tour_link" - can be either component parts or child components of our UserComponent instance. The only important thing here is that they are indeed contained inside UserComponent's dom element. That's what our html code may look like: Here's the cool part: we have two entities that are called tos - one of them is UserComponent's part and the other one is a child component with the role of the same name. Both of them are going to be displayed! However, if you only wanted to show the component part entity, but not the child component, you'd prepend entity name with a dot:

[{ first_sign_in: true }, "accept_cookies,.tos,tour_link"]

Similarly, if you wanted to show the child component with the role tos, but not the component part, you'd prepend the entity name with # like this:
[{ first_sign_in: true }, "accept_cookies,#tos,tour_link"]

Finally, as mentioned previously, Webface's state manager takes care of strings with commas in them and converts them to arrays, so the following two state declarations are identical:
[{ first_sign_in: true }, "accept_cookies,tos,tour_link"]
// is the same as
[{ first_sign_in: true }, ["accept_cookies", "tos", "tour_link"]]

Options

You can pass several options to DisplayStateManager that are unique to it:

  • default_state_action - can be either "show" or "hide". The default value is "show". This option defines what the in transition will be and, consequently, what the out transition is going to be too - for all of state declarations processed by DisplayStateManager (this was discussed in more detail above).
  • hide_animation_speed and show_animation_speed - default is 500 (ms) for both. DisplayStateManager would hide elements using the hide()/show()/hidePart()/showPart() behaviors with the animation length defined by these options and passed along to those behavior methods. If set to 0, then no animation is used.
Here's an example of passing options to DisplayStateManager:
this.states = [
  "display", { default_state_action: "hide", hide_animation_speed: 0, show_animation_speed: 200 },
  [{ first_sign_in: false }, "accept_cookies,tos,tour_link"]
];

Note that we set default_state_action to "hide", which means that by default every entity that's listed for any state is going to be displayed. That's why we purposefully changed the state declaration and said first_sign_in: false - because we WANT to hide "accept_cookies", "tos", "tour_link" entities if it's not the first time a user signs in. Also note that for hiding animation we chose the speed of 0, which means all entities that need to be hidden will be hidden instantly, by setting display: none;.

Additionally DisplayStateManager accepts pick_states_with_longest_definition_only and debug options which we'll discuss on the common options page.