Commit bf1d441a authored by Devin Carlson's avatar Devin Carlson

Add the Dialog module as a dependency to simplify modal dialog handling.

parent 5f1cae10
......@@ -5,33 +5,6 @@
* Admin page callbacks for the entity_embed module.
*/
/**
* Menu callback; Provide the dialog for embedding entities.
*/
function entity_embed_dialog($filter_format, $embed_button) {
$input = $_POST;
$dialog_options = array();
if (isset($input['dialog'])) {
$dialog_options = $input['dialog'];
}
// Render the content.
$form = drupal_get_form('entity_embed_dialog_form', $input, $filter_format, $embed_button);
// Determine the title: use the title provided by the form if any, otherwise
// get it from the menu item.
$title = isset($form['#title']) ? $form['#title'] : drupal_get_title();
$content = drupal_render($form);
drupal_process_attached($form);
$commands[] = entity_embed_command_open_modal_dialog($title, $content, $dialog_options);
return array('#type' => 'ajax', '#commands' => $commands);
}
/**
* Form constructor for the entity embed dialog form.
*
......@@ -40,7 +13,9 @@ function entity_embed_dialog($filter_format, $embed_button) {
* @see entity_embed_dialog_form_validate()
* @ingroup forms
*/
function entity_embed_dialog_form($form, &$form_state, $input, $filter_format, $embed_button) {
function entity_embed_dialog_form($form, &$form_state, $filter_format, $embed_button) {
$input = $_POST;
$values = isset($form_state['values']) ? $form_state['values'] : array();
// Initialize entity element with form attributes, if present.
......@@ -434,7 +409,7 @@ function submitEmbedForm(&$form, $form_state) {
}
$commands[] = entity_embed_command_editor_dialog_save($values);
$commands[] = entity_embed_command_close_modal_dialog();
$commands[] = dialog_command_close_modal_dialog();
}
return array(
......
......@@ -5,6 +5,7 @@ core = 7.x
dependencies[] = ctools
dependencies[] = ckeditor
dependencies[] = dialog
dependencies[] = entity
dependencies[] = filter
dependencies[] = jquery_update
......
......@@ -42,13 +42,11 @@ function entity_embed_menu() {
$items['entity-embed/dialog/entity-embed/%entity_embed_filter_format/%entity_embed_embed_button'] = array(
'title' => 'Add/Edit embedded entity',
'page callback' => 'entity_embed_dialog',
'page arguments' => array(3, 4),
'page callback' => 'drupal_get_form',
'page arguments' => array('entity_embed_dialog_form', 3, 4),
'access callback' => '_entity_embed_button_is_enabled',
'access arguments' => array(3, 4),
'delivery callback' => 'ajax_deliver',
'file' => 'entity_embed.admin.inc',
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
);
......@@ -258,73 +256,6 @@ function entity_embed_autocomplete_entity($filter_format, $embed_button, $string
* Implements hook_library().

*/
function entity_embed_library() {
$libraries['drupal.dialog'] = array(
'title' => 'Drupal Dialog',
'website' => 'http://www.drupal.org',
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'entity_embed') . '/js/dialog/dialog.js' => array(
'weight' => 2,
),
drupal_get_path('module', 'entity_embed') . '/js/dialog/dialog.position.js' => array(
'weight' => 2,
),
drupal_get_path('module', 'entity_embed') . '/js/dialog/dialog.jquery-ui.js' => array(
'weight' => 2,
),
),
'css' => array(
drupal_get_path('module', 'entity_embed') . '/js/dialog/dialog.theme.css' => array(),
),
'dependencies' => array(
array('system', 'jquery'),
array('system', 'ui.dialog'),
array('entity_embed', 'drupal.debounce'),
array('entity_embed', 'drupal.displace'),
),
);
$libraries['drupal.dialog.ajax'] = array(
'title' => 'Drupal AJAX Dialog',
'website' => 'http://www.drupal.org',
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'entity_embed') . '/js/dialog/dialog.ajax.js' => array(
'weight' => 2,
),
),
'dependencies' => array(
array('system', 'jquery'),
array('system', 'drupal.ajax'),
array('entity_embed', 'drupal.dialog'),
),
);
$libraries['drupal.displace'] = array(
'title' => 'Drupal Displace',
'website' => 'http://www.drupal.org',
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'entity_embed') . '/js/drupal/displace.js' => array(
'weight' => 2,
),
),
'dependencies' => array(
array('system', 'jquery'),
),
);
$libraries['drupal.debounce'] = array(
'title' => 'Drupal Debounce',
'website' => 'http://www.drupal.org',
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'entity_embed') . '/js/drupal/debounce.js' => array(
'weight' => 2,
),
),
);
$libraries['drupal.editor.dialog'] = array(
'title' => 'Drupal Editor Dialog',
'website' => 'http://www.drupal.org',
......@@ -337,7 +268,7 @@ function entity_embed_library() {
'dependencies' => array(
array('system', 'jquery'),
array('system', 'drupal.ajax'),
array('entity_embed', 'drupal.dialog'),
array('dialog', 'drupal.dialog'),
),
);
......@@ -646,7 +577,7 @@ function entity_embed_pre_render_text_format($element) {
);
}
$element['#attached']['library'][] = array('entity_embed', 'drupal.dialog.ajax');
$element['#attached']['library'][] = array('dialog', 'drupal.dialog.ajax');
$element['#attached']['js'][] = array(
'data' => array(
......
......@@ -22,174 +22,6 @@ function entity_embed_command_insert($html) {
);
}
/**
* Creates a Drupal Ajax 'close dialog' command.
*
* @param string $selector
* A CSS selector string of the dialog to close.
* @param bool $persist
* (optional) Whether to persist the dialog in the DOM or not.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_close_dialog($selector = NULL, $persist = FALSE) {
return array(
'command' => 'closeDialog',
'selector' => $selector ? $selector : '#drupal-modal',
'persist' => $persist,
);
}
/**
* Creates a Drupal Ajax 'close modal dialog' command.
*
* @param bool $persist
* (optional) Whether to persist the dialog in the DOM or not.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_close_modal_dialog($persist = FALSE) {
return array(
'command' => 'closeDialog',
'selector' => '#drupal-modal',
'persist' => $persist,
);
}
/**
* Creates a Drupal Ajax 'open dialog' command.
*
* @param string $selector
* The selector of the dialog.
* @param string $title
* The title of the dialog.
* @param string|array $content
* The content that will be placed in the dialog, either a render array
* or an HTML string.
* @param array $dialog_options
* (optional) Options to be passed to the dialog implementation. Any
* jQuery UI option can be used. See http://api.jqueryui.com/dialog.
* @param array|null $settings
* (optional) Custom settings that will be passed to the Drupal behaviors
* on the content of the dialog. If left empty, the settings will be
* populated automatically from the current request.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_open_dialog($selector, $title, $content, array $dialog_options = array(), $settings = NULL) {
$dialog_options += array('title' => $title);
if (is_array($content)) {
$html = drupal_render($content);
$content = $html;
}
// For consistency ensure the modal option is set to TRUE or FALSE.
$dialog_options['modal'] = isset($dialog_options['modal']) && $dialog_options['modal'];
return array(
'command' => 'openDialog',
'selector' => $selector,
'settings' => $settings,
'data' => $content,
'dialogOptions' => $dialog_options,
);
}
/**
* Creates a Drupal Ajax 'open modal dialog' command.
*
* The modal dialog differs from the normal modal provided by
* entity_embed_command_open_dialog in that a modal prevents other interactions
* on the page until the modal has been completed. Drupal provides a built-in
* modal for this purpose, so no selector needs to be provided.
*
* @param string $title
* The title of the dialog.
* @param string|array $content
* The content that will be placed in the dialog, either a render array
* or an HTML string.
* @param array $dialog_options
* (optional) Settings to be passed to the dialog implementation. Any
* jQuery UI option can be used. See http://api.jqueryui.com/dialog.
* @param array|null $settings
* (optional) Custom settings that will be passed to the Drupal behaviors
* on the content of the dialog. If left empty, the settings will be
* populated automatically from the current request.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_open_modal_dialog($title, $content, array $dialog_options = array(), $settings = NULL) {
$dialog_options['modal'] = TRUE;
$dialog_options += array('title' => $title);
if (is_array($content)) {
$html = drupal_render($content);
$content = $html;
}
// For consistency ensure the modal option is set to TRUE or FALSE.
$dialog_options['modal'] = isset($dialog_options['modal']) && $dialog_options['modal'];
return array(
'command' => 'openDialog',
'selector' => '#drupal-modal',
'settings' => $settings,
'data' => $content,
'dialogOptions' => $dialog_options,
);
}
/**
* Creates a Drupal Ajax 'set dialog option' command.
*
* @param string $selector
* The selector of the dialog whose title will be set. If set to an empty
* value, the default modal dialog will be selected.
* @param string $option_name
* The name of the option to set. May be any jQuery UI dialog option.
* See http://api.jqueryui.com/dialog.
* @param mixed $option_value
* The value of the option to be passed to the dialog.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_set_dialog_option($selector, $option_name, $option_value) {
return array(
'command' => 'setDialogOption',
'selector' => $selector ? $selector : '#drupal-modal',
'optionName' => $option_name,
'optionValue' => $option_value,
);
}
/**
* Creates a Drupal Ajax 'set dialog title' command.
*
* @param string $selector
* The selector of the dialog whose title will be set. If set to an empty
* value, the default modal dialog will be selected.
* @param string $title
* The title that will be set on the dialog.
*
* @return
* An array suitable for use with the ajax_render() function.
*/
function entity_embed_command_set_dialog_title($selector, $title) {
return array(
'command' => 'setDialogOption',
'selector' => $selector ? $selector : '#drupal-modal',
'optionName' => 'title',
'optionValue' => $title,
);
}
/**
* Creates a Drupal Ajax 'editor dialog save' command.
*
......
/**
* @file
* Extends the Drupal AJAX functionality to integrate the dialog API.
*/
(function ($) {
"use strict";
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');
}
},
/**
* Scan a dialog for any primary buttons and move them to the button area.
*
* @param $dialog
* An jQuery object containing the element that is the dialog target.
* @return
* 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({
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('click').trigger('mouseup');
e.preventDefault();
}
});
});
return buttons;
}
};
/**
* Command to open a dialog.
*/
Drupal.ajax.prototype.commands.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(/^#/, '') + '"/>').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.
*/
Drupal.ajax.prototype.commands.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.
*/
Drupal.ajax.prototype.commands.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.
*/
$(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.
*/
$(window).on('dialog:beforeclose', function (e, dialog, $element) {
$element.off('.dialog');
});
})(jQuery);
/**
* @file
* Adds default classes to buttons for styling purposes.
*/
(function ($) {
"use strict";
$.widget('ui.dialog', $.ui.dialog, {
options: {
buttonClass: 'button',
buttonPrimaryClass: 'button--primary'
},
_createButtons: function () {
var opts = this.options;
var primaryIndex;
var $buttons;
var index, il;
for (index = 0, il = opts.buttons.length; index < il; index += 1) {
if (opts.buttons[index].primary && opts.buttons[index].primary === true) {
primaryIndex = index;
delete opts.buttons[index].primary;
break;
}
}
this._super();
$buttons = this.uiButtonSet.children().addClass(opts.buttonClass);
if (typeof primaryIndex !== 'undefined') {
$buttons.eq(index).addClass(opts.buttonPrimaryClass);
}
}
});
})(jQuery);
/**
* @file
*
* Dialog API inspired by HTML5 dialog element:
* http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
*/
(function ($) {
"use strict";
Drupal.settings.dialog = {
autoOpen: true,
dialogClass: '',
// Drupal-specific extensions: see dialog.jquery-ui.js.
buttonClass: 'button',
buttonPrimaryClass: 'button--primary',
// When using this API directly (when generating dialogs on the client side),
// you may want to override this method and do
// @code
// jQuery(event.target).remove()
// @endcode
// as well, to remove the dialog on closing.
close: function (event) {
Drupal.detachBehaviors(event.target, null, 'unload');
}
};
Drupal.dialog = function (element, options) {
function openDialog(settings) {
settings = $.extend({}, Drupal.settings.dialog, options, settings);
// Trigger a global event to allow scripts to bind events to the dialog.
$(window).trigger('dialog:beforecreate', [dialog, $element, settings]);
$element.dialog(settings);
dialog.open = true;
$(window).trigger('dialog:aftercreate', [dialog, $element, settings]);
}
function closeDialog(value) {
$(window).trigger('dialog:beforeclose', [dialog, $element]);
$element.dialog('close');
dialog.returnValue = value;
dialog.open = false;
$(window).trigger('dialog:afterclose', [dialog, $element]);
}
var undef;
var $element = $(element);
var dialog = {
open: false,
returnValue: undef,
show: function () {
openDialog({modal: false});
},
showModal: function () {
openDialog({modal: true});
},
close: closeDialog
};
return dialog;
};
})(jQuery);
(function ($) {
"use strict";
// autoResize option will turn off resizable and draggable.
Drupal.settings.dialog = $.extend({autoResize: true, maxHeight: '95%'}, Drupal.settings.dialog);
/**
* Resets the current options for positioning.
*
* This is used as a window resize and scroll callback to reposition the
* jQuery UI dialog. Although not a built-in jQuery UI option, this can
* be disabled by setting autoResize: false in the options array when creating
* a new Drupal.dialog().
*/
function resetSize(event) {
var positionOptions = ['width', 'height', 'minWidth', 'minHeight', 'maxHeight', 'maxWidth', 'position'];
var adjustedOptions = {};
var windowHeight = $(window).height();
var option, optionValue, adjustedValue;
for (var n = 0; n < positionOptions.length; n++) {
option = positionOptions[n];
optionValue = event.data.settings[option];