Google Maps Info Window Not Allowing Mulitple Django Variables - javascript

I'm trying to set up a relatively simple info window using google maps api. I want to put multiple variables into my info window from my django backend. If I only include one variable it works fine. However, if I try to include multiple variables then nothing is rendered. I cannot figure out why. This is the offending line:
'<h1 id="infolayer-title" class="firstHeading">{{ variable1 }} {{ variable2 }}</h1>'+
However, this works fine, strangely:
'<h1 id="infolayer-title" class="firstHeading">{{ variable1 }}</h1>'+
The variables are being properly rendered in the markup, but there is a javascript error. The javascript console says SyntaxError: missing ; before statement on the line printed above, but including a semicolon before or after the variable has not solved the problem.
Here is the full implementation (most of which is straight from the maps api docs):
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script>
function initialize() {
var myLatlng = new google.maps.LatLng(122, 5);
var mapOptions = {
zoom: 15,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var contentString = '<div id="content">'+
'<div id="infolayer">'+
'</div>'+
'<h1 id="infolayer-title" class="firstHeading">{{ variable1 }} {{ variable2 }}</h1>'+
'<div id="bodyContent">'+
'<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large ' +
'Heritage Site.</p>'+
...
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Hello World!'
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
How can I get the map to render using multiple variables in the Info Layer Window? Thanks for any ideas that may help with this confusing problem!

The apostrohpe in SomeDude's is acting as the end of the contentString for that line, then there is more content after it. You need to escape this variable, which should happen by default so maybe you turned off autoescaping? Try replacing with this:
'<h1 id="infolayer-title" class="firstHeading">{% autoescape on %}{{ variable1 }} {{ variable2 }}{% endautoescape %}</h1>'+
It will encode the ' in SomeDude's as ' for a rendering of SomeDude's which will not break your string.

Related

Same statement gives an error inside for loop

The Server side uses python with flask, and the html template is jinja2. I'm trying to make a marker with google api. The latitude and longitude information are stored in stores[][] which is passed from python. This code is between <script> tag in my html file and it works fine.
var marker = new google.maps.Marker({position: {lat: {{stores[0][5]}}, lng: {{stores[0][6]}}}, map: map});
var marker = new google.maps.Marker({position: {lat: {{stores[4][5]}}, lng: {{stores[4][6]}}}, map: map});
I have multiple lat,lng from which I want to make markers, so I put it inside a for loop.
var i;
for (i = 0; i < 5; i++) {
var marker = new google.maps.Marker({position: {lat: {{stores[i][5]}}, lng: {{stores[i][6]}}}, map: map});
}
Exactly same code, but the index is i was put instead of a number for indexing. It suddenly gives errors saying
jinja2.exceptions.UndefinedError: list object has no element Undefined
I double checked that stores[][] have more than 5 elements. This is very very confusing.
You can't do this. Jinja is evaluated entirely on the server, well before the JS can run on the client. There is no way for Jinja to have access to variables from the JS code.
You should move the loop to Jinja itself.
{% for store in stores %}
var marker = new google.maps.Marker({position: {lat: {{ store[5] }}, lng: {{ store[6] }}}, map: map});
{% endfor %}

MVC show session value in HTML [duplicate]

Is it possible or is there a workaround to use Razor syntax within JavaScript that is in a view (cshtml)?
I am trying to add markers to a Google map... For example, I tried this, but I'm getting a ton of compilation errors:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
#foreach (var item in Model) {
var markerlatLng = new google.maps.LatLng(#(Model.Latitude), #(Model.Longitude));
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
</script>
Use the <text> pseudo-element, as described here, to force the Razor compiler back into content mode:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
#foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(#(Model.Latitude), #(Model.Longitude));
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
</text>
}
</script>
Update:
Scott Guthrie recently posted about #: syntax in Razor, which is slightly less clunky than the <text> tag if you just have one or two lines of JavaScript code to add. The following approach would probably be preferable, because it reduces the size of the generated HTML. (You could even move the addMarker function to a static, cached JavaScript file to further reduce the size):
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
...
// Declare addMarker function
function addMarker(latitude, longitude, title, description, map)
{
var latLng = new google.maps.LatLng(latitude, longitude);
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
// Now add markers
#foreach (var item in Model) {
#:addMarker(#item.Latitude, #item.Longitude, '#item.Title', '#item.Description', map);
}
</script>
Updated the above code to make the call to addMarker more correct.
To clarify, the #: forces Razor back into text mode, even though addMarker call looks a lot like C# code. Razor then picks up the #item.Property syntax to say that it should directly output the contents of those properties.
Update 2
It's worth noting that View code really isn't a good place to put JavaScript code. JavaScript code should be placed in a static .js file, and then it should get the data that it needs either from an Ajax call or by scanning data- attributes from the HTML. Besides making it possible to cache your JavaScript code, this also avoids issues with encoding, since Razor is designed to encode for HTML, but not JavaScript.
View Code
#foreach(var item in Model)
{
<div data-marker="#Json.Encode(item)"></div>
}
JavaScript code
$('[data-marker]').each(function() {
var markerData = $(this).data('marker');
addMarker(markerData.Latitude, markerData.Longitude,
markerData.Description, markerData.Title);
});
I just wrote this helper function. Put it in App_Code/JS.cshtml:
#using System.Web.Script.Serialization
#helper Encode(object obj)
{
#(new HtmlString(new JavaScriptSerializer().Serialize(obj)));
}
Then in your example, you can do something like this:
var title = #JS.Encode(Model.Title);
Notice how I don't put quotes around it. If the title already contains quotes, it won't explode. Seems to handle dictionaries and anonymous objects nicely too!
You're trying to jam a square peg in a round hole.
Razor was intended as an HTML-generating template language. You may very well get it to generate JavaScript code, but it wasn't designed for that.
For instance: What if Model.Title contains an apostrophe? That would break your JavaScript code, and Razor won't escape it correctly by default.
It would probably be more appropriate to use a String generator in a helper function. There will likely be fewer unintended consequences of that approach.
What specific errors are you seeing?
Something like this could work better:
<script type="text/javascript">
//now add markers
#foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(#Model.Latitude, #Model.Longitude);
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
</text>
}
</script>
Note that you need the magical <text> tag after the foreach to indicate that Razor should switch into markup mode.
That will work fine, as long as it's in a CSHTML page and not an external JavaScript file.
The Razor template engine doesn't care what it's outputting and does not differentiate between <script> or other tags.
However, you need to encode your strings to prevent XSS attacks.
I prefer "<!--" "-->" like a "text>"
<script type="text/javascript">
//some javascript here
#foreach (var item in itens)
{
<!--
var title = #(item.name)
...
-->
</script>
One thing to add - I found that Razor syntax hilighter (and probably the compiler) interpret the position of the opening bracket differently:
<script type="text/javascript">
var somevar = new Array();
#foreach (var item in items)
{ // <---- placed on a separate line, NOT WORKING, HILIGHTS SYNTAX ERRORS
<text>
</text>
}
#foreach (var item in items) { // <---- placed on the same line, WORKING !!!
<text>
</text>
}
</script>
A simple and a good straight-forward example:
<script>
// This gets the username from the Razor engine and puts it
// in JavaScript to create a variable I can access from the
// client side.
//
// It's an odd workaraound, but it works.
#{
var outScript = "var razorUserName = " + "\"" + #User.Identity.Name + "\"";
}
#MvcHtmlString.Create(outScript);
</script>
This creates a script in your page at the location you place the code above which looks like the following:
<script>
// This gets the username from the Razor engine and puts it
// in JavaScript to create a variable I can access from
// client side.
//
// It's an odd workaraound, but it works.
var razorUserName = "daylight";
</script>
Now you have a global JavaScript variable named razorUserName which you can access and use on the client. The Razor engine has obviously extracted the value from #User.Identity.Name (server-side variable) and put it in the code it writes to your script tag.
The following solution seems more accurate to me than combine JavaScript with Razor. Check this out:
https://github.com/brooklynDev/NGon
You can add almost any complex data to ViewBag.Ngon and access it in JavaScript
In the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
ViewBag.NGon.Person = person;
return View();
}
}
In JavaScript:
<script type="text/javascript">
$(function () {
$("#button").click(function () {
var person = ngon.Person;
var div = $("#output");
div.html('');
div.append("FirstName: " + person.FirstName);
div.append(", LastName: " + person.LastName);
div.append(", Age: " + person.Age);
});
});
</script>
It's allows any plain old CLR objects (POCOs) that can be serialized using the default JavascriptSerializer.
There is also one more option than #: and <text></text>.
Using <script> block itself.
When you need to do large chunks of JavaScript depending on Razor code, you can do it like this:
#if(Utils.FeatureEnabled("Feature")) {
<script>
// If this feature is enabled
</script>
}
<script>
// Other JavaScript code
</script>
Pros of this manner is that it doesn't mix JavaScript and Razor too much, because mixing them a lot will cause readability issues eventually. Also large text blocks are not very readable either.
None of the previous solutions work correctly... I have tried all the ways, but it did not give me the expected result... At last I found that there are some errors in the code... And the full code is given below.
<script type="text/javascript">
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(23.00, 90.00),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
#foreach (var item in Model)
{
<text>
var markerlatLng = new google.maps.LatLng(#(item.LATITUDE), #(item.LONGITUDE));
var title = '#(item.EMP_ID)';
var description = '#(item.TIME)';
var contentString = '<h3>' + "Employee " +title+ " was here at "+description+ '</h3>' + '<p>'+" "+ '</p>'
var infowindow = new google.maps.InfoWindow({
// content: contentString
});
var marker = new google.maps.Marker({
position: markerlatLng,
title: title,
map: map,
draggable: false,
content: contentString
});
google.maps.event.addListener(marker, 'click', (function (marker) {
return function () {
infowindow.setContent(marker.content);
infowindow.open(map, marker);
}
})(marker));
</text>
}
</script>
I finally found the solution (*.vbhtml):
function razorsyntax() {
/* Double */
#(MvcHtmlString.Create("var szam =" & mydoublevariable & ";"))
alert(szam);
/* String */
var str = '#stringvariable';
alert(str);
}
Those who, like me, don't have Json.Encode available can try this.
<script type="text/javascript">
var model = #Html.Raw(Json.Serialize(Model))
</script>

Django google-maps API v3 doesn't work with Chrome when using template variables

I want to pass latitude,longitude variables to my template to show location on Google Maps. For that i use template variables in javascript:
<script type="text/javascript">
var map;
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: {{ m_city.location.y }}, lng: {{ m_city.location.x }}},
zoom: 10
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=KEY&callback=initMap"
async defer></script>
It works fine in Firefox, but Chrome(v.42) doesn't show map at all. Although in source code of generated page latitude and longitude are correctly substituted.
If i copy generated latitude and longitude and hard code it in template then code works and Chrome displays map.
Can anyone point me to why this is happening?
UPDATE
As Selcuk pointed in comments, problem was in decimal separator(comma instead of point). Different separators were generated because of different language settings of browsers. Setting USE_L10N to False helped.
I suggest to use localize templatetag, so you can use format localisation without breaking your javascript code.
{% localize off %}
<script type="text/javascript">
var map;
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: {{ m_city.location.y }}, lng: {{ m_city.location.x }}},
zoom: 10
});
}
</script>
{% endlocalize %}
<script src="https://maps.googleapis.com/maps/api/js?key=KEY&callback=initMap"
async defer></script>

