खोज विजेट के साथ खोज इंटरफ़ेस बनाना

सर्च विजेट, वेब ऐप्लिकेशन के लिए पसंद के मुताबिक बनाया जा सकने वाला सर्च इंटरफ़ेस उपलब्ध कराता है. इसे लागू करने के लिए, कम से कम एचटीएमएल और JavaScript की ज़रूरत होती है. साथ ही, यह फ़ैसेट और पेज नंबर के हिसाब से बांटने जैसी सामान्य सुविधाओं के साथ काम करता है. सीएसएस और JavaScript की मदद से, इंटरफ़ेस को भी अपनी पसंद के मुताबिक बनाया जा सकता है.

अगर आपको और विकल्प चाहिए, तो Query API का इस्तेमाल करें. Query API की मदद से सर्च इंटरफ़ेस बनाना लेख पढ़ें.

सर्च इंटरफ़ेस बनाना

सर्च इंटरफ़ेस बनाने के लिए, यह तरीका अपनाएं:

  1. सर्च ऐप्लिकेशन को कॉन्फ़िगर करें.
  2. ऐप्लिकेशन के लिए क्लाइंट आईडी जनरेट करें.
  3. सर्च बॉक्स और नतीजों के लिए एचटीएमएल मार्कअप जोड़ें.
  4. विजेट को पेज पर लोड करें.
  5. विजेट को शुरू करें.

सर्च ऐप्लिकेशन को कॉन्फ़िगर करना

हर खोज इंटरफ़ेस के लिए, Admin console में तय किया गया खोज ऐप्लिकेशन ज़रूरी होता है. यह ऐप्लिकेशन, क्वेरी सेटिंग उपलब्ध कराता है. जैसे, डेटा सोर्स, फ़ैसेट, और खोज की क्वालिटी के पैरामीटर.

सर्च ऐप्लिकेशन बनाने के लिए, पसंद के मुताबिक सर्च एक्सपीरियंस बनाना लेख पढ़ें.

ऐप्लिकेशन के लिए क्लाइंट आईडी जनरेट करना

Cloud Search API का ऐक्सेस कॉन्फ़िगर करना में दिए गए चरणों के अलावा, अपने वेब ऐप्लिकेशन के लिए क्लाइंट आईडी जनरेट करें.

प्रोजेक्ट कॉन्फ़िगर करना

प्रोजेक्ट को कॉन्फ़िगर करते समय:

  • वेब ब्राउज़र क्लाइंट टाइप चुनें.
  • अपने ऐप्लिकेशन का ओरिजिन यूआरआई दें.
  • क्लाइंट आईडी नोट करें. इस विजेट के लिए, क्लाइंट सीक्रेट की ज़रूरत नहीं होती.

ज़्यादा जानकारी के लिए, क्लाइंट-साइड वेब ऐप्लिकेशन के लिए OAuth 2.0 लेख पढ़ें.

एचटीएमएल मार्कअप जोड़ना

विजेट के लिए इन एचटीएमएल एलिमेंट की ज़रूरत होती है:

  • खोज बॉक्स के लिए input एलिमेंट.
  • सुझाव वाले डायलॉग को ऐंकर करने के लिए एलिमेंट.
  • खोज के नतीजों के लिए एक एलिमेंट.
  • (वैकल्पिक) फ़ैसेट कंट्रोल के लिए एक एलिमेंट.

इस स्निपेट में, id एट्रिब्यूट के हिसाब से पहचाने गए एलिमेंट दिखाए गए हैं:

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>

विजेट लोड करना

<script> टैग का इस्तेमाल करके लोडर शामिल करें:

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>

onload कॉलबैक दें. जब लोडर तैयार हो जाए, तो एपीआई क्लाइंट, Google साइन-इन, और Cloud Search मॉड्यूल लोड करने के लिए, gapi.load() को कॉल करें.

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)
}

विजेट को शुरू करना

क्लाइंट लाइब्रेरी को gapi.client.init() या gapi.auth2.init() का इस्तेमाल करके शुरू करें. इसके लिए, अपने Client-ID और https://www.googleapis.com/auth/cloud_search.query स्कोप का इस्तेमाल करें. विजेट को कॉन्फ़िगर और बाइंड करने के लिए, बिल्डर क्लास का इस्तेमाल करें.

शुरुआती ब्लॉक का उदाहरण:

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'
    });
  });
}

कॉन्फ़िगरेशन वैरिएबल:

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/...";

साइन-इन करने के अनुभव को पसंद के मुताबिक बनाना

जब उपयोगकर्ता टाइप करना शुरू करते हैं, तब विजेट उन्हें साइन इन करने के लिए कहता है. अपनी पसंद के मुताबिक अनुभव पाने के लिए, वेबसाइटों के लिए Google से साइन इन करने की सुविधा का इस्तेमाल किया जा सकता है.

उपयोगकर्ताओं को सीधे तौर पर अनुमति देना

