Disable Mouse-wheel to scroll up or down - javascript

I have two pages, these are the conditions I cannot achieve, please let me know if it is not possible.
In one page, I need to disable the mouse-wheel to scroll up. So when I scroll up with mouse-wheel nothing happens, but when I scroll down the page scrolls.
In the other page, I want the exact opposite, I need to disable the scrolling down on mouse-wheel. So when I scroll down nothing happens, but when I scroll up the page scrolls.
This is all i really need, but if you think I need to explain more, please let me know, thank you.

This code works for div with id "mydiv". You can change the mydiv to the body or any other element you want. The code works in all browsers.
JS:
var mydiv = document.getElementById("mydiv");
if (mydiv.addEventListener) {
// IE9, Chrome, Safari, Opera
mydiv.addEventListener("mousewheel", MouseWheelHandler, false);
// Firefox
mydiv.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else
mydiv.attachEvent("onmousewheel", MouseWheelHandler);
function MouseWheelHandler(e) {
// cross-browser wheel delta
var e = window.event || e; // old IE support
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if(delta==1) // if mouse scrolls up
{
alert('up');
}
if(delta==-1) // if mouse scrolls down, we disable scrolling.
{
e.preventDefault();
e.stopPropagation();
return false;
}
return false;
}
NOTE: Remember to set overflow to auto or scroll for this function to work.
A working example: Click Here
Hope this helps.

Case of preventing mouse scroll down (for mouse scroll up just change comparison operator to '<'):
$(window).on("wheel mousewheel", function(e){
if(e.originalEvent.deltaY > 0) {
e.preventDefault();
return;
} else if (e.originalEvent.wheelDeltaY < 0) {
e.preventDefault();
return;
}
});
We need to check for two values because of cross-browser issues.
jsFiddle link
P. S. Warning. Since later versions of Chrome decides to treat all window events as passive by default, the code above won't work in Chrome. Will come with a better solution and update this answer ASAP.

You could try this to disable mouse scroll. I understand this is not as per your question but I believe it could help you.
JS:
function disableMouseScroll() {
return false;
}
document.onmousewheel=disableMouseScroll;
Link

Related

Scroll vertically with two fingers

I'm working on a sketch web application (using angular) and, as the one finger gesture is used to draw, I would like to be able to scroll vertically in the sketch content using two fingers.
When a try to scroll with two fingers, safari exits the current tab and show the list of opened tabs. I can cancel this behaviour by calling preventDefault() on the TouchEvent if e.touches.length > 1 but (obviously) that doesn't scroll the content. I could, of course, implement a solution that would dynamically scroll after calling e.preventDefault(), but that's a bit tricky.
I would like to know if someone knows an easier/better solution?
Thanks
Finally, I implement a basic solution based on the touchmove and touchstart events.
let lastTouchY;
element.addEventListener('touchstart', (event) =>
{
if (event.touches.length === 2)
{
event.preventDefault();
lastTouchY = event.touches[0].clientY;
}
});
element.addEventListener('touchmove', (event) =>
{
if (event.touches.length === 2)
{
event.preventDefault();
const delta = lastTouchY - event.touches[0].clientY;
lastTouchY = event.touches[0].clientY;
element.scrollTop += delta;
}
});
JSFiddle
https://jsfiddle.net/r7hkmaeo/84/

Javascript events in Chrome and Firefox

I noticed that these function doesn't work good in Firefox, but does in Chrome.
I use these function in a game in Js to shoot bullet (left mouse click) and to create a fireball all around the player with the right click that burns everyone in a small radius.
document.onclick = function(event) {
if(!player){ //to avoid onclick to be used before calling Player();
return;
}
if(player.canAttack && player.distance >= 80) { //not for sword attack
performAttack(player);
player.canAttack = false;
}
if(player.distance < 80)
performAttack(player);
//event.preventDefault();
}
document.oncontextmenu = function(event) {
//hide default behaviour of right click -> no context menu popup
event.preventDefault();
if(player.obtainedGadjet > 0) {
player.pressingMouseRight = true;
performSpecialAttack(player);
}
}
In the performAttack function I set player.isStopped = true, so my updatePlayer() doesn't change player.x and player.y while he's attacking. The same for the fireball attack. I want my player stays there.
It works in chrome, my player stops, attacks,and then can moves again, but in Firefox if I right click it somethimes acts instead as I have left clicked, so shoot the magic ball, and maybe then the fireball too. Furthermore, my player ignore isStopped = true, it seems like in Firefox oncontextmenu has "lower priority" than other events.
Any idea?
Thanks
Please note that a click event contains information about which button was pressed. You can try yourself with something like:
document.addEventListener('click', function(ev){
console.log(ev.button);
});
And, yes, click events are fired when you right-click, even if you're doing something on related contextmenu events.
So your code should look a bit more like
document.addEventListener('click', function(ev){
if (ev.button === 0) {
// Perform primary action
} else if (ev.button === 2) {
// Perform secondary action
}
});
document.addEventListener('contextmenu', function(ev){
ev.preventDefault();
});
Using the same click event is advisable as said by Ivan. You may also want to read this other discussion here on SO about best practices and why it's not always good to disable default right click behaviour (i.e.: it's not always guaranteed to work).

