How to save a Google maps overlay shape in the database? - mysql

I want to save a Google maps overlay shape in the database. This is my code. It works perfectly but I just need to save all_shapes array in the database.
<html>
<head>
<style type="text/css">
#map, html, body
{
padding: 0;
margin: 0;
height: 100%;
}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=drawing,geometry"></script>
<script>
var coordinates = [];
var all_shapes = [];
var selectedShape;
</script>
<script>
function draw_shape()
{
for(var i = 0; i < all_shapes.length; i++)
{
all_shapes[i].setMap(null);
}
for(var i = 0; i < all_shapes.length; i++)
{
all_shapes[i].setMap(map);
}
}
</script>
<script>
function clearSelection()
{
if(selectedShape)
{
selectedShape.setEditable(false);
selectedShape = null;
}
}
function setSelection(shape)
{
clearSelection();
selectedShape = shape;
shape.setEditable(true);
}
function deleteSelectedShape()
{
if (selectedShape)
{
selectedShape.setMap(null);
}
}
</script>
<script>
function save_coordinates_to_array(newShapeArg)
{
if(newShapeArg.type == google.maps.drawing.OverlayType.POLYGON)
{
var polygonBounds = newShapeArg.getPath();
for(var i = 0 ; i < polygonBounds.length ; i++)
{
coordinates.push(polygonBounds.getAt(i).lat(), polygonBounds.getAt(i).lng());
}
}
else
{
//alert("Not polygon");/////////////
}
}
</script>
<script>
var map;
function initialize()
{
map = new google.maps.Map(document.getElementById('map'), {zoom: 12, center: new google.maps.LatLng(32.344, 51.048)});
var drawingManager = new google.maps.drawing.DrawingManager();
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
var newShape = e.overlay;
newShape.type = e.type;
all_shapes.push(newShape);
setSelection(newShape);
save_coordinates_to_array(newShape);
google.maps.event.addListener(newShape, 'click', function() {setSelection(newShape)});
});
google.maps.event.addListener(map, 'click', function(e) {clearSelection();});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<table border="1">
<tr>
<td>Name</td>
<td><input name="name" id="name" type="text"></td>
</tr>
<tr>
<td>Color</td>
<td>
<table border="1" width="100%">
<tr>
<td bgcolor="#FF0000"> </td>
<td bgcolor="#00FF00"> </td>
<td bgcolor="#0000FF"> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="2"><input name="save" type="button" value="Save" onClick="draw_shape()"></td>
</tr>
<tr>
<td colspan="2"><input name="delete" type="button" value="Delete" onClick="deleteSelectedShape()"></td>
</tr>
</table>
<div id="map"></div>
</body>
</html>
Where and how can I save the created overlay shapes in the database. All shapes are saved in the var all_shapes = []; array. What kind of type I have to choose for the field in database? I mean for example int, char, etc.
I'm going to use MySQL and PHP.

