How to show the chart dynamically in phonegap application back end sqlite? - jquery-mobile

I'm doing an app using Phonegap (Cordova) and I'm using jquery mobile for that. I want to know how show the chart dynamically. The data of chart will retrieve from sqlite database. The chart will be in pie chart. Please help me.

You should try google charts
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var sqlitedata ;
//var data = google.visualization.arrayToDataTable(
// [
// ['Task', 'Hours per Day'],
// ['Work', 11],
// ['Eat', 2],
// ['Commute', 2],
// ['Watch TV', 2],
// ['Sleep', 7]
// ]
// );
var data = google.visualization.arrayToDataTable(sqlitedata );
var options = {
title: 'My Daily Activities'
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
// Wait for device API libraries to load
document.addEventListener("deviceready", onDeviceReady, false);
// Populate the database
//
function populateDB(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');//comments this line after first user
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');//comments this line after first user
}
// Query the database
//
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
// Query the success callback
function querySuccess(tx, results) {
var len = results.rows.length;
var row;
console.log("DEMO table: " + len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data = " + results.rows.item(i).data);
// get your two columns here and insert it on
sqlitedata="[[" + row[0].item(i) + "], [" + row[1].item(i) + "]]"
}
}
// Transaction error callback
//
function errorCB(err) {
console.log("Error processing SQL: "+err.code);
}
// Transaction success callback
//
function successCB() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(queryDB, errorCB);
}
// device APIs are available
//
function onDeviceReady() {
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(populateDB, errorCB, successCB);
}
</script>
</head>
<body>
<div id="piechart" style="width: 900px; height: 500px;"></div>
</body>
</html>
for fetching data please read phonegap document

Related

How to clear the google map markers before refreshing with a new map? [duplicate]

