MDL-69525 core: Publish a single event when toggling slave checkboxes
authorMihail Geshoski <mihail@moodle.com>
Tue, 1 Sep 2020 06:33:11 +0000 (14:33 +0800)
committerMihail Geshoski <mihail@moodle.com>
Tue, 1 Sep 2020 06:42:15 +0000 (14:42 +0800)
lib/amd/build/checkbox-toggleall.min.js
lib/amd/build/checkbox-toggleall.min.js.map
lib/amd/src/checkbox-toggleall.js

index 4fd1ed4..7029f5b 100644 (file)
Binary files a/lib/amd/build/checkbox-toggleall.min.js and b/lib/amd/build/checkbox-toggleall.min.js differ
index e7a5c40..f28f66b 100644 (file)
Binary files a/lib/amd/build/checkbox-toggleall.min.js.map and b/lib/amd/build/checkbox-toggleall.min.js.map differ
index 473a514..6237eff 100644 (file)
@@ -137,6 +137,45 @@ define(['jquery', 'core/pubsub'], function($, PubSub) {
         toggleSlavesToState(root, toggleGroupName, targetState);
     };
 
+    /**
+     * Toggles the master checkboxes and action elements in a given toggle group.
+     *
+     * @param {jQuery} root The root jQuery element.
+     * @param {String} toggleGroupName The name of the toggle group
+     */
+    var toggleMastersAndActionElements = function(root, toggleGroupName) {
+        var toggleGroupSlaves = getAllSlaveCheckboxes(root, toggleGroupName);
+        if (toggleGroupSlaves.length > 0) {
+            var toggleGroupCheckedSlaves = toggleGroupSlaves.filter(':checked');
+            var targetState = toggleGroupSlaves.length === toggleGroupCheckedSlaves.length;
+
+            // Make sure to toggle the exact master checkbox in the given toggle group.
+            setMasterStates(root, toggleGroupName, targetState, true);
+            // Enable the action elements if there's at least one checkbox checked in the given toggle group.
+            // Disable otherwise.
+            setActionElementStates(root, toggleGroupName, !toggleGroupCheckedSlaves.length);
+        }
+    };
+
+    /**
+     * Returns an array containing every toggle group level of a given toggle group.
+     *
+     * @param {String} toggleGroupName The name of the toggle group
+     * @return {Array} toggleGroupLevels Array that contains every toggle group level of a given toggle group
+     */
+    var getToggleGroupLevels = function(toggleGroupName) {
+        var toggleGroups = toggleGroupName.split(' ');
+        var toggleGroupLevels = [];
+        var toggleGroupLevel = '';
+
+        toggleGroups.forEach(function(toggleGroupName) {
+            toggleGroupLevel += ' ' + toggleGroupName;
+            toggleGroupLevels.push(toggleGroupLevel.trim());
+        });
+
+        return toggleGroupLevels;
+    };
+
     /**
      * Toggles the slave checkboxes to a specific state.
      *
@@ -146,14 +185,26 @@ define(['jquery', 'core/pubsub'], function($, PubSub) {
      */
     var toggleSlavesToState = function(root, toggleGroupName, targetState) {
         var slaves = getAllSlaveCheckboxes(root, toggleGroupName);
+        // Set the slave checkboxes from the masters and manually trigger the native 'change' event.
+        slaves.prop('checked', targetState).trigger('change');
+        // Get all checked slaves after the change of state.
         var checkedSlaves = slaves.filter(':checked');
 
+        // Toggle the master checkbox in the given toggle group.
         setMasterStates(root, toggleGroupName, targetState, false);
-
-        // Set the slave checkboxes from the masters.
-        slaves.prop('checked', targetState);
-        // Trigger 'change' event to toggle other master checkboxes (e.g. parent master checkboxes) and action elements.
-        slaves.trigger('change');
+        // Enable the action elements if there's at least one checkbox checked in the given toggle group. Disable otherwise.
+        setActionElementStates(root, toggleGroupName, !checkedSlaves.length);
+
+        // Get all toggle group levels and toggle accordingly all parent master checkboxes and action elements from each
+        // level. Exclude the given toggle group (toggleGroupName) as the master checkboxes and action elements from this
+        // level have been already toggled.
+        var toggleGroupLevels = getToggleGroupLevels(toggleGroupName)
+            .filter(toggleGroupLevel => toggleGroupLevel !== toggleGroupName);
+
+        toggleGroupLevels.forEach(function(toggleGroupLevel) {
+            // Toggle the master checkboxes action elements in the given toggle group level.
+            toggleMastersAndActionElements(root, toggleGroupLevel);
+        });
 
         PubSub.publish(events.checkboxToggled, {
             root: root,
@@ -190,33 +241,24 @@ define(['jquery', 'core/pubsub'], function($, PubSub) {
     var toggleMastersFromSlaves = function(e) {
         var root = e.data.root;
         var target = $(e.target);
+        var toggleGroupName = target.data('togglegroup');
+        var slaves = getAllSlaveCheckboxes(root, toggleGroupName);
+        var checkedSlaves = slaves.filter(':checked');
 
-        var toggleGroups = target.data('togglegroup').split(' ');
-        var toggleGroupLevels = [];
-        var toggleGroupLevel = '';
-        toggleGroups.forEach(function(toggleGroupName) {
-            toggleGroupLevel += ' ' + toggleGroupName;
-            toggleGroupLevels.push(toggleGroupLevel.trim());
+        // Get all toggle group levels for the given toggle group and toggle accordingly all master checkboxes
+        // and action elements from each level.
+        var toggleGroupLevels = getToggleGroupLevels(toggleGroupName);
+        toggleGroupLevels.forEach(function(toggleGroupLevel) {
+            // Toggle the master checkboxes action elements in the given toggle group level.
+            toggleMastersAndActionElements(root, toggleGroupLevel);
         });
 
-        toggleGroupLevels.forEach(function(toggleGroupName) {
-            var slaves = getAllSlaveCheckboxes(root, toggleGroupName);
-            var checkedSlaves = slaves.filter(':checked');
-            var targetState = (slaves.length === checkedSlaves.length);
-
-            // Make sure to toggle the exact master checkbox.
-            setMasterStates(root, toggleGroupName, targetState, true);
-
-            // Enable action elements when there's at least one checkbox checked. Disable otherwise.
-            setActionElementStates(root, toggleGroupName, !checkedSlaves.length);
-
-            PubSub.publish(events.checkboxToggled, {
-                root: root,
-                toggleGroupName: toggleGroupName,
-                slaves: slaves,
-                checkedSlaves: checkedSlaves,
-                anyChecked: !!checkedSlaves.length,
-            });
+        PubSub.publish(events.checkboxToggled, {
+            root: root,
+            toggleGroupName: toggleGroupName,
+            slaves: slaves,
+            checkedSlaves: checkedSlaves,
+            anyChecked: !!checkedSlaves.length,
         });
     };
 
@@ -281,7 +323,7 @@ define(['jquery', 'core/pubsub'], function($, PubSub) {
 
             var root = $(document.body);
             root.on('click', '[data-action="toggle"][data-toggle="master"]', {root: root}, toggleSlavesFromMasters);
-            root.on('change', '[data-action="toggle"][data-toggle="slave"]', {root: root}, toggleMastersFromSlaves);
+            root.on('click', '[data-action="toggle"][data-toggle="slave"]', {root: root}, toggleMastersFromSlaves);
         }
     };