When you simply want to store the shapes somehow, you may use a JSON-string, store it in e.g. a Text-column(char would be to small to store detailed polygons/polylines )
Note: when you create the JSON-string, you must convert the properties(e.g. to native arrays or objects), you cannot store for example LatLng's directly, because the prototype will be lost when saving it. Pathes of polylines/polygons may be stored encoded
Another approach:
use multiple columns, e.g.
a column(varchar) where you store the type(LatLng, Circle,Polyline,etc.)
a column(geometry) where you store the geometric features(LatLng,Polygon or Polyline)
a column(int) where you store a radius(used when you insert a circle)
optionally column(text) where you store the style-options(when needed)
The first suggestion would be sufficient when you simply want to store it.
When you must be able to select particular shapes, e.g for a given area, use the 2nd suggestion.
See http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html for details of the spatial extensions
2 functions that either remove the circular references and create storable objects, or restore the overlays from these stored objects.
var IO={
//returns array with storable google.maps.Overlay-definitions
IN:function(arr,//array with google.maps.Overlays
encoded//boolean indicating if pathes should be stored encoded
){
var shapes = [],
goo=google.maps,
shape,tmp;
for(var i = 0; i < arr.length; i++)
{
shape=arr[i];
tmp={type:this.t_(shape.type),id:shape.id||null};
switch(tmp.type){
case 'CIRCLE':
tmp.radius=shape.getRadius();
tmp.geometry=this.p_(shape.getCenter());
break;
case 'MARKER':
tmp.geometry=this.p_(shape.getPosition());
break;
case 'RECTANGLE':
tmp.geometry=this.b_(shape.getBounds());
break;
case 'POLYLINE':
tmp.geometry=this.l_(shape.getPath(),encoded);
break;
case 'POLYGON':
tmp.geometry=this.m_(shape.getPaths(),encoded);
break;
}
shapes.push(tmp);
}
return shapes;
},
//returns array with google.maps.Overlays
OUT:function(arr,//array containg the stored shape-definitions
map//map where to draw the shapes
){
var shapes = [],
goo=google.maps,
map=map||null,
shape,tmp;
for(var i = 0; i < arr.length; i++)
{
shape=arr[i];
switch(shape.type){
case 'CIRCLE':
tmp=new goo.Circle({radius:Number(shape.radius),
center:this.pp_.apply(this,shape.geometry)});
break;
case 'MARKER':
tmp=new goo.Marker({position:this.pp_.apply(this,shape.geometry)});
break;
case 'RECTANGLE':
tmp=new goo.Rectangle({bounds:this.bb_.apply(this,shape.geometry)});
break;
case 'POLYLINE':
tmp=new goo.Polyline({path:this.ll_(shape.geometry)});
break;
case 'POLYGON':
tmp=new goo.Polygon({paths:this.mm_(shape.geometry)});
break;
}
tmp.setValues({map:map,id:shape.id})
shapes.push(tmp);
}
return shapes;
},
l_:function(path,e){
path=(path.getArray)?path.getArray():path;
if(e){
return google.maps.geometry.encoding.encodePath(path);
}else{
var r=[];
for(var i=0;i<path.length;++i){
r.push(this.p_(path[i]));
}
return r;
}
},
ll_:function(path){
if(typeof path==='string'){
return google.maps.geometry.encoding.decodePath(path);
}
else{
var r=[];
for(var i=0;i<path.length;++i){
r.push(this.pp_.apply(this,path[i]));
}
return r;
}
},
m_:function(paths,e){
var r=[];
paths=(paths.getArray)?paths.getArray():paths;
for(var i=0;i<paths.length;++i){
r.push(this.l_(paths[i],e));
}
return r;
},
mm_:function(paths){
var r=[];
for(var i=0;i<paths.length;++i){
r.push(this.ll_.call(this,paths[i]));
}
return r;
},
p_:function(latLng){
return([latLng.lat(),latLng.lng()]);
},
pp_:function(lat,lng){
return new google.maps.LatLng(lat,lng);
},
b_:function(bounds){
return([this.p_(bounds.getSouthWest()),
this.p_(bounds.getNorthEast())]);
},
bb_:function(sw,ne){
return new google.maps.LatLngBounds(this.pp_.apply(this,sw),
this.pp_.apply(this,ne));
},
t_:function(s){
var t=['CIRCLE','MARKER','RECTANGLE','POLYLINE','POLYGON'];
for(var i=0;i<t.length;++i){
if(s===google.maps.drawing.OverlayType[t[i]]){
return t[i];
}
}
}
}
The array returned by IO.IN may be sended to a serverside script. The serverside script should iterate over this array and INSERT a JSON-string into the table:
<?php
$mysqli = new mysqli(/*args*/);
$stmt = $mysqli->prepare('INSERT INTO `tableName`(`columnName`) VALUES (?)');
$stmt->bind_param('s', $json);
foreach($_POST['shapes'] as $value){
$json = json_encode($value);
$stmt->execute();
}
?>
to restore the shapes fetch them:
<?php
$json=array();
$res=$mysqli->query('SELECT `columnName` from `tableName`');
while ($row = $res->fetch_assoc()) {
$json[]=json_decode($row['columnName']);
}
$res->close();
$json=json_encode($json);
?>
and pass the result to IO.OUT():
IO.OUT(<?php echo $json;?>, someGoogleMapsInstance);
Demo: http://jsfiddle.net/doktormolle/EdZk4/show/

