Google Maps Problem with Zend Framework - php

Hi I am having issues inserting a map from google maps and using the send framework.
My issue is similar to Question 921811
However when adding the script to my view I am getting the googlemaps api in twice and no map being rendered by the view.
This is what I am adding to the view script
<?php
$this->headScript()->appendFile('http://maps.google.com/maps?file=api&;v=2&;sensor=true&;key=ABQIAAAAHSJ3TgOTyvA1VzwU8g4Y7RT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRmCy1h3nGv3n46kcqaFljsimqfWw');
$this->headScript()->appendScript(' var map = null;
var geocoder = null;
function initialize() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
geocoder = new GClientGeocoder();
}
}
function showAddress(address) {
if (geocoder) {
geocoder.getLatLng(
address,
function(point) {
if (!point) {
alert(address + " not found");
} else {
map.setCenter(point, 13);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(address);
}
}
);
}
}
');
?>
However this is adding the maps API in twice with a lot of escaped html, which is causing the maps to fail to load. e.g.
<script type="text/javascript" src="<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=true&amp;key=ABQIAAAAHSJ3TgOTyvA1VzwU8g4Y7RT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRmCy1h3nGv3n46kcqaFljsimqfWw" type="text/javascript"></script>"></script>
<script type="text/javascript" src="http://maps.google.com/maps?file=api&;v=2&;sensor=true&;key=ABQIAAAAHSJ3TgOTyvA1VzwU8g4Y7RT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRmCy1h3nGv3n46kcqaFljsimqfWw"></script>
<script type="text/javascript">
//<!--
var map = null;
var geocoder = null;
function initialize() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
geocoder = new GClientGeocoder();
}
}
.....
Any idea why the google maps API is being added twice with the escaped html tags? I have no idea and the examples I have found don't seem to have this issue.
Thanks in advance

The reason you're not seeing any map is because the URL in your appendFile() call is broken. Remove all the semi-colons:
http://maps.google.com/maps?file=api&v=2&sensor=true&key=whatever
That will fix the second <script> tag and make the Google map actually work.
That still leaves you with the first <script> tag, though. But that must be related to how you're actually printing the contents of the HeadScript view helper. Can you show us what that code looks like?

Related

Distance between a searched address and nearest existing placemark on a google maps api v3

I'm developing a web page with a Google Maps API v3. I currently have a functional map and search bar. I need to be able to display the distance from a searched address to the nearest placemark on one of the KML files on the map. How can I do this?
Here is the code for the page:
<script type="text/javascript">
var geocoder;
var map;
var marker;
var layers = [];
function initialize() {
geocoder = new google.maps.Geocoder ();
var latlng = new google.maps.LatLng (41, -73.4);
var myOptions = {
zoom: 7,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
marker = new google.maps.Marker({map:map});
layers[0] = new google.maps.KmlLayer('http://dl.dropbox.com/u/80233620/South-and-North-County-Trailway.kml',
{preserveViewport: true});
layers[1] = new google.maps.KmlLayer('http://www.nyc.gov/html/dot/downloads/misc/cityracks.kml',
{preserveViewport: true});
layers[2] = new google.maps.KmlLayer('http://dl.dropbox.com/u/80233620/NWS%20Radar%20Images.kmz',
{preserveViewport: true});
for (var i = 0; i < layers.length; i++) {
layers[i].setMap(map);
}
}
function codeAddress () {
var address = document.getElementById ("address").value;
geocoder.geocode ( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results [0].geometry.location);
marker.setPosition(results [0].geometry.location);
map.setZoom(14);
}
else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function toggleLayer(i) {
if(layers[i].getMap() === null) {
layers[i].setMap(map);
}
else {
layers[i].setMap(null);}
}
</script>
You cannot access the data in KML layers like that
https://developers.google.com/maps/documentation/javascript/layers#KMLLayers
Because KML may include a large number of features, you may not access
feature data from the KmlLayer object directly. Instead, as features
are displayed, they are rendered to look like clickable Maps API
overlays.
Instead you can process the XML and add markers manually, then use the geometry library and computeDistanceBetween() to get the distance. I usually multiply the distance by some number to account for turns (The distance formula gets a straight line distance). I believe around 1.2 was the most accurate.

How to locate places nearby to my custom markers

I have a webapp that creates markers on a google map and I'm wondering if there is some way to locate place nearby my custom markers so users can see what is around them.
Thank you in advance,
Robert
The Places Libraryapi-doc provides the information you seek. You load the library by adding the libraries=places parameter to the URL that loads the Google Map, as shown here:
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false">
</script>
And then you request data about places using code similar to this, copied from the Place Search Requests section of the Developer's Guide, which will search for stores within 500 meters of the point defined in the variable pyrmont:
var map;
var service;
var infowindow;
function initialize() {
var pyrmont = new google.maps.LatLng(-33.8665433,151.1956316);
map = new google.maps.Map(document.getElementById('map'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: pyrmont,
zoom: 15
});
var request = {
location: pyrmont,
radius: '500',
types: ['store']
};
service = new google.maps.places.PlacesService(map);
service.search(request, callback);
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
var place = results[i];
createMarker(results[i]);
}
}
}

