|
902 | 902 | }); |
903 | 903 |
|
904 | 904 | // ** создание "универсального" модального окна, для добавления или изменения данных клиента (согласно передаваемого типа) |
| 905 | + let modalContactsArr = []; // глобальная инициализация массива контактов (будущих row-контактов) |
| 906 | + |
905 | 907 | function createModalWindowByType(type, clientData = {}) { |
906 | 908 | const modalId = type === 'add' ? 'add-modal' : 'edit-modal'; |
907 | 909 | const modalTitle = type === 'add' ? 'Новый клиент' : 'Изменить данные'; |
908 | 910 | const modalCancelBtn = type === 'add' ? 'Отмена' : 'Удалить клиента'; |
909 | 911 |
|
910 | | - const modalContactsArr = []; // организация массива контактов (будущих контактов) |
911 | | - |
912 | 912 | const modalWrap = document.createElement('div'); |
913 | 913 | const modalDialog = document.createElement('div'); |
914 | 914 | const modalContent = document.createElement('div'); |
|
1152 | 1152 | initTippy(modalHeaderXBtn, 'закрыть', 'left'); |
1153 | 1153 | }, 0); |
1154 | 1154 |
|
1155 | | - // запуск логики добавления/создания "внутренней" строки контактов (передача объекта/context(a) с необходимыми элементами/сущностями) |
| 1155 | + // запуск логики добавления/создания "внутренней" строки контактов (передача объекта/context(a) с необходимыми элементами) |
1156 | 1156 | modalBodyAddBtn.addEventListener('click', () => { |
1157 | 1157 | createModalContactsElement({ |
1158 | 1158 | modalWrap, |
| 1159 | + modalBodyAddContactsRowWrap, |
1159 | 1160 | modalBodyAddBtn, |
1160 | | - modalContactsArr, |
1161 | 1161 | }); |
1162 | 1162 | }); |
1163 | 1163 |
|
1164 | 1164 | // запуск проверки на "пустые" контакты (перед закрытием модального окна) |
1165 | | - modalWrap.addEventListener('hide.bs.modal', checkEmptyRowContacts); |
| 1165 | + modalWrap.addEventListener('hide.bs.modal', (event) => { |
| 1166 | + checkEmptyRowContacts(event, modalWrap); |
| 1167 | + }); |
1166 | 1168 |
|
1167 | 1169 | // удаление/очистка от невалидных row-контактов (при закрытие модального окна, передача объекта/context(a)) |
1168 | | - modalWrap.addEventListener('hidden.bs.modal', () => |
| 1170 | + modalWrap.addEventListener('hidden.bs.modal', () => { |
1169 | 1171 | removeInvalidRowContacts({ |
| 1172 | + modalWrap, |
| 1173 | + modalBodyAddContactsRowWrap, |
1170 | 1174 | modalBodyAddBtn, |
1171 | | - modalContactsArr, |
1172 | | - }) |
1173 | | - ); |
| 1175 | + }); |
| 1176 | + |
| 1177 | + if (modalContactsArr.length === 0) { |
| 1178 | + modalBodyAddContactsRowWrap.classList.add('d-none'); |
| 1179 | + } |
| 1180 | + |
| 1181 | + modalContactsArr = []; // очистка массива |
| 1182 | + }); |
1174 | 1183 |
|
1175 | 1184 | return modalWrap; // возврат модального окна (т.е. здесь/без добавления в DOM.. позже, при клике) |
1176 | 1185 | } |
|
1197 | 1206 |
|
1198 | 1207 | // ** организация "динамического" добавления строки контакта/row-contact (по нажатию "Добавить контакт" кнопки, в модальных/универсальных окнах) |
1199 | 1208 | function createModalContactsElement(context = {}) { |
1200 | | - const { modalWrap, modalBodyAddBtn, modalContactsArr } = context; // получение необходимых элементов/сущностей (через деструктуризациию входящего/передаваемого объекта) |
| 1209 | + const { modalWrap, modalBodyAddContactsRowWrap, modalBodyAddBtn } = context; // получение необходимых элементов (через деструктуризациию входящего/передаваемого объекта) |
1201 | 1210 |
|
1202 | 1211 | if (modalContactsArr.length >= 10) return; // проверка количества контактов (не более 10) |
1203 | 1212 |
|
|
1343 | 1352 | ); |
1344 | 1353 |
|
1345 | 1354 | // отображение изначально скрытой обвёртки/родителя |
1346 | | - const modalContactsRowWrap = document.querySelector( |
1347 | | - '.modal__body-contacts-row-wrap' |
1348 | | - ); |
1349 | | - modalContactsRowWrap.classList.remove('d-none'); |
1350 | | - |
1351 | | - modalContactsRowWrap.append(modalContactElement); // добавление в DOM строки контактов |
| 1355 | + modalBodyAddContactsRowWrap.classList.remove('d-none'); |
| 1356 | + modalBodyAddContactsRowWrap.append(modalContactElement); // добавление в DOM строки контактов |
1352 | 1357 |
|
1353 | 1358 | // организация дополнительных отступов для "Добавить контакт" кнопки (при появлении строки контактов) |
1354 | 1359 | if (modalContactsArr.length === 0) { |
|
1375 | 1380 | dynamicContactValidation: true, |
1376 | 1381 | }); |
1377 | 1382 |
|
1378 | | - modalContactsArr.push(modalContactElement); // добавление контакта во "внешний" массив |
| 1383 | + modalContactsArr.push(modalContactElement); // добавление контакта во внешний/глобальный массив |
1379 | 1384 |
|
1380 | 1385 | // исключение ещё/прожатия кнопки "Добавить контакт", если контактов/уже 10 (вывод сообщения) |
1381 | 1386 | if (modalContactsArr.length >= 10) { |
|
1393 | 1398 | isDropdownToggleAllowed = false; |
1394 | 1399 | setTimeout(() => (isDropdownToggleAllowed = true), 200); |
1395 | 1400 |
|
1396 | | - const alreadyOpenDropBtn = document.querySelector('.drop-open'); // фиксация открытого/уже списка (согласно drop-кнопки) |
| 1401 | + const alreadyOpenDropBtn = modalWrap.querySelector('.drop-open'); // фиксация открытого/уже списка (согласно drop-кнопки) |
1397 | 1402 | const nowClickedDropBtn = event.currentTarget; // фиксация нажатой drop-кнопки (сейчас) |
1398 | 1403 |
|
1399 | 1404 | // закрытие ранее открытого выпадающего списка (если такой был) |
1400 | 1405 | if (alreadyOpenDropBtn && alreadyOpenDropBtn !== nowClickedDropBtn) { |
1401 | | - closeBtnDropdown(); |
| 1406 | + closeBtnDropdown(modalWrap); |
1402 | 1407 | } |
1403 | 1408 |
|
1404 | 1409 | const nowShowedDropList = nowClickedDropBtn.nextElementSibling; // фиксация "ново-открытого" выпадающего списка (согласно drop-кнопки) |
|
1419 | 1424 | modalContactList.addEventListener('click', (event) => { |
1420 | 1425 | if (event.target.tagName === 'LI') { |
1421 | 1426 | getContactDropSelection(event.target, { |
| 1427 | + modalWrap, |
1422 | 1428 | modalContactDropBtn, |
1423 | 1429 | modalContactList, |
1424 | 1430 | modalContactHiddenInput, |
|
1431 | 1437 | if (event.target.tagName === 'LI' && event.key === 'Enter') { |
1432 | 1438 | event.preventDefault(); // исключение непредвиденных событий/поведения |
1433 | 1439 | getContactDropSelection(event.target, { |
| 1440 | + modalWrap, |
1434 | 1441 | modalContactDropBtn, |
1435 | 1442 | modalContactList, |
1436 | 1443 | modalContactHiddenInput, |
|
1440 | 1447 | }); |
1441 | 1448 |
|
1442 | 1449 | // автоматическое закрытие/скрытие развёрнутого выпадающего drop-списка (при работе НЕ с ним) |
1443 | | - document.addEventListener('click', (event) => { |
1444 | | - const openDropdownBtn = document.querySelector('.drop-open'); |
| 1450 | + modalWrap.addEventListener('click', (event) => { |
| 1451 | + const openDropdownBtn = modalWrap.querySelector('.drop-open'); |
1445 | 1452 |
|
1446 | 1453 | // закрытие/скрытие выпадающего списка (если последующий "клик" не по нему, не по drop-кнопке) |
1447 | 1454 | if ( |
1448 | 1455 | openDropdownBtn && |
1449 | 1456 | !openDropdownBtn.contains(event.target) && |
1450 | 1457 | !openDropdownBtn.nextElementSibling.contains(event.target) |
1451 | 1458 | ) { |
1452 | | - closeBtnDropdown(); // вызов соответствующей функции |
| 1459 | + closeBtnDropdown(modalWrap); // вызов соответствующей функции |
1453 | 1460 | } |
1454 | 1461 | }); |
1455 | 1462 |
|
1456 | 1463 | modalWrap.addEventListener('focusout', (event) => { |
1457 | | - const openDropdownBtn = document.querySelector('.drop-open'); |
| 1464 | + const openDropdownBtn = modalWrap.querySelector('.drop-open'); |
1458 | 1465 |
|
1459 | 1466 | // закрытие/скрытие выпадающего списка (если "фокус" перешёл на другой элемент, в другое место) |
1460 | 1467 | if ( |
1461 | 1468 | openDropdownBtn && |
1462 | 1469 | !openDropdownBtn.contains(event.relatedTarget) && |
1463 | 1470 | !openDropdownBtn.nextElementSibling.contains(event.relatedTarget) |
1464 | 1471 | ) { |
1465 | | - closeBtnDropdown(); // вызов соответствующей функции |
| 1472 | + closeBtnDropdown(modalWrap); // вызов соответствующей функции |
1466 | 1473 | } |
1467 | 1474 | }); |
1468 | 1475 |
|
|
1481 | 1488 | event.stopPropagation(); // исключение непредвиденных событий/поведения |
1482 | 1489 | deleteModalContactsElement(event, { |
1483 | 1490 | modalBodyAddBtn, |
1484 | | - modalContactsArr, |
1485 | | - }); // удаление строки контактов (посредствам "X" кнопки, передача объекта/context(a)) |
| 1491 | + modalBodyAddContactsRowWrap, |
| 1492 | + }); // удаление строки контактов (посредствам "X", передача context(a)) |
1486 | 1493 | }); |
1487 | 1494 |
|
1488 | 1495 | // организация удаления строки контактов и через TAB/Enter |
|
1491 | 1498 | event.stopPropagation(); // исключение непредвиденных событий/поведения |
1492 | 1499 | deleteModalContactsElement(event, { |
1493 | 1500 | modalBodyAddBtn, |
1494 | | - modalContactsArr, |
1495 | | - }); // удаление строки контактов (посредствам "X" кнопки, передача объекта/context(a)) |
| 1501 | + modalBodyAddContactsRowWrap, |
| 1502 | + }); // удаление строки контактов (посредствам "X", передача context(a)) |
1496 | 1503 | } |
1497 | 1504 | }); |
1498 | 1505 | } |
|
1501 | 1508 | function getContactDropSelection(target, context = {}) { |
1502 | 1509 | const selectedItemValue = target.getAttribute('data-value'); |
1503 | 1510 | const { |
| 1511 | + modalWrap, |
1504 | 1512 | modalContactDropBtn, |
1505 | 1513 | modalContactList, |
1506 | 1514 | modalContactHiddenInput, |
|
1537 | 1545 |
|
1538 | 1546 | updateRowInputType(modalContactInput, selectedItemValue); // обновление атрибута/значения "type" у/для инпута (кому возможно) |
1539 | 1547 | updateDropItemPaddings(modalContactList); // обновление/изменение отступов для li/вариантов выпадающего списка (для первого и последнего элементов) |
1540 | | - closeBtnDropdown(); // закрытие выпадающего списка |
| 1548 | + closeBtnDropdown(modalWrap); // закрытие выпадающего списка |
1541 | 1549 | modalContactInput.focus(); // перевод фокуса на соседний инпут (после выбора в выпадающем списке) |
1542 | 1550 | } |
1543 | 1551 |
|
|
1576 | 1584 | } |
1577 | 1585 |
|
1578 | 1586 | // ** организация закрытия/скрытия выпадающего row-contact списка в модальном окне (снятие фокуса) |
1579 | | - function closeBtnDropdown() { |
1580 | | - const openDropdownBtn = document.querySelector('.drop-open'); // фиксация "открывающей" drop-кнопки |
| 1587 | + function closeBtnDropdown(modalWrap) { |
| 1588 | + const openDropdownBtn = modalWrap.querySelector('.drop-open'); // фиксация "открывающей" drop-кнопки |
1581 | 1589 |
|
1582 | 1590 | if (openDropdownBtn) { |
1583 | 1591 | const dropdownList = openDropdownBtn.nextElementSibling; // фиксация выпадающего списка |
|
1640 | 1648 | // ** удаление строки row-контакта в модальном окне (через "X" кнопку, с/без уточняющего сообщения) |
1641 | 1649 | function deleteModalContactsElement(event, context = {}) { |
1642 | 1650 | const clickedContactsXBtn = event.currentTarget; // получение ИМЕННО кнопки, а не/может внутренней иконки (согласно "размазанного" события) |
1643 | | - const { modalBodyAddBtn, modalContactsArr } = context; // получение необходимых элементов/сущностей (через деструктуризациию входящего/передаваемого объекта) |
| 1651 | + const { modalBodyAddBtn, modalBodyAddContactsRowWrap } = context; // получение необходимых элементов (через деструктуризациию входящего/передаваемого объекта) |
1644 | 1652 |
|
1645 | 1653 | if (clickedContactsXBtn) { |
1646 | 1654 | tippy.hideAll(); // предварительное скрытие всех/вдруг "активных" tooltips (перед удалением искомой строки) |
|
1682 | 1690 |
|
1683 | 1691 | // проверка на количество строк контактов (нет, скрытие обвёртки/родителя и удаление дополнительных отступов) |
1684 | 1692 | if ( |
1685 | | - document.querySelectorAll('.modal__body-add-contact-element') |
1686 | | - .length === 0 |
| 1693 | + modalBodyAddContactsRowWrap.querySelectorAll( |
| 1694 | + '.modal__body-add-contact-element' |
| 1695 | + ).length === 0 |
1687 | 1696 | ) { |
1688 | | - const modalContactsRowWrap = document.querySelector( |
1689 | | - '.modal__body-contacts-row-wrap' |
1690 | | - ); |
1691 | | - modalContactsRowWrap.classList.add('d-none'); |
| 1697 | + modalBodyAddContactsRowWrap.classList.add('d-none'); |
1692 | 1698 | modalBodyAddBtn.classList.remove('modal-contact-btn-margin'); |
1693 | 1699 | } |
1694 | 1700 | } else { |
|
1699 | 1705 | } |
1700 | 1706 |
|
1701 | 1707 | // ** организация проверки на "пустые" row-контакты, перед закрытием соответствующего модального окна (вывод сообщения) |
1702 | | - function checkEmptyRowContacts(event) { |
1703 | | - const allContactRows = document.querySelectorAll('.modal-contact-element'); |
| 1708 | + function checkEmptyRowContacts(event, modalWrap) { |
| 1709 | + const allContactRows = modalWrap.querySelectorAll('.modal-contact-element'); |
1704 | 1710 |
|
1705 | 1711 | // определение "пустых" контактов (формирование соответствующего массива) |
1706 | 1712 | const emptyContacts = Array.from(allContactRows).filter((row) => { |
|
1724 | 1730 | } |
1725 | 1731 |
|
1726 | 1732 | // ** удаление/очистка от невалидных row-контактов (при закрытии модального окна) |
1727 | | - function removeInvalidRowContacts(context) { |
1728 | | - const { modalBodyAddBtn, modalContactsArr } = context; // получение необходимых элементов/сущностей (через деструктуризациию входящего/передаваемого объекта) |
1729 | | - const invalidContactRows = document.querySelectorAll( |
| 1733 | + function removeInvalidRowContacts(context = {}) { |
| 1734 | + const { modalWrap, modalBodyAddContactsRowWrap, modalBodyAddBtn } = context; // получение необходимых элементов (через деструктуризациию входящего/передаваемого объекта) |
| 1735 | + const invalidContactRows = modalWrap.querySelectorAll( |
1730 | 1736 | '.modal-contact-element .is-invalid' |
1731 | 1737 | ); |
1732 | 1738 |
|
|
1750 | 1756 |
|
1751 | 1757 | // скрытие "обвёртки" контактов если в массиве контактов пусто |
1752 | 1758 | if (modalContactsArr.length === 0) { |
1753 | | - const modalContactsRowWrap = document.querySelector( |
1754 | | - '.modal__body-contacts-row-wrap' |
1755 | | - ); |
1756 | | - modalContactsRowWrap.classList.add('d-none'); |
| 1759 | + modalBodyAddContactsRowWrap.classList.add('d-none'); |
1757 | 1760 | modalBodyAddBtn.classList.remove('modal-contact-btn-margin'); // удаление дополнительных отступов |
1758 | 1761 | } |
1759 | 1762 | } |
|
0 commit comments