113 lines
4.8 KiB
JavaScript
113 lines
4.8 KiB
JavaScript
// SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
|
//
|
|
// 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;
|
|
}
|