I’m wondering if there is a way to connect Kintone Javascript to Google Maps API so we can use their functions. I’ve been trying it so far with no luck.
Hello James,
It is definitely possible to use Google Maps API in Kintone JavaScript customization. However, there is no detailed article written about it.
Though it should be possible by enabling Google Maps to call document.write
after onload event and loading the Google API library (https://maps-api-ssl.google.com/maps/api/js?v=3&sensor=false).
Kintone Developer Program has two map-related tutorials:
There is a Japanese article about using Google Maps API in Kintone JavaScript customization:
Here is the relevant code with comments translated into English:
/*
* Map display sample program
* Copyright (c) 2013 Cybozu
* Licensed under the MIT License
*/
(() => {
'use strict';
// Google Maps API Key
const api_key = 'Your Google API key';
// Add the element to the header
const load = (src) => {
const head = document.getElementsByTagName('head')[0];
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
head.appendChild(script);
};
// Execute the Google Maps API
const loadGMap = () => {
// Define document.write
const nativeWrite = document.write;
document.write = (html) => {
const m = html.match(/script.+src="([^"]+)"/);
if (m) {
load(m[1]);
} else {
nativeWrite(html);
}
};
// Load the Google Map API library
load('https://maps.googleapis.com/maps/api/js?v=3&key=' + api_key);
};
// Display a map using the value of the address field in the record display event
kintone.events.on('app.record.detail.show', (event) => {
// Based on the address information, display the map below the address field
const drawMap = () => {
if (kintone.app.record.getFieldElement('address').length === 0) {
return;
}
// Verify that a "map_address" named element does not already exist
if (document.getElementsByName('map_address').length !== 0) {
return;
}
// Create a div element to display the map
const mapAddressEl = document.createElement('div');
mapAddressEl.setAttribute('id', 'map_address');
mapAddressEl.setAttribute('name', 'map_address');
// Add the element, set by mapAddressEl, to the space field placed in the "address_field" field
const space = kintone.app.record.getSpaceElement('Map');
space.appendChild(mapAddressEl);
// Define a Google Geocoder
const gc = new google.maps.Geocoder();
// Get the value from the "address_field" field
const rec = kintone.app.record.get();
const addressValue = rec.record.address_field.value;
// Execute the Geocoding API
gc.geocode({
address: addressValue,
language: 'en',
country: 'US'
}, (results, status) => {
if (status === google.maps.GeocoderStatus.OK) {
// Specify the size of map elements
mapAddressEl.setAttribute('style', 'width: 300px; height: 250px');
const point = results[0].geometry.location;
const address = results[0].formatted_address;
// Set the map display settings (center position, zoom size, etc.)
const opts = {
zoom: 15,
center: point,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true
};
const map = new google.maps.Map(document.getElementById('map_address'), opts);
// Set the marker
new google.maps.Marker({
position: point,
map: map,
title: address
});
}
});
};
// Wait for Google Map to load
const waitLoaded = (_timeout, interval) => {
setTimeout(() => {
const timeout = _timeout - interval;
if ((typeof google !== 'undefined')
&& (typeof google.maps !== 'undefined')
&& (typeof google.maps.version !== 'undefined')) {
drawMap(); // Show map based on address
} else if (_timeout > 0) {
waitLoaded(timeout, interval);
}
}, interval);
};
if (document.getElementsByName('map_latlng').length === 0) {
loadGMap();
waitLoaded(10 * 1000, 100);
}
});
})();
Above code will require the following in the Kintone App:
- Text field with
address_field
as the field code - Space field with
Map
as the field code
I have looked at those documents and what I want is not to display a map, but instead use the Distance Matrix API from Google so I can calculate the distance between two locations so we can use that to track gas mileage.
I’m wondering if their’s a way that I can just connect to my API key and then access different API’s that way such as:
var geocoder =new google.maps.Geocoder();
var service =new google.maps.DistanceMatrixService();
I’m still working out a full solution, but I found many more helpful examples on the Cybozu developer website. I just had to use Chrome to translate the page to English from Japanese automatically, but they have a lot of good examples, such as this one:
Geolocation API(位置情報)を使ったモバイル用のカスタマイズをしよう – cybozu developer network
I’ll post a full solution once I finish.
I’ve figured out how to connect to Google Maps API and both the Distance Matrix Service and the Geocoder.
With help from Kintone’s Japanese Developer tutorial: 住所から地図を表示する - cybozu developer network
I was able to get it started and figure out the rest.
Like in the above article, I downloaded the customer database template that is already provided in Kintone.
Then, instead of adding a space field, I added a second label field across from the one already present and gave it a field name of address2
and changed the label header to End Address as well.
Here’s my full code for those that need help as well:
(() => {
'use strict';
// Google Maps API Key
const api_key = 'Your Google API key';
// Add the element to the header
const load = (src) => {
const head = document.getElementsByTagName('head')[0];
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
head.appendChild(script);
};
// Execute the Google Maps API
const loadGMap = () => {
// Define document.write
const nativeWrite = document.write;
document.write = (html) => {
const m = html.match(/script.+src="([^"]+)"/);
if (m) {
load(m[1]);
} else {
nativeWrite(html);
}
};
// Load the Google Map API library
load('https://maps.googleapis.com/maps/api/js?v=3&key=' + api_key);
};
// Display a map using the value of the address field in the record display event
kintone.events.on('app.record.detail.show', (event) => {
// Based on the address information, display the map below the address field
const drawMap = () => {
if (kintone.app.record.getFieldElement('address').length === 0) {
return;
}
// Verify that a "map_address" named element does not already exist
if (document.getElementsByName('map_address').length !== 0) {
return;
}
// Create a div element to display the map
const mapAddressEl = document.createElement('div');
mapAddressEl.setAttribute('id', 'map_address');
mapAddressEl.setAttribute('name', 'map_address');
// Add the element, set by mapAddressEl, to the space field placed in the "address_field" field
const space = kintone.app.record.getSpaceElement('Map');
space.appendChild(mapAddressEl);
// Define a Google Geocoder
const gc = new google.maps.Geocoder();
// Get the value from the "address_field" field
const rec = kintone.app.record.get();
const addressValue = rec.record.address_field.value;
// Execute the Geocoding API
gc.geocode({
address: addressValue,
language: 'en',
country: 'US'
}, (results, status) => {
if (status === google.maps.GeocoderStatus.OK) {
// Specify the size of map elements
mapAddressEl.setAttribute('style', 'width: 300px; height: 250px');
const point = results[0].geometry.location;
const address = results[0].formatted_address;
// Set the map display settings (center position, zoom size, etc.)
const opts = {
zoom: 15,
center: point,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true
};
const map = new google.maps.Map(document.getElementById('map_address'), opts);
// Set the marker
new google.maps.Marker({
position: point,
map: map,
title: address
});
}
});
};
// Wait for Google Maps to load
const waitLoaded = (_timeout, interval) => {
setTimeout(() => {
const timeout = _timeout - interval;
if ((typeof google !== 'undefined')
&& (typeof google.maps !== 'undefined')
&& (typeof google.maps.version !== 'undefined')) {
drawMap(); // Show map based on address
} else if (_timeout > 0) {
waitLoaded(timeout, interval);
}
}, interval);
};
if (document.getElementsByName('map_latlng').length === 0) {
loadGMap();
waitLoaded(10 * 1000, 100);
}
});
})();