How can I detect when an element dynamically added has loaded? - javascript

Edit: added Handlebar template loading
I am trying to detect when a dynamically added element has been loaded (from a handlebars template), but the event never fires.
Here is the code:
var source = $('#mapTemplate').html();
var template = Handlebars.compile(source);
$('#wrapper').fadeOut(function() {
$('#wrapper').html(template());
$('#wrapper').fadeIn();
});
$('body').on('ready', '#mapCanvas', function() {
alert('Ready')
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("mapCanvas"),mapOptions);
})
What am I doing wrong?

Your template is available on the page immediately after the call to insert handlebar's template
$('#wrapper').html(template());
//#mapCanvas should be available
However, you're probably getting an error because you are telling the div to fade in and jQuery makes it invisible initially. Be sure to wait until the fadeIn finishes.
var source = $('#mapTemplate').html();
var template = Handlebars.compile(source);
$('#wrapper').fadeOut(function() {
$('#wrapper').html(template());
$('#wrapper').fadeIn(function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("mapCanvas"),mapOptions);
});
});

As you have discovered, there is no "ready" event when a template is loaded.
The usual solution to knowing when anything that is dynamically loaded is ready is to supply a completion callback function to the code that is doing the loading. When that callback is called, the content is available in the page. I don't know exactly how you're loading the handlebars template, but the handlebars functions I see for loading a template, all take a callback argument that is called after the template has been successfully loaded. You would then trigger your map logic from within that callback.
If you show us the code you're using for loading the template, we can be much more specific.
Now, that you've shown us the code, your template is already preloaded and you can restructure you code like this to add the mapping stuff as soon as the fadeIn has finished:
var source = $('#mapTemplate').html();
var template = Handlebars.compile(source);
$('#wrapper').fadeOut(function() {
$('#wrapper').html(template()).fadeIn(function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("mapCanvas"),mapOptions);
});
});

Related

Mapbox marker click event in Ionic 2 / Angular 2

