Using swipe gestures for navigation in jQuery Mobile

This post is more than 2 years old.

A few weeks back I posted a simple jQuery Mobile demo that demonstrated paged search results. The idea was simple - present an input field to the user to search against a database of art and allow for paged results. Be sure to review that entry on the particulars. I thought it would be interesting to look into a cooler way of paging through the results - using swipe gestures.

Swipe gestures are simply the act of dragging your finger across the mobile device. jQuery Mobile supports listening in to both a left and right swipe event. I thought it would be cool to use a right swipe to move forward and a left swipe to go back. In theory - this should be simple. I've got navigation links already. If I listen in to my swipeleft/swiperight events I can fetch the URL and then perform the load myself. I thought it would be easy, but my first attempt failed. Let's look at what I did and then I'll explain why it failed.

$(document).ready(function() {

 $('#searchPage').live('swipeleft swiperight',function(event){
	console.log(event.type);
	if (event.type == "swipeleft") {
		var prev = $("#prevlink");
		 if (prev.length) {
			 var prevurl = $(prev).attr("href");
			 console.log(prevurl);
		 }
	 }
	 if (event.type == "swiperight") {
		 var next = $("#nextlink");
		 if (next.length) {
			 var nexturl = $(next).attr("href");
			 console.log(nexturl);
		 }
	 }
 });

});

I began by creating a listener for swipeleft and swiperight. The event details will tell me which one was called and since the logic is very similar for both it made sense to just use one handler. I'm listening in on "searhPage", which if you look at the previous entry, is the page that displayed search results. I had not included an ID on that page so I simply added it to this version:

<div id="searchPage" data-role="page" data-theme="e">

Now we branch out based on the swipe action. I use a selector to get either the previous or next link. These links were used for buttons and contain the URL we need for the relevant page to load. Now it's possible that you may try to swipe left on the first page of results. I check the length of the selector result to see if we actually have something before I try to get the URL. Finally, I log the URL to see if it works.

Here is where things got odd. I began to test this and noticed that my links were all based on the first match. What I mean is, when I would do a swipe right, I'd always get the link for page 2, no matter what page I was on. When I would swipe left, I'd first get nothing (if I was on page one), but then I'd get the link for page 1 if I was on page 2 or any other page. It's like jQuery was caching the result of the selector and not refetching it on a swipe. Then I realized my problem.

As you navigate from page to page, jQuery Mobile will make an XHR request to load the page. But - notice the previous code block had an ID of searchPage. I was - basically - loading pages into my DOM that had the same ID. If I understand things right, I was basically making multiple pages with the same ID. On a whim I made a quick change. First - I made my page use a unique ID based on the starting position of the results. I then added a static class.

<div id="search#url.start#" data-role="page" data-theme="e" class="searchPage">

I then modified my event handler to listen in to the class, not the ID:

$('.searchPage').live('swipeleft swiperight',function(event){

This seemed to work well, but then I had a problem with my selectors. I could now possibly have multiple prevLink and nextLink items in my DOM. I remembered that jQuery let's you look for something inside another item. I also remembered jQuery Mobile provides a pointer to the current page. I tried this modification:

var prev = $("#prevlink",$.mobile.activePage);

And it worked! Here is the complete JavaScript block. Notice too I also actually added the navigation part as well:

<script> $(document).ready(function() {

$('.searchPage').live('swipeleft swiperight',function(event){
	console.log(event.type);
	if (event.type == "swipeleft") {
		var prev = $("#prevlink",$.mobile.activePage);
		if (prev.length) {
			var prevurl = $(prev).attr("href");
			console.log(prevurl);
			$.mobile.changePage(prevurl);
		}
	}
	if (event.type == "swiperight") {
		var next = $("#nextlink",$.mobile.activePage);
		if (next.length) {
			var nexturl = $(next).attr("href");
			console.log(nexturl);
			$.mobile.changePage(nexturl);
		}
	}
	event.preventDefault();
});

}); </script>

You can test this yourself below. Any comments?

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate for HERE Technologies. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Phil Green posted on 3/15/2011 at 2:39 AM

Nice. The swipe events are the wrong way round though; if you're swiping to the next page in abook you start from the right, therefore you trigger a swipeleft event and vice versa.

You can also specify a transition direction so when you go to a previous page (swiperight, heh) the transition would "follow" the motion.

Comment 2 by Raymond Camden posted on 3/15/2011 at 5:08 AM

Yep - you are right. That would make more sense. Trivial enough to change though. :)

Comment 3 by Anton Ranestam posted on 4/17/2011 at 11:47 PM

Doesn't work :(

Comment 4 by Raymond Camden posted on 4/17/2011 at 11:56 PM

Can you explain how it isn't working for you?

Comment 5 by wHiTeHaT posted on 6/21/2011 at 1:14 AM

Doesnt work for me either.
I sended link from chrome to phone (htc legend 2.2)
i inserted something in the search , i press submit the search key.it say no results.I then try to swipe to the right (go back) nothing happen.So i try swipe left, nothing happen.

Comment 6 by Raymond Camden posted on 6/23/2011 at 5:52 AM

Well, the swipe isn't meant to work when no results are found. Try searching for "e", it should return a lot of results that include pagination.

Comment 7 by Jens posted on 7/13/2011 at 1:14 PM

Worked great, thanks!

Comment 8 by Lindsay posted on 8/2/2011 at 3:06 AM

Thanks so much for posting this tutorial - it helps me understand the touch actions much better now.

One thing though.. your demo has a user interface flaw.. You have the "swipe left" go to previous screens where as the nature of the swipe to the left is to move forward. I think this is what is confusion people about your demo as well because I couldn't get it to work either.

also, your buttons to click to go to the post content somewhat interfere and sometimes get clicked accidentally while swiping.

just some thoughts.

Comment 9 by Raymond Camden posted on 8/2/2011 at 3:13 AM

Yeah, a few people commented on that. Perfect example of where my logical mind incorrectly merged with the analog world. ;)

Comment 10 by Lindsay posted on 8/2/2011 at 3:18 AM

OOPS.. shoudl have read the comments before posting one. It's ok though.. you developer types get a buy on all of that kind of stuff!!!

Comment 11 by Raymond Camden posted on 8/2/2011 at 3:20 AM

Heh, you should see the animation I just created in Adobe Edge. It was.... epic in it's badness.

Comment 12 by Lindsay posted on 8/2/2011 at 3:20 AM

Ohh I also meant to ask..

Can you post a simplified version of your html markup? I am trying to create a mobile version of my photography website and would like to have my galleries swipe-able but need to learn more about how you did it structurally.

Comment 13 by Raymond Camden posted on 8/2/2011 at 3:22 AM

It would be best to check the jQuery Mobile docs for that - or you can download my presentation (from the presentations tab), but the JQM docs are best. They did an excellent job at making it simple to work with.

Comment 14 by rob posted on 8/10/2011 at 12:58 AM

swipe doesn't work for me either - iphone4 safari.

search worked, click works, swipe doesn't.

Comment 15 by Raymond Camden posted on 8/10/2011 at 7:16 AM

I'll check tomorrow. I've got an iPad2 now so it's easier to test.

Comment 16 by Raymond Camden posted on 8/12/2011 at 5:44 PM

I just tested on my iPad2 and it worked. Don't forget I made the mistake of doing it backwards. Search for "e", and swipe from left to right to advance to the next page.

Comment 17 by buffalo0 posted on 9/9/2011 at 6:34 PM

Didn't work for me on iPod touch

Comment 18 by Raymond Camden posted on 9/9/2011 at 6:56 PM

What version of ios? Unfortunately, with no iPod Touch to test against, I can't help much. Check the support matrix here:

http://jquerymobile.com/gbs/

iPod Touch is not called out, although it should be considered the same as the iPhone probably.

Comment 19 by Tom Solyan posted on 9/17/2011 at 7:23 PM

Are the swipe gestures supposed to work on Android phones? I can get them to side between the data-role pages when using the button, but, the actual swipe gestures don't seem to work? Do I need to add actual jquery scripts? Thanks and by the way, I really appreciate your help...

Comment 20 by Raymond Camden posted on 9/18/2011 at 9:43 PM

Not quite sure what you mean by "Do I need to add actual jquery scripts" - you definitely need to include jQuery for anything in JQM to work. If your site is online, I can take a look.

Comment 21 by Tom posted on 9/18/2011 at 10:42 PM

Here is a link to a test page I set up following your easy to understand code, it works with the links, but dose not "swipe" with fingers with android phone?
http://www.backseatbettys.c...
If I can get it functioning properly I have some stuff I would like to add it to. Here is a link to how I have been doing nearly the same thing, but this also only works with the links, but, it does worl on regular PCs as well. It just slides html content set up as php includes:
http://www.socialdealer.com...

Again, thanks for any input you may have....

Comment 22 by Raymond Camden posted on 9/19/2011 at 1:24 AM

You didn't write the code though. As my blog entry explains above, you have to actually write event handlers for it.

Also - you want to upgrade to the latest jqm.

Comment 23 by Mike posted on 9/21/2011 at 8:33 AM

ios 4.3.1 iphone 4.

