当x = 0时执行Math.pow(10,x)时,使用JavaScript更改R Shiny错误中的noUIslider标签 [英] Using javascript to alter noUIslider tags in R Shiny error when performing Math.pow(10,x) when x = 0

查看:95
本文介绍了当x = 0时执行Math.pow(10,x)时,使用JavaScript更改R Shiny错误中的noUIslider标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在先前的SO问题中

In an earlier SO question here I have come to a point where I have a noUiSliderInput that gets it's labels updated to a scientific notation format with the help of javascript.

剩下的问题是,当输入为0时noUiSliderInput会跳到10,因此它应该跳到1.(10 ^ 0是1,而不是10).我怀疑是Math.pow(10,x)的问题,但我不确定

The remaining problem is that the noUiSliderInput jumps to 10 when the input is 0 and it therefore should jump to 1. (10^0 is 1, not 10). I suspect a problem with Math.pow(10,x) is the cause but I am not sure

更新: 通过更改javascript代码已解决了滑块跳转到最大值的最初问题,该代码现在将shiny中的值用作滑块的min,max和value的输入. 我已在问题中更改了应用程序的代码以表示当前情况.

UPDATE: The initial problem of the slider jumping to the maximum value has been fixed by changing the javascript code, which now takes values from shiny as input for the min, max and value of the slider. I have changed the code of the app here in the question to represent the current situation.

#END UPDATE#

这里的行为是通过使用第二个sliderInputnumericInput框模拟的,该框会导致noUiSliderInput所需的所有三个值都改变

The behavior is simulated here with the use of a second sliderInput and numericInput boxes that causes all three values needed for the noUiSliderInput to cahange

在我的实际app中,noUiSliderInput链接到plot,并且用户选择的任何数据column都链接到plot.因此,用户选择绘制的任何数据将需要noUiSliderInputupdate,即range. slider也链接到具有较早创建的设置的datatable(数据中某些列的阈值的数据表),并且当用户单击datatable条目时,它会update向下选择将要绘制的数据(以及noUiSliderInput range)以及阈值(noUiSliderInput value)应基于datatable中的值的高度.

In my real app the noUiSliderInput is linked to a plot, and whatever data column the user chooses to plot. So, whatever data the user chooses to plot will require the noUiSliderInput to update it's range. The slider is also linked to a datatable with earlier created settings (a datatable of threshold values for some of the columns in the data), and when the user clicks a datatable entry, it will update the drop down that selects which data is to be plotted (and thus the noUiSliderInput range), as well as at what height the threshold (noUiSliderInput value) should be based on the value in the datatable.

这一次触发三个变化,即范围(即noUiSliderInput的最小值和最大值)以及noUiSliderInput的值.

This fires three changes at once, range (i.e. min & max of noUiSliderInput), as well as value of the noUiSliderInput.

我设法得到了一个模拟该行为的虚拟app,除了noUiSliderInputvalue被当前的javascript似乎错误地更新了.

I managed to get a dummy app that simulates this behavior working, except the value of the noUiSliderInput gets updated wrong by the current javascript it seems.

示意图大致如下所示

The schematic looks like this roughly

在这里您可以看到单击table会将值发送到noUiSliderInput值,并将参数名称发送给参数selectInput,然后获取数据并将其发送到plot,并将最小值,最大值:range发送到noUiSliderInput. 之所以这样构建,是因为用户还可以直接从selectInput中选择参数(columns)(其中许多不在阈值表中)

Where you can see that clicking on the table will send a value to the noUiSliderInput value, and a parameter name to the parameter selectInput, which then gets the data, sends it to the plot, and send the min, max: range to the noUiSliderInput. It is build this way because the user can also select parameters (columns) from the selectInput directly (many of which are not in the table of thresholds)

到目前为止的应用程序:

library(shiny)
library(shinyWidgets)
library(shinyjs)

js <- function(Min, Max, Start){
  sprintf(paste(
    "var slider = document.getElementById('Histoslider').noUiSlider;",
    "slider.updateOptions({",
    "  start: %s,",
    "  range: {min: %s, max: %s},",
    "  format: wNumb({", 
    "    encoder: function(x){return parseFloat(Math.pow(10,x));}", 
    "  })", 
    "});",
    "var pipsValues = $('.noUi-value');",
    "pipsValues.each(function(){$(this).html('10<sup>'+$(this).attr('data-value')+'</sup>')});",
    sep = "\n"
  ), Start, Min, Max)
}