I'm getting started with Ionic 2 / Angular 2 and trying to implement Mapbox into my app.
To display custom markers (code example here) Mapbox expects a DOM element, which, as far as I understand it, is not really the Angular way. I want to add a click event on the marker but because Mapbox uses elements, I'm not entirely sure how to approach this cleanly "the Angular way".
Basically, this is the latest version (showing the map and the marker works, but predictably when I click the marker the event listener can't find this.onMarkerClicked):
export class HomePage {
//(...)
refreshMapPosition() {
/*Initializing Map*/
mapboxgl.accessToken = this.config.mapbox_public_token;
this.map = new mapboxgl.Map({ /*https://www.mapbox.com/mapbox-gl-js/api/#map*/
style: 'mapbox://styles/mapbox/light-v9',
center: [this.Coordinates.longitude, this.Coordinates.latitude],
zoom: 16,
pitch: 80,
minZoom: 7.5,
maxZoom: 17,
container: 'map',
interactive: false,
});
var elCreature = document.createElement('div');
elCreature.className = 'icon-creature alpaca';
elCreature.addEventListener('click', function() {
this.onMarkerClicked();
});
var markerCreature = new mapboxgl.Marker(elCreature, {offset: [-20, -20]})
.setLngLat([this.Coordinates.longitude, this.Coordinates.latitude])
.addTo(this.map);
}
onMarkerClicked() {
console.log("click");
}
}
I'd be much happier if it was possible to have elCreature coming from a component, where I could use <div class="icon-creature alpaca" (click)="onMarkerClicked"></div>. What's the best approach there?
// on your marker HTML
var _self = this;
var _data = this.value;
el.addEventListener('click', function() {
self.markerClicked(_data);
});
// angular method
markerClicked(value){
console.log(value);
}
So I found something that maybe could help you, I created a marker as the documentation mentioned and then I got the element of that market with the getElement() function, after that I added the event to the marker, I do not know if it works with various markers but you can try.
var marker = new mapboxgl.Marker()
.setLngLat([lng, lat])
.addTo(this.map);
marker.getElement().addEventListener("click", function(){
console.log("function");
});
After sleep a while I found that there another thing that you can use, so you can create a Popup first and then add that Popou to a Marker object with the setPopup() method and actually it like an onClick event, because, when you click the Marker the Popup appears. Here is an example.
var popup = new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML("<h1>Hello</h1>");
var marker = new mapboxgl.Marker()
.setLngLat(coordinates)
.setPopup(popup)
.addTo(this.map);
The variable "coordinates" is an array, such that coordinates = [lng,lat], and this.map is just a variable under my Angular class that call to the mapboxgl.Map object.
You have to know that I am using Ionic 4 in this case. If you need more information please tell me.
Regards.

Load Google Map in new window by appending a button

I'm trying to append a button to a page that when clicked will display my google map in a new page. I have a button that when clicked either gives an error or gives a blank page.
My code:
$('.content--body__wrapper').append('<button id="show-map" />')
$('.content--body__wrapper').append(`<script>
document.getElementById("show-map").addEventListener("click", function(){
var center = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: center
});
var marker = new google.maps.Marker({
position: center,
map: map,
});
})
</script>`);
$('.content--body__wrapper').append(`<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBcwtM8EBe7BE1NyPbU5SDYVYoBBtbtpTI&libraries=drawing" asyncdefer></script>`);
Error Code:
Edit: I took the callback out of the script source and I still don't get a page to load but I do have a lot less errors.
$('.content--body__wrapper').append('<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBcwtM8EBe7BE1NyPbU5SDYVYoBBtbtpTI&libraries=drawing&callback=initMap" async defer></script>');
In this line you say : when the API is loaded run the function called InitMap.
The problem is that this function is not definied in your js.
So remove this callback to use the documentReady event or remove documentReadyListener and create a function name initMap

Google map on page loaded by AJAX - how to initialize?

I'm having a bit of trouble getting a google map to initialize on a page loaded by AJAX.
Live test page (in dev): http://dma.nz/practice/
The map is near the bottom of the page.
Currently it works - the map initializes when page it loaded directly or via AJAX, however it's giving me the following error in console:
Uncaught TypeError: Cannot read property 'firstChild' of null
In my footer I have:
<script src="/js/map.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBpC5JE9ZmQduEXiGbiNxZsws8OLMiC-Bw&callback=initMap" async defer></script>
<script src="/js/init.js"></script>
map.js contains:
function initMap() {
var mapOptions = {
zoom: 17,
center: new google.maps.LatLng(-36.85855, 174.754944),
disableDefaultUI: true,
styles: [
{"featureType":"administrative",
"elementType":"labels.text.fill",
"stylers":[{"gamma":"0.00"},{"weight":"0.01"},{"visibility":"off"}]
},
{"featureType":"landscape",
"elementType":"all",
"stylers":[{"color":"#ffffff"}]
},
{"featureType":"landscape.natural",
"elementType":"geometry",
"stylers":[{"visibility":"on"}]
},
{"featureType":"landscape.natural.terrain",
"elementType":"geometry.stroke",
"stylers":[{"visibility":"on"}]
},
{"featureType":"poi",
"elementType":"all",
"stylers":[{"visibility":"off"}]
},
{"featureType":"road",
"elementType":"all",
"stylers":[{"saturation":"-100"},{"lightness":"32"},{"visibility":"on"}]
},
{"featureType":"road",
"elementType":"labels.text",
"stylers":[{"visibility":"off"}]
},
{"featureType":"road.highway",
"elementType":"all",
"stylers":[{"visibility":"simplified"}]
},
{"featureType":"road.highway",
"elementType":"geometry",
"stylers":[{"visibility":"on"},{"lightness":"63"}]
},
{"featureType":"road.highway",
"elementType":"labels.text",
"stylers":[{"visibility":"off"}]
},
{"featureType":"road.highway",
"elementType":"labels.icon",
"stylers":[{"visibility":"off"}]
},
{"featureType":"road.arterial",
"elementType":"labels.icon",
"stylers":[{"visibility":"off"}]
},
{"featureType":"transit",
"elementType":"all",
"stylers":[{"visibility":"off"}]
},
{"featureType":"transit.station",
"elementType":"all",
"stylers":[{"visibility":"off"}]
},
{"featureType":"water",
"elementType":"all",
"stylers":[{"visibility":"on"},{"color":"#eeeeee"}]
}
]
};
// Get the HTML DOM element that will contain your map
var mapElement = document.getElementById('google-map');
// Create the Google Map using our element and options defined above
var map = new google.maps.Map(mapElement, mapOptions);
// Add marker
var marker = new google.maps.Marker({
icon: '/img/icons/map-pin.svg',
position: new google.maps.LatLng(-36.858749, 174.754944),
map: map,
title: 'DMA'
});
}
And then the related part of init.js
ajaxLoad = function(html) {
init();
// init google map
initMap();
// change html title
var HTMLtitle = $(".content > section:first-of-type").attr("data-title");
$(document).prop('title', HTMLtitle);
document.title = HTMLtitle;
// Used for popState event (back/forward browser buttons)
changedPage = true; }
The callback on my google maps API script call appears to properly initialize the map if page is loaded directly. If page is loaded by AJAX that doesn't work so I added the line initMap(); there to load the map after the new content is loaded via AJAX.
This is working, but throwing an error and I'm worried that this error is causing other script on my page not to work properly.
Any ideas on how to modify this so that the map initializes regardless of whether the page is loaded directly or by AJAX, and doesn't create any JS errors? Thanks!
I reproduced the error when I switched from the http://dma.nz/practice/ page to http://dma.nz/projects/ page.
As I can see you try to initialize map instance in line 82 of your map.js. The problem here is missing element with id "google-map". You don't have any DOM element with id "google-map" when you load the projects page. So you try to pass null in map constructor.
To avoid this error add a check that DOM element with id "google-map" exists.
// Get the HTML DOM element that will contain your map
var mapElement = document.getElementById('google-map');
if (mapElement) {
// Create the Google Map using our element and options defined above
var map = new google.maps.Map(mapElement, mapOptions);
// Add marker
var marker = new google.maps.Marker({
icon: '/img/icons/map-pin.svg',
position: new google.maps.LatLng(-36.858749, 174.754944),
map: map,
title: 'DMA'
});
}

How to stop run javascript function when asp.net webform loaded?

I'm write this code for show my position on the map:
<script src="http://maps.googleapis.com/maps/api/js"></script>
<script>
function initialize(x, y) {
alert(x);
alert(y);
var mapProp = {
center: new google.maps.LatLng(x, y),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
up code run the initialize function when page load or postback,but i write this code for asp button:
Page.ClientScript.RegisterStartupScript(this.GetType(), "beh", "initialize(38.076306,46.279637);", true);
and i want when button fire,send value to function and java script function change the map position,it's work,but when button fire,function run ,and run again when web form loaded!,and in first time show correct position,but when page load event occurred,send null value to function and show empty position, i think when run java script function in asp button fire,and not run java script function when page load occurred?
The problem with your code is the execution order of the code blocks. Execution time of code that is added via the ClientScriptManager.RegisterStartupScript according to the msdn:
The script block added by the RegisterStartupScript method executes when the page finishes loading but before the page's OnLoad event is raised.
So, you could solve your problem by adding a boolean variable in your script tag (which get's executed while the page is loading), set it to false initially and change it to true in your button click handler (which is executed once the page has finished loading). Then in your window.onload event listener, check if the variable is false. If it is, you can initialize the map.
So, your javascript would change to this:
<script>
var isButtonClick = false;
function initialize(x, y) {
var mapProp = {
center: new google.maps.LatLng(x, y),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
}
google.maps.event.addDomListener(window, 'load', function () { if(!isButtonClick)initialize(0, 0) });
</script>
and your button click handler to this:
void ButtonClick(object sender, EventArgs e)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "beh", "isButtonClick=true;initialize(38.076306,46.279637);", true);
}
I tested it locally and it worked fine

Getting events of a JS object using jQuery

Hi I am using the following code to
var view = new storeLocator.View(); //it has an event called load
$(view).on("load",function(){
alert("Gochcha!!");
return true;
})
But I don know why I never get the alert to fired ? Can anybody please tell me what am I missing ?
I think the code snippet din make things clear. Lemme share the entire code I am trying:
google.maps.event.addDomListener(window, 'load', function() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(-28, 135),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var panelDiv = $('#panel');
var data = new MyDataSource;
var view = new storeLocator.View(map, data, {
geolocation: true,
features: data.getFeatures()
});
$(view).on("load",function(){
alert("Gochcha!!");
return true;
})
});//End of map load
What I am trying is not Triggering the event, but binding my function to an event of a javascript object, so that whenever the event fires I get my function called first and then continue what it was suppose to do. The even does fire as I see the map and the data get loaded but I am not getting my function to get working.
make sure the context in which you are raising the event is the view otherwise this wont get caught

Categories

Resources