/**
* @file
- * Extends the Drupal AJAX functionality to integrate the dialog API.
+ * dialog.ajax.js
*/
-
(function ($, Drupal) {
- 'use strict';
- /**
- * Initialize dialogs for Ajax purposes.
- *
- * @type {Drupal~behavior}
- */
- Drupal.behaviors.dialog = {
- attach: function (context, settings) {
- var $context = $(context);
+ var dialogAjaxCurrentButton;
+ var dialogAjaxOriginalButton;
- // Provide a known 'drupal-modal' DOM element for Drupal-based modal
- // dialogs. Non-modal dialogs are responsible for creating their own
- // elements, since there can be multiple non-modal dialogs at a time.
- if (!$('#drupal-modal').length) {
- $(Drupal.theme.bootstrapModal()).appendTo('body');
+ $(document)
+ .ajaxSend(function () {
+ if (dialogAjaxCurrentButton && dialogAjaxOriginalButton) {
+ dialogAjaxCurrentButton.html(dialogAjaxOriginalButton.html());
+ dialogAjaxCurrentButton.prop('disabled', dialogAjaxOriginalButton.prop('disabled'));
}
-
- // Special behaviors specific when attaching content within a dialog.
- // These behaviors usually fire after a validation error inside a dialog.
- var $dialog = $context.closest('.modal');
- if ($dialog.length) {
- // Remove and replace the dialog buttons with those from the new form.
- if ($dialog.modal('option', 'drupalAutoButtons')) {
- // Trigger an event to detect/sync changes to buttons.
- $dialog.trigger('dialogButtonsChange');
- }
-
- // Attempt to force focus on the first visible input (not :input) in
- // the modal body when the behavior is run.
- Drupal.behaviors.dialog.focus($dialog);
+ })
+ .ajaxComplete(function () {
+ if (dialogAjaxCurrentButton && dialogAjaxOriginalButton) {
+ dialogAjaxCurrentButton.html(dialogAjaxOriginalButton.html());
+ dialogAjaxCurrentButton.prop('disabled', dialogAjaxOriginalButton.prop('disabled'));
}
+ dialogAjaxCurrentButton = null;
+ dialogAjaxOriginalButton = null;
+ })
+ ;
- var originalClose = settings.dialog.close;
- // Overwrite the close method to remove the dialog on closing.
- settings.dialog.close = function (event) {
- originalClose.apply(settings.dialog, arguments);
- $(event.target).remove();
- };
- },
-
- /**
- * Attempt to focus the first visible input (not :input) in the modal body.
- *
- * @param {jQuery} $dialog
- * An jQuery object containing the element that is the dialog target.
- */
- focus: function ($dialog) {
- $dialog.find('.modal-body input:visible:first').trigger('focus');
- },
-
- /**
- * Scan a dialog for any primary buttons and move them to the button area.
- *
- * @param {jQuery} $dialog
- * An jQuery object containing the element that is the dialog target.
- *
- * @return {Array}
- * An array of buttons that need to be added to the button area.
- */
- prepareDialogButtons: function ($dialog) {
- var buttons = [];
- var $buttons = $dialog.find('.form-actions :input[type=submit]');
- $buttons.each(function () {
- // Hidden form buttons need special attention. For browser consistency,
- // the button needs to be "visible" in order to have the enter key fire
- // the form submit event. So instead of a simple "hide" or
- // "display: none", we set its dimensions to zero.
- // See http://mattsnider.com/how-forms-submit-when-pressing-enter/
- var $originalButton = $(this).css({
- display: 'block',
- width: 0,
- height: 0,
- padding: 0,
- border: 0
- });
- buttons.push({
- text: $originalButton.html() || $originalButton.attr('value'),
- class: $originalButton.attr('class'),
- click: function (e) {
+ /**
+ * {@inheritdoc}
+ */
+ Drupal.behaviors.dialog.prepareDialogButtons = function prepareDialogButtons($dialog) {
+ var buttons = [];
+ var $buttons = $dialog.find('.form-actions').find('button, input[type=submit], .form-actions a.button');
+ $buttons.each(function () {
+ var $originalButton = $(this).css({
+ display: 'block',
+ width: 0,
+ height: 0,
+ padding: 0,
+ border: 0,
+ overflow: 'hidden'
+ });
+ var classes = $originalButton.attr('class').replace('use-ajax-submit', '');
+ buttons.push({
+ text: $originalButton.html() || $originalButton.attr('value'),
+ class: classes,
+ click: function click(e) {
+ dialogAjaxCurrentButton = $(e.target);
+ dialogAjaxOriginalButton = $originalButton;
+ if ($originalButton.is('a')) {
+ $originalButton[0].click();
+ }
+ else {
$originalButton.trigger('mousedown').trigger('mouseup').trigger('click');
e.preventDefault();
}
- });
+ }
});
- return buttons;
- }
- };
-
- /**
- * Command to open a dialog.
- *
- * @param {Drupal.Ajax} ajax
- * @param {object} response
- * @param {number} [status]
- *
- * @return {bool|undefined}
- */
- Drupal.AjaxCommands.prototype.openDialog = function (ajax, response, status) {
- if (!response.selector) {
- return false;
- }
-
- var $dialog = $(response.selector);
- if (!$dialog.length) {
- // Create the element if needed.
- $dialog = $(Drupal.theme.bootstrapModal({ id: response.selector.replace(/^#/, '') })).appendTo('body');
- }
- // Set up the wrapper, if there isn't one.
- var id = $dialog.attr('id');
- if (response.selector === '#' + id) {
- response.selector = '#' + id + '--body';
- }
- else if (!ajax.wrapper) {
- ajax.wrapper = id + '--body';
- }
-
- // Use the ajax.js insert command to populate the dialog contents.
- response.command = 'insert';
- response.method = 'html';
- ajax.commands.insert(ajax, response, status);
-
- // Move the buttons to the jQuery UI dialog buttons area.
- if (!response.dialogOptions.buttons) {
- response.dialogOptions.drupalAutoButtons = true;
- response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
- }
-
- // Bind dialogButtonsChange.
- $dialog.on('dialogButtonsChange', function () {
- var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
- $dialog.modal('option', 'buttons', buttons);
});
-
- // Open the dialog itself.
- response.dialogOptions = response.dialogOptions || {};
- var dialog = Drupal.dialog($dialog.get(0), response.dialogOptions);
- if (response.dialogOptions.modal) {
- dialog.showModal();
- }
- else {
- dialog.show();
- }
-
- // Add the standard Drupal class for buttons for style consistency.
- $dialog.parent().find('.ui-dialog-buttonset').addClass('form-actions');
+ return buttons;
};
- /**
- * Command to close a dialog.
- *
- * If no selector is given, it defaults to trying to close the modal.
- *
- * @param {Drupal.Ajax} [ajax]
- * @param {object} response
- * @param {string} response.selector
- * @param {bool} response.persist
- * @param {number} [status]
- */
- Drupal.AjaxCommands.prototype.closeDialog = function (ajax, response, status) {
- var $dialog = $(response.selector);
- if ($dialog.length) {
- Drupal.dialog($dialog.get(0)).close();
- if (!response.persist) {
- // Wrap this in a timer so animations can finish.
- setTimeout(function() {
- $dialog.remove();
- }, 1000);
- }
- }
-
- // Unbind dialogButtonsChange.
- $dialog.off('dialogButtonsChange');
- };
-
- /**
- * Command to set a dialog property.
- *
- * JQuery UI specific way of setting dialog options.
- *
- * @param {Drupal.Ajax} [ajax]
- * @param {object} response
- * @param {string} response.selector
- * @param {string} response.optionsName
- * @param {string} response.optionValue
- * @param {number} [status]
- */
- Drupal.AjaxCommands.prototype.setDialogOption = function (ajax, response, status) {
- var $dialog = $(response.selector);
- if ($dialog.length) {
- $dialog.modal('option', response.optionName, response.optionValue);
- }
- };
-
- /**
- * Binds a listener on dialog before creation to setup title and buttons.
- *
- * @param {jQuery.Event} e
- * @param {Drupal.dialog} dialog
- * @param {jQuery} $element
- * @param {object} settings
- */
- $(window).on('dialog:beforecreate', function (e, dialog, $element, settings) {
- // Replace title.
- if (settings.title) {
- var $header = $element.find('.modal-header');
- if (!$header[0]) {
- $header = $(Drupal.theme.bootstrapModalHeader()).prependTo($element.find('.modal-content'));
- }
- $header.find('.modal-title').text(Drupal.checkPlain(settings.title));
- }
-
- // Remove any existing buttons.
- $element.find('.modal-footer').remove();
-
- // Add new buttons.
- if (settings.buttons && settings.buttons.length) {
- var $footer = $(Drupal.theme.bootstrapModalFooter('', true)).appendTo($element.find('.modal-content'));
- for (var i in settings.buttons) {
- if (!settings.buttons.hasOwnProperty(i)) continue;
- var button = settings.buttons[i];
- $('<button class="' + button.class + '">' + button.text + '</button>')
- .appendTo($footer)
- .on('click', button.click);
- }
- }
- });
-
- /**
- * Binds a listener on dialog creation to handle the cancel link.
- *
- * @param {jQuery.Event} e
- * @param {Drupal.dialog} dialog
- * @param {jQuery} $element
- * @param {object} settings
- */
- $(window).on('dialog:aftercreate', function (e, dialog, $element, settings) {
- Drupal.behaviors.dialog.focus($element);
- $element.on('click.dialog', '.dialog-cancel', function (e) {
- dialog.close('cancel');
- e.preventDefault();
- e.stopPropagation();
- });
- });
-
- /**
- * Removes all 'dialog' listeners.
- *
- * @param {jQuery.Event} e
- * @param {Drupal.dialog} dialog
- * @param {jQuery} $element
- */
- $(window).on('dialog:beforeclose', function (e, dialog, $element) {
- $element.off('.modal.drupal');
- });
-
-})(jQuery, Drupal);
+})(window.jQuery, window.Drupal, window.Drupal.bootstrap);