Programmatically close Data Viewer tabs in RStudio - r

I wanted to make a script that closes all Data Viewer tabs in RStudio (those invoked by clicking on a data object in the Environment pane, or by calling utils::View()) but keeps all the "usual" document tabs.
First, I found rstudioapi::documentClose() function - not sure if it works for Data Viewer tabs, it requires the document id that seems to be not applicable here: calling getActiveDocumentContext() on Data Viewer tab returns #console.
Then, there's executeCommand('closeSourceDoc') option that closes the current tab, whether it is Data Viewer or standard document. I could probably use executeCommand('nextTab') to loop through all opened tabs, but I can't find how to determine if the active tab is Data Viewer or not...
Any hints?

The following code seems to do what you want.
Tabs=c()
doc=rstudioapi::documentPath()
while (is.null(doc)||!doc%in% Tabs) {
if(is.null(doc)){
rstudioapi::executeCommand('closeSourceDoc')
}
rstudioapi::executeCommand('nextTab')
Tabs=c(Tabs,doc);
doc=rstudioapi::documentPath()
}

Related

R Shiny - Run application in background and issue UI controls with code

I am writing a vignette for my Shiny application package. At the beginning of my vignette, I source a file called screenshots.R that produces nice screenshots of my application. I am producing them like so:
webshot::appshot(mypackage::run_datepicker_app(),
file = "man/figures/datepicker.png", vwidth = 500, vheight = 200)
This works great and it gives me a great screenshot of what is - in this case - a couple dateInput fields. However, I'd like to be able to get a screenshot of the dateInput in use (say, with the calendar selection exposed).
Is there a way to issue commands to the application object in a script so I can get screenshots of the application in use, rather than having to do it manually?
Have you tried using ShinyDriver from the shinytest package?
You can use shinytest to have a headless browser run the app, interact with it, and take screenshots programmatically. If you don't have phantomJS installed, you'll need to run shinytest::installDependencies() before using ShinyDriver. All you need to do is point it to a directory containing a shiny app (in my case, the folder is 'myApp').
install.packages("shinytest")
shinytest::installDependencies()
app <- shinytest::ShinyDriver$new("myApp")
app$takeScreenshot("screenshot1.png")
button <- app$findElement("#button")
button$click()
Sys.sleep(1)
app$takeScreenshot("screenshot2.png")
app$stop()
I am starting the app in a headless browser, taking a screenshot, finding the button with the id 'button', clicking it, and taking another screenshot, then closing the app. Navigate to specific elements using "#id", where id is just the id you gave the shiny input. You can specify a file path to a png file in the takeScreenshot calls, so that you can then use them in your code elsewhere. Note that you may need to use Sys.sleep to stop the screenshots from being taken before the UI updates.

Download Highcharts Generated Table into R

I'm trying to download a csv file of data corresponding to the chart on the below website:
http://vixcentral.com/
If I click on the menu button on the top right of the chart there's an option to download the chart data into a csv.
The issue is that that button seems to generate a download link that only works temporarily, so I'm unable to use a regular downloader such as read_csv or rio::import to pull the file into R.
It seems both the chart and the download link are generated by the Highcharts javascript.
Is there any straightforward way to download this data into R by figuring out the link?
Or does it have to be a scraping excercise?
If you right-click on the screen and press 'Inspect Element', then go to the 'Network' tab, you can see xhr requests being done to obtain data (for example while clicking around the different charts).
You noted that you're interested in the result of http://vixcentral.com/ajax_update/?_=1590762673737.
The number in the end of this URL is the Unix epoch of the current time. That's why it changes.
There is a little bit of security from scraping in the sense that they try to block requests that do not come from their own site. By setting the header X-Requested-With to "XMLHttpRequest", it works. You can view the headers used for this request by clicking on it in the 'inspect element' screen of your browser. There are a bunch of headers being set, and by removing each one and testing, I found out that this is the only one that's needed for your purpose.
Below reads the data and parses it into an R object using jsonlite.
res <- httr::GET("http://vixcentral.com/ajax_update/?_=1590762673737",
add_headers("X-Requested-With" = "XMLHttpRequest"))
res_text <- content(res, "text")
jsonlite::fromJSON(res_text)

