newFilterElement.blade.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <div class="dropdown-menu" style="width: 300px;" aria-labelledby="{{$id}}">
  2. <div class="px-1">
  3. <div class="d-flex mb-2 {{ $isSort ? '' : 'd-none' }}">
  4. <div class="me-3">Сортировка</div>
  5. <div class="d-flex w-75">
  6. <button type="button" class="btn btn-outline-secondary btn-sm w-100" id="sort-by-asc-{{$id}}"><i class="bi bi-arrow-up"></i>ASC</button>
  7. <button type="button" class="btn btn-outline-secondary btn-sm w-100" id="sort-by-desc-{{$id}}"><i class="bi bi-arrow-down"></i>DESC</button>
  8. </div>
  9. </div>
  10. <form class="dropdown-filter_{{$id}} mb-2">
  11. <div class="d-flex align-items-center mb-2">
  12. <input class="form-control me-2" id="search_{{$id}}" placeholder="Поиск">
  13. <button type="button" class="btn btn-outline-secondary btn-sm" id="sort-filter-{{$id}}" title="А-Я / Я-А">
  14. <i class="bi bi-sort-alpha-down" id="sort-filter-icon-{{$id}}"></i>
  15. </button>
  16. </div>
  17. <div class="ps-1" id="filter-list-{{$id}}" style="max-height: 200px; overflow-y: scroll;">
  18. </div>
  19. </form>
  20. <div class="modal-footer d-flex justify-content-between" id="modal-footer_{{$id}}">
  21. <button type="button" class="btn btn-outline-secondary reset-filters_{{$id}} btn-sm w-50 border-0" id="reset-filters_{{$id}}">Отмена</button>
  22. <button type="button" class="btn btn-primary accept-filter_{{$id}} btn-sm w-50" id="accept-filter_{{$id}}">Применить</button>
  23. </div>
  24. </div>
  25. </div>
  26. @push('scripts')
  27. <script type="module">
  28. function escapeHtml(str) {
  29. return str.toString()
  30. .replace(/&/g, "&amp;")
  31. .replace(/"/g, "&quot;")
  32. .replace(/</g, "&lt;")
  33. .replace(/>/g, "&gt;");
  34. }
  35. // Ждём загрузки jQuery через Vite
  36. function waitForJQuery(callback) {
  37. if (typeof window.$ !== 'undefined') {
  38. callback();
  39. } else {
  40. setTimeout(() => waitForJQuery(callback), 50);
  41. }
  42. }
  43. waitForJQuery(async function () {
  44. const $container = $("#filter-list-{{$id}}");
  45. const $searchInput = $("#search_{{$id}}");
  46. const $sortBtn = $("#sort-filter-{{$id}}");
  47. const $sortIcon = $("#sort-filter-icon-{{$id}}");
  48. const urlParams = new URL(document.location.href);
  49. const existingFilter = urlParams.searchParams.get(`filters[{{$id}}]`);
  50. const selectedValues = existingFilter ? existingFilter.split("||") : [];
  51. let filterData = [];
  52. let sortAsc = true;
  53. function renderFilterList(data) {
  54. const html = data.map(item => `
  55. <div class="form-check">
  56. <input class="form-check-input" type="checkbox" value="${escapeHtml(item)}" id="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
  57. <label class="form-check-label" for="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
  58. ${escapeHtml(item)}
  59. </label>
  60. </div>
  61. `).join('');
  62. $container.html(html);
  63. selectedValues.forEach(value => {
  64. $container.find(`.form-check-input[value="${$.escapeSelector(value)}"]`).prop("checked", true);
  65. });
  66. }
  67. function sortData(asc) {
  68. const collator = new Intl.Collator('ru', { sensitivity: 'base', numeric: true });
  69. return [...filterData].sort((a, b) => {
  70. if (a === '-пусто-') return -1;
  71. if (b === '-пусто-') return 1;
  72. return asc ? collator.compare(a, b) : collator.compare(b, a);
  73. });
  74. }
  75. try {
  76. const response = await fetch(`{!! route('getFilters', ['column' => $id, 'table' => $table]) !!}`);
  77. const data = await response.json();
  78. if (Array.isArray(data) && data.length) {
  79. if(data[0] === null) data[0] = '-пусто-';
  80. filterData = data;
  81. const sortedData = sortData(sortAsc);
  82. renderFilterList(sortedData);
  83. } else {
  84. $("#search_{{$id}}").parent().hide();
  85. $("#modal-footer_{{$id}}").hide();
  86. $container.html('<div class="text-muted">Нет данных</div>');
  87. }
  88. } catch (error) {
  89. console.error("Ошибка при загрузке фильтров:", error);
  90. $container.html('<div class="text-danger">Ошибка загрузки</div>');
  91. }
  92. $sortBtn.on("click", function (e) {
  93. e.preventDefault();
  94. sortAsc = !sortAsc;
  95. $sortIcon.removeClass("bi-sort-alpha-down bi-sort-alpha-up")
  96. .addClass(sortAsc ? "bi-sort-alpha-down" : "bi-sort-alpha-up");
  97. const sortedData = sortData(sortAsc);
  98. renderFilterList(sortedData);
  99. });
  100. $("#accept-filter_{{$id}}").on("click", function () {
  101. const checkedValues = $container.find(".form-check-input:checked")
  102. .map(function () {
  103. return $(this).val();
  104. })
  105. .get();
  106. let currentUrl = new URL(document.location.href);
  107. if(!checkedValues.join('||')) {
  108. currentUrl.searchParams.delete('filters[{{$id}}]');
  109. } else {
  110. currentUrl.searchParams.set('filters[{{$id}}]', checkedValues.join('||'));
  111. }
  112. currentUrl.searchParams.delete('page');
  113. document.location.href = currentUrl.href;
  114. });
  115. $("#reset-filters_{{$id}}").on("click", function () {
  116. let currentUrl = new URL(document.location.href);
  117. currentUrl.searchParams.delete('filters[{{$id}}]');
  118. document.location.href = currentUrl.href;
  119. });
  120. $searchInput.on("input", function () {
  121. const query = $(this).val().toLowerCase();
  122. $container.find(".form-check").each(function () {
  123. const labelText = $(this).find("label").text().toLowerCase();
  124. if (labelText.includes(query)) {
  125. $(this).show();
  126. } else {
  127. $(this).hide();
  128. $(this).find(".form-check-input").prop("checked", false);
  129. }
  130. });
  131. });
  132. $('#sort-by-asc-{{$id}}').on('click', function () {
  133. let columnName = '{{$id}}';
  134. let currentUrl = new URL(document.location.href);
  135. currentUrl.searchParams.set('sortBy', columnName);
  136. if(currentUrl.searchParams.get('order') === 'desc') {
  137. currentUrl.searchParams.delete('order');
  138. }
  139. document.location.href = currentUrl.href;
  140. });
  141. $('#sort-by-desc-{{$id}}').on('click', function () {
  142. let columnName = '{{$id}}';
  143. let currentUrl = new URL(document.location.href);
  144. currentUrl.searchParams.set('sortBy', columnName);
  145. currentUrl.searchParams.set('order', 'desc');
  146. document.location.href = currentUrl.href;
  147. });
  148. });
  149. </script>
  150. @endpush