[BUGFIX] Correctly show sub item indicator in svg tree 37/51237/5
authorThorben Nissen <thorben.nissen@kapp-hamburg.de>
Tue, 10 Jan 2017 13:21:56 +0000 (14:21 +0100)
committerTymoteusz Motylewski <t.motylewski@gmail.com>
Wed, 25 Jan 2017 08:59:12 +0000 (09:59 +0100)
Changes the way the svg tree nodes are checked for "indeterminate" state
after the data is loaded, so the initial state. Changes code using "rootNode"
to using list of all nodes. Removes unused code.

Resolves: #79246
Releases: master
Change-Id: I7a076a6d3d2c29f0318598227af5d674caa3642f
Reviewed-on: https://review.typo3.org/51237
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Thomas Maroschik <tmaroschik@dfau.de>
Tested-by: Thomas Maroschik <tmaroschik@dfau.de>
Reviewed-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Tested-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SvgTree.js

index e908dbc..e4134c4 100644 (file)
@@ -114,23 +114,6 @@ define(['d3', 'TYPO3/CMS/Backend/FormEngine/Element/SvgTree'], function (d3, Svg
     };
 
     /**
-     * Does not modify the data, just checking with early return
-     *
-     * @param {Node} node
-     */
-    SelectTree.prototype.hasCheckedOrIndeterminateChildren = function (node) {
-        if (!node.children) {
-            return false;
-        }
-
-        return node.children.some(function (child) {
-            if (child.checked || child.indeterminate) {
-                return true;
-            }
-        });
-    };
-
-    /**
      * Updates the indeterminate state for ancestors of the current node
      *
      * @param {Node} node
@@ -138,9 +121,12 @@ define(['d3', 'TYPO3/CMS/Backend/FormEngine/Element/SvgTree'], function (d3, Svg
     SelectTree.prototype.updateAncestorsIndetermineState = function (node) {
         var me = this;
         //foreach ancestor except node itself
+        var indeterminate = false;
         node.parents.forEach(function (index) {
             var n = me.nodes[index];
-            n.indeterminate = (node.checked || node.indeterminate) ? true : me.hasCheckedOrIndeterminateChildren(n);
+            n.indeterminate = (node.checked || node.indeterminate || indeterminate);
+            // check state for the next level
+            indeterminate = (node.checked || node.indeterminate || n.checked || n.indeterminate)
         });
     };
 
@@ -164,17 +150,14 @@ define(['d3', 'TYPO3/CMS/Backend/FormEngine/Element/SvgTree'], function (d3, Svg
     /**
      * Sets indeterminate state for a subtree. It relays on the tree to have indeterminate state reset beforehand.
      *
-     * @param {Node} node
+     * @param {Array} nodes
      */
-    SelectTree.prototype.calculateIndeterminate = function (node) {
-        if (!node.children) {
-            node.indeterminate = false;
-            return;
-        }
-
-        node.eachAfter(function (n) {
-            if ((n.checked || n.indeterminate) && n.parent) {
-                n.parent.indeterminate = true;
+    SelectTree.prototype.calculateIndeterminate = function (nodes) {
+        nodes.forEach(function(node) {
+            if ((node.checked || node.indeterminate) && node.parents && node.parents.length > 0) {
+                node.parents.forEach(function(parentNodeIndex) {
+                    nodes[parentNodeIndex].indeterminate = true;
+                })
             }
         })
     };
@@ -186,6 +169,8 @@ define(['d3', 'TYPO3/CMS/Backend/FormEngine/Element/SvgTree'], function (d3, Svg
      */
     SelectTree.prototype.nodeSelectedAfter = function (node) {
         this.updateAncestorsIndetermineState(node);
+        // check all nodes again, to ensure correct display of indeterminate state
+        this.calculateIndeterminate(this.nodes);
         this.saveCheckboxes(node);
     };
 
index 59d7f5e..72e243e 100644 (file)
  */
 define(['jquery', 'd3'], function ($, d3) {
     'use strict';
-    /**
-     * Returns descendants of the current node in the pre-order traversal, such that a given node is only visited
-     * after all of its ancestors have already been visited. In other words "children before siblings"
-     *
-     * @returns {Node[]}
-     */
-    d3.hierarchy.prototype.descendantsBefore = function () {
-        var nodes = [];
-        this.eachBefore(function (node) {
-            nodes.push(node);
-        });
-        return nodes;
-    };
 
     /**
      * @constructor
@@ -83,13 +70,6 @@ define(['jquery', 'd3'], function ($, d3) {
         this.linksContainer = null;
 
         /**
-         * Tree root node
-         *
-         * @type {Node}
-         */
-        this.rootNode = null;
-
-        /**
          *
          * @type {{nodes: Node[], links: Object, icons: Object}}
          */
@@ -590,7 +570,7 @@ define(['jquery', 'd3'], function ($, d3) {
             if (this.settings.exclusiveNodesIdentifiers.length && node.checked === false) {
                 if (exclusiveKeys.indexOf('' + node.identifier) > -1) {
                     // this key is exclusive, so uncheck all others
-                    this.rootNode.each(function (node) {
+                    this.nodes.forEach(function (node) {
                         if (node.checked === true) {
                             node.checked = false;
                             me.dispatch.call('nodeSelectedAfter', me, node);