searched for "e", only two results. can't test pagination on that I guess.

Searched for "A", have quite a few results. But, no swiping happening :(

Comment 24 by Mike posted on 9/21/2011 at 8:35 AM

Oh there we go, I searched for "P" and lots of results were returned and was able to swipe.

Comment 25 by Mike posted on 9/21/2011 at 8:38 AM

Spamming your comment section. Going to try and implement it now. It is very sensitive though. Lots of accidental clicks going on. Still, good place to start.

Comment 26 by miaka posted on 11/10/2011 at 7:17 PM

Opened on an iPhone and while searching for "e" it gets looped on loading ;( and doesn't work.

Comment 27 by Raymond Camden posted on 11/10/2011 at 7:25 PM

Just tested on my iPad2 and it worked. Maybe refresh try again?

Comment 28 by miaka posted on 11/10/2011 at 7:42 PM

Went on the site the second time and works now. Weird. It may be, because I entered some garbled text the first time ("hgdh"), but I did try refreshing and then the same was happening for "e" and "a" (continues loop). May be something with iPhone cache though, anyway.

Swipe gesture sure is nice! :) Thanks, that demo helped a lot!

Comment 29 by Raymond Camden posted on 11/10/2011 at 7:43 PM

As a reminder, don't forget I screwed up the directions here (I mean swipe directions). When you take this code and put it into your million dollar idea, swap em - and then send me a check. ;)

Comment 30 by Developer posted on 2/1/2012 at 8:36 PM

Hi! there is posible to make this effect with touching page??

If you make a movement with your finger right to left go to the next page, but if you move left to right go back.

Anybody can help about this?

Gracias! ;)

Comment 31 by Raymond Camden posted on 2/1/2012 at 8:37 PM

I'm sorry - what you describe _is_ a swipe, is it not?

Comment 32 by Developer posted on 2/2/2012 at 12:22 PM

Yes!! I implemented in my RSS feed APP (like your tutorial about this), but I have a problem when I'm in the first entry detail I try to swipe to the next entry detail but I can't

Comment 33 by Raymond Camden posted on 2/2/2012 at 7:56 PM

Well, I'd need more info on why it is failing. If this is online where I can see, let me know.

Comment 34 by Developer posted on 2/2/2012 at 7:58 PM

I solved the problem.

I added:
$("#PageDetail).live("pageshow swipeleft swiperight"(function(e) {

...

And this I can see if event type is swipeleft and go to the next entry with some more code that I develop :)

Comment 35 by KC Painter posted on 2/27/2012 at 10:34 PM

This example is exactly what I needed. I have not implemented it in my site yet, but it seems straight forward enough. If not I'll bug you with a few questions.

Comment 36 by KC Painter posted on 2/28/2012 at 3:09 AM

I inserted your swipe function into my site, and I am getting a weird error. It says l.data("page") is undefined in code.jquery.com/jquery-1.5..... I have a ref to this script library included in my HTML, and am not sure why it does not read the particular var. Any help would be greatly appreciated.

Comment 37 by Raymond Camden posted on 2/28/2012 at 3:59 AM

Is it online where we can see?

Comment 38 by KC Painter posted on 2/28/2012 at 7:18 PM

Sorry for the long URL

http://kcpaintersworld.com/...

Comment 39 by Raymond Camden posted on 2/29/2012 at 12:34 AM

Interesting. I note you aren't using jQuery Mobile UI items, like pages. If you modify your container div to have data-role="page", does it work?

Comment 40 by Ryan Archer posted on 5/22/2014 at 7:30 AM

Hi again Raymond,

Nice example you have put together here, very helpful. For the time being I have just simplified it quite a bit to:

$("body").bind("swipeleft", function(e) {
$.mobile.changePage( '#nextPage, { transition: "slide" });

My issue is that I am using the multi page site template structure (putting all pages into one HTML file) and it will not work. Is there a workaround for this or would I have to abandon multi page?

Comment 41 by Raymond Camden posted on 5/22/2014 at 4:29 PM

Um... I don't know. That's weird - cuz afaik - whether you put the pages in one HTML or multiple, it should plain work. (Of course, you have a typo in your code above but I assume it was an accident when you typed.) Is the event not firing? Ie, can you add a console.log before the changePage?

Comment 42 by Ryan Archer posted on 5/22/2014 at 4:46 PM

Maybe it was the typo Ray, I have had a few of those obvious comma,semicolon,brackets issues today. I found a solution here at stackoverlow that did a good job.

I also wanted to be selective about which pages in the stack that I wanted to allow swipe gestures on. Link to stackoverflow is below:

http://stackoverflow.com/qu...