In IE8 and blackberry playbook javascript setInterval function not working properly

I have a defined a click which works as desired in all except two. I am binding the click event as follows :
$('#next_item').bind(myDown,function (e) {
config.scrolling = true;
config.scrollTimer = setInterval(function (e) {
if(!config.scrolling) return false;
if(myScroll.x >= myScroll.maxScrollX){
myScroll.scrollTo((config.itemWidth+config.itemBoxSpacing), 0, 400, true);
}else{
config.scrolling=false;
clearInterval(config.scrollTimer);
}
}, 100);
return false;
});
I am using iScroll 4. The #next_item is used to scroll the dynamically added div onclick. setInterval function() is used because on single click i want to scroll one div at a time and on mousedown i want the div to scroll till i do mouseup. Now the problem is on single click more then one div scroll at a time in blackberry playbook but works fine in ipad, android tablet and desktop browser including IE8. Also when i do mousedown in blacberry playbook the div keeps on scrolling till end and does not stop immediately on mouseup and for IE8 the div stops and scroll seems like setInterval is not working properly. What changes needs to be done to make this work in both IE8 and blackberry playbook
Update :
var isIOS = config.isIpad || config.isIphone || config.isAndroid;
var myDown = isIOS ? "touchstart" : "mousedown";
var myUp = isIOS ? "touchend" : "mouseup";
$('#next_item').bind(myUp,function (e) {
config.scrolling = false;
clearInterval(config.scrollTimer);
return false;
});
I have solved the blackberry problem. I had to just change one line of my code.
var isIOS = 'ontouchstart' in document.documentElement; /*This detects all touch devices*/
In my earlier code i was not detecting blackberry playbook and so it was receiving the mousedown event which caused the default touchstart event for touch devices to trigger along with the mousedown event and hence unexpected result.
I still could not solve the IE8 issue. Please anyone suggest what to do for IE8.

Safari iPad 1: how to disable zoom/centering on double-tap, but keep pinch zoom

