How to take control of mousewheel scroll before it happens? - javascript

I'm trying to get the event for a mousewheel scroll right before it happens so that I can stop the scroll and do some stuff and then give back control to the user.
Currently I have the following code to cancel out the scroll. However the scroll happens once and then control is taken away from the user. I'd like to make sure the scroll does not happen, do some other stuff instead, and then give control back afterwards.
$('body').on({ 'mousewheel': function(e) {
e.preventDefault();
e.stopPropagation();
}});
How can I do this?

You can use the onwheel event.
window.onwheel = function(){
alert('your magic here');
return false;
}

Are you able to debug and see if the event is being fired in the first scroll?
Is your code inside a $(document).ready( function?
If you are using jquery-mousewheel plug-in, you will be able to call this only if you are attaching it after the plug-in is ready and declared before your script (might be on your page header).

Related

jQuery disable clicks temporarily

My website has lots of elements which trigger ajax data retrieval on click, and some drag&drop elements handled by jquery ui. Many elements use their own click events, attached directly to them. I need some functionality which will ignore all mouse clicks/mouseup/mousedown events temporarily under some predefined circumstances. For example, I want to disable drag & drop entirely until some ajax request is in progress, etc. I thought I would bind on click and preventDefault(), I tried to bind on document, like this, but it doesn't seem to work:
$(document).on("mousedown", "*", null, function(ev){ev.preventDefault();});
I think it's because when the event reaches $(document), it was already triggered on all childs, so it's too late to preventDefault().
One solution I could imagine is to set some global variable, like ignore_clicks=true; and then add to every function which handles mouse click a check if this variable is true or not. This seems very difficult and I'm afraid even impossible due to external click handlers like in jquery-ui code.
Another solution I imagine is to temporarily put some fixed style element, 100% width and 100% height, zero opacity, over the current page, but this doesn't seem like an ideal solution, feels more like a hack. Furthermore if there is any ongoing animation on the webpage while it is covered by transparent element, the performance of the animation is degraded.
Is there any simple and elegant solution which would allow me to temporarily block all mouse clicks on the given page? (mouseup & mousedown too).
One solution is to stop the event in the capturing phase by using addEventListener:
document.addEventListener("mousedown", function(e) {
e.preventDefault();
e.stopPropagation();
}, true /* true == capturing phase */);
Do note that this won't work in IE8.
With jquery you can toggle on/off event handlers:
function doClick(e) {
e.preventDefault(); //Prevent default event.
//do some fancy ajax stuf...
};
//Toggle on:
$(document).on('click', '.clickable', doClick);
//Toggle off:
$(document).off('click', '.clickable', doClick);
This will work with any event such as click/mousedown/mouseup etc.
If you want to prevent all other events from being fired, you could try as follows:
function preventPropagation(e) {
e.stopImmediatePropagation();
};
//Toggle on when ajax:
$(document).on('click mousedown mouseup', '*', preventPropagation);
//Toggle off when ajax finishes:
$(document).off('click mousedown mouseup', '*', preventPropagation);
If you want to prevent all mouse-based interactions, you could place an invisible overlay in front of the dom, e.g.
HTML
<div id="click-blocker" style="display: none;"></div>
CSS
#click-blocker {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
JS
// to disable clicks:
$('#click-blocker').show()
// to enable clicks again
$('#click-blocker').hide()
By showing the click-blocker, all clicks will happen to the blocker, since it's in front of everything, but since it has no content or background, the user will perceive it as their clicks are just not doing anything.
This won't work if you only want to disable a specific type of interaction, e.g. drag+drop as you mentioned.
I do not think having a "processing" animation overlay is a hack and it seems pretty elegant to me. Plenty of applications use this because it gives users feedback. They know that the application is working and they'll have to wait.

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();
}

How do I make a div both scrollable and clickable?

<div id="menuContainer"></div>
<div id="menuItemTemplate" class="menuItem">
<div class="menuItemTitle"></div>
<div class="menuItemImage"><img src="resources/BlackRightChevron.png"/></div>
</div>
The menuContainer div is dynamically appended with clones of the menuItemTemplate. The current click event:
menuContainer.addEventListener('click',menuContainer_click,false);
does not fire when menuContainer overflows in the y-axis.
So I implemented some code found else where on stackoverflow.
Which makes it scrollable but the click events do not run (probably because of the preventDefault()s). Without them I figure every event would be registered as a click instead of a possible move.
Oh, I'm using jQuery mobile and it's UI as well.
Is there any solution to my problem?
The changes I made as per the suggestion:
var scrollStartPosY=0;
document.getElementById(element).addEventListener("touchstart", function(event) {
scrollStartPosY=this.scrollTop+event.touches[0].pageY;
event.preventDefault();
},false);
document.getElementById(element).addEventListener("touchmove", function(event) {
this.scrollTop=scrollStartPosY-event.touches[0].pageY;
event.preventDefault();
move = true;
},false);
document.getElementById(element).addEventListener("touchend", function(event) {
if(move)
move = false;
else
menuContainer_Click(event);
},false);
I'm sure the preventDefaults are wiping out your click. In any case you're using click/mousedown/touchstart to scroll exclusively.
What I think you should do is register a touchend event to trigger whatever you intend to have the current click event do. You may want to verify whether there has been a scroll in the meantime and if so, ignore the touchend. That would differentiate between the two separate intentions of scrolling and clicking.
Decided that iScroll was just an easier solution. Though having difficulty with only one div not scrolling completely to the "bottom".

Avoid page back to top after load

I'm using this script
jQuery(document).ready(function($) {
$(".scroll").click(function(event){
event.preventDefault();
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 2000);
});
});
in order to smooth scroll down when my nav elements are clicked... the problem is that if a link is clicked before page finish loading, when it finishes the page will go back to top again.
I thought event.preventDefault(); was to avoid that. Help please.
you should use the document.onLoad event instead.
document.ready is invoked after all of the HTML is brought down into the document and ready for parsing.
onLoad on the other hand is invoked after all images / resources are loaded into the page as well.
If you wait for this event, then you should have desired results. although they won't have any click functionality until then.
Furthermore, preventDefault does not avoid this. All that does is disable the default action of the element you apply it to. so it prevent's whatever the default action would be for your 'scroll' elements

Why does 'mousemove'-event triggers on page load and how to prevent this (using jQuery mobile)?

when I bind the mousemove-event on the body
$("body").mousemove(function(e)...
on document-ready it also triggers when the page is loaded, the mouse is inside the browser window but mouse isn't moved. Why is that? How could I prevent this?
Edit: seems that this is a Safari-Bug. In Firefox I can't reproduce this behaviour.
this should not be happining anyhow just try bind() or live().
$("body").stop(true)
$("body").bind('mousemove', function(e){
alert('mouse moved');
});
on load, call the following :-
document.onmousemove=return false;
window.onmousemove=return false;
MouseDown will not work

Categories