FRjs/forms: Gene Dropdowns

The FRjs/forms module creates several extensions to the <select> tag/HTMLSelectElement class which let you place self-populating dropdowns in your HTML markup, or easily create them in Javascript.

For basic setup of the module, see FRjs/forms: Getting Started.

This tutorial covers how to use the Automatic Gene Dropdowns. (In the source code, this is the GeneSelect class.)

A dropdown of this type automatically populates itself with options representing Flight Rising's genes. By setting a few attributes, you can add constraints on which slot (primary/secondary/tertiary) and breed to display genes for. You can also link it to a BreedSelect to cause it to dynamically repopulate to reflect the currently chosen breed.

Basic Usage

After loading the FRjs/forms module, there are two methods for creating a gene dropdown.

In HTML

To create a <select> that uses this functionality in your HTML files, just add the attribute is="fr-genes" to the element:

<select is="fr-genes"></select>

In Javascript

To create a <select> that uses this functionality in a script:

  1. Create a select element with document.createElement() and set the is option to fr-genes.
  2. Use .setAttribute() to set any of the standard and custom attributes you need. Add any options you want to have in addition to the genes.
  3. Attach it to the document.
const geneDropdown = document.createElement("select", { is: "fr-genes" });
document.body.append(geneDropdown);

When working with any of these custom dropdowns in javascript, be aware that they'll only self-populate after two things have happened:

  1. The element is attached to the document.
  2. The FRjs/forms module has run.

If you need to access the self-populated options in your code, you must either wait until the DOMContentLoaded event has fired, or do so in a script which imports FRjs/forms.

Custom Attributes

In addition to all standard attributes available for <select> elements, gene dropdowns support the following custom attributes:

AttributeTypeValue If UnsetDescription
defaultstring"basic"Case insensitive. Specifies, by text content, which option should be the default selected option when creating the dropdown and when repopulating it. You can use the text content of any option here, including ones you add yourself.
slot"primary" or "secondary" or "tertiary""primary"Puts a slot constraint on this element; ie, will only contain options for either of primary, secondary, or tertiary genes.
breed-namestringnullCase insensitive. Puts a breed constraint on this element; ie, it will only contain genes available on the given breed.
breedstringnull

Specifies, by ID, a breed dropdown whose value will be used as a breed constraint; ie, it will only contain genes available on that breed dropdown's currently selected breed.

This attribute takes precedence over breed-name.

Linking to a Breed Dropdown

Like the Custom Attributes section mentioned, this element has the built-in ability to automatically repopulate itself based on what the currently selected option of a breed dropdown on the page is.

For example: If the linked breed dropdown has "Aether" as it's current selection, this element will only contain genes available on Aethers. If the user then selects "Nocturne" in the linked breed dropdown, this element will repopulate itself to only contain genes available on modern breeds.

To use this functionality, make sure the breed dropdown you wish to link to has a a unique id attribute, then set this gene dropdown's breed attribute to that id.

This works similarly to setting the for attribute on a <label> to the id of the form element it's labeling.

If you intend to create a gene dropdown that's linked to a breed dropdown, the easiest way is with HTML markup.

You can do it with a script instead, but you have to be more careful about the order of operations if you do. For best performance you should set the gene dropdown's attributes before attaching either element to the document, and attach the breed dropdown to the document before the linked gene dropdown.

Repopulation Behaviour

Gene dropdowns have the ability to automatically repopulate themselves when the constraints placed on them via their custom attributes change.

The following events will cause a gene dropdown to repopulate itself:

  • It gets attached to the document. (i.e. when being created in HTML, or appended with a script)
  • The slot attribute changes while it's attached to the document.
  • The breed attribute changes to indicate a breed dropdown which is attached to the document, while the gene dropdown is already attached to the document.
  • The breed-name attribute changes while it's attached to the document (provided the breed attribute is NOT set).
  • Its linked breed dropdown, which is currently attached to the document, fires a change event (provided the gene dropdown is already attached to the document).
  • Its linked breed dropdown, which was not yet attached to the document, gets attached to the document (provided the gene dropdown is already attached to the document).

In short, if something about it or relevant to it changes while it's on the page, it will generate new options.

For this reason, the simplest and most performant way to place constraints on a gene dropdown, including linking it to a breed dropdown, is to set its attributes in the HTML markup upfront.

If you're creating a gene dropdown with a script, for best performance you should set all the custom attributes you need before attaching it to the document, to avoid triggering multiple repopulate events.

If you're also creating its linked breed dropdown with a script, for best performance you should attach the breed dropdown to the document before any gene dropdowns linked to it; that way you trigger one repopulation event (gene dropdown attached) instead of two (gene dropdown attached, then breed dropdown attached).

This element marks its automatically generated options with the attribute data-auto="true". When it repopulates, it ONLY removes options that have that attribute. Options you added yourself will be preserved, but will moved to the top of the option list if they weren't there already.

Examples

HTML

Create a gene dropdown containing secondary genes for the Aether breed, whose default option is "Basic":

<select is="fr-genes" slot="secondary" breed-name="aether"></select>

Create a gene dropdown containing tertiary genes for all breeds, whose default option is "Pick a gene":

<select is="fr-genes" slot="tertiary" default="pick a gene">
    <option>Pick a gene</option>
</select>

Create a gene dropdown containing primary genes, whose default option is "Basic", which will match its contents to the current selection of a nearby breed dropdown:

<select is="fr-breeds" id="dragon-breed"></select>

<select is="fr-genes" slot="primary" breed="dragon-breed"></select>

Javascript

Create a breed dropdown with three linked gene dropdowns, one for each slot:

const breeds = document.createElement("select", { is: "fr-breeds" });
breeds.id = "breed-1";

const primary = document.createElement("select", { is: "fr-genes" });
primary.setAttribute("breed", breeds.id);

const secondary = document.createElement("select", { is: "fr-genes" });
secondary.setAttribute("breed", breeds.id);
secondary.setAttribute("slot", "secondary");

const tertiary = document.createElement("select", { is: "fr-genes" });
tertiary.setAttribute("breed", breeds.id);
tertiary.setAttribute("slot", "tertiary");

// When creating elements in scripts, you should attach breed dropdowns to the document
// BEFORE their linked gene dropdowns.
document.body.append(breeds, primary, secondary, tertiary);