I'm building a website, in an attempt to save space on the mobile version I want to let users swipe horizontally through a few sections that contain multiple div's, like on the Facebook app. However, the content that needs swiping is within a div.
Frameworks like jQuery Mobile and JQTouch don't seem applicable because they're designed to be used as a framework.
I've tried using SwipeView, JQSwipe, as well as the jQuery mobile and jQTouch frameworks.
So, does anyone know of any stand-alone JS or jQ plugin that gives swipe functionality to div's? One's I've found so far either seem not to work or need the content organised in a different way to what I have.
Ideally, the HTML will look something like:
<div class="swipe-wrapper">
<div class="swipe-element">content</div>
<div class="swipe-element">contnet</div>
<div class="swipe-element">content</div>
</div>
Very similar to how many sliders work I'd imagine.
Look at adding 3 events listeners to your DIV to create your own swipe effect.
ontouchstart, ontouchmove, ontouchend
Then call these function for each event above respectively....
var startTime,startPoint,endPoint
function moveStart(e){
startTime = (new Date()).getTime()
startPoint = e.originalEvent.pageX
}
function moving(e){
endPoint = e.originalEvent.pageX
}
function moveEnd(e){
var d = (new Date()).getTime()
var secs = (d-startTime)/100
var delta = startPoint-endPoint
// if swipe takes longer than .2 of second and less than .6 of a second
if(secs> 2 && secs <6){
if(delta>30){ // swipe over at least 30px distance
//animate the div to move right
}else if(delta<-30){
//animate the div to move left
}
}
}
Related
I have a site here:
www.completefaq.com
The main page contains a slider, which I built on my own. It changes the slides automatically after 8 secs. and on a click on forward or backward button. But, the problem is that I want it to scroll even when one tries to just slide it on a touchscreen.
Any help is appreciated. I can only use CSS, JavaScript, HTML and PHP, because other APIs such as JQuery, tend to slowdown the website.
Since you don't want a jQuery plugin, it's going to be non trivial due to the differences between the various touch platforms, and in the end you would probably end up in reinventing the wheel trying to get the abstraction you need. Above all, your effort will clearly depend on the level of accuracy you want to achieve, so it's advisable that you don't try to make the images respond to every minimal touch event.
I believe your best bet is to use Tocca.js, a very promising, standalone script which is "super lightweight" (only 1kB) and aims to normalize touch events among existing devices.
Hammer.js is more accurate, but could be a bit heavier in your case.
QuoJS is also good but it's not focused only on touch events.
You may find this and this SO question interesting. Finally, you can always take inspiration from the several existing touch-enabled javascript image sliders.
Here is a very lightweight script to start with.
Put this script somewhere below your div#featured, or execute it on dom ready.
You may want ajust the minimum swipe time (200ms) and minimum swipe distance (50px):
var featured = document.getElementById("featured");
if( "ontouchstart" in window ) {
var touchStart = function(evt) {
var startTime = (new Date()).getTime();
var startX = evt.changedTouches[0].pageX;
var touchEnd = function(evt) {
document.removeEventListener("touchend", touchEnd);
var diffX = evt.changedTouches[0].pageX - startX;
var elapsed = (new Date()).getTime() - startTime;
console.log( "Swiped " + diffX + " pixels in " + elapsed + " milliseconds" );
if( elapsed < 200 && Math.abs(diffX) > 50 ) {
( diffX < 0 ) ? slideright() : slideleft();
}
}
document.addEventListener("touchend", touchEnd);
};
featured.addEventListener("touchstart", touchStart);
}
I understand that you want to keep your website light, but if you wan't more advanced gesture recognition that this simple swipe, you will have to go with some kind of framework.
I'm using the fullpage.js plugin for a single page marketing site.
I'm using navigation links to jump to scenes (all horizontal) around the site so I want to disable to the touch/swipe (between scenes) feature as it interferes with other touch elements.
I've been though all the documentation but I can't find out how to achieve this.
Any help is welcome. Thanks, Jack.
Just use the option autoScrolling:false when initializing the plugin. This way the mouse wheel won't swipe and neither the touch events will.
If you want to keep the mouse wheel scrolling (for computers) but disable the touch events (touch devices), then I would recommend you to initialize the plugin in a different way for touch devices.
In order to do so, I recommend you to do something like this.
Update 2016:
You can use the options responsiveWidth or responsiveHeight as well as the class fp-auto-height-responsive.
The options will disable the autoScrolling feature for mobile devices under the specified dimensions. Examples available in the examples folder of fullPage.js or online.
You can also use responsiveSlides and force the transformation of horizontal slides into vertical sections on responsive. This can be done through the Responsive Slides extension.
Update Sep-2014:
A method named $.fn.fullpage.setAllowScrolling can also be used with this same purpose. It will disable both the touch scrolling and the mouse scrolling.
Update Jun-2014:
autoScrolling:false only disables the vertical scrolling.
If you want also to disable the horizontal one, there's no way to do it right now. You would need to modify a bit the plugin.
Inside fullpage.js replaces this:
function removeTouchHandler() {
if (isTablet) {
$(document).off('touchstart MSPointerDown');
$(document).off('touchmove MSPointerMove');
}
}
For this:
$.fn.fullpage.removeTouchHandler = function (){
if (isTablet) {
$(document).off('touchstart MSPointerDown');
$(document).off('touchmove MSPointerMove');
}
};
And then, when you initialize the plugin, call that public function in the afterRender callback like so:
$(document).ready(function() {
$('#fullpage').fullpage({
afterRender: function(){
$.fn.fullpage.removeTouchHandler();
}
});
});
Don't call fullpage twice. Just add the afterRender function inside your initialization.
The setAllowScrolling function also accepts a second argument for directions so the following can be used to disable left/right scrolling/swiping:
$.fn.fullpage.setAllowScrolling(false, 'left, right');
As of June 2017, none of the previous methods worked for me. The simplest way I found to effectively disable touch is as follows.
In jquery.fullPage.js you will find the function setAllowScrolling
function setAllowScrolling(value, directions){
if(typeof directions !== 'undefined'){
directions = directions.replace(/ /g,'').split(',');
$.each(directions, function (index, direction){
setIsScrollAllowed(value, direction, 'm');
});
}
else if(value){
setMouseWheelScrolling(true);
addTouchHandler();
}else{
setMouseWheelScrolling(false);
removeTouchHandler();
}
}
When fullpage is initialized it automatically calls setAllowScrolling(true), triggering the else if(value) condition above. Simply comment out the call to addTouchHandler() to fully disable it, or add some sort of condition for it to be called, eg
var winw = $(window).width();
if (winw > 480){
addTouchHandler();
}
With this method the left and right arrows still work when tapped, so horizontal slides can still be navigated. It should be noted that using $.fn.fullpage.setAllowScrolling(false, 'left, right'); will also disable the arrows.
This question is more of an advice research, I do hope that it will be helpful for others and it won't closed, as I'm not quite sure where to ask for advice on this matter.
I've been developing for mobile for the past 6 months and I had the occasion to deal with all kinds of situations and bugs on various devices.
The most troubling was the scrolling issue, when it comes to scrolling in multiple areas of the website. On three projects that I have been working on I've been building a navigation that behaves the same way that the native iOS Facebook app has, or the Google website on mobile, etc. And for each one I came up with different solutions.
But a few days ago I have just released a new JavaScript library, drawerjs, that can be used to generate such navigation (so called off canvas concept). The difference between the other libs and this one is that is library agnostic, and it acts on touch behavior (the same way that the Facebook app behaves) not just open / close on click.
One of the things that I have left to implement is a solution for scrolling inside the menu and the navigation without affecting one another (most of the time when you scroll in such way, the content tends to scroll together with you menu or after you have reached the end of the menu scrolling).
I have two solutions in mind:
One approach would be to use the same principle I'm using for dragging the content and showing the navigation, on touchmove I prevent the default scrolling on document / content and I start translating the contents with the same amount you scroll. And with the same resistant behavior as a touch slider would have (when you exceed the boundaries and let go, the contents would translate back so it doesn't exceed the boundary anymore, or on swipe with the same behavior).
A second approach would be using the native overflow-scrolling that iOS has and would offer the same feel as described in the first approach. The downside of this would be that only iOS devices would have the nice resistant feature, but it would be, supposedly, less of a hassle the the first approach.
So I'm not quite sure which approach I should take, or if there any better solutions for that. I'm also trying to keep in mind that some users would like to hide the url bar, so scrolling on the body / html would have to be kept (on the y axis).
You could do touchmove . But as far as I understand, you want something like this?
http://jsfiddle.net/2DwyH/
using
var menu = $('#menu')
menu.on('mousewheel', function(e, d) {
if((this.scrollTop === (menu[0].scrollHeight - menu.height()) && d < 0) || (this.scrollTop === 0 && d > 0)) {
e.preventDefault();
}
});
Using this plugin from Brandon Aaron - github : https://github.com/brandonaaron/jquery-mousewheel
And it should work with Android: What DOM events are available to WebKit on Android?
Some more info here: Prevent scrolling of parent element?
Also without using the plugin above , using only jQuery you could do this like it says on the link above - answer from Troy Alford
$('.Scrollable').on('DOMMouseScroll mousewheel', function(ev) {
var $this = $(this),
scrollTop = this.scrollTop,
scrollHeight = this.scrollHeight,
height = $this.height(),
delta = (ev.type == 'DOMMouseScroll' ?
ev.originalEvent.detail * -40 :
ev.originalEvent.wheelDelta),
up = delta > 0;
var prevent = function() {
ev.stopPropagation();
ev.preventDefault();
ev.returnValue = false;
return false;
}
if (!up && -delta > scrollHeight - height - scrollTop) {
// Scrolling down, but this will take us past the bottom.
$this.scrollTop(scrollHeight);
return prevent();
} else if (up && delta > scrollTop) {
// Scrolling up, but this will take us past the top.
$this.scrollTop(0);
return prevent();
}
});
The JS Fiddle he mentions: http://jsfiddle.net/TroyAlford/4wrxq/1/
Why not just provide a fixed height to your widget (min and max will also do). Then define like these -
height: x px;
overflow-y: auto;
This way till the focus is inside the widget, it'll only overflow the widget, once outside the page will scroll without affecting widget content at all.
I have a website page and I've added to the body of the page touch events.
More exactly for swipe right and swipe left. Since the event listener is added to the body of the page and I have added event.preventDefault(); i can't scroll the page any more.
How can i scroll the page in the browser ?
P.S. The code is pure javascript / library agnostic.
Edit #1. This site viewed in mobile seems to do it http://swipejs.com/ . It slides the tabs right to left and back as well as scroll the website. I just can't seen in the code how :(
Use iscroll plugin. it's help to you.
see example : http://cubiq.org/dropbox/iscroll4/examples/simple/
Unfortunately there is no easy answer. The best way is to build smart gesture recognizers. Or use something like this (for Safari Mobile):
http://mud.mitplw.com/JSGestureRecognizer/#single-gesture
You will notice that when you are touching a gesture recognizer, there is no scrolling. However, you could make the callback of a recognizer scroll the page.
Wondering why it only says it supports Safari mobile? That's because Safari mobile has its own set of touch events. However, you can use it as a start and try to add support for other platforms.
I have the same problem that swiping without "preventDefault()". Because I want to achieve a pulltorefresh's effect, I can only prevent the pulldown event but not pullup. The code like this:
function touchBindMove(evt){
//evt.preventDefault();
try{
var deviceHeight = window.innerHeight;
var touch = evt.touches[0]; //获取第一个触点
var x = Number(touch.pageX); //页面触点X坐标
var y = Number(touch.pageY); //页面触点Y坐标
//记录触点初始位置
if((y - offsetStart) > 0 && document.body.scrollTop == 0){
evt.preventDefault();
var page = document.getElementsByClassName('tweet-page')[0];
var rate = 0;
end = x;
offsetEnd = y;
rate = (offsetEnd - offsetStart) / (2 * deviceHeight);
//tool.print(rate);
easing.pullMotion(page, rate);
}
}catch(e){
alert(e.message);
}
}
"y - offsetStart" judges whether the event is pulldown and "document.body.scrollTop == 0" judges the scrollbar is in the middle or not.
Maybe it can help you a little bit.
I want to provide the user with the experience of scrolling through content, but I would like to load the content dynamically so the content in their viewing area is what they would expect, but there is no data above or below what they are looking at. For performance reasons, I don't want that data loaded. So when they scroll down new data gets loaded into their view, and data previously in their view is discarded. Likewise when scrolling up. The scroll bar should represent their location within the entire content though, so using "infinite scrolling" or "lazy loading" does not look like what I need.
My solution may be that I need to re-architect things. As of now, my project is a hex-viewer that allows you to drop a binary file onto it. I create html elements for every byte. This causes performance issues when you end up with a 1MB file (1,000,000+ DOM elements). One solution would be to not use DOM elements/byte but I think this will make other features harder, so I'd like to just not display as many DOM elements at once.
Make a div, set overflow to scroll or auto. As user scrolls you can change the content of the div.
You could look at yahoo mail (the JavaScript based one) to see how they do it (they add rows with email as you scroll).
You don't necessarily need custom scroll bars.
You could look for some code here for custom scroll bars:
http://www.java2s.com/Code/JavaScript/GUI-Components/Scrolltextwithcustomscollbar.htm
or here:
http://www.dyn-web.com/code/scroll/
I'm looking for an answer to this question as well so I'll share where I'm at with it.
I have a large amount of content I want to display vertically and have the user scroll through it. I can load it all into the DOM and scroll normally but that initial creation phase is horribly slow and scrolling can awfully slow also. Also, I will dynamically add to it as I stream more data in.
So I want the same thing which is to be able to dynamically populate and update a non-scrolling area with content. I want to make it seem as if the user is scrolling through that content and have a model (which has lots of data) that is kept off the DOM until it would be seen.
I figure I'll use a queue concept for managing the visible DOM elements. I'd store queueHeadIndex and queueTailIndex to remember what off-DOM elements are shown in the DOM. When the user scrolls down, I'd work out what whether the head of queue falls off the screen and if it does update queueHeadIndex and remove it's DOM element. Secondly I'd then work out whether I need to update queueTailIndex and add a new element to the DOM. For the elements currently in the DOM I'd need to move them (not sure if they need animation here or not yet).
UPDATE:
I've found this which seems to have some promise http://jsfiddle.net/GdsEa/
My current thinking is that there are two parts to the problem.
Firstly, I think I want to disable scrolling and have some sort of virtual scrolling. I've just started looking at http://www.everyday3d.com/blog/index.php/2014/08/18/smooth-scrolling-with-virtualscroll/ for this. This would capture all the events and enable me to programmatically adjust what's currently visible etc. but the browser wouldn't actually be scrolling anything. This seems to provide mouse wheel driven scrolling.
Secondly, I think I need to display a scroll bar. I've had a look at http://codepen.io/chriscoyier/pen/gzBsA and I'm searching around more for something that looks more native. I just want it to visually display where the scroll is and allow the user to adjust the scroll position by dragging the scroller.
Stackoverflow is insisting I paste code so here is some code from that codepen link above
var elem = document.getElementById('scroll-area'),
track = elem.children[1],
thumb = track.children[0],
height = parseInt(elem.offsetHeight, 10),
cntHeight = parseInt(elem.children[0].offsetHeight, 10),
trcHeight = parseInt(track.offsetHeight, 10),
distance = cntHeight - height,
mean = 50, // For multiplier (go faster or slower)
current = 0;
elem.children[0].style.top = current + "px";
thumb.style.height = Math.round(trcHeight * height / cntHeight) + 'px';
var doScroll = function (e) {
// cross-browser wheel delta
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
// (1 = scroll-up, -1 = scroll-down)
if ((delta == -1 && current * mean >= -distance) || (delta == 1 && current * mean < 0)) {
current = current + delta;
}
// Move element up or down by updating the `top` value
elem.children[0].style.top = (current * mean) + 'px';
thumb.style.top = 0 - Math.round(trcHeight * (current * mean) / cntHeight) + 'px';
e.preventDefault();
};
if (elem.addEventListener) {
elem.addEventListener("mousewheel", doScroll, false);
elem.addEventListener("DOMMouseScroll", doScroll, false);
} else {
elem.attachEvent("onmousewheel", doScroll);
}
I imagine I'll have one class that listens to scroll events by either the virtual scroll method or the ui and then updates the ui scroller and the ui of the content I'm managing.
Anyway, I'll update this if I find anything more useful.
I think avoiding using DOM elements/byte is going to be the easier solution for me than creating a fake scrolling experience.
UPDATE: I ultimately solved this as explained here: Javascript "infinite" scrolling for finite content?
You're taking about using some serious javascript, specifically AJAX and JSON type elements. There is no easy answer to your questions. You'd need to do a lot of R&D on the subject.