Simple GeoJson Editor is an example of drawing, editing, dropping and saving shapes as geoJson on google maps. The author ( a Google intern) described the project in this post.
The Javascript and HTML are not minified.
An even better opensource tool can be found at Geojson.io

Strange behavior I found in the code http://jsfiddle.net/doktormolle/EdZk4/show/
I added next code to IN function:
if (tmp.type != 'MARKER') {
tmp.strokeColor = shape.strokeColor;
tmp.strokeWeight = shape.strokeWeight;
tmp.fillColor = shape.fillColor;
tmp.fillOpacity = shape.fillOpacity;
tmp.editable = shape.getEditable();
if (tmp.type == 'POLYLINE' || tmp.type == 'POLYGON')
tmp.infoWindowContent = shape.infoWindow.content;
}
All shapes are editable, but only the last shows editable as true. For example, I add one editable polyline and it is editable in the result.
"[{"type":"POLYLINE","id":null,"draggable":false,"geometry":["gn_sFwt`eEvmd#ig|B"],
"strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":true,
"infoWindowContent":"Polyline Length: 58.80 kms"}]"
I add second editable polyline, but in the result the first is uneditable and second editable.
"[{"type":"POLYLINE","id":null,"draggable":false,"geometry":["gn_sFwt`eEvmd#ig|B"],
"strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":false,
"infoWindowContent":"Polyline Length: 58.80 kms"},
{"type":"POLYLINE","id":null,"draggable":false,"geometry":["qoiqFgvheEcsw#ygz#"],
"strokeColor":"red","strokeWeight":3,"fillOpacity":0.35,"editable":true,
"infoWindowContent":"Polyline Length: 41.41 kms"}]"

If you need to store the path just to restore it later on a map, you can also use Google Maps Encoding Utility. It is not as powerful as Dr.Molle's answer but can be useful for storing polygons and polylines.

Related

Google Sheets Script: Get Value From Script Function Into Sidebar

