I got it to work using a couple of tricks. In ui.R,
inputIp <- function(inputId, value=''){
tagList(
singleton(tags$head(tags$script(src = "js/md5.js", type='text/javascript'))),
singleton(tags$head(tags$script(src = "js/shinyBindings.js", type='text/javascript'))),
tags$body(onload="setvalues()"),
tags$input(id = inputId, class = "ipaddr", value=as.character(value), type="text", style="display:none;")
)
}
and then in your shinyUI() call, you just need
inputIp("ipid")
somewhere.
Basically, I created a hidden text input field that the javascript file can write to. Javascript gets the IP address from another service (running PHP, I think). This set of functions is located in another file, which I've named shinyBindings.js. (Remember to put this in the /Appname/www/js/ folder when you deploy your app...)
/*
* Set the uid fingerprint into the DOM elements that need to know about it.
* Do not call before the form loads, or the selectors won't find anything.
*/
var inputIpBinding = new Shiny.InputBinding();
$.extend(inputIpBinding, {
find: function(scope) {
return $.find('.ipaddr');
},
getValue: function(el) {
return $(el).val();
},
setValue: function(el, values) {
$(el).attr("value", getip())
$(el).trigger("change");
},
subscribe: function(el, callback) {
$(el).on("change.inputIpBinding", function(e) {
callback();
});
},
unsubscribe: function(el) {
$(el).off(".inputIpBinding");
}
});
Shiny.inputBindings.register(inputIpBinding);
function getip() {
ip = null;
$.getJSON("http://jsonip.com?callback=?",
function(data){
ip = data.ip;
callback(ip);
$(".ipaddr").attr("value", ip);
$(".ipaddr").trigger("change");
//return ip address correctly
});
//alert(ip); //undefined or null
}
function callback(tempip)
{
ip=tempip;
// alert(ip); //undefined or null
}