3 * Extends the Drupal AJAX functionality to integrate the dialog API.
6 (function ($, Drupal) {
11 * Initialize dialogs for Ajax purposes.
13 * @type {Drupal~behavior}
15 * @prop {Drupal~behaviorAttach} attach
16 * Attaches the behaviors for dialog ajax functionality.
18 Drupal.behaviors.dialog = {
19 attach: function (context, settings) {
20 var $context = $(context);
22 // Provide a known 'drupal-modal' DOM element for Drupal-based modal
23 // dialogs. Non-modal dialogs are responsible for creating their own
24 // elements, since there can be multiple non-modal dialogs at a time.
25 if (!$('#drupal-modal').length) {
26 // Add 'ui-front' jQuery UI class so jQuery UI widgets like autocomplete
27 // sit on top of dialogs. For more information see
28 // http://api.jqueryui.com/theming/stacking-elements/.
29 $('<div id="drupal-modal" class="ui-front"/>').hide().appendTo('body');
32 // Special behaviors specific when attaching content within a dialog.
33 // These behaviors usually fire after a validation error inside a dialog.
34 var $dialog = $context.closest('.ui-dialog-content');
36 // Remove and replace the dialog buttons with those from the new form.
37 if ($dialog.dialog('option', 'drupalAutoButtons')) {
38 // Trigger an event to detect/sync changes to buttons.
39 $dialog.trigger('dialogButtonsChange');
42 // Force focus on the modal when the behavior is run.
43 $dialog.dialog('widget').trigger('focus');
46 var originalClose = settings.dialog.close;
47 // Overwrite the close method to remove the dialog on closing.
48 settings.dialog.close = function (event) {
49 originalClose.apply(settings.dialog, arguments);
50 $(event.target).remove();
55 * Scan a dialog for any primary buttons and move them to the button area.
57 * @param {jQuery} $dialog
58 * An jQuery object containing the element that is the dialog target.
61 * An array of buttons that need to be added to the button area.
63 prepareDialogButtons: function ($dialog) {
65 var $buttons = $dialog.find('.form-actions input[type=submit], .form-actions a.button');
66 $buttons.each(function () {
67 // Hidden form buttons need special attention. For browser consistency,
68 // the button needs to be "visible" in order to have the enter key fire
69 // the form submit event. So instead of a simple "hide" or
70 // "display: none", we set its dimensions to zero.
71 // See http://mattsnider.com/how-forms-submit-when-pressing-enter/
72 var $originalButton = $(this).css({
81 text: $originalButton.html() || $originalButton.attr('value'),
82 class: $originalButton.attr('class'),
84 // If the original button is an anchor tag, triggering the "click"
85 // event will not simulate a click. Use the click method instead.
86 if ($originalButton.is('a')) {
87 $originalButton[0].click();
90 $originalButton.trigger('mousedown').trigger('mouseup').trigger('click');
101 * Command to open a dialog.
103 * @param {Drupal.Ajax} ajax
104 * The Drupal Ajax object.
105 * @param {object} response
106 * Object holding the server response.
107 * @param {number} [status]
108 * The HTTP status code.
110 * @return {bool|undefined}
111 * Returns false if there was no selector property in the response object.
113 Drupal.AjaxCommands.prototype.openDialog = function (ajax, response, status) {
114 if (!response.selector) {
117 var $dialog = $(response.selector);
118 if (!$dialog.length) {
119 // Create the element if needed.
120 $dialog = $('<div id="' + response.selector.replace(/^#/, '') + '" class="ui-front"/>').appendTo('body');
122 // Set up the wrapper, if there isn't one.
124 ajax.wrapper = $dialog.attr('id');
127 // Use the ajax.js insert command to populate the dialog contents.
128 response.command = 'insert';
129 response.method = 'html';
130 ajax.commands.insert(ajax, response, status);
132 // Move the buttons to the jQuery UI dialog buttons area.
133 if (!response.dialogOptions.buttons) {
134 response.dialogOptions.drupalAutoButtons = true;
135 response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
138 // Bind dialogButtonsChange.
139 $dialog.on('dialogButtonsChange', function () {
140 var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
141 $dialog.dialog('option', 'buttons', buttons);
144 // Open the dialog itself.
145 response.dialogOptions = response.dialogOptions || {};
146 var dialog = Drupal.dialog($dialog.get(0), response.dialogOptions);
147 if (response.dialogOptions.modal) {
154 // Add the standard Drupal class for buttons for style consistency.
155 $dialog.parent().find('.ui-dialog-buttonset').addClass('form-actions');
159 * Command to close a dialog.
161 * If no selector is given, it defaults to trying to close the modal.
163 * @param {Drupal.Ajax} [ajax]
165 * @param {object} response
166 * Object holding the server response.
167 * @param {string} response.selector
168 * The selector of the dialog.
169 * @param {bool} response.persist
170 * Whether to persist the dialog element or not.
171 * @param {number} [status]
172 * The HTTP status code.
174 Drupal.AjaxCommands.prototype.closeDialog = function (ajax, response, status) {
175 var $dialog = $(response.selector);
176 if ($dialog.length) {
177 Drupal.dialog($dialog.get(0)).close();
178 if (!response.persist) {
183 // Unbind dialogButtonsChange.
184 $dialog.off('dialogButtonsChange');
188 * Command to set a dialog property.
190 * JQuery UI specific way of setting dialog options.
192 * @param {Drupal.Ajax} [ajax]
193 * The Drupal Ajax object.
194 * @param {object} response
195 * Object holding the server response.
196 * @param {string} response.selector
197 * Selector for the dialog element.
198 * @param {string} response.optionsName
199 * Name of a key to set.
200 * @param {string} response.optionValue
202 * @param {number} [status]
203 * The HTTP status code.
205 Drupal.AjaxCommands.prototype.setDialogOption = function (ajax, response, status) {
206 var $dialog = $(response.selector);
207 if ($dialog.length) {
208 $dialog.dialog('option', response.optionName, response.optionValue);
213 * Binds a listener on dialog creation to handle the cancel link.
215 * @param {jQuery.Event} e
216 * The event triggered.
217 * @param {Drupal.dialog~dialogDefinition} dialog
218 * The dialog instance.
219 * @param {jQuery} $element
220 * The jQuery collection of the dialog element.
221 * @param {object} [settings]
224 $(window).on('dialog:aftercreate', function (e, dialog, $element, settings) {
225 $element.on('click.dialog', '.dialog-cancel', function (e) {
226 dialog.close('cancel');
233 * Removes all 'dialog' listeners.
235 * @param {jQuery.Event} e
236 * The event triggered.
237 * @param {Drupal.dialog~dialogDefinition} dialog
238 * The dialog instance.
239 * @param {jQuery} $element
240 * jQuery collection of the dialog element.
242 $(window).on('dialog:beforeclose', function (e, dialog, $element) {
243 $element.off('.dialog');