साइन-इन की स्थितियों को मॉनिटर और मैनेज करने के लिए, 'Google से साइन इन करें' सुविधा का इस्तेमाल करें. इस उदाहरण में, बटन पर क्लिक करने पर GoogleAuth.signIn() का इस्तेमाल किया गया है:

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();
};

उपयोगकर्ताओं को अपने-आप साइन इन होने की सुविधा

अपने संगठन के उपयोगकर्ताओं के लिए, ऐप्लिकेशन को पहले से अनुमति दें, ताकि वे आसानी से साइन इन कर सकें. यह Cloud Identity Aware Proxy के साथ भी काम करता है. आईटी ऐप्लिकेशन के साथ Google साइन-इन का इस्तेमाल करना लेख पढ़ें.

इंटरफ़ेस को पसंद के मुताबिक बनाना

विजेट के दिखने के तरीके में बदलाव करने के लिए:

  • सीएसएस की मदद से स्टाइल बदलना.
  • अडैप्टर की मदद से एलिमेंट को सजाना.
  • ऐडैप्टर की मदद से कस्टम एलिमेंट बनाना.

सीएसएस की मदद से स्टाइल बदलना

इस विजेट में अपनी सीएसएस शामिल होती है. इसे बदलने के लिए, ज़्यादा जानकारी देने वाले पूर्वज सिलेक्टर का इस्तेमाल करें:

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

इस्तेमाल की जा सकने वाली सीएसएस क्लास का रेफ़रंस देखें.

अडैप्टर की मदद से एलिमेंट को सजाना

रेंडर करने से पहले एलिमेंट में बदलाव करने के लिए, एक अडैप्टर बनाएं और उसे रजिस्टर करें. इस उदाहरण में, कस्टम सीएसएस क्लास जोड़ी गई है:

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');
}

शुरू करने के दौरान अडैप्टर रजिस्टर करें:

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();

अडैप्टर की मदद से कस्टम एलिमेंट बनाना

पसंद के मुताबिक यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट बनाने के लिए, createSuggestionElement, createFacetResultElement या createSearchResultElement लागू करें. इस उदाहरण में एचटीएमएल <template> टैग का इस्तेमाल किया गया है:

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;
}

अडैप्टर को रजिस्टर करें:

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();

कस्टम फ़ैसेट एलिमेंट के लिए, इन नियमों का पालन करना ज़रूरी है:

  • क्लिक किए जा सकने वाले एलिमेंट में cloudsearch_facet_bucket_clickable अटैच करें.
  • हर बकेट को cloudsearch_facet_bucket_container में रैप करें.
  • जवाब में बकेट का क्रम बनाए रखना.

उदाहरण के लिए, यहां दिया गया स्निपेट, चेक बॉक्स के बजाय लिंक का इस्तेमाल करके फ़ैसेट रेंडर करता है.

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) {
  // ...
}

खोजने के तरीके को पसंद के मुताबिक बनाना

अडैप्टर की मदद से अनुरोधों को इंटरसेप्ट करके, खोज ऐप्लिकेशन की सेटिंग को ओवरराइड करें. अनुरोधों को लागू करने से पहले उनमें बदलाव करने के लिए, interceptSearchRequest लागू करें. इस उदाहरण में, क्वेरी को चुने गए सोर्स तक सीमित किया गया है:

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;
}

अडैप्टर को रजिस्टर करें:

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();

यहां दिए गए एचटीएमएल का इस्तेमाल, सोर्स के हिसाब से फ़िल्टर करने के लिए, एक 'चुने गए' बॉक्स को दिखाने के लिए किया जाता है:

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>

यहां दिया गया कोड, बदलाव को सुनता है, सिलेक्शन सेट करता है, और अगर ज़रूरी हो, तो क्वेरी को फिर से लागू करता है.

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);
  }
}

अडैप्टर में interceptSearchResponse लागू करके, खोज के जवाब को भी रोका जा सकता है.

वर्शन पिन करना

  • एपीआई वर्शन: इसे शुरू करने से पहले cloudsearch.config/apiVersion सेट करें.
  • विजेट का वर्शन: gapi.config.update('cloudsearch.config/clientVersion', 1.1) का इस्तेमाल करें.

अगर इन्हें सेट नहीं किया जाता है, तो दोनों की डिफ़ॉल्ट वैल्यू 1.0 होती है.

उदाहरण के लिए, विजेट को वर्शन 1.1 पर पिन करने के लिए:

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

सर्च इंटरफ़ेस को सुरक्षित करना

वेब ऐप्लिकेशन के लिए, सुरक्षा के सबसे सही तरीकों का पालन करें. खास तौर पर, क्लिकजैकिंग को रोकने के लिए.

डीबग करने की सुविधा चालू करना

डीबग करने की सुविधा चालू करने के लिए, interceptSearchRequest का इस्तेमाल करें:

if (!request.requestOptions) {
  request.requestOptions = {};
}
request.requestOptions.debugOptions = {enableDebugging: true};
return request;