This question already has answers here:
Google Maps API v3: How to remove all markers?
(32 answers)
Closed 4 years ago.
Could someone be kind enough to share how I can clear the markers in google map before refreshing it with a new set of markers?
In my map, I'm adding markers from an array that contains name, lat and long. The name can be picked from a drop down menu, and then all the markers for that name are added to the page.
Prtoject : Asp.Net Mvc
Link image: https://i.hizliresim.com/V927Py.jpg
When the user adds markers, the previous set of markers remain. I'd like to remove any existing markers before adding the new set.
After reading the documentation, I tried this:
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model List<Project_Map.Models.KONUM>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Complex Marker Icons</title>
<style>
/* 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;
}
</style>
</head>
<body>
<style>
#map_wrapper {
height: 700px;
}
#map_canvas {
width: 100%;
height: 100%;
}
</style>
<div id="map_wrapper">
<div class="mapping" id="map_canvas">
</div>
</div>
<div id="map"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
jQuery(function ($) {
var script = document.createElement('script');
script.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyBT56XlfxnK2OB4K93vWdrZci_CKjZyQOM&callback=initMap";
document.body.appendChild(script);
});
</script>
<!-- Google Maps Kodu -->
<script type="text/javascript">
var contentString = '<div id="content">' +
'<div id="siteNotice">' +
'<img src="#IMG_SRC#" />' +
'</div>' +
//'<h2 id="firstHeading" class="firstHeading">#PERSONEL#</h2>' +
'<div id="bodyContent">' +
'<b>Mesafe: </b>#MESAFE# Km<br />' +
'<b>Tarih: </b> #TARIH#' +
'</p>' +
'</div>' +
'</div>';
$(document).ready(function () {
initMap();
});
function initMap() {
var mapCenter = { lat: 39.684536, lng: 35.337094 };
var map = new google.maps.Map(document.getElementById('map_wrapper'), {
zoom: 6,// haritanın yakınlık derecesi
center: mapCenter, // haritanın merkezi
mapTypeId: google.maps.MapTypeId.HYBRID
});
var infoWindow = new google.maps.InfoWindow();
setInterval(function () {
$.ajax({
url: '#Url.Action("GetMapLocations", "Konum")',
type: "POST",
success: function (data) {
var json = JSON.parse(data);
for (var i = 0; i < json.length; i++) {
var position = {
lat: parseFloat(json[i].lat.replace(',', '.')),
lng: parseFloat(json[i].lng.replace(',', '.'))
};
var marker = new google.maps.Marker({
position: position,
animation: google.maps.Animation.BOUNCE,
map: map,
});
// infoWindow içeriğini replace et
var cs = contentString;
cs = cs.replace("#PERSONEL#", json[i].name);
cs = cs.replace("#MESAFE#", json[i].mesafe);
cs = cs.replace("#TARIH#", json[i].tarih);
cs = cs.replace("#IMG_SRC#", json[i].img);
google.maps.event.addListener(marker, 'click', (function (marker, cs, infoWindow) {
return function () {
infoWindow.setContent(cs);
infoWindow.open(map, this);
passive: true;
};
})(marker, cs, infoWindow));
};
},
error: function (data) { alert("Malesef Sunucunuza Ulaşamıyoruz. Lütfen Tekrar Deneyiniz..."); },
});
}, 5000);
};
</script>
</body>
</html>
You have to set up an array, where you can store the added marker
var gmarkers = [];
If you add a marker you have to store the marker object in the array.
gmarkers.push(marker);
If you want to remove these markers you can use something like:
function removeMarker() {
if (gmarkers.length > 0) {
for (var i=0; i<gmarkers.length; i++) {
if (gmarkers[i] != null) {
gmarkers[i].setMap(null);
}
}
}
gmarkers = [];
}

Mapbox GL Directions - mapboxgl.Directions is not a constructor

I have an issue with mapbox direction plugin, on a rails app. When I load the page where the map is, I have this error :
Uncaught TypeError: mapboxgl.Directions is not a constructor
at HTMLDocument.<anonymous> (travel.self-10030a4….js?body=1:34)
at fire (jquery.self-bd7ddd3….js?body=1:3233)
at Object.fireWith [as resolveWith] (jquery.self-bd7ddd3….js?body=1:3363)
at Function.ready (jquery.self-bd7ddd3….js?body=1:3583)
at HTMLDocument.completed (jquery.self-bd7ddd3….js?body=1:3618)
Here is the code for my map :
var map;
var directions;
// token access for MAPBOX GL
mapboxgl.accessToken = 'pk.eyJ1IjoiYW50b3RvIiwiYSI6ImNpdm15YmNwNTAwMDUyb3FwbzlzeWluZHcifQ.r44fcNU5pnX3-mYYM495Fw';
// generate map
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v10',
center: [-96, 37.8],
zoom: 5
});
// center map on selected marker
map.on('click', 'markers', function (e) {
map.flyTo({center: e.features[0].geometry.coordinates});
});
// change mouse action on enter / leave in marker
map.on('mouseenter', 'markers', function () {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'markers', function () {
map.getCanvas().style.cursor = '';
});
// Directions
var directions = new mapboxgl.Directions({
unit: 'metric',
profile: 'driving',
container: 'directions'
});
$.ajax({
dataType: 'json',
url: grabTravelData(),
success: function(data) {
geojson = data;
map.addSource("markers", {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": data
}
});
map.addLayer({
"id": "markers",
"type": "circle",
"source": "markers",
"paint": {
"circle-radius": 7,
"circle-color": "#ff7e5f"
},
});
// center map on markers
var bounds = new mapboxgl.LngLatBounds();
data.forEach(function(feature) {
bounds.extend(feature.geometry.coordinates);
});
map.fitBounds(bounds);
// test - set direction for each marker to following marker
for(var i = 0; i < data.lenght; i++) {
var last = data.length - 1
var from = data[i];
var to = data[i + 1];
directions.setOrigin(from);
if(to != from) {
directions.setDestination(to);
} else {
directions.setDestination(from);
}
}
}, error: function(data) {
console.log(data + ' error');
}
});
In this code, with a for loop I try to create a routes between each markers with the following marker.
In the header of the app I import mapbox :
<script src='https://api.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css' rel='stylesheet' />
<script src="https://cdn.jsdelivr.net/places.js/1/places.min.js"></script>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v3.1.1/mapbox-gl-directions.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v3.1.1/mapbox-gl-directions.css' type='text/css' />
Doest someone know what is this error ?
The proper way to use the Mapbox GL directions is
var directions = new MapboxDirections({
accessToken: 'YOUR-MAPBOX-ACCESS-TOKEN',
unit: 'metric',
profile: 'cycling'
});
map.addControl(directions);
For more details refer the API Documentation

2 queries to the same Google Sheet to Feed a Google Chart

I would like to have 2 different queries to get different data to feed 2 different charts into Google Charts.
I tried the following but it works for Columnchart_div but not for Columnchart_div1 (The second chart that I want to feed with the data from columns from G to J).
thank you very much
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawSheetName);
function drawSheetName() {
var queryString = encodeURIComponent('SELECT A, B, C, D');
var magicIncantation = '/gviz/tq?gid=0&headers=1&tq=';
var query = new google.visualization.Query('http://docs.google.com/spreadsheets/d/1xfb9trifQA5KDPc9Nh5hBL4MJ290Mxcc1Uod2VTPzYI' +
magicIncantation + queryString);
query.send(handleSampleDataQueryResponse);
var queryString1 = encodeURIComponent('SELECT G, H, I, J');
var magicIncantation = '/gviz/tq?gid=0&headers=1&tq=';
var query1 = new google.visualization.Query('http://docs.google.com/spreadsheets/d/1xfb9trifQA5KDPc9Nh5hBL4MJ290Mxcc1Uod2VTPzYI' +
magicIncantation + queryString1);
query1.send(handleSampleDataQueryResponse1);
}
function handleSampleDataQueryResponse1(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var optionsColumnChart1 = {
height: 400,
title: 'This is the title On Column Chart',
};
var data1 = response.getDataTable();
var chart1 = new google.visualization.ColumnChart(document.getElementById('Columnchart1_div'));
chart1.draw(data1, optionsColumnChart1);
}
function handleSampleDataQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var optionsColumnChart = {
height: 400,
title: 'This is the title On Column Chart',
};
var data = response.getDataTable();
var chart = new google.visualization.ColumnChart(document.getElementById('Columnchart_div'));
chart.draw(data, optionsColumnChart);
}
</script>
</head>
<body>
<div id="Columnchart_div1" style="width: 100%;"></div>
<div id="Columnchart_div" style="width: 100%;"></div>
</div>
</body>
</html>
You have to call your data twice. Try this one
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawSheetName);
function drawSheetName() {
var queryString = encodeURIComponent('SELECT A, B, C, D');
var magicIncantation = '/gviz/tq?gid=0&headers=1&tq=';
var query = new google.visualization.Query('http://docs.google.com/spreadsheets/d/1xfb9trifQA5KDPc9Nh5hBL4MJ290Mxcc1Uod2VTPzYI' +
magicIncantation + queryString);
query.send(handleSampleDataQueryResponse);
}
function handleSampleDataQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var optionsColumnChart = {
width: 1200,
height: 400,
title: 'OVERALL RATES AND VOLUMES',
legend: { position: 'top'},
bar: { groupWidth: '75%' },
is3D: true,
'hAxis': {
gridlines: {
count: 31
}
},
isStacked: true
};
var chart = new google.visualization.ColumnChart(document.getElementById('Columnchart_div'));
chart.draw(data, optionsColumnChart);
}
google.setOnLoadCallback(drawSheetName1);
function drawSheetName1() {
var queryString1 = encodeURIComponent('SELECT A, B, C, D');
var magicIncantation1 = '/gviz/tq?gid=0&headers=1&tq=';
var query1 = new google.visualization.Query('http://docs.google.com/spreadsheets/d/1xfb9trifQA5KDPc9Nh5hBL4MJ290Mxcc1Uod2VTPzYI' +
magicIncantation1 + queryString1);
query1.send(handleSampleDataQueryResponse1);
}
function handleSampleDataQueryResponse1(response1) {
if (response1.isError()) {
alert('Error in query: ' + response1.getMessage() + ' ' + response1.getDetailedMessage());
return;
}
var data1 = response1.getDataTable();
var optionsColumnChart1 = {
width: 1200,
height: 400,
title: 'OVERALL RATES AND VOLUMES',
legend: { position: 'top'},
bar: { groupWidth: '75%' },
is3D: true,
'hAxis': {
gridlines: {
count: 31
}
},
isStacked: true
};
var chart1 = new google.visualization.ColumnChart(document.getElementById('Columnchart1_div'));
chart1.draw(data1, optionsColumnChart1);
}
</script>
</head>
<body>
<div id="Columnchart_div" style=""width: 50%;"></div>
<div id="Columnchart1_div" style=""width: 50%;"></div>
</div>
</body>
</html>

Table not building

So as I'm not knowledgeable about jQuery and JavaScript I'm following the simpler method of using an array to build a table with Tablesorter. However, this is not working at all. In fact, even if I use the example provided (here: http://mottie.github.io/tablesorter/docs/example-widget-build-table.html) there is no result just a blank webpage. Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Tablesorter (fork)</title>
<!-- load tableSorter theme -->
<link href="./includes/tablesorter-master/css/theme.default.css" rel="stylesheet">
<!-- load jQuery and tableSorter scripts -->
<script type="text/javascript" src="./includes/jquery-2.1.0.js"></script>
<!-- <script src="http://code.jquery.com/jquery-1.11.0.js"></script> -->
<script type="text/javascript" src="./includes/tablesorter-master/js/jquery.tablesorter.js"></script>
<!-- load tableSorter widgets -->
<script type="text/javascript" src="./includes/tablesorter-master/js/jquery.tablesorter.widgets.js"></script>
<script type="text/javascript">
$(document).ready(function(){
// Call the PHP script that grabs all data from DB
$.getJSON('./get_data.php',function(data){
//alert(data.length);
var dataArr = new Array();
for (x = 0; x < data.length; x++)
{
dataArr[x] = data[x];
//console.log(dataArr[$x]);
}
applyTable(dataArr);
});
});
function applyTable(arrayIn)
{
//alert(arrayIn[0]);
$('#topdiv').tablesorter({
theme : 'default',
//widgets : ['zebra','columns'],
debug : true,
widgetOptions : {
build_source : arrayIn,
build_headers : {
rows : 1,
classes : [],
text : [],
widths : [ '15%', '15%', '30%', '15%', '40%', '30%', '30%', '30%', '30%', '30%' ]
}
}
});
$("#topdiv").trigger("updateAll");
}
</script>
</head>
<body>
<div id="topdiv"></div>
</body>
</html>
Any ideas? Mottie, where are you.
EDIT: Chrome reports no JavsScript errors. Though the console (since I specified "debug: true") gives:
stopping initialization! No table, thead, tbody or tablesorter has already been initialized
I also know that the PHP script is working fine.
EDIT, PHP CODE (excerpt):
$headersArr = array('ID', 'Col 2', 'Col 3',
'Col 4', 'Col 5', 'Col 6',
'Col 7', 'Col 8', 'Col 9', 'Col 10');
$allArr = array();
array_push($allArr, $headersArr);
while($row = mysql_fetch_object($rs))
{
$newRow = array($row->id, $row->col_B, $row->col_C,
$row->col_D, $row->col_E,
$row->col_F, $row->col_G,
$row->col_H, $row->col_I,
$row->col_J);
array_push($allArr, $newRow);
}
echo json_encode($jobsArr);
The following image is the JavaScript output in the Chrome console (I have not updated the code above to keep it from getting to big, but I simply repacked the array passed to applyTable() and outputted both arrays to the console). Which one of these arrays should be for use with Tablesorter?
From looking at the code, it looks like the array is just one long array.
dataArr = [ 'r0c0', 'r0c1', 'r0c2', 'r1c0', 'r1c1', 'r1c2', ... ];
It needs to be an array of row arrays:
dataArr = [
['r0c0', 'r0c1', 'r0c2'],
['r1c0', 'r1c1', 'r1c2'],
...
];
so make two loops (demo):
$(function () {
// Declare the array holding the data
var dataArr = [];
// Call the PHP script that grabs all data from DB
$.getJSON('./get_data.php', function (data) {
var i, j, row,
// you need to know how many columns
columns = 3,
// calculate how many rows
rows = Math.ceil(data.length / columns);
for (i = 0; i < rows; i++) {
// clear row array
row = [];
for (j = 0; j < columns; j++) {
row.push(data[i * columns + j]);
}
dataArr.push(row);
}
applyTable(dataArr);
});
});
function applyTable(arrayIn) {
$('#topdiv').tablesorter({
theme: 'default',
//widgets : ['zebra','columns'],
widgetOptions: {
build_source: arrayIn,
build_headers: {
rows: 1,
widths: ['33%', '33%', '33%']
}
}
});
}
And don't trigger an "updateAll" because the table was just built.
The error you mentioned is still showing up, it looks like an bug, but it's just an unintentional message, nothing else.
The table was not building due to missing the line in the HTML header:
<script type="text/javascript" src="./includes/tablesorter-master/js/widgets/widget-build-table.js"></script>
The PHP script is absolutely fine. The only JavaScript req'd is:
$(document).ready(function(){
$.getJSON('./get_data.php',function(data){
applyTable(data);
});
});
function applyTable(arrayIn){
$('#topdiv').tablesorter({
theme: 'default',
//widgets : ['zebra','columns'],
debug: true,
widgetOptions: {
build_source: arrayIn,
build_headers: {
rows: 1
}
}
});

403 Forbidden when trying to access a merged Fusion Table

I'm getting a 403 Forbidden error when trying to access a merged Fusion Table with the code below. Nor I understand why neither how to resolve this.
Accessing the table that has been merged with another table works like a charme.
The merged table as well as the base tables are publicly downloadable.
Anyone knows what could be wrong?? Is accessing merged tables somehow restricted?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>FÖJ-Einsatzstellen</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 12px;
}
#map-canvas {
height: 500px;
width: 600px;
}
</style>
<script type="text/javascript"
src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script type="text/javascript">
var map;
var infoWindow = new google.maps.InfoWindow();
var DEFAULT_ICON_URL = 'http://g.etfv.co/http://www.google.com'
// EDIT: change this key to your own from the Google APIs Console
// https://code.google.com/apis/console/
var apiKey = 'PLACE_YOUR_OWN_KEY_HERE';
// EDIT: Specify the table with location data and icon URLs
//var tableID = '1i0mw7f4b06sG14-mAO-zEJI1gekZ8wte_J6w05c'; // Basis-Table
var tableID = '1eCPADfnXccPMAYh24W-pUEF-eiKSlOD9e0xSKBM'; // ge-merge-te Table
// Create variables for the columns you need to retrieve from the table
var latitudeColumn = 'Latitude';
var iconUrlColumn = 'Farbcodierung für Marker';
function createMarker (coordinate, url, content) {
var marker = new google.maps.Marker({
map: map,
position: coordinate,
icon: new google.maps.MarkerImage(url)
});
google.maps.event.addListener(marker, 'click', function(event) {
infoWindow.setPosition(coordinate);
infoWindow.setContent(content);
infoWindow.open(map);
});
};
function fetchData() {
// Construct a query to get data from the Fusion Table
var query = 'SELECT '
+ latitudeColumn + ','
+ '\'' + iconUrlColumn + '\''
+ ' FROM '
+ tableID;
var encodedQuery = encodeURIComponent(query);
// Construct the URL
var url = ['https://www.googleapis.com/fusiontables/v1/query'];
url.push('?sql=' + encodedQuery);
url.push('&key=' + apiKey);
url.push('&callback=?');
// Send the JSONP request using jQuery
$.ajax({
url: url.join(''),
dataType: 'jsonp',
success: onDataFetched,
error: onError,
timeout : 7500
});
}
function onError(e) {
alert(e);
}
function onDataFetched(data) {
if(data.error) {
var errs = data.error.errors;
var msg = "";
for (var i in data.error.errors) {
msg +=
parseInt(i, 10)+1 + ". Fehler:" +
"\ndomain: " + errs[i].domain +
"\nmessage: " + errs[i].message +
"\nreason: " + errs[i].reason + "\n";
}
alert(
"Leider sind Fehler aufgetreten (um genau zu sein: " + data.error.errors.length + " Fehler, Code: " + data.error.code + "):\n" + msg
);
return;
}
var rows = data['rows'];
var iconUrl;
var iconUrl_part1 = 'http://chart.apis.google.com/chart?cht=mm&chs=32x32&chco=';
var iconUrl_part2 = '&ext=.png';
var content = "mein content";
var coordinate;
// Copy each row of data from the response into variables.
// Each column is present in the order listed in the query.
// Starting from 0.
// EDIT this if you've changed the columns, above.
for (var i in rows) {
var geocode = rows[i][0].split(",");
coordinate = new google.maps.LatLng(geocode[0],geocode[1]);
if (rows[i][1] != '') { // ensure not empty
iconUrl = iconUrl_part1 + rows[i][1] + iconUrl_part2;
createMarker(coordinate, iconUrl, content);
} else {
createMarker(coordinate, DEFAULT_ICON_URL, content);
}
}
}
function initialize() {
fetchData(); // begin retrieving data from table, and put it on the map
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(48.537778, 9.041111),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>

Resources