8

I have been impressed by the slick javascript library (http://kenwheeler.github.io/slick/) and want to incorporate it into my shiny apps/flexboard pages.

I would like to use the htmlwidgets package in R incorporate the slick js library, so have started by trying to create a package as is suggested in the online documentation (http://www.htmlwidgets.org/develop_intro.html), by carrying out the following...

devtools::create("slick")              
setwd("slick")                          
htmlwidgets::scaffoldWidget("slick")

I downloaded the js library from https://github.com/kenwheeler/slick/archive/1.6.0.zip

and placed it into the structure of the package so that I have a file structure that looks a bit like this.

R/
| slick.R

inst/
|-- htmlwidgets/
|   |-- slick.js
|   |-- slick.yaml
|   |-- lib/
|   |   |-- slick-1.6.0/
|   |   |   |-- slick/
|   |   |   |   |-- slick.min.js 
|   |   |   |   |-- slick.js
|   |   |   |   |-- slick.css
|   |   |   |   |-- slick-theme.css

My slick.yaml file looks like this...

dependencies:
  - name: slick
    version: 1.6.0
    src: htmlwidgets/lib/slick-1.6.0
    script:
        - slick/slick.min.js
        - slick/slick.js
    stylesheet: 
        - slick/slick.css
        - slick/slick-theme.css

But am really stuck as to how to adjust the inst/htmlwidget/slick.js file and the R/slick.R file in a way that can take a vector of urls and display them in a shiny app. The reason for this, is that it does not seem to match a similar input data concept as the example provided.

For reproducibility and to use the same URLs that are provided in the examples in the package, I am providing a vector of placeholder img urls that I would like to use as the contents. For each image in the carousel.

image_vec <- paste0("http://placehold.it/350x300?text=",seq(1:9))

Perhaps I might need to use something like this?...

lapply(image_vec,function(y){div(img(src=y))})

As always any help on this would be much appreciated.

EDIT

My new slick.yaml file looks like the following...after @NicE's answer post...am I missing something?

dependencies:
  - name: jquery
    version: 3.1.0
    src: htmlwidgets/lib
    script:
      - jquery-3.1.0.min.js
  - name: slick
    version: 1.6.0
    src: htmlwidgets/lib/slick-1.6.0
    script:
        - slick/slick.min.js
        - slick/slick.js
    stylesheet: 
        - slick/slick.css
        - slick/slick-theme.css

and now my file structure looks like the following:

R/
| slick.R

inst/
|-- htmlwidgets/
|   |-- slick.js
|   |-- slick.yaml
|   |-- lib/
|   |   |-- jquery-3.1.0.min.js
|   |   |-- slick-1.6.0/
|   |   |   |-- slick/
|   |   |   |   |-- slick.min.js 
|   |   |   |   |-- slick.js
|   |   |   |   |-- slick.css
|   |   |   |   |-- slick-theme.css

and my /inst/htmlwidgets/slick.js looks like the following

HTMLWidgets.widget({

  name: 'slick',

  type: 'output',

  factory: function(el, width, height) {

    // TODO: define shared variables for this instance
    // create new slick object witht the given id?
    var sl = new slick(el.id);



    return {

          renderValue: function(x) {
                    //add class to the div and center it
                    el.setAttribute("class",x.class);
                    el.style.margin = "auto";

                    //add images to the div
                    content='';    
                    for(var image in x.message)
                    {
                      content += '<div><img src="' + x.message[image] + '"/></div>';
                    }
                    el.innerHTML = content;

                    //initialize the slider.
                    $(document).ready(function(){
                      $("."+x.class).slick(x.options);      
                    });

      },

      resize: function(width, height) {

        // TODO: code to re-render the widget with a new size

      }

    };
  }
});
h.l.m
  • 13,015
  • 22
  • 82
  • 169

1 Answers1

3

Here's an attempt, using htmlwidgets_0.6:

For the dependencies, the yaml file looks the same, I just added jQuery above slick:

dependencies:
  - name: jquery
    version: 3.1.0
    src: htmlwidgets/lib
    script:
      - jquery-3.1.0.min.js
  - name: slick ...

You can get it here and put it in the lib folder.

In the slick.R file, you need to change the arguments of the slick function to add options and change x to forward all the arguments to the JS code:

slick <- function(message, class="slick_slider", options = list(), width = NULL, height = NULL) {

  # forward options using x
  x = list(
    message = message,
    class = class,
    options = options
  )
...

In the slick.js, you mainly need to change the renderValue to add the images/content to the div and display the carousel:

renderValue: function(x) {
          //add class to the div and center it
          el.setAttribute("class",x.class)
          el.style.margin = "auto";

          //add images to the div
          content='';    
          for(var image in x.message)
          {
            content += '<div><img src="' + x.message[image] + '"/></div>';
          }
          el.innerHTML = content;

          //initialize the slider.
          $(document).ready(function(){
            $("."+x.class).slick(x.options);      
          });

        }

Once you've installed it using devtools::install(), you can use it in a shiny app:

library(shiny)
library(htmlwidgets)
library(slick)

server <- function(input, output) {
  output$test_slick <- renderSlick({    
    slick(paste0("http://placehold.it/350x300?text=",1:9),
          options=list(dots=TRUE,autoplay=TRUE))
})
}

ui <- fluidPage(
  tags$style(HTML("body {background-color: #2682d5}")),
  slickOutput('test_slick',width="350px",height="300px")
)

shinyApp(ui = ui, server = server)
NicE
  • 21,165
  • 3
  • 51
  • 68
  • I get the following error when running the ui part..`Error in yaml.load(paste(readLines(input), collapse = "\n"), ...) : Scanner error: while scanning for the next token at line 11, column 5found character that cannot start any token at line 11, column 5` – h.l.m Aug 04 '16 at 11:03
  • If you copy paste the yaml from SO, I think the new lines or tab characters are wrong, I had to replace them manually for it to work. – NicE Aug 04 '16 at 11:07
  • Thanks for the suggestion....now when running shinyApp() i just get a blue screen now...but no slick objects – h.l.m Aug 04 '16 at 11:29
  • inspecting the output and looking at the error is get the following `slick.js:11 Uncaught ReferenceError: slick is not defined` – h.l.m Aug 04 '16 at 11:48
  • you don't need the `var sl = new slick(el.id);` line, there is now `slick` object in the library. I'll try to put the code in on github when I have a sec. – NicE Aug 04 '16 at 12:42
  • here's a github repo with the code for this https://github.com/erardnicolas/slick – NicE Aug 04 '16 at 17:35