I am trying to use the google places library for a nearby search request:
https://developers.google.com/maps/documentation/javascript/places#place_search_requests
i just want to pull the json response and put it in a html list, i do now want to show results on a map or something else. I do not want to use map at all. But in documentation it states that there has to be a map
service = new google.maps.places.PlacesService(**map**);
in order to pass it as an argument in the PlacesService function. What i do now is adding a map with height:0 but it still consumes much amount of memory (i develop a sencha touch 2 app and memory is important). Is there any workaround of using nearby search requests without a map? I do not want to use the Google Places API as it does not support JSONP requests.
As documented the PlacesService accepts as argument either a map or an node where to render the attributions for the results.
So you only have to use the node (a node being an html element) instead of the map.
Please note: hiding the attributions violates the places-policies(also hiding the map when used as argument, because the map will show the attributions)
This also may be interesting to you: Google places API does this violate the TOC?
Example: in a nutshell
If you're using jQuery:
var service = new google.maps.places.PlacesService($('#tag-id').get(0));
If plain Javascript:
var service = new google.maps.places.PlacesService(document.createElement('div'));
Then carry on as usual with the rest of the example code:
service.nearbySearch(request, callback);
Example: using details returned
Live demo of this example on jsFiddle.
Note: This example uses jQuery.
<ul class="reviews__content" id="reviews__content">
</ul>
<div id="service-helper"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=GOOGLE_API_KEY_HERE&libraries=places&callback=getRelevantGoogleReviews">
</script>
<script type="text/javascript">
window.getRelevantGoogleReviews = function(){
var service = new google.maps.places.PlacesService($('#service-helper').get(0)); // note that it removes the content inside div with tag '#service-helper'
service.getDetails({
placeId: 'ChIJAwEf5VFQqEcRollj8j_kqnE' // get a placeId using https://developers.google.com/places/web-service/place-id
}, function(place, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
var resultcontent = '';
for (i=0; i<place.reviews.length; ++i) {
//window.alert('Name:' + place.name + '. ID: ' + place.place_id + '. address: ' + place.formatted_address);
resultcontent += '<li class="reviews__item">'
resultcontent += '<div class="reviews__review-er">' + place.reviews[i].author_name + '</div>';
var reviewDate = new Date(place.reviews[i].time * 1000);
var reviewDateMM = reviewDate.getMonth() + 1;
var reviewDateFormatted = reviewDate.getDate() + '/' + reviewDateMM + '/' + reviewDate.getFullYear();
resultcontent += '<div class="reviews__review-date">' + reviewDateFormatted + '</div>';
resultcontent += '<div class="reviews__review-rating reviews__review-rating--' + place.reviews[i].rating +'"></div>';
if (!!place.reviews[i].text){
resultcontent += '<div class="reviews__review-comment">' + place.reviews[i].text + '</div>';
}
resultcontent += '</li>'
}
$('#reviews__content').append(resultcontent);
}
});
}
</script>
If you want to get location data from a place_id you can do it using the Geocoder class:Here the documentation. With this class you can pass a place_id to the method geocode() and get coordinates and other location data.
Was making a custom address autocomplete for a sign up form.
import {useState, useRef, useEffect } from 'React'
function AutoCompleteInput(){
const [predictions, setPredictions] = useState([]);
const [input, setInput] = useState('');
const [selectedPlaceDetail, addSelectedPlaceDetail] = useState({})
const predictionsRef = useRef();
useEffect(
()=>{
try {
autocompleteService.current.getPlacePredictions({ input }, predictions => {
setPredictions(predictions);
});
} catch (err) {
// do something
}
}
}, [input])
const handleAutoCompletePlaceSelected = placeId=>{
if (window.google) {
const PlacesService = new window.google.maps.places.PlacesService(predictionsRef.current);
try {
PlacesService.getDetails(
{
placeId,
fields: ['address_components'],
},
place => addSelectedPlaceDetail(place)
);
} catch (e) {
console.error(e);
}
}
}
return (
<>
<input onChange={(e)=>setInput(e.currentTarget.value)}
<div ref={predictionsRef}
{ predictions.map(prediction => <div onClick={ ()=>handleAutoCompletePlaceSelected(suggestion.place_id)}> prediction.description </div> )
}
</div>
<>
)
}
So basically, you setup the autocomplete call, and get back the predictions results in your local state.
from there, map and show the results with a click handler that will do the follow up request to the places services with access to the getDetails method for the full address object or whatever fields you want.
you then save that response to your local state and off you go.
Just seen Man asking in a comment above How to initialise the places service without initialising a map? so I thought I would add it here.
placesService = new google.maps.places.PlacesService($('#predicted-places').get(0));
You will need to create an html element with that id first though.
I have come across the same problem.
Why use Maps javascript Api when Places Api is already enabled.Is it an additional price to pay for this simple task?
Maps Javascript API is not used in this code.All the google.maps.Map API methods are taken out. It works fine on jsfiddle.
Just checkout whether it works on local PC.Most of the time it gives the 403 error when i tried running it on local PC storage and using limited requests provided by google API console.
acquire an API key from the google developer console and insert it in the YOUR_API_KEY slot at the script tag of the code
Don't try to run the code here.obviously.The API key needs to be replaced.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initMap() {
var input = document.getElementById('pac-input');
var options = {
types: ['establishment']
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
autocomplete.setFields(['place_id', 'geometry', 'name', 'formatted_address', 'formatted_phone_number', 'opening_hours', 'website', 'photos']);
autocomplete.addListener('place_changed', placechange);
function placechange() {
var place = autocomplete.getPlace();
var photos = place.photos;
document.getElementById('place_name').textContent = place.name;
document.getElementById('place_id').textContent = place.place_id;
document.getElementById('place_address').textContent = place.formatted_address;
document.getElementById('phone_no').textContent = place.formatted_phone_number;
document.getElementById('open_time').textContent = place.opening_hours.weekday_text[0];
document.getElementById('open_now').textContent = place.opening_hours.open_now;
document.getElementById('photo').src = photos[0].getUrl();
document.getElementById('photo').style = "width:50%;";
document.getElementById('website').textContent = place.website;
}
}
/* 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;
}
.controls {
background-color: #fff;
border-radius: 2px;
border: 1px solid transparent;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
height: 29px;
margin-left: 5px;
margin-top: 10px;
margin-bottom: 10px;
outline: none;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 400px;
}
.controls:focus {
border-color: #4d90fe;
}
.title {
font-weight: bold;
}
#infowindow-content {
display: none;
}
#map #infowindow-content {
display: inline;
}
<div>
<input id="pac-input" class="controls" type="text" placeholder="Enter a business">
</div>
<div id="info-table">
Name: <span id="place_name"></span><br> Place id: <span id="place_id"></span><br> Address :<span id="place_address"></span><br> Phone : <span id="phone_no"></span><br> Openhours: <span id="open_time"></span><br> Open Now : <span id="open_now"></span><br> website : <span id="website"></span><br> photo :<br> <img id="photo" src="" style="display:none;" />
</div>
<div id="map"></div>
<div id="infowindow-content">
<span id="place-name" class="title"></span><br>
<strong>Place ID:</strong> <span id="place-id"></span><br>
<span id="place-address"></span>
</div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap">
</script>
Related
So, I'm making a bunch of webpages for different communities, and on each I want to have a little weather box that I can customize, just with the name of the town, the current temperature, and the current weather condition. I want to be able to style it all exactly how I want. I found this site called Open Weather Map that seems to do exactly what I want. The problem is that I don't know how to use JSON. It's probably easy, but I seem to have gotten lost on any online tutorials I've tried.
This is an example of a URL for the page, that loads some JSON. http://api.openweathermap.org/data/2.5/weather?q=London,uk
I could just include this in my file and dynamically change the city and the country code to get the city I want. But how do I load this into my weather box? Let's say this is what I have:
<div class="weatherbox">
<strong class="city>{CITY NAME HERE}</strong>
<span class="temperature">{X} °C</span>
<p class="weatherdescription>{WEATHER DESCRIPTION HERE}</p>
</div>
Then how do I access the data from the JSON? I want it to be done as simply as possible. Do I include the file like this to have access to the object, or is it more complicated?
<script type="javascript" src="http://api.openweathermap.org/data/2.5/weather?q=London,uk"></script>
from your line of code:
<script type="javascript" src="http://api.openweathermap.org/data/2.5/weather?q=London,uk"></script>
this is incorrect, the api is returning JSON, it is not a javascript file so you don't access it in such a manner. Note that their API appears to take the city and country as a part of the URL parameters, so this you will need to plug in for the appropriate city/country.
For your specific question you could do something like:
var jsonData;
$(document).ready(function ()
{
$.getJSON('http://api.openweathermap.org/data/2.5/weather?q=London,uk', function(data) {
jsonData = data;
$('.city').text(jsonData.name);
// etc
});
});
See http://jsfiddle.net/jsxm7j3n/1/ for it in action.
Note in order to understand the JSON, you can run it through a JSON parser such as the one at http://json.parser.online.fr/ - this will allow you to better understand the make up of what you're receiving back, and how to parse it.
Double note: forgot to mention this solution uses JQuery - i believe there are purely javascript ways to pull it off, but it will be much more verbose and (in my opinion) harder to understand.
Assuming jQuery:
<script>
// Load the data through ajax, not by including it like a script:
$.get('http://api.openweathermap.org/data/2.5/weather?q=London,uk', function(data) {
$('.weatherbox .temperature').text(data.main.temp);
});
</script>
When you look at the response headers from the URL to the API, it is sending 2 important headers:
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: *
This means:
Return JSON object, not just a file. You don't have to use JSON.parse() or $.getJSON then.
Allow anyone to request it via ajax (security aspect of Ajax).
Because Ajax by default is async, (that's what the A stands for), you need to wrap your assignment into a function, which is executed after the request has finished.
The following Code runs. You must only change the Api Key
A full Tutorial: https://www.revilodesign.de/blog/sonstiges/wetterdaten-mit-openweathermap-api-in-eigene-webseite-einbinden/
// API URL
var apiUrl = 'https://api.openweathermap.org/data/2.5/weather?q=London,uk&units=metric&APPID=YOUR_API_KEY';
// AJAX
jQuery.ajax ({
url: apiUrl,
type: 'GET',
dataType: 'jsonp',
success: function(data) {
console.log(data);
// COORDINATES
var coordLat = data.coord.lat;
var coordLng = data.coord.lon;
// WEATHER
var weatherId = data.weather[0].id;
var weatherMain = data.weather[0].main;
var weatherDesc = data.weather[0].description;
var weatherIcon = '<img src="https://openweathermap.org/img/w/' + data.weather[0].icon + '.png" />';
var weatherBg = data.weather[0].icon;
// BASE
var baseData = data.base;
// TEMP
var mainTemp = data.main.temp;
var mainPressure = data.main.pressure;
var mainHumidity = data.main.humidity;
var mainTempMin = data.main.temp_min;
var mainTempMax = data.main.temp_max;
// VISIBILITY
var visibility = data.visibility;
// WIND
var windSpeed = data.wind.speed;
var windDeg = data.wind.deg;
// CLOUDS
var clouds = data.clouds.all;
// DT
var dt = data.dt;
// SYS
var sysType = data.sys.type;
var sysId = data.sys.id;
var sysMessage = data.sys.message;
var sysCountry = data.sys.country;
var sysSunrise = data.sys.sunrise;
var sysSunset = data.sys.sunset;
// ID
var id = data.id;
// NAME
var name = data.name;
// COD
var cod = data.cod;
jQuery('#city').html( name );
jQuery('#temp').html( mainTemp + '° C' );
jQuery('#desc').html( weatherDesc );
}
});
#weatherbox {
width: 200px;
height: 20px;
background: #b4ecff;
border-radius: 8px;
display: table;
margin: 20px auto;
text-align: center;
font-size: 14px;
line-height: 20px;
overflow:hidden;
padding: 0 0 10px 0;
}
strong,
span {
width: 100%;
display: inline-block;
padding: 10px 0;
margin: 0;
}
p {
padding: 0;
margin: 0
}
strong {
background: #00769d;
color: #fff;
text-transform: uppercase;
letter-spacing: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="weatherbox">
<strong id="city"></strong>
<span id="temp"></span>
<p id="desc"></p>
</div>
Good day,
Does anyone have an idea of how to change a bing map to google map api code. I have found a very useful code on line that is coded using bing maps and would like to change it to work with google maps. if found the code here: http://blogs.msdn.com/b/crm/archive/2011/01/19/custom-charting-capabilities-in-microsoft-dynamics-crm-2011.aspx
Code below:
<html>
<head>
<title>Accounts on Bing Maps</title>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>
<script type="text/javascript">
var map;
// Function to construct key-value pairs from a query string.
function getParametersFromQuery(query) {
var parametersDictionary = new Array();
var parameters = query.split('&');
for (var i = 0; i < parameters.length; i++) {
var keyAndValue = parameters[i].split('=');
parametersDictionary[unescape(keyAndValue[0])] = unescape(keyAndValue[1]);
}
return parametersDictionary;
}
// Function that makes a GET request to the CRM REST end-point, and invokes a callback with the results.
function retrieveFromCrmRestApi(url, callback) {
$.ajax({
type: "GET",
url: GetGlobalContext().getServerUrl() + "/XRMServices/2011/OrganizationData.svc" + url,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
callback(data.d);
}
});
}
// Function that retrieves the corresponding CRM chart, and invokes the callback when successful.
function loadChartFromCrm(callback) {
var parameters = getParametersFromQuery(window.location.search.substring(1));
parameters = getParametersFromQuery(parameters["data"]);
var id = parameters["visid"].substr(1, 36);
var type = parameters["vistype"];
var url = (type == "1111" ? "/SavedQueryVisualizationSet" : "/UserQueryVisualizationSet")
+ "(guid'" + id + "')?$select=DataDescription,PresentationDescription";
retrieveFromCrmRestApi(url, callback);
}
var locations = new Array();
function plotAccountLocations(accounts) {
if (accounts.length > 0) {
var account = accounts.pop();
var address = account.Address1_City + ', ' + account.Address1_Country;
map.Find(null, address, null, null, 0, 1, false, false, false, false,
function (shapeLayer, results, places, moreResults, error) {
if (null != places && places.length > 0) {
var place = places[0];
var newShape = new VEShape(VEShapeType.Pushpin, place.LatLong);
newShape.SetTitle(account.Name);
newShape.SetDescription(address);
locations.push(newShape);
}
// When we have found (or not found) the current account,
// recursively call the same function to find the next one.
plotAccountLocations(accounts);
});
}
else {
var shapeLayer = new VEShapeLayer();
map.AddShapeLayer(shapeLayer);
shapeLayer.AddShape(locations);
}
}
function loadAccountsFromCrm(dataDescription) {
var url = "/AccountSet?$select=Address1_Country,Address1_City,Name";
if (null != dataDescription) {
// Filter accounts based on country specified in data description.
url += "&$filter=Address1_Country eq '" + dataDescription + "'";
}
retrieveFromCrmRestApi(url,
function (data) {
var results = data["results"];
var accounts = new Array();
for (resultKey in results) {
accounts.push(results[resultKey]);
}
// Once accounts are retrieved from CRM Server, plot their locations on map.
plotAccountLocations(accounts);
}
);
}
function getMap(presentationDescription) {
// Set center and zoom defaults.
var center = null;
var zoom = 4;
if (null != presentationDescription) {
// Calculate map-center and zoom from the presentation description.
var arguments = presentationDescription.split(',');
if (arguments.length > 1) {
center = new VELatLong(arguments[0], arguments[1]);
}
if (arguments.length > 2) {
zoom = arguments[2];
}
}
map = new VEMap("map");
map.LoadMap(center, zoom, VEMapStyle.Road, true, VEMapMode.Mode2D, false, 0);
window.onresize = function (event) { map.Resize(document.body.clientWidth, document.body.clientHeight); };
window.onresize(null);
}
function loadMap() {
// First, get the chart object from CRM Server.
loadChartFromCrm(
function (chart) {
// Once we have retrieved the chart, format the map based on the chart's presentation description.
getMap(chart.PresentationDescription);
// Get Accounts from CRM Server based on the chart's data description, and plot them on the map.
loadAccountsFromCrm(chart.DataDescription);
}
);
}
</script>
</head>
<body onload="loadMap()">
<div id="map"></div>
</body>
</html>
There is no easy out of the box solution for what you are looking for.
Google API has many differences. For example, the Google API leaves keeping track of map children to the programmer (you). There is no means of looping through the map controls like there is with the Bing API. This means that your solution for saving the map content and re-displaying it will be a little different.
Although, since both API's are done via javascript, all you need to do is convert your functionality according to their documentation;
Geocoding Sample
Simple Map Initialization
Adding Shapes
Adding Markers (pushpin)
I've been playing with Google Spreadsheets and Fusion Tables to create maps, but I'm want to do some things that involve a bit more coding and hope you help refine my approach.
Essentially, I've used Spreadsheets to scrape the GP and Chemist data from the UK NHS Local sites and used Fusion Tables to geocode it (https://www.google.com/fusiontables/DataSource?docid=1xmT0D6H6JjRlXVyetubasugqQMswJqKNH7nrKh4).
What I'm trying to do now is use the Google Maps Api to publish the Fusion Table data but then add controls so that users can filter out the bits they don't want. I know how to create the custom buttons, what I can't work out is how to create queries if a button is clicked.
It's something that would be massively useful so if you can help that would be great.
My efforts so far are below:
http://davidelks.com/MashupTests/gmapsTest.html
<script type="text/javascript">
var map, infoWindow;
var toggle_doctors = 'false';
var toggle_chemists = 'false';
$(document).ready(function(){
infoWindow = new google.maps.InfoWindow({});
map = new GMaps({
div: '#map',
lat: 53.023098,
lng: -2.197793,
zoom: 11
});
var doctors = map.addControl({
position: 'left_bottom',
text: 'GPs',
style: {
margin: '1px',
padding: '1px 6px',
border: 'solid 1px #717B87',
width: '85px',
background: '#99ff99'
},
events: {
click: function(){
if (toggle_doctors == 'true'){
toggle_doctors = 'false';
doctors.style.backgroundColor = '#ffffff';
}
else {
toggle_doctors = 'true';
doctors.style.backgroundColor ='#99ff99';
}
}
}
});
var chemists = map.addControl({
position: 'left_bottom',
text: 'Late chemists',
style: {
margin: '1px',
width: '85px',
padding: '1px 6px',
border: 'solid 1px #717B87',
background: '#9999ff'
},
events: {
// toggle button between white and colour
click: function(){
if (toggle_chemists == 'true'){
toggle_chemists = 'false';
chemists.style.backgroundColor = '#ffffff';
}
else {
toggle_chemists = 'true';
chemists.style.backgroundColor ='#9999ff';
}
}
}
});
map.loadFromFusionTables({
query: {
select: '*',
from: '1xmT0D6H6JjRlXVyetubasugqQMswJqKNH7nrKh4',
where: 'TYPE == \'GP\''
},
events: {
click: function(point){
infoWindow.setPosition(point.latLng);
infoWindow.open(map.map);
}
}
});
});//end of code block
</script>
<div id="map" style="height: 500px; width: 300px; border: 1px;"></div>
Recommend you look at Derek Eders web site, as he has a template that allows for selecting sub-sets of underlying fusion table data to a map...I've leveraged it for several things, and it works great.
derekeder.com/searchable_map_template/
Try the FusionTablesLayerWizard
I'm trying to create a progress bar in Google app scripting , which when some one click a button (Go) it will be automatically, slowly go to start to end . Something you see in Firefox download window.
this is my code.
function doGet(e) {
var app = UiApp.createApplication();
var progressPanel = app.loadComponent("progressbar_auto");
var gobutton =app.getElementById("go_btn");
var go_btn_handler =app.createServerHandler("updateProgressbar");
go_btn_handler.addCallbackElement(gobutton);
gobutton.addClickHandler(go_btn_handler)
app.add(progressPanel);
return app;
}
//function time(i){
// Utilities.sleep(5);
// }
function updateProgressbar(){
var app = UiApp.getActiveApplication()
for(var i =1 ; i < 250 ; i++ ){
app.getElementById("progress").setWidth(i + 'px');
time();
}
Logger.log(i);
return app;
}
But according to this code for loop will execute very speedy & ,progress bar completed very quick . Is there any way to slow this.
You can find the my application here.
https://sites.google.com/a/macros/dewdynamics.net/exec?service=AKfycbztKB_ljMBGi_55RrK_DH3x_pRZQ993bDoAHSsxDA
Is there any way to add a slide bar , to control the progress bar. Something we can do in php or HTML 5.
Thanks
Why don't you use HtmlServices for this. Just try it:
Click Here
You can use jquery to implement this.
Updated answer: to get the status of scripts running server side, you need to store progress to the cache. Then the client side can call a server-side function to retrieve it. https://developers.google.com/apps-script/reference/cache/cache-service
No, there isn't a real way to do a progress bar on Apps Script.
There's some workarounds though. You can add multiple handlers to the same button, and in each one, with a different sleep time, you can update the GUI many times. Or, as most do, show an endless progress gif animation in a client handler (for instant feedback) and after your second handler finishes, a ServerHandler where you actually do the work, you hide the image and return the results.
I worked out a solution by storing data in the cache on the server side and reading the cache on the client side as suggested by Greg.
Screenshot
Video
Caching progress data server side
var cache = CacheService.getScriptCache();
async function updateCacheProgress(current, total, student) {
// cache for 10 seconds
cache.put("total", total, 10);
cache.put("current", current, 10);
cache.put("student", student, 10);
}
Script on client side
window.addEventListener('load', getUpdatedProcess);
function updateProgress(data) {
console.log('#student: ' + data.student)
console.log('#current: ' + data.current)
console.log('#total: ' + data.total)
var ProgressBar = document.getElementById('progressBar');
var Progress = document.getElementById('progress');
var ProgressStatus = document.getElementById('progressStatus');
var percent = 0.1
percent = data.current / data.total *100;
percent = percent.toFixed(1);
Progress.style.width = percent + '%';
Progress.innerText = percent + '%';
ProgressStatus.innerHTML = data.student + ` (${data.current} of ${data.total})`
if(percent < 100) getUpdatedProcess()
}
function getUpdatedProcess() {
google.script.run.withSuccessHandler(updateProgress).getProgress();
}
Apps Script that retrieves stored cache executed via client
function getProgress() {
var total = cache.get("total");
var current = cache.get("current");
var student = cache.get("student");
return {total: total, current: current, student: student}
}
Client HTML
<html>
<head>
<base target="_top">
<style>
* {
font-family: 'Arial';
}
#progressBar {
width: 100%;
background-color: silver;
}
#progress {
width: 0%;
height: 30px;
line-height: 32px;
text-align: center;
color: white;
background-color: green;
}
#progressStatus {
}
</style>
</head>
<body>
<div id="progressBar">
<div id="progress"></div>
</div>
<br><br>
<div id="progressStatus"><?= student ?> (<?= progress ?>)</div>
</body>
</html>
I tried Google place API, it's returning phone for a place "formatted_phone_number" or "international_phone_number".
But it is not returning for all places (just for 1 in 100 places). But, Currently I want to get phone number for each place (For example :- Hotel ).
I will send the Latitude and Longitude information to API it need to return nearest Hotel address and Phone number as well.
Please suggestion me better API for this.
Quality of the data (such as phone numbers) that you can receive from any Places API depends purely upon the quality of the data backing up that API. This will vary from vendor to vendor and coverage will differ from country to country, city to city and so on.
Your best bet here would be to run some sort of "beauty contest" to get a feel for which vendor holds the best data set that is relevant to you.
To get the phone number of a place using the Nokia RESTful Places API for example, is a two stage process:
make a general category query e.g "Hotels" near "Mumbai"
http://places.nlp.nokia.com/places/v1/discover/search?at=18.975%2C72.825833&q=hotel&tf=plain&pretty=y&size=10&app_id=_peU-uCkp-j8ovkzFGNU&app_code=gBoUkAMoxoqIWfxWA5DuMQ
Take the placeId, and query for more information such as contacts.phone
http://places.nlp.nokia.com/places/v1/places/356te7gc-e5c2e62e24254695b4e41c7762ded586;context=Zmxvdy1pZD03NTAwNzM3ZS1mZmEwLTU0ZDgtYjBkZC1lYjgwMDZmMGE2NDBfMTM1OTcwODg5MDQzNl8wXzU2ODAmcmFuaz0x?app_id=_peU-uCkp-j8ovkzFGNU&app_code=gBoUkAMoxoqIWfxWA5DuMQ
Again not all places will contain phone information. Now you could chain the response from the first request to loop through the placeIds received and place the phone numbers on screen.
An alternative would be to use the existing JavaScript API wrapper to display information as shown in the code below, you'll need your own app id and token to get it to work
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
Example from Nokia Maps API Playground, for more information visit http://api.maps.nokia.com
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=7; IE=EmulateIE9"/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Nokia Maps API Example: Search by category</title>
<meta name="description" content="Search by category"/>
<meta name="keywords" content="search, services, places, category"/>
<!-- For scaling content for mobile devices, setting the viewport to the width of the device-->
<meta name=viewport content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<!-- By default we add ?with=all to load every package available, it's better to change this parameter to your use case. Options ?with=maps|positioning|places|placesdata|directions|datarendering|all -->
<script type="text/javascript" charset="UTF-8" src="http://api.maps.nokia.com/2.2.3/jsl.js?with=all"></script>
<!-- JavaScript for example container (NoteContainer & Logger) -->
<style type="text/css">
html {
overflow:hidden;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
width: 100%;
height: 100%;
position: absolute;
}
#mapContainer {
width: 40%;
height: 80%;
left: 0;
top: 0;
position: absolute;
}
#progress {
width: 80%;
height: 10%;
left: 0;
top: 80%;
position: absolute;
}
#buttons {
width: 80%;
height: 10%;
left: 0;
top: 90%;
position: absolute;
}
</style>
</head>
<body>
<div id="mapContainer"></div>
<div id="progress"></div>
<div id="buttons">
<a onClick="searchByCategory( map.center, 'bookshop' );return false;" href="#">Find Hotels</a>
<div style="display:block">
<div id="csPlaceWidget" style="display:none"></div>
</div>
</div>
<script type="text/javascript" id="exampleJsSource">
/* Set authentication token and appid
* WARNING: this is a demo-only key
* please register on http://api.developer.nokia.com/
* and obtain your own developer's API key
*/
nokia.Settings.set("appId", "My App Id");
nokia.Settings.set("authenticationToken", "My Token");
// Get the DOM node to which we will append the map
var mapContainer = document.getElementById("mapContainer");
var infoBubbles = new nokia.maps.map.component.InfoBubbles();
// Create a map inside the map container DOM node
var map = new nokia.maps.map.Display(mapContainer, {
// Initial center and zoom level of the map
center: [18.975, 72.825833],
zoomLevel: 10,
components: [ infoBubbles,
new nokia.maps.map.component.Behavior()
]
});
var searchManager = nokia.places.search.manager,
resultSet;
var defaultHandler = function (evt) {
console.log(evt.target);
infoBubbles.openBubble('<h3>' +evt.target.title + '</h3>' + evt.target.vicinity + '<br/>'
+ '<a onclick="getPhoneNumber(\'' + evt.target.placeId +'\')" >Get Phone</a>' ,evt.target.position)
};
var myData;
var searchCat;
var maxDistance = 0;
var getPhoneNumber = function (placeId){
nokia.places.manager.getPlaceData({
placeId: placeId,
basicInfo: true,
onComplete: function (data, status) {
if ( data.contacts.phone === undefined ){
alert ("Unknown");
} else {
alert(data.contacts.phone[0].value);
}
}
});
};
// Function for receiving search results from places search and process them
var processResults = function (data, requestStatus, requestId) {
var i, len, locations, marker;
myData = data;
if (requestStatus == "OK") {
// The function findPlaces() and reverseGeoCode() of return results in slightly different formats
locations = data.results ? data.results.items : [data.location];
// We check that at least one location has been found
if (locations.length > 0) {
// Remove results from previous search from the map
if (resultSet) map.objects.remove(resultSet);
// Convert all found locations into a set of markers
resultSet = new nokia.maps.map.Container();
for (i = 0, len = locations.length; i < len; i++) {
marker = new nokia.maps.map.StandardMarker(locations[i].position, { text: i+1 });
marker.title = locations[i].title;
marker.position = locations[i].position;
marker.vicinity = locations[i].vicinity;
marker.placeId = locations[i].placeId;
marker.addListener("click", defaultHandler);
resultSet.objects.add(marker);
if (locations[i].distance > maxDistance){
maxDistance = locations[i].distance;
}
}
// Next we add the marker(s) to the map's object collection so they will be rendered onto the map
map.objects.add(resultSet);
// We zoom the map to a view that encapsulates all the markers into map's viewport
map.zoomTo(resultSet.getBoundingBox(), false);
progressUiElt.innerHTML = locations.length + " places found in the '" + searchCat + "' category within " + maxDistance + "m of "+ data.search.location.address.city ;
} else {
alert("Your search produced no results!");
}
} else {
alert("The search request failed");
}
};
// Binding of DOM elements to several variables so we can install event handlers.
var progressUiElt = document.getElementById("progress");
searchByCategory = function(searchCenter , category){
// Make a place search request
searchCat = category;
progressUiElt.innerHTML = "Looking for places in the '" + category + "' category...'";
searchManager.findPlacesByCategory({
category: category,
onComplete: processResults,
searchCenter: searchCenter,
limit: 100,
});
}
// Search for Hotels in Mumbai
searchByCategory( new nokia.maps.geo.Coordinate(18.975, 72.825833), "hotel" );
</script>
</body>
</html>
The data from the JavaScript API can be seen below:
Regarding phone numbers, please bear in mind the Restrictions from the Terms and Conditions
(ii) You will not copy, translate, modify, or create a derivative work
(including creating or contributing to a database) of, or publicly
display any Content or any part thereof except as explicitly permitted
under this Agreement. For example, the following are prohibited:
...
(iii) creating mailing lists or telemarketing lists based on the Content; or
(iv) exporting, writing, or saving the Content to a third party's
location-based platform or service ;