Disable body scrolling on element - javascript

I created a floating sticky bootstrap panel at the bottom right of the screen. It look like a chat support like intercom. When I'm scrolling on the panel the body will scroll too. And it's really weird when I'm scrolling on mobile because I display the panel in full screen and we can scroll on the body while the panel is in fullscreen.
So I put pieces of code in my JS to enable / disable the body scrollbar :
if (...) {
$('body').css('overflow', 'hidden');
} else {
$('body').css('overflow', 'scroll');
}
...
It works and it's overkill I think but I don't found better. But I have another problem. If I go on my mobile the chrome address bar will be hide when I scroll on the full screen panel and it's really ugly because the panel will be redrawed every time.
Do you know a better way to disable body scrolling when the cursor is on certain element (a magic css property ?) and disable auto hiding address bar of browsers ?
If you go on intercom with your mobile it's exactly what I want.

if you need to totally enable or disable scroll you must use this way:
if (...) {
$('html, body').css({ overflow: 'hidden', height: '100%' }); // to hide
} else {
$('html, body').css({ overflow: 'auto (or) scroll', height: 'auto' }); // to show
}
you must include html as just only body is not enough. Hope it helps.

Related

When I hide a div it pushes the div below it up

I am trying to make a scroll down animation where the user clicks a button is scrolls down to a div and deletes the two divs above it. However, my problem is that the animation works fine on chrome but on firefox and safari the button actually make you scroll past the beginning of the div.
My desired output is https://wearebarbarian.com/
My JS:
$(document).on('click', 'a[href^="#index"]', function (event) {
event.preventDefault();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top - 100
}, 1200);
$('.introsection').delay(1300).hide(0);
$('#swipe-down').delay(1300).hide(0);
$('body').css('overflowY', 'scroll');
$('#home-mobile-nav').css('position', 'fixed');
$('#home').css('margin-top', '0');
});
I think the problem is:
$('.introsection').delay(1300).hide(0);
$('#swipe-down').delay(1300).hide(0);
is there a better way to hide the divs.
the codepen to my problem is https://codepen.io/mrsalami/pen/GBRmgx
Use -webkit-, -moz- to the CSS to make the CSS specific for browser.
-webkit- is for Chrome and Safari and -moz- is for Firefox.
Only by defining specific CSS related to margin and padding, the design of the content can be maintain same through out the browser.

iPhone anchor, scrollTop, scrollTo reveals mobile button bar, but does not scroll or jump up to anchor

