I have a form that is dynamically inserted into the Google Map. However I cannot click any of the inputs. I believe I need to add a listener somewhere but I'm not sure.
Fiddle
function googlemap() {
// google map coordinates
var posY = 37.765700,
posX = -122.449134,
location = new google.maps.LatLng(posY,posX),
// offset location
posY = posY + 0.055;
offsetlocation = new google.maps.LatLng(posY,posX);
var mapOptions = {
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
draggable: true,
disableDoubleClickZoom: false,
scrollwheel: false,
zoom: 12,
center: offsetlocation,
// ROADMAP; SATELLITE; HYBRID; TERRAIN;
mapTypeId: google.maps.MapTypeId.ROADMAP
};
overlay.prototype = new google.maps.OverlayView();
// create overlay marker
overlay.prototype.onAdd = function() {
blip = document.createElement('div'),
pulse = document.createElement('div');
blip.className = 'blip';
pulse.className = 'pulse';
// createa dialog and grab contents from #mapcontents
boxText = document.createElement("div");
boxText.className = "dialog";
mapContents = $('#mapcontents').html();
boxText.innerHTML = mapContents;
$('#mapcontents').remove();
blip.appendChild(boxText);
// append 'blip' marker
this.getPanes().overlayLayer.appendChild(blip).appendChild(pulse);
}
// update blip positioning when zoomed
overlay.prototype.draw = function(){
var overlayProjection = this.getProjection(),
bounds = new google.maps.LatLngBounds(location, location),
sw = overlayProjection.fromLatLngToDivPixel(bounds.getSouthWest()),
ne = overlayProjection.fromLatLngToDivPixel(bounds.getNorthEast());
blip.style.left = sw.x + 'px';
blip.style.top = ne.y + 'px';
// shift nav into view by resizing header
var w = $('.dialog').width(),
w = (w / 2) + 25,
w = '-' + w + 'px';
h = $('.dialog').height(),
h = (h) + 100,
h = '-' + h + 'px';
$('.dialog').css({
'margin-top' : h,
'margin-left' : w
});
};
var map = new google.maps.Map(document.getElementsByClassName('map')[0], mapOptions);
// explicitly call setMap on this overlay
function overlay(map) {
this.setMap(map);
}
// center map when window resizes
google.maps.event.addDomListener(window, 'resize', function() { map.setCenter(location) });
// center map when zoomed
google.maps.event.addListener(map, 'zoom_changed', function() { map.setCenter(location) });
// I have nfi what I'm doing but I think this click listener is part of the solution.
google.maps.event.addListener('.dialog', 'click', function() {
alert('ok');
});
// process contact form
google.maps.event.addListener(map, 'domready', function() {
$('button').click(function(e) {
(e).preventDefault();
alert('ok');
return false;
var name = $(".contactform input[name='name']"),
email = $(".contactform input[name='email']"),
message = $(".contactform textarea[name='message']"),
error = false;
// clear validation errors
$('#contact input, #contact textarea').removeClass('error');
if(name.val().length < 1)
name.addClass("error");
if(!/^[a-zA-Z0-9._+-]+#[a-zA-Z0-9-]+\.[a-zA-Z]{2,4}(\.[a-zA-Z]{2,3})?(\.[a-zA-Z]{2,3})?$/.test(email.val()))
email.addClass("error");
if(message.val().length < 1)
message.addClass("error");
// if error class exists
if($(".error").length) return false;
$(this).attr('disabled', true).prepend('<i class="load animate-spin"></i>');
$.ajax({
type: "post",
dataType: "json",
url: "lib/sendmail.php",
data: $("#contactform").serialize()
})
.always(function(data) {
$('h5').animate({opacity:0},function(){
$('h5').text("Email Sent!!")
.animate({opacity:1});
});
$('.contactform').animate({opacity:0},function(){
$('.contactform').html("<p class='success'>Thank You for your form submission. We will respond as soon as possible.</p>")
.animate({opacity:1});
})
});
});
return false;
});
// add overlay
overlay = new overlay(map);
}
Any idea why I can't click the inputs?
You just need to block propagation of mousedown map event to make inputs clickable:
google.maps.event.addDomListener(blip, 'mousedown', function (e) {
e.cancelBubble = true;
if(e.stopPropogation) {
e.stopPropagation();
}
});
And you can do the same for dbclick to prevent map zooming: http://jsfiddle.net/gfKWz/1/
The click-events fire fine for all these inputs, the issue here at first is that your code will never execute, because there is no domready-event for a google.maps.Map
Change this:
google.maps.event.addListener(map, 'domready', function () {
into this:
google.maps.event.addListenerOnce(map, 'tilesloaded', function () {
for observation of the events you may use $.on(), e.g.:
$(map.getDiv()).on('click','button',function (e) {/*some code*/});
Demo: http://jsfiddle.net/doktormolle/jcfDu/
You use $('button').click which is triggered before the button is present on the dom. .click() binds the handler to all the current elements on the dom.
Better use $('button').on('click', function(){}); which binds the click event handler to all the current and future instances of button on your page. This is especially handy if you dynamically add content on the page. Through ajax or otherwise.
Read more about jQuery .on() in here http://api.jquery.com/on/
Your event has to be added in the onAdd function.
Currently, the event handler is created before the element. So it doesn't catch the click on this particular element.
http://jsfiddle.net/NeekGerd/duEEt/4/
Or you could create a new function for your overlay's bindings, just for the sake of clean-code :
overlay.prototype.onAdd = function() {
[...]
this.bindings();
}
overlay.prototype.bindings = function(){
$("button").on("click",function(){
alert("Click");
return false;
}
}
For now I have no real solution to your inputs problem.
Maybe by reattaching mousedownevents to them, and force them to focus():
$("input,textarea").on("mousedown",function(){$(this).focus();});
Same thing with your checkboxes.
On another note, since you use jQuery, why not use it all the way?
Like you can do:
$('#mapcontents')
.clone()
.wrap('<div class="dialog" />')
.wrap('<div class="blip />')
.appendTo( *selector* );
In order to quickly build some html and append it to the selected element. Much more readable (thus easier to maintain) than the DOM code you got there. Since you already use jQuery anyway.
Related
I'm trying to assign a unique ID to each feature that gets drawn on this Google Map, and then use the rightclick event to remove the feature that gets clicked on. Currently all features get removed, which is a problem.
Once the feature is added to the collection, I try to assign the unique ID:
var uniqueID = function() {
return ++currentID;
}
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
Then on rightclick event, I want to remove the feature that gets clicked on. I assumed you would need to have unique IDs for this step, hence the prior step.
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
Full code below.
JS:
var map;
var currentID = 0;
var uniqueID = function() {
return ++currentID;
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 4,
// only show roadmap type of map, and disable ability to switch to other type
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
});
map.data.setControls(['Polygon']);
map.data.setStyle({
editable: true,
draggable: true
});
bindDataLayerListeners(map.data);
//load saved data
loadPolygons(map);
}
// Apply listeners to refresh the GeoJson display on a given data layer.
function bindDataLayerListeners(dataLayer) {
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
dataLayer.addListener('setgeometry', savePolygon);
}
function loadPolygons(map) {
var data = JSON.parse(localStorage.getItem('geoData'));
map.data.forEach(function(f) {
map.data.remove(f);
});
map.data.addGeoJson(data)
}
function savePolygon() {
map.data.toGeoJson(function(json) {
localStorage.setItem('geoData', JSON.stringify(json));
});
}
initMap();
Original source: I built this example from a JSFiddle found in this thread.
your addfeature listener was wrong, as addListener takes only a single callback function, so you need to call e.feature.setProperty then savePolygon inside a single anonymous callback function
Note, you had event.feature.setProperty('featureID', uniqueID); - it needs to be event.feature.setProperty('featureID', uniqueID());
dataLayer.addListener('addfeature', function(event) {
event.feature.setProperty('featureID', uniqueID());
savePolygon(event);
});
Then, in the rightclick lsitener, you can simply get the geoData - filter out the clicked item, save the geoData and then dataLayer.remove(e.feature);
dataLayer.addListener('rightclick', function(e) {
var data = JSON.parse(localStorage.getItem('geoData'));
data.features = data.features.filter(function(feature) {
return feature.properties.featureID !== e.feature.getProperty('featureID');
});
localStorage.setItem('geoData', JSON.stringify(data));
dataLayer.remove(e.feature);
});
working fiddle
I use the jQuery Mobile in order to get the weather data from openweathermap.org and to display it. It works properly on IE10 but it doesn't work on IE11 . What can be the reason ? (It works in Chrome.) You can see the codes on http://jsfiddle.net/Gajotres/frSsS/
$(document).on('pageinit', '#index', function(){
$(document).on('click', '#city-search-btn', function(){
var cityName = $('#city-search').val();
if(cityName.length > 0) {
var url = 'http://api.openweathermap.org/data/2.5/weather?q='+cityName+'&units=metric';
$.ajax({
url: url,
dataType: "jsonp",
async: true,
beforeSend: function() {
// This callback function will trigger before data is sent
$.mobile.loading('show', {theme:"a", text:"Please wait...", textonly:false, textVisible: true}); // This will show ajax spinner
},
complete: function() {
// This callback function will trigger on data sent/received complete
$.mobile.loading('hide'); // This will hide ajax spinner
},
success: function (result) {
ajax.parseJSONP(result);
},
error: function (request,error) {
alert('Network error has occurred please try again!');
}
});
} else {
alert('Please enter city name!');
}
});
});
$(document).on('pagehide', '#map', function(){
$(this).remove();
});
$(document).on('pageshow', '#map',function(e,data){
var minZoomLevel = 12;
var myLatLng = new google.maps.LatLng(weatherData.response.coord.lat, weatherData.response.coord.lon);
var map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: minZoomLevel,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var image = {
url: 'http://openweathermap.org/img/w/'+weatherData.response.weather[0].icon+'.png'
};
infoWindow = new google.maps.InfoWindow();
infoWindow.setOptions({
content: "<div class='info-window'><div class='icon-holder'><img src='http://openweathermap.org/img/w/"+weatherData.response.weather[0].icon+".png'/></div><div class='info-holder'><span class='info-text'>City:</span><br/>"+weatherData.response.name+"<br/><span class='info-text'>Min. Temp:</span><br/>"+weatherData.response.main.temp_min+" °C<br/><span class='info-text'>Temp:</span><br/>"+weatherData.response.main.temp+" °C<br/><span class='info-text'>Max. Temp:</span><br/>"+weatherData.response.main.temp_max+" °C</div></div>",
position: myLatLng,
});
infoWindow.open(map);
});
var ajax = {
parseJSONP:function(result){
weatherData.response = result;
//alert(JSON.stringify(weatherData.response.weather[0].icon));
var mapPage = $('<div>').attr({'id':'map','data-role':'page'}).appendTo('body');
var mapHeader = $('<div>').attr({'data-role':'header', 'data-theme' : 'b','id':'map-header'}).appendTo(mapPage);
$('<h3>').html(weatherData.response.name + ' weather').appendTo(mapHeader);
$('<a>').attr({'href':'#index', 'class' : 'ui-btn-righ'}).html('Back').appendTo(mapHeader);
var mapContent = $('<div>').attr({'data-role':'content'}).appendTo(mapPage);
$('<div>').attr({'id':'map_canvas', 'style':'height:100%'}).appendTo(mapContent);
$.mobile.changePage( "#map", { transition: "slide"});
}
}
var weatherData = {
response : null
}
I don't know how much help this is, perhaps someone else will provide better explanation.
First of all looks like pageinit has been depreciated since jQuery.mobile 1.4.0: https://api.jquerymobile.com/pageinit/ They recommend replacing it with pagecreate
But the problem is obvious: neither pageinit nor pagecreate are firing in IE11. Therefore the button onlcick never gets bound. Not sure if it's IE bug or jsFiddle's...
Simply replacing pageinit with $(document).ready fixed the issue for me.
See fiddle: http://jsfiddle.net/frSsS/54/
I would like to grab an element based on the url hash, and fire the click of that element. I must be missing something, because I get the error:
Uncaught TypeError: Property '$' of object [object Object] is not a function
Here's the code
jQuery(function($){
function doUrl() {
var urlHash = window.location.hash;
if (urlHash != '') {
if ( $(urlHash).length > 0 ) {
$(urlHash).trigger('click');
}
}
}
doUrl();
});
}); // jquery
It seems that the error stems from urlHash not being an appropriate type of element to feed into $(). But the console tells me that the urlHash variable holds what I would expect it to: "#someClickableElement".
When I manually replace the urlHash variable with '#somepageid', the click event still does not fire on page load like I'd expect. So just to clarify, this does not work either:
$(function(){
$('#someClickableElement').click();
});
I can't quite tell where my problem is.
Edit
For those of you who want to see the whole code, here's a lot more of it:
var map;
function initialize() {
var mapOptions = {
zoom: 17,
center: new google.maps.LatLng(xxx,xxx),
mapTypeId: google.maps.MapTypeId.ROADMAP,
panControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
},
scaleControl: false,
mapTypeControl: false,
streetViewControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
}
// navigationControl: true, // (this is the pan and zoom together)
};
map = new google.maps.Map(document.getElementById('map-area'), mapOptions);
}
// init map
google.maps.event.addDomListener(window, 'load', initialize);
function findMapItem(lat,lon) {
var buildingLoc = new google.maps.LatLng(lat,lon);
map.panTo( buildingLoc );
removeAllMarkers();
// add new marker
buildingMarker = new google.maps.Marker({
map: map,
position: buildingLoc,
clickable: true,
icon: pathToAssets + 'bobcatMarker2.png'
//title: ,
})
buildingMarkers.push(buildingMarker);
}
jQuery(function($){
$('.mapItemsControls a').click(function(){
if ( $(this).hasClass('layerOn') ) {
$(this).removeClass('layerOn');
} else {
$('.mapItemsControls a').not(this).removeClass('layerOn');
$(this).addClass('layerOn');
}
doHistory( $(this).attr('href') );
return false;
});
$('#mapNav .findMapItem').click(function(){
var lat = $(this).data('lat');
var lon = $(this).data('lon');
if (lat != '' && lon != '') {
findMapItem(lat,lon);
}
});
function doUrl() {
var urlHash = window.location.hash;
if ( jQuery(urlHash).length > 0 ) {
jQuery(urlHash).trigger('click');
}
}
doUrl();
});
Make sure your click handler declaration comes before the doUrl() function call.
You can also greatly simplify that doUrl() function.
Click here for a working fiddle.
jQuery(function($){
$('#test').click(function() {
alert('No problems.');
});
function doUrl() {
$(window.location.hash).trigger('click');
}
doUrl();
});
I solved the problem by putting calling the function doUrl() inside the Google Maps init block. The functions that the click handler were calling were part of the google maps object and therefore couldn't fire until the Map had been initialized.
I'm unable to fire event on pano_change in the Streetview that is embedded in infowindow. I need to get the array getLinks() and getPosition() of the object StreetViewPanorama each time the user navigates in Streetview infowindow. It is declared as below. I really don't understand why (it works for events on marker and infowindow).
//code here
var contentString = '<input type="button" value="Grab this picture" onClick="captureImage()" /> <div id="content" style="width:200px;height:200px;"></div>';
//code here
var infowindow = new google.maps.InfoWindow({
content: contentString
});
//code here//
google.maps.event.addListener(infowindow, 'domready', function() {
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
pano = new google.maps.StreetViewPanorama(document.getElementById("content"), {
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: false,
addressControl: false,
linksControl: false
});
pano.bindTo("position", marker);
pano.setVisible(true);
});
You need to add google.maps.event.addListener(pano, 'links_changed', XXXX) and google.maps.event.addListener(pano, 'position_changed', XXXXX) in order to get the events.
Initialization
var pano = new google.maps.StreetViewPanorama(<element>, panoramaOptions);
google.maps.event.addListener(pano, 'pano_changed', function() {
// whatever
});
google.maps.event.addListener(pano, 'links_changed', function() {
var links = pano.getLinks();
for (var i in links) {
// whatever
}
});
google.maps.event.addListener(panorama, 'position_changed', function() {
var newPos = pano.getPosition();
});
google.maps.event.addListener(pano, 'pov_changed', function() {
var newPoV = panorama.getPov();
});
Now, every time you have a change in any of those three events (links, pov, position) the relevant function gets called.
have created a map that I'm trying to have function similar to 'My Maps'. I have two dropdownlists on the right side, based on the selection in those ddl's, you can add a custom marker / icon. You select a marker type, then click the '+' button in the top right corner of the map, and then click where you want the marker added. My issue is, this works fine in IE, Safari, and Chrome, but not in firefox. The click event doesn't seem to fire.
Here is the location of the map : https://ait.saultcollege.ca/Michael.Armstrong/Index.html
The button to add the marker in the top right has an onclick event pointing to my 'placeMarker()' function. Here is the code for placeMarker(), createMarker() ...
function placeMarker() {
select("placeMarker");
var infowindow = new google.maps.InfoWindow({});
var catID = document.getElementById('category');
var typeID = document.getElementById('ddlType');
var category = catID.options[catID.selectedIndex].value;
var markerType = typeID.options[typeID.selectedIndex].value;
if (!markerType) {
alert("You must select an icon type.");
}
else {
var moveListener = google.maps.event.addListener(customMap, 'mousemove', function(event) {
if (mapMarker) {
mapMarker.setPosition(event.latLng);
} else {
mapMarker = createMarker(event.latLng, "test", markerType, "test");
}
});
var clickListener = google.maps.event.addListener(customMap, 'click', function(event) {
if (mapMarker) {
select("hand_b");
google.maps.event.clearListeners(customMap, 'mousemove');
google.maps.event.removeListener(listener);
mapMarker = createMarker(event.latLng, "test2", markerType, "test");
var htmlInfo = "" +
"Category:" + category + "" +
"Item:" + markerType + "" +
"Notes:" +
"Location:" + mapMarker.getPosition().toString() + "" +
"" +
"";
//infowindow.setContent(htmlInfo);
//infowindow.open(customMap, mapMarker);
}
});
}
}
function createMarker(latlng, title, icon, html) {
var mapMarker = new google.maps.Marker({
position: latlng,
map: customMap,
title: title,
icon: 'Images/' + icon + '.png'
});
return mapMarker;
}
function select(buttonId) {
document.getElementById("hand_b").className = "unselected";
document.getElementById("placeMarker").className = "unselected";
document.getElementById(buttonId).className = "selected";
}
Any help or suggestions would be awesome. Could this perhaps be a bug in ff?
I did something very similar for an open-source disaster software package. In this case, lets assume I selected "Fire" in my dropdown menu and this triggers addFire(). The listener on the markers will delete the point on a click or allow you to drag it. The map can only have one listener at a time, but each marker can still have its own listener at the same time.
Here is the code that worked on Chrome, Firefox and IE8:
//This function sets up the map for adding a fire icon
function addFire() {
//Kill old listener
if(listening)
google.maps.event.removeListener(listenerhandle);
//Start new listener
listenerhandle = google.maps.event.addListener(disasterMap, 'click', addFirePoint);
listening = true;
}//end addFire
//This function adds new fire points to the map and controls dragging and clicking
function addFirePoint(event) {
//Create the marker
var fireMarker = new google.maps.Marker({
icon: "./mapimgs/fire.png", position: event.latLng, map: disasterMap, draggable: true });
newFireMarkers.push(fireMarker);
fireMarker.setTitle("Fire");
//Listen for clicks on the new marker
google.maps.event.addListener(fireMarker, 'click', function() {
fireMarker.setMap(null);
//remove the marker from the array
for(i=0;i<newFireMarkers.length;i++) {
if(fireMarker.getPosition() == newFireMarkers[i].getPosition()) {
newFireMarkers.splice(i,1);
break;
}
}
}
); //end click listener
}//end addFirePoint