ui <- fluidPage(
  useShinyjs(),
  tags$br(),
  fluidRow(
    column(4,
           uiOutput('TestSliderOut'), 
           actionButton(inputId = "UpdateSlider", label = 'Update')
    ),
    column(6, 
           sliderInput("slider2", label = NULL, min = -5, max = 20, value= c(1, 5), step = 1),
           numericInput(inputId = 'SlMin', label = 'Min', value = 1, min = -5, max = 20),
           numericInput(inputId = 'SlMax', label = 'Max', value = 5, min = -5, max = 20),
           numericInput(inputId = 'SlVal', label = 'Val', value = 3, min = -5, max = 20),
           br(),
           h5('Update counter'),
           verbatimTextOutput(outputId = "updates"),
           h5('slider value'),
           verbatimTextOutput(outputId = 'ouputval')
    )
  )
)



server <- function(input, output, session) {

  values <- reactiveValues( Counter = 0)

  output$TestSliderOut <- renderUI({
    noUiSliderInput(
      inputId = "Histoslider", label = "Slider vertical:",
      min = -2, max = 4, step = 0.01,
      value = 0, margin = 100, 
      pips = list(mode="range", density=2),
      orientation = "vertical", 
      width = "300px", height = "300px",   direction = "rtl", 
      behaviour = "tap"
    )
  })

  observeEvent(input$slider2, {
    ## simulates the change of multipe parameters of the slider: min, max, value
    newvalue <- (input$slider2[2]-input$slider2[1])/2+input$slider2[1]
    updateNumericInput(session, inputId = 'SlMin', value = input$slider2[1])
    updateNumericInput(session, inputId = 'SlMax', value = input$slider2[2])
    updateNumericInput(session, inputId = 'SlVal', value = newvalue)

  })

  observe({
    updateNoUiSliderInput(session, inputId = 'Histoslider', range = c(input$SlMin, input$SlMax), value = input$SlVal)
    shinyjs::delay(1, {  ## delay the javascript so that it runs after the slider has updated its values
      runjs(js(input$SlMin, input$SlMax, input$SlVal))     })
  })

  output$updates <- renderPrint(values$Counter)


  output$ouputval <- renderPrint(input$Histoslider)

  observeEvent(input$SlMin, { values$nouiMin <- input$SlMin })
  observeEvent(input$SlMax, { values$nouiMax <- input$SlMax })
  observeEvent(input$SlVal, { values$nouiVal <- input$SlVal })

  observeEvent(input$Histoslider, {
    print('changing code')
    runjs(js(values$nouiMin, values$nouiMax, values$nouiVal))     ## fires ones on first build of the slider
  }, once = TRUE)

}

shinyApp(ui, server)

推荐答案

嗯,看起来确实很奇怪.似乎可以通过使用set方法(设置滑块的值)而不是更新start选项来工作:

Hmm that does look strange. It seems to work by using the set method (set the value of the slider) instead of updating the start option:

js <- function(Min, Max, Start){
  sprintf(paste(
    "var slider = document.getElementById('Histoslider').noUiSlider;",
    "slider.updateOptions({",
    "  range: {min: %s, max: %s},",
    "  format: wNumb({", 
    "    decimals: 2,",
    "    encoder: function(x){return parseFloat(Math.pow(10,x));}", 
    "  })", 
    "});",
    "slider.set(%s);",
    "var pipsValues = $('.noUi-value');",
    "pipsValues.each(function(){$(this).html('10<sup>'+$(this).attr('data-value')+'</sup>')});",
    sep = "\n"
  ), Min, Max, Start)
}

请注意,代码中的updateNoUiSliderInput是无用的,因为滑块是由JS代码更新的.因此,替换

Note that the updateNoUiSliderInput in your code is useless, because the slider is updated by the JS code. So replace

  observe({
    updateNoUiSliderInput(session, inputId = 'Histoslider', range = c(input$SlMin, input$SlMax), value = input$SlVal)
    shinyjs::delay(1, {  ## delay the javascript so that it runs after the slider has updated its values
      runjs(js(input$SlMin, input$SlMax, input$SlVal))     })
  })

使用

  observeEvent(list(input$SlMin, input$SlMax, input$SlVal), {
      runjs(js(input$SlMin, input$SlMax, input$SlVal))     
  }, ignoreInit = TRUE)

这篇关于当x = 0时执行Math.pow(10,x)时,使用JavaScript更改R Shiny错误中的noUIslider标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