CKEDITOR: Scrolling Bug Toolbar
authorSven Schöling <sven.schoeling@opendynamic.de>
Tue, 9 Jun 2020 17:20:53 +0000 (19:20 +0200)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Wed, 16 Feb 2022 11:43:12 +0000 (12:43 +0100)
commit6cdee5e5dacf0ded7f12dd7332883230fc9fc159
treeadc6f42e5bcee895c3c94e9ad2df1ef917f4b1e3
parent80e5d427d5b84534ebb1c903cf9a297509a1949b
CKEDITOR: Scrolling Bug Toolbar

Der Bug ist bekannt bei ckeditor: https://github.com/ckeditor/ckeditor4/issues/3848

Was da passiert ist, dass das Plugin floatingspace, was benutzt wird um
die toolbar zu implementieren, den scroll handler nur auf document.body
macht, nicht aber auf scrollbare fivs, wie bei uns verwendet werden.

Der Fix im Quellcode vom ckeditor ist dann effektiv dieser diff hier:

diff --git a/plugins/floatingspace/plugin.js b/plugins/floatingspace/plugin.js
index 8abbcd61d..65f16025b 100644
--- a/plugins/floatingspace/plugin.js
+++ b/plugins/floatingspace/plugin.js
@ -26,6 +37,7 @@

        function attach( editor ) {
                var config = editor.config,
+               parent = parentScroll(editor.element),

                        // Get the HTML for the predefined spaces.
                        topHtml = editor.fire( 'uiSpace', { space: 'top', html: '' } ).html,
@@ -312,6 +324,7 @@
                                editor.on( 'change', changeBuffer.input );
                                win.on( 'scroll', uiBuffer.input );
                                win.on( 'resize', uiBuffer.input );
+                               parent.forEach(function(element) {
+                                 element.on( 'scroll', uiBuffer.input );
+                               });
                        } );

                        editor.on( 'blur', function() {
@@ -319,11 +332,13 @@
                                editor.removeListener( 'change', changeBuffer.input );
                                win.removeListener( 'scroll', uiBuffer.input );
                                win.removeListener( 'resize', uiBuffer.input );
+                               parent.forEach(function(element) {
+                                 element.removeListener( 'scroll', uiBuffer.input );
+                               });
                        } );

                        editor.on( 'destroy', function() {
                                win.removeListener( 'scroll', uiBuffer.input );
                                win.removeListener( 'resize', uiBuffer.input );
+                               parent.forEach(function(element) {
+                                 element.removeListener( 'scroll', uiBuffer.input );
+                               });
                                floatSpace.clearCustomData();
                                floatSpace.remove();
                        } );

Das sucht sich beim attachen das Ziel Element, sucht sich das/die
parent-Elemente die scrollbar sind, und registrtiert den scroll handler
auf diesen Elementen.

Leider gibt es keine Standardfunktion parentScroll() in javascript. Es
gibt ein Plugin gleichen Namens für jQuery, die Funktion da liefert aber
nur den nächst-höheren div und ausserdem ist jQuery innerhalb von
CKEditor nicht verfügbar. Die hier implementierte Funktion ist identisch
mit dieser hier, die angelehnt ist an das jQuery verhalten, aber pures
Javascript benutzt:

 function parentScroll(e) {
   var position = e.$.getAttribute("position"),
       excludeStaticParent = position === "absolute";
   return e.getParents().filter( function(parent) {
     var style = window.getComputedStyle(parent.$);
     if ( excludeStaticParent && style.position === "static" )
       return false;
     return (/(auto|scroll)/).test( style['overflow'] + style["overflow-y"] + style["overflow-x"] );
   });
 };

Im Gegensatz zum jQuery Plugin macht diese Variante keine Prüfung darauf
ob der Invokant selber "fixed" position hat, und liefert nicht nur
das erste Element sondern alle Treffer. Das Ergebnis ist ein normales
Javascript Array.

Der Code hier ist minified und direkt in unsere Variante injiziert, muss
also beim Upgrade reproduziert werden.

Was hier nicht gefixt ist: Das Repositioning Verhalten von floatingspace
orientiert sich weiter an Body, und nicht (wie eigentlich korrekt) am
umliegenden scrolling div.

(cherry picked from commit b64d03b5506441aa25433c0bb63753f5a126a675)
(cherry-pick von odyn)
js/ckeditor/ckeditor.js