一个闪亮的应用程序可以响应控件而无需进入服务器吗?

时间:2015-09-04 18:07:57

标签: javascript r shiny rgl

我正在htmlwidgets框架内编写一个rgl小部件,以便{1}}场景可以用于Shiny应用程序中的输出。事情基本上是有效的(虽然它仍然很粗糙;请参阅http://R-forge.r-project.org上的rgl包),但它不像rglwidget中已有的原生Javascript控件那样响应。 我怀疑问题是到服务器的往返。

有时候这是不可避免的:如果你想对一个场景进行大的改动,你可能想在R中做很多计算。但在其他情况下(原生控件覆盖的那些),没有必要R参与其中,一切都可以在Javascript中完成。

我不想复制编写Shiny输入控件的所有工作,但我想使用它们。所以我的问题是:

有没有办法告诉Shiny输入在更改时调用Javascript函数,而不是将其值发送到要在Shiny输出中使用的服务器?

1 个答案:

答案 0 :(得分:2)

我的问题的答案是"是"!它实际上相当简单,至少如果控件使用htmlwidgets框架。

警告:我在Javascript方面不是很有经验,所以这可能不是很好的Javascript风格。如果是的话请告诉我,我会改进它。

以下是这样的想法:如果我有一个带有sliderInput()的闪亮inputId = "foo"控件,那么我自己的Javascript代码可以使用window["foo"]来获取它,并且可以设置一个&# 34;平变化"它上面的事件处理程序当触发该事件处理程序时,我可以读取"值"属性,并将其发送到我的控件。

如果我不使用滑块的无功输入,我就不会因为去服务器而感到延迟。

这是我当前为小部件设计的renderValue函数:

renderValue: function(el, x, instance) {
  var applyVals = function() {

    /* We might be running before the scene exists.  If so, it
       will have to apply our initial value. */

      var scene = window[x.sceneId].rglinstance;
      if (typeof scene !== "undefined") {
        scene.applyControls(x.controls);
        instance.initialized = true;
      } else {
        instance.controls = x.controls;
        instance.initialized = false;
      }
    };

  el.rglcontroller = instance;

  if (x.respondTo !== null) {
    var control = window[x.respondTo];
    if (typeof control !== "undefined") {
      var self = this, i, oldhandler = control.onchange;
      control.onchange = function() {
        for (i=0; i<x.controls.length; i++) {
          x.controls[i].value = control.value;
        }
        if (oldhandler !== null)
          oldhandler.call(this);
        applyVals();
      };
      control.onchange();
    }
  }
  applyVals();
},