واجهة برمجة تطبيقات بيانات الإكمال التلقائي للأماكن

تتيح لك واجهة برمجة التطبيقات لبيانات الإكمال التلقائي للأماكن استرجاع عبارات البحث المقترحة آليًا لإنشاء تجارب مخصّصة للإكمال التلقائي مع مستوى تحكّم أكثر دقة من التطبيق المصغّر لميزة "الإكمال التلقائي". في هذا الدليل، ستتعرّف على كيفية استخدام واجهة برمجة التطبيقات لبيانات الإكمال التلقائي للأماكن لإجراء طلبات إكمال تلقائي استنادًا إلى طلبات بحث المستخدمين.

يوضح المثال التالي دمجًا بسيطًا للكتابة الأمامية. أدخِل طلب البحث ثم انقر لاختيار النتيجة التي تريدها.

طلبات الإكمال التلقائي

يأخذ طلب الإكمال التلقائي سلسلة إدخال طلب بحث ويعرض قائمة بتنبؤات الأماكن. لتقديم طلب إكمال تلقائي، يمكنك استدعاء fetchAutocompleteSuggestions() وإرسال طلب يتضمّن السمات المطلوبة. تحتوي السمة input على السلسلة المطلوب البحث فيها. وفي التطبيقات العادية، يتم تعديل هذه القيمة أثناء كتابة المستخدم لطلب بحث. يجب أن يتضمّن الطلب sessionToken يتم استخدامه لأغراض الفوترة.

يعرض المقتطف التالي إنشاء نص طلب وإضافة رمز مميّز للجلسة، ثم استدعاء fetchAutocompleteSuggestions() للحصول على قائمة بـ PlacePrediction.

// Add an initial request body.
let request = {
  input: "Tadi",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};
// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

تقييد توقعات الإكمال التلقائي

تعرض ميزة "الإكمال التلقائي للأماكن" تلقائيًا جميع أنواع الأماكن، وتكون متحيزة للتوقعات القريبة من موقع المستخدم، وتسترجع جميع حقول البيانات المتاحة للمكان الذي اختاره المستخدم. يمكنك ضبط خيارات الإكمال التلقائي للأماكن لتقديم توقعات أكثر صلة من خلال حصر النتائج أو انحيازها.

يؤدي حظر النتائج إلى تجاهل أداة "الإكمال التلقائي" لأي نتائج خارج منطقة الحظر. من الممارسات الشائعة تقييد النتائج بحدود الخريطة. تؤدي نتائج الانحياز إلى عرض نتائج من تطبيق "الإكمال التلقائي" المصغّر ضمن المنطقة المحددة، إلا أنّ بعض النتائج المطابِقة قد تكون خارج هذه المنطقة.

استخدِم السمة origin لتحديد نقطة الأصل التي يتم من خلالها احتساب المسافة الجيوديسية مع الوجهة. في حال إسقاط هذه القيمة، لن يتم عرض المسافة.

استخدِم السمة includedPrimaryTypes لتحديد ما يصل إلى خمسة أنواع أماكن. وإذا لم يتم تحديد أي أنواع، سيتم عرض الأماكن بجميع أنواعها.

الاطّلاع على مرجع واجهة برمجة التطبيقات

الحصول على تفاصيل المكان

لعرض كائن Place من نتيجة توقُّع مكان، عليك أولاً الاتصال بـ toPlace()، ثم الاتصال fetchFields() بالعنصر Place الناتج (يتم تضمين رقم تعريف الجلسة من توقّع المكان تلقائيًا). يؤدي الاتصال بالرقم fetchFields() إلى إنهاء جلسة الإكمال التلقائي.

let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});

const placeInfo = document.getElementById("prediction");

placeInfo.textContent =
  "First predicted place: " +
  place.displayName +
  ": " +
  place.formattedAddress;

الرموز المميزة للجلسة

تعمل الرموز المميّزة للجلسة على تجميع مرحلتَي طلب البحث والاختيار ضمن عملية بحث المستخدم التي تتم من خلال ميزة "الإكمال التلقائي" في جلسة منفصلة لأغراض الفوترة. تبدأ الجلسة عندما يبدأ المستخدم في الكتابة. تنتهي الجلسة عندما يختار المستخدم مكانًا وتُجرى فيه مكالمة للتعرّف على تفاصيل المكان.

لإنشاء رمز مميّز جديد للجلسة وإضافته إلى أحد الطلبات، يمكنك إنشاء مثيل من AutocompleteSessionToken، ثم ضبط السمة sessionToken للطلب لاستخدام الرموز المميّزة كما هو موضّح في المقتطف التالي:

// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

تنتهي الجلسة عند استدعاء fetchFields(). بعد إنشاء المثيل Place، لن تحتاج إلى تمرير الرمز المميّز للجلسة إلى fetchFields() لأنّه تتم معالجته تلقائيًا.

