Issue #2765525 by phenaproxima, Wim Leers, droplet: Add AJAX command to add style sheets to CKEditor instances
parent
9d8d1ed77b
commit
6fa5085d66
|
@ -3,7 +3,7 @@
|
|||
* CKEditor implementation of {@link Drupal.editors} API.
|
||||
*/
|
||||
|
||||
(function (Drupal, debounce, CKEDITOR, $, displace) {
|
||||
(function (Drupal, debounce, CKEDITOR, $, displace, AjaxCommands) {
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -318,4 +318,33 @@
|
|||
// Set the CKEditor cache-busting string to the same value as Drupal.
|
||||
CKEDITOR.timestamp = drupalSettings.ckeditor.timestamp;
|
||||
|
||||
})(Drupal, Drupal.debounce, CKEDITOR, jQuery, Drupal.displace);
|
||||
if (AjaxCommands) {
|
||||
|
||||
/**
|
||||
* Command to add style sheets to a CKEditor instance.
|
||||
*
|
||||
* Works for both iframe and inline CKEditor instances.
|
||||
*
|
||||
* @param {Drupal.Ajax} [ajax]
|
||||
* {@link Drupal.Ajax} object created by {@link Drupal.ajax}.
|
||||
* @param {object} response
|
||||
* The response from the Ajax request.
|
||||
* @param {string} response.editor_id
|
||||
* The CKEditor instance ID.
|
||||
* @param {number} [status]
|
||||
* The XMLHttpRequest status.
|
||||
*
|
||||
* @see http://docs.ckeditor.com/#!/api/CKEDITOR.dom.document
|
||||
*/
|
||||
AjaxCommands.prototype.ckeditor_add_stylesheet = function (ajax, response, status) {
|
||||
var editor = CKEDITOR.instances[response.editor_id];
|
||||
|
||||
if (editor) {
|
||||
response.stylesheets.forEach(function (url) {
|
||||
editor.document.appendStyleSheet(url);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
})(Drupal, Drupal.debounce, CKEDITOR, jQuery, Drupal.displace, Drupal.AjaxCommands);
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\CommandInterface;
|
||||
|
||||
/**
|
||||
* AJAX command to add style sheets to a CKEditor instance.
|
||||
*/
|
||||
class AddStyleSheetCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* The CKEditor instance ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $editorId;
|
||||
|
||||
/**
|
||||
* The style sheet URLs to add to the CKEditor instance.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $styleSheets = [];
|
||||
|
||||
/**
|
||||
* AddStyleSheetCommand constructor.
|
||||
*
|
||||
* @param string $editor_id
|
||||
* The CKEditor instance ID.
|
||||
* @param string[] $stylesheets
|
||||
* The style sheet URLs to add to the CKEditor instance.
|
||||
*/
|
||||
public function __construct($editor_id, array $stylesheets = []) {
|
||||
$this->editorId = $editor_id;
|
||||
$this->styleSheets = $stylesheets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a style sheet to the CKEditor instance.
|
||||
*
|
||||
* @param string $stylesheet
|
||||
* The style sheet URL.
|
||||
*
|
||||
* @return $this
|
||||
* The called object, for chaining.
|
||||
*/
|
||||
public function addStyleSheet($stylesheet) {
|
||||
$this->styleSheets[] = $stylesheet;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render() {
|
||||
return [
|
||||
'command' => 'ckeditor_add_stylesheet',
|
||||
'editor_id' => $this->editorId,
|
||||
'stylesheets' => $this->styleSheets,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
ajax_css:
|
||||
js:
|
||||
js/ajax-css.js: {}
|
||||
dependencies:
|
||||
- ckeditor/drupal.ckeditor
|
|
@ -0,0 +1,7 @@
|
|||
ckeditor_test.ajax_css:
|
||||
path: '/ckeditor_test/ajax_css'
|
||||
defaults:
|
||||
_title: 'AJAX CSS Test'
|
||||
_form: '\Drupal\ckeditor_test\Form\AjaxCssForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: red;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @file
|
||||
* Contains client-side code for testing CSS delivered to CKEditor via AJAX.
|
||||
*/
|
||||
|
||||
(function (Drupal, ckeditor, editorSettings, $) {
|
||||
|
||||
'use strict';
|
||||
|
||||
Drupal.behaviors.ajaxCssForm = {
|
||||
|
||||
attach: function (context) {
|
||||
// Initialize an inline CKEditor on the #edit-inline element if it
|
||||
// isn't editable already.
|
||||
$(context)
|
||||
.find('#edit-inline')
|
||||
.not('[contenteditable]')
|
||||
.each(function () {
|
||||
ckeditor.attachInlineEditor(this, editorSettings.formats.test_format);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(Drupal, Drupal.editors.ckeditor, drupalSettings.editor, jQuery);
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor_test\Form;
|
||||
|
||||
use Drupal\ckeditor\Ajax\AddStyleSheetCommand;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* A form for testing delivery of CSS to CKEditor via AJAX.
|
||||
*/
|
||||
class AjaxCssForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ckeditor_test_ajax_css_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// Create an inline and iframe CKEditor instance so we can test against
|
||||
// both.
|
||||
$form['inline'] = [
|
||||
'#type' => 'container',
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'ckeditor_test/ajax_css',
|
||||
],
|
||||
],
|
||||
'#children' => $this->t('Here be dragons.'),
|
||||
];
|
||||
$form['iframe'] = [
|
||||
'#type' => 'text_format',
|
||||
'#default_value' => $this->t('Here be llamas.'),
|
||||
];
|
||||
|
||||
// A pair of buttons to trigger the AJAX events.
|
||||
$form['actions'] = [
|
||||
'css_inline' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Add CSS to inline CKEditor instance'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'addCssInline'],
|
||||
],
|
||||
],
|
||||
'css_frame' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Add CSS to iframe CKEditor instance'),
|
||||
'#ajax' => [
|
||||
'callback' => [$this, 'addCssIframe'],
|
||||
],
|
||||
],
|
||||
'#type' => 'actions',
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an AJAX response to add CSS to a CKEditor Text Editor instance.
|
||||
*
|
||||
* @param string $editor_id
|
||||
* The Text Editor instance ID.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* An AJAX response.
|
||||
*/
|
||||
protected function generateResponse($editor_id) {
|
||||
// Build a URL to the style sheet that will be added.
|
||||
$url = drupal_get_path('module', 'ckeditor_test') . '/css/test.css';
|
||||
$url = file_create_url($url);
|
||||
$url = file_url_transform_relative($url);
|
||||
|
||||
$response = new AjaxResponse();
|
||||
return $response
|
||||
->addCommand(new AddStyleSheetCommand($editor_id, [$url]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the AJAX request to add CSS to the inline editor.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* An AJAX response.
|
||||
*/
|
||||
public function addCssInline() {
|
||||
return $this->generateResponse('edit-inline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the AJAX request to add CSS to the iframe editor.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
* An AJAX response.
|
||||
*/
|
||||
public function addCssIframe() {
|
||||
return $this->generateResponse('edit-iframe-value');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\ckeditor\FunctionalJavascript;
|
||||
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
|
||||
/**
|
||||
* Tests delivery of CSS to CKEditor via AJAX.
|
||||
*
|
||||
* @group ckeditor
|
||||
*/
|
||||
class AjaxCssTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['ckeditor', 'ckeditor_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
FilterFormat::create([
|
||||
'format' => 'test_format',
|
||||
'name' => $this->randomMachineName(),
|
||||
])->save();
|
||||
|
||||
Editor::create([
|
||||
'editor' => 'ckeditor',
|
||||
'format' => 'test_format',
|
||||
])->save();
|
||||
|
||||
user_role_grant_permissions('anonymous', ['use text format test_format']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding style sheets dynamically to CKEditor.
|
||||
*/
|
||||
public function testCkeditorAjaxAddCss() {
|
||||
$this->drupalGet('/ckeditor_test/ajax_css');
|
||||
|
||||
$session = $this->getSession();
|
||||
$assert = $this->assertSession();
|
||||
|
||||
$style_color = 'rgb(255, 0, 0)';
|
||||
|
||||
// Add the inline CSS and assert that the style is applied to the main body,
|
||||
// but not the iframe.
|
||||
$session->getPage()->pressButton('Add CSS to inline CKEditor instance');
|
||||
$assert->assertWaitOnAjaxRequest();
|
||||
$this->assertEquals($style_color, $this->getEditorStyle('edit-inline', 'color'));
|
||||
$this->assertNotEquals($style_color, $this->getEditorStyle('edit-iframe-value', 'color'));
|
||||
|
||||
$session->reload();
|
||||
|
||||
// Add the iframe CSS and assert that the style is applied to the iframe,
|
||||
// but not the main body.
|
||||
$session->getPage()->pressButton('Add CSS to iframe CKEditor instance');
|
||||
$assert->assertWaitOnAjaxRequest();
|
||||
$this->assertNotEquals($style_color, $this->getEditorStyle('edit-inline', 'color'));
|
||||
$this->assertEquals($style_color, $this->getEditorStyle('edit-iframe-value', 'color'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a computed style value for a CKEditor instance.
|
||||
*
|
||||
* @param string $instance_id
|
||||
* The CKEditor instance ID.
|
||||
* @param string $attribute
|
||||
* The style attribute.
|
||||
*
|
||||
* @return string
|
||||
* The computed style value.
|
||||
*/
|
||||
protected function getEditorStyle($instance_id, $attribute) {
|
||||
$js = sprintf(
|
||||
'CKEDITOR.instances["%s"].document.getBody().getComputedStyle("%s")',
|
||||
$instance_id,
|
||||
$attribute
|
||||
);
|
||||
return $this->getSession()->evaluateScript($js);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue