Suchoberfläche mit dem Such-Widget erstellen

Das Such-Widget bietet eine anpassbare Suchoberfläche für Webanwendungen. Für das Widget sind nur wenig HTML- und JavaScript-Code erforderlich, Implementieren und Aktivieren gängiger Suchfunktionen wie Facetten und Paginierung. Ich können auch Teile der Benutzeroberfläche mit CSS und JavaScript anpassen.

Wenn Sie mehr Flexibilität benötigen als das Widget bietet, sollten Sie das Query API Informationen zum Erstellen einer Suchoberfläche mit der Query API Weitere Informationen finden Sie unter Suchoberfläche mit der Query API erstellen.

Suchoberfläche erstellen

Zum Erstellen der Suchoberfläche sind mehrere Schritte erforderlich:

  1. Suchanwendung konfigurieren
  2. Client-ID für die Anwendung generieren
  3. HTML-Markup für das Suchfeld und die Ergebnisse hinzufügen
  4. Widget auf die Seite laden
  5. Widget initialisieren

Suchanwendung konfigurieren

Für jede Suchoberfläche muss in den Tags eine Suchanwendung definiert sein. Admin-Konsole. Die Suchanwendung bietet zusätzliche Informationen für die Abfrage, z. B. Datenquellen, Attribute, und die Suchqualität.

Informationen zum Erstellen einer Suchanwendung finden Sie unter Erstellen Sie eine benutzerdefinierte Suche.

Client-ID für die Anwendung generieren

Zusätzlich zu den Schritten in Konfigurieren Sie den Zugriff auf die Google Cloud Search API. müssen Sie auch eine Client-ID für die Webanwendung generieren.

Projekt konfigurieren

Wenn Sie das Projekt konfigurieren, geschieht Folgendes:

  • Wählen Sie als Clienttyp Webbrowser aus.
  • Geben Sie den Ursprungs-URI an. Ihrer App.
  • Notieren Sie sich die erstellte Client-ID. Sie benötigen die Client-ID, um führen Sie die nächsten Schritte aus. Der Clientschlüssel ist für den Widget.

Weitere Informationen finden Sie unter OAuth 2.0 für clientseitige Webanwendung.

HTML-Markup hinzufügen

Damit das Widget funktioniert, ist etwas HTML-Code erforderlich. Ich muss Folgendes enthalten:

  • Ein input-Element für das Suchfeld.
  • Ein Element, mit dem das Pop-up mit Vorschlägen verankert werden soll.
  • Ein Element, das die Suchergebnisse enthält.
  • (Optional) Geben Sie ein Element für die Attributsteuerelemente an.

Das folgende HTML-Snippet zeigt den HTML-Code für ein Such-Widget, wobei der -Elemente, die zu binden sind, sind durch ihr id-Attribut gekennzeichnet:

serving/widget/public/with_css/index.html
<div id="search_bar">
  <div id="suggestions_anchor">
    <input type="text" id="search_input" placeholder="Search for...">
  </div>
</div>
<div id="facet_results"></div>
<div id="search_results"></div>

Widget laden

Das Widget wird dynamisch über ein Loader-Skript geladen. Einzuschließen Verwenden Sie im Ladeprogramm das Tag <script> wie hier gezeigt:

serving/widget/public/with_css/index.html
<!-- Google API loader -->
<script src="https://apis.google.com/js/api.js?mods=enable_cloud_search_widget&onload=onLoad" async defer></script>

Im Script-Tag müssen Sie einen onload-Callback angeben. Die Funktion wird wenn das Ladeprogramm bereit ist. Wenn das Ladeprogramm bereit ist, fahren Sie mit dem Laden des Widgets fort Rufen Sie dazu gapi.load() auf, um den API-Client, Google Log-in und Cloud Search zu laden.

serving/widget/public/with_css/app.js
/**
* Load the cloud search widget & auth libraries. Runs after
* the initial gapi bootstrap library is ready.
*/
function onLoad() {
  gapi.load('client:auth2:cloudsearch-widget', initializeApp)
}

Die Funktion initializeApp() wird aufgerufen, nachdem alle Module geladen.

Widget initialisieren

Initialisieren Sie zunächst die Clientbibliothek, indem Sie gapi.client.init() oder gapi.auth2.init() durch die generierte Client-ID und den Bereich https://www.googleapis.com/auth/cloud_search.query. Verwenden Sie als Nächstes gapi.cloudsearch.widget.resultscontainer.Builder und gapi.cloudsearch.widget.searchbox.Builder Klassen zum Konfigurieren des Widgets und binden Sie ihn an Ihre HTML-Elemente.

Das folgende Beispiel zeigt, wie das Widget initialisiert wird:

serving/widget/public/with_css/app.js
/**
 * Initialize the app after loading the Google API client &
 * Cloud Search widget.
 */
function initializeApp() {
  // Load client ID & search app.
  loadConfiguration().then(function() {
    // Set API version to v1.
    gapi.config.update('cloudsearch.config/apiVersion', 'v1');

    // Build the result container and bind to DOM elements.
    var resultsContainer = new gapi.cloudsearch.widget.resultscontainer.Builder()
      .setSearchApplicationId(searchApplicationName)
      .setSearchResultsContainerElement(document.getElementById('search_results'))
      .setFacetResultsContainerElement(document.getElementById('facet_results'))
      .build();

    // Build the search box and bind to DOM elements.
    var searchBox = new gapi.cloudsearch.widget.searchbox.Builder()
      .setSearchApplicationId(searchApplicationName)
      .setInput(document.getElementById('search_input'))
      .setAnchor(document.getElementById('suggestions_anchor'))
      .setResultsContainer(resultsContainer)
      .build();
  }).then(function() {
    // Init API/oauth client w/client ID.
    return gapi.auth2.init({
        'clientId': clientId,
        'scope': 'https://www.googleapis.com/auth/cloud_search.query'
    });
  });
}

Im obigen Beispiel wird für die Konfiguration auf zwei Variablen verwiesen, die wie folgt definiert sind:

serving/widget/public/with_css/app.js
/**
* Client ID from OAuth credentials.
*/
var clientId = "...apps.googleusercontent.com";

/**
* Full resource name of the search application, such as
* "searchapplications/<your-id>".
*/
var searchApplicationName = "searchapplications/...";

Anmeldung anpassen

Standardmäßig werden Nutzer vom Widget aufgefordert, sich anzumelden und die App zu autorisieren wenn sie mit der Eingabe einer Abfrage beginnen. Sie können Google Log-in für Websites , um Nutzern eine individuellere Anmeldung zu bieten.

Nutzer direkt autorisieren

Verwenden Sie Über Google anmelden, um den Anmeldestatus Ihres und Nutzer nach Bedarf an- oder abmelden. Beispiel: Im Beispiel wird die isSignedIn Anmeldeänderungen überwachen und verwendet den GoogleAuth.signIn() Methode zum Starten der Anmeldung über eine Schaltfläche Klick:

serving/widget/public/with_signin/app.js
// Handle sign-in/sign-out.
let auth = gapi.auth2.getAuthInstance();

// Watch for sign in status changes to update the UI appropriately.
let onSignInChanged = (isSignedIn) => {
  // Update UI to switch between signed in/out states
  // ...
}
auth.isSignedIn.listen(onSignInChanged);
onSignInChanged(auth.isSignedIn.get()); // Trigger with current status.

// Connect sign-in/sign-out buttons.
document.getElementById("sign-in").onclick = function(e) {
  auth.signIn();
};
document.getElementById("sign-out").onclick = function(e) {
  auth.signOut();
};

Weitere Informationen finden Sie unter Über Google anmelden.

Nutzer automatisch anmelden

Sie können die Anmeldung weiter optimieren, indem Sie die im Namen der Nutzer in Ihrer Organisation. Diese Technik ist auch nützlich, wenn Cloud Identity-Aware Proxy verwendet wird. um die Anwendung zu schützen.

Weitere Informationen finden Sie im Hilfeartikel Google Log-in mit IT-Apps verwenden.

Benutzeroberfläche anpassen

Sie können die Darstellung der Suchoberfläche über eine Kombination von Techniken:

  • Stile mit CSS überschreiben
  • Elemente mit einem Adapter dekorieren
  • Benutzerdefinierte Elemente mit einem Adapter erstellen

Stile mit CSS überschreiben

Das Such-Widget verfügt über ein eigenes CSS, um Vorschläge und Ergebniselemente zu gestalten und die Paginierungs-Steuerelemente. Sie können diese Elemente bei Bedarf neu gestalten.

Während des Ladevorgangs lädt das Such-Widget dynamisch sein Standard-Stylesheet. Dies geschieht nach dem Laden von Anwendungs-Stylesheets, wodurch die Priorität erhöht wird. der Regeln. Um sicherzustellen, dass Ihre eigenen Stile Vorrang vor den Standards haben, Ancestor-Selektoren verwenden, um die Standardregeln spezifischer zu machen

Die folgende Regel hat beispielsweise keine Auswirkungen, wenn sie in einem statischen link- oder style-Tag im Dokument.

.cloudsearch_suggestion_container {
  font-size: 14px;
}

Qualifizieren Sie die Regel stattdessen mit der ID oder Klasse des Ancestor-Containers. die auf der Seite angegeben sind.

#suggestions_anchor .cloudsearch_suggestion_container {
  font-size: 14px;
}

Eine Liste der Supportklassen und Beispiel-HTML, die vom Widget erstellt wurden, finden Sie in der Referenz zu unterstützten CSS-Klassen

Elemente mit einem Adapter dekorieren

Um ein Element vor dem Rendering zu dekorieren, erstellen Sie ein Adapter, der eine der Dekorierungsmethoden wie decorateSuggestionElement oder decorateSearchResultElement.

Mit den folgenden Adaptern wird dem Vorschlag beispielsweise eine benutzerdefinierte Klasse hinzugefügt und Ergebniselemente.

serving/widget/public/with_decorated_element/app.js
/**
 * Search box adapter that decorates suggestion elements by
 * adding a custom CSS class.
 */
function SearchBoxAdapter() {}
SearchBoxAdapter.prototype.decorateSuggestionElement = function(element) {
  element.classList.add('my-suggestion');
}

/**
 * Results container adapter that decorates suggestion elements by
 * adding a custom CSS class.
 */
function ResultsContainerAdapter() {}
ResultsContainerAdapter.prototype.decorateSearchResultElement = function(element) {
  element.classList.add('my-result');
}

Verwende setAdapter(), um den Adapter beim Initialisieren des Widgets zu registrieren der jeweiligen Builder-Klasse an:

serving/widget/public/with_decorated_element/app.js
// Build the result container and bind to DOM elements.
var resultsContainer = new gapi.cloudsearch.widget.resultscontainer.Builder()
  .setAdapter(new ResultsContainerAdapter())
  // ...
  .build();

// Build the search box and bind to DOM elements.
var searchBox = new gapi.cloudsearch.widget.searchbox.Builder()
  .setAdapter(new SearchBoxAdapter())
  // ...
  .build();

Mit einem Decorator können die Attribute des Containerelements sowie beliebige untergeordneten Elementen. Untergeordnete Elemente können während der Dekoration hinzugefügt oder entfernt werden. Wenn Sie jedoch strukturelle Änderungen an den Elementen vornehmen, sollten Sie erwägen, anstatt sie zu dekorieren.

Benutzerdefinierte Elemente mit einem Adapter erstellen

So erstellen Sie ein benutzerdefiniertes Element für einen Vorschlag, einen Attributcontainer oder ein Suchergebnis: einen Adapter erstellen und registrieren, createSuggestionElement, createFacetResultElement oder createSearchResultElement repräsentiert.

Die folgenden Adapter veranschaulichen die Erstellung benutzerdefinierter Vorschläge und Suchergebnisse -Elementen mithilfe von <template>-HTML-Tags hinzufügen.

serving/widget/public/with_custom_element/app.js
/**
 * Search box adapter that overrides creation of suggestion elements.
 */
function SearchBoxAdapter() {}
SearchBoxAdapter.prototype.createSuggestionElement = function(suggestion) {
  let template = document.querySelector('#suggestion_template');
  let fragment = document.importNode(template.content, true);
  fragment.querySelector('.suggested_query').textContent = suggestion.suggestedQuery;
  return fragment.firstElementChild;
}

/**
 * Results container adapter that overrides creation of result elements.
 */
function ResultsContainerAdapter() {}
ResultsContainerAdapter.prototype.createSearchResultElement = function(result) {
  let template = document.querySelector('#result_template');
  let fragment = document.importNode(template.content, true);
  fragment.querySelector('.title').textContent = result.title;
  fragment.querySelector('.title').href = result.url;
  let snippetText = result.snippet != null ?
    result.snippet.snippet : '';
  fragment.querySelector('.query_snippet').innerHTML = snippetText;
  return fragment.firstElementChild;
}

Verwende setAdapter(), um den Adapter bei der Initialisierung des Widgets zu registrieren der jeweiligen Builder-Klasse an:

serving/widget/public/with_custom_element/app.js
// Build the result container and bind to DOM elements.
var resultsContainer = new gapi.cloudsearch.widget.resultscontainer.Builder()
  .setAdapter(new ResultsContainerAdapter())
  // ...
  .build();

// Build the search box and bind to DOM elements.
var searchBox = new gapi.cloudsearch.widget.searchbox.Builder()
  .setAdapter(new SearchBoxAdapter())
  // ...
  .build();

Benutzerdefinierte Attributelemente mit createFacetResultElement erstellen unterliegt mehreren Einschränkungen:

  • Sie müssen die CSS-Klasse cloudsearch_facet_bucket_clickable an die Element, auf das Nutzende klicken, um zwischen einem Bucket zu wechseln.
  • Sie müssen jeden Bucket mit dem CSS-Code in einem Element, in dem es enthalten ist, umschließen. Klasse cloudsearch_facet_bucket_container.
  • Sie können die Buckets nicht in einer anderen Reihenfolge rendern, als sie in der Antwort.

Das folgende Snippet rendert Facetten beispielsweise mithilfe von Links stattdessen von Kontrollkästchen.

serving/widget/public/with_custom_facet/app.js
/**
 * Results container adapter that intercepts requests to dynamically
 * change which sources are enabled based on user selection.
 */
function ResultsContainerAdapter() {
  this.selectedSource = null;
}

ResultsContainerAdapter.prototype.createFacetResultElement = function(result) {
  // container for the facet
  var container = document.createElement('div');

  // Add a label describing the facet (operator/property)
  var label = document.createElement('div')
  label.classList.add('facet_label');
  label.textContent = result.operatorName;
  container.appendChild(label);

  // Add each bucket
  for(var i in result.buckets) {
    var bucket = document.createElement('div');
    bucket.classList.add('cloudsearch_facet_bucket_container');

    // Extract & render value from structured value
    // Note: implementation of renderValue() not shown
    var bucketValue = this.renderValue(result.buckets[i].value)
    var link = document.createElement('a');
    link.classList.add('cloudsearch_facet_bucket_clickable');
    link.textContent = bucketValue;
    bucket.appendChild(link);
    container.appendChild(bucket);
  }
  return container;
}

// Renders a value for user display
ResultsContainerAdapter.prototype.renderValue = function(value) {
  // ...
}

Suchverhalten anpassen

Die Einstellungen für die Suchanwendung entsprechen den Standardeinstellungen, Konfiguration für eine Suchoberfläche und sind statisch. So implementieren Sie dynamische Filter oder Facetten verwenden, z. B. das Umschalten zwischen Datenquellen, die Einstellungen der Suchanwendung durch Abfangen der Suchanfrage überschreiben mit einem Adapter.

Implementieren Sie einen Adapter mit dem interceptSearchRequest zum Ändern von Anfragen an die Search API vor der Ausführung.

Der folgende Adapter fängt beispielsweise Anfragen zur Einschränkung von Abfragen ab an eine vom Nutzer ausgewählte Quelle gesendet:

serving/widget/public/with_request_interceptor/app.js
/**
 * Results container adapter that intercepts requests to dynamically
 * change which sources are enabled based on user selection.
 */
function ResultsContainerAdapter() {
  this.selectedSource = null;
}
ResultsContainerAdapter.prototype.interceptSearchRequest = function(request) {
  if (!this.selectedSource || this.selectedSource == 'ALL') {
    // Everything selected, fall back to sources defined in the search
    // application.
    request.dataSourceRestrictions = null;
  } else {
    // Restrict to a single selected source.
    request.dataSourceRestrictions = [
      {
        source: {
          predefinedSource: this.selectedSource
        }
      }
    ];
  }
  return request;
}

Um den Adapter beim Initialisieren des Widgets zu registrieren, verwenden Sie die Methode setAdapter() beim Erstellen der ResultsContainer-Methode

serving/widget/public/with_request_interceptor/app.js
var resultsContainerAdapter = new ResultsContainerAdapter();
// Build the result container and bind to DOM elements.
var resultsContainer = new gapi.cloudsearch.widget.resultscontainer.Builder()
  .setAdapter(resultsContainerAdapter)
  // ...
  .build();

Der folgende HTML-Code wird verwendet, um ein Auswahlfeld zum Filtern nach anzuzeigen. Quellen:

serving/widget/public/with_request_interceptor/index.html
<div>
  <span>Source</span>
  <select id="sources">
    <option value="ALL">All</option>
    <option value="GOOGLE_GMAIL">Gmail</option>
    <option value="GOOGLE_DRIVE">Drive</option>
    <option value="GOOGLE_SITES">Sites</option>
    <option value="GOOGLE_GROUPS">Groups</option>
    <option value="GOOGLE_CALENDAR">Calendar</option>
    <option value="GOOGLE_KEEP">Keep</option>
  </select>
</div>

Der folgende Code überwacht die Änderung, legt die Auswahl fest und führt die Abfrage bei Bedarf neu aus.

serving/widget/public/with_request_interceptor/app.js
// Handle source selection
document.getElementById('sources').onchange = (e) => {
  resultsContainerAdapter.selectedSource = e.target.value;
  let request = resultsContainer.getCurrentRequest();
  if (request.query) {
    // Re-execute if there's a valid query. The source selection
    // will be applied in the interceptor.
    resultsContainer.resetState();
    resultsContainer.executeRequest(request);
  }
}

Sie können die Suchantwort auch abfangen, indem Sie Folgendes implementieren: interceptSearchResponse im Adapter.

API-Version anpinnen

Standardmäßig verwendet das Widget die neueste stabile API-Version. Zum Sperren eines bestimmte Version haben, legen Sie den Konfigurationsparameter cloudsearch.config/apiVersion fest bevor Sie das Widget initialisieren.

serving/widget/public/basic/app.js
gapi.config.update('cloudsearch.config/apiVersion', 'v1');

Die API-Version wird standardmäßig auf 1.0 gesetzt, wenn sie nicht konfiguriert oder auf einen ungültigen Wert festgelegt wird.

Widget-Version anpinnen

Um unerwartete Änderungen an Suchoberflächen zu vermeiden, legen Sie den Parameter cloudsearch.config/clientVersion-Konfigurationsparameter wie gezeigt:

gapi.config.update('cloudsearch.config/clientVersion', 1.1);

Wenn die Widget-Version nicht konfiguriert oder auf einen ungültigen Wert festgelegt ist, wird standardmäßig 1.0 verwendet.

Suchoberfläche schützen

Suchergebnisse enthalten streng vertrauliche Informationen. Best Practices anwenden zum Schutz von Webanwendungen, insbesondere vor Clickjacking-Angriffe.

Weitere Informationen finden Sie unter OWASP Guide Project

Fehlerbehebung aktivieren

interceptSearchRequest verwenden um die Fehlerbehebung für das Such-Widget zu aktivieren. Beispiel:

  if (!request.requestOptions) {
  // Make sure requestOptions is populated
  request.requestOptions = {};
  }
  // Enable debugging
  request.requestOptions.debugOptions = {enableDebugging: true}

  return request;