R 如何使用Shining在文本文件中保留更改?

R 如何使用Shining在文本文件中保留更改?,r,shiny,R,Shiny,我有一个用于注释文本文件的闪亮的小应用程序 用户界面提供了fileInput来选择.txt文件。其中一个文件是应用程序启动时的默认文件 Next,Previous按钮允许用户显示文件内容,一次显示一句话 用户可以选择句子中的任何文本,然后单击添加标记按钮对句子进行注释。操作按钮触发javascript函数addMarkup() 该句子在标记后显示 我只是在这里发布闪亮的应用程序代码。应用程序的完整代码可在 我的问题是,在对句子进行注释后,如何将它们保存到文件中? 更新: 我已经读过了,希望能够

我有一个用于注释文本文件的闪亮的小应用程序

  • 用户界面提供了
    fileInput
    来选择
    .txt
    文件。其中一个文件是应用程序启动时的默认文件
  • Next
    Previous
    按钮允许用户显示文件内容,一次显示一句话
  • 用户可以选择句子中的任何文本,然后单击添加标记按钮对句子进行注释。操作按钮触发javascript函数
    addMarkup()
  • 该句子在标记后显示
  • 我只是在这里发布闪亮的应用程序代码。应用程序的完整代码可在

    我的问题是,在对句子进行注释后,如何将它们保存到文件中?

    更新:
    我已经读过了,希望能够阅读有关持久存储的文档。然而,我仍然不确定如何捕捉标记后的句子

    这里有两个问题-保留更改,然后保存输出。我用一点JS和一点R代码解决了这个问题。我将在Github上执行pull请求以提交更广泛的代码。然而,这是它的核心

    在用于选择内容的Javascript中,可以使用
    shinny.onInputChange()
    更新
    输入
    向量的元素。为此,您可以为语料库创建一个
    reactiveValues
    项,然后使用界面中的输入对其进行更新

    下面,您会注意到我从使用textnode切换到只使用内部HTML。像以前一样,使用一个节点和
    firstChild
    ,最终会截断第一个注释之后的句子(因为它只拾取
    之前的内容)。这样做似乎效果更好

    window.onload = function(){
      document.getElementById('mark').addEventListener('click', addMarkup);
    }
    
    function addMarkup(){
      var sentence = document.getElementById("sentence").innerHTML,
      selection="";
      if(window.getSelection){
        selection = window.getSelection().toString();
      }
      else if(document.selection && document.selection.type != "Control"){
        selection = document.selection.createRange().text;
      }
      if(selection.length === 0){
        return;
      }
      marked = "<mark>".concat(selection).concat("</mark>");
      result = sentence.replace(selection, marked);
      document.getElementById("sentence").innerHTML = result;
      Shiny.onInputChange("textresult",result);
    }
    
    现在,代码有一些变化。从文件加载基本相同。我对
    隔离
    的怀疑是正确的-用
    观察
    替换它可以完成我想做的,而
    隔离
    只会给你初始加载。无论如何,我们使用
    观察
    将语料库值加载到您创建的
    reactiveValues
    对象-这是给我们一个传播数据更改的地方

    我们保留了向前和向后移动的剩余逻辑。但是,我们更改了输出的呈现方式,以便它查看
    reactiveValues
    对象。然后,我们创建一个观察者,使用更新的Javascript输入更新
    reactiveValues
    对象。发生这种情况时,数据将永久存储,您还可以在字符串中标记多个序列(尽管我没有使用嵌套标记或删除标记进行任何操作)。最后,添加了一个保存函数-生成的字符串将保存下来,并使用
    显示标记区域


    如果加载以前标记的文件,标记将再次显示。

    1)无论是在上面的代码中还是在github上,我都可以找到“标记代码”;没有使用
    input$mark
    的函数,……我是否缺少sthg,或者它可能在未共享的
    MyUtils.R
    中?2) 关于持久数据存储链接:您正在寻找本地文件系统解决方案?@BigDataScientist 1)这是在JSI中完成的,它已更新github repo以包含
    MyUtils.R
    。关于持久数据存储,客户机最好能在自己的机器上保存文件。这里的问题是,您的标记只是模仿用户选择,因此它没有硬编码在句子中,这使得保存很困难。你应该试着像我在你最初的问题中建议的那样使用
    span
    。这将在字符串中硬编码所选内容并使其易于保存。是否需要为每个句子捕获多个注释?
    readCorpus <- function(pathToFile){
      con <- file(pathToFile) 
      sentences <- readLines(con, encoding = "UTF-8")
      close(con)
      return(sentences)
    }
    
    window.onload = function(){
      document.getElementById('mark').addEventListener('click', addMarkup);
    }
    
    function addMarkup(){
      var sentence = document.getElementById("sentence").innerHTML,
      selection="";
      if(window.getSelection){
        selection = window.getSelection().toString();
      }
      else if(document.selection && document.selection.type != "Control"){
        selection = document.selection.createRange().text;
      }
      if(selection.length === 0){
        return;
      }
      marked = "<mark>".concat(selection).concat("</mark>");
      result = sentence.replace(selection, marked);
      document.getElementById("sentence").innerHTML = result;
      Shiny.onInputChange("textresult",result);
    }
    
    library(shiny)
    source("MyUtils.R")
    ui <- fluidPage(
      tags$head(tags$script(src="textselection.js")),
      titlePanel("Corpus Annotation Utility"),
      sidebarLayout(
        sidebarPanel(
          fileInput('fileInput', 'Select Corpus', accept = c('text', 'text','.txt')),
          actionButton("Previous", "Previous"),
          actionButton("Next", "Next"),
          actionButton("mark", "Add Markup"),
          downloadButton(outputId = "save",label = "Download")),
        mainPanel(
          tags$h1("Sentence: "),
          htmlOutput("sentence"))
      )
    )
    
    server <- function(input, output) {
      corpus <- reactive({
        corpusFile <- input$fileInput
        if(is.null(corpusFile)) {
          return(readCorpus('data/news.txt'))
        } else {
          return(readCorpus(corpusFile$datapath))
        }
      })
    
      values <- reactiveValues(current = 1)
      observe({
        values$corpus <- corpus()
      })
      output$sentence <- renderText(values$corpus[values$current])
    
      observeEvent(input$Next,{
        if(values$current >=1 & values$current < length(corpus())) {
          values$current <- values$current + 1
        }
      })
      observeEvent(input$Previous,{
        if(values$current > 1 & values$current <= length(corpus())) {
          values$current <- values$current - 1
        }
      })
      observeEvent(input$mark,{
        values$corpus[values$current] <- input$textresult
      })
      output$save <- downloadHandler(filename = "marked_corpus.txt",
                                     content = function(file) {
    
                                       writeLines(text = values$corpus,
                                                  con = file,
                                                  sep = "\n")
                                     })
    }