--- /dev/null
+/**
+ * @file
+ * Provides utility functions for Quick Edit.
+ */
+
+(function ($, Drupal) {
+
+ 'use strict';
+
+ /**
+ * @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) {
+ var 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) {
+ var $message = $('<div>' + message + '</div>');
+ var networkErrorModal = Drupal.dialog($message.get(0), {
+ title: title,
+ dialogClass: 'quickedit-network-error',
+ buttons: [
+ {
+ text: Drupal.t('OK'),
+ click: function () {
+ networkErrorModal.close();
+ },
+ primary: true
+ }
+ ],
+ create: function () {
+ $(this).parent().find('.ui-dialog-titlebar-close').remove();
+ },
+ close: function (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: function (options, callback) {
+ var fieldID = options.fieldID;
+
+ // Create a Drupal.ajax instance to load the form.
+ var 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: function (xhr, url) {
+ // Show a modal to inform the user of the network error.
+ var fieldLabel = Drupal.quickedit.metadata.get(fieldID, 'label');
+ var 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.
+ var 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: function (options, $submit) {
+ // Re-wire the form to handle submit.
+ var 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: function (response, status) {
+ for (var 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: function (ajax) {
+ $(ajax.element).off('click.quickedit');
+ }
+
+ };
+
+})(jQuery, Drupal);