util.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * @file
  3. * Provides utility functions for Quick Edit.
  4. */
  5. (function ($, Drupal) {
  6. 'use strict';
  7. /**
  8. * @namespace
  9. */
  10. Drupal.quickedit.util = Drupal.quickedit.util || {};
  11. /**
  12. * @namespace
  13. */
  14. Drupal.quickedit.util.constants = {};
  15. /**
  16. *
  17. * @type {string}
  18. */
  19. Drupal.quickedit.util.constants.transitionEnd = 'transitionEnd.quickedit webkitTransitionEnd.quickedit transitionend.quickedit msTransitionEnd.quickedit oTransitionEnd.quickedit';
  20. /**
  21. * Converts a field id into a formatted url path.
  22. *
  23. * @example
  24. * Drupal.quickedit.util.buildUrl(
  25. * 'node/1/body/und/full',
  26. * '/quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode'
  27. * );
  28. *
  29. * @param {string} id
  30. * The id of an editable field.
  31. * @param {string} urlFormat
  32. * The Controller route for field processing.
  33. *
  34. * @return {string}
  35. * The formatted URL.
  36. */
  37. Drupal.quickedit.util.buildUrl = function (id, urlFormat) {
  38. var parts = id.split('/');
  39. return Drupal.formatString(decodeURIComponent(urlFormat), {
  40. '!entity_type': parts[0],
  41. '!id': parts[1],
  42. '!field_name': parts[2],
  43. '!langcode': parts[3],
  44. '!view_mode': parts[4]
  45. });
  46. };
  47. /**
  48. * Shows a network error modal dialog.
  49. *
  50. * @param {string} title
  51. * The title to use in the modal dialog.
  52. * @param {string} message
  53. * The message to use in the modal dialog.
  54. */
  55. Drupal.quickedit.util.networkErrorModal = function (title, message) {
  56. var $message = $('<div>' + message + '</div>');
  57. var networkErrorModal = Drupal.dialog($message.get(0), {
  58. title: title,
  59. dialogClass: 'quickedit-network-error',
  60. buttons: [
  61. {
  62. text: Drupal.t('OK'),
  63. click: function () {
  64. networkErrorModal.close();
  65. },
  66. primary: true
  67. }
  68. ],
  69. create: function () {
  70. $(this).parent().find('.ui-dialog-titlebar-close').remove();
  71. },
  72. close: function (event) {
  73. // Automatically destroy the DOM element that was used for the dialog.
  74. $(event.target).remove();
  75. }
  76. });
  77. networkErrorModal.showModal();
  78. };
  79. /**
  80. * @namespace
  81. */
  82. Drupal.quickedit.util.form = {
  83. /**
  84. * Loads a form, calls a callback to insert.
  85. *
  86. * Leverages {@link Drupal.Ajax}' ability to have scoped (per-instance)
  87. * command implementations to be able to call a callback.
  88. *
  89. * @param {object} options
  90. * An object with the following keys:
  91. * @param {string} options.fieldID
  92. * The field ID that uniquely identifies the field for which this form
  93. * will be loaded.
  94. * @param {bool} options.nocssjs
  95. * Boolean indicating whether no CSS and JS should be returned (necessary
  96. * when the form is invisible to the user).
  97. * @param {bool} options.reset
  98. * Boolean indicating whether the data stored for this field's entity in
  99. * PrivateTempStore should be used or reset.
  100. * @param {function} callback
  101. * A callback function that will receive the form to be inserted, as well
  102. * as the ajax object, necessary if the callback wants to perform other
  103. * Ajax commands.
  104. */
  105. load: function (options, callback) {
  106. var fieldID = options.fieldID;
  107. // Create a Drupal.ajax instance to load the form.
  108. var formLoaderAjax = Drupal.ajax({
  109. url: Drupal.quickedit.util.buildUrl(fieldID, Drupal.url('quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode')),
  110. submit: {
  111. nocssjs: options.nocssjs,
  112. reset: options.reset
  113. },
  114. error: function (xhr, url) {
  115. // Show a modal to inform the user of the network error.
  116. var fieldLabel = Drupal.quickedit.metadata.get(fieldID, 'label');
  117. 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});
  118. Drupal.quickedit.util.networkErrorModal(Drupal.t('Network problem!'), message);
  119. // Change the state back to "candidate", to allow the user to start
  120. // in-place editing of the field again.
  121. var fieldModel = Drupal.quickedit.app.model.get('activeField');
  122. fieldModel.set('state', 'candidate');
  123. }
  124. });
  125. // Implement a scoped quickeditFieldForm AJAX command: calls the callback.
  126. formLoaderAjax.commands.quickeditFieldForm = function (ajax, response, status) {
  127. callback(response.data, ajax);
  128. Drupal.ajax.instances[this.instanceIndex] = null;
  129. };
  130. // This will ensure our scoped quickeditFieldForm AJAX command gets
  131. // called.
  132. formLoaderAjax.execute();
  133. },
  134. /**
  135. * Creates a {@link Drupal.Ajax} instance that is used to save a form.
  136. *
  137. * @param {object} options
  138. * Submit options to the form.
  139. * @param {bool} options.nocssjs
  140. * Boolean indicating whether no CSS and JS should be returned (necessary
  141. * when the form is invisible to the user).
  142. * @param {Array.<string>} options.other_view_modes
  143. * Array containing view mode IDs (of other instances of this field on the
  144. * page).
  145. * @param {jQuery} $submit
  146. * The submit element.
  147. *
  148. * @return {Drupal.Ajax}
  149. * A {@link Drupal.Ajax} instance.
  150. */
  151. ajaxifySaving: function (options, $submit) {
  152. // Re-wire the form to handle submit.
  153. var settings = {
  154. url: $submit.closest('form').attr('action'),
  155. setClick: true,
  156. event: 'click.quickedit',
  157. progress: false,
  158. submit: {
  159. nocssjs: options.nocssjs,
  160. other_view_modes: options.other_view_modes
  161. },
  162. /**
  163. * Reimplement the success handler.
  164. *
  165. * Ensure {@link Drupal.attachBehaviors} does not get called on the
  166. * form.
  167. *
  168. * @param {Drupal.AjaxCommands~commandDefinition} response
  169. * The Drupal AJAX response.
  170. * @param {number} [status]
  171. * The HTTP status code.
  172. */
  173. success: function (response, status) {
  174. for (var i in response) {
  175. if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) {
  176. this.commands[response[i].command](this, response[i], status);
  177. }
  178. }
  179. },
  180. base: $submit.attr('id'),
  181. element: $submit[0]
  182. };
  183. return Drupal.ajax(settings);
  184. },
  185. /**
  186. * Cleans up the {@link Drupal.Ajax} instance that is used to save the form.
  187. *
  188. * @param {Drupal.Ajax} ajax
  189. * A {@link Drupal.Ajax} instance that was returned by
  190. * {@link Drupal.quickedit.form.ajaxifySaving}.
  191. */
  192. unajaxifySaving: function (ajax) {
  193. $(ajax.element).off('click.quickedit');
  194. }
  195. };
  196. })(jQuery, Drupal);