.. Copyright (C) 2016 Champs Libres Cooperative SCRLFS Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". 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. .. code-block:: html+twig
{{ form_row(form.accompagnementRQTHDate) }}
{{ form_row(form.accompagnementComment) }}
.. code-block:: javascript 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. .. code-block:: javascript new ShowHide({ froms: froms, test: test_function, container: containers , // using this option, we use the event `input` instead of `change` event_name: 'input' }); Examples -------- .. literalinclude:: js-functions/show_hide.js :language: javascript 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: .. code-block:: javascript 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. .. code-block:: javascript 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. .. code-block:: javascript 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. .. code-block:: html
The JS code will be: .. code-block:: javascript 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(); } });