239 lines
7.6 KiB
JavaScript
239 lines
7.6 KiB
JavaScript
/**
|
|
* @file
|
|
* Extends the Drupal AJAX functionality to integrate the dialog API.
|
|
*/
|
|
|
|
(function ($, Drupal) {
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* Initialize dialogs for Ajax purposes.
|
|
*
|
|
* @type {Drupal~behavior}
|
|
*
|
|
* @prop {Drupal~behaviorAttach} attach
|
|
* Attaches the behaviors for dialog ajax functionality.
|
|
*/
|
|
Drupal.behaviors.dialog = {
|
|
attach: function (context, settings) {
|
|
var $context = $(context);
|
|
|
|
// 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) {
|
|
// Add 'ui-front' jQuery UI class so jQuery UI widgets like autocomplete
|
|
// sit on top of dialogs. For more information see
|
|
// http://api.jqueryui.com/theming/stacking-elements/.
|
|
$('<div id="drupal-modal" class="ui-front"/>').hide().appendTo('body');
|
|
}
|
|
|
|
// Special behaviors specific when attaching content within a dialog.
|
|
// These behaviors usually fire after a validation error inside a dialog.
|
|
var $dialog = $context.closest('.ui-dialog-content');
|
|
if ($dialog.length) {
|
|
// Remove and replace the dialog buttons with those from the new form.
|
|
if ($dialog.dialog('option', 'drupalAutoButtons')) {
|
|
// Trigger an event to detect/sync changes to buttons.
|
|
$dialog.trigger('dialogButtonsChange');
|
|
}
|
|
|
|
// Force focus on the modal when the behavior is run.
|
|
$dialog.dialog('widget').trigger('focus');
|
|
}
|
|
|
|
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();
|
|
};
|
|
},
|
|
|
|
/**
|
|
* 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) {
|
|
$originalButton.trigger('mousedown').trigger('mouseup').trigger('click');
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
return buttons;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Command to open a dialog.
|
|
*
|
|
* @param {Drupal.Ajax} ajax
|
|
* The Drupal Ajax object.
|
|
* @param {object} response
|
|
* Object holding the server response.
|
|
* @param {number} [status]
|
|
* The HTTP status code.
|
|
*
|
|
* @return {bool|undefined}
|
|
* Returns false if there was no selector property in the response object.
|
|
*/
|
|
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 = $('<div id="' + response.selector.replace(/^#/, '') + '" class="ui-front"/>').appendTo('body');
|
|
}
|
|
// Set up the wrapper, if there isn't one.
|
|
if (!ajax.wrapper) {
|
|
ajax.wrapper = $dialog.attr('id');
|
|
}
|
|
|
|
// 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.dialog('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');
|
|
};
|
|
|
|
/**
|
|
* Command to close a dialog.
|
|
*
|
|
* If no selector is given, it defaults to trying to close the modal.
|
|
*
|
|
* @param {Drupal.Ajax} [ajax]
|
|
* The ajax object.
|
|
* @param {object} response
|
|
* Object holding the server response.
|
|
* @param {string} response.selector
|
|
* The selector of the dialog.
|
|
* @param {bool} response.persist
|
|
* Whether to persist the dialog element or not.
|
|
* @param {number} [status]
|
|
* The HTTP status code.
|
|
*/
|
|
Drupal.AjaxCommands.prototype.closeDialog = function (ajax, response, status) {
|
|
var $dialog = $(response.selector);
|
|
if ($dialog.length) {
|
|
Drupal.dialog($dialog.get(0)).close();
|
|
if (!response.persist) {
|
|
$dialog.remove();
|
|
}
|
|
}
|
|
|
|
// Unbind dialogButtonsChange.
|
|
$dialog.off('dialogButtonsChange');
|
|
};
|
|
|
|
/**
|
|
* Command to set a dialog property.
|
|
*
|
|
* JQuery UI specific way of setting dialog options.
|
|
*
|
|
* @param {Drupal.Ajax} [ajax]
|
|
* The Drupal Ajax object.
|
|
* @param {object} response
|
|
* Object holding the server response.
|
|
* @param {string} response.selector
|
|
* Selector for the dialog element.
|
|
* @param {string} response.optionsName
|
|
* Name of a key to set.
|
|
* @param {string} response.optionValue
|
|
* Value to set.
|
|
* @param {number} [status]
|
|
* The HTTP status code.
|
|
*/
|
|
Drupal.AjaxCommands.prototype.setDialogOption = function (ajax, response, status) {
|
|
var $dialog = $(response.selector);
|
|
if ($dialog.length) {
|
|
$dialog.dialog('option', response.optionName, response.optionValue);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Binds a listener on dialog creation to handle the cancel link.
|
|
*
|
|
* @param {jQuery.Event} e
|
|
* The event triggered.
|
|
* @param {Drupal.dialog~dialogDefinition} dialog
|
|
* The dialog instance.
|
|
* @param {jQuery} $element
|
|
* The jQuery collection of the dialog element.
|
|
* @param {object} [settings]
|
|
* Dialog settings.
|
|
*/
|
|
$(window).on('dialog:aftercreate', function (e, dialog, $element, settings) {
|
|
$element.on('click.dialog', '.dialog-cancel', function (e) {
|
|
dialog.close('cancel');
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Removes all 'dialog' listeners.
|
|
*
|
|
* @param {jQuery.Event} e
|
|
* The event triggered.
|
|
* @param {Drupal.dialog~dialogDefinition} dialog
|
|
* The dialog instance.
|
|
* @param {jQuery} $element
|
|
* jQuery collection of the dialog element.
|
|
*/
|
|
$(window).on('dialog:beforeclose', function (e, dialog, $element) {
|
|
$element.off('.dialog');
|
|
});
|
|
|
|
})(jQuery, Drupal);
|