rmarkdown::render() doesn't allow multiple users at the same time?

I have a shiny app that renders an HTML report from an action button. Once this is rendered, a download button shows up in the screen so that the result of that action button can be downloaded. I had to create this two separate buttons because the download handler seems to have a time out, so since my Rmd file takes a bit longer to render, it wouldn't work and it throws an error in the server.
I am currently rendering my Rmd like in the following:
rmarkdown::render(tempReport, output_file = tmp_file,
params = params,
envir = new.env(parent = globalenv()))
The problem is: if one user is rendering his/her report in the server, if a second user clicks the action button to render it at the same time, it will only start rendering once the first user is finished.
Does anyone have any solutions to this?
The behavior you are observing is a result of the fact that R is single-threaded. The direct answer to your issue is that you need to implement asynchronous methods to allow multiple render() processes to run concurrently. More on this at: https://rstudio.github.io/promises/.
If you don't want to go down the asynchronous path and there are a reasonable number of possible report variants, you can pre-render the output and have the user simply open the selected output rather than rendering on-demand.

RSelenium: Switching Windows using Window Handle

I've been working with RSelenium all day and still hitting road blocks here and there. My current issue is using the code WebElemReports$clickElement() which clicks a link and a new window opens. I tried to adjust Firefox settings in "about:config" so that it will not open a new window. It doesn't open a window in normal use, but using RSelenium, it opens a new window still. I also looked at this approach but couldn't follow the logic of how it worked:
How to clickElement() and open the link in the same tab
My next thought process was to use the switchToWindow() function along with getWindowHandles(). The code I wrote is as follows:
remDr$closeWindow()
windHand <- remDr$getWindowHandles()
remDr$switchToWindow(windHand)
My thinking is that I will close the current window so that there will only be one handle to reference and pass that handle to the switchToWindow function. I can't find much switchToWindow documentation for R. I receive the following error with using the code above:
Error: Summary: UnknownError
Detail: An unknown server-side error occurred while processing the command.
class: org.openqa.selenium.WebDriverException
Any help on this would be much appreciated--I tried to research this as much as possible so this won't get marked as a duplicate question like my last post. Many Thanks.
Actually you can't close main window, you can switch to child window as below :-
# get main window and store to switch back
currWindow <- remDr$getCurrentWindowHandle()
#gel all windows
windows <- remDr$getWindowHandles()
#loop through switching child window
for (window in windows[[1]]) {
if (window != currWindow[[1]])
remDr$switchToWindow(window)
}
#now do your stuff with child window
#now close your child window after doing all stuff
remDr$closeWindow()
#now switch back to main window for further stuff
remDr$switchToWindow(currWindow[[1]])

show warning message to user in ASP.NET

I have a pop up window that is create in run time, and can have several text area. I need to count number of characters of its text area and show warning to users if they pass maximum number.
the application wrote by ASP.NET. I can't use "onClientClick", because I don't know the name of the text area, they created run time and I save their name in a dictionary that just have in server side.
I tried to use "RegisterStartupScript" to call java script "alert" method but it doesn't work. In fact it works but it execute all the save code and show alert after that. but I want to execute save code after user confirmation.
I think to open message box with jquery but my current windows is opening with AJAX and it won't nice to open another AJAX page.
Can You help me and show me the way to show warning, or solving my problem.
You need to use the onkeypress or onkeyup events in the text area, and use a function like this to show the warning:
onkeypress="checkLength(this, 200);"
And the JavaScript function:
checkLength = function(input, maxLength){
if (input.value.length > maxLength)
alert('Length exceeds maximum');
}

Resources