Leaflet OSM Marker Popup Positioning - popup

I'm working a map website using OpenStreetMap, and I'm using image marker rather the default one. The first problem when zooming map in or out, marker's position slightly changing... So I set anchor point using L.point. However, the chain reaction happened also to pop up, which described by this picture :
Popup covered the marker, and the positioning doesn't seem right. Any suggestion how to tinkering popup's point? Here's my code :
var locations = data;
for ( var i=0; i < locations.length; i++) {
if (locations[i][0] == 'panic') {
var icon = L.icon({iconUrl:"{{asset('assets/splash4.gif')}}", iconAnchor: new L.Point(36,41) });
var marker = L.marker( [locations[i][1], locations[i][2]], {icon: icon});
marker.bindPopup( locations[i][5] + " <br>" + locations[i][6] + " <br>" + locations[i][7] + " <br><br>" + locations[i][3] + " <br>" + locations[i][4] ).addTo( map );
if(i == locations.length - 1){
map.setView(new L.LatLng(locations[i][1], locations[i][2]), 18);
marker.bindPopup(locations[i][5] + " <br>" + locations[i][6] + " <br>" + locations[i][7] + " <br><br>" + locations[i][3] + " <br>" + locations[i][4]).openPopup().addTo( map );
}
} else {
var icon2 = L.icon({iconUrl:"{{asset('assets/opmarkerblue1.png')}}", iconAnchor: new L.Point(0,32)});
var marker = L.marker( [locations[i][1], locations[i][2]], {icon: icon2});
marker.bindPopup( locations[i][5] + " <br>" + locations[i][6] + " <br>" + locations[i][7] + " <br><br>" + locations[i][3] + " <br>" + locations[i][4] ).addTo( map );
}
}
Any help appreciated.

Use the popupAnchor option when instantiating your L.Icons. That's another L.Point with pixel coordinates relative to the iconAnchor.
The tutorial for custom marker icons also explains how the options for L.Icon work.

Related

On right click of an Item

I'm trying to make a Hypixel Skyblock remake, and I'm trying to make a sword that teleports you forward. I don't need help with that, but I need help with this: I put some test code, just to see if it works, and it doesn't
#EventHandler(priority=EventPriority.HIGH)
public void onPlayerUse(PlayerInteractEvent event){
Player p = event.getPlayer();
World world = p.getWorld();
Location pLocation = p.getLocation();
Location tLocation = new Location(world, pLocation.getX(), pLocation.getY() + 2, pLocation.getZ());
if(p.getItemInHand() == ItemUtils.Aspect_Of_The_End()){
p.teleport(tLocation);
}
}
But when I right click, it doesn't teleport me 2 blocks upwards, and idk why.
Here is the code for the item itself:
public static ItemStack Aspect_Of_The_End()
{
ItemStack Aspect_Of_The_End = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta itemMeta_aote = Aspect_Of_The_End.getItemMeta();
itemMeta_aote.setDisplayName(ChatColor.BLUE + "Aspect Of The End");
itemMeta_aote.addItemFlags(ItemFlag.HIDE_ENCHANTS);
itemMeta_aote.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
List<String> l = new ArrayList<String>();
l.add(Utils.chat("&7") + "Damage: " + Utils.chat("&c") + "+100");
l.add(Utils.chat("&7") + "Strength: " + Utils.chat("&c") + "+100");
l.add(" ");
l.add(Utils.chat("&6") + "Item Ability: Instant Transmission " + Utils.chat("&e") + "RIGHT CLICK");
l.add(Utils.chat("&7") + "Teleport " + Utils.chat("&a") + "8 blocks " + Utils.chat("&7") + "ahead of");
l.add(Utils.chat("&7") + "you and gain " + Utils.chat("&a") + "+50 " + Utils.chat("&f") + "✦ Speed");
l.add(Utils.chat("&7") + "for " + Utils.chat("&a") + "3 seconds.");
l.add(Utils.chat("&8") + "Mana Cost: " + Utils.chat("&3") + "50");
l.add(" ");
l.add(Utils.chat("&9") + "RARE SWORD");
itemMeta_aote.setLore(l);
Aspect_Of_The_End.setItemMeta(itemMeta_aote);
ShapedRecipe recipe_aote = new ShapedRecipe(Aspect_Of_The_End);
recipe_aote.shape(" e "," e "," d ");
recipe_aote.setIngredient('e', Material.EYE_OF_ENDER);
recipe_aote.setIngredient('d', Material.DIAMOND);
Bukkit.addRecipe(recipe_aote);
return Aspect_Of_The_End;
}
EDIT: Forgot to say, but there are no errors in console, eclipse, nor when the sword is right clicked.
You want to use .equals() instead of == to check if it is the aspect of the end.

