Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / quickedit / js / util.es6.js
diff --git a/web/core/modules/quickedit/js/util.es6.js b/web/core/modules/quickedit/js/util.es6.js
new file mode 100644 (file)
index 0000000..7fa952b
--- /dev/null
@@ -0,0 +1,209 @@
+/**
+ * @file
+ * Provides utility functions for Quick Edit.
+ */
+
+(function ($, Drupal) {
+  /**
+   * @namespace
+   */
+  Drupal.quickedit.util = Drupal.quickedit.util || {};
+
+  /**
+   * @namespace
+   */
+  Drupal.quickedit.util.constants = {};
+
+  /**
+   *
+   * @type {string}
+   */
+  Drupal.quickedit.util.constants.transitionEnd = 'transitionEnd.quickedit webkitTransitionEnd.quickedit transitionend.quickedit msTransitionEnd.quickedit oTransitionEnd.quickedit';
+
+  /**
+   * Converts a field id into a formatted url path.
+   *
+   * @example
+   * Drupal.quickedit.util.buildUrl(
+   *   'node/1/body/und/full',
+   *   '/quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode'
+   * );
+   *
+   * @param {string} id
+   *   The id of an editable field.
+   * @param {string} urlFormat
+   *   The Controller route for field processing.
+   *
+   * @return {string}
+   *   The formatted URL.
+   */
+  Drupal.quickedit.util.buildUrl = function (id, urlFormat) {
+    const parts = id.split('/');
+    return Drupal.formatString(decodeURIComponent(urlFormat), {
+      '!entity_type': parts[0],
+      '!id': parts[1],
+      '!field_name': parts[2],
+      '!langcode': parts[3],
+      '!view_mode': parts[4],
+    });
+  };
+
+  /**
+   * Shows a network error modal dialog.
+   *
+   * @param {string} title
+   *   The title to use in the modal dialog.
+   * @param {string} message
+   *   The message to use in the modal dialog.
+   */
+  Drupal.quickedit.util.networkErrorModal = function (title, message) {
+    const $message = $(`<div>${message}</div>`);
+    var networkErrorModal = Drupal.dialog($message.get(0), {
+      title,
+      dialogClass: 'quickedit-network-error',
+      buttons: [
+        {
+          text: Drupal.t('OK'),
+          click() {
+            networkErrorModal.close();
+          },
+          primary: true,
+        },
+      ],
+      create() {
+        $(this).parent().find('.ui-dialog-titlebar-close').remove();
+      },
+      close(event) {
+        // Automatically destroy the DOM element that was used for the dialog.
+        $(event.target).remove();
+      },
+    });
+    networkErrorModal.showModal();
+  };
+
+  /**
+   * @namespace
+   */
+  Drupal.quickedit.util.form = {
+
+    /**
+     * Loads a form, calls a callback to insert.
+     *
+     * Leverages {@link Drupal.Ajax}' ability to have scoped (per-instance)
+     * command implementations to be able to call a callback.
+     *
+     * @param {object} options
+     *   An object with the following keys:
+     * @param {string} options.fieldID
+     *   The field ID that uniquely identifies the field for which this form
+     *   will be loaded.
+     * @param {bool} options.nocssjs
+     *   Boolean indicating whether no CSS and JS should be returned (necessary
+     *   when the form is invisible to the user).
+     * @param {bool} options.reset
+     *   Boolean indicating whether the data stored for this field's entity in
+     *   PrivateTempStore should be used or reset.
+     * @param {function} callback
+     *   A callback function that will receive the form to be inserted, as well
+     *   as the ajax object, necessary if the callback wants to perform other
+     *   Ajax commands.
+     */
+    load(options, callback) {
+      const fieldID = options.fieldID;
+
+      // Create a Drupal.ajax instance to load the form.
+      const formLoaderAjax = Drupal.ajax({
+        url: Drupal.quickedit.util.buildUrl(fieldID, Drupal.url('quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode')),
+        submit: {
+          nocssjs: options.nocssjs,
+          reset: options.reset,
+        },
+        error(xhr, url) {
+          // Show a modal to inform the user of the network error.
+          const fieldLabel = Drupal.quickedit.metadata.get(fieldID, 'label');
+          const message = Drupal.t('Could not load the form for <q>@field-label</q>, either due to a website problem or a network connection problem.<br>Please try again.', { '@field-label': fieldLabel });
+          Drupal.quickedit.util.networkErrorModal(Drupal.t('Network problem!'), message);
+
+          // Change the state back to "candidate", to allow the user to start
+          // in-place editing of the field again.
+          const fieldModel = Drupal.quickedit.app.model.get('activeField');
+          fieldModel.set('state', 'candidate');
+        },
+      });
+      // Implement a scoped quickeditFieldForm AJAX command: calls the callback.
+      formLoaderAjax.commands.quickeditFieldForm = function (ajax, response, status) {
+        callback(response.data, ajax);
+        Drupal.ajax.instances[this.instanceIndex] = null;
+      };
+      // This will ensure our scoped quickeditFieldForm AJAX command gets
+      // called.
+      formLoaderAjax.execute();
+    },
+
+    /**
+     * Creates a {@link Drupal.Ajax} instance that is used to save a form.
+     *
+     * @param {object} options
+     *   Submit options to the form.
+     * @param {bool} options.nocssjs
+     *   Boolean indicating whether no CSS and JS should be returned (necessary
+     *   when the form is invisible to the user).
+     * @param {Array.<string>} options.other_view_modes
+     *   Array containing view mode IDs (of other instances of this field on the
+     *   page).
+     * @param {jQuery} $submit
+     *   The submit element.
+     *
+     * @return {Drupal.Ajax}
+     *   A {@link Drupal.Ajax} instance.
+     */
+    ajaxifySaving(options, $submit) {
+      // Re-wire the form to handle submit.
+      const settings = {
+        url: $submit.closest('form').attr('action'),
+        setClick: true,
+        event: 'click.quickedit',
+        progress: false,
+        submit: {
+          nocssjs: options.nocssjs,
+          other_view_modes: options.other_view_modes,
+        },
+
+        /**
+         * Reimplement the success handler.
+         *
+         * Ensure {@link Drupal.attachBehaviors} does not get called on the
+         * form.
+         *
+         * @param {Drupal.AjaxCommands~commandDefinition} response
+         *   The Drupal AJAX response.
+         * @param {number} [status]
+         *   The HTTP status code.
+         */
+        success(response, status) {
+          for (const i in response) {
+            if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
+              this.commands[response[i].command](this, response[i], status);
+            }
+          }
+        },
+        base: $submit.attr('id'),
+        element: $submit[0],
+      };
+
+      return Drupal.ajax(settings);
+    },
+
+    /**
+     * Cleans up the {@link Drupal.Ajax} instance that is used to save the form.
+     *
+     * @param {Drupal.Ajax} ajax
+     *   A {@link Drupal.Ajax} instance that was returned by
+     *   {@link Drupal.quickedit.form.ajaxifySaving}.
+     */
+    unajaxifySaving(ajax) {
+      $(ajax.element).off('click.quickedit');
+    },
+
+  };
+}(jQuery, Drupal));