Using Razor within JavaScript

Is it possible or is there a workaround to use Razor syntax within JavaScript that is in a view (cshtml)?
I am trying to add markers to a Google map... For example, I tried this, but I'm getting a ton of compilation errors:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
#foreach (var item in Model) {
var markerlatLng = new google.maps.LatLng(#(Model.Latitude), #(Model.Longitude));
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
</script>
Use the <text> pseudo-element, as described here, to force the Razor compiler back into content mode:
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
// Now add markers
#foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(#(Model.Latitude), #(Model.Longitude));
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
</text>
}
</script>
Update:
Scott Guthrie recently posted about #: syntax in Razor, which is slightly less clunky than the <text> tag if you just have one or two lines of JavaScript code to add. The following approach would probably be preferable, because it reduces the size of the generated HTML. (You could even move the addMarker function to a static, cached JavaScript file to further reduce the size):
<script type="text/javascript">
// Some JavaScript code here to display map, etc.
...
// Declare addMarker function
function addMarker(latitude, longitude, title, description, map)
{
var latLng = new google.maps.LatLng(latitude, longitude);
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: map,
draggable: false
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
}
// Now add markers
#foreach (var item in Model) {
#:addMarker(#item.Latitude, #item.Longitude, '#item.Title', '#item.Description', map);
}
</script>
Updated the above code to make the call to addMarker more correct.
To clarify, the #: forces Razor back into text mode, even though addMarker call looks a lot like C# code. Razor then picks up the #item.Property syntax to say that it should directly output the contents of those properties.
Update 2
It's worth noting that View code really isn't a good place to put JavaScript code. JavaScript code should be placed in a static .js file, and then it should get the data that it needs either from an Ajax call or by scanning data- attributes from the HTML. Besides making it possible to cache your JavaScript code, this also avoids issues with encoding, since Razor is designed to encode for HTML, but not JavaScript.
View Code
#foreach(var item in Model)
{
<div data-marker="#Json.Encode(item)"></div>
}
JavaScript code
$('[data-marker]').each(function() {
var markerData = $(this).data('marker');
addMarker(markerData.Latitude, markerData.Longitude,
markerData.Description, markerData.Title);
});
I just wrote this helper function. Put it in App_Code/JS.cshtml:
#using System.Web.Script.Serialization
#helper Encode(object obj)
{
#(new HtmlString(new JavaScriptSerializer().Serialize(obj)));
}
Then in your example, you can do something like this:
var title = #JS.Encode(Model.Title);
Notice how I don't put quotes around it. If the title already contains quotes, it won't explode. Seems to handle dictionaries and anonymous objects nicely too!
You're trying to jam a square peg in a round hole.
Razor was intended as an HTML-generating template language. You may very well get it to generate JavaScript code, but it wasn't designed for that.
For instance: What if Model.Title contains an apostrophe? That would break your JavaScript code, and Razor won't escape it correctly by default.
It would probably be more appropriate to use a String generator in a helper function. There will likely be fewer unintended consequences of that approach.
What specific errors are you seeing?
Something like this could work better:
<script type="text/javascript">
//now add markers
#foreach (var item in Model) {
<text>
var markerlatLng = new google.maps.LatLng(#Model.Latitude, #Model.Longitude);
var title = '#(Model.Title)';
var description = '#(Model.Description)';
var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
</text>
}
</script>
Note that you need the magical <text> tag after the foreach to indicate that Razor should switch into markup mode.
That will work fine, as long as it's in a CSHTML page and not an external JavaScript file.
The Razor template engine doesn't care what it's outputting and does not differentiate between <script> or other tags.
However, you need to encode your strings to prevent XSS attacks.
I prefer "<!--" "-->" like a "text>"
<script type="text/javascript">
//some javascript here
#foreach (var item in itens)
{
<!--
var title = #(item.name)
...
-->
</script>
One thing to add - I found that Razor syntax hilighter (and probably the compiler) interpret the position of the opening bracket differently:
<script type="text/javascript">
var somevar = new Array();
#foreach (var item in items)
{ // <---- placed on a separate line, NOT WORKING, HILIGHTS SYNTAX ERRORS
<text>
</text>
}
#foreach (var item in items) { // <---- placed on the same line, WORKING !!!
<text>
</text>
}
</script>
A simple and a good straight-forward example:
<script>
// This gets the username from the Razor engine and puts it
// in JavaScript to create a variable I can access from the
// client side.
//
// It's an odd workaraound, but it works.
#{
var outScript = "var razorUserName = " + "\"" + #User.Identity.Name + "\"";
}
#MvcHtmlString.Create(outScript);
</script>
This creates a script in your page at the location you place the code above which looks like the following:
<script>
// This gets the username from the Razor engine and puts it
// in JavaScript to create a variable I can access from
// client side.
//
// It's an odd workaraound, but it works.
var razorUserName = "daylight";
</script>
Now you have a global JavaScript variable named razorUserName which you can access and use on the client. The Razor engine has obviously extracted the value from #User.Identity.Name (server-side variable) and put it in the code it writes to your script tag.
The following solution seems more accurate to me than combine JavaScript with Razor. Check this out:
https://github.com/brooklynDev/NGon
You can add almost any complex data to ViewBag.Ngon and access it in JavaScript
In the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
ViewBag.NGon.Person = person;
return View();
}
}
In JavaScript:
<script type="text/javascript">
$(function () {
$("#button").click(function () {
var person = ngon.Person;
var div = $("#output");
div.html('');
div.append("FirstName: " + person.FirstName);
div.append(", LastName: " + person.LastName);
div.append(", Age: " + person.Age);
});
});
</script>
It's allows any plain old CLR objects (POCOs) that can be serialized using the default JavascriptSerializer.
There is also one more option than #: and <text></text>.
Using <script> block itself.
When you need to do large chunks of JavaScript depending on Razor code, you can do it like this:
#if(Utils.FeatureEnabled("Feature")) {
<script>
// If this feature is enabled
</script>
}
<script>
// Other JavaScript code
</script>
Pros of this manner is that it doesn't mix JavaScript and Razor too much, because mixing them a lot will cause readability issues eventually. Also large text blocks are not very readable either.
None of the previous solutions work correctly... I have tried all the ways, but it did not give me the expected result... At last I found that there are some errors in the code... And the full code is given below.
<script type="text/javascript">
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(23.00, 90.00),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
#foreach (var item in Model)
{
<text>
var markerlatLng = new google.maps.LatLng(#(item.LATITUDE), #(item.LONGITUDE));
var title = '#(item.EMP_ID)';
var description = '#(item.TIME)';
var contentString = '<h3>' + "Employee " +title+ " was here at "+description+ '</h3>' + '<p>'+" "+ '</p>'
var infowindow = new google.maps.InfoWindow({
// content: contentString
});
var marker = new google.maps.Marker({
position: markerlatLng,
title: title,
map: map,
draggable: false,
content: contentString
});
google.maps.event.addListener(marker, 'click', (function (marker) {
return function () {
infowindow.setContent(marker.content);
infowindow.open(map, marker);
}
})(marker));
</text>
}
</script>
I finally found the solution (*.vbhtml):
function razorsyntax() {
/* Double */
#(MvcHtmlString.Create("var szam =" & mydoublevariable & ";"))
alert(szam);
/* String */
var str = '#stringvariable';
alert(str);
}
Those who, like me, don't have Json.Encode available can try this.
<script type="text/javascript">
var model = #Html.Raw(Json.Serialize(Model))
</script>

Setting marker title in Google Maps API 3 using jQuery

I am having a couple of problems with Google Maps and jQuery. Wondered if anyone can help with the smaller of the two problems and hopefully it will help me to fixing the bigger one.
I am using the below code to populate a google map, basically it uses generated HTML to populate the maps in the form:
<div class="item mapSearch" id="map52.48228_-1.9026:800">
<div class="box-prise"><p>(0.62km away)</p><div class="btn-book-now">
BOOK NOW
</div>
</div><img src="http://media.toptable.com/images/thumb/13152.jpg" alt="Metro Bar and Grill" width="60" height="60" />
<div class="info">
<h2>Metro Bar and Grill</h2>
<p class="address">73 Cornwall Street, Birmingham, B3 2DF</p><strong class="proposal">2 courses £14.50</strong>
<dl>
<dt>Diner Rating: </dt>
<dd>7.8</dd>
</dl></div></div>
<div class="item mapSearch" id="map52.4754_-1.8999:3195">
<div class="box-prise"><p>(0.97km away)</p><div class="btn-book-now">
BOOK NOW
</div>
</div><img src="http://media.toptable.com/images/thumb/34998.jpg" alt="Filini Restaurant - Birmingham" width="60" height="60" />
<div class="info">
<h2>Filini Restaurant - Birmingham</h2>
<p class="address">Radisson Blu Hotel, 12 Holloway Circus, Queensway, Birmingham, B1 1BT</p><strong class="proposal">2 for 1: main courses </strong>
<dl>
<dt>Diner Rating: </dt>
<dd>7.8</dd>
</dl></div></div>
<div class="item mapSearch" id="map52.47775_-1.90619:10657">
<div class="box-prise"><p>(1.05km away)</p><div class="btn-book-now">
BOOK NOW
</div>
</div><img src="http://media.toptable.com/images/thumb/34963.jpg" alt="B1 " width="60" height="60" />
<div class="info">
<h2>B1 </h2>
<p class="address">Central Square , Birmingham, B1 1HH</p><strong class="proposal">25% off food</strong>
<dl>
<dt>Diner Rating: </dt>
<dd>7.9</dd>
</dl></div></div>
The JavaScript loops though all the divs with class mapSearch and uses this to plot markers using the div ID to get the lat/lon and ID of the venue:
var locations = $(".mapSearch");
for (var i=0;i<locations.length;i++) {
var id = locations[i].id;
if (id) {
var jsLonLat = id.substring(3).split(":")[0];
var jsId = id.substring(3).split(":")[1];
var jsLat = jsLonLat.split("_")[0];
var jsLon = jsLonLat.split("_")[1];
var jsName = $("h2").text();
var jsAddress = $("p.address").text();
var latlng = new google.maps.LatLng(jsLat,jsLon);
var marker = new google.maps.Marker({
position: latlng,
map:map,
icon: greenRestaurantImage,
title: jsName
});
google.maps.event.addListener(marker, 'click', function() {
//Check to see if info window already exists
if (!infowindow) {
//if doesn't exist then create a empty InfoWindow object
infowindow = new google.maps.InfoWindow();
}
//Set the content of InfoWindow
infowindow.setContent(jsAddress);
//Tie the InfoWindow to the market
infowindow.open(map,marker);
});
bounds.extend(latlng);
map.fitBounds(bounds);
}
}
The markers all plot OK on the map, however I am having probs with the infoWindow bit. I want to display info about each venue when clicked, however using my code above it just puts all info in one box when clicked, not individually. Hoping it is a simple fix!
Hoping once I fix this I can work out a way to get the info window displaying if I hover over the div in the html.
As far as my jQuery knowledge is concerned, what you are seeing is right; $("h2").text() will concatenate inner text of all H2s into one string and return it. You better try something along these lines:
// inside your if (id) clause
var jsName = $("h2", locations[i]).text();
var jsAddress = $("p.address", locations[i]).text();
You can .each() over $(".mapSearch") if you want to simplify your code.
$(document).ready(function() {
//<![CDATA[
if (GBrowserIsCompatible()) {
function createMarker(point, html) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
// Display the map, with some controls and set the initial location
var map = new GMap2(document.getElementById("map"));
map.enableContinuousZoom();
//map.enableScrollWheelZoom();
map.enablePinchToZoom(); // ForiPhone users
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(51.53177, -0.08001), 16);
var icon = new GIcon();
var point = new GLatLng(51.53177, -0.08001);
var marker = createMarker(point, '<div style="width:240px" id="mapsball"></div>');
map.addOverlay(marker, icon);
}
// display a warning if the browser was not compatible
else {
alert("Sorry, Google Maps is not compatible with your browser");
}
//]]>
});

Categories

Resources