I wonder if its possible to prevent double-tap-to-zoom and double-tap-to-center on a specific HTML element in Safari iOS (iPad 1) ?
Because my small HTML5 game forces users to make fast clicks (or taps), which are interpreted as double clicks, and when it happens - the page changes zoom and centers itself.
Detecting double clicks (like in this answer - Safari iPad : prevent zoom on double-tap) smells bad..
Wrong answer #1:
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> - does not suit my purposes, because it will block any zoom.
Wrong answer #2: maybe would .preventDefault() on click event alone be enough for that ? - Does not have any effect.
There's no other way than catching the events you want to prevent, and call preventDefault() on them, as you had already more or less figured out.
Indeed, some particular CSS properties / values may change the global site behavior (fixed width or fixed, for example), but you're not safe from changes to the OS (see fixedhandling change in iOS5), nor do these changes necessarily prevent all behavior (pinch might be off, but not double-tapping).
So, the best way to disable default behavior only for double-tapping is to take advantage of the count of touches iOS provides: if we have only one contact, then we're tapping. Two, this means we're pinching.
The following setup code provides that functionality:
var elm = document.body; // or some selection of the element you want to disable
var catcher = function(evt) {
if (evt.touches.length < 2)
evt.preventDefault();
};
elm.addEventListener('touchstart', catcher, true);
Demo on jsFiddle.
Note: the third parameter (true) to addEventListener means that we want to capture events, that is catch them all, even for our descendant children.
I am preventing doubletaps like this:
var doubleTouchStartTimestamp = 0;
$(document).bind("touchstart", function (event) {
var now = +(new Date());
if (doubleTouchStartTimestamp + 500 > now) {
event.preventDefault();
}
doubleTouchStartTimestamp = now;
});
The elegance lies within the fact, that no timeouts are needed. I only update a timestamp. It only gets compared on the next touchstart. Works for me on iOS 6.
Doubletaps further down the dom are not affected.
The same works without jQuery, as well:
var doubleTouchStartTimestamp = 0;
document.addEventListener("touchstart", function (event) {
var now = +(new Date());
if (doubleTouchStartTimestamp + 500 > now) {
event.preventDefault();
}
doubleTouchStartTimestamp = now;
});
I wrote a jQuery plugin for the same purpose - selectively disabling double-tap zoom on given page elements (in my case, navigation buttons to flip pages) I want to respond to every tap (including double-tap) as a normal click event, with no iOS "touch magic", no matter how fast the user clicks it.
To use it, just run something like $('.prev,.next').nodoubletapzoom(); on the elements you care for. The principle it uses is to listen for consecutive touchstart events on a node within 500ms, and running event.preventDefault() on the second, unless other touches are active at the same time. As that preventDefault consumes both touches, we also synthesize the two "missed" click events for the node, so your intended touch action happens as many times as the user intended.
Apple has a lot of tips with specialized tags for webkit (Safari). View Official Docs
What iOS version/Safari browser are you using? That site most definitely does not let you double-tap. I found some CSS but haven't had time to try it as I'm about to step out:
body {
-webkit-text-size-adjust:none;
margin:0px;
}
div{
clear:both!important;
display:block!important;
width:100%!important;
float:none!important;
margin:0!important;
padding:0!important;
}
You will need to implement a double tap function and preventDefault on the second tap. Here is some tested code that uses global variables that should get you started:
<button id="test1">Double Tap Me!</button>
<div id="test2">EMPTY</div>
var elm1 = document.getElementById('test1');
var elm2 = document.getElementById('test2');
var timeout;
var lastTap = 0;
elm1.addEventListener('touchend', function(event) {
var currentTime = new Date().getTime();
var tapLength = currentTime - lastTap;
clearTimeout(timeout);
if (tapLength < 500 && tapLength > 0) {
elm2.innerHTML = 'Double Tap';
event.preventDefault();
} else {
elm2.innerHTML = 'Single Tap';
timeout = setTimeout(function() {
elm2.innerHTML = 'Single Tap (timeout)';
clearTimeout(timeout);
}, 500);
}
lastTap = currentTime;
});
And a fiddle: http://jsfiddle.net/brettwp/J4djY/
JQuery approach to disable Double Tap Zoom in MVC4
To Disable the double tap (double mouse down) functionality on iOS 1+ you need to catch the touchStart Event and create an override to prevent the zoom.
// Using Single script.js and JQuery.Mobile-1.2.0 UI each page in MVC gets assigned JQuery through delegates so you don't have to do a full refresh of the page allowing you to take advantage of the data-prefetch which loads the page in the DOM when the app loads for the first time
$(document).delegate("#CashRegister", "pageinit", function () {
// To Disable 'Pinch to Zoom' Note: don't implement gester event handlers if you want to
//keep pinch to zoom functionality NOTE: i use this as my pageinit is a delegate of a page
this.addEventListener("gesturestart", gestureStart, false);
this.addEventListener("gesturechange", gestureChange, false);
this.addEventListener("gestureend", gestureEnd, false);
//handle each event by disabling the defaults
function gestureStart(event) {
event.preventDefault();
}
function gestureChange(event) {
event.preventDefault();
}
function gestureEnd(event) {
event.preventDefault();
}
//Recreate Double Tap and preventDefault on it
$(this).bind('touchstart', function preventZoom(e) {
// recreate the double tab functionality
var t2 = e.timeStamp
, t1 = $(this).data('lastTouch') || t2
, dt = t2 - t1
, fingers = e.originalEvent.touches.length;
$(this).data('lastTouch', t2);
if (!dt || dt > 500 || fingers > 1) return; // not double-tap
e.preventDefault(); // double tap - prevent the zoom
// also synthesize click events we just swallowed up
$(this).trigger('click').trigger('click');
});
Actually, .preventDefault() definitely does work... using jQuery:
var InputHandler = {
startEventType : isTouch ? "touchstart" : "mousedown"
}
$(selector).bind(InputHandler.startEventType, function(evnt) {
evnt.preventDefault();
});
Your problem with trying to prevent on .click() is that the browser isn't throwing a "click" element. Safari only fires a click to help simulate a click... But when there's a double tab, Safair doesn't through a "click" element. Your event handler for .click() doesn't ever fire, and therefore the .preventDefault() doesn't fire either.

How to detect mouseup on a scrollbar? (or "scrollEnd" event)

Anyone have any idea how to detect a mouseup event on a scrollbar? It works in FF, but not in Chrome or IE9.
I set up a quick demo: http://jsfiddle.net/2EE3P/
The overall idea is that I want to detect a scrollEnd event. There is obviously no such thing so I was going with a combination of mouseUp and timers, but mouseUp isn't firing in most browsers! The div contains a grid of items so when the user stops scrolling I want to adjust the scroll position to the nearest point that makes sense, e.g. the edge of the nearest cell. I don't, however, want to automatically adjust the position if they're in the middle of scrolling.
I'll also happily accept any answer that gives me the equivalent of scrollEnd
found a solution that works without timers but only if you are scrolling the complete window.
switch(event.type){
case 'mousedown':
_btnDown = true;
//THIS IS ONLY CAUSE MOUSEUP ON SCROLLBAR IS BUGGY
$(document).bind('mousemove',function(event){
if(event.pageX < ($(window).width() - 30)){
//mouse is off scrollbar
$(this).unbind(event);
$(this).trigger('mouseup');
}
});
break:
case 'mouseup':
//do whatever
_btnDown = false;
break;
}
pretty dirty .. but works.
Using jquery there is a .scroll event you can use. Maybe use a global variable to keep track of when .scrollTop() (it returns the number of pixels there are above the screen) has stopped changing? Still creates a race condition, but it should work.
Answering my own question so I can close it -- there is no good solution to this, so timers it is...
I was handling the same problem. For me IE9 don't emit mouseup event for scrollbars. So, I checked and on IE9 when you "mouseup" it emits a mousemove event. So what I did was monitor scrolling, and monitor mousemove. When user is scrolling, and a mousemove event happens, then I understand it as a mouseup event. Only do this check for IE9, cheching the proto property availability. The code will also run for Opera, but Opera has the mouseup and then no problem for me when both events happens. Here is the code, I write AngularJS + ZEPTO code, so get the idea and write your own code, don't expect to copy&paste this code directly:
// Global for scrolling timeout
var q;
// Action to do when stop scrolling
var updatePosition = function() {
// Put the code for stop scrolling action here
}
$(document).on('mousemove', function(e) {
console.log('MOUSE MOVE ' + e.pageX + ',' + e.pageY);
if(!('__proto__' in {})) {
// for IE only, because it dont have mouseup
if($scope.scrolling && $scope.mouse_down) {
console.log('FAKE MOUSE UP FOR IE');
// Only simulate the mouseup if mouse is down and scrolling
$scope.scrolling = false;
$scope.mouse_down = false;
// Update Position is the action i do when mouseup, stop scrolling
updatePostition();
}
}
});
$(window).on('scroll', function(){
console.log('SCROLLING');
// Set the scrolling flag to true
if(!$scope.scrolling) {
$scope.scrolling = true;
}
// Stop if for some reason you disabled the scrolling monitor
if(!$scope.monitor_scrolling) return;
// Monitor scroll with a timeout
// Update Position is the action i do when stop scrolling
var speed = 200;
$timeout.cancel(q);
q = $timeout(updatePostition, speed);
});
$(window).on('mousedown', function() {
console.log('MOUSE DOWN');
// Stop monitor scrolling
$scope.monitor_scroll = false;
// Set that user is mouse down
$scope.mouse_down = true;
});
$(window).on('mouseup', function() {
console.log('MOUSE UP');
// Enable scrolling monitor
$scope.monitor_scroll = true;
// Change mouse state
$scope.mouse_down = false;
// Action when stop scrolling
updatePostition();
});
Was fighting with this problem. My system also runs for mobile and I have a large horizontal scrolling, that always when user stop scrolling, it need to find the actual item the used is viewing and centralize this item on screen (updatePosition). Hope this can help you. This is to support IE9+, FF, Chorme and Opera, I'm not worrying with old browsers.
Best Regards
Is very late but.... there are solution with any scroll in any part of your page.... I do it with the next code...
onScroll = function(){
$(window).unbind("mouseup").one('mouseup',function(e) {
alert("scroll up")
});
};
$(window).bind("scroll", onScroll);
body{
height:5000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories