From 122c48f0d120b63a02593e6d722a62758b6119ab Mon Sep 17 00:00:00 2001
From: Lauri Eskola <lauri.eskola@acquia.com>
Date: Tue, 22 Feb 2022 14:50:08 +0200
Subject: [PATCH] Issue #3265230 by bnjmnm, Wim Leers: Refactor
 ie11.filter.warnings.es6.js to simpler structure & other improvements

---
 core/modules/ckeditor5/ckeditor5.module       |   7 +-
 .../ckeditor5/js/ie11.filter.warnings.es6.js  | 102 ++++++++----------
 .../ckeditor5/js/ie11.filter.warnings.js      |  52 ++++-----
 3 files changed, 78 insertions(+), 83 deletions(-)

diff --git a/core/modules/ckeditor5/ckeditor5.module b/core/modules/ckeditor5/ckeditor5.module
index f24f30d595ab..cf05c70fcd5d 100644
--- a/core/modules/ckeditor5/ckeditor5.module
+++ b/core/modules/ckeditor5/ckeditor5.module
@@ -292,8 +292,11 @@ function _update_ckeditor5_html_filter(array $form, FormStateInterface $form_sta
   }
 
   // If switching to CKEditor 5 from another editor and there are errors in that
-  // switch, add an error class to the editor select, otherwise remove.
-  $response->addCommand(new InvokeCommand('[data-drupal-selector="edit-editor-editor"]', !$form_state->get('ckeditor5_is_active') && $form_state->get('ckeditor5_is_selected') && !empty($form_state->getErrors()) ? 'addClass' : 'removeClass', ['error']));
+  // switch, add an error class and attribute to the editor select, otherwise
+  // remove.
+  $ckeditor5_selected_but_errors = !$form_state->get('ckeditor5_is_active') && $form_state->get('ckeditor5_is_selected') && !empty($form_state->getErrors());
+  $response->addCommand(new InvokeCommand('[data-drupal-selector="edit-editor-editor"]', $ckeditor5_selected_but_errors ? 'addClass' : 'removeClass', ['error']));
+  $response->addCommand(new InvokeCommand('[data-drupal-selector="edit-editor-editor"]', $ckeditor5_selected_but_errors ? 'attr' : 'removeAttr', ['data-error-switching-to-ckeditor5', TRUE]));
 
   if (!function_exists('_add_attachments_to_editor_update_response')) {
 
diff --git a/core/modules/ckeditor5/js/ie11.filter.warnings.es6.js b/core/modules/ckeditor5/js/ie11.filter.warnings.es6.js
index 1e125d985a70..85e4ed00deb5 100644
--- a/core/modules/ckeditor5/js/ie11.filter.warnings.es6.js
+++ b/core/modules/ckeditor5/js/ie11.filter.warnings.es6.js
@@ -15,10 +15,8 @@
         '(-ms-high-contrast: active), (-ms-high-contrast: none)',
       );
       const editorSelect = once(
-        'editor-select',
-        document.querySelector(
-          '#filter-format-edit-form #edit-editor-editor, #filter-format-add-form #edit-editor-editor',
-        ),
+        'editor-ie11-warning',
+        '[data-drupal-selector="filter-format-edit-form"] [data-drupal-selector="edit-editor-editor"], [data-drupal-selector="filter-format-add-form"] [data-drupal-selector="edit-editor-editor"]',
       );
 
       if (typeof editorSelect[0] !== 'undefined') {
@@ -33,15 +31,16 @@
         );
 
         /**
-         * Adds an IE11 compatibility warning to the message container.
+         * Adds IE11 compatibility warnings to the message container.
          */
