PageSourceSearch

https://www.komkids.nl/wp-content/themes/buro26/vendor/js/filter26.js?ver=7.1.2

js komkids.nl collected 2026-10-07 10:42:29 UTC 11,736 bytes, 322 lines download raw bytes

1/**
2 * Filter26
3 * @version 1.1.1
4 * @description Filter26 is een filter plugin die het mogelijk maakt om items te filteren op basis van data attributen.
5 * @author Buro26
6 */
7
8// Zet een reference naar jQuery als $ geen function is of undefined.
9if (typeof $ !== 'function') {
10    $ = (typeof jQuery === 'function') ? jQuery : undefined;
11}
12
13class Filter26 {
14    constructor ({
15        filterableItems = '.filter-item',
16        animationType = 'fade',
17        animationDuration = 200,
18        filterBtn = '.filterBtn',
19        itemCounter = '.item-counter',
20        resetFiltersBtn = '.reset-filter',
21        filterSelect,
22        filterRange,
23        useUrlParams
24    }) {
25        this.filterableItems = filterableItems
26        this.animationType = animationType
27        this.animationDuration = animationDuration
28        this.filterBtn = filterBtn
29        this.itemCounter = itemCounter
30        this.resetFiltersBtn = resetFiltersBtn
31        this.filterSelect = filterSelect
32        this.filterRange = filterRange
33        this.useUrlParams = useUrlParams
34
35        this.filters = {}
36
37        this.startFiltering();
38    }
39
40    /**
41     * Start het filteren.
42     */
43    startFiltering() {
44        $(document).ready(() => {
45            if (!this.filterableItems) this.setError('Filter26: geen filterableItems ingesteld')
46            if (!this.filterBtn) this.setError('Filter26: geen filterBtn ingesteld')
47            if (!this.itemCounter) this.setError('Filter26: geen itemCounter ingesteld')
48            if (!this.filterSelect) this.setError('Filter26: geen filterSelect ingesteld')
49            if (!this.filterRange) this.setError('Filter26: geen filterRange ingesteld')
50
51            this.triggerEvent('filter26:onFilterStart')
52            this.restoreFiltersFromUrl()
53
54            if (this.itemCounter) {
55                this.updateCounter()
56            }
57        })
58
59        // Filteren met buttons
60        if (this.filterBtn) {
61            $(this.filterBtn).on('click', (e) => {
62                const filter = $(e.target)
63                let filterButtonId = filter.attr('id');
64                if (this.useUrlParams) this.storeFilterInUrl(filterButtonId, filter.data(filterButtonId))
65                this.updateFilterObject(filterButtonId, filter.data(filterButtonId))
66                if (!filterButtonId) this.setError('Filter26: Geen id op de filterbutton gevonden!');
67                this.setActiveFilter(filter)
68                this.doFilter(this.filters)
69            })
70        }
71
72        // Filteren met selects
73        if (this.filterSelect) {
74            $(this.filterSelect).on('change', (e) => {
75                const filterSelect = $(e.target);
76                if (filterSelect.attr('id') !== 'sort') {
77                    if (this.useUrlParams) this.storeFilterInUrl(filterSelect.attr('id'), filterSelect.val())
78                    this.updateFilterObject(filterSelect.attr('id'), filterSelect.val())
79                    this.doFilter(this.filters)
80                } else if (filterSelect.attr('id') === 'sort') {
81                    let sort = filterSelect.find(":selected").val()
82                    let sortBy = sort.split('-')[0]
83                    let sortOrder = sort.split('-')[1]
84                    this.sortItems(sortBy, sortOrder)
85                }
86            })
87        }
88
89        // Filteren met ranges
90        if (this.filterRange) {
91            $(this.filterRange).on('change', (e) => {
92                const filterRange = $(e.target);
93                if (filterRange.attr('id') !== 'sort') {
94                    if (this.useUrlParams) this.storeFilterInUrl(filterRange.attr('id'), filterRange.val())
95                    this.updateFilterObject(filterRange.attr('id'), filterRange.val())
96                    this.doFilter(this.filters)
97                } else if (filterRange.attr('id') === 'sort') {
98                    let sort = filterRange.find(":selected").val()
99                    let sortBy = sort.split('-')[0]
100                    let sortOrder = sort.split('-')[1]
101                    this.sortItems(sortBy, sortOrder)
102                }
103            })
104        }
105
106        // Reset filters
107        if (this.resetFiltersBtn) {
108            $(this.resetFiltersBtn).on('click', () => {
109                this.filters = {}
110                $(this.filterableItems).show(this.animationDuration)
111                $(this.filterBtn).removeClass('active')
112                $(this.filterSelect).val('')
113                this.updateCounter()
114                this.removeUrlParams()
115            })
116        }
117
118        $(window).on('popstate', (e) => {
119            this.restoreFiltersFromUrl()
120        })
121    }
122
123    /**
124     * Verwijder de URL parameters.
125     */
126    removeUrlParams() {
127        window.location.search = '';
128        window.location.href.replace(window.location.search, '');
129    }
130
131    /**
132     * Zet een error.
133     * @param {String} message - De error message.
134     */
135    setError(message) {
136        console.log('Filter26: ' + message)
137    }
138
139    /**
140     * Sorteer de items.
141     * @param {String} sortBy - De naam van de filter.
142     * @param {String} sortOrder - De waarde van de filter.
143     */
144    sortItems(sortBy, sortOrder) {
145        this.triggerEvent('filter26:onSortingStart', { sortBy, sortOrder })
146
147        let visibleItems = $(this.filterableItems + ':visible');
148        visibleItems.fadeOut(100);
149
150        visibleItems.sort(function (a, b) {
151            let valueA = $(a).data(sortBy);
152            let valueB = $(b).data(sortBy);
153
154            // Sorteer de items op basis van hun data attribuut.
155            if (sortOrder === 'asc') {
156                return valueA.localeCompare(valueB);
157            } else {
158                return valueB.localeCompare(valueA);
159            }
160        }).appendTo($(this.filterableItems).parent()).fadeIn(100);
161        if (this.useUrlParams) this.storeFilterInUrl('sort', sortBy + '-' + sortOrder)
162    }
163
164    /**
165     * Update de filter object.
166     * @param {String} filterName - De naam van de filter.
167     * @param {String} filterValue - De waarde van de filter.
168     */
169    updateFilterObject(filterName, filterValue) {
170        if (filterValue !== '') {
171            // Controleer eerst of de filter al bestaat, zo ja, update de waarde
172            if (this.filters[filterName]) {
173                this.filters[filterName].value = filterValue;
174            } else {
175                this.filters[filterName] = { key: filterName, value: filterValue };
176            }
177        } else {
178            delete this.filters[filterName]
179            let animationType = this.animationType
180            let animationDuration = this.animationDuration
181
182            if (Object.keys(this.filters).length === 0) {
183                if (animationType === 'show') $(this.filterableItems).show(animationDuration)
184                else $(this.filterableItems).fadeIn(animationDuration)
185            }
186        }
187    }
188
189    /**
190     * Haalt de filters op uit de URL.
191     */
192    restoreFiltersFromUrl() {
193        const urlParams = new URLSearchParams(window.location.search);
194
195        urlParams.forEach((urlValue, urlKey) => {
196            const filter = $(`#${urlKey}`)
197            if (filter.length && urlKey !== 'sort') {
198                this.updateFilterObject(urlKey, urlValue)
199                let filterButtonId = filter.attr('id');
200                $(this.filterBtn).removeClass('active')
201                $(`#${urlKey}[data-${filterButtonId}="${urlValue}"]`).addClass('active') // Zet de button op de juiste filterwaarde
202                $('#' + urlKey).val(urlValue); // Zet de select elementen op de juiste filterwaarde
203            }
204        })
205
206        this.doFilter(this.filters)
207
208        // Als het filteren klaar is en er is een sorteer parameter meegegeven, sorteer dan de items.
209        $(this.filterableItems).promise().done(() => {
210            if (urlParams.has('sort')) {
211                let sortBy = urlParams.get('sort').split('-')[0]
212                let sortOrder = urlParams.get('sort').split('-')[1]
213                this.sortItems(sortBy, sortOrder)
214
215                $('#sort').val(urlParams.get('sort'))
216            }
217        })
218    }
219
220    /**
221     * Slaat de filter op in de URL.
222     * @param {String} filterName - De naam van de filter.
223     * @param {String} filterValue - De waarde van de filter.
224     */
225    storeFilterInUrl(filterName, filterValue) {
226        const urlParams = new URLSearchParams(window.location.search)
227        if (filterName && filterValue) {
228            urlParams.set(filterName, filterValue)
229        } else if (!filterValue) {
230            urlParams.delete(filterName)
231        }
232        history.pushState(null, '', `${window.location.pathname}?${urlParams.toString()}`)
233    }
234
235    /**
236     * Zet de actieve filter button.
237     * @param {Object} filter - De filter button.
238     */
239    setActiveFilter(filter) {
240        $(this.filterBtn).removeClass('active')
241        filter.addClass('active')
242    }
243
244    /**
245     * Update de teller van de items.
246     */
247    updateCounter() {
248        const numberOfVisibleItems = $(this.filterableItems + ':visible').length;
249        const itemCounter = $(this.itemCounter);
250
251        itemCounter.animate({ itemCounter: numberOfVisibleItems }, {
252            duration: this.animationDuration,
253            easing: 'swing',
254            step: function (currentNumber) {
255                itemCounter.text(Math.ceil(currentNumber))
256            }
257        });
258
259        this.triggerEvent('filter26:onFilterEnd', { filters: this.filters, numberOfVisibleItems })
260    }
261
262    /**
263     * Trigger een event.
264     * @param {String} eventName - De naam van het event.
265     * @param {Object} data - De data die meegegeven moet worden.
266     */
267    triggerEvent(eventName, data) {
268        $(this.filterableItems).trigger(eventName, { data });
269    }
270
271    /**
272     * Filtert de items op basis van de meegegeven filters.
273     * @param {Object} filters - The filters to apply.
274     */
275    doFilter(filters) {
276        $(this.filterableItems).hide();
277        this.triggerEvent('filter26:onFilterProgress', filters);
278
279        let animationType = this.animationType;
280        let animationDuration = this.animationDuration;
281
282        $(this.filterableItems).each((index, element) => {
283            const item = $(element);
284            let visible = true;
285
286            for (let [filterGroep, filterKeuze] of Object.entries(filters)) {
287                if (this.filterRange && (filterGroep.endsWith("-from") || filterGroep.endsWith("-to"))) {
288                    const filterKey = filterGroep.split('-')[0];
289
290                    // Converteer de datum naar een Date object.
291                    const parseDate = (dateString) => {
292                        const [day, month, year] = dateString.split('-').map(Number);
293                        return new Date(year, month - 1, day);
294                    };
295
296                    const cardDate = parseDate(item.data(filterKey));
297                    const filterDate = parseDate(filterKeuze.value);
298
299                    if ((filterGroep.endsWith("-from") && cardDate < filterDate) ||
300                        (filterGroep.endsWith("-to") && cardDate > filterDate)) {
301                        visible = false;
302                    }
303                } else {
304                    const itemValue = item.data(filterGroep);
305                    if (!itemValue || !itemValue.toString().includes(filterKeuze.value)) {
306                        visible = false;
307                    }
308                }
309            }
310
311            if (visible) {
312                if (animationType === 'show') item.show(animationDuration);
313                else item.fadeIn(animationDuration);
314            }
315        });
316
317        $(this.filterableItems).promise().done(() => {
318            this.updateCounter();
319        });
320    }
321
322}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.