For an analysis spreadsheet, a function does a lot of calculations for each of ~240 rows of data. The function is slow, so I added code to check how long it's been running whilst looping.
Before 360 secs is up I exit - first saving the last row processed in Project Properties, and providing an alert. I can then rerun the function, which checks if the function did not complete, and asks if I want to continue from the last row processed. All good.
However, this can take up to half an hour to finally complete , so I've been looking online for ways to run multiple instances of the function simultaneously. I found a suggestion that uses the Sidebar.
The Sidebar is opening as expected, but despite some help, my script in the HTML is not setting the table cells with the initial "size". The server-side function c_Optimise_Stabilator_Allocation() is correctly returning an array like [87.0, 74.0, 62.0, 25.0], but the client-side function setSize(arrSize) is not working.
The GS code is:
// display sidebar in gs
function c_Optimise_Stabilator_Sidebar(){
var html = HtmlService.createHtmlOutputFromFile('StabSidebar').setTitle('Optimise Stabilator').setWidth(250);
SpreadsheetApp.getUi().showSidebar(html);
}
function c_Optimise_Stabilator_Allocation(tranche, operation){
var debug = true;
const ui = SpreadsheetApp.getUi();
// Get numRows
const sAngle = "Optimise_Stab_Angle";
const range = c_GetRangeObjByName(sAngle);
const numRows = range.getLastRow(); // s/b ~248 rows
// set different num rows per tranche, using percentage
const pct1 = 0.35, pct2 = 0.30, pct3 = 0.25;
const size1 = Math.round(numRows*pct1), startRow1 = 0;
const size2 = Math.round(numRows*pct2), startRow2 = size1;
const size3 = Math.round(numRows*pct3), startRow3 = size1+size2;
const size4 = numRows-size1-size2-size3, startRow4 = size1+size2+size3;
if (debug) { Logger.log ('T1: '+size1+'; T2: '+size2+'; T3: '+size3+'; T4: '+size4); }
if (operation=='size') {
var arrSize = [size1, size2, size3, size4];
if (debug) { Logger.log(arrSize); }
return arrSize;
} else if (operation=='run') {
switch(tranche) {
case 'tranche1' :
// c_Optimise_Stabilator(startRow1, size1);
break;
case 'tranche2' :
// c_Optimise_Stabilator(startRow2, size2);
break;
case 'tranche3' :
// c_Optimise_Stabilator(startRow3, size3);
break;
case 'tranche4' :
// c_Optimise_Stabilator(startRow4, size4);
break;
default :
break;
}
}
return;
}
The HTML code:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button onclick='run()'>Run Stabilator Optimisation</button><br>
<table>
<tr> <th>Tr</th> <th>Status</th> <th>Optimised</th> <th>Tot.Rows</th> <th>Time</th> </tr>
<tr> <td>1</td> <td id='status1'>Waiting...</td> <td id='opt1'>0</td> <td id='size1'>0</td> <td id='time1'>xxx</td> </tr>
<tr> <td>2</td> <td id='status2'>Waiting...</td> <td id='opt2'>0</td> <td id='size2'>0</td> <td id='time2'>xxx</td> </tr>
<tr> <td>3</td> <td id='status3'>Waiting...</td> <td id='opt3'>0</td> <td id='size3'>0</td> <td id='time3'>xxx</td> </tr>
<tr> <td>4</td> <td id='status4'>Waiting...</td> <td id='opt4'>0</td> <td id='size4'>0</td> <td id='time4'>xxx</td> </tr>
</table>
<script>
window.onload=function(){
console.log('onload');
google.script.run
.withSuccessHandler( function(arrSize) {
setSize(arrSize);
}
)
.c_Optimise_Stabilator_Allocation('all', 'size');
}
function setSize(arrSize){
console.log('setSize');
for(var i=0;i<vA.length;i++) {
document.getElementById('size' + (i+1)).innerHTML=arrSize[i];
}
}
function run() {
google.script.run.c_Optimise_Foil('tranche1', 'run'); document.getElementById('status1').innerHTML='Running...';
google.script.run.c_Optimise_Foil('tranche2', 'run'); document.getElementById('status2').innerHTML='Running...';
google.script.run.c_Optimise_Foil('tranche3', 'run'); document.getElementById('status3').innerHTML='Running...';
google.script.run.c_Optimise_Foil('tranche4', 'run'); document.getElementById('status4').innerHTML='Running...';
}
console.log("My Code");
</script>
</body>
</html>
I have cobbled together the code for the HTML as best I could from various sources, but can't find why the functions to setSize aren't working. Any suggestions would be welcome. MTIA
I don't really want to debug your code for you but I did want to know if it would handle multiple callbacks so here's a simple example of it doing that:
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
window.onload=function(){
google.script.run
.withSuccessHandler(function(vA) {
updateSelect(vA);
})
.getSelectOptions();
}
function updateSelect(vA,id){//the id allows me to use it for other elements
var id=id || 'sel1';
var select = document.getElementById(id);
select.options.length = 0;
for(var i=0;i<vA.length;i++) {
select.options[i] = new Option(vA[i],vA[i]);
}
}
function sendRequest() {
const n=document.getElementById('sel1').value;
document.getElementById('div' + n).innerHTML='Initiating Request' + n;
google.script.run
.withSuccessHandler(function(v){
document.getElementById('div' + v).innerHTML='Received Request' + v;
})
.initRequest(n);
}
function sendAll() {
for(let i=1;i<5;i++) {
document.getElementById('div' + i).innerHTML="Iniating Request" + i;
google.script.run
.withSuccessHandler(function(v){
document.getElementById('div' + v).innerHTML='Received Request' + v;
})
.initRequest(i);
}
}
console.log("My Code");
</script>
</head>
<body>
<select id='sel1'></select>
<input type="button" value="Initiate" onClick="sendRequest();" />
<input type="button" value="All" onclick="sendAll();" />
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
</body>
</html>
CODE:
function getSelectOptions() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const rg=sh.getRange(1,1,sh.getLastRow());
const vs=rg.getValues();
return vs;
}
function launchDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile("ah3"),"Testing");
}
function initRequest(n) {
return n;
}
I don't expect any points for it. I just thought it might be helpful to know that it can work. Somebody will most likely vote it down and then I'll remove it.

