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?
Related
I have animation with ScrollMagic library and I am also using GSAP. This is description of animation on scroll in steps. Every number is one scroll:
Add class overflow-hidden to body, to disable scrolling.
Move credit-cards
Move remove some images
Start doing transform: translate(x,y) rotateZ(zdeg)
Stop scrolling and make image that was translated sticky
So this works good with mouse on mousewheel event. The question is:
What is the best way to implement touch scroll with very same effect when user comes from iOS or Andorid. (When user comes to my website from android, iPhone, iPad etc.)
I know that there is touchmove event.
var image = document.getElementById('image-phone');
if(step == 1){
//do first step
}...
//mousewheel event
window.addEventListener('mousewheel', function (e) {
//this is implemented
});
//touchnmove event
window.addEventListener('touchmove', function (e) {
//should I use this event
});
I've created a sticky navbar for a subnav, which should stick at the top of the screen when the user scrolls down. Therefore I've tried some javascript, which changes the position to 'fixed' when the top is reached. Avoiding a gap in the content when the navbar is taken out of the flow, I've also added a placeholder, which has the same height as the navbar.
On Desktop it really works and looks how it should be. But I got a "touch" issue on mobile view. When I scroll down on mobile view the navbar will not appear during the process of scrolling over the viewpoint, where the css class is changing. It only appears when I stop scrolling after that viewpoint. When it shows up I can normally scroll up and down and I am only getting this issue again if I repeat this procedure, where the navbar has to change the css class. So it might be a problem with the css class change and I guess the problem could be in the javascript snippet. Does anybody know a solution for this? I'd like to have the same behavior like on desktop view, so the navbar is always visible and just fixed to the very top of the screen, even if it is in the flow of scrolling.
JS:
var menu = document.querySelector('#irp-localnav');
var menuPosition = menu.getBoundingClientRect();
var placeholder = document.createElement('div');
placeholder.style.width = menuPosition.width + 'px';
placeholder.style.height = menuPosition.height + 'px';
var isAdded = false;
window.addEventListener('scroll', function() {
if (window.pageYOffset >= menuPosition.top && !isAdded) {
menu.classList.add('sticky');
menu.parentNode.insertBefore(placeholder, menu);
isAdded = true;
} else if (window.pageYOffset < menuPosition.top && isAdded) {
menu.classList.remove('sticky');
menu.parentNode.removeChild(placeholder);
isAdded = false;
}
});
If you guess an error in the html/css markup, just let me know, so I get in touch with you again by posting this markup
Kind Regards
I was able to hack around. For anyone, who is facing a similiar issue:
Mobile browsers simply do not fire on a scroll event, while the event is in process. They fire when the event has stopped, so, when you've stopped scrolling. Using translate3d(0px,0px,0px) can solve this. Refer to this thread to read more about it:
iOS 9 Safari: changing an element to fixed position while scrolling won't paint until scroll stops
Kind Regards!
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();
}
});
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.
I'm developing an web app. On the left side is an sidebar using the Sidr-plugin (jQuery Plugin: Sidr). The test site is on my developing server. My problem is that if I'm swipe from left-to-right the sidebar is displayed. That's very good. But if I want to close the sidebar by swiping from right-to-left I must prevent the scrolling by add this following code:
$('body').bind('touchmove', function(e){e.preventDefault()})
I did that, but now: My navigation in the top of the page (menu) doesn't work fine. I can't scroll until to the end.
So my question is: How can I change this. It should only prevent the vertical Scrolling if I'm going to close the Sidebar on the left.
Here's my complete JavaScript:
$(function(){
$(document).foundation();
$('#sidebar-toggle').sidr();
var hammertime = Hammer(document.getElementById("wrapper")).on("swiperight", function(event) {
$.sidr('open');
});
var hammertime = Hammer(document.getElementById("wrapper")).on("swipeleft", function(event) {
$.sidr('close');
});
var hammertime = Hammer(document.getElementById("content")).on("tap", function(event) {
$.sidr('close');
});
$('body').bind('touchmove', function(e){e.preventDefault()})
});
Make page not scrollable
Something like this?
I think that using $(document) would be better!
Reference: Prevent horizontal scroll on jQuery Mobile
var lastY;
$(document).bind('touchmove', function (e){
var currentY = e.touches[0].clientY;
if (currentY !== lastY){
// moved vertically
return;
}
lastY = currentY;
//insert code if you want to execute something when an horizontal touchmove is made
});
I was trying to integrate Sidr with Hammer JS but there is conflict, so I got rid of Hammer and used the code below, which uses TouchWipe JS combined with Sidr JS.
<!-- Swipe to open or close mobile menu -->
<script>
jQuery(window).touchwipe({
wipeLeft: function() {
// Close
jQuery.sidr('close', 'sidr-main');
},
wipeRight: function() {
// Open
jQuery.sidr('open', 'sidr-main');
},
preventDefaultEvents: false
});
</script>
I guess the problem you are facing with right-to-left swipe should be fixed.