1/** 2 * Ajax Autocomplete for jQuery, version 1.2.27 3 * (c) 2015 Tomas Kirda 4 * 5 * Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license. 6 * For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete 7 * 8 * Modified by Damian Góra: http://damiangora.com 9 * Minify: https://www.toptal.com/developers/javascript-minifier/ 10 */ 11 12/*jslint browser: true, white: true, single: true, this: true, multivar: true */ 13/*global define, window, document, jQuery, exports, require */ 14 15// Expose plugin as an AMD module if AMD loader is present: 16(function (factory) { 17 "use strict"; 18 if (typeof define === 'function' && define.amd) { 19 // AMD. Register as an anonymous module. 20 define(['jquery'], factory); 21 } else if (typeof exports === 'object' && typeof require === 'function') { 22 // Browserify 23 factory(require('jquery')); 24 } else { 25 // Browser globals 26 factory(jQuery); 27 } 28}(function ($) { 29 'use strict'; 30 31 var utils = (function () { 32 return { 33 escapeRegExChars: function (value) { 34 return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); 35 }, 36 createNode: function (containerClass) { 37 var div = document.createElement('div'); 38 div.className = containerClass; 39 div.style.position = 'absolute'; 40 div.style.display = 'none'; 41 div.setAttribute('unselectable', 'on'); 42 return div; 43 }, 44 highlight: function (suggestionValue, phrase) { 45 46 if (dgwt_wcas.is_premium) { 47 var i, 48 tokens = phrase.split(/ /), 49 highlighted = false, 50 last = ''; 51 52 if (tokens) { 53 last = tokens[tokens.length - 1]; 54 tokens = tokens.sort(function (a, b) { 55 return b.length - a.length; 56 }); 57 58 for (i = 0; i < tokens.length; i++) { 59 if (tokens[i] && tokens[i].length >= 1) { 60 61 var token = tokens[i].replace(/[\^\@]/g, ''); 62 63 if (token.length > 0) { 64 if (token.trim().length === 1 && tokens[i] !== last) { 65 var pattern = '((\\s|^)' + utils.escapeRegExChars(token.trim()) + '\\s)'; 66 } else if (token.trim().length === 1 && tokens[i] === last) { 67 var pattern = '((\\s|^)' + utils.escapeRegExChars(token.trim()) + ')'; 68 } else { 69 var pattern = '(' + utils.escapeRegExChars(token.trim()) + ')'; 70 } 71 72 suggestionValue = suggestionValue.replace(new RegExp(pattern, 'gi'), '\^\^$1\@\@'); 73 highlighted = true; 74 } 75 } 76 } 77 } 78 79 if (highlighted) { 80 suggestionValue = suggestionValue.replace(/\^\^/g, '<strong>'); 81 suggestionValue = suggestionValue.replace(/@@/g, '<\/strong>'); 82 } 83 84 85 } else { 86 var pattern = '(' + utils.escapeRegExChars(phrase) + ')'; 87 suggestionValue = suggestionValue.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>'); 88 } 89 90 return suggestionValue; 91 }, 92 debounce: function (func, wait) { 93 var timeout, 94 debounceID = new Date().getUTCMilliseconds(); 95 96 // First query in the chain 97 if (ajaxDebounceState.id.length === 0) { 98 ajaxDebounceState.id = debounceID; 99 func(); 100 return; 101 } 102 103 ajaxDebounceState.id = debounceID; 104 105 timeout = setTimeout(function () { 106 107 if (debounceID !== ajaxDebounceState.id) { 108 clearTimeout(timeout); 109 return; 110 } 111 112 // Last query in the chain 113 func(); 114 ajaxDebounceState.id = ''; 115 116 }, wait); 117 }, 118 mouseHoverDebounce: function (func, selector, wait) { 119 var timeout; 120 121 timeout = setTimeout(function () { 122 123 if ($(selector + ':hover').length > 0) { 124 func(); 125 } else { 126 clearTimeout(timeout); 127 return; 128 } 129 130 131 }, wait); 132 }, 133 isTextSelected: function () { 134 var selected = false, 135 selObj = document.getSelection(); 136 137 if (typeof selObj == 'object') { 138 if (selObj.toString().length > 0) { 139 selected = true; 140 } 141 } 142 return selected 143 }, 144 getActiveInstance: function () { 145 var $el = $('.dgwt-wcas-search-wrapp.dgwt-wcas-active'), 146 instance; 147 if ($el.length > 0) { 148 $el.each(function () { 149 var $input = $(this).find('.dgwt-wcas-search-input'); 150 if (typeof $input.data('autocomplete') == 'object') { 151 instance = $input.data('autocomplete'); 152 return false;
153 } 154 }); 155 } 156 157 return instance; 158 }, 159 hashCode: function (s) { 160 var h = 0, i = s.length; 161 while (i > 0) { 162 h = (h << 5) - h + s.charCodeAt(--i) | 0; 163 } 164 return h < 0 ? h * -1 : h; 165 }, 166 isBrowser: function (browser) { 167 return navigator.userAgent.indexOf(browser) !== -1; 168 }, 169 isIOS: function () { 170 return [ 171 'iPad Simulator', 172 'iPhone Simulator', 173 'iPod Simulator', 174 'iPad', 175 'iPhone', 176 'iPod' 177 ].includes(navigator.platform) 178 // iPad on iOS 13 detection 179 || (navigator.userAgent.includes("Mac") && "ontouchend" in document) 180 }, 181 isIE11: function () { 182 return !!navigator.userAgent.match(/Trident\/7\./); 183 }, 184 setLocalStorageItem(key, value) { 185 try { 186 window.localStorage.setItem( 187 key, 188 JSON.stringify(value) 189 ); 190 } catch (error) { 191 // A more advanced implementation would handle the error case 192 } 193 }, 194 getLocalStorageItem(key, defaultValue) { 195 try { 196 const item = window.localStorage.getItem(key); 197 return item ? JSON.parse(item) : defaultValue; 198 } catch (error) { 199 return defaultValue; 200 } 201 }, 202 removeLocalStorageItem(key) { 203 try { 204 window.localStorage.removeItem(key); 205 } catch (error) { 206 } 207 } 208 }; 209 }()), 210 ajaxDebounceState = { 211 id: '', 212 callback: null, 213 ajaxSettings: null, 214 object: null, 215 }, 216 keys = { 217 ESC: 27, 218 TAB: 9, 219 RETURN: 13, 220 LEFT: 37, 221 UP: 38, 222 RIGHT: 39, 223 DOWN: 40 224 }, 225 noop = $.noop; 226 227 function DgwtWcasAutocompleteSearch(el, options) { 228 var that = this; 229 230 // Shared variables: 231 that.element = el; 232 that.el = $(el); 233 that.suggestions = []; 234 that.badQueries = []; 235 that.selectedIndex = -1; 236 that.currentValue = that.element.value; 237 that.timeoutId = null; 238 that.cachedResponse = {}; 239 that.cachedDetails = {}; 240 that.cachedPrices = {}; 241 that.detailsRequestsSent = []; 242 that.onChangeTimeout = null; 243 that.onChange = null; 244 that.isLocal = false;
245 that.suggestionsContainer = null; 246 that.detailsContainer = null; 247 that.autoAligmentprocess = null; 248 that.noSuggestionsContainer = null; 249 that.latestActivateSource = ''; 250 that.actionTriggerSource = ''; 251 that.options = $.extend(true, {}, DgwtWcasAutocompleteSearch.defaults, options); 252 that.classes = { 253 selected: 'dgwt-wcas-suggestion-selected', 254 suggestion: 'dgwt-wcas-suggestion', 255 suggestionsContainerOrientTop: 'dgwt-wcas-suggestions-wrapp--top', 256 inputFilled: 'dgwt-wcas-search-filled', 257 darkenOverlayMounted: 'js-dgwt-wcas-search-darkoverl-mounted', 258 fixed: 'dgwt-wcas-suggestions-wrapp-fixed' 259 }; 260 that.hint = null; 261 that.hintValue = ''; 262 that.selection = null; 263 that.overlayMobileState = 'off'; 264 that.overlayDarkenedState = 'off'; 265 that.isMouseDownOnSearchElements = false; 266 that.isPreSuggestionsMode = false; 267 268 // Voice search 269 that.voiceSearchRecognition = null; 270 that.voiceSearchStarted = null; 271 272 // Search history 273 that.recentlyViewedProductsKey = 'fibosearch_recently_viewed_products'; 274 that.recentlySearchedPhrasesKey = 'fibosearch_recently_searched_phrases'; 275 276 // Initialize and set options: 277 that.initialize(); 278 that.setOptions(options); 279 280 } 281 282 DgwtWcasAutocompleteSearch.utils = utils; 283 284 $.DgwtWcasAutocompleteSearch = DgwtWcasAutocompleteSearch; 285 286 DgwtWcasAutocompleteSearch.defaults = { 287 ajaxSettings: {}, 288 autoSelectFirst: false, 289 appendTo: 'body', 290 serviceUrl: null, 291 lookup: null, 292 onSelect: null, 293 containerDetailsWidth: 'auto', 294 showDetailsPanel: false, 295 showImage: false, 296 showPrice: false, 297 showSKU: false, 298 showDescription: false, 299 showSaleBadge: false, 300 showFeaturedBadge: false, 301 dynamicPrices: false, 302 saleBadgeText: 'sale', 303 featuredBadgeText: 'featured', 304 minChars: 3, 305 maxHeight: 600, 306 dpusbBreakpoint: 550, // (details panel under search bar - breakpoint) If search bar width is lower than this option, suggestions wrapper and details panel will show under search bar with the same width 307 deferRequestBy: 0, 308 params: {}, 309 formatResult: _formatResult, 310 delimiter: null, 311 zIndex: 999999999, 312 type: 'GET', 313 noCache: false, 314 isRtl: false, 315 onSearchStart: noop, 316 onSearchComplete: noop, 317 onSearchError: noop, 318 preserveInput: false, 319 searchFormClass: 'dgwt-wcas-search-wrapp', 320 containerClass: 'dgwt-wcas-suggestions-wrapp', 321 containerDetailsClass: 'dgwt-wcas-details-wrapp', 322 preSuggestionsWrappClass: 'dgwt-wcas-pre-suggestions-wrapp', 323 darkenedOverlayClass: 'dgwt-wcas-darkened-overlay', 324 searchInputClass: 'dgwt-wcas-search-input', 325 preloaderClass: 'dgwt-wcas-preloader', 326 closeTrigger: 'dgwt-wcas-close', 327 formClass: 'dgwt-wcas-search-form', 328 voiceSearchClass: 'dgwt-wcas-voice-search', 329 voiceSearchSupportedClass: 'dgwt-wcas-voice-search-supported', 330 voiceSearchActiveClass: 'dgwt-wcas-voice-search-active', 331 voiceSearchDisabledClass: 'dgwt-wcas-voice-search-disabled', 332 tabDisabled: false, 333 dataType: 'text', 334 currentRequest: null, 335 triggerSelectOnValidInput: true, 336 isPremium: false, 337 overlayMobile: false, 338 preventBadQueries: true, 339 lookupFilter: _lookupFilter, 340 paramName: 'query', 341 transformResult: _transformResult, 342 noSuggestionNotice: 'No results', 343 forceFixPosition: false, 344 positionFixed: false, 345 debounceWaitMs: 400, 346 sendGAEvents: true, 347 enableGASiteSearchModule: false, 348 showProductVendor: false, 349 disableHits: false, 350 disableSubmit: false, 351 voiceSearchEnabled: false, 352 voiceSearchLang: '', 353 showRecentlySearchedProducts: false, 354 showRecentlySearchedPhrases: false, 355 } 356 357 function _lookupFilter(suggestion, originalQuery, queryLowerCase) { 358 return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1; 359 } 360 361 function _transformResult(response) { 362 return typeof response === 'string' ? JSON.parse(response)
362: response; 363 } 364 365 function _formatResult(suggestionValue, currentValue, highlight, options) { 366 // Do not replace anything if there current value is empty 367 if (!currentValue) { 368 return suggestionValue; 369 } 370 371 if (highlight) { 372 suggestionValue = utils.highlight(suggestionValue, currentValue); 373 } 374 375 if (!options.convertHtml) { 376 return suggestionValue; 377 } 378 379 return suggestionValue.replace(/&/g, '&') 380 .replace(/</g, '<') 381 .replace(/>/g, '>') 382 .replace(/"/g, '"') 383 .replace(/'/g, ''') 384 .replace(/<sup/g, '<sup') 385 .replace(/<\/sup/g, '</sup') 386 .replace(/sup>/g, 'sup>') 387 .replace(/<sub/g, '<sub') 388 .replace(/<\/sub/g, '</sub') 389 .replace(/sub>/g, 'sub>') 390 .replace(/<br\s?\/?>/g, '<br/>') 391 .replace(/<(\/?(strong|b|br|span))>/g, '<$1>') 392 .replace(/<(strong|span)\s+class\s*=\s*"([^&]+)">/g, '<$1 class="$2">'); 393 } 394 395 DgwtWcasAutocompleteSearch.prototype = { 396 initialize: function () { 397 var that = this; 398 399 // Remove autocomplete attribute to prevent native suggestions: 400 that.element.setAttribute('autocomplete', 'off'); 401 402 that.options.params = that.applyCustomParams(that.options.params); 403 404 that.createContainers(); 405 406 that.registerEventsSearchBar(); 407 that.registerEventsSuggestions(); 408 that.registerEventsDetailsPanel(); 409 that.registerIconHandler(); 410 that.registerFlexibleLayout(); 411 that.initVoiceSearch(); 412 413 that.fixPosition = function () { 414 that.adjustContainerWidth(); 415 if (that.visible) { 416 that.fixPositionSuggestions(); 417 if (that.canShowDetailsPanel()) { 418 that.fixPositionDetailsPanel(); 419 } 420 } 421 that.positionOverlayDarkened(); 422 }; 423 424 // Fix position on resize 425 $(window).on('resize.autocomplete', function () { 426 var that = utils.getActiveInstance(); 427 clearTimeout(window.dgwt_wcas.resizeOnlyOnce); 428 if (typeof that != 'undefined') { 429 window.dgwt_wcas.resizeOnlyOnce = setTimeout(function () { 430 that.fixPosition(); 431 }, 100); 432 } 433 }); 434 435 // Fix position on scroll 436 $(window).on('scroll.autocomplete', function () { 437 var that = utils.getActiveInstance(); 438 clearTimeout(window.dgwt_wcas.scrollOnlyOnce); 439 if (typeof that != 'undefined') { 440 window.dgwt_wcas.scrollOnlyOnce = setTimeout(function () { 441 that.fixPosition(); 442 }, 100); 443 } 444 }); 445 446 // Trigger only when x axis is changed 447 var windowWidth = $(window).width(); 448 $(window).on('resize.autocomplete', function () { 449 var newWidth = $(window).width(); 450 if (newWidth != windowWidth) { 451 that.toggleMobileOverlayMode(); 452 windowWidth = newWidth; 453 } 454 }); 455 456 if (that.isBreakpointReached('mobile-overlay')) { 457 that.activateMobileOverlayMode(); 458 } 459 460 that.hideAfterClickOutsideListener(); 461 462 // Mark as initialized 463 that.suggestionsContainer.addClass('js-dgwt-wcas-initialized'); 464 465 if (that.detailsContainer && that.detailsContainer.length > 0) { 466 that.detailsContainer.addClass('js-dgwt-wcas-initialized'); 467 } 468 }, 469 createContainers: function (type) { 470 var that = this, 471 options = that.options; 472 473 // Suggestions 474 if ($('.' + options.containerClass).length == 0) { 475 476 that.suggestionsContainer = $(DgwtWcasAutocompleteSearch.utils.createNode(options.containerClass)); 477 478 that.suggestionsContainer.appendTo(options.appendTo || 'body'); 479 480 that.suggestionsContainer.addClass('woocommerce'); 481 482 // Add conditional classes 483 if (options.showImage === true) { 484 that.suggestionsContainer.addClass('dgwt-wcas-has-img'); 485 } 486 487 // Price 488 if (options.showPrice === true) { 489 that.suggestionsContainer.addClass('dgwt-wcas-has-price'); 490 } 491 492 // Description 493 if (options.showDescription === true) { 494 that.suggestionsContainer.addClass('dgwt-wcas-has-desc'); 495 } 496 497 // SKU 498 if (options.showSKU === true) { 499 that.suggestionsContainer.addClass('dgwt-wcas-has-sku'); 500 } 501 502 // Headings 503 if (options.showHeadings === true) { 504 that.suggestionsContainer.addClass('dgwt-wcas-has-headings'); 505 } 506 507 } else { 508 509 that.suggestionsContainer = $('.' + that.options.containerClass); 510 511 } 512 513 // Details Panel
514 if (that.canShowDetailsPanel()) { 515 516 if ($('.' + options.containerDetailsClass).length == 0) { 517 that.detailsContainer = $(DgwtWcasAutocompleteSearch.utils.createNode(options.containerDetailsClass)); 518 that.detailsContainer.appendTo(options.appendTo || 'body'); 519 520 that.detailsContainer.addClass('woocommerce'); 521 } else { 522 523 that.detailsContainer = $('.' + options.containerDetailsClass); 524 525 } 526 527 } 528 }, 529 registerEventsSearchBar: function () { 530 var that = this; 531 532 // The Control event that checks if other listeners work 533 that.el.on('fibosearch/ping', function () { 534 that.el.addClass('fibosearch-pong'); 535 }); 536 537 // Extra tasks on submit 538 that.getForm().on('submit.autocomplete', function (e) { 539 540 if (that.options.disableSubmit) { 541 e.preventDefault(); 542 return false; 543 } 544 545 // Prevent submit empty form 546 var $input = $(this).find('.' + that.options.searchInputClass); 547 if ($input.length && $input.val().length === 0) { 548 e.preventDefault(); 549 return false; 550 } 551 552 // If variation suggestion exist, click it instead submit search results page 553 if (that.suggestions.length > 0) { 554 555 $.each(that.suggestions, function (i, suggestion) { 556 557 if ( 558 typeof suggestion.type != 'undefined' 559 && suggestion.type == 'product_variation' 560 ) { 561 that.select(i); 562 e.preventDefault(); 563 return false; 564 } 565 }); 566 567 } 568 569 if (that.options.showRecentlySearchedPhrases) { 570 that.saveHistorySearches($input.val()); 571 } 572 573 // Clean before submit 574 that.closeOverlayMobile(); 575 }); 576 577 // Position preloader 578 if (document.readyState === 'complete') { 579 that.positionPreloaderAndMic(); 580 } else { 581 $(window).on('load', function () { 582 that.positionPreloaderAndMic(); 583 }); 584 } 585 586 that.el.on('keydown.autocomplete', function (e) { 587 that.onKeyPress(e); 588 }); 589 that.el.on('keyup.autocomplete', function (e) { 590 that.onKeyUp(e); 591 }); 592 that.el.on('blur.autocomplete', function () { 593 that.onBlur(); 594 }); 595 that.el.on('focus.autocomplete', function (e) { 596 that.onFocus(e); 597 }); 598 that.el.on('change.autocomplete', function (e) { 599 that.onKeyUp(e); 600 }); 601 that.el.on('input.autocomplete', function (e) { 602 that.onKeyUp(e); 603 }); 604 605 }, 606 registerEventsSuggestions: function () { 607 var that = this, 608 suggestionSelector = '.' + that.classes.suggestion, 609 suggestionsContainer = that.getSuggestionsContainer(); 610 611 // Register these events only once 612 if (suggestionsContainer.hasClass('js-dgwt-wcas-initialized')) { 613 return; 614 } 615 616 // Select suggestion and enable details panel on hovering over it 617 $(document).on('mouseenter.autocomplete', suggestionSelector, function () { 618 var that = utils.getActiveInstance(); 619 620 if (typeof that == 'undefined') { 621 return; 622 } 623 624 var currentIndex = $(this).data('index'); 625 var selector = '.dgwt-wcas-suggestion[data-index="' + currentIndex + '"]'; 626 627 var timeOffset = that.canShowDetailsPanel() ? 100 : 1; 628 629 if (that.selectedIndex != currentIndex) { 630 631 if (that.suggestions[currentIndex].type == 'headline' 632 || that.suggestions[currentIndex].type == 'headline-v2') { 633 return; 634 } 635 636 utils.mouseHoverDebounce(function () { 637 if (that.selectedIndex !== currentIndex) { 638 that.latestActivateSource = 'mouse'; 639 that.getDetails(that.suggestions[currentIndex]); 640 that.activate(currentIndex); 641 } 642 }, selector, timeOffset); 643 644 } 645 }); 646 647 var alreadyClicked = false;
648 // Redirect to the new URL after click a suggestions 649 $(document).on('click.autocomplete', suggestionSelector, function (e) { 650 if (!alreadyClicked) { 651 var that = utils.getActiveInstance(); 652 that.actionTriggerSource = 'click'; 653 654 alreadyClicked = true; 655 setTimeout(function () { 656 alreadyClicked = false; 657 }, 500); 658 659 if (typeof e.ctrlKey === 'undefined' || e.ctrlKey === false) { 660 that.select($(this).data('index')); 661 e.preventDefault(); 662 } 663 } else { 664 e.preventDefault(); 665 } 666 }); 667 668 // FIX issue with touchpads for some laptops (marginal cases) 669 $(document).on('mousedown.autocomplete', suggestionSelector, function (e) { 670 var _this = this; 671 if (e.button === 0) { 672 setTimeout(function () { 673 if (!alreadyClicked) { 674 var that = utils.getActiveInstance(); 675 that.select($(_this).data('index')); 676 } 677 }, 250); 678 } 679 }); 680 681 // Mark cursor position for onBlur event 682 $('.' + that.options.containerClass).on('mousedown.autocomplete', function (e) { 683 var that = utils.getActiveInstance(); 684 that.isMouseDownOnSearchElements = true; 685 }); 686 687 $(document).on('click', '.js-dgwt-wcas-sugg-hist-clear', function () { 688 that.resetPreSuggestions(); 689 }); 690 }, 691 registerEventsDetailsPanel: function () { 692 var that = this, 693 detailsContainer = that.getDetailsContainer(); 694 695 if (!that.canShowDetailsPanel() || detailsContainer.hasClass('js-dgwt-wcas-initialized')) { 696 return; 697 } 698 699 // Update quantity 700 $(document).on('change.autocomplete', '[name="js-dgwt-wcas-quantity"]', function (e) { 701 var $input = $(this).closest('.js-dgwt-wcas-pd-addtc').find('[data-quantity]'); 702 $input.attr('data-quantity', $(this).val()); 703 }); 704 705 // Mark cursor position for onBlur event 706 $('.' + that.options.containerDetailsClass).on('mousedown.autocomplete', function (e) { 707 var that = utils.getActiveInstance(); 708 that.isMouseDownOnSearchElements = true; 709 }); 710 711 }, 712 registerIconHandler: function () { 713 var that = this, 714 $formWrapper = that.getFormWrapper(), 715 $form = that.getForm(); 716 717 $formWrapper.on('click.autocomplete', '.js-dgwt-wcas-search-icon-handler', function (e) { 718 719 var $input = $formWrapper.find('.' + that.options.searchInputClass); 720 721 if ($formWrapper.hasClass('dgwt-wcas-layout-icon-open')) { 722 that.hide(); 723 $form.hide(true); 724 725 $formWrapper.removeClass('dgwt-wcas-layout-icon-open'); 726 727 728 } else { 729 var $arrow = $formWrapper.find('.dgwt-wcas-search-icon-arrow'); 730 $form.hide(); 731 $arrow.hide(); 732 $formWrapper.addClass('dgwt-wcas-layout-icon-open'); 733 that.positionIconSearchMode($formWrapper); 734 735 $form.fadeIn(50, function () { 736 $arrow.show(); 737 that.positionPreloaderAndMic($formWrapper); 738 739 var textEnd = that.currentValue.length; 740 if (textEnd > 0) { 741 $input[0].setSelectionRange(textEnd, textEnd); 742 } 743 744 $input.focus(); 745 }); 746 747 setTimeout(function () { 748 that.fixPosition(); 749 }, 110); 750 751 } 752 753 }); 754 755 if ($('.js-dgwt-wcas-initialized').length == 0 && $('.js-dgwt-wcas-search-icon-handler').length > 0) { 756 757 $(document).on('click.autocomplete', function (event) { 758 759 if ($('.dgwt-wcas-layout-icon-open').length) { 760 761 var $target = $(event.target); 762 763 if (!($target.closest('.' + that.options.searchFormClass).length > 0 764 || $target.closest('.' + that.options.containerClass).length > 0 765 || $target.closest('.' + that.options.containerDetailsClass).length > 0 766 )) { 767 that.hideIconModeSearch(); 768 } 769 770 } 771 }); 772 } 773 }, 774 registerFlexibleLayout: function () { 775 var that = this; 776 777 // Trigger only when x axis is changed 778 var windowWidth = $(window).width(); 779 $(window).on('resize.autocomplete', function () { 780 var newWidth = $(window).width(); 781 if (newWidth != windowWidth) { 782 that.reloadFlexibleLayout(); 783 windowWidth = newWidth; 784 } 785 }); 786 787 if (document.readyState == 'complete') { 788 that.reloadFlexibleLayout(); 789 } else { 790 $(window).on('load.autocomplete', function () { 791 that.reloadFlexibleLayout(); 792 }); 793 } 794 795 }, 796 activateMobileOverlayMode: function () { 797 var that = this, 798 $formWrapper = that.getFormWrapper(); 799 800 if ( 801 $formWrapper.hasClass('js-dgwt-wcas-mobile-overlay-enabled') 802 && !$formWrapper.find('.js-dgwt-wcas-enable-mobile-form').length 803 ) { 804 805 $formWrapper.prepend('<div class="js-dgwt-wcas-enable-mobile-form dgwt-wcas-enable-mobile-form"></div>'); 806 $formWrapper.addClass('dgwt-wcas-mobile-overlay-trigger-active'); 807 808 var $el = $formWrapper.find('.js-dgwt-wcas-enable-mobile-form'); 809 810 $el.on('click.autocomplete', function (e) { 811 812 if (that.options.mobileOverlayDelay > 0) { 813 setTimeout(function () { 814 that.showMobileOverlay(); 815 }, that.options.mobileOverlayDelay); 816 } else { 817 that.showMobileOverlay(); 818 } 819 820 }); 821 822 } 823 824 }, 825 deactivateMobileOverlayMode: function () { 826 var that = this, 827 $formWrapper = that.getFormWrapper(), 828 $suggestionsWrapper = that.getSuggestionsContainer(); 829 830 var $el = $formWrapper.find('.js-dgwt-wcas-enable-mobile-form'); 831 832 if ($formWrapper.hasClass('js-dgwt-wcas-mobile-overlay-enabled') 833 && $el.length 834 ) { 835 that.closeOverlayMobile(); 836 $el.remove(); 837 $formWrapper.removeClass('dgwt-wcas-mobile-overlay-trigger-active'); 838 } 839 840 }, 841 toggleMobileOverlayMode: function () { 842 var that = this, 843 $formWrapper = that.getFormWrapper(), 844 isMobOverlayEnabled = false;
845 846 // Break early if this search bar shouldn't open in overlay mobile mode 847 if (!$formWrapper.hasClass('js-dgwt-wcas-mobile-overlay-enabled')) { 848 return; 849 } 850 851 // Determine the search should open in mobile overlay 852 if ($formWrapper.find('.js-dgwt-wcas-enable-mobile-form').length) { 853 isMobOverlayEnabled = true; 854 } 855 856 // Toggled? 857 if ( 858 (!isMobOverlayEnabled && that.isBreakpointReached('mobile-overlay')) 859 || (isMobOverlayEnabled && !that.isBreakpointReached('mobile-overlay')) 860 ) { 861 862 var $suggestionsWrapper = that.getSuggestionsContainer(); 863 864 that.close(false); 865 866 if ($suggestionsWrapper.length) { 867 $suggestionsWrapper.html(''); 868 } 869 870 that.hideIconModeSearch(); 871 } 872 873 // Activate overlay on mobile feature 874 if (!isMobOverlayEnabled && that.isBreakpointReached('mobile-overlay')) { 875 that.activateMobileOverlayMode(); 876 } 877 878 // Deactivate overlay on mobile feature 879 if (isMobOverlayEnabled && !that.isBreakpointReached('mobile-overlay')) { 880 that.deactivateMobileOverlayMode(); 881 } 882 }, 883 showMobileOverlay: function () { 884 var that = this; 885 886 if (that.overlayMobileState === 'on') { 887 return; 888 } 889 890 that.overlayMobileState = 'on'; 891 892 var zIndex = 99999999999, 893 $wrapper = that.getFormWrapper(), 894 $suggestionsWrapp = that.getSuggestionsContainer(), 895 $overlayWrap, 896 html = ''; 897 898 $('html').addClass('dgwt-wcas-overlay-mobile-on'); 899 $('html').addClass('dgwt-wcas-open-' + that.getSearchStyle()); 900 html += '<div class="js-dgwt-wcas-overlay-mobile dgwt-wcas-overlay-mobile">'; 901 html += '<div class="dgwt-wcas-om-bar js-dgwt-wcas-om-bar">'; 902 html += '<button class="dgwt-wcas-om-return js-dgwt-wcas-om-return">' 903 if (typeof dgwt_wcas.back_icon == 'string') { 904 html += dgwt_wcas.back_icon; 905 } 906 html += '</button>'; 907 html += '</div>'; 908 html += '</div>'; 909 910 // Create overlay 911 $(that.options.mobileOverlayWrapper).append(html); 912 $overlayWrap = $('.js-dgwt-wcas-overlay-mobile'); 913 $overlayWrap.css('zIndex', zIndex); 914 915 $wrapper.after('<span class="js-dgwt-wcas-om-hook"></span>'); 916 $wrapper.appendTo('.js-dgwt-wcas-om-bar'); 917 $suggestionsWrapp.appendTo('.js-dgwt-wcas-om-bar'); 918 $wrapper.addClass('dgwt-wcas-search-wrapp-mobile'); 919 920 if ($wrapper.hasClass('dgwt-wcas-has-submit')) { 921 $wrapper.addClass('dgwt-wcas-has-submit-off'); 922 $wrapper.removeClass('dgwt-wcas-has-submit'); 923 } 924 925 $wrapper.find('.' + that.options.searchInputClass).focus(); 926 927 $(document).on('click.autocomplete', '.js-dgwt-wcas-om-return', function (e) { 928 that.closeOverlayMobile($overlayWrap); 929 }); 930 document.dispatchEvent(new CustomEvent('fibosearch/show-mobile-overlay', { 931 detail: that 932 })); 933 }, 934 closeOverlayMobile: function ($overlayWrap) { 935 var that = this; 936 937 if (!$('html').hasClass('dgwt-wcas-overlay-mobile-on')) { 938 that.overlayMobileState = 'off'; 939 return; 940 } 941 942 var $suggestionsWrapp = that.getSuggestionsContainer(); 943 944 var $clonedForm = $('.js-dgwt-wcas-om-bar').find('.' + that.options.searchFormClass); 945 946 if ($clonedForm.hasClass('dgwt-wcas-has-submit-off')) { 947 $clonedForm.removeClass('dgwt-wcas-has-submit-off'); 948 $clonedForm.addClass('dgwt-wcas-has-submit'); 949 } 950 951 $clonedForm.removeClass('dgwt-wcas-search-wrapp-mobile'); 952 $('html').removeClass('dgwt-wcas-overlay-mobile-on'); 953 $('html').removeClass('dgwt-wcas-open-' + that.getSearchStyle()); 954 $suggestionsWrapp.appendTo('body'); 955 $suggestionsWrapp.removeAttr('body-scroll-lock-ignore'); 956 $('.js-dgwt-wcas-om-hook').after($clonedForm); 957 $('.js-dgwt-wcas-overlay-mobile').remove(); 958 $('.js-dgwt-wcas-om-hook').remove(); 959 960 setTimeout(function () { 961 $clonedForm.find('.' + that.options.searchInputClass).val(''); 962 var $closeBtn = $clonedForm.find('.dgwt-wcas-close'); 963 if ($clonedForm.length > 0) { 964 $closeBtn.removeClass('dgwt-wcas-close'); 965 $closeBtn.html(''); 966 } 967 968 that.hide(); 969 970 }, 150); 971 972 973 that.overlayMobileState = 'off'; 974 975 document.dispatchEvent(new CustomEvent('fibosearch/hide-mobile-overlay', { 976 detail: that 977 })); 978 }, 979 reloadFlexibleLayout: function () { 980 var that = this,
981 $searchWrapp = that.getFormWrapper(), 982 flexibleMode = 0; 983 984 /** 985 * flexibleMode 986 * 0 = not set 987 * 1 = Icon on mobile, search bar on desktop 988 * 2 = Icon on desktop, search bar on mobile 989 */ 990 991 if ($searchWrapp.hasClass('js-dgwt-wcas-layout-icon-flexible')) { 992 flexibleMode = 1; 993 } 994 995 if ($searchWrapp.hasClass('js-dgwt-wcas-layout-icon-flexible-inv')) { 996 flexibleMode = 2; 997 } 998 if (flexibleMode > 0) { 999 1000 if ( 1001 (flexibleMode === 1 && that.isBreakpointReached('search-layout')) 1002 || (flexibleMode === 2 && !that.isBreakpointReached('search-layout')) 1003 ) { 1004 $searchWrapp.addClass('js-dgwt-wcas-layout-icon'); 1005 $searchWrapp.addClass('dgwt-wcas-layout-icon'); 1006 } else { 1007 $searchWrapp.removeClass('js-dgwt-wcas-layout-icon'); 1008 $searchWrapp.removeClass('dgwt-wcas-layout-icon'); 1009 } 1010 1011 $searchWrapp.addClass('dgwt-wcas-layout-icon-flexible-loaded'); 1012 } 1013 }, 1014 onFocus: function (e) { 1015 var that = this, 1016 $formWrapper = that.getFormWrapper(), 1017 options = that.options; 1018 // Mark as active 1019 $('.' + options.searchFormClass).removeClass('dgwt-wcas-active'); 1020 $formWrapper.addClass('dgwt-wcas-active'); 1021 1022 // Mark as focus 1023 $('body').addClass('dgwt-wcas-focused'); 1024 $formWrapper.addClass('dgwt-wcas-search-focused'); 1025 1026 if ($(e.target).closest('.dgwt-wcas-search-wrapp-mobile').length == 0) { 1027 that.enableOverlayDarkened(); 1028 } 1029 1030 that.fixPosition(); 1031 1032 if (that.el.val().length === 0) { 1033 if (that.canShowPreSuggestions()) { 1034 that.showPreSuggestions(); 1035 } 1036 } else if (that.el.val().length >= that.options.minChars) { 1037 that.onValueChange(); 1038 } 1039 }, 1040 onBlur: function () { 1041 var that = this, 1042 options = that.options, 1043 value = that.el.val(), 1044 query = that.getQuery(value); 1045 1046 // Remove focused classes 1047 $('body').removeClass('dgwt-wcas-focused'); 1048 $('.' + options.searchFormClass).removeClass('dgwt-wcas-search-focused'); 1049 1050 if (!that.isMouseDownOnSearchElements) { 1051 1052 that.hide(); 1053 1054 if (that.selection && that.currentValue !== query) { 1055 (options.onInvalidateSelection || $.noop).call(that.element); 1056 } 1057 } 1058 1059 document.dispatchEvent(new CustomEvent('fibosearch/close', { 1060 detail: that 1061 })); 1062 }, 1063 abortAjax: function () { 1064 var that = this; 1065 if (that.currentRequest) { 1066 that.currentRequest.abort(); 1067 that.currentRequest = null; 1068 } 1069 }, 1070 setOptions: function (suppliedOptions) { 1071 var that = this, 1072 $suggestionsContainer = that.getSuggestionsContainer(), 1073 1074 options = $.extend({}, that.options, suppliedOptions); 1075 1076 that.isLocal = Array.isArray(options.lookup); 1077 1078 if (that.isLocal) { 1079 options.lookup = that.verifySuggestionsFormat(options.lookup); 1080 } 1081 1082 $suggestionsContainer.css({ 1083 'max-height': !that.canShowDetailsPanel() ? options.maxHeight + 'px' : 'none', 1084 'z-index': options.zIndex 1085 }); 1086 1087 // Add classes 1088 if (that.canShowDetailsPanel()) { 1089 var $detailsContainer = that.getDetailsContainer(); 1090 1091 $detailsContainer.css({ 1092 'z-index': (options.zIndex - 1) 1093 }); 1094 } 1095 1096 options.onSearchComplete = function () { 1097 var $searchForm = that.getFormWrapper(); 1098 $searchForm.removeClass('dgwt-wcas-processing'); 1099 that.preloader('hide', 'form', 'dgwt-wcas-inner-preloader'); 1100 that.showCloseButton(); 1101 }; 1102 1103 this.options = options; 1104 }, 1105 clearCache: function () { 1106 this.cachedResponse = {}; 1107 this.cachedDetails = {}; 1108 this.cachedPrices = {}; 1109 this.badQueries = []; 1110 }, 1111 clear: function (cache) { 1112 if (cache) { 1113 this.clearCache(); 1114 } 1115 this.currentValue = ''; 1116 this.suggestions = []; 1117 }, 1118 close: function (focus) { 1119 var that = this, 1120 $el = that.el.closest('.' + that.options.searchFormClass).find('.' + that.options.searchInputClass), 1121 $wrapp = that.getFormWrapper(); 1122 1123 that.hide(); 1124 that.clear(false); 1125 that.hideCloseButton(); 1126 $el.val(''); 1127 $wrapp.removeClass(that.classes.inputFilled); 1128 1129 if (focus) { 1130 $el.focus(); 1131 } 1132 }, 1133 fixPositionSuggestions: function () { 1134 var that = this, 1135 $suggestions = that.getSuggestionsContainer(), 1136 $formEl = that.getForm(), 1137 $input = that.el, 1138 formData = that.getElementInfo($formEl), 1139 inputData = that.getElementInfo($input), 1140 offset = { 1141 top: inputData.top + inputData.height, 1142 left: formData.left 1143 }; 1144 1145 // Set different vertical coordinates when the search bar is in the fixed position 1146 if (that.ancestorHasPositionFixed($formEl)) { 1147 offset.top = inputData.topViewPort + inputData.height; 1148 $suggestions.addClass(that.classes.fixed); 1149 } else { 1150 $suggestions.removeClass(that.classes.fixed); 1151 } 1152 1153 that.getSuggestionsContainer().css(offset); 1154 },
1155 fixPositionDetailsPanel: function () { 1156 var that = this, 1157 $searchBar = that.getFormWrapper(), 1158 $suggestions = that.getSuggestionsContainer(), 1159 $detailsPanel = that.getDetailsContainer(), 1160 $formEl = that.getForm(), 1161 $input = that.el, 1162 formData = that.getElementInfo($formEl), 1163 inputData = that.getElementInfo($input), 1164 offset = { 1165 top: inputData.top + inputData.height, 1166 left: formData.left + $suggestions.outerWidth(false) 1167 }; 1168 1169 // Set different vertical coordinate when the search bar is in the fixed position 1170 if (that.ancestorHasPositionFixed($searchBar)) { 1171 offset.top = inputData.topViewPort + inputData.height; 1172 $detailsPanel.addClass(that.classes.fixed); 1173 } else { 1174 $detailsPanel.removeClass(that.classes.fixed) 1175 } 1176 1177 // Stick the details panel to the right side of the suggestion wrapper and to the bottom border of the search form 1178 $detailsPanel.css(offset); 1179 1180 $('body').removeClass('dgwt-wcas-full-width dgwt-wcas-details-outside dgwt-wcas-details-right dgwt-wcas-details-left dgwt-wcas-details-notfit'); 1181 1182 // Details Panel Mode 1: Both suggestions wrapper and details panel wrapper have the same width as the search bar 1183 if ($searchBar.outerWidth() >= that.options.dpusbBreakpoint) { 1184 $('body').addClass('dgwt-wcas-full-width'); 1185 1186 if (that.options.isRtl === true) { 1187 offset.left = formData.left + $detailsPanel.outerWidth(false); 1188 $suggestions.css('left', offset.left); 1189 $detailsPanel.css('left', formData.left); 1190 } 1191 1192 return; 1193 } 1194 1195 // Details Panel Mode 2: The suggestions' wrapper has the same width as the search bar. 1196 // Details panel clings to the left or right side of the suggestion wrapper. 1197 var windowWidth = $(window).width(), 1198 cDWidth = $detailsPanel.outerWidth(), 1199 cOffset = $detailsPanel.offset(); 1200 1201 $('body').addClass('dgwt-wcas-details-outside dgwt-wcas-details-right'); 1202 1203 // Is the details panel fits the space of the right side? 1204 // Not? Try to move to the left side 1205 if (windowWidth < (cOffset.left + cDWidth)) { 1206 $('body').removeClass('dgwt-wcas-details-right'); 1207 $('body').addClass('dgwt-wcas-details-left'); 1208 offset.left = $suggestions.offset().left - $detailsPanel.outerWidth(false); 1209 $detailsPanel.css('left', offset.left); 1210 cOffset = $detailsPanel.offset(); 1211 } 1212 1213 // Is the details' panel fits the space of the left side? 1214 // Not? Try to hide it by adding class "dgwt-wcas-details-notfit" 1215 if (cOffset.left < 1) { 1216 $('body').removeClass('dgwt-wcas-details-left dgwt-wcas-details-right'); 1217 $('body').addClass('dgwt-wcas-details-notfit'); 1218 } 1219 }, 1220 fixHeight: function () { 1221 var that = this; 1222 1223 if (!that.canShowDetailsPanel()) { 1224 return false; 1225 } 1226 1227 var $suggestionsWrapp = that.getSuggestionsContainer(), 1228 $detailsWrapp = that.getDetailsContainer(); 1229 1230 $suggestionsWrapp.css('height', 'auto'); 1231 $detailsWrapp.css('height', 'auto'); 1232 1233 var sH = $suggestionsWrapp.outerHeight(false), 1234 dH = $detailsWrapp.outerHeight(false), 1235 minHeight = 340; 1236 1237 $suggestionsWrapp.find('.dgwt-wcas-suggestion:last-child').removeClass('dgwt-wcas-suggestion-no-border-bottom'); 1238 1239 if (sH <= minHeight && dH <= minHeight) { 1240 return false; 1241 } 1242 1243 $suggestionsWrapp.find('.dgwt-wcas-suggestion:last-child').addClass('dgwt-wcas-suggestion-no-border-bottom'); 1244 1245 if (dH < sH) { 1246 $detailsWrapp.css('height', (sH) + 'px'); 1247 } 1248 1249 if (sH < dH) { 1250 $suggestionsWrapp.css('height', dH + 'px'); 1251 } 1252 1253 return false;
1254 }, 1255 automaticAlignment: function () { 1256 var that = this, 1257 $input = that.getFormWrapper().find('.dgwt-wcas-search-input'), 1258 $suggestionsContainer = that.getSuggestionsContainer(), 1259 $detailsWrapp = that.getDetailsContainer(); 1260 1261 if (that.autoAligmentprocess != null) { 1262 return; 1263 } 1264 1265 var markers = [$input.width(), $suggestionsContainer.height()]; 1266 if (that.canShowDetailsPanel()) { 1267 markers[2] = $detailsWrapp.height(); 1268 } 1269 1270 that.autoAligmentprocess = setInterval(function () { 1271 1272 var newMarkers = [$input.width(), $suggestionsContainer.height()]; 1273 if (that.canShowDetailsPanel()) { 1274 newMarkers[2] = $detailsWrapp.height(); 1275 } 1276 1277 for (var i = 0; i < markers.length; i++) { 1278 1279 if (markers[i] != newMarkers[i]) { 1280 1281 that.fixHeight(); 1282 that.fixPosition(); 1283 markers = newMarkers; 1284 break; 1285 } 1286 } 1287 1288 1289 if (that.canShowDetailsPanel()) { 1290 1291 var innerDetailsHeight = $detailsWrapp.find('.dgwt-wcas-details-inner').height(); 1292 1293 1294 if ((innerDetailsHeight - $detailsWrapp.height()) > 2) { 1295 that.fixHeight(); 1296 } 1297 } 1298 1299 }, 10); 1300 1301 }, 1302 getElementInfo: function ($el) { 1303 var data = {}, 1304 viewPort, 1305 offset; 1306 1307 viewPort = $el[0].getBoundingClientRect(); 1308 offset = $el.offset(); 1309 1310 data.left = offset.left; 1311 data.top = offset.top; 1312 data.width = $el.outerWidth(false); 1313 data.height = $el.outerHeight(false); 1314 data.right = data.left + data.width; 1315 data.bottom = data.top + data.height; 1316 data.topViewPort = viewPort.top; 1317 data.bottomViewPort = viewPort.top + data.height; 1318 1319 return data; 1320 }, 1321 getFormWrapper: function () { 1322 var that = this; 1323 return that.el.closest('.' + that.options.searchFormClass); 1324 }, 1325 getForm: function () { 1326 var that = this; 1327 return that.el.closest('.' + that.options.formClass); 1328 }, 1329 getSuggestionsContainer: function () { 1330 var that = this; 1331 return $('.' + that.options.containerClass); 1332 }, 1333 getDetailsContainer: function () { 1334 var that = this; 1335 return $('.' + that.options.containerDetailsClass); 1336 }, 1337 scrollDownSuggestions: function () { 1338 var that = this, 1339 $el = that.getSuggestionsContainer(); 1340 $el[0].scrollTop = $el[0].scrollHeight; 1341 }, 1342 isCursorAtEnd: function () { 1343 var that = this, 1344 valLength = that.el.val().length, 1345 selectionStart = that.element.selectionStart, 1346 range; 1347 1348 if (typeof selectionStart === 'number') { 1349 return selectionStart === valLength; 1350 } 1351 if (document.selection) { 1352 range = document.selection.createRange(); 1353 range.moveStart('character', -valLength); 1354 return valLength === range.text.length; 1355 } 1356 return true; 1357 }, 1358 onKeyPress: function (e) { 1359 var that = this, 1360 $wrapp = that.getFormWrapper(); 1361 1362 that.addActiveClassIfMissing(); 1363 1364 // If suggestions are hidden and user presses arrow down, display suggestions: 1365 if (!that.visible && e.keyCode === keys.DOWN && that.currentValue) { 1366 that.suggest(); 1367 return; 1368 } 1369 1370 if (!that.visible) { 1371 // Hide the search icon mode on ESC when there are no suggestions 1372 if (e.keyCode === keys.ESC && $wrapp.hasClass('dgwt-wcas-layout-icon-open')) { 1373 that.hideIconModeSearch(); 1374 } 1375 1376 // Hide the darkened overlay on ESC when there are no suggestions 1377 if (e.keyCode === keys.ESC && that.isMountedOverlayDarkened()) { 1378 that.disableOverlayDarkened(); 1379 that.el.blur(); 1380 } 1381 1382 return; 1383 } 1384 1385 // Open selected suggestion in new tab 1386 if ((e.ctrlKey || e.metaKey) && e.keyCode === keys.RETURN) { 1387 if (that.selectedIndex > -1) { 1388 that.openInNewTab(that.selectedIndex); 1389 } 1390 return; 1391 } 1392 1393 switch (e.keyCode) { 1394 case keys.ESC: 1395 that.close(); 1396 break; 1397 case keys.RIGHT: 1398 if (that.hint && that.options.onHint && that.isCursorAtEnd()) { 1399 that.selectHint(); 1400 break; 1401 } 1402 return; 1403 case keys.TAB: 1404 break; 1405 case keys.RETURN: 1406 1407 if (that.selectedIndex === -1) { 1408 if (that.options.disableSubmit) { 1409 return false;
1410 } 1411 that.hide(); 1412 return; 1413 } 1414 that.actionTriggerSource = 'enter'; 1415 that.select(that.selectedIndex); 1416 break; 1417 case keys.UP: 1418 that.moveUp(); 1419 break; 1420 case keys.DOWN: 1421 that.moveDown(); 1422 break; 1423 default: 1424 return; 1425 } 1426 1427 // Cancel event if function did not return: 1428 e.stopImmediatePropagation(); 1429 e.preventDefault(); 1430 }, 1431 onKeyUp: function (e) { 1432 var that = this; 1433 1434 switch (e.keyCode) { 1435 case keys.UP: 1436 case keys.DOWN: 1437 return; 1438 } 1439 1440 clearTimeout(that.onChangeTimeout); 1441 1442 if (that.currentValue !== that.el.val()) { 1443 if (that.options.deferRequestBy > 0) { 1444 // Defer lookup in case when value changes very quickly: 1445 that.onChangeTimeout = setTimeout(function () { 1446 that.onValueChange(); 1447 }, that.options.deferRequestBy); 1448 } else { 1449 that.onValueChange(); 1450 } 1451 } 1452 }, 1453 onValueChange: function () { 1454 if (this.ignoreValueChange) { 1455 this.ignoreValueChange = false; 1456 return; 1457 } 1458 1459 var that = this, 1460 options = that.options, 1461 value = that.el.val(), 1462 query = that.getQuery(value), 1463 $wrapp = that.getFormWrapper(); 1464 1465 if (that.selection && that.currentValue !== query) { 1466 that.selection = null; 1467 (options.onInvalidateSelection || $.noop).call(that.element); 1468 } 1469 1470 clearTimeout(that.onChangeTimeout); 1471 that.currentValue = value; 1472 that.selectedIndex = -1; 1473 1474 // Check existing suggestion for the match before proceeding: 1475 if (options.triggerSelectOnValidInput && that.isExactMatch(query)) { 1476 that.select(0); 1477 return; 1478 } 1479 1480 // Mark as filled 1481 if (query.length > 0) { 1482 if (!$wrapp.hasClass(that.classes.inputFilled)) { 1483 $wrapp.addClass(that.classes.inputFilled); 1484 } 1485 } else { 1486 $wrapp.removeClass(that.classes.inputFilled); 1487 } 1488 1489 if (query.length < options.minChars) { 1490 1491 if (that.canShowPreSuggestions() && query.length === 0) { 1492 that.showPreSuggestions(); 1493 } else { 1494 that.hideCloseButton(); 1495 that.hide(); 1496 } 1497 } else { 1498 that.getSuggestions(query); 1499 } 1500 }, 1501 isExactMatch: function (query) { 1502 var suggestions = this.suggestions; 1503 1504 return (suggestions.length === 1 && suggestions[0].value.toLowerCase() === query.toLowerCase()); 1505 }, 1506 isNoResults: function (suggestions) { 1507 return suggestions.length === 1 && typeof suggestions[0].type !== 'undefined' && suggestions[0].type === 'no-results'; 1508 }, 1509 canShowDetailsPanel: function () { 1510 var that = this,
1511 show = that.options.showDetailsPanel; 1512 1513 if ($(window).width() < 768 || ('ontouchend' in document) || that.isPreSuggestionsMode) { 1514 show = false; 1515 } 1516 return show; 1517 }, 1518 isBreakpointReached: function (context) { 1519 var that = this, 1520 breakpoint = 0; 1521 1522 switch (context) { 1523 case 'search-layout': 1524 breakpoint = that.options.layoutBreakpoint; 1525 if (that.isSetParam('layout_breakpoint')) { 1526 breakpoint = Number.parseInt(that.getParam('layout_breakpoint')); 1527 } 1528 break; 1529 case 'mobile-overlay': 1530 breakpoint = that.options.mobileOverlayBreakpoint; 1531 if (that.isSetParam('mobile_overlay_breakpoint')) { 1532 breakpoint = Number.parseInt(that.getParam('mobile_overlay_breakpoint')); 1533 } 1534 break; 1535 } 1536 1537 return $(window).width() <= breakpoint; 1538 }, 1539 getQuery: function (value) { 1540 var delimiter = this.options.delimiter, 1541 parts; 1542 1543 if (!delimiter) { 1544 return value.trim(); 1545 } 1546 parts = value.split(delimiter); 1547 return $.trim(parts[parts.length - 1]); 1548 }, 1549 getSuggestionsLocal: function (query) { 1550 var that = this, 1551 options = that.options, 1552 queryLowerCase = query.toLowerCase(), 1553 filter = options.lookupFilter, 1554 limit = parseInt(options.lookupLimit, 10), 1555 data; 1556 1557 data = { 1558 suggestions: $.grep(options.lookup, function (suggestion) { 1559 return filter(suggestion, query, queryLowerCase); 1560 }) 1561 }; 1562 1563 if (limit && data.suggestions.length > limit) { 1564 data.suggestions = data.suggestions.slice(0, limit); 1565 } 1566 1567 return data; 1568 }, 1569 getSuggestions: function (q) { 1570 var response, 1571 that = this, 1572 options = that.options, 1573 serviceUrl = options.serviceUrl, 1574 searchForm = that.getFormWrapper(), 1575 params, 1576 cacheKey, 1577 ajaxSettings, 1578 iconSearchActive = that.isActiveIconModeSearch(); 1579 1580 options.params[options.paramName] = q; 1581 1582 if (typeof dgwt_wcas.current_lang != 'undefined') { 1583 options.params['l'] = dgwt_wcas.current_lang; 1584 } 1585 1586 that.preloader('show', 'form', 'dgwt-wcas-inner-preloader'); 1587 searchForm.addClass('dgwt-wcas-processing'); 1588 1589 if (options.onSearchStart.call(that.element, options.params) === false) { 1590 return; 1591 } 1592 1593 params = options.ignoreParams ? null : options.params; 1594 1595 if ($.isFunction(options.lookup)) { 1596 options.lookup(q, function (data) { 1597 that.suggestions = data.suggestions; 1598 that.suggest(); 1599 that.selectFirstSuggestion(data.suggestions); 1600 options.onSearchComplete.call(that.element, q, data.suggestions); 1601 }); 1602 return; 1603 } 1604 1605 if (!$('body').hasClass('dgwt-wcas-open')) { 1606 document.dispatchEvent(new CustomEvent('fibosearch/open', { 1607 detail: that 1608 })); 1609 } 1610 1611 if (that.isLocal) { 1612 response = that.getSuggestionsLocal(q); 1613 } else { 1614 if ($.isFunction(serviceUrl)) { 1615 serviceUrl = serviceUrl.call(that.element, q); 1616 } 1617 cacheKey = serviceUrl + '?' + $.param(params || {}); 1618 response = that.cachedResponse[cacheKey]; 1619 } 1620 1621 if (response && Array.isArray(response.suggestions)) { 1622 that.suggestions = response.suggestions; 1623 that.suggest(); 1624 that.selectFirstSuggestion(response.suggestions); 1625 options.onSearchComplete.call(that.element, q, response.suggestions); 1626 1627 if (that.isNoResults(response.suggestions)) { 1628 document.dispatchEvent(new CustomEvent('fibosearch/no-results', { 1629 detail: that 1630 })); 1631 } else { 1632 document.dispatchEvent(new CustomEvent('fibosearch/show-suggestions', { 1633 detail: that 1634 })); 1635 } 1636 } else if (!that.isBadQuery(q)) { 1637 that.abortAjax(); 1638 1639 ajaxSettings = { 1640 url: serviceUrl, 1641 data: params, 1642 type: options.type, 1643 dataType: options.dataType 1644 }; 1645 1646 $.extend(ajaxSettings, options.ajaxSettings); 1647 1648 ajaxDebounceState.object = that; 1649 ajaxDebounceState.ajaxSettings = ajaxSettings; 1650 1651 utils.debounce(function () { 1652 1653 var that = ajaxDebounceState.object, 1654 ajaxSettings = ajaxDebounceState.ajaxSettings; 1655 1656 1657 that.currentRequest = $.ajax(ajaxSettings).done(function (data) { 1658 1659 // Interrupt if the icon mode was closed in the meantime
1660 if (iconSearchActive && !that.isActiveIconModeSearch()) { 1661 return; 1662 } 1663 1664 var result; 1665 that.currentRequest = null; 1666 result = that.options.transformResult(data, q); 1667 1668 if (typeof result.suggestions !== 'undefined') { 1669 that.processResponse(result, q, cacheKey); 1670 that.selectFirstSuggestion(result.suggestions); 1671 1672 if (that.isNoResults(result.suggestions)) { 1673 that.gaEvent(q, 'Autocomplete Search without results'); 1674 } else { 1675 that.gaEvent(q, 'Autocomplete Search with results'); 1676 } 1677 } 1678 1679 that.fixPosition(); 1680 1681 that.options.onSearchComplete.call(that.element, q, result.suggestions); 1682 1683 that.updatePrices(); 1684 1685 if (that.isNoResults(result.suggestions)) { 1686 document.dispatchEvent(new CustomEvent('fibosearch/no-results', { 1687 detail: that 1688 })); 1689 } else { 1690 document.dispatchEvent(new CustomEvent('fibosearch/show-suggestions', { 1691 detail: that 1692 })); 1693 } 1694 }).fail(function (jqXHR, textStatus, errorThrown) { 1695 that.options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown); 1696 }); 1697 1698 1699 }, options.debounceWaitMs); 1700 1701 1702 } else { 1703 options.onSearchComplete.call(that.element, q, []); 1704 } 1705 1706 }, 1707 getDetails: function (suggestion) { 1708 var that = this; 1709 1710 // Disable details panel 1711 if (!that.canShowDetailsPanel()) { 1712 return false; 1713 } 1714 1715 // Brake if there are no suggestions 1716 if (suggestion == null || typeof suggestion.type == 'undefined') { 1717 return; 1718 } 1719 1720 // Disable on more product suggestion 1721 if (typeof suggestion.type == 'string' && suggestion.type === 'more_products') { 1722 return; 1723 } 1724 1725 that.fixHeight(); 1726 1727 var $containerDetails = that.getDetailsContainer(), 1728 currentObjectID = that.prepareSuggestionObjectID(suggestion), 1729 result; 1730 1731 // Check cache 1732 result = that.cachedDetails[currentObjectID]; 1733 1734 if (result != null) { 1735 1736 // Load response from cache 1737 that.detailsPanelSetScene(currentObjectID); 1738 that.fixHeight(); 1739 that.fixPosition(); 1740 1741 } else { 1742 1743 var data = { 1744 action: dgwt_wcas.action_result_details, 1745 items: [] 1746 }; 1747 1748 $.each(that.suggestions, function (i, suggestion) { 1749 1750 if ( 1751 typeof suggestion.type != 'undefined' 1752 && suggestion.type != 'more_products' 1753 && suggestion.type != 'headline' 1754 ) { 1755 var itemData = { 1756 objectID: that.prepareSuggestionObjectID(suggestion), 1757 value: suggestion.value != null ? suggestion.value : '' 1758 }; 1759 data.items.push(itemData); 1760 } 1761 }); 1762 1763 1764 that.detailsPanelClearScene(); 1765 that.preloader('show', 'details', ''); 1766 1767 // Prevent duplicate ajax requests 1768 if ($.inArray(currentObjectID, that.detailsRequestsSent) != -1) { 1769 return; 1770 } else { 1771 that.detailsRequestsSent.push(currentObjectID); 1772 } 1773 1774 $.ajax({ 1775 data: data, 1776 type: 'post', 1777 url: dgwt_wcas.ajax_details_endpoint, 1778 success: function (response) { 1779 1780 var result = typeof response === 'string' ? JSON.parse(response)
1780: response; 1781 1782 if (typeof result.items != 'undefined') { 1783 for (var i = 0; i < result.items.length; i++) { 1784 var cacheKey = result.items[i]['objectID']; 1785 that.cachedDetails[cacheKey] = {html: result.items[i]['html']} 1786 that.detailsPanelAddToScene(cacheKey); 1787 1788 if (typeof result.items[i]['price'] != 'undefined' && result.items[i]['price'].length > 0) { 1789 that.cachedPrices[cacheKey] = result.items[i]['price']; 1790 } 1791 } 1792 } 1793 1794 that.preloader('hide', 'details', ''); 1795 1796 var currentObjectID = that.prepareSuggestionObjectID(that.suggestions[that.selectedIndex]); 1797 1798 if (that.cachedDetails[currentObjectID] != null) { 1799 that.detailsPanelSetScene(currentObjectID); 1800 } else { 1801 // @TODO Maybe display some error or placeholder 1802 that.detailsPanelClearScene(); 1803 } 1804 that.fixPosition(); 1805 that.fixHeight(); 1806 1807 that.updatePrices(true); 1808 }, 1809 error: function (jqXHR, exception) { 1810 1811 that.preloader('hide', 'details', ''); 1812 1813 that.detailsPanelClearScene(); 1814 that.fixPosition(); 1815 that.fixHeight(); 1816 }, 1817 }); 1818 } 1819 1820 $(document).trigger('dgwtWcasDetailsPanelLoaded', that); 1821 document.dispatchEvent(new CustomEvent('fibosearch/show-details-panel', { 1822 detail: that 1823 })); 1824 }, 1825 updatePrices: function (noAjax) { 1826 var that = this, 1827 i, j, 1828 productsToLoad = []; 1829 1830 if (!(that.options.showPrice && that.options.dynamicPrices)) { 1831 return; 1832 } 1833 1834 if (that.suggestions.length == 0) { 1835 return; 1836 } 1837 1838 for (i = 0; i < that.suggestions.length; i++) { 1839 1840 if ( 1841 typeof that.suggestions[i].type != 'undefined' 1842 && (that.suggestions[i].type == 'product' || that.suggestions[i].type == 'product_variation') 1843 ) { 1844 var key = 'product__' + that.suggestions[i].post_id; 1845 1846 if (typeof that.cachedPrices[key] != 'undefined') { 1847 1848 that.updatePrice(i, that.cachedPrices[key]); 1849 1850 } else { 1851 1852 that.applyPreloaderForPrice(i); 1853 1854 productsToLoad.push(that.suggestions[i].post_id); 1855 } 1856 } 1857 1858 } 1859 1860 1861 if (!noAjax && productsToLoad.length > 0) { 1862 1863 var data = { 1864 action: typeof dgwt_wcas.action_get_prices == 'undefined' ? 'dgwt_wcas_get_prices' : dgwt_wcas.action_get_prices, 1865 items: productsToLoad 1866 }; 1867 1868 $.ajax({ 1869 data: data, 1870 type: 'post', 1871 url: dgwt_wcas.ajax_prices_endpoint, 1872 success: function (response) { 1873 1874 if (typeof response.success != 'undefined' && response.success && response.data.length > 0) { 1875 for (i = 0; i < response.data.length; i++) { 1876 1877 var postID = response.data[i].id, 1878 price = response.data[i].price; 1879 1880 if (that.suggestions.length > 0) { 1881 for (j = 0; j < that.suggestions.length; j++) { 1882 if ( 1883 typeof that.suggestions[j].type != 'undefined' 1884 && (that.suggestions[j].type == 'product' || that.suggestions[j].type == 'product_variation') 1885 && that.suggestions[j].post_id == postID 1886 ) { 1887 1888 var key = 'product__' + postID; 1889 1890 that.cachedPrices[key] = price; 1891 1892 that.updatePrice(j, price); 1893 1894 } 1895 } 1896 } 1897 } 1898 } 1899 1900 }, 1901 error: function (jqXHR, exception) { 1902 1903 }, 1904 }); 1905 1906 } 1907 1908 }, 1909 updatePrice: function (index, price) { 1910 var that = this; 1911 1912 if (typeof that.suggestions[index] != 'undefined') { 1913 1914 that.suggestions[index].price = price; 1915 1916 var $price = $('.dgwt-wcas-suggestions-wrapp').find('[data-index="' + index + '"] .dgwt-wcas-sp'); 1917 1918 if ($price.length) { 1919 $price.html(price); 1920 } 1921 } 1922 1923 }, 1924 applyCustomParams: function (params) { 1925 var that = this; 1926 1927 // Custom params (global) 1928 if (typeof dgwt_wcas.custom_params == 'object') { 1929 var cp = dgwt_wcas.custom_params; 1930 for (var property in cp) { 1931 params[property] = cp[property]; 1932 } 1933 } 1934 1935 // Custom params (local) 1936 var inputCustomParams = that.el.data('custom-params'); 1937 1938 if (typeof inputCustomParams === 'object') { 1939 for (var property in inputCustomParams) { 1940 params[property] = inputCustomParams[property]; 1941 } 1942 } 1943 1944 return params; 1945 }, 1946 isSetParam: function (param) { 1947 var that = this; 1948 return typeof that.options.params[param] != 'undefined'; 1949 }, 1950 getParam: function (param) { 1951 var that = this; 1952 return that.isSetParam(param) ? that.options.params[param] : ''; 1953 }, 1954 applyPreloaderForPrice: function (index) { 1955 var that = this; 1956 1957 if (typeof that.suggestions[index] != 'undefined') { 1958 var $price = $('.dgwt-wcas-suggestions-wrapp').find('[data-index="' + index + '"] .dgwt-wcas-sp'); 1959 if ($price.length) { 1960 $price.html('<div class="dgwt-wcas-preloader-price"><div class="dgwt-wcas-preloader-price-inner"> <div></div><div></div><div></div></div></div>'); 1961 } 1962 } 1963 }, 1964 prepareSuggestionObjectID: function (suggestion) { 1965 var objectID = ''; 1966 1967 if (typeof suggestion != 'undefined' && typeof suggestion.type != 'undefined') { 1968 1969 //Products and post types 1970 if (suggestion.post_id != null) { 1971 objectID = suggestion.type + '__' + suggestion.post_id; 1972 1973 if (suggestion.type === 'product_variation') { 1974 objectID += '__' + suggestion.variation_id; 1975 } 1976 1977 // Post types 1978 if (typeof suggestion.post_type != 'undefined') { 1979 objectID = suggestion.type + '__' + suggestion.post_id + '__' + suggestion.post_type; 1980 } 1981 1982 } 1983 1984 //Terms 1985 if (suggestion.term_id != null && suggestion.taxonomy != null) { 1986 objectID = suggestion.type + '__' + suggestion.term_id + '__' + suggestion.taxonomy; 1987 } 1988 } 1989 1990 return objectID; 1991 }, 1992 detailsPanelSetScene: function (objectID) { 1993 var that = this, 1994 $containerDetails = that.getDetailsContainer(), 1995 objectHash = utils.hashCode(objectID),
1996 $el = $containerDetails.find('.dgwt-wcas-details-inner[data-object="' + objectHash + '"]'); 1997 1998 if ($el.length) { 1999 that.preloader('hide', 'details', ''); 2000 that.detailsPanelClearScene(); 2001 $el.addClass('dgwt-wcas-details-inner-active'); 2002 } 2003 }, 2004 detailsPanelAddToScene: function (objectID) { 2005 var that = this, 2006 $containerDetails = that.getDetailsContainer(), 2007 object = that.cachedDetails[objectID], 2008 objectHash = utils.hashCode(objectID), 2009 html = ''; 2010 2011 if (typeof object != 'undefined' && typeof object.html == 'string') { 2012 html = object.html.replace('<div ', '<div data-object="' + objectHash + '" '); 2013 } 2014 2015 if ($containerDetails.find('.dgwt-wcas-details-inner[data-object="' + objectHash + '"]').length == 0) { 2016 $containerDetails.append(html); 2017 } 2018 }, 2019 detailsPanelClearScene: function () { 2020 var that = this, 2021 $containerDetails = that.getDetailsContainer(), 2022 $views = $containerDetails.find('.dgwt-wcas-details-inner'); 2023 2024 if ($views.length) { 2025 $views.removeClass('dgwt-wcas-details-inner-active'); 2026 } 2027 }, 2028 selectFirstSuggestion: function (suggestions) { 2029 var that = this, 2030 index = 0, 2031 noResults = false; 2032 2033 if (!that.canShowDetailsPanel()) { 2034 return; 2035 } 2036 2037 if (suggestions != 'undefined' && suggestions.length > 0) { 2038 $.each(that.suggestions, function (i, suggestion) { 2039 2040 if ( 2041 typeof suggestion.type != 'undefined' 2042 && suggestion.type != 'more_products' 2043 && suggestion.type != 'headline' 2044 && suggestion.type != 'headline-v2' 2045 && suggestion.type != 'no-results' 2046 ) { 2047 index = i; 2048 return false; 2049 } 2050 2051 if (typeof suggestion.type === 'undefined' || suggestion.type === 'no-results') { 2052 noResults = true; 2053 } 2054 2055 }); 2056 } 2057 2058 if (noResults) { 2059 return; 2060 } 2061 2062 that.latestActivateSource = 'system'; 2063 that.getDetails(suggestions[index]); 2064 that.activate(index); 2065 }, 2066 isBadQuery: function (q) { 2067 if (!this.options.preventBadQueries) { 2068 return false; 2069 } 2070 2071 var badQueries = this.badQueries, 2072 i = badQueries.length; 2073 2074 while (i--) { 2075 if (q.indexOf(badQueries[i]) === 0) { 2076 return true; 2077 } 2078 } 2079 2080 return false; 2081 }, 2082 hide: function (clear) { 2083 var that = this, 2084 $suggestions = that.getSuggestionsContainer(), 2085 $detailsPanel = that.getDetailsContainer(); 2086 2087 if ($.isFunction(that.options.onHide) && that.visible) { 2088 that.options.onHide.call(that.element, container); 2089 } 2090 2091 that.visible = false; 2092 that.selectedIndex = -1; 2093 clearTimeout(that.onChangeTimeout); 2094 $suggestions.hide(); 2095 $suggestions.removeClass(that.classes.suggestionsContainerOrientTop); 2096 $suggestions.removeClass(that.classes.fixed); 2097 2098 if (that.canShowDetailsPanel()) { 2099 $detailsPanel.hide(); 2100 $detailsPanel.removeClass(that.classes.fixed); 2101 } 2102 2103 that.hidePreSuggestions(); 2104 2105 $('body').removeClass('dgwt-wcas-open'); 2106 if (!$('html').hasClass('dgwt-wcas-overlay-mobile-on')) { 2107 $('html').removeClass('dgwt-wcas-open-' + that.getSearchStyle()); 2108 } 2109 $('body').removeClass('dgwt-wcas-block-scroll');
2110 $('body').removeClass('dgwt-wcas-is-details'); 2111 $('body').removeClass('dgwt-wcas-full-width'); 2112 $('body').removeClass('dgwt-wcas-nores'); 2113 $('body').removeClass('dgwt-wcas-details-outside'); 2114 $('body').removeClass('dgwt-wcas-details-right'); 2115 $('body').removeClass('dgwt-wcas-details-left'); 2116 2117 if (that.autoAligmentprocess != null) { 2118 clearInterval(that.autoAligmentprocess); 2119 that.autoAligmentprocess = null; 2120 } 2121 2122 that.isMouseDownOnSearchElements = false; 2123 2124 if (typeof clear == 'boolean' && clear) { 2125 2126 that.hideCloseButton(); 2127 2128 that.currentValue = ''; 2129 that.suggestions = []; 2130 2131 } 2132 }, 2133 positionIconSearchMode: function ($formWrapper) { 2134 var that = this, 2135 formLeftValue = -20, 2136 $form = that.getForm(), 2137 formWidth = $form.width(), 2138 windowWidth = $(window).width(); 2139 2140 var iconLeftOffset = $formWrapper[0].getBoundingClientRect().left; 2141 2142 var iconLeftRatio = (iconLeftOffset + 10) / windowWidth; 2143 2144 formLeftValue = Math.floor(-1 * (formWidth * iconLeftRatio)); 2145 2146 // Prevent shifting to the left more than the icon position (also positioned from the left) 2147 formLeftValue = Math.max(formLeftValue, -1 * iconLeftOffset); 2148 2149 $form.css({'left': formLeftValue + 'px'}); 2150 2151 }, 2152 isActiveIconModeSearch: function () { 2153 var active = false, 2154 $openedElements = $('.dgwt-wcas-layout-icon-open'); 2155 if ($openedElements.length > 0) { 2156 active = true; 2157 } 2158 return active; 2159 }, 2160 hideIconModeSearch: function () { 2161 var that = this; 2162 2163 if (that.isActiveIconModeSearch() && !utils.isTextSelected()) { 2164 $('.dgwt-wcas-layout-icon-open').removeClass('dgwt-wcas-layout-icon-open'); 2165 } 2166 }, 2167 hideAfterClickOutsideListener: function () { 2168 var that = this; 2169 if (!('ontouchend' in document)) { 2170 2171 $(document).mouseup(function (e) { 2172 if (!that.visible) { 2173 return; 2174 } 2175 2176 var outsideForm = !($(e.target).closest('.' + that.options.searchFormClass).length > 0 || $(e.target).hasClass(that.options.searchFormClass)), 2177 outsideContainer = !($(e.target).closest('.' + that.options.containerClass).length > 0 || $(e.target).hasClass(that.options.containerClass)); 2178 2179 if (!that.canShowDetailsPanel()) { 2180 2181 if (outsideForm && outsideContainer) { 2182 that.hide(); 2183 } 2184 2185 } else { 2186 2187 var outsidecontainerDetails = !($(e.target).closest('.' + that.options.containerDetailsClass).length > 0 || $(e.target).hasClass(that.options.containerDetailsClass)); 2188 2189 if (outsideForm && outsideContainer && outsidecontainerDetails) { 2190 that.hide(); 2191 } 2192 2193 } 2194 2195 }); 2196 2197 } 2198 }, 2199 suggest: function () { 2200 if (!this.suggestions.length) { 2201 this.hide(); 2202 return; 2203 } 2204 2205 var that = this, 2206 options = that.options, 2207 groupBy = options.groupBy, 2208 formatResult = options.formatResult, 2209 value = that.getQuery(that.currentValue), 2210 className = that.classes.suggestion, 2211 classSelected = that.classes.selected, 2212 container = that.getSuggestionsContainer(), 2213 containerDetails = that.getDetailsContainer(), 2214 noSuggestionsContainer = $(that.noSuggestionsContainer), 2215 beforeRender = options.beforeRender, 2216 html = '', 2217 category, 2218 formatGroup = function (suggestion, index) { 2219 var currentCategory = suggestion.data[groupBy]; 2220 2221 if (category === currentCategory) { 2222 return ''; 2223 } 2224 2225 category = currentCategory; 2226 2227 return '<div class="autocomplete-group"><strong>' + category + '</strong></div>'; 2228 }; 2229 2230 if (options.triggerSelectOnValidInput && that.isExactMatch(value)) { 2231 that.select(0); 2232 return; 2233 } 2234 2235 $('body').removeClass('dgwt-wcas-nores'); 2236 2237 // Build suggestions inner HTML: 2238 $.each(that.suggestions, function (i, suggestion) { 2239 2240 var url = typeof suggestion.url == 'string' && suggestion.url.length ? suggestion.url : '#'; 2241 2242 if (groupBy) { 2243 html += formatGroup(suggestion, value, i); 2244 } 2245 2246 if (typeof suggestion.type == 'undefined' || (suggestion.type != 'product') && suggestion.type != 'product_variation') { 2247 2248 var classes = className, 2249 innerClass = 'dgwt-wcas-st', 2250 prepend = '', 2251 append = '', 2252 title = '', 2253 highlight = true, 2254 isImg; 2255 2256 if (suggestion.taxonomy === 'product_cat') { 2257 classes += ' dgwt-wcas-suggestion-tax dgwt-wcas-suggestion-cat'; 2258 if (!options.showHeadings) { 2259 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels['tax_' + suggestion.taxonomy] + '</span>'; 2260 } 2261 if (typeof suggestion.breadcrumbs != 'undefined' && suggestion.breadcrumbs) { 2262 title = suggestion.breadcrumbs + ' > ' + suggestion.value; 2263 append += '<span class="dgwt-wcas-st-breadcrumbs"><span class="dgwt-wcas-st-label-in">' + dgwt_wcas.labels.in + ' </span>' + suggestion.breadcrumbs + '</span>'; 2264 //@TODO RTL support 2265 } 2266 2267 } else if (suggestion.taxonomy === 'product_tag') { 2268 classes += ' dgwt-wcas-suggestion-tax dgwt-wcas-suggestion-tag'; 2269 if (!options.showHeadings) { 2270 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels['tax_' + suggestion.taxonomy] + '</span>'; 2271 } 2272 } else if (options.isPremium && suggestion.taxonomy === options.taxonomyBrands) { 2273 classes += ' dgwt-wcas-suggestion-tax dgwt-wcas-suggestion-brand'; 2274 if (!options.showHeadings) { 2275 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels['tax_' + suggestion.taxonomy] + '</span>'; 2276 } 2277 } else if (options.isPremium && suggestion.type === 'taxonomy') { 2278 classes += ' dgwt-wcas-suggestion-tax dgwt-wcas-suggestion-tax-' + suggestion.taxonomy; 2279 if (!options.showHeadings) { 2280 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels['tax_' + suggestion.taxonomy] + '</span>'; 2281 } 2282 } else if (options.isPremium && suggestion.type === 'vendor') { 2283 classes += ' dgwt-wcas-suggestion-vendor dgwt-wcas-suggestion-vendor'; 2284 if (!options.showHeadings) { 2285 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels.vendor + '</span>'; 2286 } 2287 } else if (options.isPremium && suggestion.type === 'post' && typeof suggestion.post_type !== 'undefined' && suggestion.post_type === 'post') { 2288 classes += ' dgwt-wcas-suggestion-pt dgwt-wcas-suggestion-pt-post'; 2289 if (!options.showHeadings) { 2290 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels.post + '</span>'; 2291 } 2292 } else if (options.isPremium && suggestion.type === 'post' && typeof suggestion.post_type !== 'undefined' && suggestion.post_type === 'page') { 2293 classes += ' dgwt-wcas-suggestion-pt dgwt-wcas-suggestion-pt-page'; 2294 if (!options.showHeadings) { 2295 prepend += '<span class="dgwt-wcas-st--direct-headline">' + dgwt_wcas.labels.page + '</span>'; 2296 } 2297 } else if (suggestion.type === 'more_products') { 2298 classes += ' js-dgwt-wcas-suggestion-more dgwt-wcas-suggestion-more'; 2299 innerClass = 'dgwt-wcas-st-more'; 2300 suggestion.value = dgwt_wcas.labels.show_more + '<span class="dgwt-wcas-st-more-total"> (' + suggestion.total + ')</span>'; 2301 highlight = false;
2302 } else if (options.showHeadings && suggestion.type === 'headline') { 2303 classes += ' js-dgwt-wcas-suggestion-headline dgwt-wcas-suggestion-headline'; 2304 if (typeof dgwt_wcas.labels[suggestion.value + '_plu'] != 'undefined') { 2305 suggestion.value = dgwt_wcas.labels[suggestion.value + '_plu']; 2306 } 2307 highlight = false; 2308 } else { 2309 classes += ' dgwt-wcas-suggestion-nores'; 2310 suggestion.value = dgwt_wcas.labels.no_results; 2311 highlight = false; 2312 if (that.canShowDetailsPanel()) { 2313 that.detailsPanelClearScene(); 2314 } 2315 $('body').addClass('dgwt-wcas-nores'); 2316 } 2317 2318 // Image 2319 if (typeof suggestion.image_src != 'undefined' && suggestion.image_src) { 2320 isImg = true; 2321 } 2322 2323 title = title.length > 0 ? ' title="' + title + '"' : ''; 2324 2325 html += '<a href="' + url + '" class="' + classes + '" data-index="' + i + '">'; 2326 2327 if (isImg) { 2328 html += '<span class="dgwt-wcas-si"><img src="' + suggestion.image_src + '" /></span>'; 2329 html += '<div class="dgwt-wcas-content-wrapp">'; 2330 } 2331 2332 html += '<span' + title + ' class="' + innerClass + '">'; 2333 2334 if (suggestion.type === 'vendor') { 2335 html += '<span class="dgwt-wcas-st-title">' + prepend + formatResult(suggestion.value, value, highlight, options) + append + '</span>'; 2336 2337 // Vendor city 2338 if (suggestion.shop_city) { 2339 html += '<span class="dgwt-wcas-vendor-city"><span> - </span>' + formatResult(suggestion.shop_city, value, true, options) + '</span>'; 2340 } 2341 2342 // Description 2343 if (typeof suggestion.desc != 'undefined' && suggestion.desc) { 2344 html += '<span class="dgwt-wcas-sd">' + formatResult(suggestion.desc, value, true, options) + '</span>'; 2345 } 2346 2347 } else { 2348 html += prepend + formatResult(suggestion.value, value, highlight, options) + append; 2349 } 2350 2351 html += '</span>'; 2352 2353 html += isImg ? '</div>' : ''; 2354 html += '</a>'; 2355 } else { 2356 2357 html += that.createProductSuggestion(suggestion, i); 2358 2359 } 2360 }); 2361 2362 this.adjustContainerWidth(); 2363 2364 noSuggestionsContainer.detach(); 2365 container.html(html); 2366 2367 if ($.isFunction(beforeRender)) { 2368 beforeRender.call(that.element, container, that.suggestions); 2369 } 2370 2371 container.show(); 2372 2373 // Add class on show 2374 $('body').addClass('dgwt-wcas-open'); 2375 $('html').addClass('dgwt-wcas-open-' + that.getSearchStyle()); 2376 2377 // Reset the latest mousedown position 2378 that.isMouseDownOnSearchElements = false; 2379 2380 that.automaticAlignment(); 2381 2382 if (that.canShowDetailsPanel()) { 2383 $('body').addClass('dgwt-wcas-is-details'); 2384 containerDetails.show(); 2385 that.fixHeight(); 2386 } 2387 2388 // Select first value by default: 2389 if (options.autoSelectFirst) { 2390 that.selectedIndex = 0; 2391 container.scrollTop(0); 2392 container.children('.' + className).first().addClass(classSelected); 2393 } 2394 2395 that.visible = true; 2396 that.fixPosition(); 2397 }, 2398 createProductSuggestion: function (suggestion, index, extClassName) { 2399 var that = this, 2400 html = '', 2401 parent = '', 2402 dataAttrs = '', 2403 options = that.options, 2404 className = that.classes.suggestion, 2405 isImg = false, 2406 value = that.getQuery(that.currentValue), 2407 formatResult = options.formatResult, 2408 url = typeof suggestion.url == 'string' && suggestion.url.length ? suggestion.url : '#'; 2409 2410 if (typeof extClassName == 'string') { 2411 className += ' ' + extClassName; 2412 } 2413 2414 // Image 2415 if (options.showImage === true && typeof suggestion.thumb_html != 'undefined') { 2416 isImg = true; 2417 } 2418 2419 var sugVarClass = suggestion.type === 'product_variation' ? ' dgwt-wcas-suggestion-product-var' : ''; 2420 // One suggestion HTML 2421 dataAttrs += typeof suggestion.post_id != 'undefined' ? 'data-post-id="' + suggestion.post_id + '" ' : ''; 2422 dataAttrs += typeof suggestion.taxonomy != 'undefined' ? 'data-taxonomy="' + suggestion.taxonomy + '" ' : ''; 2423 dataAttrs += typeof suggestion.term_id != 'undefined' ? 'data-term-id="' + suggestion.term_id + '" ' : ''; 2424 html += '<a href="' + url + '" class="' + className + ' dgwt-wcas-suggestion-product' + sugVarClass + '" data-index="' + index + '" ' + dataAttrs + '>'; 2425 2426 // Image 2427 if (isImg) { 2428 html += '<span class="dgwt-wcas-si">' + suggestion.thumb_html + '</span>'; 2429 } 2430 2431 2432 html += isImg ? '<div class="dgwt-wcas-content-wrapp">' : ''; 2433 2434 2435 // Open Title wrapper 2436 html += '<div class="dgwt-wcas-st">'; 2437 2438 // Custom content before title (3rd party) 2439 if (typeof suggestion.title_before != 'undefined' && suggestion.title_before) { 2440 html += suggestion.title_before; 2441 } 2442 2443 // Title 2444 html += '<span class="dgwt-wcas-st-title">' + formatResult(suggestion.value, value, true, options) + parent + '</span>'; 2445 2446 // Custom content after title (3rd party) 2447 if (typeof suggestion.title_after != 'undefined' && suggestion.title_after) { 2448 html += suggestion.title_after; 2449 } 2450 2451 // SKU 2452 if (options.showSKU === true && typeof suggestion.sku != 'undefined' && suggestion.sku.length > 0) { 2453 html += '<span class="dgwt-wcas-sku">(' + dgwt_wcas.labels.sku_label + ' ' + formatResult(suggestion.sku, value, true, options) + ')</span>'; 2454 } 2455 2456 // Description 2457 if (options.showDescription === true && typeof suggestion.desc != 'undefined' && suggestion.desc) { 2458 html += '<span class="dgwt-wcas-sd">' + formatResult(suggestion.desc, value, true, options) + '</span>'; 2459 } 2460 2461 // Vendor 2462 if (options.showProductVendor === true && typeof suggestion.vendor != 'undefined' && suggestion.vendor) { 2463 var vendorBody = '<span class="dgwt-wcas-product-vendor"><span class="dgwt-wcas-product-vendor-label">' + dgwt_wcas.labels.vendor_sold_by + ' </span>' + suggestion.vendor + '</span>' 2464 2465 if (typeof suggestion.vendor_url != 'undefined' && suggestion.vendor_url) { 2466 // Since version v1.12.0 suggestions tag was changed from <div> to <a> and vendor links are no longer supported. 2467 html += '<span class="dgwt-wcas-product-vendor-link" data-url="' + suggestion.vendor_url + '">' + vendorBody + '</span>'; 2468 } else { 2469 html += vendorBody; 2470 } 2471 2472 } 2473 2474 // Custom content after description (3rd party) 2475 if (typeof suggestion.content_after != 'undefined' && suggestion.content_after) { 2476 html += suggestion.content_after; 2477 } 2478 2479 // Close title wrapper 2480 html += '</div>'; 2481 2482 2483 var showPrice = options.showPrice === true && typeof suggestion.price != 'undefined', 2484 showMetaBefore = typeof suggestion.meta_before != 'undefined', 2485 showMetaAfter = typeof suggestion.meta_after != 'undefined',
2486 showMeta = showPrice || showMetaBefore || showMetaAfter; 2487 // @todo show sale and featured badges 2488 2489 // Meta 2490 html += showMeta ? '<div class="dgwt-wcas-meta">' : ''; 2491 2492 // Custom content before meta (3rd party) 2493 if (showMetaBefore) { 2494 html += suggestion.meta_before; 2495 } 2496 2497 // Price 2498 if (showPrice) { 2499 html += '<span class="dgwt-wcas-sp">' + suggestion.price + '</span>'; 2500 } 2501 2502 // Custom content after meta (3rd party) 2503 if (showMetaAfter) { 2504 html += suggestion.meta_after; 2505 } 2506 2507 // Close Meta 2508 html += showMeta ? '</div>' : ''; 2509 2510 html += isImg ? '</div>' : ''; 2511 html += '</a>'; 2512 2513 return html; 2514 }, 2515 getSearchStyle: function () { 2516 var that = this, 2517 $searchWrapp = that.getFormWrapper(), 2518 style = 'solaris'; //Default style 2519 2520 $($searchWrapp.attr('class').split(/\s+/)).each(function (index) { 2521 if (/dgwt-wcas-style-/i.test(this)) { 2522 style = this.replace(/dgwt-wcas-style-/i, ''); 2523 } 2524 }); 2525 2526 return style; 2527 }, 2528 adjustContainerWidth: function () { 2529 var that = this, 2530 $searchBar = that.getFormWrapper(), 2531 $suggestions = that.getSuggestionsContainer(), 2532 $detailsPanel = that.getDetailsContainer(), 2533 $baseElement = that.getForm(), 2534 baseWidth = $baseElement.outerWidth(); 2535 2536 if (!$searchBar.length) { 2537 return; 2538 } 2539 2540 // Mode 1 - suggestions wrapper width is the same as search bar width 2541 $suggestions.css('width', baseWidth + 'px'); 2542 2543 // Mode 2 - keep the suggestions wrapper and the details panel together under the search bar 2544 if (that.canShowDetailsPanel() && baseWidth >= that.options.dpusbBreakpoint) { 2545 var measurementError = 0; 2546
2547 // Width 50:50 2548 $suggestions.css('width', baseWidth / 2); 2549 $detailsPanel.css('width', baseWidth / 2); 2550 2551 // Fix browsers subtleties such as calculating sizes as float numbers. 2552 measurementError = baseWidth - ($suggestions.outerWidth() + $detailsPanel.outerWidth()); 2553 if (measurementError != 0) { 2554 $detailsPanel.css('width', $detailsPanel.outerWidth() + measurementError); 2555 } 2556 } 2557 }, 2558 positionPreloaderAndMic: function ($formWrapper) { 2559 var that = this; 2560 2561 var $submit = typeof $formWrapper == 'object' ? $formWrapper.find('.dgwt-wcas-search-submit') : $('.dgwt-wcas-search-submit'); 2562 2563 if ($submit.length > 0) { 2564 $submit.each(function () { 2565 var $preloader = $(this).closest('.dgwt-wcas-search-wrapp').find('.dgwt-wcas-preloader'), 2566 isSolarisStyle = $(this).closest('.dgwt-wcas-search-wrapp').hasClass('dgwt-wcas-style-solaris'), 2567 isVoiceSearchSupported = $(this).closest('.dgwt-wcas-search-wrapp').hasClass(that.options.voiceSearchSupportedClass), 2568 $voiceSearch = $(this).closest('.dgwt-wcas-search-wrapp').find('.' + that.options.voiceSearchClass); 2569 2570 if (isVoiceSearchSupported && isSolarisStyle) { 2571 if (dgwt_wcas.is_rtl == 1) { 2572 $voiceSearch.css('left', $(this).outerWidth() + 'px'); 2573 } else { 2574 $voiceSearch.css('right', $(this).outerWidth() + 'px'); 2575 } 2576 } 2577 2578 if (dgwt_wcas.is_rtl == 1) { 2579 $preloader.css('left', $(this).outerWidth() + 'px'); 2580 } else { 2581 $preloader.css('right', $(this).outerWidth() + 'px'); 2582 } 2583 2584 }); 2585 } 2586 2587 }, 2588 /* 2589 * Manages preloader 2590 * 2591 * @param action (show or hide) 2592 * @param container (parent selector) 2593 * @param cssClass 2594 */ 2595 preloader: function (action, place, cssClass) { 2596 var that = this, 2597 html, 2598 $container, 2599 defaultClass = 'dgwt-wcas-preloader-wrapp', 2600 cssClasses = cssClass == null ? defaultClass : defaultClass + ' ' + cssClass; 2601 2602 if (place === 'form') { 2603 2604 // Return early if the preloader is disable via the settings for a search bar 2605 if (dgwt_wcas.show_preloader != 1) { 2606 return; 2607 } 2608 2609 $container = that.getFormWrapper().find('.dgwt-wcas-preloader'); 2610 } else if (place === 'details') { 2611 $container = that.getDetailsContainer(); 2612 } 2613 2614 if ($container.length == 0) { 2615 return; 2616 } 2617 2618 // Handle preloader for a search bar 2619 if (place === 'form') { 2620 if (action === 'hide') { 2621 $container.removeClass(cssClass); 2622 $container.html(''); 2623 } else { 2624 $container.addClass(cssClass); 2625 if (typeof dgwt_wcas.preloader_icon == 'string') { 2626 $container.html(dgwt_wcas.preloader_icon); 2627 } 2628 } 2629 return; 2630 } 2631 2632 // Handle preloader for a details panel 2633 var $preloader = $container.find('.' + defaultClass); 2634 2635 // Action hide 2636 if (action === 'hide') { 2637 if ($preloader.length) { 2638 $preloader.remove(); 2639 } 2640 return 2641 } 2642 2643 // Action show 2644 if (action === 'show') { 2645 var rtlSuffix = that.options.isRtl ? '-rtl' : ''; 2646 html = '<div class="' + cssClasses + '"><img class="dgwt-wcas-placeholder-preloader" src="' + dgwt_wcas.img_url + 'placeholder' + rtlSuffix + '.png" /></div>'; 2647 that.detailsPanelClearScene(); 2648 if ($preloader.length) { 2649 $preloader.remove(); 2650 } 2651 $container.prepend(html); 2652 } 2653 }, 2654 verifySuggestionsFormat: function (suggestions) { 2655 2656 // If suggestions is string array, convert them to supp
2656orted format: 2657 if (suggestions.length && typeof suggestions[0] === 'string') { 2658 return $.map(suggestions, function (value) { 2659 return {value: value, data: null}; 2660 }); 2661 } 2662 2663 return suggestions; 2664 }, 2665 processResponse: function (result, originalQuery, cacheKey) { 2666 var that = this, 2667 options = that.options; 2668 2669 result.suggestions = that.verifySuggestionsFormat(result.suggestions); 2670 2671 // Cache results if cache is not disabled: 2672 if (!options.noCache) { 2673 that.cachedResponse[cacheKey] = result; 2674 if (options.preventBadQueries && !result.suggestions.length) { 2675 that.badQueries.push(originalQuery); 2676 } 2677 } 2678 2679 // Return if originalQuery is not matching current query: 2680 if (originalQuery !== that.getQuery(that.currentValue)) { 2681 return; 2682 } 2683 2684 that.suggestions = result.suggestions; 2685 that.suggest(); 2686 }, 2687 activate: function (index) { 2688 var that = this, 2689 activeItem, 2690 selected = that.classes.selected, 2691 container = that.getSuggestionsContainer(), 2692 children = container.find('.' + that.classes.suggestion); 2693 2694 container.find('.' + selected).removeClass(selected); 2695 2696 that.selectedIndex = index; 2697 2698 if (that.selectedIndex !== -1 && children.length > that.selectedIndex) { 2699 activeItem = children.get(that.selectedIndex); 2700 $(activeItem).addClass(selected); 2701 return activeItem; 2702 } 2703 2704 return null; 2705 }, 2706 selectHint: function () { 2707 var that = this, 2708 i = $.inArray(that.hint, that.suggestions); 2709 2710 that.select(i); 2711 }, 2712 select: function (i) { 2713 var that = this; 2714 2715 if (that.options.disableHits) { 2716 return; 2717 } 2718 2719 // Break early if a "select" event isn't related to suggestions 2720 if (typeof that.suggestions[i] == 'undefined') { 2721 return; 2722 } 2723 2724 // Don't select if there is headline element 2725 if (typeof that.suggestions[i] != 'undefined' 2726 && (that.suggestions[i].type == 'headline' || that.suggestions[i].type == 'headline-v2')) { 2727 return; 2728 } 2729 2730 that.closeOverlayMobile(); 2731 that.hide(); 2732 that.onSelect(i); 2733 }, 2734 moveUp: function () { 2735 var that = this; 2736 2737 if (that.selectedIndex === -1) { 2738 return; 2739 } 2740 2741 that.latestActivateSource = 'key'; 2742 2743 if (that.selectedIndex === 0) { 2744 that.getSuggestionsContainer().children('.' + that.classes.suggestion).first().removeClass(that.classes.selected); 2745 that.selectedIndex = -1; 2746 that.ignoreValueChange = false; 2747 that.el.val(that.currentValue); 2748 return; 2749 } 2750 2751 that.adjustScroll(that.selectedIndex - 1, 'up'); 2752 }, 2753 moveDown: function () { 2754 var that = this; 2755 2756 if (that.selectedIndex === (that.suggestions.length - 1)) { 2757 return; 2758 } 2759 2760 that.latestActivateSource = 'key'; 2761 2762 that.adjustScroll(that.selectedIndex + 1, 'down'); 2763 }, 2764 adjustScroll: function (index, direction) { 2765 var that = this; 2766 2767 2768 if (that.suggestions[index].type === 'headline') { 2769 index = direction === 'down' ? index + 1 : index - 1; 2770 } 2771 2772 if (typeof that.suggestions[index] == 'undefined') { 2773 return; 2774 } 2775 2776 var activeItem = that.activate(index); 2777 2778 that.getDetails(that.suggestions[index]); 2779 2780 if (that.suggestions[index].type === 'more_products') { 2781 2782 return; 2783 } 2784
2785 if (!activeItem || that.canShowDetailsPanel()) { 2786 return; 2787 } 2788 2789 var offsetTop, 2790 upperBound, 2791 lowerBound, 2792 $suggestionContainer = that.getSuggestionsContainer(), 2793 heightDelta = $(activeItem).outerHeight(false); 2794 2795 offsetTop = activeItem.offsetTop; 2796 upperBound = $suggestionContainer.scrollTop(); 2797 lowerBound = upperBound + that.options.maxHeight - heightDelta; 2798 2799 if (offsetTop < upperBound) { 2800 $suggestionContainer.scrollTop(offsetTop); 2801 } else if (offsetTop > lowerBound) { 2802 $suggestionContainer.scrollTop(offsetTop - that.options.maxHeight + heightDelta); 2803 } 2804 2805 if (!that.options.preserveInput) { 2806 // During onBlur event, browser will trigger "change" event, 2807 // because value has changed, to avoid side effect ignore, 2808 // that event, so that correct suggestion can be selected 2809 // when clicking on suggestion with a mouse 2810 that.ignoreValueChange = true; 2811 //that.el.val(that.getValue(that.suggestions[index].value)); 2812 } 2813 }, 2814 onSelect: function (index) { 2815 var that = this, 2816 onSelectCallback = that.options.onSelect, 2817 suggestion = that.suggestions[index], 2818 forceSubmit = false; 2819 2820 if (typeof suggestion.type != 'undefined') { 2821 if ( 2822 suggestion.type === 'more_products' 2823 || (that.actionTriggerSource === 'enter' && that.latestActivateSource != 'key' && suggestion.type != 'product_variation') 2824 ) { 2825 that.el.closest('form').trigger('submit'); 2826 forceSubmit = true; 2827 } 2828 2829 if (suggestion.type === 'history-search') { 2830 that.currentValue = that.getValue(suggestion.value); 2831 if (that.currentValue !== that.el.val() && !that.options.preserveInput) { 2832 that.el.val(that.currentValue.replace(/(<([^>]+)>)/gi, ' ').replace(/\s\s+/g, ' ')); 2833 } 2834 that.el.closest('form').trigger('submit'); 2835 forceSubmit = true; 2836 } 2837 2838 } 2839 2840 if (suggestion.type === 'product' || suggestion.type === 'product_variation') { 2841 if (that.options.showRecentlySearchedProducts) { 2842 that.saveHistoryProducts(suggestion); 2843 } 2844 } 2845 2846 if (!forceSubmit) { 2847 2848 that.currentValue = that.getValue(suggestion.value); 2849 2850 if (that.currentValue !== that.el.val() && !that.options.preserveInput) { 2851 that.el.val(that.currentValue.replace(/(<([^>]+)>)/gi, ' ').replace(/\s\s+/g, ' ')); 2852 } 2853 2854 if (suggestion.url.length > 0) { 2855 window.location.href = suggestion.url; 2856 } 2857 2858 that.suggestions = []; 2859 that.selection = suggestion; 2860 } 2861 2862 if ($.isFunction(onSelectCallback)) { 2863 onSelectCallback.call(that.element, suggestion); 2864 } 2865 }, 2866 openInNewTab: function (index) { 2867 var that = this, 2868 suggestion = that.suggestions[index]; 2869 if (suggestion.url.length > 0) { 2870 window.open(suggestion.url, '_blank').focus(); 2871 } 2872 }, 2873 getValue: function (value) { 2874 var that = this, 2875 delimiter = that.options.delimiter, 2876 currentValue, 2877 parts; 2878 2879 if (!delimiter) { 2880 return value; 2881 } 2882 2883 currentValue = that.currentValue; 2884 parts = currentValue.split(delimiter); 2885 2886 if (parts.length === 1) { 2887 return value; 2888 } 2889 2890 return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value; 2891 }, 2892 dispose: function () { 2893 var that = this, 2894 $el = that.el, 2895 $formWrapper = that.getFormWrapper(), 2896 $suggestionsWrapper = that.getSuggestionsContainer(), 2897 $mobileHandler = $formWrapper.find('.js-dgwt-wcas-enable-mobile-form'); 2898 2899 // Remove all events 2900 if ($formWrapper.length) { 2901 var $items = $formWrapper.find('*'); 2902 $items.each(function () { 2903 $(this).off('.autocomplete'); 2904 }); 2905 } 2906 2907 $el.off('fibosearch/ping'); 2908 2909 $formWrapper.off('click.autocomplete', '.js-dgwt-wcas-search-icon-handler'); 2910 2911 $el.removeData('autocomplete'); 2912 $(window).off('resize.autocomplete', that.fixPosition); 2913 2914 $formWrapper.removeClass('dgwt-wcas-active'); 2915 2916 that.close(false); 2917 2918 // Remove mobile handler 2919 if ($mobileHandler.length) { 2920 $mobileHandler.remove(); 2921 } 2922 2923 if ($suggestionsWrapper.length) { 2924 $suggestionsWrapper.html(''); 2925 } 2926 }, 2927 isMountedOverlayDarkened: function () { 2928 var that = this, 2929 $wrapp = that.getFormWrapper(), 2930 mounted = false;
2931 2932 if ($wrapp.hasClass(that.classes.darkenOverlayMounted)) { 2933 mounted = true; 2934 } 2935 return mounted; 2936 }, 2937 enableOverlayDarkened: function () { 2938 var that = this, 2939 options = that.options, 2940 $formWrapper; 2941 2942 if (!that.isMountedOverlayDarkened()) { 2943 return; 2944 } 2945 2946 $formWrapper = that.getFormWrapper(); 2947 2948 $formWrapper.addClass('dgwt-wcas-search-darkoverl-on'); 2949 $('body').addClass('dgwt-wcas-darkoverl-on'); 2950 2951 // Create node 2952 if ($('.' + options.darkenedOverlayClass).length == 0) { 2953 var html = '<div class="' + options.darkenedOverlayClass + '"><div></div><div></div><div></div><div></div></div>'; 2954 $('body').append(html); 2955 var $darkenedOverlay = $('.' + that.options.darkenedOverlayClass); 2956 2957 that.positionOverlayDarkened(); 2958 2959 $darkenedOverlay.on('click.autocomplete', function (e) { 2960 that.disableOverlayDarkened(); 2961 }); 2962 2963 } 2964 2965 that.overlayDarkenedState = 'on'; 2966 2967 }, 2968 disableOverlayDarkened: function () { 2969 var that = this, 2970 options = that.options, 2971 $wrapps; 2972 2973 if (!that.isMountedOverlayDarkened()) { 2974 return; 2975 } 2976 2977 $wrapps = $('.dgwt-wcas-search-darkoverl-on'); 2978 2979 if ($wrapps.length) { 2980 $wrapps.removeClass('dgwt-wcas-search-darkoverl-on'); 2981 } 2982 $('body').removeClass('dgwt-wcas-darkoverl-on'); 2983 2984 2985 var $el = $('.' + options.darkenedOverlayClass); 2986 if ($el.length > 0) { 2987 $el.remove(); 2988 that.overlayDarkenedState = 'off'; 2989 } 2990 }, 2991 positionOverlayDarkened: function () { 2992 var that = this, 2993 fixed = false, 2994 $darkenedOverlay = $('.' + that.options.darkenedOverlayClass); 2995 2996 if ($darkenedOverlay.length > 0) { 2997 2998 if (that.ancestorHasPositionFixed(that.getFormWrapper())) { 2999 fixed = true; 3000 $darkenedOverlay.addClass('dgwt-wcas-suggestions-wrapp-fixed'); 3001 } else { 3002 $darkenedOverlay.removeClass('dgwt-wcas-suggestions-wrapp-fixed'); 3003 } 3004 3005 $darkenedOverlay.children('div').each(function (i) { 3006 that.positionOverlayDarkenedDiv($(this), i + 1, fixed); 3007 }); 3008 } 3009 }, 3010 positionOverlayDarkenedDiv: function ($el, orient, fixed) { 3011 var that = this, 3012 elData, 3013 $baseEl = that.getFormWrapper(), 3014 css, 3015 secureOffset = 200; // Secure buffer 3016 3017 3018 // Different position for search icon layout 3019 if ($baseEl.hasClass('js-dgwt-wcas-layout-icon')) { 3020 $baseEl = that.getForm(); 3021 } 3022 3023 elData = that.getElementInfo($baseEl); 3024 3025 /** 3026 * Note 1: If fixed == true, it means position should be calculated related to screen, 3027 * otherwise it will be calculated related to document 3028 * 3029 * Note 2: It concerns cases 1,3 and 4. 1px is subtracted to achieve an exact match of document height. 3030 * I don't know why it's needed. 3031 */ 3032 3033 switch (orient) { 3034 case 1: 3035 css = { 3036 left: (-secureOffset) + 'px', 3037 top: (-secureOffset) + 'px', 3038 width: (elData.left + secureOffset) + 'px', 3039 height: ($(document).outerHeight(false) + secureOffset - 1) + 'px' 3040 }; 3041 break; 3042 case 2: 3043 var topSpan = fixed ? elData.topViewPort : elData.top; 3044 css = { 3045 left: (-secureOffset) + 'px', 3046 top: (-secureOffset) + 'px', 3047 width: ($(window).outerWidth(false) + secureOffset) + 'px', 3048 height: (topSpan + secureOffset) + 'px', 3049 }; 3050 break; 3051 case 3: 3052 css = { 3053 left: (elData.left + elData.width) + 'px', 3054 top: (-secureOffset) + 'px', 3055 width: ($(window).outerWidth(false) - elData.right) + 'px', 3056 height: ($(document).outerHeight(false) + secureOffset - 1) + 'px' 3057 }; 3058 break; 3059 case 4: 3060 var topSpan = fixed ? elData.topViewPort : elData.top; 3061 css = { 3062 left: (-secureOffset) + 'px', 3063 top: (topSpan + elData.height) + 'px', 3064 width: ($(window).outerWidth(false) + secureOffset) + 'px', 3065 height: ($(document).outerHeight(false) - elData.bottom - 1) + 'px' 3066 }; 3067 break; 3068 } 3069 3070 if (css) { 3071 $el.css(css); 3072 } 3073 }, 3074 showCloseButton: function () { 3075 var that = this, 3076 iconBody = typeof dgwt_wcas.close_icon != 'undefined' ? dgwt_wcas.close_icon : '', 3077 $actionsEl = that.getFormWrapper().find('.' + that.options.preloaderClass); 3078 3079 if (that.el.val().length < that.options.minChars) { 3080 return; 3081 } 3082 3083 // Click close icon 3084 if (!$actionsEl.hasClass(that.options.closeTrigger)) { 3085 $actionsEl.on('click.autocomplete', function () { 3086 that.close(true); 3087 }); 3088 } 3089 3090 $actionsEl.addClass(that.options.closeTrigger); 3091 $actionsEl.html(iconBody); 3092 3093 }, 3094 hideCloseButton: function () { 3095 var that = this, 3096 $btn = that.getFormWrapper().find('.' + that.options.closeTrigger); 3097 3098 if ($btn.length) { 3099 $btn.removeClass(that.options.closeTrigger); 3100 $btn.html(''); 3101 } 3102 3103 $btn.off('click.autocomplete'); 3104 }, 3105 canShowPreSuggestions: function () { 3106 var that = this, 3107 canShow = false;
3108 3109 if (that.options.showRecentlySearchedProducts || that.options.showRecentlySearchedPhrases) { 3110 canShow = true; 3111 } 3112 3113 return canShow; 3114 }, 3115 showPreSuggestions: function () { 3116 var that = this, 3117 suggestionsIndex = 0, 3118 i, 3119 html = '', 3120 $suggestionsWrapper = that.getSuggestionsContainer(), 3121 $searchBar = that.getFormWrapper(), 3122 noHistory = true, 3123 historyProducts = [], 3124 historySearches = [], 3125 origShowImageOpt = that.options.showImage; 3126 3127 that.isPreSuggestionsMode = true; 3128 3129 that.suggestions = []; 3130 that.suggestionsContainer.addClass('dgwt-wcas-has-img'); 3131 if (!origShowImageOpt) { 3132 that.suggestionsContainer.addClass('dgwt-wcas-has-img-forced'); 3133 } 3134 3135 that.options.showImage = true; 3136 3137 if (that.options.showRecentlySearchedProducts) { 3138 historyProducts = utils.getLocalStorageItem(that.recentlyViewedProductsKey, []); 3139 } 3140 3141 if (that.options.showRecentlySearchedPhrases) { 3142 historySearches = utils.getLocalStorageItem(that.recentlySearchedPhrasesKey, []); 3143 } 3144 3145 // Break early if there is nothing to show 3146 if (historyProducts.length === 0 && historySearches.length === 0) { 3147 return; 3148 } 3149 3150 // Show headline 3151 that.suggestions.push({type: 'headline-v2', value: '',}); 3152 html += '<span class="dgwt-wcas-suggestion dgwt-wcas-suggestion-headline-v2" data-index="' + suggestionsIndex + '">'; 3153 if (typeof dgwt_wcas.labels['search_hist'] != 'undefined') { 3154 var label = dgwt_wcas.labels['search_hist']; 3155 label += ' <span class="js-dgwt-wcas-sugg-hist-clear dgwt-wcas-sugg-hist-clear">' + dgwt_wcas.labels['search_hist_clear'] + '</span>'; 3156 html += '<span className="dgwt-wcas-st">' + label + '</span>'; 3157 } 3158 html += '</span>'; 3159 suggestionsIndex++; 3160 3161 // History: products 3162 if (historyProducts.length > 0) { 3163 for (i = 0; i < historyProducts.length; i++) { 3164 html += that.createProductSuggestion(historyProducts[i], suggestionsIndex, 'dgwt-wcas-suggestion-history-product'); 3165 that.suggestions.push(historyProducts[i]); 3166 suggestionsIndex++; 3167 } 3168 } 3169 3170 3171 // History: searches 3172 if (historySearches.length > 0) { 3173 for (i = 0; i < historySearches.length; i++) { 3174 var suggestion = { 3175 type: 'history-search', 3176 value: historySearches[i], 3177 url: '#', 3178 thumb_html: dgwt_wcas.magnifier_icon 3179 }; 3180 3181 if ($searchBar.hasClass('dgwt-wcas-style-pirx')) { 3182 suggestion.thumb_html = dgwt_wcas.magnifier_icon_pirx; 3183 } 3184 3185 that.suggestions.push(suggestion); 3186 3187 html += '<a href="' + suggestion.url + '" class="' + that.classes.suggestion + ' dgwt-wcas-suggestion-history-search" data-index="' + suggestionsIndex + '">'; 3188 html += '<span class="dgwt-wcas-si">' + suggestion.thumb_html + '</span>'; 3189 html += '<div class="dgwt-wcas-content-wrapp">'; 3190 html += '<div class="dgwt-wcas-st"><span class="dgwt-wcas-st-title">' + suggestion.value + '</span></div>' 3191 html += '</div>'; 3192 html += '</a>'; 3193 3194 suggestionsIndex++; 3195 } 3196 } 3197 3198 // Show pre-suggestions 3199 $suggestionsWrapper.html(html); 3200 $suggestionsWrapper.show(); 3201 3202 // Add class on show 3203 $('body').addClass('dgwt-wcas-open'); 3204 $('body').addClass('dgwt-wcas-open-pre-suggestions'); 3205 $('html').addClass('dgwt-wcas-open-' + that.getSearchStyle()); 3206 3207 // Reset the latest mousedown position 3208 that.isMouseDownOnSearchElements = false;
3209 3210 that.visible = true; 3211 that.fixPosition(); 3212 that.options.showImage = origShowImageOpt; 3213 3214 3215 document.dispatchEvent(new CustomEvent('fibosearch/open', { 3216 detail: that 3217 })); 3218 3219 document.dispatchEvent(new CustomEvent('fibosearch/show-pre-suggestions', { 3220 detail: that 3221 })); 3222 }, 3223 resetPreSuggestions: function () { 3224 var that = this, 3225 $suggestionsWrapp = that.getSuggestionsContainer(), 3226 activeInstance = utils.getActiveInstance(); 3227 3228 utils.removeLocalStorageItem(that.recentlyViewedProductsKey); 3229 utils.removeLocalStorageItem(that.recentlySearchedPhrasesKey); 3230 3231 that.suggestions = []; 3232 $suggestionsWrapp.html(''); 3233 $('body').removeClass('dgwt-wcas-open-pre-suggestions'); 3234 3235 activeInstance.el.focus(); 3236 }, 3237 hidePreSuggestions: function () { 3238 var that = this; 3239 3240 if (!that.options.showImage) { 3241 that.suggestionsContainer.removeClass('dgwt-wcas-has-img'); 3242 } 3243 that.suggestionsContainer.removeClass('dgwt-wcas-has-img-forced'); 3244 3245 that.isPreSuggestionsMode = false; 3246 }, 3247 saveHistoryProducts: function (suggestion) { 3248 var that = this, 3249 viewedProducts = utils.getLocalStorageItem(that.recentlyViewedProductsKey, []); 3250 3251 viewedProducts = [suggestion, ...viewedProducts]; 3252 viewedProducts = [...new Map(viewedProducts.map((item) => { 3253 if (typeof item['price'] != 'undefined') { 3254 delete item['price']; 3255 } 3256 3257 if (!that.options.showImage) { 3258 item['thumb_html'] = dgwt_wcas.history_icon; 3259 } 3260 return [item['post_id'], item]; 3261 })).values()]; 3262 utils.setLocalStorageItem(that.recentlyViewedProductsKey, viewedProducts.slice(0, 5)); 3263 }, 3264 saveHistorySearches: function (value) { 3265 var that = this, 3266 phrases = utils.getLocalStorageItem(that.recentlySearchedPhrasesKey, []); 3267 3268 phrases = [value, ...phrases]; 3269 phrases = [...new Set(phrases)]; 3270 utils.setLocalStorageItem(that.recentlySearchedPhrasesKey, phrases.slice(0, 5)); 3271 }, 3272 addActiveClassIfMissing: function () { 3273 var activeEl = document.activeElement; 3274 if ( 3275 typeof activeEl == 'object' 3276 && $(activeEl).length 3277 && $(activeEl).hasClass('dgwt-wcas-search-input') 3278 ) { 3279 3280 var $search = $(activeEl).closest('.dgwt-wcas-search-wrapp'); 3281 3282 if ($search.length && !$search.hasClass('dgwt-wcas-active')) { 3283 $search.addClass('dgwt-wcas-active'); 3284 } 3285 } 3286 }, 3287 ancestorHasPositionFixed: function ($element) { 3288 3289 var $checkElements = $element.add($element.parents()); 3290 var isFixed = false; 3291 3292 $checkElements.each(function () { 3293 3294 if ($(this).css("position") === "fixed") { 3295 isFixed = true; 3296 return false; 3297 } 3298 }); 3299 return isFixed; 3300 }, 3301 gaEvent: function (label, category) { 3302 var that = this; 3303 var gaObj = window.hasOwnProperty('GoogleAnalyticsObject') && window.hasOwnProperty(window['GoogleAnalyticsObject']) ? window[window['GoogleAnalyticsObject']] : false; 3304 if (that.options.sendGAEvents) { 3305 try { 3306 if (typeof gtag !== 'undefined') { 3307 gtag('event', 'autocomplete_search', { 3308 'event_label': label, 3309 'event_category': category 3310 }); 3311 } else if (gaObj !== false) { 3312 var tracker = gaObj.getAll()[0]; 3313 if (tracker) tracker.send({ 3314 hitType: 'event', 3315 eventCategory: category, 3316 eventAction: 'autocomplete_search', 3317 eventLabel: label 3318 }); 3319 } 3320 } catch (error) { 3321 } 3322 } 3323 if (that.options.enableGASiteSearchModule) { 3324 try { 3325 if (typeof gtag !== 'undefined') { 3326 gtag('event', 'page_view', { 3327 'page_path': '/?s=' + encodeURI(label) + '&post_type=product&dgwt_wcas=1', 3328 }); 3329 } else if (gaObj !== false) { 3330 var tracker2 = gaObj.getAll()[0]; 3331 if (tracker2) { 3332 tracker2.set('page', '/?s=' + encodeURI(label) + '&post_type=product&dgwt_wcas=1'); 3333 tracker2.send('pageview'); 3334 } 3335 } 3336 } catch (error) { 3337 } 3338 } 3339 3340 $(document).trigger('dgwtWcasGAEvent', {'term': label, 'category': category}); 3341 }, 3342 initVoiceSearch: function () { 3343 var that = this; 3344 if (!that.options.voiceSearchEnabled) { 3345 return false;
3346 } 3347 var $formWrapper = that.getFormWrapper(); 3348 var $input = $formWrapper.find('.' + that.options.searchInputClass); 3349 var $voiceSearch = $formWrapper.find('.' + that.options.voiceSearchClass); 3350 3351 var speechRecognition = false; 3352 if (typeof SpeechRecognition === "function") { 3353 speechRecognition = SpeechRecognition; 3354 } else if (typeof webkitSpeechRecognition === "function") { 3355 speechRecognition = webkitSpeechRecognition; 3356 } 3357 if (!speechRecognition) { 3358 return false; 3359 } 3360 3361 if (utils.isBrowser('Chrome') && utils.isIOS()) { 3362 // Chrome speech recognition on iPhone and iPad is not working well. 3363 return false; 3364 } 3365 3366 that.voiceSearchSetState('inactive', $voiceSearch); 3367 $formWrapper.addClass(that.options.voiceSearchSupportedClass); 3368 3369 that.voiceSearchRecognition = new speechRecognition(); 3370 that.voiceSearchRecognition.lang = that.options.voiceSearchLang; 3371 that.voiceSearchRecognition.continuous = false; 3372 that.voiceSearchRecognition.interimResults = true; 3373 that.voiceSearchRecognition.maxAlternatives = 1; 3374 3375 $voiceSearch.on('click', function () { 3376 if ( 3377 $formWrapper.hasClass('dgwt-wcas-mobile-overlay-trigger-active') && 3378 !$('html').hasClass('dgwt-wcas-overlay-mobile-on') 3379 ) { 3380 $formWrapper.find('.js-dgwt-wcas-enable-mobile-form').click(); 3381 $formWrapper.find('.' + that.options.searchInputClass).blur(); 3382 } 3383 if (that.voiceSearchStarted) { 3384 that.voiceSearchAbort(); 3385 return; 3386 } 3387 if (that.voiceSearchIsInitialized()) { 3388 that.voiceSearchAbort(); 3389 } 3390 that.voiceSearchRecognition.start(); 3391 }); 3392 3393 that.voiceSearchRecognition.onstart = function (event) { 3394 that.voiceSearchSetState('active', $voiceSearch); 3395 } 3396 3397 that.voiceSearchRecognition.onresult = function (event) { 3398 const result = event.results[0]; 3399 const text = result[0].transcript; 3400 $input.val(text); 3401 if (result.isFinal) { 3402 $input.trigger('change'); 3403 if (!('ontouchend' in document)) { 3404 $input.focus(); 3405 } 3406 that.voiceSearchSetState('inactive', $voiceSearch); 3407 } 3408 } 3409 3410 that.voiceSearchRecognition.onspeechend = function () { 3411 that.voiceSearchSetState('inactive', $voiceSearch); 3412 that.voiceSearchRecognition.stop(); 3413 } 3414 3415 that.voiceSearchRecognition.onnomatch = function (event) { 3416 that.voiceSearchSetState('inactive', $voiceSearch); 3417 } 3418 3419 that.voiceSearchRecognition.onerror = function (event) { 3420 switch (event.error) { 3421 case 'aborted': 3422 case 'no-speech': 3423 that.voiceSearchSetState('inactive', $voiceSearch); 3424 break; 3425 case 'network': 3426 break; 3427 case 'not-allowed': 3428 case 'service-not-allowed': 3429 that.voiceSearchSetState('off', $voiceSearch); 3430 break; 3431 } 3432 } 3433 }, 3434 voiceSearchAbort: function () { 3435 var that = this; 3436 if (that.voiceSearchIsInitialized()) { 3437 that.voiceSearchRecognition.abort(); 3438 that.voiceSearchStarted = false; 3439 } 3440 }, 3441 voiceSearchIsInitialized: function () { 3442 var that = this; 3443 return that.voiceSearchRecognition !== null; 3444 }, 3445 voiceSearchSetState: function (state, $voiceSearch) { 3446 var that = this; 3447 switch (state) { 3448 case 'active': 3449 that.voiceSearchStarted = true; 3450 if (typeof dgwt_wcas.voice_search_active_icon == 'string') { 3451 $voiceSearch.html(dgwt_wcas.voice_search_active_icon); 3452 } 3453 // $voiceSearch.removeClass(that.options.voiceSearchDisabledClass).addClass(that.options.voiceSearchActiveClass); 3454 break; 3455 case 'inactive': 3456 that.voiceSearchStarted = false;
vendor: 10,714 bytes, lines 3457-3697
3457 if (typeof dgwt_wcas.voice_search_inactive_icon == 'string') { 3458 $voiceSearch.html(dgwt_wcas.voice_search_inactive_icon); 3459 } 3460 // $voiceSearch.removeClass(that.options.voiceSearchActiveClass + ' ' + that.options.voiceSearchDisabledClass); 3461 break; 3462 case 'off': 3463 that.voiceSearchStarted = false; 3464 // $voiceSearch.removeClass(that.options.voiceSearchActiveClass).addClass(that.options.voiceSearchDisabledClass); 3465 if (typeof dgwt_wcas.voice_search_disabled_icon == 'string') { 3466 $voiceSearch.html(dgwt_wcas.voice_search_disabled_icon); 3467 } 3468 break; 3469 } 3470 }, 3471 }; 3472 3473 // Create chainable jQuery plugin: 3474 $.fn.dgwtWcasAutocomplete = function (options, args) { 3475 var dataKey = 'autocomplete'; 3476 // If function invoked without argument return 3477 // instance of the first matched element: 3478 if (!arguments.length) { 3479 return this.first().data(dataKey); 3480 } 3481 3482 return this.each(function () { 3483 var inputElement = $(this), 3484 instance = inputElement.data(dataKey); 3485 3486 if (typeof options === 'string') { 3487 if (instance && typeof instance[options] === 'function') { 3488 instance[options](args); 3489 } 3490 } else { 3491 // If instance already exists, destroy it: 3492 if (instance && instance.dispose) { 3493 instance.dispose(); 3494 } 3495 3496 instance = new DgwtWcasAutocompleteSearch(this, options); 3497 inputElement.data(dataKey, instance); 3498 } 3499 }); 3500 }; 3501 3502 // Don't overwrite if it already exists 3503 if (!$.fn.autocomplete) { 3504 $.fn.autocomplete = $.fn.dgwtWcasAutocomplete; 3505 } 3506 3507 (function () { 3508 /*----------------------------------------------------------------- 3509 /* IE11 polyfills 3510 /*-----------------------------------------------------------------*/ 3511 if (utils.isIE11()) { 3512 // https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.includes%2CString.prototype.includes 3513 (function (self, undefined) { 3514 function Call(t, l) { 3515 var n = arguments.length > 2 ? arguments[2] : []; 3516 if (!1 === IsCallable(t)) throw new TypeError(Object.prototype.toString.call(t) + "is not a function."); 3517 return t.apply(l, n) 3518 } 3519 3520 function CreateMethodProperty(e, r, t) { 3521 var a = {value: t, writable: !0, enumerable: !1, configurable: !0}; 3522 Object.defineProperty(e, r, a) 3523 } 3524 3525 function Get(n, t) { 3526 return n[t] 3527 } 3528 3529 function IsCallable(n) { 3530 return "function" == typeof n 3531 } 3532 3533 function RequireObjectCoercible(e) { 3534 if (null === e || e === undefined) throw TypeError(Object.prototype.toString.call(e) + " is not coercible to Object."); 3535 return e 3536 } 3537 3538 function SameValueNonNumber(e, n) { 3539 return e === n 3540 } 3541 3542 function ToBoolean(o) { 3543 return Boolean(o) 3544 } 3545 3546 function ToObject(e) { 3547 if (null === e || e === undefined) throw TypeError(); 3548 return Object(e) 3549 } 3550 3551 function GetV(t, e) { 3552 return ToObject(t)[e] 3553 } 3554 3555 function GetMethod(e, n) { 3556 var r = GetV(e, n); 3557 if (null === r || r === undefined) return undefined; 3558 if (!1 === IsCallable(r)) throw new TypeError("Method not callable: " + n); 3559 return r 3560 } 3561 3562 function Type(e) { 3563 switch (typeof e) { 3564 case"undefined": 3565 return "undefined"; 3566 case"boolean": 3567 return "boolean"; 3568 case"number": 3569 return "number"; 3570 case"string": 3571 return "string"; 3572 case"symbol": 3573 return "symbol"; 3574 default: 3575 return null === e ? "null" : "Symbol" in self && (e instanceof self.Symbol || e.constructor === self.Symbol) ? "symbol" : "object" 3576 } 3577 } 3578 3579 function IsRegExp(e) { 3580 if ("object" !== Type(e)) return !1; 3581 var n = "Symbol" in self && "match" in self.Symbol ? Get(e, self.Symbol.match) : undefined; 3582 if (n !== undefined) return ToBoolean(n); 3583 try { 3584 var t = e.lastIndex; 3585 return e.lastIndex = 0, RegExp.prototype.exec.call(e), !0 3586 } catch (l) { 3587 } finally { 3588 e.lastIndex = t 3589 } 3590 return !1 3591 } 3592 3593 function OrdinaryToPrimitive(r, t) { 3594 if ("string" === t) var e = ["toString", "valueOf"]; else e = ["valueOf", "toString"]; 3595 for (var i = 0; i < e.length; ++i) { 3596 var n = e[i], a = Get(r, n); 3597 if (IsCallable(a)) { 3598 var o = Call(a, r); 3599 if ("object" !== Type(o)) return o 3600 } 3601 } 3602 throw new TypeError("Cannot convert to primitive.") 3603 } 3604 3605 function SameValueZero(n, e) { 3606 return Type(n) === Type(e) && ("number" === Type(n) ? !(!isNaN(n) || !isNaN(e)) || (1 / n === Infinity && 1 / e == -Infinity || (1 / n == -Infinity && 1 / e === Infinity || n === e)) : SameValueNonNumber(n, e)) 3607 } 3608 3609 function ToInteger(n) { 3610 if ("symbol" === Type(n)) throw new TypeError("Cannot convert a Symbol value to a number"); 3611 var t = Number(n); 3612 return isNaN(t) ? 0 : 1 / t === Infinity || 1 / t == -Infinity || t === Infinity || t === -Infinity ? t : (t < 0 ? -1 : 1) * Math.floor(Math.abs(t)) 3613 } 3614 3615 function ToLength(n) { 3616 var t = ToInteger(n); 3617 return t <= 0 ? 0 : Math.min(t, Math.pow(2, 53) - 1) 3618 } 3619 3620 function ToPrimitive(e) { 3621 var t = arguments.length > 1 ? arguments[1] : undefined; 3622 if ("object" === Type(e)) { 3623 if (arguments.length < 2) var i = "default"; else t === String ? i = "string" : t === Number && (i = "number"); 3624 var r = "function" == typeof self.Symbol && "symbol" == typeof self.Symbol.toPrimitive ? GetMethod(e, self.Symbol.toPrimitive) : undefined; 3625 if (r !== undefined) { 3626 var n = Call(r, e, [i]); 3627 if ("object" !== Type(n)) return n; 3628 throw new TypeError("Cannot convert exotic object to primitive.") 3629 } 3630 return "default" === i && (i = "number"), OrdinaryToPrimitive(e, i) 3631 } 3632 return e 3633 } 3634 3635 function ToString(t) { 3636 switch (Type(t)) { 3637 case"symbol": 3638 throw new TypeError("Cannot convert a Symbol value to a string"); 3639 case"object": 3640 return ToString(ToPrimitive(t, String)); 3641 default: 3642 return String(t) 3643 } 3644 } 3645 3646 CreateMethodProperty(Array.prototype, "includes", function e(r) { 3647 "use strict"; 3648 var t = ToObject(this), o = ToLength(Get(t, "length")); 3649 if (0 === o) return !1; 3650 var n = ToInteger(arguments[1]); 3651 if (n >= 0) var a = n; else (a = o + n) < 0 && (a = 0); 3652 for (; a < o;) { 3653 var i = Get(t, ToString(a)); 3654 if (SameValueZero(r, i)) return !0; 3655 a += 1 3656 } 3657 return !1 3658 }); 3659 CreateMethodProperty(String.prototype, "includes", function e(t) { 3660 "use strict"; 3661 var r = arguments.length > 1 ? arguments[1] : undefined, n = RequireObjectCoercible(this), 3662 i = ToString(n); 3663 if (IsRegExp(t)) throw new TypeError("First argument to String.prototype.includes must not be a regular expression"); 3664 var o = ToString(t), g = ToInteger(r), a = i.length, p = Math.min(Math.max(g, 0), a); 3665 return -1 !== String.prototype.indexOf.call(i, o, p) 3666 }); 3667 })('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {}); 3668 } 3669 3670 // RUN 3671 $(document).ready(function () { 3672 "use strict"; 3673 3674 /*----------------------------------------------------------------- 3675 /* Mobile detection 3676 /*-----------------------------------------------------------------*/ 3677 if (utils.isIOS()) { 3678 $('html').addClass('dgwt-wcas-is-ios'); 3679 } 3680 3681 /*----------------------------------------------------------------- 3682 /* Set some global variables 3683 /*-----------------------------------------------------------------*/ 3684 window.dgwt_wcas.resizeOnlyOnce = null; 3685 window.dgwt_wcas.scrollOnlyOnce = null; 3686 3687 /*----------------------------------------------------------------- 3688 /* Fire autocomplete 3689 /*-----------------------------------------------------------------*/ 3690 3691 window.dgwt_wcas.config = { 3692 minChars: dgwt_wcas.min_chars, 3693 width: dgwt_wcas.sug_width, 3694 autoSelectFirst: false, 3695 triggerSelectOnValidInput: false, 3696 serviceUrl: dgwt_wcas.ajax_search_endpoint, 3697 paramName: 's',
3698 showDetailsPanel: dgwt_wcas.show_details_panel == 1 ? true : false, 3699 showImage: dgwt_wcas.show_images == 1 ? true : false, 3700 showPrice: dgwt_wcas.show_price == 1 ? true : false, 3701 showDescription: dgwt_wcas.show_desc == 1 ? true : false, 3702 showSKU: dgwt_wcas.show_sku == 1 ? true : false, 3703 showSaleBadge: dgwt_wcas.show_sale_badge == 1 ? true : false, 3704 showFeaturedBadge: dgwt_wcas.show_featured_badge == 1 ? true : false, 3705 dynamicPrices: typeof dgwt_wcas.dynamic_prices != 'undefined' && dgwt_wcas.dynamic_prices ? true : false, 3706 saleBadgeText: dgwt_wcas.labels.sale_badge, 3707 featuredBadgeText: dgwt_wcas.labels.featured_badge, 3708 isRtl: dgwt_wcas.is_rtl == 1 ? true : false, 3709 showHeadings: dgwt_wcas.show_headings == 1 ? true : false, 3710 isPremium: dgwt_wcas.is_premium == 1 ? true : false, 3711 taxonomyBrands: dgwt_wcas.taxonomy_brands, 3712 layoutBreakpoint: dgwt_wcas.layout_breakpoint, 3713 mobileOverlayBreakpoint: dgwt_wcas.mobile_overlay_breakpoint, 3714 mobileOverlayWrapper: dgwt_wcas.mobile_overlay_wrapper, 3715 mobileOverlayDelay: dgwt_wcas.mobile_overlay_delay, 3716 debounceWaitMs: dgwt_wcas.debounce_wait_ms, 3717 sendGAEvents: dgwt_wcas.send_ga_events, 3718 convertHtml: dgwt_wcas.convert_html, 3719 enableGASiteSearchModule: dgwt_wcas.enable_ga_site_search_module, 3720 appendTo: typeof dgwt_wcas.suggestions_wrapper != 'undefined' ? dgwt_wcas.suggestions_wrapper : 'body', 3721 showProductVendor: typeof dgwt_wcas.show_product_vendor != 'undefined' && dgwt_wcas.show_product_vendor ? true : false, 3722 disableHits: typeof dgwt_wcas.disable_hits != 'undefined' && dgwt_wcas.disable_hits ? true : false, 3723 disableSubmit: typeof dgwt_wcas.disable_submit != 'undefined' && dgwt_wcas.disable_submit ? true : false, 3724 voiceSearchEnabled: typeof dgwt_wcas.voice_search_enabled != 'undefined' && dgwt_wcas.voice_search_enabled ? true : false, 3725 voiceSearchLang: typeof dgwt_wcas.voice_search_lang != 'undefined' ? dgwt_wcas.voice_search_lang : '', 3726 showRecentlySearchedProducts: typeof dgwt_wcas.show_recently_searched_products != 'undefined' ? dgwt_wcas.show_recently_searched_products : false, 3727 showRecentlySearchedPhrases: typeof dgwt_wcas.show_recently_searched_phrases != 'undefined' ? dgwt_wcas.show_recently_searched_phrases : false, 3728 }; 3729 3730 $('.dgwt-wcas-search-input').dgwtWcasAutocomplete(window.dgwt_wcas.config); 3731 3732 }); 3733 3734 3735 /** 3736 * UI Fixer. Fixes several known UX issues related to search bars 3737 */ 3738 var UI_FIXER = { 3739 brokenSearchUi: typeof dgwt_wcas.fixer.broken_search_ui != 'undefined' && dgwt_wcas.fixer.broken_search_ui ? true : false, 3740 brokenSearchUiAjax: typeof dgwt_wcas.fixer.broken_search_ui_ajax != 'undefined' && dgwt_wcas.fixer.broken_search_ui_ajax ? true : false, 3741 brokenSearchUiHard: typeof dgwt_wcas.fixer.broken_search_ui_hard != 'undefined' && dgwt_wcas.fixer.broken_search_ui_hard ? true : false, 3742 brokenSearchElementorPopups: typeof dgwt_wcas.fixer.broken_search_elementor_popups != 'undefined' && dgwt_wcas.fixer.broken_search_elementor_popups ? true : false, 3743 brokenSearchJetMobileMenu: typeof dgwt_wcas.fixer.broken_search_jet_mobile_menu != 'undefined' && dgwt_wcas.fixer.broken_search_jet_mobile_menu ? true : false, 3744 brokenSearchBrowserBackArrow: typeof dgwt_wcas.fixer.broken_search_browsers_back_arrow != 'undefined' && dgwt_wcas.fixer.broken_search_browsers_back_arrow ? true : false, 3745 forceRefreshCheckout: typeof dgwt_wcas.fixer.force_refresh_checkout != 'undefined' && dgwt_wcas.fixer.force_refresh_checkout ? true : false, 3746 searchBars: [], 3747 init: function () { 3748 var that = this; 3749 3750 /** 3751 * Fix broken search bars UI - first approach, after loading the page 3752 * Some page builders can copy instances of search bar without events eg. mobile usage. 3753 */ 3754 if (that.brokenSearchUi) { 3755 $(document).ready(function () { 3756 that.fixBrokenSearchUi(); 3757 }); 3758 } 3759 3760 /** 3761 * 3762 */ 3763 if (that.brokenSearchUiAjax) { 3764 that.fixBrokenSearchUiAjax(); 3765 } 3766 3767 /** 3768 * Repair search bars continuously 3769 * May overload the browser. Disabled by default. 3770 */ 3771 if (that.brokenSearchUiHard) { 3772 that.fixBrokenSearchUiHard(); 3773 } 3774 3775 /** 3776 * Fix Elementor popups 3777 * Reinit the search bars after loading Elementor popup 3778 */ 3779 if (that.brokenSearchElementorPopups) { 3780 $(document).ready(function () { 3781 that.fixBrokenSearchOnElementorPopupsV1(); 3782 that.fixBrokenSearchOnElementorPopupsV2(); 3783 }); 3784 } 3785 3786 /** 3787 * Fix search bars displayed in Jet Smart Menu 3788 * if there are duplicated inputs 3789 */ 3790 if (that.brokenSearchJetMobileMenu) { 3791 $(window).on('load', function () { 3792 that.fixSearchInJetMobileMenu(); 3793 }); 3794 } 3795 3796 /** 3797 * Fix broken search bars after click browser's back arrow. 3798 * Not worked for some browsers especially Safari and FF 3799 * Add dgwt-wcas-active class if wasn't added for some reason 3800 */ 3801 if (that.brokenSearchBrowserBackArrow) { 3802 that.fixbrokenSearchBrowserBackArrow(); 3803 } 3804 3805 /** 3806 * Refreshing the content on the checkout page when a product is added to the cart from the search Details Panel 3807 */ 3808 if (that.forceRefreshCheckout) { 3809 that.fixforceRefreshCheckout(); 3810 } 3811 }, 3812 fixBrokenSearchUi: function () { 3813 var that = this; 3814 3815 $(document).ready(function () { 3816 setTimeout(function () { 3817 that.pullAndReconditionSearchBars(); 3818 }, 50); 3819 }); 3820 3821 $(window).on('load', function () { 3822 setTimeout(function () { 3823 that.pullAndReconditionSearchBars(); 3824 }, 500); 3825 }); 3826 }, 3827 fixBrokenSearchUiAjax: function () { 3828 var that = this; 3829 $(document).ajaxSuccess(function (event, request, settings) { 3830 3831 // Exclude FiboSearch and WooCommerce AJAX requests 3832 if (typeof settings.url == 'string' && new RegExp('search\.php|wc-ajax').test(settings.url)) { 3833 return; 3834 } 3835 3836 if (typeof request.responseText == 'string' && request.responseText.includes('dgwt-wcas-search-input')) { 3837 setTimeout(function () { 3838 that.pullAndReconditionSearchBars(); 3839 }, 500); 3840 } 3841 }); 3842 }, 3843 fixBrokenSearchUiHard: function () { 3844 var that = this; 3845 $(document).ready(function () { 3846 3847 if (that.searchBars.length === 0) { 3848 that.pullAndReconditionSearchBars(); 3849 } 3850 3851 setInterval(function () { 3852 that.pullAndReconditionSearchBars(); 3853 }, 1000); 3854 }); 3855 }, 3856 fixBrokenSearchOnElementorPopupsV1: function () { 3857 var that = this; 3858 $(document).on('elementor/popup/show', () => { 3859 setTimeout(function () { 3860 that.pullAndReconditionSearchBars(); 3861 }, 500); 3862 }); 3863 }, 3864 fixBrokenSearchOnElementorPopupsV2: function () { 3865 var that = this; 3866 $(document).ready(function () { 3867 if ( 3868 typeof window.elementorFrontend != 'undefined' 3869 && typeof window.elementorFrontend.documentsManager != 'undefined' 3870 && typeof window.elementorFrontend.documentsManager.documents != 'undefined' 3871 ) { 3872 3873 $.each(elementorFrontend.documentsManager.documents, function (id, document) { 3874 3875 if (typeof document.getModal != 'undefined' && document.getModal) { 3876 3877 document.getModal().on('show', function () { 3878 setTimeout(function () { 3879 that.pullAndReconditionSearchBars(); 3880 }, 500); 3881 3882 }); 3883 } 3884 }); 3885 } 3886 }); 3887 }, 3888 fixSearchInJetMobileMenu: function () { 3889 var that = this; 3890 3891 if ($('.jet-mobile-menu__toggle').length === 0) { 3892 return; 3893 } 3894 3895 $(document).ajaxSend(function (event) { 3896 3897 if ( 3898 typeof event.currentTarget != 'undefined' 3899 && typeof event.currentTarget.activeElement == 'object' 3900 && $(event.currentTarget.activeElement).hasClass('jet-mobile-menu__toggle') 3901 ) { 3902 3903 setTimeout(function () { 3904 var $search = $(".jet-mobile-menu__container .dgwt-wcas-search-input"); 3905 3906 if ($search.length > 0) { 3907 that.pullAndReconditionSearchBars(); 3908 } 3909 3910 }, 500); 3911 3912 } 3913 }); 3914 }, 3915 fixforceRefreshCheckout: function () { 3916 $(document.body).on('added_to_cart', function () { 3917 if ( 3918 $(document.body).hasClass('woocommerce-checkout') && 3919 $('.dgwt-wcas-search-input').length > 0 3920 ) { 3921 $(document.body).trigger('update_checkout'); 3922 } 3923 }); 3924 }, 3925 fixbrokenSearchBrowserBackArrow: function () { 3926 $(window).on('load', function () { 3927 var i = 0; 3928 var interval = setInterval(function () { 3929 3930 var activeEl = document.activeElement; 3931 if ( 3932 typeof activeEl == 'object' 3933 && $(activeEl).length 3934 && $(activeEl).hasClass('dgwt-wcas-search-input') 3935 ) { 3936
3937 var $search = $(activeEl).closest('.dgwt-wcas-search-wrapp'); 3938 3939 if ($search.length && !$search.hasClass('dgwt-wcas-active')) { 3940 $search.addClass('dgwt-wcas-active'); 3941 clearInterval(interval); 3942 } 3943 } 3944 3945 // Stop after 5 seconds 3946 if (i > 10) { 3947 clearInterval(interval); 3948 } 3949 3950 i++; 3951 3952 }, 500); 3953 }); 3954 }, 3955 pullAndReconditionSearchBars: function () { 3956 var that = this, 3957 $inputs = $('.dgwt-wcas-search-input'), 3958 firstPull = that.searchBars.length == 0; 3959 3960 if ($inputs.length > 0) { 3961 $inputs.each(function () { 3962 var $searchBar = $(this), 3963 isNew = true, 3964 i; 3965 3966 // Check if this search bar is new one or not 3967 if (that.searchBars.length > 0) { 3968 for (i = 0; i < that.searchBars.length; i++) { 3969 if ($searchBar[0] === that.searchBars[i][0]) { 3970 isNew = false; 3971 break; 3972 } 3973 } 3974 } 3975 3976 if (isNew) { 3977 var changedId = false; 3978 if (!that.hasUniqueId($searchBar)) { 3979 that.makeUniqueID($searchBar); 3980 changedId = true; 3981 } 3982 3983 if (!firstPull || !that.isInitialized($searchBar) || changedId) { 3984 that.reinitSearchBar($searchBar) 3985 } 3986 3987 that.searchBars.push($searchBar); 3988 } 3989 3990 if (!that.hasEvents($searchBar)) { 3991 that.reinitSearchBar($searchBar) 3992 } 3993 3994 }); 3995 } 3996 }, 3997 hasEvents: function ($searchBarInput) { 3998 var hasEvents = false; 3999 $searchBarInput.trigger('fibosearch/ping'); 4000 if ($searchBarInput.hasClass('fibosearch-pong')) { 4001 hasEvents = true; 4002 } 4003 $('.fibosearch-pong').removeClass('fibosearch-pong'); 4004 return hasEvents; 4005 }, 4006 isInitialized: function ($searchBarInput) { 4007 return typeof $searchBarInput.data('autocomplete') == 'object'; 4008 }, 4009 hasUniqueId: function ($searchBarInput) { 4010 var that = this, 4011 unique = true; 4012 if (that.searchBars.length > 0) { 4013 for (var i = 0; i < that.searchBars.length; i++) { 4014 if ($searchBarInput.attr('id') === that.searchBars[i].attr('id')) { 4015 unique = false; 4016 } 4017 } 4018 } 4019 return unique; 4020 }, 4021 reinitSearchBar: function ($searchBarInput) { 4022 if (typeof $searchBarInput.data('autocomplete') == 'object') { 4023 $searchBarInput.data('autocomplete').dispose(); 4024 } 4025 $searchBarInput.dgwtWcasAutocomplete(window.dgwt_wcas.config); 4026 }, 4027 makeUniqueID: function ($searchBarInput) { 4028 var newID = Math.random().toString(36).substring(2, 6); 4029 newID = 'dgwt-wcas-search-input-' + newID; 4030 4031 $searchBarInput.attr('id', newID); 4032 $searchBarInput.closest('form').find('label').attr('for', newID); 4033 }, 4034 } 4035 4036 if (typeof dgwt_wcas.fixer.core == 'undefined') { 4037 dgwt_wcas.fixer.core = UI_FIXER;
4038 dgwt_wcas.fixer.core.init(); 4039 } 4040 4041 }()); 4042 4043}));
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.