Understanding consumeRollupEvent - javascript

I have an add-on, where when user holds down right mouse button, they can scroll the wheel and it will change tabs.
Now in Windows, if user pushes down on right button it doesn't open context menu. In linux it opens context menu on mouse down.
DOMMouseScroll event listner is on the chrome window ie: window.addEventListener('DOMMouseScroll', func, true)
So if you copy this code and paste it to scratchapd:
window.addEventListener('DOMMouseScroll', function() {
window.removeEventListener('DOMMouseScroll', arguments.callee, true);
console.log('scroll caught and removed')
}, true)
then go to the browser window, right click to open context menu, and scroll while mouse is over the context-menu, in windows, the scroll is caught. In linux it is not. (curious note here: mousedown events are caught if listener added on window and the click was in the context-menu).
I thought setting consume rollup event to no consume would solve it. But it's not.
Any ideas on how to fix this issue and does consumeRollupEvent have any affect here?
Currently i was setting consume rollup event to false in the popupshowing event of context-menu:
noConsume: function(event) {
if (event.target != document.getElementById('contentAreaContextMenu')) { return }
if (event.target.popupBoxObject) {
//event.target.popupBoxObject.setConsumeRollupEvent(Components.interfaces.nsIPopupBoxObject.ROLLUP_NO_CONSUME); //no longer support setConsumeRollupEvent
}
event.target.setAttribute('consumeoutsideclicks', false);
event.target.consumeoutsideclicks = false;
},
Right now I'm suspecting it's the DOMMouseScroll event that's not being caught, so i changed it to addEventListner('wheel'... and sent user test addon, waiting for his word back.

I don't think setConsumeRollupEvent will help you to intercept the scroll events. It refers to the rolling up of the context menu (i.e. the event that caused the context menu to close); nothing to do with mouse wheel rolling.
https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Method/setConsumeRollupEvent
It might be worth concentrating on why there is a difference in behaviour between Windows and Linux. It might be a Firefox bug or at the very least it might give you a clue about the best way to work around it. Maybe there is a way to prevent the context menu being invoked on MouseDown in Linux, it sounds like that would be the most desirable outcome for your add-on.

Related

Responding to touchstart and mousedown in desktop and mobile, without sniffing

So, I have a problem. I want to respond to a user pressing the mouse button (on desktop) or touching a div (on mobile). I'm trying to be compatile with evergreen browsers. This is what I tried so far:
listen only to mouseDown event. This works on desktop but doesn't work in mobile if the user is dragging. I want the handler to be called as soon as the user touches the screen, no matter if they're moving their finger in the process.
listen only to touchStart event. This works on mobile and desktop, except for Edge and Safari desktop, which don't support touch events.
listen to both, then preventDefault. This causes a double handler call on Chrome mobile. It seems that touch events are passive to allow uninterrupted scrolling on mobile Chrome, so preventDefualt has no effect on them . What I get is a warning message saying "[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080" in the console, preventDefault is ignored and my event is called twice.
Obviously this can be solved by sniffing touch events, but the net is full of self-righteous rants on how one has to be device-agnostic and that it's dangerous to detect touch events before the user interacted.
So I guess that the question is: is there a way to do what I want to do without sniffing for touch events?
Below my sample React code:
function handler(e) {
console.log('handler called')
e.preventDefault()
}
export default function MyElement() {
return (
<div
onMouseDown={handler}
onTouchStart={handler}
>
Hello
</div>
)
}
It turn out it's not yet possible in React. One workaround is set a flag the first time touchStart it's received.
touchHandler = () => {
this.useTouch = true
this.realHandler()
}
mouseHandler = () => {
if (this.useTouch) return
this.realHandler()
}
With the caveat that the first touchStart can be lost in case of dragging.
Quite disappointing.

Disable taphold default event, cross device

