Source: JsonSchemaForms.js

/**
 * The main module implementing the form construction.
 *
 * @module JsonSchemaForms
 */
'use strict';

import FormElement from './form/formElement.js';
import defaultFormOptions from './form/defaultFormOptions.js';

import $RefParser from '@apidevtools/json-schema-ref-parser';
import jquery from 'jquery';

/**
 * Builds an HTML form from a given JSON Schema. The main function to be
 * interacted by users.
 *
 * It allows to provide specific options for the form construction, and a custom
 * callback function triggered on submission.
 *
 * @param {object} schema The JSON Schema to represent as an HTML form.
 * @param {Function} [submitCallback=() => {}] Callback function to be called
 * when the form triggers the `submit` DOM event.
 * @param {object} customFormOptions Form options overriding the default. See
 * {@link defaultFormOptions} for details.
 *
 * @returns {HTMLDivElement} A `<div>` element containing the HTML form.
 */
function build(schema, submitCallback = () => {}, customFormOptions = {}) {
  // Builds form options by merging the provided custom options with the
  // defaults.
  const formOptions = {
    ...defaultFormOptions,
    ...customFormOptions,
  };

  // Ensures jQuery is available if Bootstrap is required but failed loading.
  if (formOptions.bootstrap && !window.$) {
    console.warn('Bootstrap expected but JQuery was not loaded.');
    window.$ = jquery;
  }

  const containerDiv = document.createElement('div');

  $RefParser.dereference(schema, (err, s) => {
    if (err) console.error(err);
    else {
      // Generates the form recursively.
      const rootFormElement = new FormElement(s, {
        formOptions,
      });

      // Creates the HTML structure containing the form.
      const formDiv = document.createElement('div');
      const form = formDiv.appendChild(document.createElement('form'));
      form.id = formOptions.formId;

      form.addEventListener('submit', (event) => {
        const valid = submitCallback(rootFormElement);

        if (valid === false) event.preventDefault();
      });

      const submitButton = form.appendChild(document.createElement('button'));
      submitButton.type = 'submit';
      submitButton.innerText = formOptions.submitButtonText;

      containerDiv.appendChild(rootFormElement.layout.root);
      containerDiv.appendChild(formDiv);

      if (formOptions.bootstrap) {
        containerDiv.classList.add('container-fluid', 'bg-light');
        formDiv.classList.add('pt-4');
        submitButton.classList.add('btn', 'btn-primary');
      }
    }
  });

  return containerDiv;
}

export default { build };