Google Maps Geocoder not giving results

I am using Google Maps V3 API and using its Geocoder to do reverse geocoding of the point on the map where the user clicks on.
Load the geocoding function when DOM is fully loaded
$(function() {
reverse_geocode(40.714224,-73.961452);
});
Function that does the reverse geocoding:
function reverse_geocode(lat,lng) {
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(10,-10);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
alert('asdasd');
} else {
alert("Geocoder failed due to: " + status);
}
});
}
If I call the reverse_geocode function when the page first loads, everything works fine and the alert() is called.
However, if I call reverse_geocode() only when triggered by a rightclick on the map followed by a mouseclick on a div, using the code below, nothing happens! Any idea what went wrong?
google.maps.event.addListener(map, "rightclick", function(event) {
//some code not shown
$("#info_rightclick_top").click(function(e) {
info_ok_handleclick();
});
});
function info_ok_handleclick() {
$("#info_ok").click(function(e) {
var lat = marker_search_location.getPosition().lat();
var lng = marker_search_location.getPosition().lng();
var latlng = lat + "_" + lng;
reverse_geocode(10,-10);
// some code hidden
});
Using this bellow code you can search a location by keywords.
<?php
include_once("include/GoogleMap.php");
include_once("include/JSMin.php");
$mapcity="India";
$mapdesc="description about this map";
$MAP_OBJECT = new GoogleMapAPI();
$MAP_OBJECT->_minify_js = isset($_REQUEST["min"])?FALSE:TRUE;
$MAP_OBJECT->addMarkerByAddress($mapcity,"Map name", $mapdesc);
$MAP_OBJECT->enableStreetViewControls();
?>
<html>
<head>
<?=$MAP_OBJECT->getHeaderJS();?>
<?=$MAP_OBJECT->getMapJS();?>
</head>
<body>
<?=$MAP_OBJECT->printOnLoad();?>
<?=$MAP_OBJECT->setMapType(ROADMAP);?>
<?=$MAP_OBJECT->printMap();?>
<?=$MAP_OBJECT->printSidebar();?>
</body>
</html>

Google Maps load issues on PHP page

I'm connecting a Google Map to a MySQL database to list distributors all over the world, and I seem to be having a few issues.
Sometimes the page itself will not load at all in Firefox (v4 on Mac). It's temperamental on my machine (FF v3.6 Mac) and a Windows machine (FF v4 Win 7), ok in Safari/Opera, doesn't load at all in IE 9 (Win 7). Not sure if it's a network issue or code.
Load time is pretty slow. Might be because the map covers the whole page (will create a square block to place it in).
The URL of the page is here and I used the code from Sean Feeney's page.
The code I have is:
<script src="http://maps.google.com/maps?file=api&v=2&key=<I entered my key here>" type="text/javascript"></script>
<body onUnload="GUnload()">
<div id="map" style="position:absolute;top:0px;bottom:0px;left:0;right:0;"></div>
</body>
<script type="text/javascript">
//<![CDATA[
var map;
var latlngbounds;
if (GBrowserIsCompatible()) {
function createMarker(point, address) {
var marker = new GMarker(point);
var html = address;
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
function extendBounding(point) {
latlngbounds.extend(point);
var zoom = map.getBoundsZoomLevel(latlngbounds);
if (zoom < 10) {
zoom = 12;
}
map.setCenter(latlngbounds.getCenter(), zoom);
}
}
map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl3D());
map.addControl(new GMapTypeControl());
latlngbounds = new GLatLngBounds();
GDownloadUrl("genxml.php", function(data) {
var xml = GXml.parse(data);
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var address = markers[i].getAttribute("address");
var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var marker = createMarker(point, address);
map.addOverlay(marker);
extendBounding(point);
}
});
}
//]]>
</script>
The code that gets the data is the same as the example.
Any ideas as to why it doesn't always load in the browsers, and why it seems to take a while to load?
Thanks,
Adrian
Ideally you should wrap the code that loads the map inside a document ready or window load event.
I notice that your code is not nested properly inside the GBrowserIsCompatible() block so please fix that.
As far as I remember, Google maps API v2 requires you to call the setCenter() method before doing any operations on the map. So to begin with, set the center to (0, 0) immediately after creating the map.
I notice that you're downloading XML data before you add markers to the map. You must take into account the time taken by the server to serve the XML data. If you've called the setCenter() before downloading the XML, the map will display while the XML downloads asynchronously.
Inside the code that handles the XML data: when you add a marker, do not call setCenter() immediately. Doing so will cause the function to be called 1000 times if you have 1000 markers in your XML. Instead, just call latlngbounds.extend(point). Once you have iterated the loop, calculate the zoom/center and call setCenter(). This way you will end up calling this function only twice.
Edit
I've figured out what the problem is. The genxml.php randomly returns the string Google Geo error 620 occurred which cannot be parsed as XML which raises JavaScript errors and no markers are shown. Better have a look at the code of that file and see why this happens randomly. On other times when that file actually returns valid XML, the markers appear as expected.
It appears Google recently tightened geocoding requests. If you send 10 too fast, it cuts you off with 620 error. The solution they recommend is adding a dynamic timer. Other stackoverflow posts suggested a 0.25 second static timer was good enough, but I've found Google's recommendation of using a while loop that increments the timer value as needed works better. For example:
// Initialize delay in geocode speed
public $delay = 0;
public function lookup(arguments)
{
$geocode_pending = true;
while ($geocode_pending) {
$search = //address string to search;
$response = $this->performRequest($search, 'xml');
$xml = new SimpleXMLElement($response);
$status = (int) $xml->Response->Status->code;
switch ($status) {
case self::G_GEO_SUCCESS:
require_once('placemark.php');
$placemarks = array();
foreach ($xml->Response->Placemark as $placemark)
$placemarks[] = Placemark::FromSimpleXml($placemark);
$geocode_pending = false;
return $placemarks;
case self::G_GEO_TOO_MANY_QUERIES:
$delay += 100000;
case self::G_GEO_UNKNOWN_ADDRESS:
case self::G_GEO_UNAVAILABLE_ADDRESS:
return array();
default:
throw new Exception(sprintf('Google Geo error %d occurred', $status));
}
usleep($delay);
}
}
You can run your map code with window.load after everything is loaded:
jQuery(document).ready(function initAutocomplete() {
var p_lag=$('#longitude').val();
var p_lat=$('#latitude').val();
if(p_lat==''){
var p_lat=20.593684;
}
if(p_lag==''){
var p_lag=78.96288000000004 ;
}
var myLatLng = {lat: p_lat,lng: p_lag};
var map = new google.maps.Map(document.getElementById('dvMap'), {
center: myLatLng,
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: myLatLng,
draggable: true,
map: map,
title: 'Map'
});
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
//map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function () {
searchBox.setBounds(map.getBounds());
});
//Click event for getting lat lng
google.maps.event.addListener(map, 'click', function (e) {
$('input#latitude').val(e.latLng.lat());
$('input#longitude').val(e.latLng.lng());
});
google.maps.event.addListener(marker, 'dragend', function (e) {
$('input#latitude').val(e.latLng.lat());
$('input#longitude').val(e.latLng.lng());
});
var markers = [];
// [START region_getplaces]
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function () {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
/*markers.forEach(function (marker) {
marker.setMap(null);
});*/
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function (place) {
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
$('#latitude').val(place.geometry.location.lat());
$('#longitude').val(place.geometry.location.lng());
marker.setPosition(place.geometry.location);
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
map.fitBounds(bounds);
});
});
}
);

