Issues when reading Xaringan presentations on mobile

JavaScript to the rescue!

By Lucio Cornejo in rmarkdown

December 27, 2021

Perhaps it’s just bad luck, but I’ve encountered a couple of issues on mobile when reading Xaringan slides.
Here I’ll describe how I have dealt with those issues, mainly using JavaScript.

Quickly alternating between slides

During a mobile Xaringan presentation, if you tap the screen, the next or previous slide will show up.
However, if you tap many times, and fast, the screen usually activates a zoom.
Here is a way to disable such screen zoom when double tapping, using CSS :

/* Disable double-tap zoom */
html { touch-action: manipulation; } 

Unintended slide change due to tap

The following has occurred during a mobile Xaringan presentation:

  • When I’ve scrolled through a vertically long slide, the tap to activate the scrolling activates an unintended slide change.
  • When tapping an image with a link, the slide changes and the link is not opened.

The following JavaScript code has fixed those problems in my presentations:

// Code to fix the change of slide when scrolling and when clicking some elements
let touchmoved;
$('div.remark-slide-container').on('touchend', function(event){
  if(touchmoved === true) {
    // Do not change slide if scrolling took place
    event.preventDefault(); 
    event.stopPropagation();
  } else {
    // Fix for issue when clicking an image with an anchor
    if(event.target.tagName === "IMG") {
        if (event.target.parentNode.getAttribute("href").includes("https:")) {
            // If there was no scrolling and the user clicked on an image
            // which has an anchor, then do not change slide and open
            // in a next window the site linked to image touched
            event.preventDefault(); 
            event.stopPropagation();
            window.open(event.target.parentNode.getAttribute("href"));
        } 
    }
    
    // Fix for issue when clicking the symbol of a <details><summary> ...
    if (event.target.tagName === "SUMMARY") {
        if(event.target.parentNode.tagName === "DETAILS") {
            event.preventDefault();
            event.stopPropagation();
            // Manually toggle between open or closed <details>
            if(event.target.parentNode.open === true) {
                event.target.parentNode.open = false;
            } else {
                event.target.parentNode.open = true;
            }
        }
    }
  }
}).on('touchmove', function(){
  touchmoved = true;
}).on('touchstart', function(){
  touchmoved = false;
});

Swipe to go to previous or next slide, not working

Such functionality is available via Remark.js, therefore, it would be expected to work with Xaringan. However, despite it being included in Xaringan presentations I’ve found online, it hasn’t worked for mine.

I’ve implemented such functionality a little bit different, because my code allows for any swipe slide change to be cancelled if the user on mobile lifts up his or her finger which triggered the tap event, near enough to where the tap initially took place.

The Xaringan presentations I’ve read on mobile do not have such swipe slide change cancel functionality.

Here is the JavaScript code:

// Code to change between slides depending on user screen swipe 
let touchstartX = 0;
let touchendX = 0;
let swiped = false;

function conditional_swipe() {
    // Swiped left
    if (touchendX < touchstartX) {
        if ( (touchstartX - touchendX) > (screen.availWidth)*0.25 ) slideshow.gotoNextSlide();
    } else {
        // Swiped right, because swiped equals true
        if ( (touchendX - touchstartX) > (screen.availWidth)*0.25 ) slideshow.gotoPreviousSlide();
    }
}
    
$('div.remark-slide-container').on('touchstart', event => {
    touchstartX = event.changedTouches[0].screenX;
    swiped = false;
});

$('div.remark-slide-container').on('touchmove', function() { swiped = true; });

$('div.remark-slide-container').on('touchend', event => {
    touchendX = event.changedTouches[0].screenX;
    if (swiped === true) conditional_swipe();
});

Did you know?

Lastly, just a brief mention that many functions related to the slides in Xaringan (for example, go to previous slide, go to next slide, get the slide’s current number, etc) are already defined in Remark.js, so you can use them with JavaScript.
In order to see those functions, open a Xaringan presentation on Desktop, go to the Console (ctrl+shift+i in Chrome) and type slideshow. , then the available functions should pop up.