How to restrict scrolling to the div that mouse is currently hovering? - javascript

I have a div name scrollable and whenever I hover mouse over it I want scrolling limited to this div only so that after reaching top/bottom of the div, scrolling will be stuck to the div. I've used the following code:
<div class="scrollable" style="overflow-y: scroll; height: 2px;"
onmouseover="document.body.style.overflow='hidden'"
onmouseout="document.body.style.overflow='auto'" >
Some text<br>sometext<br>sometext
</div>
Doing this gets the job done, but only problem as main scrollbar is hidden the webpage looks weird everytime I hover over '.scrollable'
Also using window.onwheel=function(){return false;} doesnt help as it prevents scrolling of anyelement.
Is there a way to enable scrolling only on hovered div and not on others while keeping main page scrollbar visible?
Thank you

You can disable scrolling without hiding the scrollbar, check this post.
Using jQuery, this would lead to:
$(".scroll").hover(function() {
var oldScrollPos = $(window).scrollTop();
$(window).on('scroll.scrolldisabler', function(event) {
$(window).scrollTop(oldScrollPos);
event.preventDefault();
});
}, function() {
$(window).off('scroll.scrolldisabler');
});
Check it out.

For me, hopefully can work
$('body').on('mousewheel', '.someDIVClass', (e: any) => {
if (e.originalEvent.wheelDelta / 120 > 0) {
// You can get scroll value here to do other things
}
else {
// You can get scroll value here to do other things
}
// This will prevent window to scroll
e.preventDefault();
e.stopPropagation();
});

Related

How to link page scroll to a div element scroll? Or how to scroll div element using page scroll?

So I have an issue with scrolling the page and some div with content inside it.
There is a .container at the bottom of the page and footer goes after it.
When an user gets to the bottom of the page there should be possibility to continue scrolling the page but exactly the .scrollable container should be scrolled.
By default we can scroll .scrollable div's content if mouse cursor is over it. But I need to somehow link common page scroll to this .scrollable div's scroll.
How does this problem can be solved?
Here the JSFiddle link to make the issue more clear
$(window).on('mousewheel', function(e) {
//scrolling bottom
if(e.originalEvent.wheelDelta /120 <= 0) {
//checks if we reached bottom
if($(this).scrollTop() + $(this).height() == $(document).height()) {
$('.scrollable').scrollTop($('.scrollable').scrollTop() + 10);
}
}
});
EDIT: After lots of digging I've managed to build a script for exactly what you need
NOTE: The event is currently bound on mousewheel but there are more types of scrolling such as: dragging, clicking, arrow keys and I'm not aware of function to cover them all and do the thing you want in the same time.
I forked your Fiddle

Prevent parent page from scrolling when mouse is over embedded iframe in Firefox