I'm adding a back to top button fixed to bottom of the browser window. When clicked, it scrolls to top in desktop and Android, but not iPhone. On the iPhone, the scrollTo event reveals the address bar and the bottom mobile button bar, but does not return the user to the top of the page.
EDIT: The address bar and button bar on the iPhone appears when a touch event occurs within 20-30px of the bottom of the screen. This is why this back to top button doesn't work. Moving it 40px up stops the address/button bars from appearing.
I've attempted to just place it raw:
$('#scroll-to-top-button').on('click', function() {
window.scrollTo(0,0);
});
And with a timer:
$('#scroll-to-top-button').on('click', function() {
window.setTimeout(function() {
window.scrollTo(0,0);
}, 500);
});
I tried using scrollTop, which had the same results: browser button bar and address bar appear, but no scroll.
I also tried initiating the scrollTo and at the same time setting a timeOut with another scrollTo. The timeout never fires.
I did also try scrolling html or body, or a combination of the two:
$('#scroll-to-top-button').on('click', function() {
$('html,body').animate({
scrollTop: 0,
}, 200);
});
Only html
$('#scroll-to-top-button').on('click', function() {
$('body').animate({
scrollTop: 0,
}, 200);
});
only body
$('#scroll-to-top-button').on('click', function() {
$('html').animate({
scrollTop: 0,
}, 200);
});
I've tried resetting the button to an anchor tag and trying to get it to link within the page. This doesn't work with just basic html anchor functionality:
<div id="main-body"> ... lots of content forcing scrollbars to appear ... </div>
<a id="scroll-to-top-button" class="btn btn-default" href="#main-body">Back to Top</a>
And tried preventing default and animating the link to the anchor:
$('#scroll-to-top-button').on('click', function(e) {
e.preventDefault();
$('html,body').animate({
scrollTop: 0,
}, 200);
});
Here's a link demonstrating the problem. In this link, the code is using one of my last examples down this question, where it's purely an anchor tag trying to link to top of page.
http://willanni.com/dev/iphone-scroll/
I thought maybe missing the viewport tag might be causing it, so I added the following: <meta name="viewport" content="width=device-width, initial-scale=1">. However. When I add that in, it still does not make it work.
Besides forcing the address bar and button bar to always be visible in iPhone, is there a way to get this to scroll to top of window in iPhone? (Note: iPad doesn't have this issue, though it had a different weird issue that required the timeout to fix. Different story though)
Try using jQuery animate on body and html:
$("BODY,HTML").animate({
scrollTop: 0
}, 100);
// second parameter is time so adjust it if you please
The answer is that there really is no way to do this without forcing the address/buttons bar to be always visible.
The iPhone captures any touch event within about 20-30px of the bottom of the screen, and displays the address and bottom buttons bar. No page script, button, or links are triggered or registered as touched until the bar is revealed. A position: fixed, bottom: 0; button then is not able to be activated until the second touch:
First touch reveals the bottom button bar (and address bar)
Second touch activates whatever button/script/anchor functionality is in place
Adding an event listener to the window doesn't capture a touch event in that area of the screen while the button bar is hidden. For example, in order to test I set a timeout to allow myself a bit of time to scroll down and hide the bottom bar. In all areas of the screen except the bottom, this worked:
window.addEventListener('touchstart', function() {
setTimeout(function() {
alert('touchstart');
}, 500);
});
In that bottom region, nothing.
So, in effect, to have a button attached to the bottom of the screen work on first click, you'll need to apply some hacky css to the body and html tags to force the address and button bars to always appear:
html,body {
-webkit-overflow-scrolling: touch !important;
overflow: auto !important;
height: 100% !important;
}

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

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

Why would my Javascript break on iOS?

I have this code on jsFiddle that is implemented and works just fine on desktop browsers and works, to a point, on mobile devices. http://jsfiddle.net/heufT/
What my code is doing
If the screen is larger than 960px wide (or thereabouts) a normal horizontal navigation will be displayed, however if the screen is less than 960px wide the navigation becomes apart of a button, which when clicked reveals the same links in a vertical menu instead. When you scroll the page, the header will shrink to a smaller height and if you go back to the top the header goes back to the same height as before. There is also a .load script that will ensure this all happens even when you resize your browser (mainly for use on desktop).
jQuery(document).ready(function($){
// prepend menu icon
$('nav').prepend('<div id="menu-icon"></div>');
/* toggle nav */
$("#menu-icon").on("click", function(){
$("ul#prim").slideToggle();
$(this).toggleClass("active");
});
});
// Navigation resize event on scroll
$(document).scroll(function(){
if($(window).width()>959){
$("ul#prim").addClass("adjTop");
}
if($(window).width()<958){
$("ul#prim").removeClass("adjTop");
}
if ($(this).scrollTop()>105){
// animate fixed div to small size:
$('header').stop().animate({ height: 90 },50, 'linear');
$('ul#prim.adjTop').stop().animate({ top: '50%', 'margin-top': 18 },50, 'linear');
$('ul#prim').stop().animate({ top: 62 },50, 'linear');
$("img.logo").fadeOut();
$("img.bao_logo").fadeIn(1000);
} else {
// animate fixed div to original size
$('header').stop().animate({ height: 175 },50, 'linear');
$('ul#prim.adjTop').stop().animate({ top: '50%', 'margin-top': 18 },50, 'linear');
$('ul#prim').stop().animate({ top: 105 },50, 'linear');
$("img.logo").fadeIn(1000);
$("img.bao_logo").hide();
}
});
$(window).resize(function() {
if($(window).width()>959){
$("ul#prim").addClass("adjTop");
}
if($(window).width()<958){
$("ul#prim").removeClass("adjTop");
}
// Showreel
$(window).resize(function(){
// Resize video to fix aspect ratio when window resizes
// Only do this if video is currently visible
if ($('#showreel').height()!=0){
$('#showreel').height(($('#showreel').width()/16)*9);
}
});
});
(function($){
// Custom scrollbars for work feature on homepage
$(window).load(function(){
$(".scroll-pane").mCustomScrollbar({
horizontalScroll:true,
mouseWheel: false
});
});
})(jQuery);​
The problem
The one thing I have been noticing though on iPad and iPhone especially is that the JS will work but then when you pinch/zoom Javascript completely breaks and the navigation button doesn't work nor does the shrinking/growing of my header.
I have tried disabling pinch/zoom using the meta viewport tag which obviously stops the user from zooming in to the page but even when you at least try to pinch/zoom and it doesn't do anything, i've noticed the JS still breaks and nothing works.
Has anyone got any pointers? Is there any errors in my code that would casue this? Am I missing anything?
Ok so after testing for a couple of days I ended up revisiting the meta viewport tag and added a maximum-scale attribute combined with the user scalable attribute and it cured the problem. Not sure if this is the right way to go about things as the user is prevented from pinch/zooming and therefore impacts usability but this is a short term solution none the less.
My viewport tag now looks like so:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

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