onclick even after loading a map - ammap - javascript

I am using a small script I modified that uses ammaps library. I use the world map and if I click on certain countries it will load the country's map including the states.
Now, I am struggling on finding a solution to that after I opened a country and click on a state I want to use an onclick event then to just open up the appropriate website for that state. My jsfiddle is here http://jsfiddle.net/xzAx7/ and I would appreciate any help.
This is my code how I load new maps after I clicked on the country. These maps include the states.
map.addListener("clickMapObject", function (event) {
if (event.mapObject.id == "FR") {
loadNewMap("http://www.ammap.com/lib/maps/js/franceLow.js", "franceLow");
}
else if (event.mapObject.id == "RU") {
loadNewMap("http://www.ammap.com/lib/maps/js/russiaLow.js", "russiaLow");
}
else if (event.mapObject.id == "US") {
loadNewMap("http://www.ammap.com/lib/maps/js/usaLow.js", "usaLow");
}
});

I would move the handler to a separate function and would add another if, which would also check the id and generate url.
If you can not generate URL's automatically, then you should not use getAreasFromMap option but add each area in new data provider and set url property for the areas.

if (event.mapObject.id == "FR") {
map.clear();
map.dataProvider.mapVar = AmCharts.maps.franceLow;
map.write("mapdiv");
};

Related

How to setVisibility to a particular layer when clicked?- Openlayers

I have more than 10 layers , where i have to set one layer to visibility when clicked , I tried a code and its not working. I dont know how to make it better.
var mapClick = [layer1,layer2,layer3......]
if (mapClick == 'layer1'){
layer.setVisibility(true)
}
else {
layer.setVisibility(false)
}
You can modify layer visibility with layer.setVisible(true/false), not setVisibility.
Here the API reference: https://openlayers.org/en/latest/apidoc/module-ol_layer_Layer-Layer.html#setVisible

DOM elements manipulation with javascript persists after reload or going to next page in pagination

I am trying to toggle a view between grid and list view mode on my frontend HTML page. I am able to do this fine with dom and HTML classes manipulation by toggling "display: none" between two containers. However, when I go to the next product page(through pagination) or when I reload the page, the default view is the one that appears and not the one that was last toggled. Is there a way to persist the view in case a page reload or product pagination changes? thank you.
here is the dom code that achieves this :
viewList.addEventListener('click', function() {
this.classList.add('view__active');
viewGrid.classList.remove('view__active');
gridItem.classList.add('hidden');
listItem.classList.remove('hidden');
});
viewGrid.addEventListener('click', function() {
this.classList.add('view__active');
viewList.classList.remove('view__active');
gridItem.classList.remove('hidden');
listItem.classList.add('hidden');
});
So far I found that I have to use localStorage to achieve this. but is there a better way to do this?
Essentially what is happening is when you request something from the server, the server responds with an HTML document, and whichever scripts associated with that document is run, So whatever JS executed in the first request is not in context when the second request(paginate or reload) is made.
So you need a way to persist information across these page loads, For that, you have 3 options.
Use sessionStorage.
Use localStorage
Use Cookies.
Of the 3 above the easiest would be to use either option 1 or 2.
Replying to your comment,
Also, If I am using localStorage, What am I using to store the view state?
I'm not quite clear as to what you mean by "What you are using to store the state" If your question is about where your data is stored, you need not worry about it as this is handled by the browser. If your question is about "How" to store it you can go through the MDN docs attached in option 1 or 2. This is simply storing a key-value pair as shown in the docs
localStorage.setItem('preferedView', 'grid'); You can add this to your on click handlers as follows,
viewList.addEventListener('click', function() {
this.classList.add('view__active');
viewGrid.classList.remove('view__active');
gridItem.classList.add('hidden');
listItem.classList.remove('hidden');
localStorage.setItem('preferedView', 'grid');
});
viewGrid.addEventListener('click', function() {
this.classList.add('view__active');
viewList.classList.remove('view__active');
gridItem.classList.remove('hidden');
listItem.classList.add('hidden');
localStorage.setItem('preferedView', 'list');
});
Then when loading a new page at the top of your script you can get the users preferedView(if existing) via const preferedView = localStorage.getItem('preferedView');
Here is a complete example from MDN
In order for anyone to find an answer for a similar task, thanks to #Umendra insight, I was able to solve this by using this :
function viewToggeler(viewBtn1, viewBtn2, view1, view2, viewStord) {
viewBtn2.classList.add('view__active');
viewBtn1.classList.remove('view__active');
view1.classList.add('hidden');
view2.classList.remove('hidden');
sessionStorage.setItem('preferedView', viewStord);
}
viewList.addEventListener('click', () => {
viewToggeler(viewGrid, viewList, gridItem, listItem, 'list');
});
viewGrid.addEventListener('click', () => {
viewToggeler(viewList, viewGrid, listItem, gridItem, 'grid');
});
if (sessionStorage.getItem('preferedView') === 'grid') {
viewToggeler(viewList, viewGrid, listItem, gridItem, 'grid');
} else if (sessionStorage.getItem('preferedView') === 'list') {
viewToggeler(viewGrid, viewList, gridItem, listItem, 'list');
}
I ended up using sessionStorage over localStorage because it empties itself on window/tab closing which might be the most desirable result. localStorage persists even after exiting the browser and opening it back.
Also, at any point someone wants to empty the sessionStorage on exit, I used :
window.addEventListener('onbeforeunload', () => {
sessionStorage.removeItem('preferedView');
});

