关于javascript:拖放时出现R闪亮输入反应性错误

R Shiny Input Reactivity Error on Drag-and-Drop

我目前正在使用一些自定义js创建R Shiny应用,以提供拖放功能。 虽然拖放对单个文件非常有效,但是当我使用ShinyJS重置它时,再次上载同一文件不能正常工作。 我了解这是因为不会以重新输入具有相同名称的文件来触发onchange函数(无论文件内容是否已修改)

JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var datasets = {};
var dragOver = function(e) { e.preventDefault(); };

var dropData = function(e) {
    e.preventDefault();
    handleDrop(e.dataTransfer.files);
};

var removeFiles = function(e){
    jQuery('#datafile').empty();
}

var handleDrop = function(files) {
    for (var i = 0, f; f = files[i]; i++) {
    var reader = new FileReader();

    reader.onload = (function(file) {
        return function(e) {
        datasets[file.name.toLowerCase()] = e.target.result;
        Shiny.onInputChange("datafile", datasets);
        var div = document.createElement("div");
        var src ="https://cdn0.iconfinder.com/data/icons/office/512/e42-512.png";
        div.id ="datasets";
        div.innerHTML = [
           "<img class='thumb' src='", src,"' title='", encodeURI(file.name),
           "'/>","", file.name,""].join('');
        document.getElementById("drop-area").appendChild(div);
        };
    })(f);
    reader.readAsText(f);
    }
};

Server.R(其中一部分用于查看文件输入):

1
2
3
4
5
6
7
8
9
10
11
12
observeEvent(input$datafile, {
    infile <- input$datafile
    if (is.null(infile)) {
      # User has not uploaded a file yet
      return(NULL)
    }

    # CLEAN FILE
    name <- names(input$datafile)[1]
    csvFile <- read.csv(text=input$datafile[[name]])

  output$dataTable <- renderDataTable(csvFile , options = list(scrollX = '1100px') )

}

ui.R(仅相关部分):

1
2
3
4
5
6
7
   # DRAG AND DROP FILE INPUT
   h3(id="data-title","Drop Datasets"),

   div(class="col-xs-12", id="drop-area", ondragover="dragOver(event)",
       ondrop="dropData(event)" , onClick="fallback(event)"),

   div(onClick="removeFiles(event)", actionButton(inputId="resetAutomaticInput", label="Reset Input")

我不明白如何使闪亮的值具有反应性来触发与input $ datafile相关的事件。 任何帮助深表感谢!


我看了一下并玩了一段时间,首先使其成为一个可行的示例。我认为拖放功能是一个有用的示例。它也正确处理多点。也有一些有趣的javascript构造-至少对我来说。

为了解决此问题,我没有使用BigDataScientist建议的随机数,而是使用了一个对其他事物也可能有用的计数。

总共进行了以下更改:

  • 将这些片段完成,成为一个完整的Shiny工作示例,并将其保存到自己的目录中。
  • 将javascript代码放在保存Shiny代码的目录下的名为www的子目录中。
  • 在UI代码中添加了tag$head(tag$script(...语句以加载该javascript。
  • drop-area div中添加了一些innerhtml文本,因此可以放入其中。
  • 在JavaScript中添加了dropcount
  • 更改了html,以便将dropcount回显到drop-area div。
  • 将输出更改为verbatumPrintOutput,以便可以在较小的区域中看到更多的数据框。
  • 在输出中添加了更多字段,因此您可以更好地看到input$datafile中的内容。
  • 将JS for循环更改为不会产生警告的内容。
  • 在顶部添加了jslint注释,以消除其他警告。
  • 添加了一些输出字段(inputdatafilerowsdatafile),因此您可以跟踪input$datafile中的内容-直到我不清楚真正的错误是什么,但这只是我...
  • 稍微更改了输出中的逻辑,以使重置功能按人们可能期望的方式工作(示例代码似乎仍然不完整)
  • 可能还有其他一些我忘记的小事情。

这是代码:

JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*jshint loopfunc:true */ // git rid of warning
var datasets = {};
var dragOver = function(e) { e.preventDefault(); };

var dropData = function(e) {
  e.preventDefault();
  handleDrop(e.dataTransfer.files);
};
var dropcount=0;

var removeFiles = function(e){
    txt ="Drop Area"+dropcount;
    jQuery('#drop-area').html(txt);
    datasets = {};
    Shiny.onInputChange("datafile", datasets);
};
var handleDrop = function(files) {
  for (var i = 0; i<files.length; i++) {
    f = files[i];
    var reader = new FileReader();

    reader.onload = (function(file) {
      return function(e) {
        datasets[file.name.toLowerCase()+'|'+dropcount] = e.target.result;
        Shiny.onInputChange("datafile", datasets);
        var div = document.createElement("div");
        var src ="https://cdn0.iconfinder.com/data/icons/office/512/e42-512.png";
        div.id ="datasets";
        div.innerHTML = [
         "<img class='thumb' src='", src,"' title='", encodeURI(file.name),
         "'/>","", file.name,""].join('');
        drpel = document.getElementById("drop-area");
        drpel.appendChild(div);
        drpel.childNodes[0] ="Drop Area"+dropcount;
      };
    })(f);
    reader.readAsText(f);
    dropcount++;
  }
};

这是闪亮的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
library(plotly)
library(htmlwidgets)
library(shiny)
library(ggplot2)

ui <- shinyUI(fluidPage(

  tags$head(tags$script(type="text/javascript", src ="fileUp.js")),

  # DRAG AND DROP FILE INPUT
  h3(id="data-title","Drop Datasets"),

  div(class="col-xs-12",id="drop-area",ondragover="dragOver(event)",
      ondrop="dropData(event)",onClick="fallback(event)","Drop Area"),

  div(onClick="removeFiles(event)",
      actionButton(inputId="resetAutomaticInput",label="Reset Input"),
      verbatimTextOutput("inputdatafile"),
      verbatimTextOutput("rowsdatafile"),
      verbatimTextOutput("dataTable"))
))    
server <- shinyServer(function(input, output) {

  observeEvent(input$datafile, {
    infile <- input$datafile
    if (length(infile)==0) {
      # User has not uploaded a file yet
        return(NULL)
    }    
    # CLEAN FILE
    name <- names(input$datafile)[length(infile)]
    csvFile <- reactive(
      if (length(input$datafile)>0){
        read.csv(text=input$datafile[[name]])
      }
    )

    output$dataTable <- renderPrint(csvFile())
    output$inputdatafile <- renderPrint(names(input$datafile))
    output$rowsdatafile <- renderPrint(sapply(input$datafile,nchar))
  })
})
shinyApp(ui, server)

屏幕截图:

enter image description here