map.on('click',onClick) is also fired when zoomBox - javascript

I have defined a map.on('click',onClick) event, but it also fires when someone uses the zoomBox Handler (Shift+draw zoom box)
function onClick(e) {alert(e.latlng);}
e.type is always 'click'
I am using Leaflet version 0.5.1.
How can I avoid this?
thanks in advance

I think you found a bug! I found this bug appears in IE 10 only, and not only 0.5.1, but 0.6 also has same issue. You can report a bug to Leaflet issue tracker.
For now, temporary, you can track mousedown point and compare to click point to determine whether cursor is moved.
var mousedownPoint; // global
map.on('mousedown', function (e) {
mousedownPoint = e.containerPoint;
});
map.on('click', function (e) {
if (!e.containerPoint.equals(mousedownPoint)) {
return;
}
// DO WHAT YOU WANT
});

Related

Prevent child event from firing

I have a slider that I am currently making. I am making slow progress, but I am making progress nonetheless!
Currently I have this:
http://codepen.io/r3plica/pen/mEKyGG?editors=1011#0
There are 2 things you can do with this control, the first thing is you can drag left or right. The second thing you can do is click a "point" and it will scroll to the center.
The problem I have is that if I start dragging from a point, when I let go it will invoke the moveToCenter method.
I have tried to prevent this by adding
// Stop from accessing any child events
e.preventDefault();
e.stopPropagation();
to the end of the dragEventHandler, but this did not work.
I also have 2 boolean values options.drag and options.start. I though I might be able to use them somehow (if the drag has started and is enabled then don't perform the moveToCenter but this didn't work either.
Do anyone have any idea how to get this to work?
Maybe this will help. You can register your events in bubbling or capturing mode, using addEventListener method. It defines orders of processing your events - child -> parent (bubbling), or vice versa (capturing).
http://www.quirksmode.org/js/events_advanced.html
So, if you use addEventListener(event, handler, true), it will use capturing event mode.
Codepen:
http://codepen.io/anon/pen/bZKdqV?editors=1011
divs.forEach(function (div) {
div.addEventListener('click', function(e) {
e.stopPropagation();
console.log('parent');
}, true);
});
Be aware of browser support (IE9+). All modern browsers - yes, of course.
http://caniuse.com/#search=addeventlistener
Update
So it turned out to be easier than first approach. (no need for capturing)
Check out codepen:
http://codepen.io/anon/pen/QExjzV?editors=1010
Changes from your sample:
At the beginning of moveToCenter: function(e, options, animate) function
if (options.started) {
return;
}
In if (['mouseup', 'mouseleave'].indexOf(e.type) > -1):
setTimeout(function() {
options.started = false;
} , 100);
instead of
options.started = false;
Hope this helps.

Doubletap event on input text on mobile [duplicate]

I'm looking for the best solution to adding both "doubletap" and "longtap" events for use with jQuery's live(), bind() and trigger(). I rolled my own quick solution, but it's a little buggy. Does anyone have plugins they would recommend, or implentations of their own they'd like to share?
It has been reported to jQuery as a bug, but as doubletapping isn't the same as doubleclicking, it does not have a high priority. However, mastermind Raul Sanchez coded a jquery solution for doubletap which you can probably use!
Here's the link, works on mobile Safari.
It's easy to use:
$('selector').doubletap(function() {});
-edit-
And there's a longtap plugin here! You can see a demo on your iPad or iPhone here.
rsplak's answer is good. I checked out that link and it does work well.
However, it only implements a doubletap jQuery function
I needed a custom doubletap event that I could bind/delegate to. i.e.
$('.myelement').bind('doubletap', function(event){
//...
});
This is more important if you're writing a backbone.js style app, where there is a lot of event binding going on.
So I took Raul Sanchez's work, and turned it into a "jQuery special event".
Have a look here: https://gist.github.com/1652946 Might be useful to someone.
Just use a multitouch JavaScript library like Hammer.js. Then you can write code like:
canvas
.hammer({prevent_default: true})
.bind('doubletap', function(e) { // Also fires on double click
// Generate a pony
})
.bind('hold', function(e) {
// Generate a unicorn
});
It supports tap, double tap, swipe, hold, transform (i.e., pinch) and drag. The touch events also fire when equivalent mouse actions happen, so you don't need to write two sets of event handlers. Oh, and you need the jQuery plugin if you want to be able to write in the jQueryish way as I did.
I wrote a very similar answer to this question because it's also very popular but not very well answered.
You can also use jQuery Finger which also supports event delegation:
For longtap:
// direct event
$('selector').on('press', function() { /* handle event */ });
// delegated event
$('ancestor').on('press', 'selector', function() { /* handle event */ });
For double tap:
// direct event
$('selector').on('doubletap', function() { /* handle event */ });
// delegated event
$('ancestor').on('doubletap', 'selector', function() { /* handle event */ });
Here's a pretty basic outline of a function you can extend upon for the longtap:
$('#myDiv').mousedown(function() {
var d = new Date;
a = d.getTime();
});
$('#myDiv').mouseup(function() {
var d = new Date;
b = d.getTime();
if (b-a > 500) {
alert('This has been a longtouch!');
}
});
The length of time can be defined by the if block in the mouseup function. This probably could be beefed up upon a good deal. I have a jsFiddle set up for those who want to play with it.
EDIT: I just realized that this depends on mousedown and mouseup being fired with finger touches. If that isn't the case, then substitute whatever the appropriate method is... I'm not that familiar with mobile development.
based on latest jquery docs i've written doubletap event
https://gist.github.com/attenzione/7098476
function itemTapEvent(event) {
if (event.type == 'touchend') {
var lastTouch = $(this).data('lastTouch') || {lastTime: 0},
now = event.timeStamp,
delta = now - lastTouch.lastTime;
if ( delta > 20 && delta < 250 ) {
if (lastTouch.timerEv)
clearTimeout(lastTouch.timerEv);
return;
} else
$(this).data('lastTouch', {lastTime: now});
$(this).data('lastTouch')['timerEv'] = setTimeout(function() {
$(this).trigger('touchend');
}, 250);
}
}
$('selector').bind('touchend', itemTapEvent);

Leaflet Touch Events not firing

// Setup map
var polymap = L.map('map').setView([51.932994, 4.509373], 14);
// Setup tilelayer
var mapquestUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png',
subDomains = ['otile1', 'otile2', 'otile3', 'otile4'],
mapquestAttrib = 'Data, imagery and map information provided by MapQuest,'
+ 'OpenStreetMap and contributors.';
var osm = L.tileLayer(mapquestUrl, {
attribution: mapquestAttrib,
subdomains: subDomains
});
polymap.addLayer(osm);
polymap.on('mousedown touchstart', function onMouseDown(event) {
alert("start");
});
JSFiddle
Leaflet should normally fire the touchstart event as it does with the mousedown event, but using a mobile phone, I get no event fired.
Can somebody tell me if there's any mistake in the code, that prevents the touchevent from firing?
I have added touch events to leaflet in a branch https://github.com/lee101/Leaflet/tree/add-mobile-touch-events
There is still a problem with touchend events not getting fired if a touchstart event happens on a map control.
You can build the source with npm install && jake after you clone the repository.
I should hopefully contribute it back after i fix that issue.
It is difficult to get normal touch events working properly with leaflet map because the map itself use touch events to permit zoom & pan function.
To avoid this issue, you may use this
library to catch specific touch event (tap,double tap,press,flick,drag)
<script src="http://domain.ltd/path/jquery.finger.js"></script>
$.Finger = {
pressDuration: 300,
doubleTapInterval: 300,
flickDuration: 150,
motionThreshold: 5
};
polymap.on('tap', function(e) {
alert("start");
});
Best regards

Open Layers 3 Zoom map event handler

I need to handle a zoom event in Open Layers 3.
The following is my code:
map_object = new ol.Map({
target: 'map',
controls: controls_list,
interactions: interactions_list,
overlays: [overlay],
layers: [OSM_raster, WFS_layer],
view: view
});
map_object.on("Zoom", function() {
console.log('Zooming...');
});
This code runs with no errors and shows a map, but there is no output to the console, suggesting this function isn't firing.
I have also tried:
map_object.on("drag", function() {
console.log('Dragging...');
});
And this too does nothing.
Any help as to how to handle map control events in OL3 would be much appreciated (particularly zooming!). Note I have tried 'zoom' as well as 'Zoom' for the type field of the on method.
Just to add to this, you can check variations of events available with 'propertychange', from what I am seeing, there is no explicit .on ('zoom', ...) but rather you can access 'resolution' and other properties as mentioned in previous comments:
map.getView().on('propertychange', function(e) {
switch (e.key) {
case 'resolution':
console.log(e.oldValue);
break;
}
});
try with moveend event. (see https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:moveend).
As mentioned by tonio, the way to listen on zoom change, which is called resolution change in openlayers terminology, is with
map.getView().on('change:resolution', (event) => {
console.log(event);
});
I find this is better (more succinct, less cruft) than listening on the general propertychange and verifying manually if the change concerns resolution.
This fires rapidly when using the mouse button so throttling it might be a good idea before launching any computation that waits for it to change.
Documentation for View
You can manage the moveend event...
We will need a global variable to alocate map’s view zoom level. I’ve
named it as currentZoomLevel.
There is available a moveend event. Let’s use it, and add a zoom level
check function..
In case of there’s a new zoom level, we trigger a zoomend event to
DOM’s document.
Finally we will need to add zoomend listener to the document element.
var = currentZoomLevel;
map.on('moveend', checknewzoom);
function checknewzoom(evt)
{
var newZoomLevel = map.getView().getZoom();
if (newZoomLevel != currentZoomLevel)
{
currentZoomLevel = newZoomLevel;
$(document).trigger("zoomend", zoomend_event);
}
}
$(document).on('zoomend', function () {
console.log("Zoom");
//Your code here
});
Source

Enable and disable jquery knob dynamically

I'm using the excellent jQuery knob plugin. However, I need to dynamically enable/disable the element depending on user input. There is support for having a disabled state on page load which have the effect that no mouse (or touch) events are bound to the canvas element. Does anyone know how to resolve this issue, that is, how to (after page load) bind and unbind these mouse event listeners?
Ideally I would like to do something like this (on a disabled knob)
$('.button').click(function() {
$('.knob').enable();
});
Edit:
I ended up rewriting the source which binds/unbinds the mouse and touch events. The solution is not perfect so I leave the question open if someone perhaps have a better (cleaner) solution.
html
<input class="knobSlider" data-readOnly="true">
<button id="testBtn">clickHere</button>
script
in doc ready,
$(".knobSlider").knob();
$("#testBtn").click(function(){
$(".knobSlider").siblings("canvas").remove();
if($(".knobSlider").attr("data-readOnly")=='true'){
$(".knobSlider").unwrap().removeAttr("data-readOnly readonly").data("kontroled","").data("readonly",false).knob();
}
else{
$(".knobSlider").unwrap().attr("data-readOnly",true).data("kontroled","").data("readonly",true).knob();
}
});
For reference you can use my jsfiddle link > http://jsfiddle.net/EG4QM/ (check this in firefox, because of some external resource load problem in chrome)
If someone doesn't like how the accepted answer destroys and recreates the internal canvas element, then checkout my approach:
https://jsfiddle.net/604kj5g5/1/
Essentially, check the draw() implementation (I also recommend listening on value changes in the draw method instead of the change and release, which work for and click and mousewheel events respectively, which imo is inconvenient).
var $input = $("input");
var knobEnabled = true;
var knobPreviousValue = $input.val();
$input.knob({
draw: function () {
if (knobPreviousValue === $input.val()) {
return;
}
if (!knobEnabled) {
$input.val(knobPreviousValue).trigger("change");
return;
}
knobPreviousValue = $input.val();
console.log($input.val());
},
});
Try this to disable the control.
I'm still trying to find a way to enable it back
$("#btnDisable").click(function(){
$("#knob").off().prev().off();
});

Categories

Resources