[tools 3/4] testbot/cgi: Keep the master checkbox synchronized with the others.

Francois Gouget fgouget at codeweavers.com
Tue Apr 19 10:27:56 CDT 2022


The master checkbox is automatically checked / unchecked when the other
checkboxes are. This also removes the need to figure out what the
initial state of the master checkbox should be.
And it simplifies the master checkbox HTML code.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
 testbot/lib/ObjectModel/CGI/Table.pm | 22 ++++---------
 testbot/web/Submit.pl                |  6 ++--
 testbot/web/js/table.js              | 49 ++++++++++++++++++++++++----
 3 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/testbot/lib/ObjectModel/CGI/Table.pm b/testbot/lib/ObjectModel/CGI/Table.pm
index b55fa4157..1e33d7879 100644
--- a/testbot/lib/ObjectModel/CGI/Table.pm
+++ b/testbot/lib/ObjectModel/CGI/Table.pm
@@ -52,33 +52,25 @@ Generates a master checkbox that changes all the checkboxes with the specified
 =over
 
 =item CbGroup
-A string identifying this group of checkboxes.
+A string identifying this group of checkboxes. The 'cbgroup' attribute of all
+checkboxes in this group must be set to this value:
 
-=item Checked
-True if the initial state should be checked.
+  <input type='checkbox' cbgroup='$CbGroup' name='...'>
 
 =item Attrs
 A string containing extra attributes to be inserted in this master checkbox
-tag. It should not contain the type, checked and onchange attributes.
+tag. It should not contain the type and hidden attributes.
 
 =back
 =back
 =cut
 
-sub GenerateMasterCheckbox($;$$)
+sub GenerateMasterCheckbox($;$)
 {
-  my ($CbGroup, $Checked, $Attrs) = @_;
+  my ($CbGroup, $Attrs) = @_;
 
   $Attrs ||= "";
-  $Checked = $Checked ? " checked" : "";
-  print <<EOF;
-<script type='text/javascript'>
-<!--
-// Only add the master checkbox if JavaScript is enabled
-document.write("<input$Attrs type='checkbox' onchange='SetCheckboxes(this, "$CbGroup");'$Checked>");
-//-->
-</script>
-EOF
+  print "<input$Attrs type='checkbox' hidden='true' mcbgroup='$CbGroup'>\n";
 }
 
 1;
diff --git a/testbot/web/Submit.pl b/testbot/web/Submit.pl
index cf00ed53d..9292d387b 100644
--- a/testbot/web/Submit.pl
+++ b/testbot/web/Submit.pl
@@ -780,7 +780,6 @@ sub GenerateFields($)
     print "<thead><tr><th class='Record'>";
 
     # Check which VMs are selected and set the master default
-    my $MasterChecked = 1;
     foreach my $VMRow (@{$self->{VMRows}})
     {
       next if ($VMRow->{Incompatible});
@@ -796,10 +795,9 @@ sub GenerateFields($)
       {
         $VMRow->{Checked} = 1;
       }
-      $MasterChecked = 0 if (!$VMRow->{Checked});
     }
 
-    GenerateMasterCheckbox("vmcb", $MasterChecked);
+    GenerateMasterCheckbox("vmcb");
     print "</th>\n";
     print "<th class='Record'>VM Name</th>\n";
     print "<th class='Record'>Options</th>\n";
@@ -815,7 +813,7 @@ sub GenerateFields($)
       my $VM = $VMRow->{VM};
 
       print "<tr class='", ($Even ? "even" : "odd"),
-            "'><td><input class='vmcb' name='$VMRow->{Field}' type='checkbox'";
+            "'><td><input cbgroup='vmcb' name='$VMRow->{Field}' type='checkbox'";
       $Even = !$Even;
       print " checked='checked'" if ($VMRow->{Checked});
       print "/></td>\n";
diff --git a/testbot/web/js/table.js b/testbot/web/js/table.js
index 350dd8453..f617912c5 100644
--- a/testbot/web/js/table.js
+++ b/testbot/web/js/table.js
@@ -16,11 +16,48 @@
  */
 "use strict";
 
-function SetCheckboxes(master, group)
+var mcb_count;
+var mcb_checked;
+
+function SetCheckboxes(e)
+{
+    const master = e.target.closest("input");
+    const group = master.getAttribute("mcbgroup");
+    const selector = 'input[cbgroup="' + group + '"]';
+    document.querySelectorAll(selector).forEach(cb => {
+        cb.checked = master.checked;
+    });
+    mcb_checked[group] = master.checked ? mcb_count[group] : 0;
+}
+
+function UpdateMasterCb(e)
+{
+    const cb = e.target.closest("input");
+    const group = cb.getAttribute("cbgroup");
+    mcb_checked[group] += cb.checked ? 1 : -1;
+
+    const master = document.querySelector('input[mcbgroup="' + group + '"]');
+    master.checked = (mcb_count[group] == mcb_checked[group]);
+}
+
+
+function InitMasterCbs()
 {
-  var cbs = document.getElementsByClassName(group);
-  for (var i = 0; i < cbs.length; i++)
-  {
-    cbs[i].checked = master.checked;
-  }
+    mcb_count = {};
+    mcb_checked = {};
+    document.querySelectorAll("input[mcbgroup]").forEach(master => {
+        const group = master.getAttribute("mcbgroup");
+        mcb_count[group] = mcb_checked[group] = 0;
+        const selector = 'input[cbgroup="' + group + '"]';
+        document.querySelectorAll(selector).forEach(cb => {
+            mcb_count[group]++;
+            if (cb.checked) mcb_checked[group]++;
+            cb.addEventListener('click', UpdateMasterCb);
+        });
+        master.checked = (mcb_count[group] == mcb_checked[group]);
+        master.addEventListener('click', SetCheckboxes);
+        master.hidden = false;
+    });
 }
+
+window.addEventListener('load', InitMasterCbs);
-- 
2.30.2




More information about the wine-devel mailing list