Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dowiedz się, jak zaimplementować autouzupełnianie (zapytania typowe i sugerowane wyniki), gdy użytkownik zacznie wpisywać tekst w polu wyszukiwania. W tym samouczku pokażemy zapytania autouzupełniane i sugerowane wyniki oddzielnie, a następnie razem. Użytkownik może wpisać tylko dwa lub trzy znaki, aby zlokalizować wszystkie dostępne wyniki.
W tym poradniku nauczysz się, jak:
- Dodawanie sugestii
- Dodawanie wyróżniania do sugestii
- Dodaj autouzupełnianie
- Łączenie autouzupełniania i sugestii
Przegląd
Ten samouczek dodaje autouzupełnianie i sugerowane wyniki do poprzedniego samouczka Dodawanie stronicowania do wyników wyszukiwania.
Ukończona wersja kodu w tym samouczku można znaleźć w następującym projekcie:
Wymagania wstępne
- Rozwiązanie 2a-add-paging (GitHub). Ten projekt może być twoją własną wersją utworzoną z poprzedniego samouczka lub kopią z usługi GitHub.
Dodawanie sugestii
Zacznijmy od najprostszego przypadku oferowania alternatyw dla użytkownika: listy rozwijanej sugerowanych wyników.
W pliku index.cshtml zmień instrukcję
@idTextBoxFor na azureautosuggest.@Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautosuggest" }) <input value="" class="searchBoxSubmit" type="submit">Po wykonaniu tego polecenia, po zamknięciu </div>, wprowadź ten skrypt. Ten skrypt korzysta z widżetu Autouzupełnianie z biblioteki interfejsu użytkownika jQuery typu open source, aby przedstawić listę rozwijaną sugerowanych wyników.
<script> $("#azureautosuggest").autocomplete({ source: "/Home/SuggestAsync?highlights=false&fuzzy=false", minLength: 2, position: { my: "left top", at: "left-23 bottom+10" } }); </script>Identyfikator
"azureautosuggest"łączy powyższy skrypt z polem wyszukiwania. Opcja źródłowa widżetu jest ustawiona na metodę Sugestii, która wywołuje interfejs API Sugestii z dwoma parametrami zapytania: highlights i fuzzy, które w tym przypadku są ustawione na wartość false. Ponadto, do wyzwolenia wyszukiwania potrzebne są co najmniej dwa znaki.
Dodawanie odwołań do skryptów jQuery do widoku
Aby uzyskać dostęp do biblioteki jQuery, zmień sekcję <nagłówka> pliku widoku na następujący kod:
<head> <meta charset="utf-8"> <title>Typeahead</title> <link href="https://code.jquery.com/ui/1.12.1/themes/start/jquery-ui.css" rel="stylesheet"> <script src="https://code.jquery.com/jquery-1.10.2.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <link rel="stylesheet" href="~/css/hotels.css" /> </head>Ponieważ wprowadzamy nowe odwołanie jQuery, musimy również usunąć lub dodać komentarz do domyślnego odwołania jQuery w pliku _Layout.cshtml (w folderze Views/Shared ). Znajdź następujące wiersze i oznacz jako komentarz pierwszy wiersz skryptu, jak pokazano poniżej. Ta zmiana pozwala uniknąć konfliktowych odwołań do jQuery.
<environment include="Development"> <!-- <script src="~/lib/jquery/dist/jquery.js"></script> --> <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script> <script src="~/js/site.js" asp-append-version="true"></script> </environment>Teraz możemy użyć wstępnie zdefiniowanych funkcji autouzupełniania jQuery.
Dodaj akcję sugerowania do kontrolera
Na kontrolerze głównym dodaj akcję SuggestAsync (po akcji PageAsync ).
public async Task<ActionResult> SuggestAsync(bool highlights, bool fuzzy, string term) { InitSearch(); // Setup the suggest parameters. var options = new SuggestOptions() { UseFuzzyMatching = fuzzy, Size = 8, }; if (highlights) { options.HighlightPreTag = "<b>"; options.HighlightPostTag = "</b>"; } // Only one suggester can be specified per index. It is defined in the index schema. // The name of the suggester is set when the suggester is specified by other API calls. // The suggester for the hotel database is called "sg", and simply searches the hotel name. var suggestResult = await _searchClient.SuggestAsync<Hotel>(term, "sg", options).ConfigureAwait(false); // Convert the suggested query results to a list that can be displayed in the client. List<string> suggestions = suggestResult.Value.Results.Select(x => x.Text).ToList(); // Return the list of suggestions. return new JsonResult(suggestions); }Parametr Size określa, ile wyników ma być zwracanych (jeśli nieokreślone, wartość domyślna to 5). Sugestor jest określony w indeksie wyszukiwania podczas tworzenia indeksu. W przykładowym indeksie hoteli obsługiwanym przez firmę Microsoft nazwa sugestora to "sg" i wyszukuje sugerowane dopasowania wyłącznie w polu HotelName .
Dopasowywanie rozmyte pozwala na uwzględnianie "prawie trafień" w danych wyjściowych aż do maksymalnej odległości edycji wynoszącej jeden. Jeśli parametr highlights ma wartość true, do danych wyjściowych zostaną dodane pogrubione tagi HTML. W następnej sekcji ustawimy oba parametry na true.
Mogą wystąpić błędy składniowe. Jeśli tak, dodaj następujące dwie instrukcje using na początku pliku.
using System.Collections.Generic; using System.Linq;Uruchom aplikację. Czy po wprowadzeniu, na przykład, ciągu "po" uzyskujesz różne opcje? Teraz spróbuj użyć ciągu "pa".
Zwróć uwagę, że wprowadzone litery muszą rozpoczynać się od wyrazu, a nie po prostu być zawarte w słowie.
W skrypcie widoku ustaw &fuzzy na true, a następnie uruchom aplikację ponownie. Teraz wprowadź "po". Zwróć uwagę, że wyszukiwanie zakłada, że popełniłeś błąd w jednej literze.
Jeśli cię interesuje, składnia zapytań Lucene w usłudze Azure Cognitive Search szczegółowo opisuje logikę używaną w wyszukiwaniach rozmytych.
Dodawanie wyróżniania do sugestii
Możemy poprawić wygląd sugestii użytkownika, ustawiając parametr highlights na true. Najpierw musimy jednak dodać kod do widoku, aby wyświetlić pogrubiony tekst.
W widoku (index.cshtml) dodaj następujący skrypt po skrypcie
"azureautosuggest", który został wcześniej opisany.<script> var updateTextbox = function (event, ui) { var result = ui.item.value.replace(/<\/?[^>]+(>|$)/g, ""); $("#azuresuggesthighlights").val(result); return false; }; $("#azuresuggesthighlights").autocomplete({ html: true, source: "/home/suggest?highlights=true&fuzzy=false&", minLength: 2, position: { my: "left top", at: "left-23 bottom+10" }, select: updateTextbox, focus: updateTextbox }).data("ui-autocomplete")._renderItem = function (ul, item) { return $("<li></li>") .data("item.autocomplete", item) .append("<a>" + item.label + "</a>") .appendTo(ul); }; </script>Teraz zmień identyfikator pola tekstowego, tak aby był odczytywany w następujący sposób.
@Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azuresuggesthighlights" }) <input value="" class="searchBoxSubmit" type="submit">Uruchom ponownie aplikację, a wprowadzony tekst powinien być pogrubiony w sugestiach. Spróbuj wpisać "pa".
Logika używana w powyższym skrypce wyróżniania nie jest niezawodna. Jeśli wprowadzisz termin, który pojawia się dwa razy w tej samej nazwie, wyniki oznaczone pogrubieniem nie są dokładnie tym, czego oczekujesz. Spróbuj wpisać "mo".
Jednym z pytań, na które deweloper musi odpowiedzieć, jest, kiedy skrypt działa "wystarczająco dobrze", a kiedy należy zająć się jego dziwactwami. Nie będziemy w tym samouczku bardziej rozwijać tematu wyróżniania, ale warto rozważyć znalezienie precyzyjnego algorytmu, jeśli wyróżnianie nie jest skuteczne dla Twoich danych. Aby uzyskać więcej informacji, zobacz Wyróżnianie trafień.
Dodaj autouzupełnianie
Inna odmiana, nieco inna niż sugestie, to autouzupełnianie (czasami nazywane "type-ahead"), które kończy termin zapytania. Ponownie zaczniemy od najprostszej implementacji przed ulepszeniem środowiska użytkownika.
Wprowadź następujący skrypt w widoku, postępując zgodnie z poprzednimi skryptami.
<script> $("#azureautocompletebasic").autocomplete({ source: "/Home/Autocomplete", minLength: 2, position: { my: "left top", at: "left-23 bottom+10" } }); </script>Teraz zmień identyfikator pola tekstowego, aby wyglądał następująco.
@Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocompletebasic" }) <input value="" class="searchBoxSubmit" type="submit">W kontrolerze głównym wprowadź akcję AutocompleteAsync po akcji SuggestAsync.
public async Task<ActionResult> AutoCompleteAsync(string term) { InitSearch(); // Setup the autocomplete parameters. var ap = new AutocompleteOptions() { Mode = AutocompleteMode.OneTermWithContext, Size = 6 }; var autocompleteResult = await _searchClient.AutocompleteAsync(term, "sg", ap).ConfigureAwait(false); // Convert the autocompleteResult results to a list that can be displayed in the client. List<string> autocomplete = autocompleteResult.Value.Results.Select(x => x.Text).ToList(); return new JsonResult(autocomplete); }Zwróć uwagę, że używamy tej samej funkcji sugestora o nazwie "sg" zarówno w wyszukiwaniu autouzupełniania, jak i przy sugestiach (więc staramy się automatycznie uzupełniać tylko nazwy hoteli).
Istnieje szereg ustawień AutocompleteMode i używamy trybu OneTermWithContext. Aby uzyskać opis dodatkowych opcji, odwołaj się do API Autouzupełniania.
Uruchom aplikację. Zwróć uwagę, że zakres opcji wyświetlanych na liście rozwijanej to pojedyncze wyrazy. Spróbuj wpisać wyrazy rozpoczynające się od "re". Zwróć uwagę, że liczba opcji zmniejsza się w miarę wpisywania większej liczby liter.
Jak widać, skrypt sugestii, który został uruchomiony wcześniej, jest prawdopodobnie bardziej przydatny niż ten skrypt autouzupełniania. Aby uczynić autouzupełnianie bardziej przyjaznym dla użytkownika, rozważ użycie go z sugerowanymi wynikami.
Łączenie autouzupełniania i sugestii
Łączenie autouzupełniania i sugestii jest najbardziej złożone z naszych opcji i prawdopodobnie zapewnia najlepsze środowisko użytkownika. Chcemy wyświetlić inline z tekstem podczas jego wpisywania, pierwszą sugestię usługi Azure Cognitive Search do automatycznego uzupełniania tekstu. Ponadto chcemy mieć szereg sugestii jako listę rozwijaną.
Istnieją biblioteki, które oferują tę funkcję — często nazywane "wbudowanym autouzupełnieniem" lub podobną nazwą. Jednak zamierzamy natywnie zaimplementować tę funkcję, aby móc eksplorować interfejsy API. Najpierw rozpoczniemy pracę nad kontrolerem w tym przykładzie.
Dodaj akcję do kontrolera, która zwraca tylko jeden wynik autouzupełniania wraz z określoną liczbą sugestii. Wywołamy tę akcję AutoCompleteAndSuggestAsync. W kontrolerze głównym dodaj następującą akcję, po wykonaniu innych nowych akcji.
public async Task<ActionResult> AutoCompleteAndSuggestAsync(string term) { InitSearch(); // Setup the type-ahead search parameters. var ap = new AutocompleteOptions() { Mode = AutocompleteMode.OneTermWithContext, Size = 1, }; var autocompleteResult = await _searchClient.AutocompleteAsync(term, "sg", ap); // Setup the suggest search parameters. var sp = new SuggestOptions() { Size = 8, }; // Only one suggester can be specified per index. The name of the suggester is set when the suggester is specified by other API calls. // The suggester for the hotel database is called "sg" and simply searches the hotel name. var suggestResult = await _searchClient.SuggestAsync<Hotel>(term, "sg", sp).ConfigureAwait(false); // Create an empty list. var results = new List<string>(); if (autocompleteResult.Value.Results.Count > 0) { // Add the top result for type-ahead. results.Add(autocompleteResult.Value.Results[0].Text); } else { // There were no type-ahead suggestions, so add an empty string. results.Add(""); } for (int n = 0; n < suggestResult.Value.Results.Count; n++) { // Now add the suggestions. results.Add(suggestResult.Value.Results[n].Text); } // Return the list. return new JsonResult(results); }Jedna opcja autouzupełniania jest zwracana na górze listy wyników, a następnie wszystkie sugestie.
W widoku najpierw zaimplementujemy trik, aby jasnoszary wyraz autouzupełniania był wyświetlany bezpośrednio pod pogrubionym tekstem wprowadzanym przez użytkownika. Kod HTML obejmuje pozycjonowanie względne w tym celu. Zmień instrukcję TextBoxFor (i otaczające ją instrukcje <div>) na następującą, zwracając uwagę, że drugie pole wyszukiwania, oznaczone jako poniżej, znajduje się bezpośrednio pod naszym normalnym polem wyszukiwania, przesuwając to pole wyszukiwania o 39 pikseli z jego domyślnego położenia!
<div id="underneath" class="searchBox" style="position: relative; left: 0; top: 0"> </div> <div id="searchinput" class="searchBoxForm" style="position: relative; left: 0; top: -39px"> @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocomplete" }) <input value="" class="searchBoxSubmit" type="submit"> </div>Zauważ, że ponownie zmieniamy identyfikator na azureautocomplete w tym przypadku.
W widoku wprowadź również następujący skrypt, po wprowadzeniu wszystkich wprowadzonych do tej pory skryptów. Skrypt jest długi i złożony ze względu na różne zachowania wejściowe, które obsługuje.
<script> $('#azureautocomplete').autocomplete({ delay: 500, minLength: 2, position: { my: "left top", at: "left-23 bottom+10" }, // Use Ajax to set up a "success" function. source: function (request, response) { var controllerUrl = "/Home/AutoCompleteAndSuggestAsync?term=" + $("#azureautocomplete").val(); $.ajax({ url: controllerUrl, dataType: "json", success: function (data) { if (data && data.length > 0) { // Show the autocomplete suggestion. document.getElementById("underneath").innerHTML = data[0]; // Remove the top suggestion as it is used for inline autocomplete. var array = new Array(); for (var n = 1; n < data.length; n++) { array[n - 1] = data[n]; } // Show the drop-down list of suggestions. response(array); } else { // Nothing is returned, so clear the autocomplete suggestion. document.getElementById("underneath").innerHTML = ""; } } }); } }); // Complete on TAB. // Clear on ESC. // Clear if backspace to less than 2 characters. // Clear if any arrow key hit as user is navigating the suggestions. $("#azureautocomplete").keydown(function (evt) { var suggestedText = document.getElementById("underneath").innerHTML; if (evt.keyCode === 9 /* TAB */ && suggestedText.length > 0) { $("#azureautocomplete").val(suggestedText); return false; } else if (evt.keyCode === 27 /* ESC */) { document.getElementById("underneath").innerHTML = ""; $("#azureautocomplete").val(""); } else if (evt.keyCode === 8 /* Backspace */) { if ($("#azureautocomplete").val().length < 2) { document.getElementById("underneath").innerHTML = ""; } } else if (evt.keyCode >= 37 && evt.keyCode <= 40 /* Any arrow key */) { document.getElementById("underneath").innerHTML = ""; } }); // Character replace function. function setCharAt(str, index, chr) { if (index > str.length - 1) return str; return str.substr(0, index) + chr + str.substr(index + 1); } // This function is needed to clear the "underneath" text when the user clicks on a suggestion, and to // correct the case of the autocomplete option when it does not match the case of the user input. // The interval function is activated with the input, blur, change, or focus events. $("#azureautocomplete").on("input blur change focus", function (e) { // Set a 2 second interval duration. var intervalDuration = 2000, interval = setInterval(function () { // Compare the autocorrect suggestion with the actual typed string. var inputText = document.getElementById("azureautocomplete").value; var autoText = document.getElementById("underneath").innerHTML; // If the typed string is longer than the suggestion, then clear the suggestion. if (inputText.length > autoText.length) { document.getElementById("underneath").innerHTML = ""; } else { // If the strings match, change the case of the suggestion to match the case of the typed input. if (autoText.toLowerCase().startsWith(inputText.toLowerCase())) { for (var n = 0; n < inputText.length; n++) { autoText = setCharAt(autoText, n, inputText[n]); } document.getElementById("underneath").innerHTML = autoText; } else { // The strings do not match, so clear the suggestion. document.getElementById("underneath").innerHTML = ""; } } // If the element loses focus, stop the interval checking. if (!$input.is(':focus')) clearInterval(interval); }, intervalDuration); }); </script>Zwróć uwagę, że funkcja interval jest używana do czyszczenia tekstu bazowego, gdy przestaje odpowiadać temu, co wpisuje użytkownik, oraz do dopasowania formatu liter (dużych lub małych) z tym, co wpisuje użytkownik (jak "pa" pasuje do "PA", "pA", "Pa" podczas wyszukiwania), aby nakładany tekst był przejrzysty.
Przeczytaj komentarze w skrypcie, aby uzyskać pełniejsze zrozumienie.
Na koniec musimy wprowadzić niewielkie dostosowanie do dwóch klas HTML, aby były przezroczyste. Dodaj następujący wiersz do klas searchBoxForm i searchBox w pliku hotels.css.
background: rgba(0,0,0,0);Teraz uruchom aplikację. Wprowadź ciąg "pa" w polu wyszukiwania. Czy otrzymujesz "pałac" jako sugestię autouzupełniania, wraz z nazwami dwóch hoteli zawierających "pa"?
Spróbuj użyć tabulacji, aby zaakceptować sugestię autouzupełniania, a następnie wybrać inne sugestie, korzystając ze strzałek i klawisza tabulacji. Spróbuj ponownie, używając myszy i pojedynczego kliknięcia. Sprawdź, czy skrypt dokładnie obsługuje wszystkie te sytuacje.
Możesz zdecydować, że załadowanie biblioteki, która oferuje tę funkcję, jest prostsze, ale teraz wiesz przynajmniej jeden sposób, żeby wbudowane automatyczne uzupełnianie działało.
Wnioski
Rozważ następujące wnioski z tego projektu:
- Autouzupełnianie (nazywane również "type-ahead") i podpowiedzi mogą umożliwić użytkownikowi wpisanie tylko kilku klawiszy w celu zlokalizowania dokładnie tego, czego chce.
- Autouzupełnianie i sugestie współpracujące ze sobą mogą zapewnić bogate doświadczenie użytkownika.
- Zawsze testuj funkcje autouzupełniania przy użyciu wszystkich form danych wejściowych.
- Użycie funkcji setInterval może być przydatne podczas weryfikowania i poprawiania elementów interfejsu użytkownika.
Dalsze kroki
W następnym samouczku przyjrzymy się innemu sposobie ulepszania środowiska użytkownika przy użyciu aspektów w celu zawężenia wyszukiwań jednym kliknięciem.