How to extend Leaflet Icon Class to add data-open attribute to marker HTML?

I'm trying to trigger some functionality based on the click of a marker on a GeoJSON layer in Leaflet. The eventual functionality I'm trying to implement is a flyout, or scroll out type modal populated from the individual feature's JSON attributes. Essentially, I'm trying to implement the functionality in this Tutsplus Tutorial with dynamic feature content based on the marker click.
I THINK I've figured out most of the pieces I need, but I'm struggling with how to add a data attribute, specifically data-open, to the individual marker. Building on an earlier question of mine I've realized it's not enough to just update a DOM element's CSS, but rather my app should be implementing changes based on data attributes to fully get the functionality I want.
From this question I know that this should be done by extending the L.Icon class that Leaflet provides, but the answer is a bit too terse for my current JS skills. I apologize for this effectively being a "ELI5" of a previously asked question, but I'm not sure where the options and slug come into function. I think they're implied by the question, rather than the answer I'm citing and being set on the marker itself.
Here's a simplified version of the the click handler on my markers, which grabs and zooms to location, gets feature info, and populates that info to a div. The zoom functionality works, as does extracting and placing the feature info, but I'm struggling with how to connect the functionality to trigger the modal and place the div with the feature info over the map.
function zoomToFeature(e) {
var latLngs = [e.target.getLatLng()];
var markerBounds = L.latLngBounds(latLngs);
var street = e.target.feature.properties.str_addr;
document.getElementById('street').textContent = street;
mymap.fitBounds(markerBounds);
//where the modal trigger should be
document.getElementById('infoBox').classList.add('is-visible');
}
Here are the event listeners taken from the linked tutorial, which are currently not firing, but I have them working in a standalone implementation:
const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
//this is the event I want to trigger on marker click
for (const el of openEls) {
el.addEventListener("click", function() {
const modalId = this.dataset.open;
console.log(this);
document.getElementById(modalId).classList.add(isVisible);
});
}
for (const el of closeEls) {
el.addEventListener("click", function() {
this.parentElement.parentElement.parentElement.classList.remove(isVisible);
});
}
document.addEventListener("click", e => {
if (e.target == document.querySelector(".modal.is-visible")) {
document.querySelector(".modal.is-visible").classList.remove(isVisible);
}
});
So, where I'm trying to get is that when my markers are clicked, the trigger the modal to appear over the map. So, I think I'm missing connecting the marker click event with the event that triggers the modal. I think what's missing is adding the data attribute to the markers, or some way chain the events without the data attributes. As there's no direct way to add an attribute to the markers, I try to add slug option on my circle markers:
var circleMarkerOptions = {
radius: 2,
weight: 1,
opacity: 1,
fillOpacity: 0.8,
slug: 'open',
}
and If I read the previously asked question's answer correctly, than extending the Icon Class this way should add a data-open attribute.
L.Icon.DataMarkup = L.Icon.extend({
_setIconStyles: function(img, name) {
L.Icon.prototype._setIconStyles.call(this, img, name);
if (options.slug) {
img.dataset.slug = options.slug;
}
}
});
A stripped down version of my code is here (thanks #ghybs). My full implementation pulls the markers from a PostGIS table. It's a bit hard to see in the Plunker, but this code adds my class to my modal, but doesn't trigger the functionality. It does trigger the visibility if the class is manually updated to modal.is-visible, but the current implementation which renders modal is-visbile doesn't, which I think is because the CSS is interpreted on page load(?) and not in response to the update via the dev tools, while the concatenated css class matches extactly(?). When I do trigger the modal via the dev tools, the close modal listeners don't seem to work, so I'm also missing that piece of the puzzle.
So, it's a work-around to setting the data attribute, but I realized I was shoe-horning a solution where it wasn't needed. Assuming someone ends up with the same mental block. Appropriate listeners on the modal close button and another function passed to the existing marker click listener produce the desired functionality.
const closeM = document.querySelector(".close-modal");
closeM.addEventListener("click", closeMe);
var modal = document.getElementById('infoBox');
and
function modalAction(){
modal.style.display = 'block';
}
function closeMe(){
modal.style.display = 'none';
}

Open leaflet marker using url parameter not working now that markercluster is used

I have a leaflet application at http://atlantaartmap.com. The javascript it uses is http://atlantaartmap.com/lazy_art.js.
At line 16, I grab a url parameter that can be used to open the map on a specific piece. While creating the markers, there is a piece of code at line 71 that checks to see if the most recently created marker has the ID referred to in the URL.
This code used to work, but I recently added marker clusters to the website and it no longer does. It still pans and zooms to the marker, but the popup does not open. Here is an example.
http://atlantaartmap.com/index.html?piece=40
if (marker.feature.properties.pieceID == pieceID) {
map.setView(marker.getLatLng(), newZoom());
marker.openPopup();
}
I'm not sure why, but map.setView() works and marker.openPopup() doesn't.
Any ideas? Thanks in advance.
My guess (am unable to test this) is that your map is still zooming while you call openPopup on the marker. At that time the marker isn't added to the map yet because of your cluster so the popup won't show. You could try to wait untill the setView method has completed by listening to the zoomend event and then open the popup:
if (marker.feature.properties.pieceID == pieceID) {
map.setView(marker.getLatLng(), newZoom()).once('zoomend', function () {
marker.openPopup();
});
}
If that won't work you can try to use a little delay with setTimeout:
if (marker.feature.properties.pieceID == pieceID) {
map.setView(marker.getLatLng(), newZoom()).once('zoomend', function () {
setTimeout(function () {
marker.openPopup();
}, 500); // Uses millisecs, you might need to fiddle around with it
});
}
Another option could be to wait for the marker's add event:
if (marker.feature.properties.pieceID == pieceID) {
marker.once('add', function () {
marker.openPopup();
});
map.setView(marker.getLatLng(), newZoom());
}
Hope that helps, as said am unable to test this due to the complexity of your case so i'm not sure. Good luck!

Bing Maps Click Event on a Pin

How can i setup a callback function for a click event on a pin?
I need both pins the green one (one location) and the red one (clustered locations).
I'm using the v6 api.
That's the code so far:
var shape = new VEShape(VEShapeType.Pushpin, new VELatLong(pin.position.lat, pin.position.lng));
shape.SetTitle('<h2>'+pin.overlay.headline+'</h2>');
shape.SetDescription('<p>'+pin.overlay.text+'</p>');
var pinIcon = new VECustomIconSpecification();
pinIcon.Image = '/images/map/pin.png';
pinIcon.TextContent = '.';
shape.SetCustomIcon(pinIcon);
The correct way to do this is to override the onclick and onmouseover
functions within VEMap.AttachEvent(); AttachEvent has many return values
useful in identifying which pin you click/mouseover, such as the pinID (elementID return value for the VEMap.onclick() method).
You can use the ID in combination with map.ShowInfoBox(), and map.GetShapeByID to
show your infobox upon click.
READ: VEMap.AttachEvent <-- Google that, I'd paste the URL but I need more rep on StackOverflow
READ: VEMap.onclick. Also, Understand the return values:
READ All mouse events
http://msdn.microsoft.com/en-us/library/bb412438.aspx
/*************************************
* Code snippets..
* For example purposes I'm going to do
* things a bit out of order.
*************************************/
// Attach your events in the map load callback:
map.AttachEvent("onmouseover", myFnForMouseOver);
map.AttachEvent("onclick", myFnForOnClick);
// Callback functions used in the AttachEvent(s) above..
function myFnForMouseOver(e){
if(e.elementID){
return true; // Disables the rollover ShowInfoBox()
}
}
function myFnForOnClick(e){
if(e.elementID){
// Show infobox using the PINs/Shapes actual ID, (return value from e.elementID)
map.ShowInfoBox(map.GetShapeByID(e.elementID));
return true;
}
}
/*
* end
*/
Thats it
R Baker
You are not limited to setting just the text and image of a pin -- you can use the CustomHTML property to specify it as an HTML element. That allows you to handle clicks or any other events on it.
A simple example would have an HTML pin image with an inline click handler:
pinIcon.CustomHTML = "<img onclick='alert(\"tadaa\")' src='/images/map/pin.png' />";
If you are separating code from markup, e.g. using jQuery, you can specify the pin's element ID, and use that later to associate a click handler with it. For example:
pinIcon.CustomHTML = "<img id='pin' src='/images/map/pin.png' />";
shape.SetCustomIcon(pinIcon);
...
map.AddShape(shape);
$("#pin").click(function() { alert("tadaa"); });

Categories

Resources