Component: Form Inset

Implementation Notes

Validation is based on Parsley.js

Notes

  • The form must have the class formValidator.
  • The timing of validation is controlled by the data-parsley-trigger attribute.
    • The timing should be set globally in the form tag.
    • For fields that deviate from the global rule, the value can be overwritten.
    • Fields with a fixed format (e.g. email addresses) should not be validated on input, as they would otherwise display an error immediately upon entry.
  • The desired file format can be determined via the data-parsley-file-types attribute. The value must be a comma-separated list of file types (e.g. image/jpeg, image/png).
  • The maximum file size can be determined via the data-parsley-max-file-size attribute. The value must be specified in kilobytes without a unit (e.g. 1024).

Troubleshooting

  • Radio button groups are only validated if the associated options have values (that are not empty).

Known Issues

Internet Explorer

There are problems with input fields of type “Date” in Internet Explorer (all versions) and Parsley.js, as Internet Explorer ignores the local format. The value of the field in IE always has the pattern “YYYY-MM-DD”, but Parsley expects, for example, “DD.MM.YYYY” in German and marks the field as erroneous.

This incompatibility is solved via a script that converts all fields of type “Date” to fields of type “Text” in Internet Explorer and tells Parsley via the data-parsley-pattern attribute to test it like a date (in the German notation).

