// SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel // // SPDX-License-Identifier: AGPL-3.0-or-later import { Utility } from '../../core/utility'; import { EventManager, EventWrapper, EVENT_TYPE } from '../../lib/event-manager/event-manager'; const MASS_INPUT_SELECTOR = '.massinput'; const RECIPIENT_CATEGORIES_SELECTOR = '.recipient-categories'; const RECIPIENT_CATEGORY_SELECTOR = '.recipient-category'; const RECIPIENT_CATEGORY_CHECKBOX_SELECTOR = '.recipient-category__checkbox'; const RECIPIENT_CATEGORY_OPTIONS_SELECTOR = '.recipient-category__options'; const RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR = '.recipient-category__toggle-all [type="checkbox"]'; const RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR = '.recipient-category__checked-counter'; @Utility({ selector: RECIPIENT_CATEGORIES_SELECTOR, }) export class CommunicationRecipients { massInputElement; _element; _eventManager; constructor(element) { if (!element) { throw new Error('Communication Recipient utility cannot be setup without an element!'); } this._element = element; this._eventManager = new EventManager(); this.massInputElement = this._element.closest(MASS_INPUT_SELECTOR); this.setupRecipientCategories(); this._eventManager.registerNewMutationObserver(this.setupRecipientCategories.bind(this), this.massInputElement, { childList: true }); } setupRecipientCategories() { Array.from(this.massInputElement.querySelectorAll(RECIPIENT_CATEGORY_SELECTOR)).forEach(this.setupRecipientCategory.bind(this)); } _removeCheckedCounter() { let checkedCounters = this._element.querySelectorAll(RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR); checkedCounters.forEach((checkedCounter) => { checkedCounter.innerHTML = ''; }); } destroy() { this._eventManager.cleanUp(); this._removeCheckedCounter(); } setupRecipientCategory(recipientCategoryElement) { const categoryCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKBOX_SELECTOR); const categoryOptions = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_OPTIONS_SELECTOR); if (categoryOptions) { const categoryCheckboxes = Array.from(categoryOptions.querySelectorAll('[type="checkbox"]')); const toggleAllCheckbox = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_TOGGLE_ALL_SELECTOR); // setup category checkbox to toggle all child checkboxes if changed const categoryToggleEvent = new EventWrapper(EVENT_TYPE.CHANGE,(() => { categoryCheckboxes.filter(checkbox => !checkbox.disabled).forEach(checkbox => { checkbox.checked = categoryCheckbox.checked; }); updateCheckedCounter(recipientCategoryElement, categoryCheckboxes); updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes); }).bind(this), categoryCheckbox ); this._eventManager.registerNewListener(categoryToggleEvent); // update counter and toggle checkbox initially updateCheckedCounter(recipientCategoryElement, categoryCheckboxes); updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes); // register change listener for individual checkboxes categoryCheckboxes.forEach(checkbox => { const individualToggleEvent = new EventWrapper(EVENT_TYPE.CHANGE, (() => { updateCheckedCounter(recipientCategoryElement, categoryCheckboxes); updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes); }).bind(this), checkbox); this._eventManager.registerNewListener(individualToggleEvent); }); // register change listener for toggle all checkbox if (toggleAllCheckbox) { const toggleAllEvent = new EventWrapper(EVENT_TYPE.CHANGE, (() => { categoryCheckboxes.filter(checkbox => !checkbox.disabled).forEach(checkbox => { checkbox.checked = toggleAllCheckbox.checked; }); updateCheckedCounter(recipientCategoryElement, categoryCheckboxes); }).bind(this), toggleAllCheckbox); this._eventManager.registerNewListener(toggleAllEvent); } } } } // update checked state of toggle all checkbox based on all other checkboxes function updateToggleAllCheckbox(toggleAllCheckbox, categoryCheckboxes) { const allChecked = categoryCheckboxes.reduce((acc, checkbox) => acc && checkbox.checked, true); toggleAllCheckbox.checked = allChecked; } // update value of checked counter function updateCheckedCounter(recipientCategoryElement, categoryCheckboxes) { const checkedCounter = recipientCategoryElement.querySelector(RECIPIENT_CATEGORY_CHECKED_COUNTER_SELECTOR); const checkedCheckboxes = categoryCheckboxes.reduce((acc, checkbox) => checkbox.checked ? acc + 1 : acc, 0); checkedCounter.innerHTML = checkedCheckboxes + '/' + categoryCheckboxes.length; }