1515 {% for field in form.hidden_fields %}
1616 {{ field }}
1717 {% endfor %}
18- < div class ="filter-form-group ">
19- {% for field in form.visible_fields %}
20- < div class ="filter-form-input ">
21- {{ field.errors }}
22- < label for ="{{ field.auto_id }} " style ="display: block; ">
23- {{ field.label }}
24- {% if field.help_text %}
25- < i class ="fa-solid fa-circle-question has-popover " data-trigger ="hover " data-content ="{{ field.help_text }} " data-placement ="right " data-container ="body ">
26- </ i >
18+ < div class ="container-fluid filter-form-group ">
19+ {% for field in form.visible_fields %}
20+ < div class ="col-lg-3 col-md-4 col-sm-6 col-12 ">
21+ < div class ="filter-form-input " style ="min-width: 0; ">
22+ < label for ="{{ field.auto_id }} " class ="form-label mb-1 " style ="display: block; ">
23+ {{ field.label }}
24+ {% if field.help_text %}
25+ < i class ="fa-solid fa-circle-question has-popover "
26+ data-trigger ="hover "
27+ data-content ="{{ field.help_text }} "
28+ data-placement ="right "
29+ data-container ="body ">
30+ </ i >
31+ {% endif %}
32+ </ label >
33+ {% with placeholder="placeholder:"|add:field.label %}
34+ {{ field|addcss:"class: form-control filter-form-control"|addcss:placeholder }}
35+ {% endwith %}
36+ </ div >
37+ </ div >
38+ {% endfor %}
39+ </ div >
40+ < div class ="container-fluid ">
41+ < div class ="row mt-3 ">
42+ < div class ="col-12 ">
43+ < div class ="d-flex justify-content-end align-items-center ">
44+ {% if submit == 'report' %}
45+ {% query_string_as_hidden %}
46+ < button class ="btn btn-secondary " name ="_generate " type ="submit ">
47+ < i class ="fa-solid fa-file-lines "> </ i > Generate Report
48+ </ button >
49+ {% else %}
50+ < button id ="apply " class ="btn btn-secondary me-2 ">
51+ < i class ="fa-solid fa-filter "> </ i > Apply Filters
52+ </ button >
53+ {% if clear_js %}
54+ < a class ="btn btn-outline-secondary me-2 " href ="#{{form_id}} " id ="clear_js " role ="button ">
55+ < i class ="fa-solid fa-remove "> </ i > Clear Filters
56+ </ a >
57+ {% else %}
58+ < a class ="btn btn-outline-secondary me-2 " href ="{{ clear_link|default:request.path }} " id ="clear " role ="button " >
59+ < i class ="fa-solid fa-remove "> </ i > Clear Filters
60+ </ a >
61+ {% endif %}
62+ {% if restart_link %}
63+ < a href ="{{ restart_link }} " id ="restart " class ="btn btn-secondary ">
64+ < i class ="fa-solid fa-remove "> </ i > Restart
65+ </ a >
2766 {% endif %}
28- </ label >
29- {% with placeholder="placeholder:"|add:field.label %}
30- {{ field|addcss:"class: form-control filter-form-control"|addcss:placeholder }}
31- {% endwith %}
67+ {% endif %}
68+ </ div >
3269 </ div >
33- {% endfor %}
34- </ div >
35- {% if submit == 'report' %}
36- {% query_string_as_hidden %}
37- < div class ="inline-block " style ="vertical-align: text-top ">
38- < button class ="btn btn-secondary " name ="_generate " type ="submit ">
39- < i class ="fa-solid fa-file-lines "> </ i > Generate Report
40- </ button >
41- </ div >
42- {% else %}
43- < div class ="inline-block " style ="vertical-align: text-top ">
44- < button id ="apply " class ="btn btn-sm btn-secondary ">
45- < i class ="fa-solid fa-filter "> </ i > Apply Filters
46- </ button >
47-
48- {% if clear_js %}
49- < a href ="#{{form_id}} " id ="clear_js " class ="clear centered "> [Clear Filters] </ a >
50- {% elif clear_link %}
51- < a href ="{{ clear_link }} " id ="clear " class ="clear centered "> [Clear Filters] </ a >
52- {% else %}
53- < a href ="{{ request.path }} " id ="clear " class ="clear centered "> [Clear Filters] </ a >
54- {% endif %}
55- {% if restart_link %}
56- < a href ="{{ restart_link }} " id ="clear " class ="clear centered "> [Restart] </ a >
57- {% endif %}
5870 </ div >
59- {% endif %}
71+ </ div >
72+
6073 </ form >
61-
6274</ div >
6375< script >
6476 $ ( document ) . ready ( function ( ) {
65- $ ( ".filter-set>form" ) . first ( ) . submit ( function ( event ) {
77+ const form = $ ( ".filter-set>form" ) ;
78+ $ ( form ) . first ( ) . submit ( function ( event ) {
6679 var formData = $ ( ".filter-set>form" ) . first ( ) . serializeArray ( ) ;
6780 var filteredFormData = formData . filter ( function ( item ) {
6881 // Remove null or empty values
8194
8295 // Append the new query parameters to the base URL
8396 var newAction = baseUrl + "?" + queryParams . join ( "&" ) ;
84-
85- // Append the query parameters to the action URL
86- var newAction = baseUrl + "?" + queryParams . join ( "&" ) ;
8797 window . location . href = newAction ;
8898 event . preventDefault ( ) ;
8999 } ) ;
90- } ) ;
91- </ script >
100+
101+ // Clear filter logic below should clear filters without reload and
102+ // have the button disabled if no filters are active
103+
104+ const clearFilterLink = $ ( "#clear, #clear_js" ) ;
105+
106+ const hasActiveFilters = ( ) => {
107+ return $ ( form )
108+ . find ( ":input:not([type='hidden'])" )
109+ . filter ( function ( ) {
110+ const value = $ ( this ) . val ( ) ;
111+
112+ if ( $ ( this ) . is ( "select[multiple]" ) ) {
113+ // Checking if value is an array and has non-empty elements at the same time
114+ return Array . isArray ( value ) && value . some ( v => v && v . trim ( ) !== "" ) ;
115+ } else if ( $ ( this ) . is ( ":checkbox, :radio" ) ) {
116+ // Checkboxes and radio buttons
117+ return $ ( this ) . prop ( "checked" ) ;
118+ } else if ( typeof value === "string" ) {
119+ // Text inputs, textareas
120+ return value . trim ( ) !== "" && value !== "unknown" && value !== null ;
121+ } else {
122+ // Other input types
123+ return value !== null && value !== undefined ;
124+ }
125+ } ) . length > 0 ;
126+ } ;
127+
128+ const updateClearFiltersState = ( ) => {
129+ const filtersActive = hasActiveFilters ( ) ;
130+
131+ if ( clearFilterLink . length ) {
132+ clearFilterLink
133+ . toggleClass ( "disabled" , ! filtersActive )
134+ . toggleClass ( "btn-outline-secondary" , ! filtersActive )
135+ . toggleClass ( "btn-secondary" , filtersActive )
136+ . attr ( "aria-disabled" , ! filtersActive )
137+ . css ( "pointer-events" , filtersActive ? "auto" : "none" ) ;
138+ }
139+ } ;
140+
141+ $ ( form ) . on ( "input change" , updateClearFiltersState ) ;
142+
143+ $ ( document ) . on ( 'click' , '#clear, #clear_js' , function ( event ) {
144+ event . preventDefault ( ) ;
145+ if ( $ ( this ) . attr ( "aria-disabled" ) === "true" ) {
146+ return ;
147+ }
148+ const form = $ ( this ) . closest ( ".filter-set" ) . find ( "form" ) ;
149+ if ( form . length ) {
150+ clear_form ( form ) ;
151+ // Refresh some UI components to work have cleared form from all respective libraries
152+ form . find ( "select.selectpicker" ) . selectpicker ( "refresh" ) ;
153+ form . find ( ".multi-tag-input" ) . val ( '' ) . trigger ( 'change' ) ;
154+ form . find ( "select.select2-hidden-accessible" ) . val ( null ) . trigger ( 'change' ) ;
155+ form . find ( ".select2-selection__choice" ) . remove ( ) ;
156+ form . find ( ".select2-search__field" ) . val ( '' ) ;
157+ // Update the state for the clear filters button
158+ updateClearFiltersState ( ) ;
159+
160+ }
161+ } ) ;
162+ } ) ;
163+ </ script >
0 commit comments