HTML5 Drag and Drop - Map - html

I have to make a map of Europe with its countries
and then I need a few pics of products from those countries
After that I have to match the pic with the country with drag and drop
if the product is dropped on the correct country it should send me to another page (with more info about the product)
if it's wrong it should display a message
anyone have an idea? I checked for some basic drag and drop stuff but since I'm new to html5 etc and webdesign in general it's really hard to make this from scratch
thanks!
EDIT: also only use HTML, CSS, JS

This can be achieved with the MapQuest JavaScript API. What I would start with is by adding polygon overlays to the map for each country, the colour can be sett to completely transparent by setting the opacity for the overlay to 0.0. From each overlay add a mouseup event listener to each overlay, this event listener can then be used to determine what it was you were dragging in the first place.
For the drag start functionality you can either do this yourself or you could use something like the jQuery UI draggable support, you could then use the dragstop event from the draggable API in conjunction with mouseup on the overlay to perform your logic.
Check out the basic map to get a map going.
Some code to start with
var countryCode;
// Adds an overlay and wires an event for mouseup.
function addMapOverlay(points, cc) {
var poly = new MQA.PolygonOverlay();
poly.setShapePoints(points);
poly.color = "#ffffff";
poly.colorAlpha=0.0;
poly.fillColor = "#ffffff";
poly.fillColorAlpha=0.0;
poly.addListener(rectangle, 'mouseup', function(evt) {
if (evt.eventName === "mouseup") {
// Here you have the event firing for the mouse-up on the overlay.
countryCode = cc;
}
});
}
For the drag-start.
$("#some-country-item").draggable({
start: function(event, ui) {
countryCode = null;
},
stop: function(event, ui) {
if (countryCode === "what you expected") {
// Released on correct country.
} else {
// Did not release on correct country.
}
}
});
You may need to test the event handling to ensure that the correct events are fired in the right order, or use the mouseover event on the overlay object.
The code samples are theoretical and should help you find the right direction to go.

Related

Wrong code in tutorial for event listeners