<div class="formInset">

    <h2 class="formInset-title">Form title</h2>

    <div class="formInset-description">
        <p>Cardigan Pinterest gentrify, biodiesel locavore Echo Park bespoke tattooed mlkshk. Master cleanse actually XOXO Schlitz. Four loko disrupt jean shorts meh, normcore vegan tilde vinyl small batch organic Marfa migas Austin Schlitz. Bitters sartorial gastropub, hashtag four loko skateboard chillwave deep.</p>

    </div>

    <form class="formInset-form" method="POST" action="./" accept-charset="UTF-8">

        <fieldset class="formFieldset">

            <legend class="formFieldset-legend">Ich bin ein Abschnitt</legend>

            <div class="formFieldset-fields">
                <div class="formFieldset-field">
                    <div class="formField">

                        <label class="label is-optional" for="field-id">Bezeichnung</label>

                        <span class="formField-field">
                            <input class="field" type="text" id="field-id" name="fieldname" placeholder="" spellcheck="false" />

                        </span>

                        <div class="formMessage js-formValidator-message">
                            Ich bin ein Hinweis.
                        </div>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formSelect">

                        <label class="label is-optional" for="field-select">Auswahlliste</label>

                        <span class="formSelect-input">
                            <span class="select">

                                <select id="field-select">
                                    <option value="" disabled="disabled" selected="selected">Please select</option>
                                    <hr />
                                    <option value="-1">
                                        Show all
                                    </option>
                                    <hr />
                                    <option value="1">
                                        Option 1
                                    </option>
                                    <option value="2">
                                        Option 2
                                    </option>
                                    <option value="3">
                                        Option 3
                                    </option>
                                    <option value="4" disabled="disabled">
                                        Unavailable option
                                    </option>
                                </select>

                            </span>

                        </span>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formTextarea is-optional">

                        <label class="label is-optional" for="field-uniqueID-textarea">Textfeld</label>

                        <textarea class="formTextarea-field" id="field-uniqueID-textarea" name="textarea" placeholder="Aufforderung Nachricht zu schreiben"></textarea>

                        <div class="formMessage js-formValidator-message">
                            Ich bin ein Hinweis.
                        </div>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <fieldset class="formToggleSet is-optional">

                        <legend class="formToggleSet-label">Gruppe mit Optionen</legend>

                        <div class="formToggleSet-options">
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Cardigan</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Raw Denim</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Flexitarian</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Letterpress & Mustache</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Gatekeep</span></label>

                                </div>
                            </div>
                        </div>

                        <div class="formMessage js-formValidator-message">
                            Wählen Sie mindestens eine Option aus.
                        </div>

                    </fieldset>

                </div>
                <div class="formFieldset-field">
                    <div class="formToggle is-checkbox is-required is-small">

                        <label class="formToggle-label is-required is-small"><span class="toggle is-checkbox is-small">
                                <input class="toggle-input" role="switch" type="checkbox" name="toggle" value="" required="" data-parsley-trigger="change" /><span class="toggle-marker"></span>
                            </span>
                            <span>Ich habe die <a href="#">Datenschutzhinweise</a>, die <a href="#">Teilnahmebedingungen</a> und die <a href="#">allgemeinen Geschäftsbedingungen</a> gelesen und akzeptiere sie.</span></label>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formFieldset-note">
                        <strong class="label">Datenschutz</strong>
                        <small>Die Datenverarbeitung erfolgt wie in der <a href="#" target="_blank">Datenschutzerklärung für die Website</a> beschrieben.</small>
                    </div>
                </div>

            </div>

        </fieldset>

        <fieldset class="formFieldset">

            <legend class="formFieldset-legend">Ich bin ein Abschnitt</legend>

            <div class="formFieldset-fields">
                <div class="formFieldset-field">
                    <div class="formField">

                        <label class="label is-optional" for="field-id">Bezeichnung</label>

                        <span class="formField-field">
                            <input class="field" type="text" id="field-id" name="fieldname" placeholder="" spellcheck="false" />

                        </span>

                        <div class="formMessage js-formValidator-message">
                            Ich bin ein Hinweis.
                        </div>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formSelect">

                        <label class="label is-optional" for="field-select">Auswahlliste</label>

                        <span class="formSelect-input">
                            <span class="select">

                                <select id="field-select">
                                    <option value="" disabled="disabled" selected="selected">Please select</option>
                                    <hr />
                                    <option value="-1">
                                        Show all
                                    </option>
                                    <hr />
                                    <option value="1">
                                        Option 1
                                    </option>
                                    <option value="2">
                                        Option 2
                                    </option>
                                    <option value="3">
                                        Option 3
                                    </option>
                                    <option value="4" disabled="disabled">
                                        Unavailable option
                                    </option>
                                </select>

                            </span>

                        </span>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formTextarea is-optional">

                        <label class="label is-optional" for="field-uniqueID-textarea">Textfeld</label>

                        <textarea class="formTextarea-field" id="field-uniqueID-textarea" name="textarea" placeholder="Aufforderung Nachricht zu schreiben"></textarea>

                        <div class="formMessage js-formValidator-message">
                            Ich bin ein Hinweis.
                        </div>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <fieldset class="formToggleSet is-optional">

                        <legend class="formToggleSet-label">Gruppe mit Optionen</legend>

                        <div class="formToggleSet-options">
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Cardigan</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Raw Denim</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Flexitarian</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Letterpress & Mustache</span></label>

                                </div>
                            </div>
                            <div class="formToggleSet-option">
                                <div class="formToggle is-checkbox is-optional">

                                    <label class="formToggle-label is-optional"><span class="toggle is-checkbox">
                                            <input class="toggle-input" role="switch" type="checkbox" name="checkbox-group[]" value="" /><span class="toggle-marker"></span>
                                        </span>
                                        <span>Gatekeep</span></label>

                                </div>
                            </div>
                        </div>

                        <div class="formMessage js-formValidator-message">
                            Wählen Sie mindestens eine Option aus.
                        </div>

                    </fieldset>

                </div>
                <div class="formFieldset-field">
                    <div class="formToggle is-checkbox is-required is-small">

                        <label class="formToggle-label is-required is-small"><span class="toggle is-checkbox is-small">
                                <input class="toggle-input" role="switch" type="checkbox" name="toggle" value="" required="" data-parsley-trigger="change" /><span class="toggle-marker"></span>
                            </span>
                            <span>Ich habe die <a href="#">Datenschutzhinweise</a>, die <a href="#">Teilnahmebedingungen</a> und die <a href="#">allgemeinen Geschäftsbedingungen</a> gelesen und akzeptiere sie.</span></label>

                    </div>

                </div>
                <div class="formFieldset-field">
                    <div class="formFieldset-note">
                        <strong class="label">Datenschutz</strong>
                        <small>Die Datenverarbeitung erfolgt wie in der <a href="#" target="_blank">Datenschutzerklärung für die Website</a> beschrieben.</small>
                    </div>
                </div>

            </div>

        </fieldset>

        <div class="buttonGroup">

            <button class="button is-secondary"><span class="button-label">Back</span></button>

            <button class="button" type="submit"><span class="button-label">Send</span></button>

        </div>

    </form>

