diff --git a/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php b/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
index dd53245..e0687f5 100644
--- a/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
+++ b/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
@@ -116,8 +116,8 @@ function testLoading() {
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
$this->assertTrue(count($body) === 1, 'A body field exists.');
$this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
- $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-body-0-value"]');
- $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
+ $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and @data-editor-for="edit-body-0-value"]');
+ $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has a "data-editor-for" attribute with the correct value.');
$this->assertTrue(in_array('ckeditor/drupal.ckeditor', explode(',', $settings['ajaxPageState']['libraries'])), 'CKEditor glue library is present.');
// Enable the ckeditor_test module, customize configuration. In this case,
diff --git a/core/modules/editor/js/editor.js b/core/modules/editor/js/editor.js
index 022bc9f..9c07810 100644
--- a/core/modules/editor/js/editor.js
+++ b/core/modules/editor/js/editor.js
@@ -14,44 +14,45 @@
* A text format selector DOM element.
*
* @return DOM
- * The text area DOM element.
+ * The text area DOM element, if it was found.
*/
function findFieldForFormatSelector($formatSelector) {
var field_id = $formatSelector.attr('data-editor-for');
+ // This selector will only find text areas in the top-level document. We do
+ // not support attaching editors on text areas within iframes.
return $('#' + field_id).get(0);
}
/**
- * Changes the text editor on the text area for the given text format selector.
+ * Changes the text editor on a text area.
*
- * @param jQuery $formatSelector
- * A text format selector DOM element.
- * @param String activeFormatID
- * The currently active text format; its associated text editor will be
- * detached.
+ * @param DOM field
+ * The text area DOM element.
* @param String newFormatID
- * The text format we're changing to; its associated text editor will be
- * attached.
+ * The text format we're changing to; the text editor for the currently
+ * active text format will be detached, and the text editor for the new text
+ * format will be attached.
*/
- function changeTextEditor($formatSelector, activeFormatID, newFormatID) {
- var originalFormatID = activeFormatID;
- var field = findFieldForFormatSelector($formatSelector);
+ function changeTextEditor(field, newFormatID) {
+ var previousFormatID = field.getAttribute('data-editor-active-text-format');
+
// Detach the current editor (if any) and attach a new editor.
- if (drupalSettings.editor.formats[activeFormatID]) {
- Drupal.editorDetach(field, drupalSettings.editor.formats[activeFormatID]);
+ if (drupalSettings.editor.formats[previousFormatID]) {
+ Drupal.editorDetach(field, drupalSettings.editor.formats[previousFormatID]);
}
// When no text editor is currently active, stop tracking changes.
- else if (!drupalSettings.editor.formats[activeFormatID]) {
+ else {
$(field).off('.editor');
}
- activeFormatID = newFormatID;
// Attach the new text editor (if any).
- if (drupalSettings.editor.formats[activeFormatID]) {
- var format = drupalSettings.editor.formats[activeFormatID];
- filterXssWhenSwitching(field, format, originalFormatID, Drupal.editorAttach);
+ if (drupalSettings.editor.formats[newFormatID]) {
+ var format = drupalSettings.editor.formats[newFormatID];
+ filterXssWhenSwitching(field, format, previousFormatID, Drupal.editorAttach);
}
- $formatSelector.attr('data-editor-active-text-format', newFormatID);
+
+ // Store the new active format.
+ field.setAttribute('data-editor-active-text-format', newFormatID);
}
/**
@@ -61,7 +62,8 @@
*/
function onTextFormatChange(event) {
var $select = $(event.target);
- var activeFormatID = $select.attr('data-editor-active-text-format');
+ var field = event.data.field;
+ var activeFormatID = field.getAttribute('data-editor-active-text-format');
var newFormatID = $select.val();
// Prevent double-attaching if the change event is triggered manually.
@@ -75,7 +77,7 @@
// markup to be stripped away.
var supportContentFiltering = drupalSettings.editor.formats[newFormatID] && drupalSettings.editor.formats[newFormatID].editorSupportsContentFiltering;
// If there is no content yet, it's always safe to change the text format.
- var hasContent = findFieldForFormatSelector($select).value !== '';
+ var hasContent = field.value !== '';
if (hasContent && supportContentFiltering) {
var message = Drupal.t('Changing the text format to %text_format will permanently remove content that is not allowed in that text format.
Save your changes before switching the text format to avoid losing data.', {
'%text_format': $select.find('option:selected').text()
@@ -89,7 +91,7 @@
text: Drupal.t('Continue'),
'class': 'button button--primary',
click: function () {
- changeTextEditor($select, activeFormatID, newFormatID);
+ changeTextEditor(field, newFormatID);
confirmationDialog.close();
}
},
@@ -121,7 +123,7 @@
confirmationDialog.showModal();
}
else {
- changeTextEditor($select, activeFormatID, newFormatID);
+ changeTextEditor(field, newFormatID);
}
}
@@ -140,11 +142,17 @@
return;
}
- $(context).find('.editor').once('editor', function () {
+ $(context).find('[data-editor-for]').once('editor', function () {
var $this = $(this);
- var activeFormatID = $this.val();
- $this.attr('data-editor-active-text-format', activeFormatID);
var field = findFieldForFormatSelector($this);
+ // Opt-out if no supported text area was found.
+ if (!field) {
+ return;
+ }
+
+ // Store the current active format.
+ var activeFormatID = $this.val();
+ field.setAttribute('data-editor-active-text-format', activeFormatID);
// Directly attach this text editor, if the text format is enabled.
if (settings.editor.formats[activeFormatID]) {
@@ -165,7 +173,7 @@
// Attach onChange handler to text format selector element.
if ($this.is('select')) {
- $this.on('change.editorAttach', onTextFormatChange);
+ $this.on('change.editorAttach', { field: field }, onTextFormatChange);
}
// Detach any editor when the containing form is submitted.
$this.parents('form').on('submit', function (event) {
@@ -188,17 +196,17 @@
if (trigger === 'serialize') {
// Removing the editor-processed class guarantees that the editor will
// be reattached. Only do this if we're planning to destroy the editor.
- editors = $(context).find('.editor-processed');
+ editors = $(context).find('.editor-processed[data-editor-for]');
}
else {
- editors = $(context).find('.editor').removeOnce('editor');
+ editors = $(context).find('[data-editor-for]').removeOnce('editor');
}
editors.each(function () {
var $this = $(this);
var activeFormatID = $this.val();
var field = findFieldForFormatSelector($this);
- if (activeFormatID in settings.editor.formats) {
+ if (field && activeFormatID in settings.editor.formats) {
Drupal.editorDetach(field, settings.editor.formats[activeFormatID], trigger);
}
});
diff --git a/core/modules/editor/src/Element.php b/core/modules/editor/src/Element.php
index 934e5e4..a87f3a0 100644
--- a/core/modules/editor/src/Element.php
+++ b/core/modules/editor/src/Element.php
@@ -73,7 +73,6 @@ function preRenderTextFormat(array $element) {
'#name' => $element['format']['format']['#name'],
'#value' => $format_id,
'#attributes' => array(
- 'class' => array('editor'),
'data-editor-for' => $field_id,
),
);
diff --git a/core/modules/editor/src/Tests/EditorLoadingTest.php b/core/modules/editor/src/Tests/EditorLoadingTest.php
index 3a8a374..002ccd3 100644
--- a/core/modules/editor/src/Tests/EditorLoadingTest.php
+++ b/core/modules/editor/src/Tests/EditorLoadingTest.php
@@ -156,8 +156,8 @@ public function testLoading() {
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
$this->assertTrue(count($body) === 1, 'A body field exists.');
$this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
- $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-body-0-value"]');
- $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
+ $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and @data-editor-for="edit-body-0-value"]');
+ $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has a "data-editor-for" attribute with the correct value.');
// Load the editor image dialog form and make sure it does not fatal.
$this->drupalGet('editor/dialog/image/full_html');
@@ -190,8 +190,8 @@ public function testLoading() {
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
$this->assertTrue(count($body) === 1, 'A body field exists.');
$this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page.');
- $hidden_input = $this->xpath('//input[@type="hidden" and @value="plain_text" and contains(@class, "editor") and @data-editor-for="edit-body-0-value"]');
- $this->assertTrue(count($hidden_input) === 1, 'A single text format hidden input exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
+ $hidden_input = $this->xpath('//input[@type="hidden" and @value="plain_text" and @data-editor-for="edit-body-0-value"]');
+ $this->assertTrue(count($hidden_input) === 1, 'A single text format hidden input exists on the page and has a "data-editor-for" attribute with the correct value.');
// Create an "article" node that uses the full_html text format, then try
// to let the untrusted user edit it.