PageSourceSearch

https://www.moulinex.com/_ui/addons/gsebstorefrontcommons/desktop/…/search/gseb.richautocomplete.js?v=26.10.0

js moulinex.com collected 2026-10-01 12:26:07 UTC 25,423 bytes, 677 lines download raw bytes

vendor: 4,785 bytes, lines 1-129
1(function ($, window, document, undefined) {
2
3  $.widget( "ui.advancedAutocomplete", $.ui.autocomplete, {
4
5    _create: function() {
6      // Some browsers only repeat keydown events, not keypress events,
7      // so we use the suppressKeyPress flag to determine if we've already
8      // handled the keydown event. #7269
9      // Unfortunately the code for & in keypress is the same as the up arrow,
10      // so we use the suppressKeyPressRepeat flag to avoid handling keypress
11      // events when we know the keydown event was used to modify the
12      // search term. #7799
13      var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
14        nodeName = this.element[ 0 ].nodeName.toLowerCase(),
15        isTextarea = nodeName === "textarea",
16        isInput = nodeName === "input";
17
18      this.isMultiLine =
19        // Textareas are always multi-line
20        isTextarea ? true :
21          // Inputs are always single-line, even if inside a contentEditable element
22          // IE also treats inputs as contentEditable
23          isInput ? false :
24            // All other element types are determined by whether or not they're contentEditable
25            this.element.prop( "isContentEditable" );
26
27      this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
28      this.isNewMenu = true;
29
30      this.element
31        .addClass( "ui-autocomplete-input" )
32        .attr( "autocomplete", "off" );
33
34      this._on( this.element, {
35        keydown: function( event ) {
36          if ( this.element.prop( "readOnly" ) ) {
37            suppressKeyPress = true;
38            suppressInput = true;
39            suppressKeyPressRepeat = true;
40            return;
41          }
42
43          suppressKeyPress = false;
44          suppressInput = false;
45          suppressKeyPressRepeat = false;
46          var keyCode = $.ui.keyCode;
47          switch ( event.keyCode ) {
48            case keyCode.PAGE_UP:
49              suppressKeyPress = true;
50              this._move( "previousPage", event );
51              break;
52            case keyCode.PAGE_DOWN:
53              suppressKeyPress = true;
54              this._move( "nextPage", event );
55              break;
56            case keyCode.UP:
57              suppressKeyPress = true;
58              this._keyEvent( "previous", event );
59              break;
60            case keyCode.DOWN:
61              suppressKeyPress = true;
62              this._keyEvent( "next", event );
63              break;
64            case keyCode.ENTER:
65              // when menu is open and has focus
66              if ( this.menu.active ) {
67                // #6055 - Opera still allows the keypress to occur
68                // which causes forms to submit
69                suppressKeyPress = true;
70                event.preventDefault();
71                this.menu.select( event );
72              }
73              break;
74            case keyCode.TAB:
75              if ( this.menu.active ) {
76                this.menu.select( event );
77              }
78              break;
79            case keyCode.ESCAPE:
80              if ( this.menu.element.is( ":visible" ) ) {
81                if ( !this.isMultiLine ) {
82                  this._value( this.term );
83                }
84                this.close( event );
85                // Different browsers have different default behavior for escape
86                // Single press can mean undo or clear
87                // Double press in IE means clear the whole form
88                event.preventDefault();
89              }
90              break;
91            default:
92              suppressKeyPressRepeat = true;
93              // search timeout should be triggered before the input value is changed
94              this._searchTimeout( event );
95              break;
96          }
97        },
98        keypress: function( event ) {
99          if ( suppressKeyPress ) {
100            suppressKeyPress = false;
101            if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
102              event.preventDefault();
103            }
104            return;
105          }
106          if ( suppressKeyPressRepeat ) {
107            return;
108          }
109
110          // replicate some key handlers to allow them to repeat in Firefox and Opera
111          var keyCode = $.ui.keyCode;
112          switch ( event.keyCode ) {
113            case keyCode.PAGE_UP:
114              this._move( "previousPage", event );
115              break;
116            case keyCode.PAGE_DOWN:
117              this._move( "nextPage", event );
118              break;
119            case keyCode.UP:
120              this._keyEvent( "previous", event );
121              break;
122            case keyCode.DOWN:
123              this._keyEvent( "next", event );
124              break;
125          }
126        },
127        input: function( event ) {
128          if ( suppressInput ) {
129            suppressInput = false;
130            event.preventDefault();
131            return;
132          }
133          this._searchTimeout( event );
134        },
135        focus: function( event ) {
136          // show OneClick-Suggest on focus
137          if (this.element.val().length < ( this.options.minLength || 1)) {
138            this.options.oneClickSuggestHandler.call(this);
139          }
140          this.selectedItem = null;
141          this.previous = this._value();
142        },
143        blur: function( event ) {
144          (this.options.onBeforeBlurHandler || function () {}).call(this, event);
145          if ( this.cancelBlur ) {
146            delete this.cancelBlur;
147            return;
148          }
149
150          clearTimeout( this.searching );
151        }
152      });
153
154      this._initSource();
155      this.menu = $( "<div>" )
156        .addClass( "ui-autocomplete ui-front autocomplete-container" )
157        .appendTo( this._appendTo() )
158        .menu({
159          // disable ARIA support, the live region takes care of that
160          role: null
161        })
162        .hide()
163        .data("ui-menu");
164      //.menu( "instance" );
165
166      this._on( this.menu.element, {
167        mousedown: function( event ) {
168          // prevent moving focus out of the text field
169          event.preventDefault();
170
171          // IE doesn't prevent moving focus even with event.preventDefault()
172          // so we set a flag to know when we should ignore the blur event
173          this.cancelBlur = true;
174          this._delay(function() {
175            delete this.cancelBlur;
176          });
177
178          // clicking on the scrollbar causes focus to shift to the body
179          // but we can't detect a mouseup or a click immediately afterward
180          // so we have to track the next mousedown and close the menu if
181          // the user clicks somewhere outside of the autocomplete
182          var menuElement = this.menu.element[ 0 ];
183          if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
184            this._delay(function() {
185              var that = this;
186              this.document.one( "mousedown", function( event ) {
187                if ( event.target !== that.element[ 0 ] &&
188                  event.target !== menuElement &&
189                  !$.contains( menuElement, event.target ) && !that.cancelBlur) {
190                  that.close();
191                }
192                that._delay(function() {
193                  delete that.cancelBlur;
194                });
195              });
196            });
197          }
198        },
199        menufocus: function( event, ui ) {
200          var label, item;
201          // support: Firefox
202          // Prevent accidental activation of menu items in Firefox (#7024 #9118)
203          if ( this.isNewMenu ) {
204            this.isNewMenu = false;
205            if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
206              this.menu.blur();
207
208              this.document.one( "mousemove", function() {
209                $( event.target ).trigger( event.originalEvent );
210              });
211
212              return;
213            }
214          }
215
216          item = ui.item.data( "ui-autocomplete-item" );
217          if ( false !== this._trigger( "focus", event, { item: item } ) ) {
218            // use value to match what will end up in the input, if it was a key event
219            if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
220              this._value( item.value );
221            }
222          }
223
224          // Announce the value in the liveRegion
225          label = ui.item.attr( "aria-label" ) || ( item ? item.value : '' );
226          if ( label && $.trim( label ).length ) {
227            this.liveRegion.children().hide();
228            $( "<div>" ).text( label ).appendTo( this.liveRegion );
229          }
230        },
231        menuselect: function( event, ui ) {
232          var item = ui.item.data( "ui-autocomplete-item" ),
233            previous = this.previous;
234
235          // only trigger when focus was lost (click on menu)
236          if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
237            this.element.focus();
238            this.previous = previous;
239            // #6109 - IE triggers two focus events and the second
240            // is asynchronous, so we need to reset the previous
241            // term synchronously and asynchronously :-(
242            this._delay(function() {
243              this.previous = previous;
244              this.selectedItem = item;
245            });
246          }
247
248          if ( false !== this._trigger( "select", event, { item: item } ) ) {
249            this._value( item.value );
250          }
251          // reset the term after the select event
252          // this allows custom select handling to work properly
253          this.term = this._value();
254
255          this.close( event );
256          this.selectedItem = item;
257        }
258      });
259
260      this.liveRegion = $( "<span>", {
261        role: "status",
262        "aria-live": "assertive",
263        "aria-relevant": "additions"
264      })
265        .addClass( "ui-helper-hidden-accessible" )
266        .appendTo( this.document[ 0 ].body );
267
268      // turning off autocomplete prevents the browser from remembering the
269      // value when navigating through history, so we re-enable autocomplete
270      // if the page is unloaded before the widget is destroyed. #7790
271      this._on( this.window, {
272        beforeunload: function() {
273          this.element.removeAttr( "autocomplete" );
274        }
275      });
276    },
277
278    search: function( value, event ) {
279      value = value != null ? value : this._value();
280
281      // always save the actual value, not the one passed as an argument
282      this.term = this._value();
283
284      if (!value.length) {
285        // show OneClick-Suggest if term.length = 0
286        this.options.oneClickSuggestHandler.call(this);
287        return false;
288      } else if ( value.length < this.options.minLength ) {
289        // close if  1 <= term.length < minLength
290        return this.close( event );
291      }
292
293      if ( this._trigger( "search", event ) === false ) {
294        return;
295      }
296
297      return this._search( value );
298    },
299
300    __response: function( content ) {
301      if ( content ) {
302        // get render function
303        this.__renderMenu = content.render;
304        content = this._normalize( content );
305      }
306      this._trigger( "response", null, { content: content } );
307      // show suggest if we have a __renderMenu function
308      // or we have a content Array
309      if ( !this.options.disabled && content && (content.length || !!this.__renderMenu) && !this.cancelSearch ) {
310        this._suggest( content );
311        this._trigger( "open" );
312      } else {
313        // use ._close() instead of .close() so we don't cancel future searches
314        this._close();
315      }
316    },
317
318    _suggest: function( items ) {
319      var ul = this.menu.element.empty();
320      // use render function stored in __renderMenu if exist
321      // or use default function "_renderMenu"
322      (this.__renderMenu || this._renderMenu)( ul, items );
323      this.__renderMenu = undefined;
324      this.isNewMenu = true;
325      //this.menu.refresh();
326
327      // size and position menu
328      ul.show();
329      //this._resizeMenu();
330      ul.position( $.extend({
331        of: this.element
332      }, this.options.position ) );
333
334      if ( this.options.autoFocus ) {
335        this.menu.next();
336      }
337    }
338  });
339
340  $.extend( $.ui.advancedAutocomplete, {
341    escapeRegex: function( value ) {
342      return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
343    },
344    filter: function( array, term ) {
345      var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
346      return $.grep( array, function( value ) {
347        return matcher.test( value.label || value.value || value );
348      });
349    }
350  });
351
352// live region extension, adding a `messages` option
353// NOTE: This is an experimental API. We are still investigating
354// a full solution for string manipulation and internationalization.
355  $.widget( "ui.advancedAutocomplete", $.ui.advancedAutocomplete, {
356    options: {
357      messages: {
358        noResults: "No search results.",
359        results: function( amount ) {
360          return amount + ( amount > 1 ? " results are" : " result is" ) +
361            " available, use up and down arrow keys to navigate.";
362        }
363      }
364    },
365
366    __response: function( content ) {
367      var message;
368      this._superApply( arguments );
369      if ( this.options.disabled || this.cancelSearch ) {
370        return;
371      }
372      if ( content && content.length ) {
373        message = this.options.messages.results( content.length );
374      } else {
375        message = this.options.messages.noResults;
376      }
377      this.liveRegion.children().hide();
378      $( "<div>" ).text( message ).appendTo( this.liveRegion );
379    }
380  });
381
382  var advancedAutocomplete = $.ui.advancedAutocomplete;
383})(window.jQuery, window, document);
384
385(function ($) {
386  try {
387    // delete element and return innerHTML
388    function getCMSBlock (selector) {
389      var $elem = $(selector);
390      var $temp = $elem.html();
391      $elem.remove();
392      return $temp;
393    }
394
395    // delete (noResult & oneClickSuggest) block from dom
396    $.extend(GSEB.options.richAutocomplete, {
397      noResult: getCMSBlock('#noResult-container'),
398      oneClickSuggest: getCMSBlock('#oneClickSuggest-container')
399    });
400
401    GSEB.allBrands.richAutocomplete = (function () {
402      var self = {
403        getRichSuggestions: function (formname, globalId, id, url) {
404          $(id).advancedAutocomplete((function () {
405            var currentInstance;
406            var term;
407            var openingMode;
408            var allowSubmit = false;
409            var options = {
410              appendTo: "#autocomplete-container",
411              minLength: 2,
412              autoFocus: false,
413              renderOptions: {
414                autoSuggest: function (ul, items, innerHTML, noResult) {
415                  allowSubmit = true;
416                  ul.removeClass('one-click-suggest');
417                  ul.removeClass('no-result-found');
418                  return innerHTML;
419                },
420                noResult: function (ul, items, innerHTML, noResult) {
421                  allowSubmit = false;
422                  ul.removeClass('one-click-suggest');
423                  ul.addClass('no-result-found');
424                  var $result = $(GSEB.options.richAutocomplete.noResult);
425                  $result.find('#autosuggest-search-term').text(term);
426                  return $result[0].outerHTML;
427                },
428                oneClickSuggest: function (ul, items, innerHTML, noResult) {
429                  allowSubmit = false;
430                  ul.removeClass('no-result-found');
431                  ul.addClass('one-click-suggest');
432                  return GSEB.options.richAutocomplete.oneClickSuggest;
433                }
434              },
435              render: function (ul, items, innerHTML, noResult) {
436                $(options.appendTo || '.ui-menu').css('display', 'block');
437                self.toggleBodyScrolling(false);
438                openingMode = noResult ? 'noResult' : (innerHTML ? 'autoSuggest' : 'oneClickSuggest')
439                ul.html((options.renderOptions[openingMode])(ul, items, innerHTML, noResult))
440              },
441              source: function (request, response) {
442                currentInstance = this;
443                term = request.term;
444                var _options = this.options;
445                $.get(url, request, function (ajaxResponce) {
446                  var _innerHTMLResponce = $(ajaxResponce).html();
447                  var _response = [];
448                  _response.render = function (ul, items) {
449                    _options.render(ul, items, _innerHTMLResponce, _innerHTMLResponce && !_innerHTMLResponce.trim().length)
450                  };
451                  response(_response);
452                }).fail(function () {
453                  var _innerHTMLResponce = GSEB.options.richAutocomplete.autocompleteNotFound;
454                  var _response = [];
455                  _response.render = function (ul, items) {
456                    _options.render(ul, items, _innerHTMLResponce, _innerHTMLResponce && _innerHTMLResponce.trim().length)
457                  };
458                  response(_response);
459                });
460              },
461              response: function (event, ui) {
462
463              },
464              oneClickSuggestHandler: function () {
465                currentInstance = this;
466                if (!!$(GSEB.options.richAutocomplete.oneClickSuggest).find('.autocomplete-cat').length) {
467                  this.__renderMenu = this.options.render;
468                  this._suggest();
469                  this._trigger("open");
470                }
471              },
472              onCloseHandler: function (event, ui) {
473                if (event.target !== event.currentTarget && event.currentTarget.id !== 'close-search') return
474                options.onBeforeCloseHandler(event, ui);
475                options.close(event, ui)
476              },
477              onBeforeCloseHandler: function (event, ui) {
478                $(id).blur();
479                return true;
480              },
481              onBeforeBlurHandler: function (event, ui) {
482                return !allowSubmit && $(event.relatedTarget).attr('type') === 'submit' || $(event.relatedTarget).is('.dropmenu-toggle.homologation-iconSearchHeader')
483                  ? this.cancelBlur = true
484                  : false;
485              },
486              onSubmitHandler: function () {
487                $(id).closest('form').on('submit', function (event) {
488                  if (!allowSubmit) {
489                    event.preventDefault();
490                  }
491                  return allowSubmit;
492                })
493              },
494              open: function (event, ui) {
495                self.suggestionSlider();
496                self.debounce(options.onResizeHandler(event, ui), 500);
497              },
498              close: function (event, ui) {
499                $(options.appendTo || '.ui-menu').css('display', 'none');
500                self.toggleBodyScrolling(true);
501                $(window).off('resize');
502                if (!currentInstance) return;
503                currentInstance.close( event );
504                currentInstance._change( event );
505              },
506              focus: function (event, ui) {
507                return false;
508              },
509              onMouseDownHandler: function (event, ui) {
510                function focusInput () {
511                  return !!setTimeout(function () {
512                    currentInstance.element.focus()
513                  }, 1)
514                }
515
516                $(id).closest('form').find('[type="submit"]').on('mousedown', function () {
517                  return !allowSubmit ? (currentInstance.cancelBlur = true) && focusInput() : false;
518                });
519                $('#global-search.search.content-toggle.homologation-globalSearch, .wrap-search > form > .search-input-wrapper.dropdown-menu').on('mousedown', function (event) {
520                  if (event.target === this) {
521                    currentInstance.cancelBlur = true;
522                    focusInput();
523                  }
524                });
525              },
526              onResizeHandler: function (event, ui) {
527                var $autocompleteContainer = $('.autocomplete-container');
528                var innerHTML = $autocompleteContainer.html();
529                $(window).on('resize', function () {
530                  $autocompleteContainer.html(innerHTML);
531                  self.initSlimScroll();
532                });
533                self.initSlimScroll();
534              }
535            };
536
537            if (!!GSEB.options.richAutocomplete && !!GSEB.options.richAutocomplete.options) {
538              var specificOptions = GSEB.options.richAutocomplete.options;
539              for (var _option in specificOptions) {
540                if (specificOptions.hasOwnProperty(_option)) {
541                  options[_option] = specificOptions[_option];
542                }
543
544              }
545            }
546
547            ([
548              'onSubmitHandler',
549              'onMouseDownHandler'
550            ]).forEach(function (handler) {
551              (!!options[handler]) && options[handler]();
552            });
553
554            $(document).on('click touchstart', '#close-search, .close-search, ' + (options.appendTo || '.ui-menu'), options.onCloseHandler);
555            self.onCloseHandler = options.onCloseHandler
556
557            return options;
558          })());
559          self.initBody()
560        },
561
562        suggestionSlider: function () {
563          if ($('.suggestion-slider > .item').length > 4) {
564            $('.suggestion-slider')
565              .addClass('owl-carousel')
566              .owlCarousel({
567                items: 4,
568                nav: true,
569                margin: 12,
570                dots: false,
571                pagination: false,
572                responsiveClass: true,
573                responsive: {
574                  0: {
575                    mouseDrag: true,
576                    items: 2,
577                    center: false,
578                    autoHeight: false
579                  },
580                  720: {
581                    mouseDrag: true,
582                    items: 4,
583                    center: false,
584                    autoHeight: false
585                  }
586                }
587              });
588          }
589        },
590
591        initSlimScroll: function () {
592          var $window = $(window);
593          var $autocompleteContainer = $('.autocomplete-container');
594          $autocompleteContainer.css('height', '');
595          var height = $window.height() - $autocompleteContainer.offset().top + (GSEB.platform.isMobile() && GSEB.constants.site !== GSEB.brands.VPC ? 0 : $window.scrollTop());
596          var minHeight = height ? Math.min(height, $autocompleteContainer.height()) : height;
597          if (((minHeight + height) / (2 * minHeight)) <= 1.018 || GSEB.constants.site === GSEB.brands.Tefal || GSEB.constants.site === GSEB.brands.VPC && $window.width() <= 720) {
598              $autocompleteContainer
599                  .css({
600                      height: minHeight + 'px'
601                  });
602              $autocompleteContainer.niceScroll();
603          }
604        },
605
606        toggleBodyScrolling: function (scroll) {
607            if (scroll === false) {
608                $('body')
609                    .addClass('no-overflow')
610                    .css('cssText', 'overflow: hidden;');
611                document.ontouchmove = function () { }
612                document.ontouchmove = self.onFreezeVpHandler;
613            } else if (document.ontouchmove === self.onFreezeVpHandler) {
614                $('html, body')
615                    .removeClass('no-overflow')
616                    .css({ 'overflow': '' });
617                document.ontouchmove = function () { }
618            }
619        },
620
621        onFreezeVpHandler: function (event) {
622          if ($(event.target).is('#autocomplete-container')) {
623            self.onCloseHandler($.extend({}, event, {
624              target: event.target,
625              currentTarget: event.target
626            }));
627          }
628          event.preventDefault();
629          return false;
630        },
631
632        onCloseHandler: function (event) {
633          //
634        },
635
636        initBody: function () {
637          $('html, body').addClass('platform-' + navigator.platform)
638        },
639        debounce : function(func, wait, immediate) {
640            var timeout;
641            return function() {
642                var context = this, args = arguments;
643                var later = function() {
644                    timeout = null;
645                    if (!immediate) func.apply(context, args);
646                };
647                var callNow = immediate && !timeout;
648                clearTimeout(timeout);
649                timeout = setTimeout(later, wait);
650                if (callNow) func.apply(context, args);
651            };
652        }
653      };
654
655      return self;
656    })();
657
658    if (GSEB.constants.autocompleteRich) {
659      GSEB.allBrands.richAutocomplete.getRichSuggestions("search_form", "#global-search", "#search", GSEB.options.richAutocomplete.url);
660
661      $("body").mousedown(function (event) {
662        var $target = $(event.target);
663        if ($target.parents('#autocomplete-container').length === 0 && !$target.is('#global-search') &&
664          $target.parents('[name="search_form"]').length === 0 ||
665          !!$target.parents('#close-search').length ||
666          $target.is('#close-search')) {
667          GSEB.allBrands.richAutocomplete.onCloseHandler($.extend({}, event, {
668            target: event.target,
669            currentTarget: event.target
670          }))
671        }
672      });
673    }
674  } catch (exeption) {
675    console.log(exeption)
676  }
677})(window.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.