"Enhance interactivity in R with Plotly by creating clickable URLs for faceted

I am working with a ggplot2 plot that passes to plotly and then outputs to html using Rmarkdown. I am attempting to implement a JS function that opens the underlying URL when clicking on the points. Despite my efforts, the faceting seems to alter the point order and the existing solutions are not effective.

There is a related question on Stack Overflow (Add onclick open hyperlink event to an html widget created in R) that addresses a similar issue, but the solutions do not work due to the faceting issue. I also explored another post (Open hyperlink on click on an ggplot/plotly chart), but the suggested solution did not solve my problem.

Here is an example dataset:

library(ggplot2)
library(plotly)
library(htmlwidgets)
library(htmltools)

myData <- data.frame(x=c(1,2,3, 4, 6), y=c(3,2,1, 5, 4), type = c("a", "b", "c", "a", "b"), urls=c("https://www.google.com/", "http://stackoverflow.com/", "https://www.r-project.org/", "https://www.reddit.com/", "https://www.yahoo.com/"))

ggp <- ggplot(data=myData, aes(x=x, y=y)) +
              geom_point() +
              facet_wrap(type ~ .)
ply <- plotly_build(ggp)

ply$elementId <- "PlotlyGraph"

javascript <- HTML(paste("var myPlot = document.getElementById('PlotlyGraph');
                     myPlot.on('plotly_click', function(data){
                     var urls = ", toJSON(split(myData, myData$type)), ";
                     window.open(urls[data.points[0].data.name][data.points[0].pointNumber]['urls'],'_blank')
                     });", sep=''))

ply <- prependContent(ply, onStaticRenderComplete(javascript))

ply

The issue may be attributed to ggplot not ordering the data as expected by JS. I am unsure how to resolve this. Any suggestions?

Answer №1

After exploring various options, I found a solution that worked well for me by following the example provided in the plotly book. In this approach, the urls are passed through the customdata attribute. I even tested this in an Rmarkdown file. The only minor issue I faced was with the click event not working for the first point in the RStudio Viewer (it worked for all other points), but this problem was resolved when I opened it in the browser:

library(ggplot2)
library(plotly)
library(htmlwidgets)

myData <- data.frame(
  x = c(1, 2, 3, 4, 6), y = c(3, 2, 1, 5, 4),
  type = c("a", "b", "c", "a", "b"),
  urls = c("https://www.google.com/", "http://stackoverflow.com/", "https://www.r-project.org/", "https://www.reddit.com/", "https://www.yahoo.com/")
)

ggp <- ggplot(data = myData, aes(x = x, y = y, customdata = urls)) +
  geom_point() +
  facet_wrap(type ~ .)

ply <- ggplotly(ggp)

onRender(
  ply, "
  function(el) {
    el.on('plotly_click', function(d) {
      var url = d.points[0].customdata;
      window.open(url);
    });
  }
")

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transform the infoBox into a jQuery dialog modal window

In this section, I have integrated a map with markers and infoBoxes. My goal now is to replace the infoBoxes with jquery dialog() and modal window functionalities. How can I achieve this effectively? Below is the code snippet that includes the implementat ...

Attempting to remove certain characters from a given string

let currentDate = new Date(); currentDate.toLocaleString; If I were to console log the value of currentDate, it would show: Wed Oct 16 2019 15:57:22 GMT+0300 (Israel Daylight Time) However, what if I only want to display the minutes and seconds like 57: ...

Siblings are equipped with the advanced selector feature to

I'm struggling to understand this setup I have: <div class="container"> for n = 0 to ... <a href="some url">Link n</a> endfor for each link in ".container" <div class="poptip"></div> ...

What is the most effective method for determining the distance between two UK Postcodes?

Can you suggest a reliable method for calculating the distance between two UK postcodes in order to determine if they are within range? I do not intend to display a map, but instead provide a list of results for valid locations. For example, showing loca ...

Error encountered when attempting to retrieve token from firebase for messaging

I am currently working on implementing web push notifications using Firebase. Unfortunately, when attempting to access messaging.getToken(), I encounter an error stating "messaging is undefined." Below is the code snippet I am utilizing: private messaging ...

jQuery loading and updating

I am faced with a scenario where I have both a 'test.html' and a 'test.php' files. The content of 'test.html' is as follows: <html> <head> <script type="text/javascript" src="/js/jquery-1.8.2.js">< ...

Retrieve the most recently updated or added item in a dropdown list using jQuery or AngularJS

Having a multiple select element with the chosen jquery plugin, I am trying to identify the latest selection made using the change event. Struggling to locate a simple method to access the most recent selection, I am currently inspecting the last item in ...

Identify when the Vue page changes and execute the appropriate function

Issue with Map Focus Within my application, there are two main tabs - Home and Map. The map functionality is implemented using OpenLayers. When navigating from the Home tab to the Map tab, a specific feature on the map should be focused on. However, if th ...

Is it possible to integrate external search functionality with Vuetify's data table component

I am currently working with the v-data-table component from Vuetify, which comes with a default filter bar in its properties. This table retrieves data from a local JSON file. The issue arises when I have another external component, a search bar created u ...

Comparing a stored array in Mongo against a native JavaScript array with identical length and values results in a failed deep assert comparison

In my mongoose ORM, I have a field in mongo defined as: state: {type: [Number], required: true } When I check a sample document in the mongo console, the state appears as: state: [ 1, 1, 1 ] Everything seems to be in order so far. However, when I try t ...

What is the best way to limit a form to only allow 2 checkbox selections?

Seeking advice on implementing a form for a website giveaway featuring 3 prizes. Each participant should only be able to select 2 items from the list. I've already created a JavaScript-based form, but I'm concerned about its reliability since it ...

Updating the content of a file on an iPhone

Is there a way to update the entire document content with a response from an ajax request? I've tested out using document.body.innerHTML and document.write(), which both work on desktop Safari. However, I'm looking for a solution that will also ...

Arrange the array based on the key values

I am currently working with a function that sorts by name and an array containing value/key pairs. I am trying to figure out how I can dynamically pass the key on which the sort is being performed, so that I can call the same function each time with diffe ...

How to trigger a hover effect on a div and its child simultaneously using HTML and jQuery

Here's my concept: I want the text to be contained within div elements with an integrated image, rather than just having fading in and out pictures. Here's my attempt: #first{ position: absolute; } #second{ position: absolute; -we ...

Error encountered: EPERM when attempting to rename a directory in Node.js unexpectedly

There is a requirement for me to remove the Backup folder, rename the processor as Backup, create a Processor folder again, and send a response to the user. The code I am using for this task is as follows: fsExtra.remove('app/Backup', function(e ...

Display advertisement upon clicking

I am looking to enhance my HTML page by incorporating Google Adsense adverts that load up when a visitor clicks on video links. After 10 seconds, the page should automatically redirect to the video file. Any suggestions on how to achieve this? Thanks! ...

Issue with Node REST API: PUT request is failing to update data in the request

Encountering issues while attempting to update data through a PUT request. Despite making the request, the data remains unchanged and continues to display the previous information in Postman. Details of the PUT request sent via Postman: http://localhost: ...

The MUI5 drawer overlapping a modal dialog

Is it possible to use MUI5 to open a side drawer on top of a modal dialog that triggers it? Currently, the dialog triggers the side drawer but it opens behind this. It appears as though a modal dialog (drawer) is attempting to open over an already-opened ...

Error: The function does not exist for collections.Map

I'm encountering a TypeError on my page: collections.Map is not a function. Below is my JavaScript code and I can't seem to figure out what the issue is. this.state = { collections: SHOP_DATA }; render() { const {collections} = this.sta ...

What is the best way to transform a JSON object with various key-value pairs into a list using JavaScript?

There's a JSON string that I need to convert into a different format, here is the original: var jsonData = [{"label":"Hass1(<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="354d4d4d6a465058755d5a4158545c591b565a58">[emai ...