Dojo - add event listener to dynamically created element

Hi I'm trying to add event listener to dynamically created "<a></a>" element, but with no success.
Here is the item/element:
var item = "<div class='item' id='" + id + "'>"
+ "<div class='cell ion-chevron-right'>"
+ "<span class='cell items'>" + text + "</span>"
+ "<a id='" + id + "_icon' class='mIcon ion-ios-close-outline' style='margin-left:-22px; font-size:18px;'></a>"
+ "</div>"
+ "<div class='cell'>" + price + "</div>"
+ "</div>";
return item;
}
And here I insert it into the HTML:
var addAccessorie = function(id, text, price){
var m = id + "_accessorie";
dojo.place(newAccesorieItem(m, text, price)
,"maintenance_accessorie"
,"after"); // before/after
}
How can I add a CLICK event to the "<a>" in DOJO?
Use dojo/dom-construct to create the <a> element and then use dojo/on to bind the onclick event.
var aElement= domConstruct.toDom("<a id='" + id + "_icon' class='mIcon ion-ios-close-outline'
style='margin-left:-22px; font-size:18px;'></a>");
on(aElement, 'click', function(){
//Your click handler
});
If you keep your code exactly as it is,
you can do:
var addAccessorie = function(id, text, price){
var m = id + "_accessorie";
dojo.place(newAccesorieItem(m, text, price)
,"maintenance_accessorie"
,"after"); // before/after
on(dom.byId(m + '_icon'), 'click', function(){
//what needs to be done when <a> is clicked
});
}
Only need to add is a require for dojo/dom and dojo/on

ng-grid first line rendered only, and cannot catch selection event

I'm working on my own project using angurarjs and ag-grid.
I have 2 problems:
1. is that i cannot refresh a status bar in case of selection in ag-rig. I can catch the event, and the function is running, but statusText scope element is reresshed only after navigation is happend to an other page. Very strange behaviour.
2. only the first 3 lines of grid is rendered, and only after scrolling the rest is shown.
Could anyone help me?
Code:
$scope[page + 'GridOptions'] = {
columnDefs: [],
rowData: null,
onGridReady: $scope.fillGrid,
rowSelection: 'single',
onSelectionChanged: function(){
$scope.selectRow()
}
}
$scope.selectRow = function(){
localStorageService.set(page + 'SelectedRow', $scope[page + 'GridOptions'].api.getSelectedRows()[0])
console.log($scope[page + 'GridOptions'].api.getSelectedRows()[0])
$scope.statusText = "selected item's id: " + $scope[page + 'GridOptions'].api.getSelectedRows()[0]._id
for(i=0; i<$scope[page + 'GridColumns'].length; i++){
localStorageService.set($scope[page + 'GridColumns'][i].field, $scope[page + 'SelectedRow'][$scope[page + 'GridColumns'][i].field])
$scope[$scope[page + 'GridColumns'][i].field] = localStorageService.get($scope[page + 'GridColumns'][i].field)
}
console.log(page)
localStorageService.set(page + 'DisableButton', false)
$scope[page + 'DisableButton'] = eval(localStorageService.get(page + 'DisableButton'))
$scope[page + 'GridOptions'].api.refreshView()
}

Removing items from leaflet markercluster

I have two functions that load markers into my map. (Both functions are called on success of an ajax call)
First Function is like this:
function loadEpsMarkers(data) {
for (var i = 0; i < data.length; i++) {
var plateNo = data[i].PLATE_NUMBER;
var permitNo = data[i].PERMITINFOID;
var inventoryId = data[i].INVENTORY_ID;
var icon = epsiconR;
if (data[i].INVENTORY_STATUS === 'Complete') {
icon = epsiconC;
}
var popup = '<h5>EPS</h5>' + 'Plate:' + plateNo + '<br/>' +
' Permit: <a class=\'link\' data-inventoryId="' + inventoryId + '" href=' + url + '>' + permitNo + '</a>' +
'<p style=\"color:blue\">' + '' + '<a class=\'link\' href=' + url + '>' +
'Import' + '</a>' + '<br/>' + '<a class=\'link\' href=' + url + '>' +
'Duplicate' + '</a>' + '<br/>' + '<a class=\'link\' href=' + url + '>' +
'Removed' + '</a>' + '<br/>' + '</p>';
var m = L.marker([data[i].REF_LATITUDE, data[i].REF_LONGITUDE], { icon: icon, draggable: 'true' })
.bindPopup(popup);
markerClusters.addLayer(m);
}
map.addLayer(markerClusters);
map.invalidateSize(false);
}
The second Function is same except the data is different.
This works fine and I get the clustered markers as expected.
Now I have a button, when I click this button, it should hide the markers from the first call.
The easy way out is to remove layers and then redo just the second call. But that seems like an inefficient way of doing this.
This gets more complex if I have 4 such data calls and I want to toggle markers from each of those calls.
I have tried something like this as well:
$('#dvEpsOnlyMarkers').click(function () {
markerClusters.removeLayer(m);
});
But that isn't working. Any ideas on how I can make this work ?
Thanks in advance
A very simple way of achieving what you describe is to store references to markers of each group in arrays, and manipulate those arrays to add / remove the layers into MCG:
var markersCall1 = [],
markersCall2 = [],
markersCall3 = [],
markersCall4 = [];
function loadEpsMarkersX(data) { // Replace X by 1...4
for (var i = 0; i < data.length; i++) {
// Convert data...
var m = L.marker(/* latLng, options, popup... */);
markersCallX.push(m); // Replace X by 1...4
}
// Actually add to MarkerClusterGroup.
// Replace X by 1...4
markerClusters.addLayers(markersCallX); // note the addLayers with "s".
}
$('#dvEpsOnlyMarkersX').click(function (event) { // Replace X by 1...4
// Assuming it is a checkbox, you can use it to toggle.
if (this.checked) {
// Replace X by 1...4
markerClusters.addLayers(markersCallX); // note the "s".
} else {
// Replace X by 1...4
markerClusters.removeLayers(markersCallX); // note the "s".
}
});
When you have batches of markers to add / remove like in your case, you can conveniently use the MarkerClusterGroup methods addLayers and removeLayers (with a trailing s) with an array of the markers to process. These methods are much more efficient than adding / removing markers one by one.

OpenLayers: Open popup when hovering vector, without closing it when mouse is over popup itself

I have a map with a vector layer showing features from GeoJSON. When I hover the feature, a pop-up shows up at the beginning of the linestring. But it is flickering, it appears and disappears. I guess the feature somehow gets deselected. Maybe popup gets in the middle between mouse and the feature so the condition of feature being hovered is no more fulfilled. How can I solve it? I want the pop up to be displayed when the mouse is over the feature, no matter if the popup is in the way.
I think it can be replicated even with example code: http://openlayers.org/dev/examples/light-basic.html .
It happens even if my mouse is not directly over the white part of the popup.
It seems to me the problem is more severe in chrome than in firefox. Maybe this is not the problem of my code, but bug. If so, sorry for posting here.
I am using foollowing code :
layer = new OpenLayers.Layer.Vector("JOSM", {
eventListeners: {
'featureselected': function(evt) {
var feature = evt.feature;
var detailsTextHtml = "";
var lines = feature.attributes.evaluations.split("\n");
for (var i = 0; i < lines.length; i++) {
if (lines[i] !== "") {
detailsTextHtml += " <br> " + lines[i];
}
}
popup = new OpenLayers.Popup.FramedCloud("popup",
OpenLayers.LonLat.fromString(feature.geometry.getVertices()[0].toShortString()),
null,
"<div style='font-size:.8em'>Coefficient: " + feature.attributes.coefficient + "<br>Color:" + feature.attributes.color + "<br>Details: " + detailsTextHtml + "</div>",
null,
true
);
feature.popup = popup;
map.addPopup(popup);
},
'featureunselected': function(evt) {
var feature = evt.feature;
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
},
styleMap: styleMap,
strategies: [new OpenLayers.Strategy.Fixed()],
projection: geographic,
protocol: new OpenLayers.Protocol.HTTP({
url: "webresources/getJosmAspectsDetailed?startLon=" + document.getElementById('startLon').value +
"&startLat=" + document.getElementById('startLat').value +
"&endLon=" + document.getElementById('endLon').value +
"&endLat=" + document.getElementById('endLat').value + "&speed=17&comfort=0&quietness=0",
format: new OpenLayers.Format.GeoJSON()
})
});