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

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

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

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

يأخذ طلب الإكمال التلقائي سلسلة إدخال طلب بحث ويعرض قائمة بتنبؤات الأماكن. لتقديم طلب للإكمال التلقائي، استدعِ الرمز 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"
    "باريس"،
    "باريس، الجمعة"
  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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

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

تجربة النموذج