I'm struggling to disable default taphold browser event. Nothing that I have found on Google provided any help. I have only Android 4.4.4 mobile and Chrome dev tools for testing. I tried CSS fixes, such as webkit-touch-callout and others, but apparently they don't work for Android, also they don't work in Chrome dev tools.
I also tried detecting right click, (e.button==2), it doesn't work.
I came up with a solution, but it solves one problem and creates another. I just want to have a custom action for 'long press' event for selected anchors and I don't want the default pop up to appear (open in a new tab, copy link address, etc.)
This is what I did:
var timer;
var tap;
$("body").on("touchstart", my_selector, function(e) {
e.preventDefault();
timer = setTimeout(function() {
alert('taphold!');
tap=false;
},500);
});
$("body").on("touchend", my_selector, function() {
if(tap) alert('tap');
else tap=true;
clearTimeout(timer);
});
It successfully disables the default taphold event and context menu doesn't appear. However it also disables useful events, such as swipe. The links are in a vertical menu and the menu is higher than the screen, so a user has to scroll it. If he tries to scroll, starting on an anchor, it won't scroll, it will alert 'tap!'
Any ideas how could I disable taphold default or how could I fix this code so it disables only tap events and leave default swipe events enabled?
Edit: Now I thought about setting a timeout, if the pointer is in the same place for lets say 100ms, then prevent default action. However e.preventDefault(); doesn't work inside setTimeout callback.
So now I'm just asking about the simplest example. Can I prevent default actions after certain amount of time has passed (while the touch is still there).
And this is my whole problem in a fiddle. http://jsfiddle.net/56Szw/593/
This is not my code, I got this from http://www.gianlucaguarini.com/blog/detecting-the-tap-event-on-a-mobile-touch-device-using-javascript/
Notice that while swiping the box up and down, scrolling doesn't work.
I got the solution. It was so simple! I had no idea there's an oncontextmenu event. This solves everything:
$("body").on("contextmenu", my_selector, function() { return false; });
For an <img> I had to use event.preventDefault() instead of return false.
document.querySelector('img').addEventListener('contextmenu', (event) => {
event.preventDefault();
}

Chrome right-click dialog swalllows mouse events

In Chrome the right-click dialog seems to swallow all mouse events. This means that you get mouse-down events without corresponding mouse-up events.
This includes every right-click, and any left-click where the right button is pressed before the left button is released (in which case you get two mouse-downs but no mouse-ups).
You can see the problem in action here (you may wish to mute your speakers) if you're curious.
I was just wondering if anyone knew of any workarounds for this? Using window.onmousedown instead of document.onmousedown doesn't fix the problem unfortunately.
You'll want to add a handler for the contextmenu event that cancels the opening of that menu.
See MDN for some details.
window.oncontextmenu = function(event) {
event.preventDefault();
event.stopPropagation();
return false;
};

jquery detecting mouseup

I have a problem.
The code works fine in Firefox but in Chrome it messes up.
The code is rather basic.
There's a div with a background. Upon jquery's mousedown upon that div I set a function to run at an interval. Upon mouseup the interval is cleared. Simple, right?
So problem is this. Say the user right-clicks in Chrome and brings up the context menu. Or they drag the div. The mouseup event is no longer registered.
Any ideas?
I had an idea where I'd just get the status of the mouse button. But that seems to be impossible to do without a mouse even firing.
function mouseD(e){
mouseE = e;
timer = setInterval(scroller, 50);
$(document).mouseup(function(){
clearInterval(timer);
});
//mouseB = e.button;
//mouseW = e.which;
//console.log(e.button + " D " + e.which);
}
imgbox.mousedown(mouseD);
EDIT:
So I managed to solve the context menu and dragging problems by disallowing such acts. The user just can't do it anymore. But if the user right- and left-clicks at the same moment the mouseup never registers.
Check out this website: it goes into detail about Mouse Events with different browsers.
http://unixpapa.com/js/mouse.html

How do I catch taps but not scrolling in Javascript in Android?

I'm making an Javascript web app and I can't for the life of me get the touchstart event to fire. I get the touchmove and touchend events no problem. This is a problem because as I see it the best way to distinguish between a tap and a scrolling motion is to zero a counter on the touchstart event, update it at touchmove and then compare it at touchend. I'm doing this so I can do some action at the end of tap but not a scroll. For instance, it would be very confusing if a page opened for an item in a listed after you finished scrolling down that list, but it would be nice to be able to tap on an item to open its page.
This is what I have:
// FIXME: this doesn't seem to ever fire
el.addEventListener('touchstart', function(e) {
// make sure that at the start of every touch we're not considered to be moving
alert("Touch starting");
app.__touchMoving = 0;
}, false);
el.addEventListener('touchmove', function(e) {
app.__touchMoving++;
}, false);
el.addEventListener('touchend', function(e) {
alert("Touch ended. We moved beforehand this many times: " + app.__touchMoving);
// if we are moving
if (app.__touchMoving > 0) {
// stop, since we're dragging, not tapping
return false;
}
// else we're no longer moving, so it was a tap
}
I never see the touchstart alert. If I scroll the touchend will fire and app__touchMoving will have some sort of decent value. On a side note, I've noticed that sometimes the touchend will seem to fire multiple times.
Am I missing something basic here? Plenty of people say that this should work just fine on Android (and iPhone) yet the first listener never seems to fire.
Update: I should mention that I've been testing on a Samsung Galaxy S running Android 2.1.
I don't know if u can use it: iScroll

Categories