Knockout: Click Binding with Foreach Parameters

So, I have a Google Map with some locations. I'm trying to get the map markers to filter out when you click on the corresponding list item for it. The only way I can get it to work is if I put in the marker title's exact string like so:
<tbody data-bind="foreach: filteredItems()">
<tr data-bind="click: toggleGroup('Michi Ramen')">
<td id="listTitle" data-bind="text: $data.title"></td>
</tr>
</tbody>
Of course, that makes each list item filter the exact thing. Putting toggleGroup.bind($data.title) doesn't work.
This is my current viewModel:
var viewModel = function(data) {
var self = this;
self.filters = ko.observableArray(data.filters);
self.filter = ko.observable('');
self.shops = data.shops;
self.filteredItems = ko.dependentObservable(function() {
var filter = self.filter().toLowerCase();
if (!filter) {
return self.shops();
} else {
return ko.utils.arrayFilter(self.shops(), function(Shop) {
return Shop.title().toLowerCase().indexOf(filter) !== -1;
});
}
}, viewModel);
};
And this is the function I'm using to try and filter the markers.
function toggleGroup(title) {
var i;
for (i = 0; i < markers.length; i++) {
var marker = markers[i];
if (marker.title === title) {
marker.setVisible(true);
} else {
markers[i].setVisible(false);
}
}
}
My guess is that title is an observable, so you need to do click: toggleGroup.bind($data, $data.title()).
Alternatively click: function(data, event) { toggleGroup(data.title()) }.

Make basic search in array with if and else

I am trying to make a basic search function. if input.value does exist in array alert message, if not, push it to array ans show in HTML. I think I have already most of work done, but there is somewhere a mistake. Thank you in advance for your help guys .)
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value = myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
In javascript, there are 2 ways to do a comparison.
Strict Equality Operator === strict equality operator.
If you are not sure about the exact datatype for the values being compared, then you can use the == for comparison.
The line document.getElementById("inputForMyDict").value = myDict[i] needs comparison operator and not the assignment operator (=). So you need to replace the = with either == or ===.
so your javascript code should look like
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value == myDict[i]) {
// If you know exact data type, then use the below line instead and comment the above line if (document.getElementById("inputForMyDict").value === myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
Update1: Based on the clarification, provided by comments, you don't need to have a for loop to check for existence of element in array. Javascript provides a convenient way by indexOf method on an array. indexOf method check for the existence of an element in an array and returns the index of the element in the Array. However, if the element is not found then it returns -1.
Full code below which should work.
<!DOCTYPE html>
<html>
<body>
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
//for (var i = 0; i < myDict.length; i++) {
var valueInTextbox = document.getElementById("inputForMyDict").value;
if(myDict.indexOf(valueInTextbox) > -1){
alert("your input is already in your list");
} else {
myDict.push(valueInTextbox);
document.getElementById("demo").innerHTML = myDict;
}
}
//}
</script>
</body>
</html>

Google MAP API V3 - Street View next panorama link

