mirror of
https://github.com/rstudio/shiny.git
synced 2026-04-07 03:00:20 -04:00
Change {immediate: ...} to {priority: "deferred|immediate|event"}
This was the product of a long discussion between @wch, @alandipert, @bborgesr
and myself. The conflation of immediate (no throttle/debounce) and non-dedupe
in a single "immediate" flag was deemed unacceptable, because UI controls often
want immediacy but also dedupe. Introducing a second "dedupe" flag would work
but {immediate: false, dedupe: false} doesn't make much sense, and dedupe not
only implies that InputNoResendDecorator should behave differently but also
InputBatchSender (i.e. no deduplication AND no coalescing).
We decided to remove the "immediate" boolean option and replace it with a
string option that would have three possibilities at this time. The only con
to this approach is if anyone is calling onInputChange with immediate:true
today, and I can't imagine anyone is. The immediate flag only has any effect
if the input id that's being set has been put in debounce/throttle mode, and
I don't even think that is documented today, and I'm not even sure it's
possible to do it from custom JS (that's not part of a custom input binding).
This commit is contained in:
@@ -766,7 +766,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
this.pendingData[name] = value;
|
||||
|
||||
if (!this.reentrant) {
|
||||
if (opts.immediate) {
|
||||
if (opts.priority === "event") {
|
||||
this.$sendNow();
|
||||
} else if (!this.timerId) {
|
||||
this.timerId = setTimeout(this.$sendNow.bind(this), 0);
|
||||
@@ -807,7 +807,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
|
||||
var jsonValue = JSON.stringify(value);
|
||||
|
||||
if (!opts.immediate && this.lastSentValues[inputName] && this.lastSentValues[inputName].jsonValue === jsonValue && this.lastSentValues[inputName].inputType === inputType) {
|
||||
if (opts.priority !== "event" && this.lastSentValues[inputName] && this.lastSentValues[inputName].jsonValue === jsonValue && this.lastSentValues[inputName].inputType === inputType) {
|
||||
return;
|
||||
}
|
||||
this.lastSentValues[inputName] = { jsonValue: jsonValue, inputType: inputType };
|
||||
@@ -854,7 +854,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
evt.value = value;
|
||||
evt.binding = opts.binding;
|
||||
evt.el = opts.el;
|
||||
evt.immediate = opts.immediate;
|
||||
evt.priority = opts.priority;
|
||||
|
||||
$(document).trigger(evt);
|
||||
|
||||
@@ -862,9 +862,9 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
name = evt.name;
|
||||
if (evt.inputType !== '') name += ':' + evt.inputType;
|
||||
|
||||
// opts aren't passed along to lower levels in the input decorator
|
||||
// Most opts aren't passed along to lower levels in the input decorator
|
||||
// stack.
|
||||
this.target.setInput(name, evt.value, { immediate: opts.immediate });
|
||||
this.target.setInput(name, evt.value, { priority: opts.priority });
|
||||
}
|
||||
};
|
||||
}).call(InputEventDecorator.prototype);
|
||||
@@ -877,7 +877,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
this.setInput = function (name, value, opts) {
|
||||
this.$ensureInit(name);
|
||||
|
||||
if (opts.immediate) this.inputRatePolicies[name].immediateCall(name, value, opts);else this.inputRatePolicies[name].normalCall(name, value, opts);
|
||||
if (opts.priority !== "deferred") this.inputRatePolicies[name].immediateCall(name, value, opts);else this.inputRatePolicies[name].normalCall(name, value, opts);
|
||||
};
|
||||
this.setRatePolicy = function (name, mode, millis) {
|
||||
if (mode === 'direct') {
|
||||
@@ -929,11 +929,25 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
|
||||
// Merge opts with defaults, and return a new object.
|
||||
function addDefaultInputOpts(opts) {
|
||||
return $.extend({
|
||||
immediate: false,
|
||||
|
||||
opts = $.extend({
|
||||
priority: "immediate",
|
||||
binding: null,
|
||||
el: null
|
||||
}, opts);
|
||||
|
||||
if (opts && typeof opts.priority !== "undefined") {
|
||||
switch (opts.priority) {
|
||||
case "deferred":
|
||||
case "immediate":
|
||||
case "event":
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unexpected input value mode: '" + opts.priority + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
function splitInputNameType(name) {
|
||||
@@ -6072,7 +6086,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
|
||||
inputs = new InputValidateDecorator(inputs);
|
||||
|
||||
exports.onInputChange = function (name, value, opts) {
|
||||
exports.setInputValue = exports.onInputChange = function (name, value, opts) {
|
||||
opts = addDefaultInputOpts(opts);
|
||||
inputs.setInput(name, value, opts);
|
||||
};
|
||||
@@ -6086,7 +6100,11 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
||||
var type = binding.getType(el);
|
||||
if (type) id = id + ":" + type;
|
||||
|
||||
var opts = { immediate: !allowDeferred, binding: binding, el: el };
|
||||
var opts = {
|
||||
priority: allowDeferred ? "deferred" : "immediate",
|
||||
binding: binding,
|
||||
el: el
|
||||
};
|
||||
inputs.setInput(id, value, opts);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
6
inst/www/shared/shiny.min.js
vendored
6
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -101,7 +101,7 @@ function initShiny() {
|
||||
|
||||
inputs = new InputValidateDecorator(inputs);
|
||||
|
||||
exports.onInputChange = function(name, value, opts) {
|
||||
exports.setInputValue = exports.onInputChange = function(name, value, opts) {
|
||||
opts = addDefaultInputOpts(opts);
|
||||
inputs.setInput(name, value, opts);
|
||||
};
|
||||
@@ -116,7 +116,11 @@ function initShiny() {
|
||||
if (type)
|
||||
id = id + ":" + type;
|
||||
|
||||
let opts = { immediate: !allowDeferred, binding: binding, el: el };
|
||||
let opts = {
|
||||
priority: allowDeferred ? "deferred" : "immediate",
|
||||
binding: binding,
|
||||
el: el
|
||||
};
|
||||
inputs.setInput(id, value, opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ var InputBatchSender = function(shinyapp) {
|
||||
this.pendingData[name] = value;
|
||||
|
||||
if (!this.reentrant) {
|
||||
if (opts.immediate) {
|
||||
if (opts.priority === "event") {
|
||||
this.$sendNow();
|
||||
} else if (!this.timerId) {
|
||||
this.timerId = setTimeout(this.$sendNow.bind(this), 0);
|
||||
@@ -231,7 +231,7 @@ var InputNoResendDecorator = function(target, initialValues) {
|
||||
const { name: inputName, inputType: inputType } = splitInputNameType(name);
|
||||
const jsonValue = JSON.stringify(value);
|
||||
|
||||
if (!opts.immediate &&
|
||||
if (opts.priority !== "event" &&
|
||||
this.lastSentValues[inputName] &&
|
||||
this.lastSentValues[inputName].jsonValue === jsonValue &&
|
||||
this.lastSentValues[inputName].inputType === inputType) {
|
||||
@@ -276,7 +276,7 @@ var InputEventDecorator = function(target) {
|
||||
evt.value = value;
|
||||
evt.binding = opts.binding;
|
||||
evt.el = opts.el;
|
||||
evt.immediate = opts.immediate;
|
||||
evt.priority = opts.priority;
|
||||
|
||||
$(document).trigger(evt);
|
||||
|
||||
@@ -284,9 +284,9 @@ var InputEventDecorator = function(target) {
|
||||
name = evt.name;
|
||||
if (evt.inputType !== '') name += ':' + evt.inputType;
|
||||
|
||||
// opts aren't passed along to lower levels in the input decorator
|
||||
// Most opts aren't passed along to lower levels in the input decorator
|
||||
// stack.
|
||||
this.target.setInput(name, evt.value, { immediate: opts.immediate });
|
||||
this.target.setInput(name, evt.value, { priority: opts.priority });
|
||||
}
|
||||
};
|
||||
}).call(InputEventDecorator.prototype);
|
||||
@@ -300,7 +300,7 @@ var InputRateDecorator = function(target) {
|
||||
this.setInput = function(name, value, opts) {
|
||||
this.$ensureInit(name);
|
||||
|
||||
if (opts.immediate)
|
||||
if (opts.priority !== "deferred")
|
||||
this.inputRatePolicies[name].immediateCall(name, value, opts);
|
||||
else
|
||||
this.inputRatePolicies[name].normalCall(name, value, opts);
|
||||
@@ -365,11 +365,25 @@ const InputValidateDecorator = function(target) {
|
||||
|
||||
// Merge opts with defaults, and return a new object.
|
||||
function addDefaultInputOpts(opts) {
|
||||
return $.extend({
|
||||
immediate: false,
|
||||
|
||||
opts = $.extend({
|
||||
priority: "immediate",
|
||||
binding: null,
|
||||
el: null
|
||||
}, opts);
|
||||
|
||||
if (opts && typeof(opts.priority) !== "undefined") {
|
||||
switch (opts.priority) {
|
||||
case "deferred":
|
||||
case "immediate":
|
||||
case "event":
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unexpected input value mode: '" + opts.priority + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user