Detecting right click position on angular leaflet map - angular-leaflet-directive

I have a mobile page showing a map using angular-leaflet-directive 0.7.11, and have declared my required events like so:
$scope.map = {
events: [
'mousedown',
'contextmenu'
],
...
}
$scope.$on('leafletDirectiveMap.mousedown', function (event) {
debugger;
});
Where the debugger statement is, the event variable contains no information about where the map was clicked. The same event format was provided by the directive when the contextmenu event is triggered.
In fact, if I inspect the entire event variable, it is just an Object, not an Event:
Are the docs wrong? Is the example missing something? How can I obtain the X/Y or Lat/Lng for the particular position that I have right-clicked (tap-hold)?

You need to use the 'leafletEvent'. Try this:
myApp.controller('YourController', ['$scope', 'leafletEvent', function($scope) {
$scope.$on('leafletDirectiveMap.mousedown', function (event, leafletEvent) {
leafletData.getMap().then(function(map) {
map.on('click', function(e) {
console.log('e');
console.log(e);
console.log('e.latlng:');
console.log(e.latlng); // L.LatLng {lat: 19.642587534013046, lng: -4.5703125}
});
});
});
}]);

Related

In Leaflet, how to know when map.fitBounds actually changed anything?

I have a click event on a map feature that zooms into that feature when clicked by the user
Map starts like this:
When a user clicks on the map feature:
L.geoJson(geoJsonFeatureCollection, {
style,
onEachFeature
}).addTo(map)
function zoomToFeature (e) {
map.fitBounds(e.target.getBounds())
}
function onEachFeature (feature, layer) {
layer.on({
click: zoomToFeature
})
}
On a second click on the same map feature, after being already zoomed in, I'd like to forward the URL to another page (the info HTML page of that feature). But I can't distinguish both situations.
How can I know in map.fitBounds if the map bounds were already fitted, i.e., if the method actually did/zoomed/panned anything?
You can use the same calculation function from leaflet and check if it equals to the current map state:
function zoomToFeature (e) {
const bounds = e.target.getBounds();
const target = map._getBoundsCenterZoom(bounds);
if(target.zoom === map.getZoom() && map.getCenter().equals(target.center)){
// bounds already fitting
} else {
map.fitBounds(bounds);
}
}
Maybe you need to change the margin of equals. Default: .equals(target.center, 1.0E-9)

Is there any better way to get source marker on "popupopen" event in leaflet?

So this is how I do it now:
map.on('popupopen', ({ popup }) => {
if (popup instanceof L.Popup) {
const marker = popup._source as L.Marker;
}
});
I really don't like accessing private variables in leaflet. I still have not found in leaflet api clean method to get marker that is binded to active popup.
Better way is to emit new event on marker popupopen and access it from wherever you want.
popupopen: () => {
map.fire('someevent', { somemarker });
},
map.on({
'someevent': (event) => {} // <- event has marker
});

Import Leaflet Markers from a external GeoJSON

I am starting with leaflet and wanted to display more information when clicking on a marker in a map using a sidebar.
I use the php call where the geoJeson called allande_geoJson is generated with all the information I need from my database:
In the example I'm using, a maker is generated so that when you click on it, the information is displayed in the sidebar:
var marker = L.marker([51.2, 7]).addTo(map).on('click', function () {
sidebar.toggle();
});
I wanted to enter the makers directly from my geoJeson and I am trying various ways with no success, such as:
var marker= L.marker(new L.GeoJSON(allande_geoJson)).addTo(map).on('click', function () {
sidebar.toggle();
});
any ideas?
The Markers are loaded automatically when you put the geojson data in the L.geoJSON() layer.
With onEachFeature you add the click event to each marker.
function onEachFeature(feature, layer) {
layer.on('click', function () {
sidebar.toggle();
});
}
L.geoJSON(allande_geoJson, {
onEachFeature: onEachFeature
}).addTo(map);

Leaflet.js - Displaying a moving rectangle during drag

