1AUI().add('dp-search-suggest-web', function(A) { 2 var DigitalPlaceSearchSuggestWeb = { 3 init: function(params) { 4 var timeout = null; 5 const autosuggestOnlyForGroupId = params.autosuggestOnlyForGroupId; 6 const autosuggestEntryClassNamesValue = params.autosuggestEntryClassNamesValue; 7 const inputField = $('#portlet' + params.namespace.slice(0, -1) + ' input[name="' + params.inputName + '"]'); 8 const form = inputField.closest("form"); 9 const listContainer = $("<div>") 10 .attr("id", params.namespace + "autocompleteListPanel") 11 .addClass("autocomplete-list panel") 12 .css({ position: "absolute", zIndex: 1000 }) 13 .hide(); 14 15 inputField.attr("autocomplete", "off"); 16 inputField.attr("aria-autocomplete", "list"); 17 inputField.after(listContainer); 18 19 inputField.on("input", function() { 20 clearTimeout(timeout); 21 var query = inputField.val().trim(); 22 23 if (query.length > 3) { 24 timeout = setTimeout(function() { 25 DigitalPlaceSearchSuggestWeb._fetchSuggestions(inputField, listContainer, form, query, autosuggestOnlyForGroupId, autosuggestEntryClassNamesValue); 26 }, 200); 27 } else { 28 listContainer.hide(); 29 } 30 }); 31 32 inputField.on("keydown", function(e) { 33 DigitalPlaceSearchSuggestWeb._handleKeydown(e, inputField, listContainer, form); 34 }); 35 36 $(document).on("click", function(event) { 37 if (!form.has(event.target).length) { 38 listContainer.hide(); 39 } 40 }); 41 }, 42 43 _handleKeydown: function(e, inputField, listContainer, form) { 44 var items = listContainer.find(".autocomplete-item"); 45 if (items.length === 0) return; 46 47 var selectedItem = listContainer.find(".selected"); 48 var newSelectedItem = null; 49 50 if (["ArrowDown", "ArrowUp"].includes(e.key)) { 51 e.preventDefault(); 52 } 53 54 switch (e.key) { 55 case "ArrowDown": 56 if (selectedItem.length === 0) { 57 newSelectedItem = items.first(); 58 } else { 59 newSelectedItem = selectedItem.next().length ? selectedItem.next() : items.first(); 60 } 61 break; 62 63 case "ArrowUp": 64 if (selectedItem.length === 0) { 65 newSelectedItem = items.last(); 66 } else { 67 newSelectedItem = selectedItem.prev().length ? selectedItem.prev() : items.last(); 68 } 69 break; 70 71 case "Enter": 72 if (selectedItem.length > 0) { 73 inputField.val(selectedItem.text()); 74 listContainer.hide(); 75 form.submit(); 76 return; 77 } 78 break; 79 } 80 81 if (newSelectedItem) { 82 items.removeClass("selected"); 83 newSelectedItem.addClass("selected"); 84 85 listContainer.scrollTop( 86 newSelectedItem.position().top + listContainer.scrollTop() - listContainer.height() / 2 87 ); 88 } 89 }, 90 91 _fetchSuggestions: function(inputField, listContainer, form, autosuggestText, autosuggestOnlyForGroupId, autosuggestEntryClassNamesValue) { 92 var postData = { 93 autosuggestEntryClassNamesValue: autosuggestEntryClassNamesValue, 94 autosuggestLanguageId: Liferay.ThemeDisplay.getLanguageId(), 95 autosuggestOnlyForGroupId: autosuggestOnlyForGroupId, 96 autosuggestText: autosuggestText, 97 autosuggestUserId: Liferay.ThemeDisplay.getUserId() 98 }; 99 100 fetch("/o/dp-search-bar/suggest", { 101 method: "POST", 102 headers: { 103 "Content-Type": "application/json", 104 "x-csrf-token": Liferay.authToken 105 }, 106 body: JSON.stringify(postData) 107 }) 108 .then(response => response.json()) 109 .then(data => DigitalPlaceSearchSuggestWeb._showSuggestions(inputField, listContainer, form, data)) 110 .catch(error => console.error("Error fetching suggestions:", error)); 111 }, 112 113 _showSuggestions: function(inputField, listContainer, form, items) { 114 listContainer.empty().hide(); 115 116 if (!items || items.length === 0) return; 117 118 items.forEach(item => { 119 var entry = $("<div>") 120 .addClass("autocomplete-item") 121 .text(item) 122 .on("click", function() { 123 inputField.val(item); 124 listContainer.hide(); 125 form.submit(); 126 }) 127 .on("mouseenter", function() { 128 listContainer.find(".autocomplete-item").removeClass("selected"); 129 $(this).addClass("selected"); 130 }) 131 .on("mouseleave", function() { 132 $(this).removeClass("selected"); 133 }); 134 135 listContainer.append(entry); 136 }); 137 138 var inputOffset = inputField.position(); 139 listContainer.css({ 140 top: inputOffset.top + inputField.outerHeight(), 141 left: inputOffset.left, 142 width: inputField.outerWidth() 143 }).show(); 144 } 145 }; 146 147 A.DigitalPlaceSearchSuggestWeb = DigitalPlaceSearchSuggestWeb; 148}, '', { 149 requires: ['aui-io-request', 'aui-base'] 150}); 151
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.