...without limiting the scroll inside the iframe or the need to specifically name/tag all scrollable elements.
Imagine google maps widget embedded in parent page. When you zoom in the widget you don't want the parent page to scroll, obviously.
I thought an answer to my previous question solved the problem:
While scrolling inside an iframe, the body doesn't know anything about
what happens there. But when iframe scroller reach the bottom or the
top, it pass scrolling to body.
Cancel the event that propagates from the iframe.
But the solution does not work in Firefox because Firefox will not - by design - propagate events captured by iframe to the parent page, yet strangely it will scroll the parent page. See jsfiddle here.
$('body').bind('mousewheel DOMMouseScroll', onWheel);
function onWheel (e){
if (e.target === iframe)
e.preventDefault();
console.log(e);
}
So, how do I prevent page from scrolling when user zooms content in embedded iframe, in Firefox?
Since it is a bug in Firefox, the workaround is to work directly with the scroll event, instead of the mousewheel / DOMMouseScroll ones.
The way I did: When user enters the mouse over the iframe, I set a flag to true, and when he leaves the mouse out there, I set it back to false.
Then, when user tries to scroll, but the mouse arrow is inside the iframe, I prevent the parent window scrolling. But, unfortunately, you can't prevent the window scrolling with the usual e.preventDefault() method, so we still need another workaround here, forcing the window to scroll exactly to the X and Y positions it was already before.
The full code:
(function(w) {
var s = { insideIframe: false }
$(iframe).mouseenter(function() {
s.insideIframe = true;
s.scrollX = w.scrollX;
s.scrollY = w.scrollY;
}).mouseleave(function() {
s.insideIframe = false;
});
$(document).scroll(function() {
if (s.insideIframe)
w.scrollTo(s.scrollX, s.scrollY);
});
})(window);
I've created an immediately executed function to prevent defining the s variable in the global scope.
Fiddle working: http://jsfiddle.net/qznujqjs/16/
Edit
Since your question was not tagged with jQuery (although inside it, you've showed a code using the library), the solution with vanilla JS is as simple as the above one:
(function(w) {
var s = { insideIframe: false }
iframe.addEventListener('mouseenter', function() {
s.insideIframe = true;
s.scrollX = w.scrollX;
s.scrollY = w.scrollY;
});
iframe.addEventListener('mouseleave', function() {
s.insideIframe = false;
});
document.addEventListener('scroll', function() {
if (s.insideIframe)
w.scrollTo(s.scrollX, s.scrollY);
});
})(window);
Given all the prerequisites, I think the following is the sanest way to make this work in Firefox.
Wrap your iframe with a div which is a little bit shorter to enable vertical scrolling in it:
<div id="wrapper" style="height:190px; width:200px; overflow-y: auto; overflow-x: hidden;">
<iframe id="iframeid" height="200px" width="200px" src="about:blank">
</iframe>
</div>
Now you can center the iframe vertically and re-position it every time
the wrapper receives a scroll event (it will occur when a user tries to scroll away at frame edges):
var topOffset = 3;
wrapper.scrollTop(topOffset);
wrapper.on("scroll", function(e) {
wrapper.scrollTop(topOffset);
});
Combine this with your previous fix for Chrome, and it should cover all major browsers. Here is a working example - http://jsfiddle.net/o2tk05ab/5/
The only outstanding issue will be the visible vertical scrollbar on a wrapper div. There are several ways to go about it, for instance - Hide scroll bar, but still being able to scroll
I think that will solve your problem
it solved mine
var myElem=function(event){
return $(event.toElement).closest('.slimScrollDiv')
}
$(document).mouseover(function(e){
window.isOnSub=myElem(e).length>0
})
$(document).on('mousewheel',function(e){
if(window.isOnSub){
console.log(e.originalEvent.wheelDelta);
if( myElem(e).prop('scrollHeight')-myElem(e).scrollTop()<=myElem(e).height()&&(e.originalEvent.wheelDelta<0)){
e.preventDefault()
}
}
})
replace '.slimScrollDiv' with the element selector you want to
prevent parent scroll while your mouse is on it
http://jsbin.com/cutube/1/edit?html,js,output

Disable outside scrolling while in scrollable div [duplicate]

This question already has answers here:
prevent Scroll bubbling from element to window
(15 answers)
Closed 8 years ago.
I've got a few divs that hold information that you can scroll through. But when you hit the top or bottom it changes to the browsers scroll which scrolls the entire page.
I'd like to disable outside scrolling while the mouse is inside of this particular div (there's three of this type of div).
An example of what I'm trying to acheive is youtubes playlist selector.
Here's an example at youtube Hover your mouse inside the popular uploads part and trying scrolling all the way up and down.
EDIT: just tried to use the link in another browser and the video selection part doesn't seem to show up, but it's the "add to playlist" part that enables it.
Does anybody know of a way to do this?
Here's a FIDDLE
<div>
... some content ...
</div>
div {
height: 400px;
overflow: scroll;
}
$('div').on('mousewheel DOMMouseScroll', function(e) {
var scrollTo = null;
if(e.type === 'mousewheel') {
scrollTo = (e.originalEvent.wheelDelta * -1);
}
else if(e.type === 'DOMMouseScroll') {
scrollTo = 40 * e.originalEvent.detail;
}
if(scrollTo) {
e.preventDefault();
$(this).scrollTop(scrollTo + $(this).scrollTop());
}
});
Untested, but might be the answer:
$( "div" ).scroll(function( event ) {
event.stopPropagation();//Do not bubble up the DOM, do not scroll document.
});
stopPropagation() is used to prevent the event of bubbling up the DOM. This way other elements are not notified of this event.
Read more: http://api.jquery.com/event.stoppropagation/

Switch tabs based on mouse scroll

I would like to have a widget on a webpage containing a number of tabs. When the user scrolls the page and the widget comes in to view and he keeps scrolling down, the tabs should be activated one by one (without the page scrolling further down). Once the last tab is showing, the page should resume scrolling as usual. Is this doable using JS/jQuery?
UPDATE:
Since this seems too broad a question:
The problem is, I don't know how to use the scroll offset and prevent the page from scrolling down until I decide it can resume its normal behavior
UPDATE 2
I created This fiddle,
$(document).ready(function(){
$('#tabbed').mouseover(function(){
$(this).focus();
}).scroll(function(){
console.log("scrolling tabs");
});
$(window).scroll(function(evt){
var scrollPos = $(this).scrollTop()
console.log(scrollPos);
// BULLETPROOF WAY TO DETECT IF THE MOUSE IS OVER THE
// SCROLLABLE DIV AND GIVE IT FOCUS HERE?
});
});
it contains a long page and a scrollable div among its contents. The only problem is that the div starts catching scroll events only if I move my mouse. If I could find a bulletproof way to activate the scrolling div whenever the mouse is over it I'm there. Any ideas?
You can't prevent scrolling with javascript. Using iframes and divs with scroll will only work if the mouse is over them.
You can cancel the mouse wheel and keys events related to the scrolling, however the user will be able to scroll using the scrollbar (more here).
Another approach is leaving an empty area and fixing your widget inside this area, like in this working example
$(window).bind('scroll', function()
{
var scroll = $(window).scrollTop(),
innerHeight = window.innerHeight || $(window).height(),
fooScroll = $('#fooScroll'),
emptyArea = $('#emptyArea'),
offset = emptyArea.offset(),
fixedClass = 'fixed';
if(scroll > offset.top)
{
if(scroll < offset.top + emptyArea.height() - fooScroll.height())
{
fooScroll.addClass(fixedClass);
fooScroll.css("top", 0);
}
else
{
fooScroll.removeClass(fixedClass);
fooScroll.css("top", emptyArea.height() - fooScroll.height());
}
}
else
{
fooScroll.removeClass(fixedClass);
fooScroll.css("top", 0);
}
});
Then you can change the tabs while the page is scrolling.
You should be able to do this. You can use the jQuery scroll event to run your own code whenever the user scrolls up or down. Also, so long as you call e.preventDefault() whenever the scroll event is fired, you can prevent the whole window from scrolling up or down.

