I have a modalbox for for mobile site(ios device), which contains scrollable content inside it. The initial issue was that on scrolling the content inside the modal, even the background page was scrollable. To fix this, I added a 'position: fixed' property to the body tag when the modalbox is opened, and removing it when the modalbox is closed.
Though this fixes the initial scroll issue, it causes the page to scroll to top on adding the "fixed property:" to the body tag and and the page scrolls to the initial position once the modalbox is closed.
Wanted a solution to avoid the page being scrolled to top if fixed property is added to the body.
One way to do this would be monitor touch and wheel events and call preventDefault on them when you know they are going to scroll wrong element. Here's main idea:
element.addEventListener('touchstart', onTouchStart);
element.addEventListener('touchmove', onTouchMove, { passive: false });
element.addEventListener('wheel', onWheel, { passive: false });
onWheel(event) {
// Walk up the DOM tree from target element until the
// topmost element you want to isolate scroll with
// i.e. your modal and check if any of the elements
// can be scrolled in the wheel direction (event.deltaY).
// If there are no such elements, call event.preventDefault().
}
onTouchStart(event) {
// Store initial touch coordinates to determine direction later
}
onTouchMove(event) {
// Using initial touch coordinates determine direction of the move
// and do the similar thing as with the wheel event — call
// event.preventDefault() if you know that resulting scroll will happen
// outside of your modal
}
Related
Hi all I'm working on a slider, and I would that my slide detect when the horizontal scroll reaches for example 1000px from left, hence I could trigger some dynamic event - animation, CSS style, etc.
Some here know how to listen on a specific position from left?
I have tried the while loop but the stack had just overflowed,
so any hint would be great,
thanks
If you want to detect scroll position of the whole page, it should be sufficient to attach an event handler to scroll event of window element, and inside check for the value of window.pageXOffset. I have made a small demo in this codepen. The html markup and css is just for example purposes (to have enoght content so that the whole page overflows in horizontal direction), so the important code is in js:
var scrollhandler = function(){
if(window.pageXOffset > 1000){
alert("over 1000");
window.removeEventListener("scroll",scrollhandler)
}
}
window.addEventListener("scroll", scrollhandler);
I am trying to create a list of items that can be re-sorted. I have set it up on mobile where the item is to begin being moved after a long-hold, followed by a drag to re-position it.
It works fine when only a few items are present, but once enough appear to allow the div to scroll (only the div containing the ul scrolls, not the whole page), I can no longer re-position items as dragging causes a scroll.
I have tried using .preventDefault() on touchmove, but it does not appear to have an effect.
Basically, I have this:
$(document).on('touchmove mousemove', e => {
// check to make sure we're holding something
// if not, just return
e.preventDefault()
// this stops the text from being highlighted,
// but does not stop scrolling
// report the mouse/touch position to the actual move function.
})
Most solutions say that using preventDefault() stops it, but that does not appear to be the case.
What can I do here?
Edit: I have tried manipulating the overflow property, but that prevents the div from being programmatically scrolled as well, which it needs to do.
try to prevent scroll:
$('div').on('scroll', function(e) {e.preventDefault()});
I am working on a function where I have to hide the sticky footer once it reach an element -> #line-before-related-article.
When I use $(document) the sticky footer disappears when I start scrolling down, which is not what I want.
When I use $(window) the sticky footer disappears before of reaching #line-before-related-article, which is almost what I need. I want the sticky footer disappearing ONLY when it reaches the div with the id #line-before-related-article
$(window).scroll(function() {
if ($(this).scrollTop() + $(this).height() >= $('#line-before-related-article').position().top) {
console.log(console.log($('#line-before-related-article').position().top))
$('.sticky-footer').hide();
}
});
I think my issue will be fix once my function works using $(document) properly.
Any suggestions?
The window object carries the scroll property and fires the corresponding event about the browser. As you see on its name, the document object refers to the DOM elements from the top to the bottom.
scrolling the content in the browser does not fire an event on a DOM object!
you have to enable the scrolling feature by playing with CSS
here is the explanation from jquery website:
https://api.jquery.com/scroll/
The scroll event is sent to an element when the user scrolls to a different place in the element. It applies to window objects, but also to scrollable frames and elements with the overflow CSS property set to scroll (or auto when the element's explicit height or width is less than the height or width of its contents).
when your element does not have scrolling feature, it will not carry the scroll event capability.
you have to take care of the CSS code to enable the scroll event.
I have an weird issue in IE8. I have a bunch of div's in an area. Each div has the same structure. Here is the basic structure.
<div class="brandImage">
<div style="display:none;">
<a><img/></a>
<div><span>See More</span></div>
</div>
</div>
Each brandImage div has an on hover listener which will give the inner div a display:block reveling the image and allowing the user to click through.
All these "tiles" are contained in a div with a set height and is scroll-able using the jquery.mCustomScrollbar plugin.
It works with all the tiles above the fold, however, when a you start to scroll down below the fold, if you click on one of the tiles, on mousedown will cause the container to scroll up. If the container does not have to scroll very far or you release the mouse button fast enough to complete the click it will work.
My question is what could be causing the scroll up on the mousedown event?
The plugin defaulted to scroll on focus. The function that was called on focusin. This was scrolling the container. Here is the code from the plugin.
/*scrolling on element focus (e.g. via TAB key)*/
if($this.data("autoScrollOnFocus")){
if(!$this.data("bindEvent_focusin")){
mCustomScrollBox.bind("focusin",function(){
mCustomScrollBox.scrollTop(0).scrollLeft(0);
var focusedElem=$(document.activeElement);
if(focusedElem.is("input,textarea,select,button,a[tabindex],area,object")){
var mCSB_containerPos=mCSB_container.position().top,
focusedElemPos=focusedElem.position().top,
visibleLimit=mCustomScrollBox.height()-focusedElem.outerHeight();
if($this.data("horizontalScroll")){
mCSB_containerPos=mCSB_container.position().left;
focusedElemPos=focusedElem.position().left;
visibleLimit=mCustomScrollBox.width()-focusedElem.outerWidth();
}
if(mCSB_containerPos+focusedElemPos<0 || mCSB_containerPos+focusedElemPos>visibleLimit){
$this.mCustomScrollbar("scrollTo",focusedElemPos,{trigger:"internal"});
}
}
});
$this.data({"bindEvent_focusin":true});
}
}
When I initialize the plugin, I set autoScrollOnFocus to false and there was no issue.
Basically, I would like to do some pre-processing before the DOM elements are scrolled. The problem is that the scroll event is fired AFTER the DOM elements are scrolled. I know that when you use the mousewheel to scroll, the mousewheel scroll event gets fired before DOM elements are scrolled although it does not provide you with the anticipated scroll position and it is only one type of scroll. I am wondering if there is any event that gets fired for every scroll method(eg. mousewheel, dragging the scroll bar, pushing the down arrow etc.) BEFORE the DOM elements are scrolled. It does not have to be an event. I am not trying to scroll to a certain position so scrollTo would not be applicable.
The chain of event with on scroll:
User scrolls -> DOM elements physically scroll -> fires onScroll event -> handle stuff
The desired chain of event:
User scrolls -> some event is captured and do what I want to do -> DOM elements physically scroll -> fires onScroll event -> handle stuff
Heres something you might want to try.
Give your page overflow:hidden so that no scroll bars appear, then place an absolutely positioned div with the correct width & height over the content. When this div is scrolled, you can then update any underlying content before re-triggering the event.
You would need to pass through clicks etc as well, so this is really a hack. Something like jQuery would help with the triggering of the events and measuring the height of the content.
EDIT: css pointer-events:none may help here depending on the browser. See https://developer.mozilla.org/en/css/pointer-events
The best you can do is when onScroll fires, if scrollTop > thingToStick's distance from the top, then set position: fixed on thingToStick otherwise, set position to whatever it was originally. It'll flicker when changing from not-sticking to sticking, but besides that, you won't get any flickering.
in sudo-ish code:
onScroll = function()
{
if(scrollTop > thingToStick.y)
thingToStick.position = "fixed";
else
thingToStick.position = "relative";
}
In browsers that don't support fixed positioning, you're stuck with the flicker...
Never tryed this before, but to break the chain of event it would be possible to :
Capture the scroll event
Do your stuff
Use preventDefault() and stopPropagation to inhibit the event
Fake a new scroll event using the original one (this should be feasible I think)
Hope this will help.