PageSourceSearch

https://www.lindenhof.it/wp-content/plugins/facetwp/assets/vendor/fSelect/fSelect.js?ver=3.4.7

js lindenhof.it collected 2026-09-26 11:13:24 UTC 15,494 bytes, 439 lines download raw bytes

1/* fSelect 1.0.1 - https://github.com/mgibbs189/fselect */
2
3(function($) {
4
5    String.prototype.unaccented = function() {
6        var accent = [
7            /[\300-\306]/g, /[\340-\346]/g, // A, a
8            /[\310-\313]/g, /[\350-\353]/g, // E, e
9            /[\314-\317]/g, /[\354-\357]/g, // I, i
10            /[\322-\330]/g, /[\362-\370]/g, // O, o
11            /[\331-\334]/g, /[\371-\374]/g, // U, u
12            /[\321]/g, /[\361]/g, // N, n
13            /[\307]/g, /[\347]/g, // C, c
14        ];
15        var noaccent = ['A','a','E','e','I','i','O','o','U','u','N','n','C','c'];
16
17        var str = this;
18        for (var i = 0; i < accent.length; i++) {
19            str = str.replace(accent[i], noaccent[i]);
20        }
21
22        return str;
23    }
24
25    $.fn.fSelect = function(options) {
26
27        if ('string' === typeof options) {
28            var settings = options;
29        }
30        else {
31            var settings = $.extend({
32                placeholder: 'Select some options',
33                numDisplayed: 3,
34                overflowText: '{n} selected',
35                searchText: 'Search',
36                noResultsText: 'No results found',
37                showSearch: true,
38                optionFormatter: false
39            }, options);
40        }
41
42
43        /**
44         * Constructor
45         */
46        function fSelect(select, settings) {
47            this.$select = $(select);
48            this.settings = settings;
49            this.create();
50        }
51
52
53        /**
54         * Prototype class
55         */
56        fSelect.prototype = {
57            create: function() {
58                this.idx = 0;
59                this.optgroup = 0;
60                this.selected = [].concat(this.$select.val()); // force an array
61                this.settings.multiple = this.$select.is('[multiple]');
62
63                var search_html = '';
64                var no_results_html = '';
65                var choices_html = this.buildOptions(this.$select);
66
67                if (this.settings.showSearch) {
68                    search_html = '<div class="fs-search"><input type="text" placeholder="' + this.settings.searchText + '" /></div>';
69                }
70                if ('' !== this.settings.noResultsText) {
71                    no_results_html = '<div class="fs-no-results hidden">' + this.settings.noResultsText + '</div>';
72                }
73
74                var html = '<div class="fs-label-wrap"><div class="fs-label"></div><span class="fs-arrow"></span></div>';
75                html += '<div class="fs-dropdown hidden">{search}{no-results}<div class="fs-options">' + choices_html + '</div></div>';
76                html = html.replace('{search}', search_html);
77                html = html.replace('{no-results}', no_results_html);
78
79                this.$select.wrap('<div class="fs-wrap' + (this.settings.multiple ? ' multiple' : '') + '" tabindex="0" />');
80                this.$select.addClass('hidden');
81                this.$select.before(html);
82                this.$wrap = this.$select.closest('.fs-wrap');
83                this.$wrap.data('id', window.fSelect.num_items);
84                window.fSelect.num_items++;
85
86                this.reloadDropdownLabel();
87            },
88
89            reload: function() {
90                this.destroy();
91                this.create();
92            },
93
94            destroy: function() {
95                this.$wrap.find('.fs-label-wrap').remove();
96                this.$wrap.find('.fs-dropdown').remove();
97                this.$select.unwrap().removeClass('hidden');
98            },
99
100            buildOptions: function($element) {
101                var $this = this;
102
103                var choices = '';
104                $element.children().each(function(i, el) {
105                    var $el = $(el);
106
107                    if ('optgroup' == $el.prop('nodeName').toLowerCase()) {
108                        choices += '<div class="fs-optgroup-label" data-group="' + $this.optgroup + '">' + $el.prop('label') + '</div>';
109                        choices += $this.buildOptions($el);
110                        $this.optgroup++;
111                    }
112                    else {
113                        var val = $el.prop('value');
114                        var classes = $el.attr('class');
115                        classes = ('undefined' !== typeof classes) ? ' ' + classes : '';
116
117                        // exclude the first option in multi-select mode
118                        if (0 < $this.idx || '' != val || ! $this.settings.multiple) {
119                            var disabled = $el.is(':disabled') ? ' disabled' : '';
120                            var selected = -1 < $.inArray(val, $this.selected) ? ' selected' : '';
121                            var group = ' g' + $this.optgroup;
122                            var row = '<div class="fs-option' + selected + disabled + group + classes + '" data-value="' + val + '" data-index="' + $this.idx + '"><span class="fs-checkbox"><i></i></span><div class="fs-option-label">' + $el.html() + '</div></div>';
123
124                            if ('function' === typeof $this.settings.optionFormatter) {
125                                row = $this.settings.optionFormatter(row);
126                            }
127
128                            choices += row;
129                            $this.idx++;
130                        }
131                    }
132                });
133
134                return choices;
135            },
136
137            reloadDropdownLabel: function() {
138                var settings = this.settings;
139                var labelText = [];
140
141                this.$wrap.find('.fs-option.selected').each(function(i, el) {
142                    labelText.push($(el).find('.fs-option-label').html());
143                });
144
145                if (labelText.length < 1) {
146                    labelText = settings.placeholder;
147                }
148                else if (labelText.length > settings.numDisplayed) {
149                    labelText = settings.overflowText.replace('{n}', labelText.length);
150                }
151                else {
152                    labelText = labelText.join(', ');
153                }
154
155                this.$wrap.find('.fs-label').html(labelText);
156                this.$wrap.toggleClass('fs-default', labelText === settings.placeholder);
157            }
158        }
159
160
161        /**
162         * Loop through each matching element
163         */
164        return this.each(function() {
165            var data = $(this).data('fSelect');
166
167            if (!data) {
168                data = new fSelect(this, settings);
169                $(this).data('fSelect', data);
170            }
171
172            if ('string' === typeof settings) {
173                data[settings]();
174            }
175        });
176    }
177
178
179    /**
180     * Events
181     */
182    window.fSelect = {
183        'num_items': 0,
184        'active_id': null,
185        'active_el': null,
186        'last_choice': null,
187        'idx': -1
188    };
189
190    $(document).on('click', '.fs-option:not(.hidden, .disabled)', function(e) {
191        var $wrap = $(this).closest('.fs-wrap');
192        var $select = $wrap.find('select');
193        var do_close = false;
194
195        // prevent selections
196        if ($wrap.hasClass('fs-disabled')) {
197            return;
198        }
199
200        if ($wrap.hasClass('multiple')) {
201            var selected = [];
202
203            // shift + click support
204            if (e.shiftKey && null != window.fSelect.last_choice) {
205                var current_choice = parseInt($(this).attr('data-index'));
206                var addOrRemove = ! $(this).hasClass('selected');
207                var min = Math.min(window.fSelect.last_choice, current_choice);
208                var max = Math.max(window.fSelect.last_choice, current_choice);
209
210                for (i = min; i <= max; i++) {
211                    $wrap.find('.fs-option[data-index='+ i +']')
212                        .not('.hidden, .disabled')
213                        .each(function() {
214                            $(this).toggleClass('selected', addOrRemove);
215                        });
216                }
217            }
218            else {
219                window.fSelect.last_choice = parseInt($(this).attr('data-index'));
220                $(this).toggleClass('selected');
221            }
222
223            $wrap.find('.fs-option.selected').each(function(i, el) {
224                selected.push($(el).attr('data-value'));
225            });
226        }
227        else {
228            var selected = $(this).attr('data-value');
229            $wrap.find('.fs-option').removeClass('selected');
230            $(this).addClass('selected');
231            do_close = true;
232        }
233
234        $select.val(selected);
235        $select.fSelect('reloadDropdownLabel');
236        $select.change();
237
238        // fire an event
239        $(document).trigger('fs:changed', $wrap);
240
241        if (do_close) {
242            closeDropdown($wrap);
243        }
244    });
245
246    $(document).on('keyup', '.fs-search input', function(e) {
247        if (40 == e.which) { // down
248            $(this).blur();
249            return;
250        }
251
252        var $wrap = $(this).closest('.fs-wrap');
253        var matchOperators = /[|\\{}()[\]^$+*?.]/g;
254        var keywords = $(this).val().replace(matchOperators, '\\$&');
255
256        $wrap.find('.fs-option, .fs-optgroup-label').removeClass('hidden');
257
258        if ('' != keywords) {
259            $wrap.find('.fs-option').each(function() {
260                var regex = new RegExp(keywords.unaccented(), 'gi');
261                var formatedValue = $(this).find('.fs-option-label').text().unaccented();
262
263                if (null === formatedValue.match(regex)) {
264                    $(this).addClass('hidden');
265                }
266            });
267
268            $wrap.find('.fs-optgroup-label').each(function() {
269                var group = $(this).attr('data-group');
270                var num_visible = $(this).closest('.fs-options').find('.fs-option.g' + group + ':not(.hidden)').length;
271                if (num_visible < 1) {
272                    $(this).addClass('hidden');
273                }
274            });
275        }
276
277        setIndexes($wrap);
278        checkNoResults($wrap);
279    });
280
281    $(document).on('click', function(e) {
282        var $el = $(e.target);
283        var $wrap = $el.closest('.fs-wrap');
284
285        if (0 < $wrap.length) {
286
287            // user clicked another fSelect box
288            if ($wrap.data('id') !== window.fSelect.active_id) {
289                closeDropdown();
290            }
291
292            // fSelect box was toggled
293            if ($el.hasClass('fs-label') || $el.hasClass('fs-arrow')) {
294                var is_hidden = $wrap.find('.fs-dropdown').hasClass('hidden');
295
296                if (is_hidden) {
297                    openDropdown($wrap);
298                }
299                else {
300                    closeDropdown($wrap);
301                }
302            }
303        }
304        // clicked outside, close all fSelect boxes
305        else {
306            closeDropdown();
307        }
308    });
309
310    $(document).on('keydown', function(e) {
311        var $wrap = window.fSelect.active_el;
312        var $target = $(e.target);
313
314        // toggle the dropdown on space
315        if ($target.hasClass('fs-wrap')) {
316            if (32 == e.which || 13 == e.which) {
317                e.preventDefault();
318                $target.find('.fs-label').trigger('click');
319                return;
320            }
321        }
322        // preserve spaces during search
323        else if (0 < $target.closest('.fs-search').length) {
324            if (32 == e.which) {
325                return;
326            }
327        }
328        else if (null === $wrap) {
329            return;
330        }
331
332        if (38 == e.which) { // up
333            e.preventDefault();
334
335            $wrap.find('.fs-option.hl').removeClass('hl');
336
337            var $current = $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']');
338            var $prev = $current.prevAll('.fs-option:not(.hidden, .disabled)');
339
340            if ($prev.length > 0) {
341                window.fSelect.idx = parseInt($prev.attr('data-index'));
342                $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']').addClass('hl');
343                setScroll($wrap);
344            }
345            else {
346                window.fSelect.idx = -1;
347                $wrap.find('.fs-search input').focus();
348            }
349        }
350        else if (40 == e.which) { // down
351            e.preventDefault();
352
353            var $current = $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']');
354            if ($current.length < 1) {
355                var $next = $wrap.find('.fs-option:not(.hidden, .disabled):first');
356            }
357            else {
358                var $next = $current.nextAll('.fs-option:not(.hidden, .disabled)');
359            }
360
361            if ($next.length > 0) {
362                window.fSelect.idx = parseInt($next.attr('data-index'));
363                $wrap.find('.fs-option.hl').removeClass('hl');
364                $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']').addClass('hl');
365                setScroll($wrap);
366            }
367        }
368        else if (32 == e.which || 13 == e.which) { // space, enter
369            e.preventDefault();
370
371            $wrap.find('.fs-option.hl').click();
372        }
373        else if (27 == e.which) { // esc
374            closeDropdown($wrap);
375        }
376    });
377
378    function checkNoResults($wrap) {
379        var addOrRemove = $wrap.find('.fs-option:not(.hidden)').length > 0;
380        $wrap.find('.fs-no-results').toggleClass('hidden', addOrRemove);
381    }
382
383    function setIndexes($wrap) {
384        $wrap.find('.fs-option.hl').removeClass('hl');
385        $wrap.find('.fs-search input').focus();
386        window.fSelect.idx = -1;
387    }
388
389    function setScroll($wrap) {
390        var $container = $wrap.find('.fs-options');
391        var $selected = $wrap.find('.fs-option.hl');
392
393        var itemMin = $selected.offset().top + $container.scrollTop();
394        var itemMax = itemMin + $selected.outerHeight();
395        var containerMin = $container.offset().top + $container.scrollTop();
396        var containerMax = containerMin + $container.outerHeight();
397
398        if (itemMax > containerMax) { // scroll down
399            var to = $container.scrollTop() + itemMax - containerMax;
400            $container.scrollTop(to);
401        }
402        else if (itemMin < containerMin) { // scroll up
403            var to = $container.scrollTop() - containerMin - itemMin;
404            $container.scrollTop(to);
405        }
406    }
407
408    function openDropdown($wrap) {
409        window.fSelect.active_el = $wrap;
410        window.fSelect.active_id = $wrap.data('id');
411        window.fSelect.initial_values = $wrap.find('select').val();
412        $(document).trigger('fs:opened', $wrap);
413        $wrap.find('.fs-dropdown').removeClass('hidden');
414        $wrap.addClass('fs-open');
415        setIndexes($wrap);
416        checkNoResults($wrap);
417    }
418
419    function closeDropdown($wrap) {
420        if ('undefined' == typeof $wrap && null != window.fSelect.active_el) {
421            $wrap = window.fSelect.active_el;
422        }
423        if ('undefined' !== typeof $wrap) {
424            // only trigger if the values have changed
425            var initial_values = window.fSelect.initial_values;
426            var current_values = $wrap.find('select').val();
427            if (JSON.stringify(initial_values) != JSON.stringify(current_values)) {
428                $(document).trigger('fs:closed', $wrap);
429            }
430        }
431
432        $('.fs-wrap').removeClass('fs-open');
433        $('.fs-dropdown').addClass('hidden');
434        window.fSelect.active_el = null;
435        window.fSelect.active_id = null;
436        window.fSelect.last_choice = null;
437    }
438
439})(jQuery);

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.