I have an interface where, while the map is dragged, a rectangle is drawn on the map.
I've created a stripped down version of this functionality via this plunkr. The JS used for the plunkr is this:
var map = new L.Map('leaflet', {
layers: [
new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
'attribution': 'Map data © OpenStreetMap contributors'
})
],
center: [36, -98],
zoom: 6,
renderer: L.svg({ padding: 100 })
});
var rectangle = L.rectangle(map.getBounds().pad(-0.1));
map.on("dragstart", function (e) {
var b = map.getBounds().pad(-0.1);
rectangle.setBounds(b);
rectangle.addTo(map);
map.on("drag", dragEvent);
});
map.on("dragend", function (e) {
rectangle.removeFrom(map);
map.off("drag", dragEvent);
});
map.on("mouseup", function(e){
console.log("mouseup!");
});
var dragEvent = function(e) {
rectangle.setBounds(map.getBounds().pad(-0.1));
}
This appears to work okay in Chrome and Internet Explorer. The problem I'm encountering is with Firefox (v59.0.2 64bit on Windows). In FF, if you click and drag the map, and release the mouse button while hovering over the rectangle, there seems to be a missing mouseup event. This means that if you hover over the toolbar on the right of the plunkr, you won't see the expected hover behavior until you click somewhere on the toolbar.
My questions, then:
Is there a better way to implement this functionality?
If not, anyone have an idea why this is occurring with FF?
In FF, if you click and drag the map, and release the mouse button while hovering over the rectangle, there seems to be a missing mouseup event.
Although it doesn't look good, but wrapping the removal of the rectangle in setTimeout would fix the issue:
map.on("dragend", function (e) {
setTimeout(function() {
rectangle.removeFrom(map);
}, 1);
map.off("drag");
});
Another solution would be creating an own mouseup handler for the rectangle:
map.on("dragend", function (e) {
map.off("drag");
});
map.on("mouseup", function(e) {
rectangle.removeFrom(map);
});
rectangle.on("mouseup", function (e) {
rectangle.removeFrom(map);
L.DomEvent.stopPropagation(e);
});
Also, there might be a reason to open an issue on https://github.com/Leaflet/Leaflet/issues

How do I trigger tinymce 4.x focus and blur events

I realize that this question has been asked and answered several times, but I still can't make many of the solutions work. It seems like most of the discussions are older and maybe not compatible with 4.x.
My goal: be able fire some javascript functions upon focus or blur. Here's the base code:
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
});
I tried examples like:
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
setup : function(ed) {
ed.onInit.add(function(ed, evt) {
var dom = ed.dom;
var doc = ed.getDoc();
tinymce.dom.Event.add(doc, 'blur', function(e) {
alert('blur!!!');
});
});
}
});
returns:"Uncaught TypeError: Cannot call method 'add' of undefined"
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
});
tinymce.activeEditor.on('focus', function(e) {
console.log(e.blurredEditor);
});
returns: "Uncaught TypeError: Cannot call method 'on' of undefined"
(but not sure if I have it in the right place)
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
setup: function(editor) {
editor.on('focus', function(e) {
console.log('focus event', e);
});
}
});
returns: "Uncaught SyntaxError: Unexpected identifier"
This works but only when initiating the editor. Other things I've tried but haven't gotten to work:
tinymce.FocusManager
tinymce.activeEditor
What am I missing? Thanks.
UPDATE: found a solution that worked beautifully: Why TinyMCE get focus and blur event, when user jump from other input field?
see the fiddle at http://fiddle.tinymce.com/8Xeaab/1
tinymce.init({
selector: "#editme",
inline: true,
setup: function(editor) {
editor.on('focus', function(e) {
console.log("focus");
});
editor.on('blur', function(e) {
console.log("blur");
});
}
});
Your cuestion title its about TRIGGERING focus and blur events, but you really are asking about HANDLING those events.
If anybody is still looking for triggering the events, the solution should by:
tinymce.init({
selector: "#textarea_123",
...
});
then, to set focus:
var inst = tinyMCE.EditorManager.get('textarea_123');
inst.focus();
I recently ran into this issue and although I am doing this in angularjs I was able to implement a fix for it by creating a directive that registers when you click off of it and then clears the activeElement in the html body. I will add the directive below. You just call it on the object by adding click-off like you would an ng-cloak to a tag.
(function () {
'user strict';
angular.module('app.directives').directive('clickOff', ClickOff);
function ClickOff($parse, $document) {
var directive = {
link: link
};
return directive;
function link(scope, $element, attr) {
var fn = $parse(attr["clickOff"]);
$element.bind('click', function (event) {
event.stopPropagation();
});
angular.element($document[0].body).bind("click", function (event) {
scope.$apply(function () {
$document[0].activeElement.blur();
fn(scope, { $event: event });
});
});
}
}
})();