javascript gallery swipe-right rocket surgery

How do I make page-swiping work properly in the DNA Lounge photo galleries? Go to any photo page and swipe left or right on your phone. It goes to the next or previous image, but it kinda sucks. I'd like to de-suckify it.

My code is here: dragnav.js.

What I'd like:

  • Dragging animates the current page sliding out and the new page sliding in.

  • Presumably this would require pre-loading the HTML and images on both the next and previous pages, to get them in the cache early.

  • Dragging actually changes the page URL. (And changes it from "001.html" to "002.html", not to some bullshit like "index.html#002".)

  • Good answers come in the form of "here's a Javascript snippet" rather than in the form of "here's a 30,000 line all-singing all-dancing mobile gallery application that does a ton of shit you don't care about."


Previously, previously, previously, previously, previously, previously.

Tags: , , , , ,
Current Music: EMA -- 3Jane ♬

16 Responses:

  1. Adam says:

    The third point can be done using "HTML5"; the Javascript method is called window.history.pushState().

  2. Leolo says:

    I strongly suspect I can't fullfill all four of your conditions. Changing the URL will cause your JS to reload.

    You could fake it by putting the new page in an iframe (or equiv). You then animate the iframe over the current page. When the animation is done, you then set "window.location" to the new page. This might cause "flashing" when the new page is reloaded.

  3. John Doty says:

    Here's a start:

    There's at least one bug; when you go to the next page sometimes the picture gets smaller. In the example given in the gist (from the gallery "DNA Lounge: Anti-Nowhere League, 15 May 2014"), when you try to swipe from 001.html to 002.html the picture on 002.html is the wrong size. I don't know why this is, and have spent no time trying to figure it out.

    It also flickers when it navigates, because there is no attempt to fix up the body of the page once the drag is "complete". I don't think that part is too hard, I'm just out of time right now.

    Maybe it will help?

    • jwz says:

      Thanks! But this isn't working for me in Safari, and some googling suggests that it's because adding DOMContentLoaded onto a manually-created iframe just doesn't work.

      I think maybe the way to do this would be: create off-screen borderless iframes that are the same size as the current window, to the left and right; load the prev/next documents into those; and then let dragging animate past those until it lines up, at which point you change the URL and do it all again.

      But that's going to look stupid if the content of the current page is taller than the current window and you have scrolled before dragging. And I'll bet it flickers at the end anyway.

      • John Doty says:

        Because I'm a sucker for punishment, here's one that works (checked on Chrome and Nightly and Desktop Safari, but not Mobile Safari):

        - The page size bug has been fixed. (Now it uses XMLHttpRequest to fetch the page, and createHtmlDocument() to make a document to load the contents into.)
        - It "loads" prettily now, without a flicker.

        (This file, verbatim, still binds the mouse because laziness.)

      • Ryan says:

        Am running around with the lady this weekend and so forgive my lack of code, but is there a reason you want these to be in iframes?

        I expect it's to make sure you have the link rels to operate on, but you could either return those from the ajax request as part of a json object, or if you don't mind a minor edit to your CMS, you could attach them as data-next and data-prev attributes on whatever part of the page you're most interested in cloning.

        Then you'd have off-canvas divs, ready to receive the content of the prev and next links. Ajax would load the page, grab just the relevant content (.page .bottom .CENTER?) and insert that into the off-canvas div. Then you can animate just the content into the page and your header doesn't move, which makes it even more app-like, which I'm presuming to be your intention here.

        Or you could grab/clone just the linked image element and update the navL and navR links' hrefs for a cleaner looking end product at the expense of some code complexity.

        This has the added benefit of potentially keeping more than just three total images/pages in place because you're not forced to actually destroy already loaded images. So swipes back and forth maintain state and users could swipe multiple previous images immediately since they're still in the DOM....

        Can update with some code after tomorrow if it's still helpful to do so.

  4. pvg says:

    I think you're probably 97.3% of the way there and the first responder is right - you're just missing a smidgen of history API usage. Most anything else is going to be 'oh, here, try this plugin to Bootstrap/Ember/Jquery/Pterodactyls_eating_your_face'

  5. Why is this actually a thing you want?

    I appreciate the intrinsic utility of a touch-screen interface, but I'm really okay tapping either on or just to the right of an image to see the next image in sequence, and if I'm doing that on a phone in the US there's 5% chance, at best, that the transition will be fluid. Adding JS horseshit on top of it will only make the next image load more slowly.

    • (I guess, alternately: "My mobile data^H^H^H^Hphone provider is AT&T, and I do live in the Bay Area, so I'm super interested in this, since the only way I view web pages on my phone is when I use someone else's wireless!")

    • jwz says:

      Because people expect it to work like that these days. I have watched them.

      What I have now kinda works that way, but poorly.

  6. My photo pages preload neighbor images like so:
    var next_image = new Image();
    next_image.src = 'filename.jpg';
    You don't need to do anything else with the object, it does the job just by existing.

    No idea how you would preload neighbor HTML.

  7. Also, off topic but for the arrow keys why are you using onkeyup instead of onkeydown? (I know onkeypress doesn't work.)

  8. Doc says:

    Wow. Back in the day next to the an/prc-77 the ta-43 was the most ubiquitous field phone going. It was also the most infamous; this was the phone that was used to "phone charlie", with the outgoing lines wrapped around charlie's sack and then cranked to the threshold of bejesus...

    What made you pick that image - the code really that torturous?