I am following this tutorial to build a store locator page with a Mapbox map.
I don't want to add custom markers because I already have custom map labels (symbols?), which means I don't need the optional last section of the tutorial and stop right after Add Event Listeners.
Once this is completed, the page should react to clicks in the side panel list, as well as on the map (2 event listeners). However, in the demo provided in the tutorial for that particular step, you can tell the code for the second event listener, the one making the map clickable, is not functioning, which makes me believe there is a mistake in the provided code:
// Add an event listener for when a user clicks on the map
map.on('click', function(e) {
// Query all the rendered points in the view
var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
if (features.length) {
var clickedPoint = features[0];
// 1. Fly to the point
flyToStore(clickedPoint);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedPoint);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
var selectedFeature = clickedPoint.properties.address;
for (var i = 0; i < stores.features.length; i++) {
if (stores.features[i].properties.address === selectedFeature) {
selectedFeatureIndex = i;
}
}
// Select the correct list item using the found index and add the active class
var listing = document.getElementById('listing-' + selectedFeatureIndex);
listing.classList.add('active');
}
});
Would anyone be able to tell what is wrong with this code?
Turns out the code is incomplete in that the cursor doesn't change to a pointer as you hover over a map label/marker so it doesn't clue you into realising you can click on it, hence my assumption it wasn't working at all. I assume the general users who would then face the map would be equally deceived unless the pointer shows up. So in the tutorial, if you do go ahead and click the marker, it will have the expected behaviour and display the popup, although no pointer is shown.
Here is how to create the pointer, based on this fiddle: https://jsfiddle.net/Twalsh88/5j70wm8n/25/
map.on('mouseenter', 'locations', function(e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'locations', function() {
map.getCanvas().style.cursor = '';
});

How to check if a marker is in a cluster?

With Leaflet.Markercluster, how is it possible to check if a marker is in a cluster?
Use Leaflet's hasLayer() function
Regular visible markers technically exist as layers in the map. Leaflet also has a function hasLayer() that returns true/false whether a given reference, like a stored marker, currently exists (ie "is visible") in the map as a layer.
For my specific problem, I gave a special visual decoration to a selected map marker (e.g. red border), and this decoration remained even after that marker went in-and-out of a cluster. I needed the selected marker to deselect itself if it entered a cluster.
Below is rough logic that allows me to check whether a given marker reference is visible to the user after a cluster event (that may occur for any reason, like zoom events or non-user driven movements in the map).
Relevant abbreviated code:
I hold my clustering like this...
this.markersClustered = L.markerClusterGroup({ // Lots of stuff here... } })
In my click event for individual markers, I store the marker in a "selectedItem" object (which I use for all kinds of other logic in my app)...
onEachFeature(feature, marker) {
marker.on("click", e => {
// ... (lots of code) ...
// Save instance of the marker; I call it "layer" only
// because I only use this for the hasLayer() check
this.selectedItem.layer = marker
// Here do other stuff too, whatever you need...
//this.selectedItem.target = e.target
//this.selectedItem.latlng = e.latlng
//this.selectedItem.id = e.target.feature.id
//this.selectedItem.icon = layer._icon
// ... (lots of code) ...
})
}
When cluster animations end, using hasLayer(), check whether the selected marker is in a cluster, and do stuff.
Note: the check is done at the END of clustering animation in my use case, because I didn't want the user to see the selected marker lose it's special visual decoration while the clustering animation was happening (it would appear buggy).
this.markersClustered.on('animationend', (e) => {
// Check visibility of selected marker
if(this.map.hasLayer(this.selectedItem.layer)) {
// True: Not in a cluster (ie marker is visible on map)
} else {
// False: In a cluster (ie marker is not visible on map)
}
console.log("Selected marker visible?:" + this.map.hasLayer(this.selectedItem.layer))
})

Polygon how to know if vertex moving on google map

I'm using drawing manager to draw polygon.
I want to display live moving data on polygon vertex.
I have tried used two methods below.
google.maps.event.addListener(polygon.getPath(), 'set_at', processVertex);
google.maps.event.addListener(polygon.getPath(), 'insert_at',processVertex);
But its call after vertex end moving/ drag end.
i want something while moving ...
I have this fiddle and data i'm displaying.
http://jsfiddle.net/subhashchavda/6a8db64z/65/
I want something like this
listener(polygon.getPath(), 'vertex_drag',function(){
update_data(); /* dragging/moving */
});
Is there any way /trick for listen vertex dragging ?
There is no in build function available in google map doc. so right now if want to it to workout you can use custom code like listening vertax click and drag on map.
Here is some code you can try with that.
google.maps.event.addListener(polygon, 'mousedown', function(e){
if(e.vertex){
// flag for vertax drag start
}
});
google.maps.event.addListener(map, 'mousemove', function(e){
if(e.vertex){
// flag for vertax dragging
}
});
google.maps.event.addListener(polygon, 'mouseup', function(e){
if(e.vertex){
// flag for vertax drag stop
}
});
But i'm not sure it will work with every conditions.
you need to more workout with this code.

GoogleMaps API V3 Polygon dblclick auto-complete

I have created a plotting system using the GoogleMaps Javascript API V3, which allows users to draw out and save polygons.
I have received a number of complaints concerning the autocompletion of plots as a result of accidentally doubleclicking while manually drawing out the points using the polygon drawing tool. I am therefore looking to disable this dblclick auto-complete function, so that plots will only complete once the user clicks on the first point again.
I have tried unbinding the dblclick event from the map, and attempted to stop propagation of the dblclick event by throwing an error on double click, as below (just to test the event call).
google.maps.event.addListener(map, 'dblclick', function(){
throw("stop");
});
this succeeds in stopping the zoom function on doubleclick, but autocomplete still occurs when dblclicking while plotting points (this listener is not triggered). I have even tried stopping the propagation of any doubleclick event on the whole page, all to no avail. Can anyone suggest either a way of unbinding this dblclick event, or an alternative solution to prevent the dblclick autocomplete?
I have searched through the API reference document and forums and have not been able to find a solution to this.
Add an edit button after finish!
Save your polygons into an array on "overlaycomplete" (and add your edit button at the same time)
var polyArray = [];
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
this.setDrawingMode(null);
var shape = e.overlay;
shape.type = e.type;
polyArray.push(shape);
shape.addListener('click', function(evt){
if (evt.vertex != null && this.getPath().getLength() > 3) {
this.getPath().removeAt(evt.vertex);
}
});
});
The Edit function:
function editFeature(id, action){
var shape = polyArray[id];
if(action) shape.setEditable(true);
else shape.setEditable(false);
}

User vs. System events in Google Maps API v3

I've been reading the Google Maps API docs to see if it's possible to tell the difference between a system event vs. a user one?
For example, the zoom_changed event gets triggered when you use methods like setZoom, fitBounds, etc, which in my implementation is unsavoury, as I just want to know when the user actually changes the zoom level.
Unfortunately, the click event is only fired on the map itself, not the controls, so you can't rely on that method to help detect the users input.
Ideas?
Although I haven't been able to solve this using the Google Maps API, I have created a workaround which involves me calling this method before I change the map zoom or positioning without user interaction:
MapGraph.prototype.systemMove = function() {
var _this = this;
this.isMoving = true;
return setTimeout(function() {
return _this.isMoving = false;
}, 500);
};
And my event bindings look like this:
google.maps.event.addListener(this.map, 'dragend', function(event) {
if (!_this.isMoving) return _this.mapChanged();
});
Not perfect, but it does work.
Would love to see any other implementations though.
You may also consider an alternate solution I proposed in this Stack Overflow answer, which does not rely on mouse events to recognize user-initiated changes.
Instead of trying to recognize user events, add a flag to the map whenever a programmatic change is initiated with setZoom or fitBounds.
map.systemChange = true
map.setZoom()
Then check for (and reset) the flag in the event listener.
map.addListener('zoom_changed', function () {
if (map.systemChange) {
map.systemChange = false // Reset the flag for a system-initiated event
} else {
// Handle the user-initiated event
}
});