Always scroll a div element and not page itself

I have a page layout with an inner <div id="content"> element which contains the important stuff on the page. The important part about the design is:
#content {
height: 300px;
width: 500px;
overflow: scroll;
}
Now when the containing text is larger than 300px, I need to be able to scroll it. Is it possible to scroll the <div>, even when the mouse is not hovering the element (arrow keys should also work)?
Note that I don’t want to disable the ‘global’ scrolling: There should be two scrollbars on the page, the global scrollbar and the scrollbar for the <div>.
The only thing that changes is that the inner <div> should always scroll unless it can’t be moved anymore (in which case the page should start scrolling).
Is this possible to achieve somehow?
Edit
I think the problem was a bit confusing, so I’ll append a sequence of how I would like it to work. (Khez already supplied a proof-of-concept.)
The first image is how the page looks when opened.
Now, the mouse sits in the indicated position and scrolls and what should happen is that
First the inner div scrolls its content (Fig. 2)
The inner div has finished scrolling (Fig. 3)
The body element scrolls so that the div itself gets moved. (Fig. 4)
Hope it is a bit clearer now.
(Image thanks to gomockingbird.com)
I don't think that is possible to achieve without scripting it, which could be messy, considering the numerous events which scroll an element (click, scrollwheel, down arrow, space bar).
An option could be using the jQuery scroll plugin. I know it has the availability to create scrollbars on an div. The only thing you need to add yourself is the logic to catch the events when keyboard buttons are pressed. Just check out the keycodes for the arrow keys and make the div scroll down.
The plugin can be found here.
You can use it like this;
<script type="text/javascript">
// append scrollbar to all DOM nodes with class css-scrollbar
$(function(){
$('.css-scrollbar').scrollbar();
})
</script>
here is a solution that might work: (fiddle: http://jsfiddle.net/maniator/9sb2a/)
var last_scroll = -1;
$(window).scroll(function(e){
if($('#content').scrollTop());
var scroll = $('#view').data('scroll');
if(scroll == undefined){
$('#content').data('scroll', 5);
scroll = $('#content').data('scroll');
}
else {
$('#content').data('scroll', scroll + 5);
scroll = $('#view').data('scroll');
}
/*
console.log({
'window scroll':$('window').scrollTop(),
'scroll var': scroll,
'view scroll':$('#view').scrollTop(),
'view height':$('#view').height(),
'ls': last_scroll
});
//*/
if(last_scroll != $('#content').scrollTop()){ //check for new scroll
last_scroll = $('#content').scrollTop()
$('#content').scrollTop($('#content').scrollTop() + scroll);
$(this).scrollTop(0);
//console.log(e, 'scrolling');
}
})
It is a bit buggy but it is a start :-)
The only way I believe you can achieve this is through the use of frames.
Frames - W3Schools Reference
If you just want to have a fixed positioned "div" and scroll only it, maybe you could use a trick like:
http://jsfiddle.net/3cpvT/
Scrolling with mouse wheel and all kinds of keys works as expected. Only thing is that the scrollbar is on the document body only.
I found a solution... Not perfect... http://jsfiddle.net/fGjUD/6/.
CSS:
body.noscroll {
position: fixed;
overflow-y: scroll;
width: 100%;
}
JS (jQuery):
if ($("body").height() > $(window).height()) {
var top;
$('#scrolldiv').mouseenter(function() {
top = $(window).scrollTop();
$('body').addClass('noscroll').css({top: -top + 'px'});
}).mouseleave(function() {
$('body').removeClass('noscroll');
$(window).scrollTop(top);
});
}
The text wrapping problem can be solved putting the whole content in fixed-width div. There is another bug for IE browser. If the page has center-aligned backgrond, it will move left-right on mouseenter on #scrolldiv

Categories