From 639b520d397d0695d767e12bcc0934f01e7a771c Mon Sep 17 00:00:00 2001 From: Timothy Mastny Date: Thu, 14 Jun 2018 11:01:14 -0500 Subject: [PATCH] updateInputSlider can now change from date to date-time formatting. fixes #2019 --- R/update-input.R | 22 ++++++++-- man/updateSliderInput.Rd | 11 +++-- srcjs/input_binding_slider.js | 82 +++++++++++++++++++++-------------- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/R/update-input.R b/R/update-input.R index ed987051d..f75bb01c0 100644 --- a/R/update-input.R +++ b/R/update-input.R @@ -383,13 +383,17 @@ updateNumericInput <- function(session, inputId, label = NULL, value = NULL, session$sendInputMessage(inputId, message) } -#' Change the value of a slider input on the client +#' Update Slider Input Widget +#' +#' Change the value of a slider input on the client. #' #' @template update-input #' @param value The value to set for the input object. #' @param min Minimum value. #' @param max Maximum value. #' @param step Step size. +#' @param timeFormat Date and POSIXt formatting. +#' @param timezone The timezone offset for POSIXt objects. #' #' @seealso \code{\link{sliderInput}} #' @@ -422,7 +426,7 @@ updateNumericInput <- function(session, inputId, label = NULL, value = NULL, #' } #' @export updateSliderInput <- function(session, inputId, label = NULL, value = NULL, - min = NULL, max = NULL, step = NULL) + min = NULL, max = NULL, step = NULL, timeFormat = NULL, timezone = NULL) { # Make sure that value, min, max all have the same type, because we need # special handling for dates and datetimes. @@ -444,12 +448,24 @@ updateSliderInput <- function(session, inputId, label = NULL, value = NULL, if (!is.null(value)) value <- to_ms(value) } + if (is.null(timeFormat)) { + if (type[[1]] == "date") { + timeFormat <- "%F" + } else if (type[[1]] == "datetime") { + timeFormat <- "%F %T" + } + } + + message <- dropNulls(list( label = label, value = formatNoSci(value), min = formatNoSci(min), max = formatNoSci(max), - step = formatNoSci(step) + step = formatNoSci(step), + `data-type` = type[[1]], + `time-format` = timeFormat, + timezone = timezone )) session$sendInputMessage(inputId, message) } diff --git a/man/updateSliderInput.Rd b/man/updateSliderInput.Rd index 9ce463e5f..46d2e62de 100644 --- a/man/updateSliderInput.Rd +++ b/man/updateSliderInput.Rd @@ -2,10 +2,11 @@ % Please edit documentation in R/update-input.R \name{updateSliderInput} \alias{updateSliderInput} -\title{Change the value of a slider input on the client} +\title{Update Slider Input Widget} \usage{ updateSliderInput(session, inputId, label = NULL, value = NULL, - min = NULL, max = NULL, step = NULL) + min = NULL, max = NULL, step = NULL, timeFormat = NULL, + timezone = NULL) } \arguments{ \item{session}{The \code{session} object passed to function given to @@ -22,9 +23,13 @@ updateSliderInput(session, inputId, label = NULL, value = NULL, \item{max}{Maximum value.} \item{step}{Step size.} + +\item{timeFormat}{Date and POSIXt formatting.} + +\item{timezone}{The timezone offset for POSIXt objects.} } \description{ -Change the value of a slider input on the client +Change the value of a slider input on the client. } \details{ The input updater functions send a message to the client, telling it to diff --git a/srcjs/input_binding_slider.js b/srcjs/input_binding_slider.js index 57e663431..73171e7a0 100644 --- a/srcjs/input_binding_slider.js +++ b/srcjs/input_binding_slider.js @@ -6,6 +6,38 @@ function forceIonSliderUpdate(slider) { console.log("Couldn't force ion slider to update"); } +function getTypePrettifyer(dataType, timeFormat, timezone) { + var timeFormatter; + var prettify; + if (dataType === 'date') { + timeFormatter = strftime.utc(); + prettify = function(num) { + return timeFormatter(timeFormat, new Date(num)); + }; + + } else if (dataType === 'datetime') { + if (timezone) + timeFormatter = strftime.timezone(timezone); + else + timeFormatter = strftime; + + prettify = function(num) { + return timeFormatter(timeFormat, new Date(num)); + }; + + } else { + // The default prettify function for ion.rangeSlider adds thousands + // separators after the decimal mark, so we have our own version here. + // (#1958) + prettify = function(num) { + // When executed, `this` will refer to the `IonRangeSlider.options` + // object. + return formatNumber(num, this.prettify_separator); + }; + } + return prettify; +} + var sliderInputBinding = {}; $.extend(sliderInputBinding, textInputBinding, { find: function(scope) { @@ -90,13 +122,26 @@ $.extend(sliderInputBinding, textInputBinding, { msg.from = data.value; } } - if (data.hasOwnProperty('min')) msg.min = data.min; - if (data.hasOwnProperty('max')) msg.max = data.max; - if (data.hasOwnProperty('step')) msg.step = data.step; + var sliderFeatures = ['min', 'max', 'step']; + for (var feats of sliderFeatures) { + if (data.hasOwnProperty(feats)) msg[feats] = data[feats]; + } if (data.hasOwnProperty('label')) $el.parent().find('label[for="' + $escape(el.id) + '"]').text(data.label); + var domElements = ['data-type', 'time-format', 'timezone']; + for (var elm of domElements) { + if (data.hasOwnProperty(elm)) + $el.data(elm, data[elm]); + } + + var dataType = $el.data('data-type'); + var timeFormat = $el.data('time-format'); + var timezone = $el.data('timezone'); + + msg.prettify = getTypePrettifyer(dataType, timeFormat, timezone); + $el.data('immediate', true); try { slider.update(msg); @@ -118,36 +163,9 @@ $.extend(sliderInputBinding, textInputBinding, { var $el = $(el); var dataType = $el.data('data-type'); var timeFormat = $el.data('time-format'); - var timeFormatter; + var timezone = $el.data('timezone'); - // Set up formatting functions - if (dataType === 'date') { - timeFormatter = strftime.utc(); - opts.prettify = function(num) { - return timeFormatter(timeFormat, new Date(num)); - }; - - } else if (dataType === 'datetime') { - var timezone = $el.data('timezone'); - if (timezone) - timeFormatter = strftime.timezone(timezone); - else - timeFormatter = strftime; - - opts.prettify = function(num) { - return timeFormatter(timeFormat, new Date(num)); - }; - - } else { - // The default prettify function for ion.rangeSlider adds thousands - // separators after the decimal mark, so we have our own version here. - // (#1958) - opts.prettify = function(num) { - // When executed, `this` will refer to the `IonRangeSlider.options` - // object. - return formatNumber(num, this.prettify_separator); - }; - } + opts.prettify = getTypePrettifyer(dataType, timeFormat, timezone); $el.ionRangeSlider(opts); },