1

I use rmarkdown to produce a Slidy slide show using slidy_presentation. I would like to execute some Javascript when a slide is shown. In ioslides_presentation there's a slideenter event triggered when a page is shown (see Event when slide is displayed in ioslides?), but I don't see anything like that in Slidy.

I can detect whether a particular slide is being shown (by looking at the class of its div), but I don't know how to trigger the code to do that.

Is there some way to detect that a slide change is happening?

Community
  • 1
  • 1
user2554330
  • 37,248
  • 4
  • 43
  • 90

1 Answers1

2

I researched a little and found an easy hack on how to detect which slide is currently shown:


Using a MutationObserver

In the following script we use a MutationObserver (see here and here) to observe changes in the content of the title element. Having the title we can extract the integer part of it, which represents a slide number. In this example we just show an alert containing the text "Current Slide: " followed by the number we extracted.

enter image description here

Here ist the JavaScript snippet:

<script>
var target = document.querySelector('head > title');
var observer = new window.WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        var title   = mutation.target.textContent;
        var current = +title.toString().match(/\d+/g);
        alert('Current Slide: ' + current);
    });
});
observer.observe(target, { subtree: true, characterData: true, childList: true });
</script>

Since we don't want the snippet to be interpreted as the content of a slide itself, we include it via the YAML header. Check the reproducible example below, where header.html contains only the the javascript snippet above:

MRE:

---
title: "Untitled"
author: "Martin Schmelzer"
date: "18 3 2017"
output: 
  slidy_presentation:
    includes:
      in_header: header.html
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```

## R Markdown

Slide 2 (Title slide is #1!)

## Slide with Bullets

This is slide 3!

## Slide with R Output

...and number 4!

EDIT: Modified script for ioslides

If somehow needed in ioslides, you can modify the JavaScript snippet the following way:

<script>
$(document).ready(function() {
  var target = document.querySelector('slides');
  var observer = new window.WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if(mutation.target.getAttribute('class').indexOf('current') != -1 ) {
          alert(mutation.target.getAttribute('data-slide-num'));
      }
    });
  });
  observer.observe(target, { subtree: true, attributes: true});
});
</script>

In slidy each slide consists of its own div container. The approach in ioslides is different. Here we only have a couple of <slide> elements for the past, current, next and far-next slides. The current slide element is the one which has the class current. So we just search for that class inside the forEach loop and grab it's data-slide-num attribute.

Martin Schmelzer
  • 23,283
  • 6
  • 73
  • 98
  • Thanks, that works really well in slidy. It would also work in ioslides, but it appears too slow: I was watching the class of the slide, and I think every slide changes class 5 times for each slide advance, so I was getting dozens of calls, instead of just one like `slideenter` gives. – user2554330 Mar 18 '17 at 13:50
  • You are welcome. Is there a follow up question hidden in your comment? ;) – Martin Schmelzer Mar 18 '17 at 13:54
  • I added a modified version for ioslides. – Martin Schmelzer Mar 18 '17 at 14:47