Disable rubber band in iOS full screen web app - javascript

I have a full screen web app running on iOS. When I swipe down, the screen scrolls with the rubber band effect (bumping). I want to lock the whole document but still allow scrolling divs with overflow-y: scroll where needed.
I have experimented with
document.ontouchmove = function(e){
e.preventDefault();
}
but this disables scrolling in any container. Any idea? Thank you very much.

Calling preventDefault on the event is actually correct, but you don't want to do it for every component since this will also prevent scrolling in divs (as you mention) and sliding on range inputs for instance. So you'll need to add a check in the ontouchmove handler to see if you are touching on a component that is allowed to scroll.
I have an implementation that uses detection of a CSS class. The components that I want to allow touch moves on simply have the class assigned.
document.ontouchmove = function (event) {
var isTouchMoveAllowed = false;
var p = event.target;
while (p != null) {
if (p.classList && p.classList.contains("touchMoveAllowed")) {
isTouchMoveAllowed = true;
break;
}
p = p.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
});

Related

How to create forced scrolling to anchors on a website on scroll

I have a site where I have each section as 100vh so it fills the height of the screen perfectly. The next step I wanted to implement was disabling the regular scrolling, and on scroll force the screen to jump smoothly to the top of the next 100vh section. Here is the example of this animation / feature:
https://www.quay.com.au/
I was having a hard time finding any answers for this as most things just deal with smooth scrolling when clicking on anchors, not actually forcing div relocation when the user scrolls up / down.
I just wanted to know what code I would need do this...
Thanks, been using stack overflow for a while but first post, let me know if there is anything I can do to make this more clear.
disclaimer: this solution needs some testing and probably a bit of improvements, but works for me
if you don't want to use a plugin and prefer a vanilla JavaScript solution I hacked together a small example how this can be achieved with JS features in the following codepen:
https://codepen.io/lehnerchristian/pen/QYPBbX
but the main part is:
function(e) {
console.log(e);
const delta = e.deltaY;
// check which direction we should scroll
if (delta > 0 && currentlyVisible.nextElementSibling) {
// scroll downwards
currentlyVisible = currentlyVisible.nextElementSibling;
} else if (delta < 0 && currentlyVisible.previousElementSibling) {
// scroll upwards
currentlyVisible = currentlyVisible.previousElementSibling;
} else {
return false;
}
// perform scroll
currentlyVisible.scrollIntoView({ behavior: 'smooth' });
e.preventDefault();
e.stopPropagation();
}
what it does is that it listens for the wheel event and then calls the callback, which intercepts the scroll event. inside the callback the direction is determined and then Element.scrollIntoView() is called to let the browser do the actual scrolling
check https://caniuse.com/#search=scrollintoview for browser support, if you're going for this solution

Z-index on Polymer hero transition

I am trying to make a slideshow transition to full screen as shown here: http://alexfuhr.me/polymer-talk/ (the trigger for this is clicking the button at the top right)
The transition to a full screen works fine, but the transition back to the inline view causes the fullscreen slideshow to suddenly fall underneath the scaffolding. I have tried to change z-index to high numbers to rectify this, but nothing seems to work. Does anyone know how to fix this transition? The main code is here: https://github.com/afuhrtrumpet/afuhrtrumpet.github.io/blob/master/polymer-talk/index.html
Instead of mucking around with z-index to overlay elements on top of each other, the following approach might offer a better solution.
The idea is to hide the drawer of the core-drawer-panel (inside the core-scaffold) by setting the narrow attribute to true before the forward animation starts, and then restore the value before the back animation starts.
Also, this issue only happens when the drawer is visible on the screen. So we only need to subscribe to the core-animated-pages-transition-prepare event when the page is not in narrow mode.
Something like the following should work. Personally I prefer this 'cause it also animates the in/out of the drawer panel smoothly, indicating that the fullscreen-list takes up the full screen space.
<script>
var isBackAnimation = false;
var pages = document.querySelector("#mainPages");
var fab = document.querySelector("#fullscreen-button");
var switchPages = function () {
isBackAnimation = pages.selected == 0;
pages.selected = pages.selected == 0 ? 1 : 0;
fab.icon = pages.selected == 1 ? "unfold-less" : "unfold-more";
}
window.addEventListener('polymer-ready', function () {
// locate the core-drawer-panel inside the core-scaffold
var drawerPanel = document.querySelector('core-scaffold::shadow #drawerPanel');
// on loaded, listen to this event only when it's not in narrow mode
if (!drawerPanel.narrow) {
pages.addEventListener('core-animated-pages-transition-prepare', beforeAnimation);
}
drawerPanel.addEventListener('core-responsive-change', function (event) {
// in narrow mode, the animations work fine, so we remove the handlers
if (event.detail.narrow) {
pages.removeEventListener('core-animated-pages-transition-prepare', beforeAnimation);
}
// otherwise we add the handlers
else {
pages.addEventListener('core-animated-pages-transition-prepare', beforeAnimation);
// when the page was initially in narrow mode and then got resized up, we
// need to manually reset the narrow attribute at the end of the animation
if (isBackAnimation) {
pages.addEventListener('core-animated-pages-transition-end', afterAnimation);
}
}
});
function beforeAnimation() {
drawerPanel.narrow = !drawerPanel.narrow;
}
function afterAnimation() {
drawerPanel.narrow = !drawerPanel.narrow;
// this is a once off thing, so unsubscribe it here
pages.removeEventListener('core-animated-pages-transition-end', afterAnimation);
}
});
</script>

Links being activated when scrolling on touch screen

I'm building a scrollable navigation panel for a project, and I'm having some issues optimising it for touch screens. I'm using this piece of script in order to use a touch event where necessary:
var getUserInputMethod = function() {
//same issues using touchend too
clickEvent = (Modernizr.touch) ? 'touchstart':'click';
return clickEvent;
}
$('#navigation li').on(clickEvent, function() {
$('#mainContent').load($(this).data('link'));
});
However, I can't seem to scroll without selecting a link. Is there a way I can determine between a click/tap and a scroll?

disable mousedown bind event on scrollbar

on the http://www.associationtsunami.org/ site if i make a mousedown on the document the cube rotates depending on the direction the user moves the mouse.
the code is:
key code ...
).bind('mousedown touchstart', function (evt) {
delete mouse.last;
if ($(evt.target).is('a, iframe')) {
return true;
}
evt.originalEvent.touches ? evt = evt.originalEvent.touches[0] : null;
mouse.start.x = evt.pageX;
mouse.start.y = evt.pageY;
$(document).bind('mousemove touchmove', function (event) {
dragging = 1;
// Only perform rotation if one touch or mouse (e.g. still scale with pinch and zoom)
if (!touch || !(event.originalEvent && event.originalEvent.touches.length > 1)) {
event.preventDefault();
// Get touch co-ords
event.originalEvent.touches ? event = event.originalEvent.touches[0] : null;
$('.viewport').trigger('move-viewport', { x: event.pageX, y: event.pageY });
}
});
$(document).bind('mouseup touchend', function () {
dragging = 0;
$(document).unbind('mousemove touchmove');
});
});
full code https://github.com/AssociationTsunami/tsunami/blob/gh-pages/js/cube.js#L72
i would like to disable this event if a user makes the mousedown on a scrollbar - for example on the 'ONSONPARLA' page there is a TAB with ACCORDIONS, if you open any of the accordion content you get a scrollbar on the edge or within the accordion and if you try to move the scrollbar, this also moves the cube.
what is the correct way to overwrite this in the cube.js so that the cube does not turn if the event is on a scrollbar element?
It can't be done in such manner.
But there is an alternative solution. Use some custom scroll bar plugin to replace classic scroll bar. You will be able to prevent events on him. I understand this is not an excellent solution, but according to you web page you like to take a chance. :)
Here you can find few good plugins.
Good plugin example is here.

prevent window for scrolling after div box scrolling

I have a small div box that has a vertical scroll bar and sits within an html page that also has a vertical scroll bar.
My problem is when the user reaches the end of the small DIV box scrolling, the ENTIRE html page that contains the div box then begins to scroll (assuming the user is scrolling via the mouse scroll and NOT by actually clicking the DIV box scroll buttons themselves)
is there a way to prevent the entire html page from scrolling once a user reaches in end of my small DIV box scroll? Any help would be much appreciated! Thank you!
I have tried this (but it cancels scrolling for even the div box):
if (window.addEventListener)
/** DOMMouseScroll is for mozilla. */
window.addEventListener('DOMMouseScroll', handleWheelEvent, false);
/** IE/Opera. */
window.onmousewheel = document.onmousewheel = handleWheelEvent;
function handleWheelEvent(e){
e.preventDefault();
}
I didn't look too much into your code and the problem, but I wanted to throw out a suggestion before I move on :P.
window.addEventListener
and
document.onmousewheel = handleWheelEvent;
are normally good ways to apply what you want to do the ENTIRE document, whereas if you want to apply a specific value (in this case scroll = false) to a specific element, then you need to set the reference to that specific reference (i.e. getElementById() and then it applies only to the element of the document).
Idk - maybe that helps, maybe it doesn't :P good luck.
-J
You would need to modify the handleWheelEvent function and check the srcElement property of the e event and call preventDefault() when it's not scrolling the DIV box. Here's a link with some code examples:
http://www.webdeveloper.com/forum/archive/index.php/t-158824.html
I had a similar problem. Google led me here. Over 1700 views, in 4 years, of an incomplete answer. I figured once I had coded a solution, I'd pop it in a JSFiddle and share it. Better late than never.
Tested on MacOSX / Chrome.
http://jsfiddle.net/mF8Pr/
My problem involved being able to scroll inside a textarea, within a lightbox, and disabling scrolling on the rest of the page beneath the overlay.
bind mouse wheel event to document
when event fires (optional: test to make sure overlay is visible)
check target is obj we want to have scrolling enabled
make sure 0 < obj.scrollTop < (obj.scrollHeight - obj.clientHeight)
check direction of attempted scroll event.originalEvent.deltaY
UP == negative
DOWN == positive
event.preventDefault()
$(document).bind('mousewheel', function(e){
//if($overlay.is(':visible'))
{
if(e.target != null && e.target.type != 'textarea')
{
e.preventDefault();
}
else
{
if(e.originalEvent.deltaY < 0 && e.target.scrollTop == 0)
{
e.preventDefault(); // already at top
}
else if(e.originalEvent.deltaY > 0 && e.target.scrollTop >=
(e.target.scrollHeight - e.target.clientHeight))
{
// must use greater than because sometimes
// the math is wrong by 1px
e.preventDefault(); // already at bottom
}
}
}
});
-Amanda

Categories