-        const ck5Warning = () => {
+        const addIE11Warning = () => {
           selectMessages.add(
             Drupal.t(
               'CKEditor 5 is not compatible with Internet Explorer. Text fields using CKEditor 5 will fall back to plain HTML editing without CKEditor for users of Internet Explorer.',
             ),
             {
               type: 'warning',
+              id: 'ie_11_warning',
             },
           );
           if (isIE11) {
@@ -56,6 +55,7 @@
               ),
               {
                 type: 'error',
+                id: 'ie_11_error',
               },
             );
             editorSettings.hidden = true;
@@ -63,68 +63,60 @@
         };
 
         /**
-         * Adds a warning if the selected editor is ckeditor5, otherwise clears
-         * the message container.
+         * Adds a warning if the selected editor is CKEditor 5, otherwise clears
+         * any existing IE11 warnings.
          */
         const updateWarningStatus = () => {
           if (
             select.value === 'ckeditor5' &&
-            !select.classList.contains('error')
+            !select.hasAttribute('data-error-switching-to-ckeditor5')
           ) {
-            ck5Warning();
+            addIE11Warning();
           } else {
-            editorSettings.hidden = false;
-            selectMessages.clear();
+            if (selectMessages.select('ie_11_warning')) {
+              selectMessages.remove('ie_11_warning');
+            }
+            if (selectMessages.select('ie_11_error')) {
+              selectMessages.remove('ie_11_error');
+            }
           }
         };
 
-        const selectChangeHandler = () => {
-          // Declare the observer first so the observer callback can access it.
-          let editorSelectObserver = null;
+        updateWarningStatus();
 
-          /**
-           * MutationObserver callback for the editor select.
-           *
-           * This listens for the removal 'disabled' attribute on the <select>,
-           * which means the AJAX callback has completed and the form is in a
-           * state suitable for seeing if the IE11 warning is needed.
-           *
-           * @param {Array} mutations
-           *   The element's mutations.
-           */
-          function whenSelectAttributeChanges(mutations) {
-            for (let i = 0; i < mutations.length; i++) {
-              // When the select input is no longer disabled, the AJAX request
-              // is complete and the UI is in a state where it can be determined
-              // if the IE11 warning is needed.
-              if (
-                mutations[i].type === 'attributes' &&
-                mutations[i].attributeName === 'disabled' &&
-                !select.disabled
-              ) {
-                updateWarningStatus();
-                editorSelectObserver.disconnect();
-              }
+        // This observer listens for two different attribute changes that, when
+        // they occur, may require adding or removing the IE11 warnings.
+        // - If the disabled attribute was removed, which is potentially due to
+        //   an AJAX update having completed.
+        // - If the data-error-switching-to-ckeditor5 attribute was removed,
+        //   which means a switch to CKEditor 5 that was previously blocked due
+        //   to validation errors has resumed and completed.
+        const editorSelectObserver = new MutationObserver((mutations) => {
+          for (let i = 0; i < mutations.length; i++) {
+            // When the select input is no longer disabled, the AJAX request
+            // is complete and the UI is in a state where it can be determined
+            // if the ckeditor_stylesheets warning is needed.
+            const switchToCKEditor5Complete =
+              mutations[i].type === 'attributes' &&
+              mutations[i].attributeName === 'disabled' &&
+              !select.disabled;
+            const fixedErrorsPreventingSwitchToCKEditor5 =
+              mutations[i].type === 'attributes' &&
+              mutations[i].attributeName ===
+                'data-error-switching-to-ckeditor5' &&
+              !select.hasAttribute('data-error-switching-to-ckeditor5');
+            if (
+              switchToCKEditor5Complete ||
+              fixedErrorsPreventingSwitchToCKEditor5
+            ) {
+              updateWarningStatus();
             }
           }
+        });
 
-          // An observer is used because during the select change event, it is
-          // not yet known if validation prevented the switch to CKEditor 5.
-          // The IE11 warning should only appear if the switch wasn't prevented
-          // by validation.
-          editorSelectObserver = new MutationObserver(
-            whenSelectAttributeChanges,
-          );
-          editorSelectObserver.observe(select, {
-            attributes: true,
-            attributeOldValue: true,
-          });
-        };
-
-        updateWarningStatus();
-
-        // Listen to text format selection changes.
-        select.addEventListener('change', selectChangeHandler);
+        editorSelectObserver.observe(select, {
+          attributes: true,
+        });
       }
     },
   };
