JADE + EXPRESS: Iterating over object in inline JS code (client-side)? - javascript

i want to implement a google map based on its api. i want to add a path based on coordinates to it. therefore i get my coordinates from my model and want to iterate over the object to fille the map with this points. in my jade template i include the api js code like this:
script(type='text/javascript')
function initialize() {
var myLatLng = new google.maps.LatLng(0, -180);
var myOptions = {
zoom: 3,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var flightPlanCoordinates = [
- if (typeof(pins) != null)
- var.pins.forEach(function(pin) {
new google.maps.LatLng(pin.latitude, pin.longitude),
- })
new google.maps.LatLng(0,0)
];
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates,
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2
});
flightPath.setMap(map);
}
div#map_canvas(style='height: 500px; background-color: #990000;')
the problem is: jade renders this snippet
var flightPlanCoordinates = [
- if (typeof(pins) != null)
- var.pins.forEach(function(pin) {
new google.maps.LatLng(pin.latitude, pin.longitude),
- })
new google.maps.LatLng(0,0)
];
as it is in the jade template source... the - if etc. doesn't get parsed! any ideas?
thanks!

The entire script tag (everything indented under it) is going to be passed through raw without further parsing. Jade does HTML templating not HTML templating plus nested javascript templating. To pass your pins variable from jade local template variable data to script source code, you'll have to do some other approach like using raw jade to render a tiny script tag that just calls your initialize function with the pins data as a literal, or stick your pins data into the dom somewhere and then read it from there. Something along these lines below your script tag (pseudocode, haven't tested)
- if (typeof(pins) != null)
!= "<script type='text/javascript'>"
!= "var pins = [];"
- forEach pin in pins
!= "pins.push(new Pin(" + pin.latitude + ", " + pin.longitude + "));"
!= "initialize(pins);"
!= "</script>"

I passed the value as a hidden input element, e.g.:
input(type='hidden', id='variableName', value='#{variableName}')
Accessed via jQuery:
$("#variableName").val()
Joe