await place.fetchFields({
  fields: ["displayName", "formattedAddress"],
});
await place.fetchFields({
    fields: ['displayName'],
  });

يمكنك إنشاء رمز مميّز للجلسة للجلسة التالية من خلال إنشاء مثيل جديد من AutocompleteSessionToken.

اقتراحات الرموز المميّزة للجلسة:

  • استخدم الرموز المميزة للجلسة لجميع مكالمات الإكمال التلقائي للأماكن.
  • إنشاء رمز مميّز جديد لكل جلسة
  • اجتياز رمز مميز فريد للجلسة لكل جلسة جديدة. سيؤدي استخدام الرمز المميّز نفسه لأكثر من جلسة واحدة إلى تحصيل فواتير كل طلب على حدة.

يمكنك اختياريًا حذف الرمز المميز لجلسة الإكمال التلقائي من أحد الطلبات. في حال حذف الرمز المميّز للجلسة، يتم إصدار فواتير لكل طلب على حدة، ما يؤدي إلى ظهور رمز التخزين التعريفي الإكمال التلقائي - لكل طلب. في حال إعادة استخدام رمز مميّز للجلسة، تُعتبر الجلسة غير صالحة ويتم تحصيل رسوم على الطلبات كما لو لم يتم تقديم رمز مميّز للجلسة.

مثال

أثناء كتابة المستخدم لطلب بحث، يتم استدعاء طلب الإكمال التلقائي كل ضغطات مفاتيح قليلة (وليس لكل حرف)، ويتم عرض قائمة بالنتائج المحتملة. عندما يُجري المستخدم اختيارًا من قائمة النتائج، يتم احتساب الاختيار كطلب، ويتم تجميع كل الطلبات المقدَّمة أثناء البحث وحسابها كطلب واحد. إذا اختار المستخدم مكانًا، فسيكون طلب البحث متاحًا بدون أي رسوم، ولن يتم تحصيل رسوم سوى طلب بيانات المكان. وإذا لم يختر المستخدم قرارًا خلال بضع دقائق من بداية الجلسة، سيتم تحصيل رسوم طلب البحث فقط.

من منظور التطبيق، يسير سير الأحداث على النحو التالي:

  1. يبدأ أحد المستخدمين في كتابة طلب بحث عن "القاهرة، مصر".
  2. عند رصد البيانات التي أدخلها المستخدم، ينشئ التطبيق رمزًا مميّزًا جديدًا للجلسة، وهو "الرمز المميّز أ".
  3. أثناء كتابة المستخدم، ترسل واجهة برمجة التطبيقات طلب إكمال تلقائي كل بضعة أحرف، وتعرض قائمة جديدة بالنتائج المحتملة لكل منها:
    "P"
    "Par"
    "باريس"،
    "باريس، Fr"
  4. عندما يحدّد المستخدم:
    • يتم تجميع كل الطلبات الناتجة من طلب البحث وإضافتها كطلب واحد إلى الجلسة التي يمثّلها "الرمز المميّز أ".
    • ويتم احتساب اختيار المستخدم كطلب تفصيلي للمكان، وتتم إضافته إلى الجلسة التي يمثّلها "الرمز المميّز أ".
  5. تنتهي الجلسة ويتجاهل التطبيق "الرمز المميّز أ".
مزيد من المعلومات عن كيفية فوترة الجلسات

إكمال نموذج الرمز البرمجي

يحتوي هذا القسم على أمثلة كاملة توضح كيفية استخدام واجهة برمجة التطبيقات لبيانات الإكمال التلقائي للأماكن .

توقعات الإكمال التلقائي للأماكن

يوضّح المثال التالي استدعاء fetchAutocompleteSuggestions() للإدخال "Tadi"، ثم استدعاء toPlace() للنتيجة الأولى للتوقّع، متبوعًا بطلب إلى fetchFields() للحصول على تفاصيل المكان.

TypeScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
    // @ts-ignore
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: "Tadi",
        locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ["restaurant"],
        language: "en-US",
        region: "us",
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');
        const resultsElement = document.getElementById("results") as HTMLElement;
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById("prediction") as HTMLElement;
    placeInfo.textContent = 'First predicted place: ' + place.displayName + ': ' + place.formattedAddress;

}

init();

JavaScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
  // @ts-ignore
  const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
    await google.maps.importLibrary("places");
  // Add an initial request body.
  let request = {
    input: "Tadi",
    locationRestriction: {
      west: -122.44,
      north: 37.8,
      east: -122.39,
      south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
  };
  // Create a session token.
  const token = new AutocompleteSessionToken();

  // Add the token to the request.
  // @ts-ignore
  request.sessionToken = token;

  // Fetch autocomplete suggestions.
  const { suggestions } =
    await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
  const title = document.getElementById("title");

  title.appendChild(
    document.createTextNode('Query predictions for "' + request.input + '":'),
  );

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a new list element.
    const listItem = document.createElement("li");
    const resultsElement = document.getElementById("results");

    listItem.appendChild(
      document.createTextNode(placePrediction.text.toString()),
    );
    resultsElement.appendChild(listItem);
  }

  let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.

  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  const placeInfo = document.getElementById("prediction");

  placeInfo.textContent =
    "First predicted place: " +
    place.displayName +
    ": " +
    place.formattedAddress;
}

init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Predictions</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="title"></div>
    <ul id="results"></ul>
    <p><span id="prediction"></span></p>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>

تجربة "عيّنة"

وضع النص التالي للإكمال التلقائي من خلال الجلسات

يوضّح هذا المثال استدعاء fetchAutocompleteSuggestions() استنادًا إلى طلبات بحث المستخدمين، مع عرض قائمة بالأماكن المتوقّعة كاستجابة لها، ثم استرداد تفاصيل المكان للمكان المحدّد. يوضِّح المثال أيضًا استخدام الرموز المميّزة للجلسة لتجميع طلب بحث خاص بالمستخدم مع طلب "تفاصيل المكان" النهائي.

TypeScript

let title;
let results;
let input;
let token;

// Add an initial request body.
let request = {
    input: "",
    locationRestriction: { west: -122.44, north: 37.8, east: -122.39, south: 37.78 },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ["restaurant"],
    language: "en-US",
    region: "us",
};

async function init() {
    token = new google.maps.places.AutocompleteSessionToken();

    title = document.getElementById('title');
    results = document.getElementById('results');
    input = document.querySelector("input");
    input.addEventListener("input", makeAcRequest);
    request = refreshToken(request) as any;
}

async function makeAcRequest(input) {
    // Reset elements and exit if an empty string is received.
    if (input.target.value == '') {
        title.innerText = '';
        results.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = input.target.value;

    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    title.innerText = 'Query predictions for "' + request.input + '"';

    // Clear the list first.
    results.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        a.innerText = placePrediction.text.toString();

        // Create a new list element.
        const li = document.createElement('li');
        li.appendChild(a);
        results.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    let placeText = document.createTextNode(place.displayName + ': ' + place.formattedAddress);
    results.replaceChildren(placeText);
    title.innerText = 'Selected Place:';
    input.value = '';
    refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
    // Create a new session token and add it to the request.
    token = new google.maps.places.AutocompleteSessionToken();
    request.sessionToken = token;
    return request;
}

declare global {
    interface Window {
      init: () => void;
    }
  }
  window.init = init;

JavaScript

let title;
let results;
let input;
let token;
// Add an initial request body.
let request = {
  input: "",
  locationRestriction: {
    west: -122.44,
    north: 37.8,
    east: -122.39,
    south: 37.78,
  },
  origin: { lat: 37.7893, lng: -122.4039 },
  includedPrimaryTypes: ["restaurant"],
  language: "en-US",
  region: "us",
};

async function init() {
  token = new google.maps.places.AutocompleteSessionToken();
  title = document.getElementById("title");
  results = document.getElementById("results");
  input = document.querySelector("input");
  input.addEventListener("input", makeAcRequest);
  request = refreshToken(request);
}

async function makeAcRequest(input) {
  // Reset elements and exit if an empty string is received.
  if (input.target.value == "") {
    title.innerText = "";
    results.replaceChildren();
    return;
  }

  // Add the latest char sequence to the request.
  request.input = input.target.value;

  // Fetch autocomplete suggestions and show them in a list.
  // @ts-ignore
  const { suggestions } =
    await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(
      request,
    );

  title.innerText = 'Query predictions for "' + request.input + '"';
  // Clear the list first.
  results.replaceChildren();

  for (const suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a link for the place, add an event handler to fetch the place.
    const a = document.createElement("a");

    a.addEventListener("click", () => {
      onPlaceSelected(placePrediction.toPlace());
    });
    a.innerText = placePrediction.text.toString();

    // Create a new list element.
    const li = document.createElement("li");

    li.appendChild(a);
    results.appendChild(li);
  }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  let placeText = document.createTextNode(
    place.displayName + ": " + place.formattedAddress,
  );

  results.replaceChildren(placeText);
  title.innerText = "Selected Place:";
  input.value = "";
  refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
  // Create a new session token and add it to the request.
  token = new google.maps.places.AutocompleteSessionToken();
  request.sessionToken = token;
  return request;
}

window.init = init;

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

a {
  cursor: pointer;
  text-decoration: underline;
  color: blue;
}

input {
  width: 300px;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Session</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <input id="input" type="text" placeholder="Search for a place..." />
    <div id="title"></div>
    <ul id="results"></ul>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=init&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

تجربة "عيّنة"