diff --git a/core/modules/ckeditor5/js/ie11.filter.warnings.js b/core/modules/ckeditor5/js/ie11.filter.warnings.js
index 6ebf942c81d0..87284bacfda4 100644
--- a/core/modules/ckeditor5/js/ie11.filter.warnings.js
+++ b/core/modules/ckeditor5/js/ie11.filter.warnings.js
@@ -9,7 +9,7 @@
   Drupal.behaviors.ckEditor5warn = {
     attach: function attach() {
       const isIE11 = Modernizr.mq('(-ms-high-contrast: active), (-ms-high-contrast: none)');
-      const editorSelect = once('editor-select', document.querySelector('#filter-format-edit-form #edit-editor-editor, #filter-format-add-form #edit-editor-editor'));
+      const editorSelect = once('editor-ie11-warning', '[data-drupal-selector="filter-format-edit-form"] [data-drupal-selector="edit-editor-editor"], [data-drupal-selector="filter-format-add-form"] [data-drupal-selector="edit-editor-editor"]');
 
       if (typeof editorSelect[0] !== 'undefined') {
         const select = editorSelect[0];
@@ -18,51 +18,51 @@
         const selectMessages = new Drupal.Message(selectMessageContainer);
         const editorSettings = document.querySelector('#editor-settings-wrapper');
 
-        const ck5Warning = () => {
+        const addIE11Warning = () => {
           selectMessages.add(Drupal.t('CKEditor 5 is not compatible with Internet Explorer. Text fields using CKEditor 5 will fall back to plain HTML editing without CKEditor for users of Internet Explorer.'), {
-            type: 'warning'
+            type: 'warning',
+            id: 'ie_11_warning'
           });
 
           if (isIE11) {
             selectMessages.add(Drupal.t('Text editor toolbar settings are not available in Internet Explorer. They will be available in other <a href="@supported-browsers">supported browsers</a>.', {
               '@supported-browsers': 'https://www.drupal.org/docs/system-requirements/browser-requirements'
             }), {
-              type: 'error'
+              type: 'error',
+              id: 'ie_11_error'
             });
             editorSettings.hidden = true;
           }
         };
 
         const updateWarningStatus = () => {
-          if (select.value === 'ckeditor5' && !select.classList.contains('error')) {
-            ck5Warning();
+          if (select.value === 'ckeditor5' && !select.hasAttribute('data-error-switching-to-ckeditor5')) {
+            addIE11Warning();
           } else {
-            editorSettings.hidden = false;
-            selectMessages.clear();
-          }
-        };
-
-        const selectChangeHandler = () => {
-          let editorSelectObserver = null;
+            if (selectMessages.select('ie_11_warning')) {
+              selectMessages.remove('ie_11_warning');
+            }
 
-          function whenSelectAttributeChanges(mutations) {
-            for (let i = 0; i < mutations.length; i++) {
-              if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'disabled' && !select.disabled) {
-                updateWarningStatus();
-                editorSelectObserver.disconnect();
-              }
+            if (selectMessages.select('ie_11_error')) {
+              selectMessages.remove('ie_11_error');
             }
           }
-
-          editorSelectObserver = new MutationObserver(whenSelectAttributeChanges);
-          editorSelectObserver.observe(select, {
-            attributes: true,
-            attributeOldValue: true
-          });
         };
 
         updateWarningStatus();
-        select.addEventListener('change', selectChangeHandler);
+        const editorSelectObserver = new MutationObserver(mutations => {
+          for (let i = 0; i < mutations.length; i++) {
+            const switchToCKEditor5Complete = mutations[i].type === 'attributes' && mutations[i].attributeName === 'disabled' && !select.disabled;
+            const fixedErrorsPreventingSwitchToCKEditor5 = mutations[i].type === 'attributes' && mutations[i].attributeName === 'data-error-switching-to-ckeditor5' && !select.hasAttribute('data-error-switching-to-ckeditor5');
+
+            if (switchToCKEditor5Complete || fixedErrorsPreventingSwitchToCKEditor5) {
+              updateWarningStatus();
+            }
+          }
+        });
+        editorSelectObserver.observe(select, {
+          attributes: true
+        });
       }
     }
   };
-- 
GitLab