Problem with loading google map v3 asynchronously

My current solution for loading Google map scripts, is the old fashion way.
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
But this takes to long and rendering content is delayed. Then I looked at the Google Map Documentation and discovered how one can load the Goole Map javascripts asynchronously.
So I tested this in the javascript I'm already using. This is just snippets of my script.
jQuery(document).ready(function() {
googleMaploadScript();
someFunction();
}
// Script for loading googlemap with callback to initialize Google map
function googleMaploadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.google.com/maps/api/js?sensor=true&callback=initGoogleMap";
document.body.appendChild(script);
}
// Some function that calls populateGeoMap()
function someFunction() {
(...)
populateGeoMap();
}
// Script for populating google map with locations
function populateGeoMap() {
// This is where I initialized google map each time I load the page using google map
// But since I'm using a callback, I've commented this out.
//initGoogleMap();
var lat = '12.142123';
var lng = '54.524522';
latLng = new google.maps.LatLng(lat,lng); <-- THIS FAILS
}
// Google map init
function initGoogleMap() {
alert('test'); <-- THIS ALERT IS NEVER TRIGGERED
options = {zoom: 13, mapTypeId: google.maps.MapTypeId.ROADMAP }
map = new google.maps.Map(document.getElementById("map_canvas"), options);
geocoder = new google.maps.Geocoder();
icon = new google.maps.MarkerImage("http://mysite.com/img/pin_red.png", null, null, null, new google.maps.Size(32, 32));
bounds = new google.maps.LatLngBounds();
}
My script fails at new google.maps.LatLng(lat,lng); and this is because initGoogleMap() has not been run.
It seems that the callback in the script.src did not work - because my alert is never fired. Or it might be because things are not laoded in the correct order, but still, the alert should have been triggered.
Does anyone have experience with this?
I had the same problem and worked it out like this:
the problem is the fact that you can't get to the jQuery object itself from outside jQuery.
the API callback attribute at the end has only access to the global javascript. read up opn javascript namespace to understand better.
my solution is to set up a global object outside of the $document.ready(function(){...
var global = {};
next, you write the init function inside your jQuery block for the map as a variable and attach it to the global object:
global.initMap = function(){ ...}
now you can reference your jquery function as a global variable in the url query string like this:
...&callback=global.initMap
this worked for me.
tim's suggestion is excellent!
This is working asynchronous (lazy loading) of google maps v3 script with jQuery based Google Maps plugins.
This way no script except head.js+jquery.js are blocking the page and google maps starts loading as soon as is possible.
window.load should be accessed quickly. tested on ffox 12, ie7,8,9 and chrome 18.
due to some issues with ie7,8 it was not possible to load jquery.js asynchronously :/
//////////////////// lazy loaded google map
// load head.js normally before this code.
// due to IE7,8 or head.js bug you HAVE TO load normally jQuery too:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="/PATH/head.js"></script>
// load rest of your javascript using head.js function
head.js("yourscripts.js");
// IMPORTANT: google map plugin must be tagged like this:
head.js({gmap:"YOUR_PATHs/jquery.mapka.v3-rc.js"});
var global = {};
global.googlemaps_init = function(){
head.ready("gmap", function() {
// jquery-ui-map v3 init of google maps (place YOUR jQuery based google maps plugin init here)
$('#map_canvas').gmap({ 'center': '42.345573,-71.098326' });
}); // head.gmap.ready END
} // global.googlemaps_init END
function loadGmapScript() {
var global = {};
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?&sensor=false&callback=global.googlemaps_init";
document.body.appendChild(script);
}
window.onload = loadGmapScript;
//////////////////// lazy loaded google map END
This is because you're trying to initialize an object that you don't have access to. Try moving the GA functions into the document.onready block:
$(function(){
// Script for loading googlemap with callback to initialize Google map
function googleMaploadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.google.com/maps/api/js?sensor=true&callback=initGoogleMap";
document.body.appendChild(script);
}
// Some function that calls populateGeoMap()
function someFunction() {
(...)
populateGeoMap();
}
// Script for populating google map with locations
function populateGeoMap() {
// This is where I initialized google map each time I load the page using google map
// But since I'm using a callback, I've commented this out.
//initGoogleMap();
var lat = '12.142123';
var lng = '54.524522';
latLng = new google.maps.LatLng(lat,lng); <-- THIS FAILS
}
// Google map init
function initGoogleMap() {
alert('test'); <-- THIS ALERT IS NEVER TRIGGERED
options = {zoom: 13, mapTypeId: google.maps.MapTypeId.ROADMAP }
map = new google.maps.Map(document.getElementById("map_canvas"), options);
geocoder = new google.maps.Geocoder();
icon = new google.maps.MarkerImage("http://mysite.com/img/pin_red.png", null, null, null, new google.maps.Size(32, 32));
bounds = new google.maps.LatLngBounds();
}
googleMaploadScript();
someFunction();
});
I think what happens is that you actually trigger "somefunction" before the map is loaded so JS fails and never actually executes the "initGoogleMap".
Place your somefunction at the end of the initGoogleMap like that:
google.maps.event.addListener(map, 'loaded', function(){
somefunction();
});
K
you can use the async mode when loading Google Maps api, you need to provide a callback function:
http://maps.googleapis.com/maps/api/js?sensor=true&callback=my_callback_function
Here http://lucamanzo-soluzione-software.it/wp/?p=5 you can find a simple jquery plugin showing all the steps to use the async loading and jquery, and building a map with just a few lines of code. Usage example:
$.gmapstools.init();
$("#my_map_canvas").gmap({lat:37.4221913, lng:-122.08458530000001, draw_marker:true, zoom_level:13});

Categories