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.
Related
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.
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
Trying to improve my Coffeescript skills, so thought I'd covert this jcrop demo. However it's not working as expect. Specifically, the redraw function does not appear to be being called.
This works fine.
// Create a new Selection object extended from Selection
var CircleSel = function(){ };
// Set the custom selection's prototype object to be an instance
// of the built-in Selection object
CircleSel.prototype = new $.Jcrop.component.Selection();
// Then we can continue extending it
$.extend(CircleSel.prototype,{
zoomscale: 1,
attach: function(){
this.frame.css({
background: 'url(' + $('#target')[0].src.replace('750','750') + ')'
});
},
positionBg: function(b){
var midx = ( b.x + b.x2 ) / 2;
var midy = ( b.y + b.y2 ) / 2;
var ox = (-midx*this.zoomscale)+(b.w/2);
var oy = (-midy*this.zoomscale)+(b.h/2);
//this.frame.css({ backgroundPosition: ox+'px '+oy+'px' });
this.frame.css({ backgroundPosition: -(b.x+1)+'px '+(-b.y-1)+'px' });
},
redraw: function(b){
// Call original update() method first, with arguments
$.Jcrop.component.Selection.prototype.redraw.call(this,b);
this.positionBg(this.last);
return this;
},
prototype: $.Jcrop.component.Selection.prototype
});
But when I try to write this in Coffescript it fails
CircleSel.prototype = new ($.Jcrop.component.Selection)
$.extend CircleSel.prototype,
zoomscale: 1
attach: ->
#frame.css background: 'url(' + $('#target')[0].src.replace('750', '750') + ')'
return
positionBg: (b) ->
midx = (b.x + b.x2) / 2
midy = (b.y + b.y2) / 2
ox = -midx * #zoomscale + b.w / 2
oy = -midy * #zoomscale + b.h / 2
#frame.css backgroundPosition: -(b.x + 1) + 'px ' + -b.y - 1 + 'px'
return
# this redraw function is not being called, everything else appears to work fine
redraw: (b) ->
$.Jcrop.component.Selection::redraw.call this, b
#positionBg #last
this
prototype: $.Jcrop.component.Selection.prototype
What have I done wrong?
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()
}
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()
})
});