You can use this:
script
console.log(#{var_name});

the script tags are purely text, you can't easily mix the Jade to generate this javascript, it's usually a reflection of poor design. You can just serialize things as JSON that you need on the client or use express-expose to do this

server side
JSON.stringify(users)
client side
var users=JSON.parse(("#{users}").replace(/"/g,'"'));

I had a similar issue and this line of code solved it:
var myvar = !{JSON.stringify(mydata)};
The answer came originally from this post

Related

Laravel Google Map Markers

I have this code I used to get the location of each order i receive..
var map;
var markers = <?php echo $order ?>; //this should dump a javascript array object which does not need any extra interperting.
//var marks = []; //just incase you want to be able to manipulate this later
function initMap() {
var cent = {lat: {{$orderlat->Latitude }}, lng: {{ $orderlong->Longitude }} };
var map = new google.maps.Map(document.getElementById('mymap'), {
zoom: 15,
center: cent
});
$.each( markers, function( index, value ){
var lokasi = new google.maps.LatLng({{$order[0]->Latitude }}, {{ $order[0]->Longitude }});
var marker = new google.maps.Marker({
position: lokasi,
map: map
});
});
}
For now it can only return 1 marker, because i was using this
var lokasi = new google.maps.LatLng({{$order[0]->Latitude }}, {{ $order[0]->Longitude }});
I understand I need to remove the 0 to get the rest, however i got an error which reads:
Property [Latitude] does not exist on this collection instance.
I also understand that to remove that error, I need to put them in a blade foreach, my question is, how do we insert blade in script tags? If impossible, what can I do? thanks in advance
In the blade you can simple add tag everywhere that you need:
<script>
var app = 'dd';
</script>
this Code can add in for each and you add scripts that is related to Google map
here you can learn more about blade template system: https://laravel.com/docs/5.5/blade#displaying-data
I would suggest you to make an multi dimensional array of lat long and assign to jquery var
var marker_arr = '{{$marker_locations}}'
and at apply for loop on script to place marker on that location.
Hope this helps you.

Google Maps - how to set the zoom level [duplicate]

This question already has answers here:
How to set zoom level in google map
(6 answers)
Closed 6 years ago.
I have been trying for 4+ years to figure out how to use google maps. Im beyond ecstatic to have finally become able to generate a map wiht the correct address.
This is my javascript.
I'm now struggling with how to set the zoom level. I've tried it in each of the places I've shown below - but none of them work. In each case (regardless of the number I set as the zoom level) I get a really close up map of the specific building.
Can anyone see what I'm doing wrong, or what I need to do in order to get my map to recognise my request for a zoom level? I don't get any js errors showing in the console.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5
});
var bounds = new google.maps.LatLngBounds();
// var opts = {
// zoom: 10,
// max_zoom: 16
// }
var n = addresses.length;
for (var i = 0; i < n; i++) {
var lat = addresses[i].latitude;
var lng = addresses[i].longitude;
if (lat == null || lng ==null){
console.log(addresses[i].name + " doesn't have coordinates");
}else {
var address = new google.maps.Marker({
position: {lat: parseFloat(lat), lng: parseFloat(lng)},
title: addresses[i].name,
map: map //,
// zoom: 8
});
bounds.extend(address.position);
}
}
map.fitBounds(bounds);
}
Note in response to why this question is different to many others asked on SO. I am specifically struggling with how and where to use the features provided in this JS. I can't understand any of the JS I have managed to generate - the version above is the result of 4+ years of effort in trying to learn. I can't take generic ideas in other posts and apply them as easily as others may be capable of doing. Please bear with me as I try to learn to decipher how to communicate with these languages. It's not something that I've been able to grasp readily.
Also, and specifically to the point in the answer you have flagged - maybe the code was good at the point in time the question was asked, but it looks from the google library that the correct expression should be "zoom:4" not setZoom(something). I tried both and can't get either of them to work in my code.
XOMENA'S SUGGESTION
Taking Xomena's suggestion, I tried to define zoom and center in my map function (although I'm not suer if I've done this in the correct place).
This doesnt work. The console shows an error with my js file that says:
Uncaught SyntaxError: Unexpected identifier
Now, my js file has:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
setZoom: 5
setCenter = addresses.first
});
var bounds = new google.maps.LatLngBounds();
// var opts = {
// zoom: 10,
// max_zoom: 16
// }
var n = addresses.length;
for (var i = 0; i < n; i++) {
var lat = addresses[i].latitude;
var lng = addresses[i].longitude;
if (lat == null || lng ==null){
console.log(addresses[i].name + " doesn't have coordinates");
}else {
var address = new google.maps.Marker({
position: {lat: parseFloat(lat), lng: parseFloat(lng)},
title: addresses[i].name,
map: map //,
// zoom: 8
});
// bounds.extend(address.position);
}
}
// map.fitBounds(bounds);
}
I can't find an example of how to set this up to work. I've tried putting the set zoom and set centre lines in each block of text in this js file, but I can't find a formulation that works.
NEXT ATTEMPT
I tried moving my application javascript include tag out of the head tag and beneath the body tags on my application.html.erb.
Now, I have an error that says:
js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:95 Uncaught Eb {message: "initMap is not a function", name: "InvalidValueError", stack: "Error↵ at new Eb (https://maps.googleapis.com/m…3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:130:73"}message: "initMap is not a function"name: "InvalidValueError"stack: "Error↵ at new Eb (https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:41:365)↵ at Object._.Fb (https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:41:475)↵ at Lg (https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:95:420)↵ at https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:130:58↵ at Object.google.maps.Load (https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:21:5)↵ at https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:129:20↵ at https://maps.googleapis.com/maps/api/js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:130:73"__proto__: ErrorLg # js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:95(anonymous function) # js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:130google.maps.Load # js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:21(anonymous function) # js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:129(anonymous function) # js?key=AIzaSyAleQgfNH3HRQVUCYnyAzp46xmXW7WrWrc&callback=initMap:130
kwift.CHROME.min.js:1271 Uncaught SyntaxError: Identifier 'findGoodContent' has already been declared
I have seen SO posts form others using angular (i don't use that) which suggest adding another js file to the view where the map is displayed.
Can anyone help solve this for rails where angular is not used?
The map.fitBounds() method adjusts the zoom level automatically to show all locations that you added into LatLngBounds. If you want to set zoom level yourself, don't use map.fitBounds() and use map.setZoom() method instead.
https://developers.google.com/maps/documentation/javascript/reference#Map

How to pass json data from the controller to javascript

In my cluster Table have cluster coordinates column name description,
i am directly storing coordinates in Json format like below is my cluster table ,using these coordinates i want to draw multiple cluster(polygons)
in google map,
id | description
----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | {"points":[{"lat":14.232437996569354,"lng":76.409912109375},{"lat":13.336175186494927,"lng":77.1185302734375},{"lat":12.961735843534294,"lng":77.596435546875},{"lat":12.511665400971031,"lng":76.904296875}]}
2 | {"points":[{"lat":14.232437996569354,"lng":76.409912109375}, {"lat":13.336175186494927,"lng":77.1185302734375},{"lat":12.961735843534294,"lng":77.596435546875},{"lat":12.511665400971031,"lng":76.904296875}]}
I need to draw multiple polygon
but i am trying get this json into rails controller using
controller code
query="select id,description from clusters;
#result=ActiveRecord::Base.connection.execute(query);
The problem i am facing here how to pass this #result to javascript
to draw multiple polygon in google map.
if copy this json into one varible in js i able to draw cluster but problem i am facing how pass this json data from database reading in controller to javascript in rails
my google map code in javascript if hard code json into one varible it is working but i need take this json from database how to pass json with id from controller to javascript
var obj=i need json to store here //this how to fetch json from controller to js
polygons = [];
for(var i = 0; i < obj.length; ++i){
//do something with obj[i]
for(var ind in obj[i]) {
console.log(ind);
var arr = new google.maps.MVCArray();
for(var vals in obj[i][ind]){
console.log(vals, obj[i][ind][vals].lat );
arr.push( new google.maps.LatLng( obj[i][ind][vals].lat, obj[i][ind][vals].lng ) );
}
}
polygons.push(arr);
}
polygons.forEach( function(polyPath) {
var polygon = new google.maps.Polygon({
paths: polyPath,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
I would suggest an ajax-load for points. Then you can use the JSON-Output for rendering the action. It could be:
render json: #result
Other solution: When you have the googlemaps code in your view you could assign a json-string from the db to a javascript-variable:
var json_string = '<%= #results.raw %>';

Google Maps API Polyline creation failing with "Uncaught TypeError: number is not a function"

I'm working a django project using the google maps JS api.
Basically what's going on here is that I'm creating a map centered at a point (works perfectly), drawing a bunch of points specified by the journey variable (value is substituted in by django template),
and then trying to draw a polyine between these points. (Fails to produce a polyline with a "Uncaught TypeError: number is not a function" at the JS console.)
The traceback at the JS console is pretty indecipherable to me, particularly due to all the .js files being minned.
When I log the path attribute of the polyline, and the coordinate I'm adding (as seen below), everything seems to work. I know the coord is formatted correctly, because I think Marker and Polyline should take the same datatype (LatLng) for their locations, and the Markers work fine. Anyone have any idea what's happening?
var mapOptions = {
center: { lat: 37.23112,
lng: -122.29398
},
zoom: 15
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Make the line that will trace the guys route:
var polyOptions = {
strokeColor: '#000000',
srokeOpacity: 1.0,
strokeWeight: 3
};
var poly = new google.maps.Polyline(polyOptions);
poly.setMap(map);
// Make an array of everywhere the lilguys has been. Passed into this django template as {"lat": 12, "lng": 8} objects.
var journey = [{"lat": 33.2389, "lng":-123.9349}, {"lat":32.928392, "lng":-122.29289}, {"lat":33.928982, "lng":-120.298392}];
var journey_markers = [];
// Draw all the placemarks
for (var i = 0; i < journey.length; i++) {
var coord = journey[i];
journey_markers.push(new google.maps.Marker({position: coord, map:map}));
var path = poly.getPath();
console.log(coord);
console.log(path);
path.push(coord);
}
Thank you!
EDIT:
I substituted the template variables in for what they evaluate to. This was checked by looking at the HTML source code in the browser, and confirmed to not be the source of the bug.
Figured out the answer. It seems to be that unlike Markers, the Polyine path requires google.maps.LatLng() objects rather than latlng literals.
The following fixes the issue:
...
// Draw all the placemarks
for (var i = 0; i < journey.length; i++) {
var coord = new google.maps.LatLng(journey[i].lat, journey[i].lng);
...

google maps middle of a polyline (centroid?)

I have a list of polylines, just like google maps does when I click on the polyline I want an infowindow to show up just where I clicked, and it works just fine with this function
function mapsInfoWindow(polyline, content) {
google.maps.event.addListener(polyline, 'click', function(event) {
infowindow.content = content;
infowindow.position = event.latLng;
infowindow.open(map);
});
}
the problem comes when I click on the list(using the same function for that), event obviously doesn't have the latLng, but I'd like infowindow to show up in the middle of the polyline anyway, just like it does when you click on the list in the google maps link I mentioned before.
Tried LatLngBounds(); but that gives the actuall center of the area the polylines create, not the middle I need.
Any idea how to do it?
So this is the(bit hacky) solution.
Use http://www.geocodezip.com/scripts/v3_epoly.js library, then count the total length of you polyline(various ways), divide it in half and call epoly's .GetPointsAtDistance() function upon it.
This should return LatLng point, but it acts a bit weird sometimes, returning two points or even turning that point somehow "broken". So the most secure thing you can do is probably this:
var pointInHalf = polyline.GetPointsAtDistance(polylineLength);
var pointCoordinate = new google.maps.LatLng(pointInHalf[0].lat(), pointInHalf[0].lng());
Well, better than nothing.
From http://www.geocodezip.com/v3_polyline_example_geodesic_proj.html
Without extensions and assuming the polyline is a straight line.
It is possible to convert the lat/lng coordinates to point plane (x,y) postions and calculate the average between the two. This will give you a central pixel position. You can then convert this position back to a latlng for map plotting.
var startLatLng = startMarker.getPosition();
var endLatLng = endMarker.getPosition();
var startPoint = projection.fromLatLngToPoint(startLatLng);
var endPoint = projection.fromLatLngToPoint(endLatLng);
// Average
var midPoint = new google.maps.Point(
(startPoint.x + endPoint.x) / 2,
(startPoint.y + endPoint.y) / 2);
// Unproject
var midLatLng = projection.fromPointToLatLng(midPoint);
var midMarker = createMarker(midLatLng, "text");
More information on changing the projection http://code.google.com/apis/maps/documentation/javascript/reference.html#Projection
So firstly you need to use the geometry library which calculates distances. Add libraries=geometry to your JS call, e.g.
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
Assuming you know the start point and end point for your polyline, you should be able to do this:
var inBetween = google.maps.geometry.spherical.interpolate(startLatlng, endLatlng, 0.5);
infowindow.position = inBetween;
I guess if you don't already know the start and end points, you could work it out from polyline.getPath().
to get the coordinates of your polyline you should do:
var widePath = new google.maps.Polyline({
path: waypointsCoordinates,
strokeColor: '#3366FF',
strokeOpacity: 0.0,
editable: true,
draggable: true,
strokeWeight: 3
});
and do:
var latLng [];
latLng = widePath.getPath().getArray();
Might be a bit old as well, but why not add the infobox on the click?
infowindow.setPosition(event.latLng);
infowindow.open(this.getMap());
If it's a click that is.

Categories

Resources