PageSourceSearch

https://www.austrianwine.jp/_assets/283016a5deb98031c60d7504e8f170…/suggest_controller.js?1790768776

js austrianwine.jp collected 2026-10-02 19:52:11 UTC 13,091 bytes, 301 lines download raw bytes

1function SuggestController() {
2    var instanceCounter = 0;
3    var self = this;
4    var reinitializing = false;
5
6    function getInputId($input) {
7        if (!$input.attr('id')) {
8            instanceCounter += 1;
9            $input.attr('id', 'tx-solr-suggest-' + instanceCounter);
10        }
11
12        return $input.attr('id');
13    }
14
15    function getLiveRegion($searchBox) {
16        var liveRegionId = getInputId($searchBox) + '-status';
17        var $liveRegion = jQuery('#' + liveRegionId);
18
19        if ($liveRegion.length === 0) {
20            $liveRegion = jQuery('<div></div>').attr({
21                'id': liveRegionId,
22                'class': 'sr-only',
23                'aria-live': 'polite',
24                'aria-atomic': 'true'
25            });
26            $searchBox.after($liveRegion);
27        }
28
29        return $liveRegion;
30    }
31
32    function updateActiveDescendant($searchBox) {
33        var listboxId = $searchBox.attr('aria-controls');
34        var $listbox = listboxId ? jQuery('#' + listboxId) : jQuery();
35        var $selected = $listbox.find('.autocomplete-selected').first();
36        var $liveRegion = getLiveRegion($searchBox);
37
38        if ($selected.length) {
39            var optionLabel = $selected.attr('aria-label') || $selected.find('.sr-only').first().text().trim() || $selected.text().trim();
40
41            $searchBox.attr('aria-activedescendant', $selected.attr('id'));
42            $listbox.find('.autocomplete-suggestion').attr('aria-selected', 'false');
43            $selected.attr('aria-selected', 'true');
44            $liveRegion.text('');
45            setTimeout(function () {
46                $liveRegion.text(optionLabel);
47            }, 0);
48        } else {
49            $searchBox.removeAttr('aria-activedescendant');
50            $liveRegion.text('');
51        }
52    }
53
54    function syncSuggestionsWidth($searchBox, $container) {
55        var searchBoxWidth = $searchBox[0].getBoundingClientRect().width,
56            $inputGroup = $searchBox.closest('.input-group'),
57            addonWidth = $inputGroup.find('.input-group-addon').first().outerWidth() || 0,
58            isBodyContainer = $container.parent()[0] === document.body;
59
60        if (searchBoxWidth > 0) {
61            $container.css({
62                width: isBodyContainer
63                    ? Math.ceil(searchBoxWidth + addonWidth) + 'px'
64                    : Math.ceil(searchBoxWidth) + 'px',
65                'margin-left': isBodyContainer ? -addonWidth + 'px' : '0'
66            });
67        }
68    }
69
70    function isSmallMobileViewport() {
71        return window.matchMedia('only screen and (max-width: 767px)').matches;
72    }
73
74    this.init = function () {
75
76        jQuery('form[data-suggest]').each(function () {
77            var $form = jQuery(this), $searchBox = $form.find('.tx-solr-suggest');
78            var $formAutoComplete;
79
80            if ($form.find('.tx-solr-autocomplete').length > 0){
81                $formAutoComplete = $form.find('.tx-solr-autocomplete');
82            } else if (isSmallMobileViewport()) {
83                $formAutoComplete = $searchBox.closest('.input-group');
84                if ($formAutoComplete.length === 0) {
85                    $formAutoComplete = jQuery('body');
86                }
87            } else {
88                $formAutoComplete = jQuery('body');
89            }
90
91            $form.find('.tx-solr-suggest-focus').focus();
92
93            // when no specific container found, use the form as container
94            if ($searchBox.length === 0) {
95                $searchBox = $form;
96            }
97            $searchBox.css('position', 'relative');
98            var inputId = getInputId($searchBox);
99            var listboxId = inputId + '-listbox';
100            $searchBox.attr({
101                'role': 'combobox',
102                'aria-autocomplete': 'list',
103                'aria-expanded': 'false',
104                'aria-haspopup': 'listbox',
105                'aria-controls': listboxId
106            });
107
108            $searchBox.off('keyup.autocompleteA11y').on('keyup.autocompleteA11y', function (e) {
109                if (e.which === 38 || e.which === 40) {
110                    updateActiveDescendant($searchBox);
111                }
112            });
113
114            // Prevent submit of empty search form
115            $form.off('submit.solrSuggest').on('submit.solrSuggest', function (e) {
116                if ($form.find('.tx-solr-suggest').val() === '') {
117                    e.preventDefault();
118                    $form.find('.tx-solr-suggest').focus();
119                }
120            });
121
122
123
124            var $input = $form.find('.tx-solr-suggest');
125
126            $input.devbridgeAutocomplete({
127                serviceUrl: $form.data('suggest'),
128                dataType: 'json',
129                paramName: 'tx_solr[queryString]',
130                groupBy: 'category',
131                maxHeight: 1000,
132                appendTo: $formAutoComplete,
133                forceFixPosition: true,
134                autoSelectFirst: false,
135                triggerSelectOnValidInput: false,
136                // Keep the width set in beforeRender; the library overwrites
137                // the width during fixPosition when this is set to 'auto'.
138                width: 'flex',
139                zIndex: 20,
140                onHide: function () {
141                    $searchBox.attr('aria-expanded', 'false').removeAttr('aria-activedescendant');
142                    getLiveRegion($searchBox).text('');
143                },
144                onSelect: function (suggestion) {
145                    // go to link when selecting found result
146                    if (suggestion.data.link) {
147                        // Open youtube in overlay
148                        if (suggestion.data.link.indexOf('https://www.youtube.com') === 0) {
149                            openVideoOverlay(suggestion.data.link);
150                        } else {
151                            location.href = suggestion.data.link;
152                        }
153                        // else trigger form submit (do search)
154                    } else {
155                        $form.trigger('submit');
156                    }
157                },
158                transformResult: function (response) {
159                    if (!response.suggestions) return {suggestions: []};
160                    var firstSuggestion, result = {
161                        suggestions: $.map(response.suggestions, function (count, suggestion) {
162                            if (!firstSuggestion) firstSuggestion = suggestion;
163                            return {value: suggestion, data: {category: 'suggestion', count: count}};
164                        })
165                    };
166
167                    $.each(response.documents, function (key, value) {
168                        var dataObject = value;
169
170                        var defaultGroup = $form.data('suggest-header') ? $form.data('suggest-header') : 'Top results';
171                        dataObject.category = defaultGroup;
172
173                        // if a group is set we try to get a label
174                        if(dataObject.group) {
175                            dataObject.category = $form.data('suggest-header-' + dataObject.group) ? $form.data('suggest-header-' + dataObject.group) : dataObject.group;
176                        }
177
178                        result.suggestions.push(
179                            {
180                                value: firstSuggestion,
181                                data: dataObject
182                            }
183                        );
184                    });
185
186                    return result;
187                },
188                beforeRender: function (container) {
189                    syncSuggestionsWidth($searchBox, container);
190
191                    // remove first group header
192                    container.find('.autocomplete-group:first').remove();
193                    container.addClass('tx-solr-autosuggest').attr({
194                        'id': listboxId,
195                        'role': 'listbox',
196                        'aria-label': $searchBox.data('suggestionsLabel') || 'Search suggestions'
197                    });
198
199                    container.find('.autocomplete-suggestion').each(function (index) {
200                        var $option = jQuery(this);
201                        var optionLabel = $option.find('.sr-only').first().text().trim() || $option.text().trim();
202
203                        $option.attr({
204                            'role': 'option',
205                            'id': listboxId + '-option-' + index,
206                            'aria-selected': 'false',
207                            'aria-label': optionLabel
208                        });
209                    });
210
211                    container.find('.autocomplete-group').attr('role', 'presentation');
212
213                    // add active class to container
214                    $searchBox.parent().addClass('autocomplete-active').fadeIn();
215                    $searchBox.attr('aria-expanded', 'true');
216                    updateActiveDescendant($searchBox);
217                },
218                formatResult: function (suggestion, currentValue) {
219                    // Do not replace anything if there current value is empty
220                    if (!currentValue) {
221                        return suggestion.value;
222                    }
223                    var pattern = '(' + $.Autocomplete.utils.escapeRegExChars(currentValue.trim()) + ')';
224                    // normal suggestion
225                    if (suggestion.data.category === 'suggestion') {
226                        var visualText = suggestion.value
227                            .replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>')
228                            .replace(/&/g, '&amp;')
229                            .replace(/</g, '&lt;')
230                            .replace(/>/g, '&gt;')
231                            .replace(/"/g, '&quot;')
232                            .replace(/&lt;(\/?strong)&gt;/g, '<$1>');
233
234                        var cleanText = suggestion.value
235                            .replace(/&/g, '&amp;')
236                            .replace(/</g, '&lt;')
237                            .replace(/>/g, '&gt;')
238                            .replace(/"/g, '&quot;');
239
240                        return '<span aria-hidden="true">' + visualText + '</span>' +
241                            '<span class="sr-only">' + cleanText + '</span>';
242
243                        // results
244                    } else {
245                        var title = suggestion.data.title
246                            .replace(new RegExp(pattern, 'gi'), '<em>$1<\/em>')
247                            .replace(/&/g, '&amp;')
248                            .replace(/</g, '&lt;')
249                            .replace(/>/g, '&gt;')
250                            .replace(/"/g, '&quot;')
251                            .replace(/&lt;(\/?em)&gt;/g, '<$1>');
252
253                        return '<div class="' + suggestion.data.type + '">' +
254                            (!!suggestion.data.previewImage ? '<figure ' + (!!suggestion.data.hasVideo ? 'class="hasVideo"' : '') + '>
254<img src="' + suggestion.data.previewImage + '" alt="" /></figure>' : '') +
255                            '<span class="sr-only">' + suggestion.data.category + ': ' + suggestion.data.title + '</span>' +
256                            '<a href="' + suggestion.data.link + '" class="internal-link" tabindex="-1"><span aria-hidden="true">' + title + '</span></a>' +
257                            '</div>';
258                    }
259
260                }
261            }).off('blur.solrSuggest').on('blur.solrSuggest', function () {
262                $searchBox.parent().removeClass('autocomplete-active');
263                $searchBox.attr('aria-expanded', 'false');
264                var $box = jQuery(this);
265                setTimeout(function () {
266                    $box.devbridgeAutocomplete('hide');
267                }, 200);
268            });
269
270            var mobileViewport = isSmallMobileViewport();
271            $searchBox.data('solrSuggestionsMobileViewport', mobileViewport);
272            jQuery(window)
273                .off('resize.solrSuggestions-' + inputId)
274                .on('resize.solrSuggestions-' + inputId, function () {
275                    var currentMobileViewport = isSmallMobileViewport();
276
277                    if (currentMobileViewport !== $searchBox.data('solrSuggestionsMobileViewport')) {
278                        if (!reinitializing) {
279                            reinitializing = true;
280                            self.init();
281                            if (window.solrSearchController && typeof window.solrSearchController.clearSearch === 'function') {
282                                window.solrSearchController.clearSearch();
283                            }
284                            reinitializing = false;
285                        }
286                    }
287                });
288
289        });
290    };
291}
292
293jQuery(document).ready(function() {
294    /** solr search autocomplete **/
295    var solrSuggestController = new SuggestController();
296    solrSuggestController.init();
297    jQuery("body").on("tx_solr_updated", function() {
298        solrSuggestController.init();
299    });
300
301});

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.