</div>
<div class="formInset{{#modifier}} {{.}}{{/modifier}}">

        {{#title}}
    <h2 class="formInset-title">{{{.}}}</h2>
        {{/title}}

        {{#if description}}
    <div class="formInset-description"{{#theme}} data-theme="{{.}}"{{/theme}}>
        {{{description}}}
        {{#figure}}
            {{render '@figure' (contextData '@forminset' this) merge=true}}
        {{/figure}}
        {{#documentmockup}}
            {{render '@documentmockup' (contextData '@forminset' this) merge=true}}
        {{/documentmockup}}
    </div>
        {{/if}}

    <form class="formInset-form{{#if validate}} formValidator{{/if}}" method="{{#method}}{{.}}{{/method}}{{^method}}POST{{/method}}" action="{{#action}}{{.}}{{/action}}{{^action}}./{{/action}}" accept-charset="UTF-8" {{#if validate}} data-parsley-validate data-parsley-trigger="input focusout"{{/if}}>

        {{#formfield}}
            <!-- Only for demonstration non-compliant markup -->
            {{render '@formfield' (contextData '@forminset' this) merge=false}}
        {{/formfield}}
        {{#formhidden}}
        <div>
            <!-- Only for demonstration non-compliant markup -->
            {{render '@formhidden' (contextData '@forminset' this) merge=false}}
        </div>
        {{/formhidden}}

        {{#formfieldsets}}
            {{render '@formfieldset' (contextData '@forminset' this) merge=false}}
        {{/formfieldsets}}

        {{#buttongroup}}
            {{render '@buttongroup' (contextData '@forminset' this) merge=false}}
        {{/buttongroup}}

    </form>

</div>
{
  "title": "Form title",
  "description": "<p>Cardigan Pinterest gentrify, biodiesel locavore Echo Park bespoke tattooed mlkshk. Master cleanse actually XOXO Schlitz. Four loko disrupt jean shorts meh, normcore vegan tilde vinyl small batch organic Marfa migas Austin Schlitz. Bitters sartorial gastropub, hashtag four loko skateboard chillwave deep.</p>\n",
  "formfieldsets": [
    {
      "legend": "Ich bin ein Abschnitt",
      "fields": [
        {
          "formfield": {
            "id": "id",
            "name": "fieldname",
            "label": "Bezeichnung",
            "placeholder": "Beispiel für Inhalt",
            "message": {
              "content": "Ich bin ein Hinweis."
            }
          }
        },
        {
          "formselect": {
            "id": "select",
            "label": "Auswahlliste",
            "placeholder": "Please select",
            "options": [
              {
                "label": null
              },
              {
                "label": "Show all",
                "value": -1
              },
              {
                "label": null
              },
              {
                "label": "Option 1",
                "value": 1
              },
              {
                "label": "Option 2",
                "value": 2
              },
              {
                "label": "Option 3",
                "value": 3
              },
              {
                "label": "Unavailable option",
                "value": 4,
                "is-disabled": true
              }
            ]
          }
        },
        {
          "formtextarea": {
            "id": "uniqueID-textarea",
            "name": "textarea",
            "label": "Textfeld",
            "placeholder": "Aufforderung Nachricht zu schreiben",
            "message": {
              "content": "Ich bin ein Hinweis."
            }
          }
        },
        {
          "formtoggleset": {
            "type": "checkbox-group",
            "label": "Gruppe mit Optionen",
            "message": {
              "content": "Wählen Sie mindestens eine Option aus."
            },
            "options": [
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Cardigan"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Raw Denim"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Flexitarian"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Letterpress & Mustache"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Gatekeep"
              }
            ]
          }
        },
        {
          "formtoggle": {
            "type": "checkbox",
            "id": "toggle",
            "name": "toggle",
            "label": "Ich habe die <a href=\"#\">Datenschutzhinweise</a>, die <a href=\"#\">Teilnahmebedingungen</a> und die <a href=\"#\">allgemeinen Geschäftsbedingungen</a> gelesen und akzeptiere sie.",
            "is-required": true,
            "modifier": "is-small"
          }
        },
        {
          "formnote": {
            "label": "Datenschutz",
            "content": "<small>Die Datenverarbeitung erfolgt wie in der <a href=\"#\" target=\"_blank\">Datenschutzerklärung für die Website</a> beschrieben.</small>"
          }
        }
      ],
      "buttongroup": null
    },
    {
      "legend": "Ich bin ein Abschnitt",
      "fields": [
        {
          "formfield": {
            "id": "id",
            "name": "fieldname",
            "label": "Bezeichnung",
            "placeholder": "Beispiel für Inhalt",
            "message": {
              "content": "Ich bin ein Hinweis."
            }
          }
        },
        {
          "formselect": {
            "id": "select",
            "label": "Auswahlliste",
            "placeholder": "Please select",
            "options": [
              {
                "label": null
              },
              {
                "label": "Show all",
                "value": -1
              },
              {
                "label": null
              },
              {
                "label": "Option 1",
                "value": 1
              },
              {
                "label": "Option 2",
                "value": 2
              },
              {
                "label": "Option 3",
                "value": 3
              },
              {
                "label": "Unavailable option",
                "value": 4,
                "is-disabled": true
              }
            ]
          }
        },
        {
          "formtextarea": {
            "id": "uniqueID-textarea",
            "name": "textarea",
            "label": "Textfeld",
            "placeholder": "Aufforderung Nachricht zu schreiben",
            "message": {
              "content": "Ich bin ein Hinweis."
            }
          }
        },
        {
          "formtoggleset": {
            "type": "checkbox-group",
            "label": "Gruppe mit Optionen",
            "message": {
              "content": "Wählen Sie mindestens eine Option aus."
            },
            "options": [
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Cardigan"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Raw Denim"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Flexitarian"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Letterpress & Mustache"
              },
              {
                "type": "checkbox",
                "name": "checkbox-group[]",
                "label": "Gatekeep"
              }
            ]
          }
        },
        {
          "formtoggle": {
            "type": "checkbox",
            "id": "toggle",
            "name": "toggle",
            "label": "Ich habe die <a href=\"#\">Datenschutzhinweise</a>, die <a href=\"#\">Teilnahmebedingungen</a> und die <a href=\"#\">allgemeinen Geschäftsbedingungen</a> gelesen und akzeptiere sie.",
            "is-required": true,
            "modifier": "is-small"
          }
        },
        {
          "formnote": {
            "label": "Datenschutz",
            "content": "<small>Die Datenverarbeitung erfolgt wie in der <a href=\"#\" target=\"_blank\">Datenschutzerklärung für die Website</a> beschrieben.</small>"
          }
        }
      ],
      "notes": null,
      "buttongroup": null
    }
  ],
  "buttongroup": {
    "buttons": [
      {
        "label": "Back",
        "modifier": "is-secondary"
      },
      {
        "type": "submit",
        "label": "Send"
      }
    ]
  }
}
  • Content:
    import formValidator from "./_formInset.script";
    
    function addBusinessEmailValidator() {
    
        function init(data) {
            /*
            * data {object}: Contains an array "list" with the blacklisted domains.
            *   If the top level domain is an asterisk, all possible top levels are filtered.
            *   {
            *     list: [
            *         "gmx.de",
            *         "gmail.*"
            *     ]
            *   }
            */
    
            if (typeof data !== "object" || typeof data.list !== "object" || ! data.list.length) {
                console.warn("formInset: No definition for business email is found.")
            }
    
            const domainsBlacklist = data.list;
    
            window.Parsley.addValidator('businessEmail', {
                validateString: function(value) {
    
                    const emailChunks = value.split('@');
    
                    if (emailChunks.length < 2) {
                        return true;
                    }
    
                    const domain = emailChunks[1].toLowerCase();
    
                    if (domain === "") {
                        return true;
                    }
    
                    const domainWithoutTopLevel = domain.replace(/\.[^.]+$/, ".*");
    
                    return ! domainsBlacklist.includes(domain) && ! domainsBlacklist.includes(domainWithoutTopLevel);
    
                },
                messages: {
                    en: 'Only business email addresses are accepted.',
                    de: 'Es werden nur geschäftliche E-Mail-Adressen akzeptiert.',
                    pl: 'Akceptujemy tylko firmowe adresy e-mail.',
                },
            });
    
        }
    
        fetch('/domainsBlacklist.json')
        .then(response => response.json())
        .then(data => {
            init(data);
        })
        .catch(error => console.error('formInset: Can’t load JSON with definitions for business email.', error));
    
    }
    
    
    /**
     * Telephone number validator for Parsley.js
     *
     * Regex: /^(\+?\d{2,4}\s?)?[\d\s]{8,20}$/
     * Accepts: +49 894238438290, 0049 980502389, 04584 539894385, 894238438290
     */
    
    window.Parsley.addValidator('telephone', {
    
        validateString: function (value, requirement, instance) {
            // Empty field is allowed (optional)
            if (!value || value.trim() === '') {
                return true;
            }
    
            // Regex: /^(\+?\d{2,4}\s?)?[\d\s]{8,20}$/
            // Accepts: +49 894238438290, 0049 980502389, 04584 539894385, 894238438290
            const phoneRegex = /^(\+?\d{2,4}\s?)?[\d\s]{8,20}$/,
                  isValid = phoneRegex.test(value.trim());
    
            return isValid;
        },
    
    });
    
    
    /**
     * Automatically attach telephone validation to all input[type="tel"]
     */
    
    function addTelephoneValidation() {
    
        const telInputs = document.querySelectorAll('input[type="tel"]');
    
        telInputs.forEach( input => {
            input.setAttribute('data-parsley-telephone', 'true');
            input.setAttribute('data-parsley-trigger', 'input focusout');
            input.setAttribute('data-parsley-validation-threshold', '8');
        });
    
    }
    
    /**
     * Init
     */
    
    addTelephoneValidation();
    addBusinessEmailValidator();
    
    formValidator.init({
        lang: "en",
    });
    
  • URL: /components/raw/forminset/_formInset.js
  • Filesystem Path: components/04-modules/formInset/_formInset.js
  • Size: 3 KB
  • Content:
    export default (function (){
    
        var defaults = {
    
            lang: "de",
    
            selectors: {
                forms: "form[data-parsley-validate]",
                fieldContainer: '*[data-validate="true"]',
            },
    
            submit: {
                selector: "",
                disable: true,
            },
    
        };
    
        var init = function(options){
    
            var forms = $(defaults.selectors.forms);
    
            if (forms.length === 0){
                return;
            }
    
            const settings = Object.assign({}, defaults, options);
    
            addValidators();
    
            fixIEDateInput();
    
            forms.each(function(){
                new Validator(this, settings);
            });
    
        };
    
        var Validator = function(form, settings){
    
            var self = this;
    
            this.settings = $.extend(true, {}, settings);
    
            this.form = $(form);
            this.submit = $('button[type="submit"]', this.form);
    
            if (! $.isFunction($.fn.parsley)){
                return;
            }
    
            this.form.parsley({
                excluded: "input[type=button], input[type=submit], input[type=reset], input[type=hidden], [disabled]",
                errorClass: "",
                successClass: "",
                errorsWrapper: '<ul class="parsley-errors-list"></ul>',
                errorsContainer: function (field) { return getContainer(field) },
                lang: this.settings.lang,
            }).on("field:validated", function(formField){
    
                self.updateStatus(self.form.parsley().isValid());
    
            }).on("field:success", function(formField){
    
                self.setSuccessStatus(formField);
    
            }).on("field:error", function(formField){
    
                self.setSuccessStatus(formField, false);
    
            });
    
                // Set language
    
            if ( $("html").attr("lang") ){
    
                var locale = $("html").attr("lang") || defaults.lang;
    
                var matches = locale.match(/^[a-zA-Z]{2}/),
                    lang = matches[0] || this.settings.lang;
    
                try {
                    window.Parsley.setLocale(lang);
                } catch (e) {
                    console.log("formValidator: The set language is not available.");
                }
    
            }
    
            this.updateStatus(false);
    
        };
    
        function getContainer(field){
    
            var element = field.$element;
    
            if (! element.hasClass(defaults.selectors.fieldContainer)){
                return element.closest(defaults.selectors.fieldContainer);
            }
    
            return;
    
        }
    
        Validator.prototype.updateStatus = function(status){
    
            this.form[0].dataset.valid = status;
    
        }
    
        Validator.prototype.getParent = function(element){
    
            return element.parents(this.settings.selectors.fieldContainer);
    
        }
    
        Validator.prototype.setSuccessStatus = function(formField, valid){
    
            if (typeof valid !== "boolean") {
                valid = true;
            }
    
            formField.$element.attr("aria-invalid", ! valid);
    
            const parent = formField.$element.parents(this.settings.selectors.fieldContainer);
    
            parent.attr("data-invalid", ! valid);
    
            const siblings = formField.$element.siblings();
    
            siblings.attr("data-invalid", ! valid);
    
        }
    
        Validator.prototype.updateUI = function(refresh) {
        };
    
        Validator.prototype.validate = function(refresh) {
    
            this.form.parsley().validate();
    
            return this.form.parsley().isValid();
    
        };
    
        Validator.prototype.submit = function(callback){
    
            var callback = (typeof callback === "function") ? callback : function(){};
    
            if (! $.isFunction($.fn.parsley)){
                callback();
                return true;
            }
    
            var isValid = this.validate();
    
            if (isValid){
                callback();
            }
    
            return isValid;
    
        };
    
        var addValidators = function(){
    
            window.Parsley.addValidator('maxFileSize', {
    
                validateString: function(_value, maxSize, parsleyInstance) {
    
                    if (! window.FormData) {
                        return true;
                    }
    
                    var files = parsleyInstance.$element[0].files;
    
                    return files.length != 1 || files[0].size <= maxSize * 1024;
    
                },
    
                requirementType: 'integer',
    
                messages: {
                    en: 'This file should not be larger than %s Kb.',
                    de: 'Die Datei darf nicht größer als %s KB sein.',
                }
    
            });
    
            window.Parsley.addValidator('fileTypes', {
    
                validateString: function(_value, types, parsleyInstance) {
    
                    if (! window.FormData || ! types) {
                        return true;
                    }
    
                    var types = types.split(/, ?/);
    
                    var files = parsleyInstance.$element[0].files;
    
                    return files.length != 1 || types.indexOf(files[0].type) !== -1;
    
                },
    
                requirementType: 'string',
    
                messages: {
                    en: 'This file is not the right type.',
                    de: 'Die Datei ist vom falschen Typ.',
                }
    
            });
    
        };
    
        var fixIEDateInput = function(input){
    
            function getInternetExplorerVersion(){
    
                var rV = -1; // Return value assumes failure.
    
                if (navigator.appName == 'Microsoft Internet Explorer' || navigator.appName == 'Netscape') {
                    var uA = navigator.userAgent;
                    var rE = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    
                    if (rE.exec(uA) != null) {
                        rV = parseFloat(RegExp.$1);
                    }
                    else if (!!navigator.userAgent.match(/Trident.*rv\:11\./)) {
                        rV = 11;
                    }
                }
    
                return rV;
    
            }
    
            if (getInternetExplorerVersion() === -1){
                return;
            }
    
            $('input[type="date"]').each(function(){
    
                var input = $(this);
    
                    // Please regard: Pattern does not check if date exists,
                    //   so eg. `31.02.2000` will be valid
    
                var pattern = "([0-2][1-9]|3[0-1])\\.(0[1-9]|1[0-2])\\.(19|20)\\d{2}";
    
                input.attr("type", "text")
                     .attr("data-parsley-pattern", pattern)
                     .attr("data-parsley-validation-threshold", "10");
    
            });
    
        }
    
        return {
            init: init
        };
    
    })();
    
  • URL: /components/raw/forminset/_formInset.script.js
  • Filesystem Path: components/04-modules/formInset/_formInset.script.js
  • Size: 6.3 KB
  • Content:
    @import "_formInset.settings";
    @import "_formInset.styles";
    
    %formInset {
        .fileCard {
            background-color: $_page-color;
        }
    
        .buttonGroup {
           @include stack-spacing(large);
        }
    
        &-title + &-description {
            @include stack-spacing(component);
            text-align: center;
        }
    
        &-description {
    
            > .figure {
                @include stack-spacing(large);
            }
    
        }
    
        .documentMockup {
            @include stack-spacing(large);
            background-color: $_BACKDROP-COLOR;
        }
    
        &-form {
            box-shadow: none;
    
            .buttonGroup {
                @include stack-spacing(component);
            }
    
        }
    
        &-title ~ &-form > .buttonGroup {
            justify-content: center;
        }
    
        @include only-on-desktop(){
            width: get-columns-width(8);
            margin-left: auto;
            margin-right: auto;
        }
    
    }
    
    %formInset--side-by-side {
        width: 100%;
    
        .buttonGroup {
            justify-content: flex-start;
        }
    
        %formInset-description {
            text-align: left !important;
        }
    
        %formInset-description[data-theme] {
            padding: var(--bp);
        }
    
        @include only-on-desktop(){
            display: grid;
            column-gap: var(--gg);
            row-gap: var(--sp-component);
            grid-template-columns: 1fr 1fr;
    
            .formFieldset {
                @include stack-spacing(0);
            }
    
            .formFieldset + .formFieldset {
                padding-top: 0;
            }
    
            %formInset-title {
                grid-column: 1 / span 2;
            }
    
            %formInset-description {
                @include stack-spacing(0);
                grid-column: 1 / span 1;
            }
    
            %formInset-form {
                @include stack-spacing(0);
                grid-column: 2 / span 1;
                height: 100%;
                border-radius: 0 var(--br) var(--br) 0;
    
                padding: var(--bp);
    
                background-color: $card_background-color;
    
                display: flex;
                flex-direction: column;
    
                .formFieldset {
                    padding: 0;
                }
    
                .formFieldset:only-child {
                    height: 100%;
                }
    
                > *:last-child:not(:only-child),
                .formFieldset > .buttonGroup:last-child {
                    flex-grow: 1;
                    align-items: flex-end;
                }
    
                > .buttonGroup {
                    @include stack-spacing(0);
                    padding: $formFieldset_stack-spacing 0 0;
                }
    
            }
    
            %formInset-description[data-theme] {
                padding: var(--bp-large);
                margin-right: calc(-.5 * var(--gg));
    
                border-top-left-radius: var(--br);
                border-bottom-left-radius: var(--br);
            }
    
            %formInset-description[data-theme] + %formInset-form {
                margin-left: calc(-.5 * var(--gg));
                padding: var(--bp-large);
    
                .formFieldset + .buttonGroup {
                    padding-top: $formFieldset_stack-spacing;
                }
    
            }
    
        }
    
    }
    
    .formInset.is-side-by-side {
        @extend %formInset--side-by-side;
    }
    
    // Highlighting non-compliant markup
    .formInset-form:has(> *[class^="form"]:not(.formFieldset)) {
        @extend %_not-compliant;
    }
    
  • URL: /components/raw/forminset/_formInset.scss
  • Filesystem Path: components/04-modules/formInset/_formInset.scss
  • Size: 3.2 KB
  • Content:
    %formInset {
        @include stack-spacing(section);
    
        &-title {
            @extend %sectionTitle;
            @include stack-spacing(0);
        }
    
        &-description {
            @extend %richtextBlock;
    
            &:not(:first-child) {
                @include stack-spacing();
            }
    
            > *:first-child {
                @include stack-spacing(0);
            }
    
        }
    
        &-form {
            @include stack-spacing(0);
    
            &:not(:first-child) {
                @include stack-spacing(component);
            }
    
            .buttonGroup {
                @include stack-spacing();
                justify-content: flex-end;
            }
    
            .formFieldset:first-child {
                @include stack-spacing(0);
            }
    
        }
    
    }
    
    .formInset {
        @extend %formInset;
    
        &-title {
            @extend %formInset-title;
        }
    
        &-description {
            @extend %formInset-description;
        }
    
        &-form {
            @extend %formInset-form;
        }
    
    }
    
    //***** Validation *****//
    
    .formInset-form[data-parsley-validate] {
    
        transition-duration: $_transition-duration--out;
    
        *[data-invalid="true"] {
            transition: color $_transition-duration--in;
    
            .formMessage {
                display: none;
            }
    
        }
    
        label {
            transition-property: color;
            transition-duration: inherit
        }
    
        input {
            transition-property: border-color;
            transition-duration: inherit
        }
    
        &[data-valid="false"] .button[type="submit"] {
            @include styles($formInset_button_style--invalid);
        }
    
        .formToggle-label {
            flex-wrap: wrap;
    
            span:not(.toggle) {
                flex: 1 1;
            }
    
        }
    
    }
    
    .parsley-errors {
    
        &-list {
            list-style: none;
            padding: 0;
            margin-top: 0;
    
            &:empty {
                display: none;
            }
    
            li {
                @extend %formMessage;
            }
    
            li + li {
                @include stack-spacing(small);
            }
    
            .formToggle-label & {
                order: 99;
                width: 100%;
                margin-top: $field_stack-spacing;
            }
    
        }
    
    }
    
    
  • URL: /components/raw/forminset/_formInset.styles.scss
  • Filesystem Path: components/04-modules/formInset/_formInset.styles.scss
  • Size: 2.1 KB