First of all. I was searching a long time, but I did not find what I want! How can I get next panorama? All what I know is need to get a panorama links. Links can get with getLinks();. I have read google's streetview manual, but I want to navigate with own navigation buttons not Google's!
Modified version of Google Maps Javascript API v3 streetview-events example below which adds buttons to navigate the streetview panorama via the link.
in the global scope:
var panorama = null;
var links = null;
function setPano2link(i) {
panorama.setPano(links[i].pano);
panorama.setPov({heading:links[i].heading,pitch:0});
panorama.setVisible(true);
}
Modify the "links_changed" event handler to add navigation buttons:
google.maps.event.addListener(panorama, 'links_changed', function() {
var linksTable = document.getElementById('links_table');
while(linksTable.hasChildNodes()) {
linksTable.removeChild(linksTable.lastChild);
};
links = panorama.getLinks();
for (var i in links) {
var row = document.createElement('tr');
linksTable.appendChild(row);
var labelCell = document.createElement('td');
labelCell.innerHTML = '<b>Link: ' + i + '</b>';
var valueCell = document.createElement('td');
valueCell.innerHTML = links[i].description;
var btnCell = document.createElement('td');
btnCell.innerHTML = '<input type="button" value="goto" onclick="setPano2link('+i+')"></input>';
var panoIdCell = document.createElement('td');
panoIdCell.innerHTML = links[i].pano;
var headingCell = document.createElement('td');
headingCell.innerHTML = links[i].heading;
linksTable.appendChild(labelCell);
linksTable.appendChild(valueCell);
linksTable.appendChild(btnCell);
linksTable.appendChild(panoIdCell);
linksTable.appendChild(headingCell);
}
});
working example
Complete code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Street View events</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
var cafe = new google.maps.LatLng(37.869085,-122.254775);
var panorama = null;
var links = null;
function setPano2link(i) {
panorama.setPano(links[i].pano);
panorama.setPov({heading:links[i].heading,pitch:0});
panorama.setVisible(true);
}
function initialize() {
var panoramaOptions = {
position: cafe,
pov: {
heading: 270,
pitch: 0
},
visible: true
};
panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'), panoramaOptions);
google.maps.event.addListener(panorama, 'pano_changed', function() {
var panoCell = document.getElementById('pano_cell');
panoCell.innerHTML = panorama.getPano();
});
google.maps.event.addListener(panorama, 'links_changed', function() {
var linksTable = document.getElementById('links_table');
while(linksTable.hasChildNodes()) {
linksTable.removeChild(linksTable.lastChild);
};
links = panorama.getLinks();
for (var i in links) {
var row = document.createElement('tr');
linksTable.appendChild(row);
var labelCell = document.createElement('td');
labelCell.innerHTML = '<b>Link: ' + i + '</b>';
var valueCell = document.createElement('td');
valueCell.innerHTML = links[i].description;
var btnCell = document.createElement('td');
btnCell.innerHTML = '<input type="button" value="goto" onclick="setPano2link('+i+')"></input>';
var panoIdCell = document.createElement('td');
panoIdCell.innerHTML = links[i].pano;
var headingCell = document.createElement('td');
headingCell.innerHTML = links[i].heading;
linksTable.appendChild(labelCell);
linksTable.appendChild(valueCell);
linksTable.appendChild(btnCell);
linksTable.appendChild(panoIdCell);
linksTable.appendChild(headingCell);
}
});
google.maps.event.addListener(panorama, 'position_changed', function() {
var positionCell = document.getElementById('position_cell');
positionCell.firstChild.nodeValue = panorama.getPosition() + '';
});
google.maps.event.addListener(panorama, 'pov_changed', function() {
var headingCell = document.getElementById('heading_cell');
var pitchCell = document.getElementById('pitch_cell');
headingCell.firstChild.nodeValue = panorama.getPov().heading + '';
pitchCell.firstChild.nodeValue = panorama.getPov().pitch + '';
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="pano" style="width: 45%; height: 100%;float:left"></div>
<div id="panoInfo" style="width: 45%; height: 100%;float:left">
<table>
<tr>
<td><b>Position</b></td><td id="position_cell"> </td>
</tr>
<tr>
<td><b>POV Heading</b></td><td id="heading_cell">270</td>
</tr>
<tr>
<td><b>POV Pitch</b></td><td id="pitch_cell">0.0</td>
</tr>
<tr>
<td><b>Pano ID</b></td><td id="pano_cell"> </td>
</tr>
<table id="links_table"></table>
</table>
</div>
</body>
</html>
Go to this link: https://developers.google.com/maps/documentation/embed/start
Go to Google Maps and enter the street-view mode in your browser on the location you want
Click on "Share .."
Search that hyperlink-string (CTRL-F/CMD-F) for "!2e", and copy the string from the first letter after "!" to the first letter after "s" in "!1s".
Example:
!1s
-SWqF6BeQEBI%2FWBXbp08W9pI%2FAAAAAAAACRo%2F17TZj7OS3OMBBkrcNfZ45YlZxGydVryDwCLIB
!2e
If you have any "%2F" in the HTML-string, you need to replace them with "/". If you have "-"-symbol at start, you need to replace it with
"F:-".
Now go back to the link given in the first bullet and click on the tab "Show Street View or a custom panorama"
Past the newly copied string into the field "Custom panorama ID:" and press enter
Now enter your API-key; remember to add the right API-key to your API-project that is made for panorama/street-view! (Google Maps Embed API; you can add more than one key to your project) Click on "Get Key" if you have not already
And that is it!
You will get a personal HTML-code you can past right in to you HTML-document. This is tested and works as of the date I wrote this.

Weird Google Maps V2 Marker issue

Got this code, that only works when alert (markers.length); is uncommented.
When this javascript alert not shown I dont get any Markers.. Really weird!!
In the body tag I have <body onload="load()" onunload="GUnload()">
Previoslly the load() function is called and other functions :
function showAddress(address) {
if (geocoder) {//+', '+init_street
geocoder.getLatLng(address,
function(point) {
if (!point) {
document.getElementById("place").value="not found";
//alert(address + " not found");
} else {
// document.getElementById("place").value=point.y.toFixed(4) + "," + point.x.toFixed(4);
map.setCenter(point, 16);
marker.setPoint(point);
//marker.openInfoWindowHtml(address);
}
}
);
}
}
//from a point returns and address!
function showPointAddress(response) {
if (!response || response.Status.code != 200) {//not found
//alert("Status Code:" + response.Status.code);
document.getElementById("place").value="not found";
}
else {//found
map.setCenter(marker.getPoint(), 16);
place = response.Placemark[0];
document.getElementById("place").value=place.address;
//document.getElementById("place").value=marker.getPoint().toUrlValue();
}
}
// Creates a marker at the given point with the given number icon and text
function createMarker(p,text) {
var marker = new GMarker(p);
if (text!=""){
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(text);});
}
return marker;
}
` var geocoder = null;`
` var map = null;`
function load() {//loading the map
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.enableScrollWheelZoom();
geocoder = new GClientGeocoder();
if (init_street!=""){
geocoder.getLatLng(init_street,function(point) {//set center point in map
if (point){
map.setCenter(point, zoom);
map.addOverlay(createMarker(point,init_street));
map.openInfoWindow(point,init_street);
}
});
}
map.addControl(new GLargeMapControl());
map.setMapType(G_NORMAL_MAP);
}
}`
function(data, responseCode) {
if(responseCode == 200) {
var texts = [];
var addresses = [];
var xml = GXml.parse(data);
var markers = xml.documentElement.getElementsByTagName("item");
alert (markers.length);
for (var i = 0; i < markers.length; i++) {
var address=markers[i].getElementsByTagName('address').item(0).childNodes.item(0).nodeValue;
if (address!=null){
//alert (address);
var title=markers[i].getElementsByTagName('title').item(0).childNodes.item(0).nodeValue;
var link=markers[i].getElementsByTagName('link').item(0).childNodes.item(0).nodeValue;
var desc=markers[i].getElementsByTagName('description').item(0).childNodes.item(0).nodeValue;
desc=desc.substr(0,220);//limit
addresses.push(address);
texts.push("<div style='width: 200px'><a target='_blank' href='" +link+"'>"+title+"</a><br />"+desc+"</div>");
}//if
}//for
for (var i = 0; i < addresses.length; i++) {
geocoder.getLatLng(addresses[i], function (current) {
return function(point) {
if (point) map.addOverlay(createMarker(point,texts[current]));
}
}(i));
}
}//if });
I Understand the issue of needing a callback function to load the markers, but Im lost..
Any help apreciated!! ;)
Thx in advanced!!
This usually happens when fetching data with Ajax or similar. Basically when you fetch the data you need to utilize a callback function to wait for the data. If you don't there is no data to execute on. However, if you pause the execution with a alert() the data will have been fetched in the background.
Think of it as the waiting for the DOM to load before executing Javascript on the page.
I can't give you a better answer as you have not included the code that is calling the function you included.