commit 2aabf54ed3add974b4296ff1c9e2117f375d5f98
Author: Petr Urban <urbanp@gapps.zcu.cz>
Date:   Tue Jun 28 13:18:59 2022 +0200

    #41 Created new .js function which takes care of "middle option" --> indeterminate, when not all checkboxes are selected. Removed checkbox Select All from footer and added it to header.

diff --git a/src/main/webapp/WEB-INF/templates/index.html b/src/main/webapp/WEB-INF/templates/index.html
index 4ed66f7..fa675bb 100644
--- a/src/main/webapp/WEB-INF/templates/index.html
+++ b/src/main/webapp/WEB-INF/templates/index.html
@@ -47,30 +47,30 @@
             <div class="col">
                 <!-- Table for selecting projects -->
                 <table th:if="${not #lists.isEmpty(query.projects)}" class="table">
-                    <thead>
-
-                    </thead>
+                    <thead></thead>
                     <tbody>
-                    <tr th:each="project : ${query.projects}">
-                        <td><a th:text="${project.name}" th:href="@{'/projects/' + ${project.id}}" class="anchor-table"></a></td>
-                        <td style="text-align: center">
-                            <input checked type="checkbox" class="form-check-input" name="selectedProjects"
-                                   th:value="${project.id}" th:id="@{project_} + ${project.id}">
-                        </td>
-                    </tr>
-                    </tbody>
-                    <tfoot>
+
                     <tr>
                         <td style="border-bottom: none !important; text-align: right !important;">
                             Select All
                         </td>
                         <td style="border-bottom: none; !important">
-<!--                            <label class="form-check-label" for="select_all_projects">Select All</label>-->
+                            <!--<label class="form-check-label" for="select_all_projects">Select All</label>-->
                             <input checked type="checkbox" class="form-check-input add-label" id="select_all_projects"
                                    onclick="checkAllProjects(this)">
                         </td>
                     </tr>
-                    </tfoot>
+
+                    <tr th:each="project : ${query.projects}">
+                        <td><a th:text="${project.name}" th:href="@{'/projects/' + ${project.id}}" class="anchor-table"></a></td>
+                        <td style="text-align: center">
+                            <input checked type="checkbox" class="form-check-input" name="selectedProjects"
+                                   th:value="${project.id}" th:id="@{project_} + ${project.id}"
+                            onclick="projectCheckboxesAllIndeterminate(this, 0)">
+                        </td>
+                    </tr>
+                    </tbody>
+                    <tfoot></tfoot>
                 </table>
                 <div th:unless="${not #lists.isEmpty(query.projects)}" class="alert alert-danger" role="alert">
                     There are no projects to analyze!
@@ -84,26 +84,26 @@
                     
                     </thead>
                     <tbody>
-                    <tr th:each="antiPattern : ${query.antiPatterns}">
-                        <td><a th:text="${antiPattern.printName}" th:href="@{'/anti-patterns/' + ${antiPattern.id}}" class="anchor-table"></a></td>
-                        <td style="text-align: center">
-                            <input checked type="checkbox" class="form-check-input" name="selectedAntiPatterns"
-                                   th:value="${antiPattern.id}" th:id="@{anti-pattern_} + ${antiPattern.id}">
-                        </td>
-                    </tr>
-                    </tbody>
-                    <tfoot>
                     <tr>
                         <td style="border-bottom: none !important; text-align: right !important;">
                             Select All
                         </td>
                         <td style="border-bottom: none !important; text-align: center !important;">
-<!--                            <label class="form-check-label" for="select_all_anti_patterns">Select All</label>-->
+                            <!--                            <label class="form-check-label" for="select_all_anti_patterns">Select All</label>-->
                             <input checked type="checkbox" class="form-check-input add-label" id="select_all_anti_patterns"
                                    onclick="checkAllAntiPatterns(this)">
                         </td>
                     </tr>
-                    </tfoot>
+                    <tr th:each="antiPattern : ${query.antiPatterns}">
+                        <td><a th:text="${antiPattern.printName}" th:href="@{'/anti-patterns/' + ${antiPattern.id}}" class="anchor-table"></a></td>
+                        <td style="text-align: center">
+                            <input checked type="checkbox" class="form-check-input" name="selectedAntiPatterns"
+                                   th:value="${antiPattern.id}" th:id="@{anti-pattern_} + ${antiPattern.id}"
+                                   onclick="projectCheckboxesAllIndeterminate(this, 1)">
+                        </td>
+                    </tr>
+                    </tbody>
+                    <tfoot></tfoot>
                 </table>
                 <div th:unless="${not #lists.isEmpty(query.antiPatterns)}" class="alert alert-danger" role="alert">
                     There are no anti-patterns to detect!
diff --git a/src/main/webapp/resources/js/core.js b/src/main/webapp/resources/js/core.js
index 3859158..6f90aef 100644
--- a/src/main/webapp/resources/js/core.js
+++ b/src/main/webapp/resources/js/core.js
@@ -1,3 +1,38 @@
+function projectCheckboxesAllIndeterminate(checkbox, selectPattern) {
+
+    var globalCheckboxPattern = "";
+    var checkboxPattern = "";
+
+    if (selectPattern == 0) {
+        globalCheckboxPattern = '*[id^="select_all_projects"]';
+        checkboxPattern = '*[id^="project_"]';
+    } else {
+        globalCheckboxPattern = '*[id^="select_all_anti_patterns"]';
+        checkboxPattern = '*[id^="anti-pattern_"]';
+    }
+
+    var projectCheckboxes = document.querySelectorAll(checkboxPattern);
+    var checkedCounter = 0;
+
+    for (let i = 0; i < projectCheckboxes.length; i++) {
+            if(projectCheckboxes[i].checked) {
+                checkedCounter++;
+            }
+     }
+        var projectSelectAllCheckbox = document.querySelector(globalCheckboxPattern);
+
+        if (checkedCounter <= 0) {
+            projectSelectAllCheckbox.indeterminate = false;
+            projectSelectAllCheckbox.checked = false;
+        } else if (checkedCounter < projectCheckboxes.length) {
+            projectSelectAllCheckbox.indeterminate = true;
+        } else {
+            projectSelectAllCheckbox.indeterminate = false;
+            projectSelectAllCheckbox.checked = true;
+        }
+
+}
+
 // script to popover
 $(document).ready(function () {
     $('[data-toggle="popover"]').popover();
@@ -18,6 +53,7 @@ function checkAllAntiPatterns(checkBox) {
     for (i = 0; i < antiPatterns.length; i++) {
         antiPatterns[i].checked = !!checkBox.checked;
     }
+    antiPatternsChecked = true;
 }
 
 function showProgressBar() {
