Javascript functions

Some function may be useful to manipulate elements on the page.

Show-hide elements according to a form state

The module ShowHide will allow you to show/hide part of your page using a specific test.

This must be use inside a javascript module.

Usage

In this module, the module will listen to all input given in the container_from div, and will show or hide the content of the container_target according to the result of the test function.

<div id="container_from">
        {{ form_row(form.accompagnementRQTHDate) }}
</div>

<div id="container_target">
        {{ form_row(form.accompagnementComment) }}
</div>
import { ShowHide } from 'ShowHide/show_hide.js';

var
    from = document.getElementById("container_from"),
    target = document.getElementById("container_target")
    ;

new ShowHide({
    froms: [from], // the value of from should be an iterable
    container: [target], // the value of container should be an iterable
    test: function(froms, event) {
        // iterate over each element of froms
        for (let f of froms.values()) {
            // get all input inside froms
            for (let input of f.querySelectorAll('input').values()) {
                if (input.value === 'autre') {
                    return input.checked;
                }
            }
        }

        return false;
    }
});

Once instantiated, the class ShowHide will:

  1. get all input from each element inside the froms values
  2. attach an event listener (by default, change) to each input inside each entry in froms
  3. each time the event is fired, launch the function test
  4. show the element in the container given in container, if the result of test is true, or hide them otherwise.

The test is also launched when the page is loaded.

Show/hide while the user enter data: using the input event

One can force to use another event on the input elements, instead of the default 'change' event.

For achieving this, use the event_name option.

new ShowHide({
    froms: froms,
    test: test_function,
    container: containers ,
    // using this option, we use the event `input` instead of `change`
    event_name: 'input'
});

Examples

import { ShowHide } from "ShowHide/show_hide.js";

var div_accompagnement = document.getElementById("form_accompagnement"),
  div_accompagnement_comment = document.getElementById(
    "form_accompagnement_comment",
  ),
  div_caf_id = document.getElementById("cafId"),
  div_caf_inscription_date = document.getElementById("cafInscriptionDate");
// let show/hide the div_accompagnement_comment if the input with value `'autre'` is checked
new ShowHide({
  froms: [div_accompagnement],
  test: function (froms, event) {
    for (let el of froms.values()) {
      for (let input of el.querySelectorAll("input").values()) {
        if (input.value === "autre") {
          return input.checked;
        }
      }
    }

    return false;
  },
  container: [div_accompagnement_comment],
});

// let show the date input only if the the id is filled
new ShowHide({
  froms: [div_caf_id],
  test: function (froms, event) {
    for (let el of froms.values()) {
      return el.querySelector("input").value !== "";
    }
  },
  container: [div_caf_inscription_date],
  // using this option, we use the event `input` instead of `change`
  event_name: "input",
});

Using Show/Hide in collections forms

Using show / hide in collection forms implies:

  • to launch show/hide manually for each entry when the page is loaded ;
  • to catch when an entry is added to the form ;

As the show/hide is started manually and not on page load, we add the option load_event: null to the options:

new ShowHide({
  load_event: null,
  froms: [ from ],
  container: [ container ],
  test: my_test_function
});

Note

When using load_event: null inside the options, the value of event will be null as second argument for the test function.

my_test_function(froms, event) {
    // event will be null on first launch
}

Example usage: here, we would like to catch for element inside a CV form, where the user may add multiple formation entries.

import { ShowHide } from 'ShowHide/show_hide.js';

// we factorize the creation of show hide element in this function.
var make_show_hide = function(entry) {
    let
        obtained = entry.querySelector('[data-diploma-obtained]'),
        reconnue = entry.querySelector('[data-diploma-reconnue]')
    ;
    new ShowHide({
        load_event: null,
        froms: [ obtained ],
        container: [ reconnue ],
        test: my_test_function
    });
};

// this code is fired when an entry is added on the page
window.addEventListener('collection-add-entry', function(e) {
    // if the form contains multiple collection, we filter them here:
    if (e.detail.collection.dataset.collectionName === 'formations') {
        make_show_hide(e.detail.entry);
    }
});

// on page load, we create a show/hide
window.addEventListener('load', function(_e) {
    let
        formations = document.querySelectorAll('[data-formation-entry]')
        ;

    for (let f of formations.values()) {
        make_show_hide(f);
    }
});

Handling encapsulated show/hide elements

This module allow to handle encapsulated show/hide elements. For instance :

  • in a first checkbox list, a second checkbox list is shown if some element is checked ;
  • in this second checkbox list, a third input is shown if some element is checked inside the second checkbox list.

As a consequence, if the given element in the first checkbox list is unchecked, the third input must also be hidden.

Example: when a situation professionnelle is en activite, the second element type contrat must be shown if en_activite is checked. Inside type_contrat, type_contrat_aide should be shown when contrat_aide is checked.

<div id="situation_prof">
    <input type="radio" name="situationProfessionnelle" value="" checked="checked" />
    <input type="radio" name="situationProfessionnelle" value="sans_emploi" />
    <input type="radio" name="situationProfessionnelle" value="en_activite" />
</div>


<div id="type_contrat">
    <input type="checkbox" name="typeContrat[]" value="cdd" />
    <input type="checkbox" name="typeContrat[]" value="cdi" />
    <input type="checkbox" name="typeContrat[]" value="contrat_aide" />
</div>

<div id="type_contrat_aide">
    <input type="text" name="typeContratAide" />
</div>

The JS code will be:

import { ShowHide } from 'ShowHide/show_hide.js';
// we search for the element within the DOM
// NOTE: all the elements should be searched before instanciating the showHides.
// if not, the elements **may** have disappeared from the DOM

var
    situation_prof = document.getElementById('situation_prof'),
    type_contrat = document.getElementById('type_contrat'),
    type_contrat_aide = document.getElementById('type_contrat_aide'),
    ;

// the first show/hide will apply on situation_prof
new ShowHide({
    // the id will help us to keep a track of the element
    id: 'situation_prof_type_contrat',
    froms: [situation_prof],
    container: [type_contrat],
    test: function(froms) {
        for (let f of froms.values()) {
            for (let input of f.querySelectorAll('input').values()) {
                if (input.value === 'en_activite') {
                    return input.checked;
                }
            }
        }

        return false;
    }
});

// the show/hide will apply on "contrat aide"
var show_hide_contrat_aide = new ShowHide({
    froms: [type_contrat],
    container: [type_contrat_aide],
    test: function(froms) {
        for (let f of froms.values()) {
            for (let input of f.querySelectorAll('input').values()) {
                if (input.value === 'contrat_aide') {
                    return input.checked;
                }
            }
        }

        return false;
    }
});

// we handle here the case when the first show-hide is changed: the third input must also disappears
window.addEventListener('show-hide-hide', function (e) {
    if (e.detail.id = 'situation_prof_type_contrat') {
        // we force the 3rd element to disappears
        show_hide_contrat_aide.forceHide();
    }
});

// when the first show-hide is changed, it makes appears the second one.
// we check here that the second show-hide is processed.
window.addEventListener('show-hide-show', function (e) {
    if (e.detail.id = 'situation_prof_type_contrat') {
        show_hide_contrat_aide.forceCompute();
    }
});