170170 </div >
171171 </div >
172172
173- <script >
174- const getCellValue = (tr , idx ) => tr .children [idx].innerText || tr .children [idx].textContent ;
175-
176- const comparer = (idx , asc ) => (a , b ) =>
177- ((v1 , v2 ) =>
178- v1 !== ' ' && v2 !== ' ' && ! isNaN (v1) && ! isNaN (v2) ? v1 - v2 : v1 .toString ().localeCompare (v2)
179- )(getCellValue (asc ? a : b, idx), getCellValue (asc ? b : a, idx));
180-
181- // Find the table and its headers
182- const table = document .querySelector (' table' );
183- const headers = table .querySelectorAll (' th' );
184-
185- // Add caret icon to initial header element
186- const initialHeader = table .querySelector (' [data-order]' );
187- initialHeader .innerHTML = ` ${ initialHeader .innerText } <i class =" bi bi-caret-down-fill" ></i >` ;
188-
189- // Attach click event listener to all headers
190- headers .forEach (th => th .addEventListener (' click' , function () {
191- // Get the clicked header's index, sort order, and sortable attribute
192- const thIndex = Array .from (th .parentNode .children ).indexOf (th);
193- const isAscending = this .asc = ! this .asc ;
194- const isSortable = th .getAttribute (' data-sortable' ) !== ' false' ;
195-
196- // If the column is not sortable, do nothing
197- if (! isSortable) {
198- return ;
199- }
200-
201- // Remove caret icon and active class from all headers
202- headers .forEach (h => {
203- h .classList .remove (' active' );
204- h .innerHTML = h .innerText ;
205- });
206-
207- // Add caret icon and active class to clicked header
208- th .classList .add (' active' );
209- th .innerHTML = ` ${ th .innerText } ${ isAscending ? ' <i class="bi bi-caret-down-fill"></i>' : ' <i class="bi bi-caret-up-fill"></i>' } ` ;
210-
211- // Sort the table rows based on the clicked header
212- Array .from (table .querySelectorAll (' tr:nth-child(n+2)' ))
213- .sort (comparer (thIndex, isAscending))
214- .forEach (tr => table .appendChild (tr));
215- }));
216- </script >
173+ <script >
174+ const getCellValue = (tr , idx ) => tr .children [idx].innerText || tr .children [idx].textContent ;
175+
176+ const comparer = (idx , asc ) => (a , b ) =>
177+ ((v1 , v2 ) =>
178+ v1 !== ' ' && v2 !== ' ' && ! isNaN (v1) && ! isNaN (v2) ? v1 - v2 : v1 .toString ().localeCompare (v2)
179+ )(getCellValue (asc ? a : b, idx), getCellValue (asc ? b : a, idx));
180+
181+ document .addEventListener (' DOMContentLoaded' , () => {
182+ // Find the table and its headers
183+ const table = document .querySelector (' table' );
184+ const headers = table .querySelectorAll (' th[data-sort]' );
185+
186+ // Add caret icon to initial header element
187+ const initialHeader = table .querySelector (' [data-order]' );
188+ initialHeader .innerHTML = ` ${ initialHeader .innerText } <i class =" bi bi-caret-down-fill" ></i >` ;
189+
190+ // Attach click event listener to all sortable headers
191+ headers .forEach (th => th .addEventListener (' click' , function () {
192+ // Get the clicked header's index, sort order, and sortable attribute
193+ const thIndex = Array .from (th .parentNode .children ).indexOf (th);
194+ const isAscending = this .asc = ! this .asc ;
195+ const isSortable = th .getAttribute (' data-sortable' ) !== ' false' ;
196+
197+ // If the column is not sortable, do nothing
198+ if (! isSortable) {
199+ return ;
200+ }
201+
202+ // Remove caret icon and active class from all headers
203+ headers .forEach (h => {
204+ h .classList .remove (' active' );
205+ h .innerHTML = h .innerText ;
206+ });
207+
208+ // Add caret icon and active class to clicked header
209+ th .classList .add (' active' );
210+ th .innerHTML = ` ${ th .innerText } ${ isAscending ? ' <i class="bi bi-caret-down-fill"></i>' : ' <i class="bi bi-caret-up-fill"></i>' } ` ;
211+
212+ // Sort the table rows based on the clicked header
213+ Array .from (table .querySelectorAll (' tbody tr' ))
214+ .sort (comparer (thIndex, isAscending))
215+ .forEach (tr => table .querySelector (' tbody' ).appendChild (tr));
216+ }));
217+ });
218+ </script >
219+
217220
218221
219222@endsection
0 commit comments