Why This is Helpful

Staff have shared that it’s easier to deselect absentees rather than manually selecting everyone who is present.

How It Works

This recipe adds a "Mark All As Present" button to the attendance page, allowing staff to mark everyone as attended with one click and then simply uncheck those who are absent.

Capture.PNG

"Confirm" Marks all attendees as present.

Capture12.PNG

Setup

1️⃣ Go to a "Group Attendance Detail" block settings.

Capture3.PNG

2️⃣ Navigate to Advanced Settings > Pre-HTML.

Capture4.PNG

Paste This Code

Copy and paste the following code into the Pre-HTML section:

<script>
    function insertMarkAllPresentButton() {
        let targetContainer = document.querySelector(".col-xs-12.col-sm-8.d-sm-flex") || 
                              document.querySelector(".did-attend-filter .btn-group");

        if (targetContainer && !document.getElementById("mark-all-present-group")) {
            let searchFilter = targetContainer.querySelector(".search-filter");

            // Create the btn-group wrapper for correct styling
            let btnGroup = document.createElement("div");
            btnGroup.className = "btn-group";
            btnGroup.id = "mark-all-present-group"; // Unique ID to prevent duplication
            btnGroup.style.marginLeft = "8px"; // Keep spacing consistent

            // Create "Mark All As Present" button inside btn-group
            let markAllBtn = document.createElement("button");
            markAllBtn.id = "mark-all-present";
            markAllBtn.className = "btn btn-primary";
            markAllBtn.type = "button";
            markAllBtn.textContent = "Mark All As Present";

            // Append button to btn-group
            btnGroup.appendChild(markAllBtn);

            // Insert the btn-group before search filter (or at the end if missing)
            if (searchFilter) {
                targetContainer.insertBefore(btnGroup, searchFilter);
            } else {
                targetContainer.appendChild(btnGroup);
            }

            // Auto-adjust button width
            setTimeout(() => {
                btnGroup.style.width = markAllBtn.offsetWidth + "px";
            }, 50);

            // Add click event for "Mark All As Present"
            markAllBtn.addEventListener("click", function(event) {
                event.preventDefault();
                event.stopPropagation();

                // Get the width of the button before hiding it
                let buttonWidth = btnGroup.offsetWidth;
                btnGroup.style.width = buttonWidth + "px"; // Keep button width consistent

                // Hide original button
                markAllBtn.style.display = "none";

                // Create Confirm and Cancel buttons inside btn-group
                let confirmBtn = document.createElement("button");
                confirmBtn.textContent = "Confirm";
                confirmBtn.className = "btn btn-success";
                confirmBtn.type = "button";
                confirmBtn.style.flex = "1";

                let cancelBtn = document.createElement("button");
                cancelBtn.textContent = "Cancel";
                cancelBtn.className = "btn btn-danger";
                cancelBtn.type = "button";
                cancelBtn.style.flex = "1";

                // Preserve `.btn-group` structure and replace only the button
                btnGroup.innerHTML = "";
                btnGroup.appendChild(confirmBtn);
                btnGroup.appendChild(cancelBtn);

                // Confirm button selects checkboxes
                confirmBtn.addEventListener("click", function() {
                    document.querySelectorAll(".checkbox-card input[type='checkbox']").forEach(checkbox => {
                        if (!checkbox.checked) {
                            checkbox.click();
                        }
                    });
                    resetButtons();
                });

                // Cancel button just restores "Mark All As Present"
                cancelBtn.addEventListener("click", function() {
                    resetButtons();
                });

                // Restore original button
                function resetButtons() {
                    btnGroup.innerHTML = "";
                    btnGroup.appendChild(markAllBtn);
                    markAllBtn.style.display = "inline-block";
                    btnGroup.style.width = ""; // Reset width for dynamic sizing
                }
            });

            return true;
        }
        return false;
    }

    // Use MutationObserver to detect when the target container appears dynamically
    const observer = new MutationObserver(() => {
        if (insertMarkAllPresentButton()) {
            observer.disconnect(); // Stop observing once inserted
        }
    });

    // Start observing changes in the document body
    observer.observe(document.body, { childList: true, subtree: true });
</script>