[BUGFIX] Prevent Javascript loop for RTE-enabled fields 60/36860/11
authorStanislas Rolland <typo3@sjbr.ca>
Sat, 14 Feb 2015 18:40:25 +0000 (13:40 -0500)
committerStanislas Rolland <typo3@sjbr.ca>
Mon, 16 Feb 2015 20:19:28 +0000 (21:19 +0100)
Problem: If a collapsed IRRE element with a RTE-enabled field is added,
a JavaScript loop is triggered because of missing widths of the select
fields within the RTE toolbar. This is caused by change in the way IRRE
nested inline elements are made visible using class attribute rather than
display property of style attribute. This also applies to new tab menus.
The change also affects the properties of the nested elements whose
mutations must be observe in order to detect when the RTE iframe becomes
visible.
Solution: Adjust the list of attributes to be observed on nested inline
elements. Adjust also detection of nested elements visibility state as
well as the walk to make them hidden with the visibility property of
the style attribute while the RTE framework is being rendered.

There is also a check added for TYPO3.settings.Textarea that is not
present when RTE fields are hidden by DisplayCond for a child element
that gets expanded/opened.

Releases: master
Resolves: #64930
Change-Id: I6f3bea4e9e72c33f2ae773734e9e6d794fe38ee9
Reviewed-on: http://review.typo3.org/36860
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Stanislas Rolland <typo3@sjbr.ca>
Tested-by: Stanislas Rolland <typo3@sjbr.ca>
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Editor/Iframe.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/HTMLArea/Util/TYPO3.js

index 4dd3534..9355d2b 100644 (file)
@@ -632,7 +632,7 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
         */
        FormEngine.convertTextareasResizable = function() {
                var $elements = $('.t3js-formengine-textarea');
-               if (TYPO3.settings.Textarea.autosize && $elements.length) {
+               if (TYPO3.settings.Textarea && TYPO3.settings.Textarea.autosize && $elements.length) {
                        require(['jquery/jquery.autosize.min'], function() {
                                $elements.autosize();
                        });
index 565570e..e16cf14 100644 (file)
@@ -67,13 +67,13 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Editor/Iframe',
                 * In all browsers, it breaks the evaluation of the framework dimensions
                 */
                initStyleChangeEventListener: function () {
-                       if (this.isNested && !UserAgent.isWebKit) {
+                       if (this.isNested) {
                                if (typeof MutationObserver === 'function') {
                                        var self = this;
                                        this.mutationObserver = new MutationObserver( function (mutations) { self.onNestedShowMutation(mutations); });
                                        var options = {
                                                attributes: true,
-                                               attributeFilter: ['style']
+                                               attributeFilter: ['class', 'style']
                                        };
                                        for (var i = this.nestedParentElements.sorted.length; --i >= 0;) {
                                                var nestedElement = document.getElementById(this.nestedParentElements.sorted[i]);
index 26543e3..6b23e96 100644 (file)
@@ -14,8 +14,9 @@
  * HTMLArea.util.TYPO3: Utility functions for dealing with tabs and inline elements in TYPO3 forms
  ***************************************************/
 define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
-       ['TYPO3/CMS/Rtehtmlarea/HTMLArea/UserAgent/UserAgent'],
-       function (UserAgent) {
+       ['TYPO3/CMS/Rtehtmlarea/HTMLArea/UserAgent/UserAgent',
+       'TYPO3/CMS/Rtehtmlarea/HTMLArea/DOM/DOM'],
+       function (UserAgent, Dom) {
 
        return {
 
@@ -30,7 +31,7 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
                        var i, type, level, elementId, max, simplifiedNested=[],
                                elementIdSuffix = {
                                        tab: '-DIV',
-                                       inline: '_fields',
+                                       inline: '_div',
                                        flex: '-content'
                                };
                        if (nested && nested.length) {
@@ -62,20 +63,27 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
                accessParentElements: function (parentElements, callbackFunc, args) {
                        var result = {};
                        if (parentElements.length) {
-                               var currentElement = parentElements.pop();
-                               currentElement = document.getElementById(currentElement);
-                               var actionRequired = (currentElement.style.display === 'none');
+                               var currentElementId = parentElements.pop();
+                               var currentElement = document.getElementById(currentElementId);
+                               var actionRequired = (currentElementId.indexOf('-DIV') !== -1 && !Dom.hasClass(currentElement, 'active'))
+                                       || (currentElementId.indexOf('_div') !== -1 && !Dom.hasClass(currentElement, 'panel-visible'))
+                                       || (currentElement.style.display === 'none');
                                if (actionRequired) {
                                        var visibility = currentElement.style.visibility;
                                        var position = currentElement.style.position;
                                        var top = currentElement.style.top;
                                        var display = currentElement.style.display;
-                                       var className = currentElement.parentNode.className;
+                                       var className = currentElement.className;
                                        currentElement.style.visibility = 'hidden';
                                        currentElement.style.position = 'absolute';
                                        currentElement.style.top = '-10000px';
                                        currentElement.style.display = '';
-                                       currentElement.parentNode.className = '';
+                                       if (currentElementId.indexOf('-DIV') !== -1) {
+                                               Dom.addClass(currentElement, 'active');
+                                       } else if (currentElementId.indexOf('_div') !== -1) {
+                                               Dom.addClass(currentElement, 'panel-visible');
+                                       }
+                                       currentElement.className = '';
                                }
                                result = this.accessParentElements(parentElements, callbackFunc, args);
                                if (actionRequired) {
@@ -83,7 +91,7 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
                                        currentElement.style.position = position;
                                        currentElement.style.top = top;
                                        currentElement.style.display = display;
-                                       currentElement.parentNode.className = className;
+                                       currentElement.className = className;
                                }
                        } else {
                                result = eval(callbackFunc);
@@ -100,7 +108,17 @@ define('TYPO3/CMS/Rtehtmlarea/HTMLArea/Util/TYPO3',
                allElementsAreDisplayed: function(elements) {
                        var allDisplayed = true;
                        for (var i = elements.length; --i >= 0;) {
-                               allDisplayed = document.getElementById(elements[i]).style.display !== 'none';
+                               var element = document.getElementById(elements[i]);
+                               if (element) {
+                                       if (element.style.display) {
+                                               allDisplayed = element.style.display !== 'none';
+                                       }
+                                       if (elements[i].indexOf('-DIV') !== -1) {
+                                               allDisplayed = allDisplayed && Dom.hasClass(element, 'active');
+                                       } else if (elements[i].indexOf('_div') !== -1) {
+                                               allDisplayed = allDisplayed && Dom.hasClass(element, 'panel-visible');
+                                       }
+                               }
                                if (!allDisplayed) {
                                        break;
                                }