Issue #1870764 by quicksketch, dawehner, frega, larowlan, nod_: Add an ajax command which makes it easy to use the dialog API in complex cases.
parent
ce27c58948
commit
f37b8675d2
|
@ -473,13 +473,8 @@ function ajax_prepare_response($page_callback_result) {
|
|||
// manipulation method is used. The method used is specified by
|
||||
// #ajax['method']. The default method is 'replaceWith', which completely
|
||||
// replaces the old wrapper element and its content with the new HTML.
|
||||
// Since this is the primary response content returned to the client, we
|
||||
// also attach the page title. It is up to client code to determine if and
|
||||
// how to display that. For example, if the requesting element is configured
|
||||
// to display the response in a dialog (via #ajax['dialog']), it can use
|
||||
// this for the dialog title.
|
||||
$html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result);
|
||||
$commands[] = ajax_command_insert(NULL, $html) + array('title' => drupal_get_title());
|
||||
$commands[] = ajax_command_insert(NULL, $html);
|
||||
// Add the status messages inside the new content's wrapper element, so that
|
||||
// on subsequent Ajax requests, it is treated as old content.
|
||||
$commands[] = ajax_command_prepend(NULL, theme('status_messages'));
|
||||
|
@ -594,9 +589,6 @@ function ajax_pre_render_element($element) {
|
|||
if (isset($element['#ajax']['event'])) {
|
||||
$element['#attached']['library'][] = array('system', 'jquery.form');
|
||||
$element['#attached']['library'][] = array('system', 'drupal.ajax');
|
||||
if (!empty($element['#ajax']['dialog'])) {
|
||||
$element['#attached']['library'][] = array('system', 'drupal.dialog');
|
||||
}
|
||||
|
||||
$settings = $element['#ajax'];
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\CloseDialogCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command that closes the current active dialog.
|
||||
*/
|
||||
class CloseDialogCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* A CSS selector string of the dialog to close.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
/**
|
||||
* Constructs a CloseDialogCommand object.
|
||||
*
|
||||
* @param string $selector
|
||||
* A CSS selector string of the dialog to close.
|
||||
*/
|
||||
public function __construct($selector = NULL) {
|
||||
$this->selector = $selector ? $selector : '#drupal-modal';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Ajax\CommandInterface::render().
|
||||
*/
|
||||
public function render() {
|
||||
return array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => $this->selector,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\CloseModalDialogCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command that closes the currently visible modal dialog.
|
||||
*/
|
||||
class CloseModalDialogCommand extends CloseDialogCommand {
|
||||
/**
|
||||
* Constructs a CloseModalDialogCommand object.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->selector = '#drupal-modal';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\OpenDialogCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\CommandInterface;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command to open certain content in a dialog.
|
||||
*/
|
||||
class OpenDialogCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* The selector of the dialog.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
/**
|
||||
* The title of the dialog.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* HTML content that will placed in the dialog.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $html;
|
||||
|
||||
/**
|
||||
* Stores dialog-specific options passed directly to jQuery UI dialogs. Any
|
||||
* jQuery UI option can be used. See http://api.jqueryui.com/dialog.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dialogOptions;
|
||||
|
||||
/**
|
||||
* Custom settings that will be passed to the Drupal behaviors on the content
|
||||
* of the dialog.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Constructs an OpenDialogCommand object.
|
||||
*
|
||||
* @param string $selector
|
||||
* The selector of the dialog.
|
||||
* @param string $title
|
||||
* The title of the dialog.
|
||||
* @param string $html
|
||||
* HTML that will be placed in the dialog.
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($selector, $title, $html, array $dialog_options = array(), $settings = NULL) {
|
||||
$dialog_options += array('title' => $title);
|
||||
$this->selector = $selector;
|
||||
$this->html = $html;
|
||||
$this->dialogOptions = $dialog_options;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dialog options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDialogOptions() {
|
||||
return $this->dialogOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dialog options array.
|
||||
*
|
||||
* @param array $dialog_options
|
||||
* Options to be passed to the dialog implementation. Any jQuery UI option
|
||||
* can be used. See http://api.jqueryui.com/dialog.
|
||||
*/
|
||||
public function setDialogOptions($dialog_options) {
|
||||
$this->dialogOptions = $dialog_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a single dialog option value.
|
||||
*
|
||||
* @param string $key
|
||||
* Key of the dialog option. Any jQuery UI option can be used.
|
||||
* See http://api.jqueryui.com/dialog.
|
||||
* @param mixed $value
|
||||
* Option to be passed to the dialog implementation.
|
||||
*/
|
||||
public function setDialogOption($key, $value) {
|
||||
$this->dialogOptions[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dialog title (an alias of setDialogOptions).
|
||||
*
|
||||
* @param string $title
|
||||
* The new title of the dialog.
|
||||
*/
|
||||
public function setDialogTitle($title) {
|
||||
$this->setDialogOptions('title', $title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Ajax\CommandInterface:render().
|
||||
*/
|
||||
public function render() {
|
||||
// Add the library for handling the dialog in the response.
|
||||
drupal_add_library('system', 'drupal.dialog.ajax');
|
||||
|
||||
// For consistency ensure the modal option is set to TRUE or FALSE.
|
||||
$this->dialogOptions['modal'] = isset($this->dialogOptions['modal']) && $this->dialogOptions['modal'];
|
||||
return array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => $this->selector,
|
||||
'settings' => $this->settings,
|
||||
'data' => $this->html,
|
||||
'dialogOptions' => $this->dialogOptions,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\OpenModalDialogCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\OpenDialogCommand;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command to open certain content in a dialog in a modal dialog.
|
||||
*/
|
||||
class OpenModalDialogCommand extends OpenDialogCommand {
|
||||
/**
|
||||
* Constructs an OpenModalDialog object.
|
||||
*
|
||||
* The modal dialog differs from the normal modal provided by
|
||||
* OpenDialogCommand 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 $html
|
||||
* HTML that will be placed in the dialog.
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($title, $html, array $dialog_options = array(), $settings = NULL) {
|
||||
$dialog_options['modal'] = TRUE;
|
||||
parent::__construct('#drupal-modal', $title, $html, $dialog_options, $settings);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\RedirectCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\CommandInterface;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command to set the window.location, loading that URL.
|
||||
*/
|
||||
class RedirectCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* The URL that will be loaded into window.location.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* Constructs an RedirectCommand object.
|
||||
*
|
||||
* @param string $url
|
||||
* The URL that will be loaded into window.location. This should be a full
|
||||
* URL, one that has already been run through the url() function.
|
||||
*/
|
||||
public function __construct($url) {
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Ajax\CommandInterface:render().
|
||||
*/
|
||||
public function render() {
|
||||
return array(
|
||||
'command' => 'redirect',
|
||||
'url' => $this->url,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\SetDialogOptionCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command that sets jQuery UI dialog properties.
|
||||
*/
|
||||
class SetDialogOptionCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* A CSS selector string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
/**
|
||||
* A jQuery UI dialog option name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $optionName;
|
||||
|
||||
/**
|
||||
* A jQuery UI dialog option value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $optionValue;
|
||||
|
||||
/**
|
||||
* Constructs a SetDialogOptionCommand object.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($selector, $option_name, $option_value) {
|
||||
$this->selector = $selector ? $selector : '#drupal-modal';
|
||||
$this->optionName = $option_name;
|
||||
$this->optionValue = $option_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Ajax\CommandInterface::render().
|
||||
*/
|
||||
public function render() {
|
||||
return array(
|
||||
'command' => 'setDialogOption',
|
||||
'selector' => $this->selector,
|
||||
'optionName' => $this->optionName,
|
||||
'optionValue' => $this->optionValue,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\SetDialogTitleCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\SetDialogOptionCommand;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command that sets jQuery UI dialog properties.
|
||||
*/
|
||||
class SetDialogTitleCommand extends SetDialogOptionCommand {
|
||||
|
||||
/**
|
||||
* Constructs a SetDialogTitleCommand object.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($selector, $title) {
|
||||
$this->selector = $selector ? $selector : '#drupal-modal';
|
||||
$this->optionName = 'title';
|
||||
$this->optionValue = $title;
|
||||
}
|
||||
}
|
|
@ -126,15 +126,6 @@ Drupal.ajax = function (base, element, element_settings) {
|
|||
this.wrapper = '#' + this.wrapper;
|
||||
}
|
||||
|
||||
// For Ajax responses that are wanted in a dialog, use the needed method.
|
||||
// If wanted in a modal dialog, also use the needed wrapper.
|
||||
if (this.dialog) {
|
||||
this.method = 'html';
|
||||
if (this.dialog.modal) {
|
||||
this.wrapper = '#drupal-modal';
|
||||
}
|
||||
}
|
||||
|
||||
this.element = element;
|
||||
this.element_settings = element_settings;
|
||||
|
||||
|
@ -561,19 +552,6 @@ Drupal.ajax.prototype.commands = {
|
|||
// Add the new content to the page.
|
||||
wrapper[method](new_content);
|
||||
|
||||
// If the requesting object wanted the response in a dialog, open that
|
||||
// dialog. However, a single server response can include multiple insert
|
||||
// commands (e.g., one for the primary content and another one for status
|
||||
// messages), but we only want to open the dialog once, so we assume that
|
||||
// only commands with a title property are dialog eligible.
|
||||
// @todo Consider whether this is overloading title inappropriately, and
|
||||
// if so, find another way to determine dialog eligibility.
|
||||
if (ajax.dialog && ('title' in response)) {
|
||||
var dialogOptions = $.extend({title: response.title}, ajax.dialog);
|
||||
var dialog = Drupal.dialog(wrapper, dialogOptions);
|
||||
ajax.dialog.modal ? dialog.showModal() : dialog.show();
|
||||
}
|
||||
|
||||
// Immediately hide the new content if we're using any effects.
|
||||
if (effect.showEffect !== 'show') {
|
||||
new_content.hide();
|
||||
|
@ -628,6 +606,13 @@ Drupal.ajax.prototype.commands = {
|
|||
window.alert(response.text, response.title);
|
||||
},
|
||||
|
||||
/**
|
||||
* Command to set the window.location, redirecting the browser.
|
||||
*/
|
||||
redirect: function (ajax, response, status) {
|
||||
window.location = response.url;
|
||||
},
|
||||
|
||||
/**
|
||||
* Command to provide the jQuery css() function.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* @file
|
||||
* Extends the Drupal AJAX functionality to integrate the dialog API.
|
||||
*/
|
||||
|
||||
(function ($, Drupal) {
|
||||
|
||||
"use strict";
|
||||
|
||||
Drupal.behaviors.dialog = {
|
||||
attach: function () {
|
||||
// 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) {
|
||||
$('<div id="drupal-modal" />').hide().appendTo('body');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// Open the dialog itself.
|
||||
response.dialogOptions = response.dialogOptions || {};
|
||||
var dialog = Drupal.dialog($dialog, response.dialogOptions);
|
||||
if (response.dialogOptions.modal) {
|
||||
dialog.showModal();
|
||||
}
|
||||
else {
|
||||
dialog.show();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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).close();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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, Drupal);
|
|
@ -16,17 +16,6 @@ drupalSettings.dialog = {
|
|||
}
|
||||
};
|
||||
|
||||
Drupal.behaviors.dialog = {
|
||||
attach: function () {
|
||||
// Provide a known 'drupal-modal' dom element for Drupal code to use for
|
||||
// modal dialogs. Since there can be multiple non-modal dialogs at a time,
|
||||
// it is the responsibility of calling code to create the elements it needs.
|
||||
if (!$('#drupal-modal').length) {
|
||||
$('<div id="drupal-modal" />').hide().appendTo('body');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.dialog = function (element, options) {
|
||||
|
||||
function openDialog (settings) {
|
||||
|
@ -63,22 +52,4 @@ Drupal.dialog = function (element, options) {
|
|||
return dialog;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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, Drupal, drupalSettings);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
|
||||
/**
|
||||
* Helper function to construct the storage changes in a configuration synchronization form.
|
||||
|
@ -37,6 +39,9 @@ function config_admin_sync_form(array &$form, array &$form_state, StorageInterfa
|
|||
return $form;
|
||||
}
|
||||
|
||||
// Add the AJAX library to the form for dialog support.
|
||||
$form['#attached']['library'][] = array('system', 'drupal.ajax');
|
||||
|
||||
foreach ($config_changes as $config_change_type => $config_files) {
|
||||
if (empty($config_files)) {
|
||||
continue;
|
||||
|
@ -70,7 +75,9 @@ function config_admin_sync_form(array &$form, array &$form_state, StorageInterfa
|
|||
$links['view_diff'] = array(
|
||||
'title' => t('View differences'),
|
||||
'href' => 'admin/config/development/sync/diff/' . $config_file,
|
||||
'ajax' => array('dialog' => array('modal' =>TRUE, 'width' => '700px')),
|
||||
'attributes' => array(
|
||||
'class' => array('use-ajax'),
|
||||
),
|
||||
);
|
||||
$form[$config_change_type]['list']['#rows'][] = array(
|
||||
'name' => $config_file,
|
||||
|
@ -149,12 +156,6 @@ function config_admin_diff_page($config_file) {
|
|||
// Add the CSS for the inline diff.
|
||||
$output['#attached']['css'][] = drupal_get_path('module', 'system') . '/system.diff.css';
|
||||
|
||||
$output['title'] = array(
|
||||
'#theme' => 'html_tag',
|
||||
'#tag' => 'h3',
|
||||
'#value' => t('View changes of @config_file', array('@config_file' => $config_file)),
|
||||
);
|
||||
|
||||
$diff = config_diff($target_storage, $source_storage, $config_file);
|
||||
$formatter = new DrupalDiffFormatter();
|
||||
$formatter->show_header = FALSE;
|
||||
|
@ -175,10 +176,31 @@ function config_admin_diff_page($config_file) {
|
|||
'#type' => 'link',
|
||||
'#title' => "Back to 'Synchronize configuration' page.",
|
||||
'#href' => 'admin/config/development/sync',
|
||||
'#attributes' => array(
|
||||
'class' => array('dialog-cancel'),
|
||||
),
|
||||
);
|
||||
|
||||
$title = t('View changes of @config_file', array('@config_file' => $config_file));
|
||||
|
||||
// Return AJAX requests as a dialog.
|
||||
// @todo: Set up separate content callbacks for the non-JS and dialog versions
|
||||
// of this page using the router system. See http://drupal.org/node/1944472.
|
||||
if (Drupal::service('request')->isXmlHttpRequest()) {
|
||||
// Add class to the close link.
|
||||
$output['back']['#attributes']['class'][] = 'dialog-cancel';
|
||||
|
||||
$dialog_content = drupal_render($output);
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new OpenModalDialogCommand($title, $dialog_content, array('width' => '700')));
|
||||
return $response;
|
||||
}
|
||||
// Otherwise show the page title as an element.
|
||||
else {
|
||||
$output['title'] = array(
|
||||
'#theme' => 'html_tag',
|
||||
'#tag' => 'h3',
|
||||
'#value' => $title,
|
||||
'#weight' => -10,
|
||||
);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Tests\Ajax;
|
||||
|
||||
use Drupal\simpletest\UnitTestBase;
|
||||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
use Drupal\Core\Ajax\AddCssCommand;
|
||||
use Drupal\Core\Ajax\AfterCommand;
|
||||
use Drupal\Core\Ajax\AlertCommand;
|
||||
|
@ -24,11 +24,18 @@ use Drupal\Core\Ajax\RemoveCommand;
|
|||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Ajax\RestripeCommand;
|
||||
use Drupal\Core\Ajax\SettingsCommand;
|
||||
use Drupal\Core\Ajax\OpenDialogCommand;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
use Drupal\Core\Ajax\CloseModalDialogCommand;
|
||||
use Drupal\Core\Ajax\SetDialogOptionCommand;
|
||||
use Drupal\Core\Ajax\SetDialogTitleCommand;
|
||||
use Drupal\Core\Ajax\RedirectCommand;
|
||||
|
||||
/**
|
||||
* Tests for all AJAX Commands.
|
||||
*/
|
||||
class AjaxCommandsUnitTest extends UnitTestBase {
|
||||
class AjaxCommandsUnitTest extends DrupalUnitTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
@ -305,5 +312,121 @@ class AjaxCommandsUnitTest extends UnitTestBase {
|
|||
$this->assertEqual($command->render(), $expected, 'SettingsCommand::render() returns a proper array.');
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Tests that OpenDialogCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testOpenDialogCommand() {
|
||||
$command = new OpenDialogCommand('#some-dialog', 'Title', '<p>Text!</p>', array(
|
||||
'url' => FALSE,
|
||||
'width' => 500,
|
||||
));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#some-dialog',
|
||||
'settings' => NULL,
|
||||
'data' => '<p>Text!</p>',
|
||||
'dialogOptions' => array(
|
||||
'url' => FALSE,
|
||||
'width' => 500,
|
||||
'title' => 'Title',
|
||||
'modal' => FALSE,
|
||||
),
|
||||
);
|
||||
$this->assertEqual($command->render(), $expected, 'OpenDialogCommand::render() returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that OpenModalDialogCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testOpenModalDialogCommand() {
|
||||
$command = new OpenModalDialogCommand('Title', '<p>Text!</p>', array(
|
||||
'url' => 'example',
|
||||
'width' => 500,
|
||||
));
|
||||
|
||||
$expected = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#drupal-modal',
|
||||
'settings' => NULL,
|
||||
'data' => '<p>Text!</p>',
|
||||
'dialogOptions' => array(
|
||||
'url' => 'example',
|
||||
'width' => 500,
|
||||
'title' => 'Title',
|
||||
'modal' => TRUE,
|
||||
),
|
||||
);
|
||||
$this->assertEqual($command->render(), $expected, 'OpenModalDialogCommand::render() returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that CloseModalDialogCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testCloseModalDialogCommand() {
|
||||
$command = new CloseModalDialogCommand();
|
||||
$expected = array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => '#drupal-modal',
|
||||
);
|
||||
|
||||
$this->assertEqual($command->render(), $expected, 'CloseModalDialogCommand::render() returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that CloseDialogCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testCloseDialogCommand() {
|
||||
$command = new CloseDialogCommand('#some-dialog');
|
||||
$expected = array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => '#some-dialog',
|
||||
);
|
||||
|
||||
$this->assertEqual($command->render(), $expected, 'CloseDialogCommand::render() with a selector returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that SetDialogOptionCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testSetDialogOptionCommand() {
|
||||
$command = new SetDialogOptionCommand('#some-dialog', 'width', '500');
|
||||
$expected = array(
|
||||
'command' => 'setDialogOption',
|
||||
'selector' => '#some-dialog',
|
||||
'optionName' => 'width',
|
||||
'optionValue' => '500',
|
||||
);
|
||||
|
||||
$this->assertEqual($command->render(), $expected, 'SetDialogOptionCommand::render() with a selector returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that SetDialogTitleCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testSetDialogTitleCommand() {
|
||||
$command = new SetDialogTitleCommand('#some-dialog', 'Example');
|
||||
$expected = array(
|
||||
'command' => 'setDialogOption',
|
||||
'selector' => '#some-dialog',
|
||||
'optionName' => 'title',
|
||||
'optionValue' => 'Example',
|
||||
);
|
||||
|
||||
$this->assertEqual($command->render(), $expected, 'SetDialogTitleCommand::render() with a selector returns a proper array.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that RedirectCommand objects can be constructed and rendered.
|
||||
*/
|
||||
function testRedirectCommand() {
|
||||
$command = new RedirectCommand('http://example.com');
|
||||
$expected = array(
|
||||
'command' => 'redirect',
|
||||
'url' => 'http://example.com',
|
||||
);
|
||||
|
||||
$this->assertEqual($command->render(), $expected, 'RedirectCommand::render() with the expected command array.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,20 +13,87 @@ namespace Drupal\system\Tests\Ajax;
|
|||
class DialogTest extends AjaxTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Dialog',
|
||||
'description' => 'Performs tests on #ajax[\'dialog\'].',
|
||||
'name' => 'AJAX dialogs commands',
|
||||
'description' => 'Performs tests on opening and manipulating dialogs via AJAX commands.',
|
||||
'group' => 'AJAX',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure elements with #ajax['dialog'] render correctly.
|
||||
* Test sending non-JS and AJAX requests to open and manipulate modals.
|
||||
*/
|
||||
function testDialog() {
|
||||
// Ensure the elements render without notices or exceptions.
|
||||
$this->drupalGet('ajax-test/dialog');
|
||||
|
||||
// @todo What else should we assert?
|
||||
// Set up variables for this test.
|
||||
$dialog_renderable = ajax_test_dialog_contents();
|
||||
$dialog_contents = drupal_render($dialog_renderable);
|
||||
$modal_expected_response = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#drupal-modal',
|
||||
'settings' => NULL,
|
||||
'data' => $dialog_contents,
|
||||
'dialogOptions' => array(
|
||||
'modal' => true,
|
||||
'title' => 'AJAX Dialog',
|
||||
),
|
||||
);
|
||||
$normal_expected_response = array(
|
||||
'command' => 'openDialog',
|
||||
'selector' => '#ajax-test-dialog-wrapper-1',
|
||||
'settings' => NULL,
|
||||
'data' => $dialog_contents,
|
||||
'dialogOptions' => array(
|
||||
'modal' => false,
|
||||
'title' => 'AJAX Dialog',
|
||||
),
|
||||
);
|
||||
$close_expected_response = array(
|
||||
'command' => 'closeDialog',
|
||||
'selector' => '#ajax-test-dialog-wrapper-1',
|
||||
);
|
||||
|
||||
// Check that requesting a modal dialog without JS goes to a page.
|
||||
$this->drupalGet('ajax-test/dialog-contents/nojs/1');
|
||||
$this->assertRaw($dialog_contents, 'Non-JS modal dialog page present.');
|
||||
|
||||
// Emulate going to the JS version of the page and check the JSON response.
|
||||
$ajax_result = $this->drupalGetAJAX('ajax-test/dialog-contents/ajax/1');
|
||||
$this->assertEqual($modal_expected_response, $ajax_result[1], 'Modal dialog JSON response matches.');
|
||||
|
||||
// Check that requesting a "normal" dialog without JS goes to a page.
|
||||
$this->drupalGet('ajax-test/dialog-contents/nojs');
|
||||
$this->assertRaw($dialog_contents, 'Non-JS normal dialog page present.');
|
||||
|
||||
// Emulate going to the JS version of the page and check the JSON response.
|
||||
$ajax_result = $this->drupalGetAJAX('ajax-test/dialog-contents/ajax');
|
||||
$this->assertEqual($normal_expected_response, $ajax_result[1], 'Normal dialog JSON response matches.');
|
||||
|
||||
// Emulate closing the dialog via an AJAX request. There is no non-JS
|
||||
// version of this test.
|
||||
$ajax_result = $this->drupalGetAJAX('ajax-test/dialog-close');
|
||||
$this->assertEqual($close_expected_response, $ajax_result[0], 'Close dialog JSON response matches.');
|
||||
|
||||
// Test submitting via a POST request through the button for modals. This
|
||||
// approach more accurately reflects the real responses by Drupal because
|
||||
// all of the necessary page variables are emulated.
|
||||
$ajax_result = $this->drupalPostAJAX('ajax-test/dialog', array(), 'button1');
|
||||
|
||||
// Check that CSS and JavaScript are "added" to the page dynamically.
|
||||
$dialog_css_exists = strpos($ajax_result[1]['data'], 'jquery.ui.dialog.css') !== FALSE;
|
||||
$this->assertTrue($dialog_css_exists, 'jQuery UI dialog CSS added to the page.');
|
||||
$dialog_js_exists = strpos($ajax_result[2]['data'], 'jquery.ui.dialog.js') !== FALSE;
|
||||
$this->assertTrue($dialog_css_exists, 'jQuery UI dialog JS added to the page.');
|
||||
$dialog_js_exists = strpos($ajax_result[2]['data'], 'dialog.ajax.js') !== FALSE;
|
||||
$this->assertTrue($dialog_css_exists, 'Drupal dialog JS added to the page.');
|
||||
|
||||
// Check that the response matches the expected value.
|
||||
$this->assertEqual($modal_expected_response, $ajax_result[3], 'POST request modal dialog JSON response matches.');
|
||||
|
||||
// Abbreviated test for "normal" dialogs, testing only the difference.
|
||||
$ajax_result = $this->drupalPostAJAX('ajax-test/dialog', array(), 'button2');
|
||||
$this->assertEqual($normal_expected_response, $ajax_result[3], 'POST request normal dialog JSON response matches.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,12 +35,6 @@ class FrameworkTest extends AjaxTestBase {
|
|||
$commands = $this->drupalGetAJAX('ajax-test/render');
|
||||
$expected = new SettingsCommand(array('ajax' => 'test'), TRUE);
|
||||
$this->assertCommand($commands, $expected->render(), 'ajax_render() loads settings added with drupal_add_js().');
|
||||
|
||||
// Verify that JavaScript settings are loaded for #type 'link'.
|
||||
$this->drupalGet('ajax-test/link');
|
||||
$settings = $this->drupalGetSettings();
|
||||
$this->assertEqual($settings['ajax']['ajax-link']['url'], url('filter/tips'));
|
||||
$this->assertEqual($settings['ajax']['ajax-link']['wrapper'], 'block-system-main');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1242,6 +1242,7 @@ function system_library_info() {
|
|||
array('system', 'drupal'),
|
||||
array('system', 'drupalSettings'),
|
||||
array('system', 'drupal.progress'),
|
||||
array('system', 'jquery.once'),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1305,6 +1306,22 @@ function system_library_info() {
|
|||
),
|
||||
);
|
||||
|
||||
// Drupal's integration between AJAX and dialogs.
|
||||
$libraries['drupal.dialog.ajax'] = array(
|
||||
'title' => 'Drupal Dialog AJAX',
|
||||
'version' => VERSION,
|
||||
'js' => array(
|
||||
'core/misc/dialog.ajax.js' => array('group' => JS_LIBRARY, 'weight' => 3),
|
||||
),
|
||||
'dependencies' => array(
|
||||
array('system', 'jquery'),
|
||||
array('system', 'drupal'),
|
||||
array('system', 'drupalSettings'),
|
||||
array('system', 'drupal.ajax'),
|
||||
array('system', 'drupal.dialog'),
|
||||
),
|
||||
);
|
||||
|
||||
// Drupal's states library.
|
||||
$libraries['drupal.states'] = array(
|
||||
'title' => 'Drupal states',
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\OpenDialogCommand;
|
||||
use Drupal\Core\Ajax\OpenModalDialogCommand;
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
use Drupal\Core\Ajax\HtmlCommand;
|
||||
|
||||
/**
|
||||
|
@ -31,11 +34,6 @@ function ajax_test_menu() {
|
|||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['ajax-test/link'] = array(
|
||||
'title' => 'AJAX Link',
|
||||
'page callback' => 'ajax_test_link',
|
||||
'access callback' => TRUE,
|
||||
);
|
||||
$items['ajax-test/dialog'] = array(
|
||||
'title' => 'AJAX Dialog',
|
||||
'page callback' => 'ajax_test_dialog',
|
||||
|
@ -46,6 +44,12 @@ function ajax_test_menu() {
|
|||
'page callback' => 'ajax_test_dialog_contents',
|
||||
'access callback' => TRUE,
|
||||
);
|
||||
$items['ajax-test/dialog-close'] = array(
|
||||
'title' => 'AJAX Dialog close',
|
||||
'page callback' => 'ajax_test_dialog_close',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
@ -101,21 +105,6 @@ function ajax_test_error() {
|
|||
return array('#type' => 'ajax', '#error' => $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: Renders a #type link with #ajax.
|
||||
*/
|
||||
function ajax_test_link() {
|
||||
$build['link'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => 'Show help',
|
||||
'#href' => 'filter/tips',
|
||||
'#ajax' => array(
|
||||
'wrapper' => 'block-system-main',
|
||||
),
|
||||
);
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: Renders a form elements and links with #ajax['dialog'].
|
||||
*/
|
||||
|
@ -131,10 +120,8 @@ function ajax_test_dialog() {
|
|||
$build['link'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => 'Link 1 (modal)',
|
||||
'#href' => 'ajax-test/dialog-contents',
|
||||
'#ajax' => array(
|
||||
'dialog' => array('modal' => TRUE),
|
||||
),
|
||||
'#href' => 'ajax-test/dialog-contents/nojs/1',
|
||||
'#attributes' => array('class' => array('use-ajax')),
|
||||
);
|
||||
|
||||
// Dialog behavior applied to links rendered by theme_links().
|
||||
|
@ -143,18 +130,18 @@ function ajax_test_dialog() {
|
|||
'#links' => array(
|
||||
'link2' => array(
|
||||
'title' => 'Link 2 (modal)',
|
||||
'href' => 'ajax-test/dialog-contents',
|
||||
'ajax' => array(
|
||||
'dialog' => array('modal' => TRUE),
|
||||
),
|
||||
'href' => 'ajax-test/dialog-contents/nojs/1',
|
||||
'attributes' => array('class' => array('use-ajax')),
|
||||
),
|
||||
'link3' => array(
|
||||
'title' => 'Link 3 (non-modal)',
|
||||
'href' => 'ajax-test/dialog-contents',
|
||||
'ajax' => array(
|
||||
'dialog' => array(),
|
||||
'wrapper' => 'ajax-test-dialog-wrapper-2',
|
||||
),
|
||||
'href' => 'ajax-test/dialog-contents/nojs',
|
||||
'attributes' => array('class' => array('use-ajax')),
|
||||
),
|
||||
'link4' => array(
|
||||
'title' => 'Link 4 (close non-modal if open)',
|
||||
'href' => 'ajax-test/dialog-close',
|
||||
'attributes' => array('class' => array('use-ajax')),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -167,35 +154,50 @@ function ajax_test_dialog() {
|
|||
function ajax_test_dialog_form($form, &$form_state) {
|
||||
$form['button1'] = array(
|
||||
'#type' => 'submit',
|
||||
'#name' => 'button1',
|
||||
'#value' => 'Button 1 (modal)',
|
||||
'#ajax' => array(
|
||||
'dialog' => array('modal' => TRUE),
|
||||
'callback' => 'ajax_test_dialog_form_callback_modal',
|
||||
),
|
||||
);
|
||||
$form['button2'] = array(
|
||||
'#type' => 'submit',
|
||||
'#name' => 'button2',
|
||||
'#value' => 'Button 2 (non-modal)',
|
||||
'#ajax' => array(
|
||||
'dialog' => array(),
|
||||
'wrapper' => 'ajax-test-dialog-wrapper-1',
|
||||
'callback' => 'ajax_test_dialog_form_callback_nonmodal',
|
||||
),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for ajax_test_dialog_form().
|
||||
* Non-AJAX behavior of the dialog buttons.
|
||||
*/
|
||||
function ajax_test_dialog_form_submit($form, &$form_state) {
|
||||
$form_state['redirect'] = 'ajax-test/dialog-contents';
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback handler for ajax_test_dialog_form().
|
||||
*/
|
||||
function ajax_test_dialog_form_callback_modal($form, &$form_state) {
|
||||
return ajax_test_dialog_contents('ajax', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback handler for ajax_test_dialog_form().
|
||||
*/
|
||||
function ajax_test_dialog_form_callback_nonmodal($form, &$form_state) {
|
||||
return ajax_test_dialog_contents('ajax', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: Returns the contents for dialogs opened by ajax_test_dialog().
|
||||
*/
|
||||
function ajax_test_dialog_contents() {
|
||||
function ajax_test_dialog_contents($page_mode = 'nojs', $is_modal = 0) {
|
||||
// This is a regular render array; the keys do not have special meaning.
|
||||
return array(
|
||||
$content = array(
|
||||
'content' => array(
|
||||
'#markup' => 'Example message',
|
||||
),
|
||||
|
@ -210,5 +212,30 @@ function ajax_test_dialog_contents() {
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
if ($page_mode === 'ajax') {
|
||||
$response = new AjaxResponse();
|
||||
$title = t('AJAX Dialog');
|
||||
$html = drupal_render($content);
|
||||
if ($is_modal) {
|
||||
$response->addCommand(new OpenModalDialogCommand($title, $html));
|
||||
}
|
||||
else {
|
||||
$selector = '#ajax-test-dialog-wrapper-1';
|
||||
$response->addCommand(new OpenDialogCommand($selector, $title, $html));
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
else {
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: Close the ajax dialog.
|
||||
*/
|
||||
function ajax_test_dialog_close() {
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new CloseDialogCommand('#ajax-test-dialog-wrapper-1'));
|
||||
return $response;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue