I have a Mathematica notebook that employs a fairly complicated user interface for controlling a long-running calculation. Among other things, the interface takes liberal advantage of Button, RadioButtonBar, Checkbox, and InputField.
When the effect of clicking a Button is an intermediate calculation that may take more than a couple seconds to complete, I like to provide a visual indication that the code hasn't crashed and is, in fact, doing something useful. A good way to do this is to start up a ProgressIndicator just before the intermediate calculation starts and then turn it off once the calculation is done. I have found this to be straightforward for calculations started by a Button click.
The same method does not work, however, for calculations that are initiated by changes to an InputField value. The simplified code below was written to do this but fails. The last two rows of the Grid are supposed to change automatically when updatingQ changes to True in the inner Dynamic command and then change back when updatingQ reverts to True, but it never happens. It appears that the outer Dynamic code is being blocked while the inner Dynamic code runs so it never even notices the changes to updatingQ.
On the other hand, the last two lines of the Grid respond as expected if one manually sets updatingQ=True on a separate input line.
(BTW, i) Pause[2] is just a stand-in for the intermediate calculation and ii) I multiply the input value by Pi is just to make it more obvious when the stand-in calculation is done.)
Apparently, the action portion of a Button behaves differently. Other pieces of code within the same Dynamic block can see and quickly respond when flags are changed there. It may be notable that I use Method->"Queued" in such cases. I tried the same with InputField (for which it is not a documented option) but to no effect.
I've tried various other things not shown here also without success.
A way to make this work would be much appreciated.
Clear[ProgressIndicatorTest]
updatingQ = False;
ProgressIndicatorTest = {
TextCell["ProgressIndicatorTest", "Subsubsection", Background -> LightBlue],
DynamicModule[
{filterTypes = {"Max energy", "Max length"}, filterValue, workingOn = "", iter = 0},
Scan[(filterValue[#[[1]]] = #[[2]]) &, Transpose#{filterTypes, {0.1, 100.}}];
Dynamic[
Grid[
Join[
Map[
Function[
filterType,
{filterType,
Dynamic#
InputField[
Dynamic[
filterValue[filterType],
Function[
value,
If[value > 0,
updatingQ = True;
Pause[2];
filterValue[filterType] = \[Pi] value;
updatingQ = False
]
]
], FieldSize -> 5, Alignment -> Right
]
}
], filterTypes
],
{{updatingQ, "-------"}},
{If[updatingQ,
{"Updating ... ",
ProgressIndicator[Appearance -> "Indeterminate"]},
Nothing
]}
], Alignment -> Left,
Background -> {None, {LightGreen, LightGreen, LightYellow, LightYellow}}
]
]
]
};
CellGroup[ProgressIndicatorTest]
As Forrest Gump never said, "Stackoverflow/Stackexchange is like a box of chocolates ... you never know what you'll get". And so today I found this answer which solves my problem.
Adapted to my particular case, the resulting code is as follows:
Clear[ProgressIndicatorTest]
calculation[n_] := Module[{a = .3}, Do[a = a (1 - a), {i, n 10^6}]]
updatingQ = False;
ProgressIndicatorTest = {
TextCell["ProgressIndicatorTest", "Subsubsection", Background -> LightBlue],
DynamicModule[{filterTypes = {"Max energy", "Max length"}, filterValue, upToDateQ = True},
Scan[(filterValue[#[[1]]] = #[[2]]) &, Transpose#{filterTypes, {0.1, 100.}}];
Dynamic[
Grid[
Join[
Map[
Function[
filterType,
{filterType,
DynamicWrapper[
InputField[
Dynamic[
filterValue[filterType],
Function[
value,
If[value > 0,
upToDateQ = False;
filterValue[filterType] = value
]
]
], FieldSize -> 5, Alignment -> Right
],
If[! upToDateQ,
Refresh[
updatingQ = True; calculation[2]; updatingQ = False;
upToDateQ = True,
None
]
],
SynchronousUpdating -> False
]
}
], filterTypes
],
{
If[updatingQ,
{"Updating ... ",
ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 80]},
Nothing
]
}
], Alignment -> Left,
Background -> {None, {LightGreen, LightGreen, LightYellow,}}]
]]
};
CellGroup[ProgressIndicatorTest]
This code does exactly what I want.
The key to success is wrapping DynamicWrapper around InputField and inserting a cleverly constructed second argument that performs the flag reset (upToDate=False in my case) that triggers the ProgressIndicator located elsewhere.
A couple more points.
Pause turns out not to be a good stand-in for a calculation. You may observe that the code behaves differently with a real function such as calculation.
It is interesting to note that upToDateQ can be a local variable whereas updatingQ cannot.
Kudos to Albert Retey for providing the code back in 2013.
The documentation for InputField says
"An InputField of type Expression [the default] replaces its
contents with the fully evaluated form every time the contents are
updated".
This seems to mean that InputField privately evaluates its content and all connected dynamics before releasing value changes, probably to prevent circular evaluations.
The following example condenses the problem. The first part works ok ...
changed = processing = False;
Column[{InputField[Dynamic[x, (changed = True; x = 2 #) &], FieldSize -> 5],
Dynamic[changed],
Dynamic[processing]}]
... until the dynamic below is also evaluated. Then changed never shows True because it is changed back to False before the update concludes.
Dynamic[If[changed,
processing = True;
Pause[2];
changed = processing = False]]
A alternative strategy would be to use a Button, e.g.
changed = False;
processing = Spacer[0];
Column[{InputField[Dynamic[y, (changed = True; y = #) &], FieldSize -> 5],
Button["Enter",
If[changed,
processing = ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 120];
Pause[2];
y = 2 y;
changed = False;
processing = Spacer[0]], Method -> "Queued", Enabled -> Dynamic[changed]],
Dynamic[changed],
Dynamic[processing]}]
This shorter version avoids the need to tab out of the input field.
changed = False;
processing = Spacer[0];
Column[{InputField[Dynamic[y], FieldSize -> 5],
Button["Enter",
processing = ProgressIndicator[Appearance -> "Indeterminate", ImageSize -> 120];
Pause[2];
y = 2 y;
processing = Spacer[0], Method -> "Queued"], Dynamic[processing]}]
Note the use of Method -> "Queued" gives Button the advantage over InputField. Without it Button appears to have the same problem.
Hi i am trying to pluralize based on https://kazupon.github.io/vue-i18n/guide/pluralization.html
imageCount== 1
? $t("message.imageMessage", 1, { imageCount})
: $t("message.imageMessage", imageCount, {
imageCount
})
imageMessage: '{imageCount} image downloaded | {imageCount} images downloaded'
Problem : currently it is displaying bo the messages which should not happen,is there anything wrong in the way which i have implemented?
Codesandbox: https://codesandbox.io/s/lingering-haze-z9jzt?file=/src/components/HelloWorld.vue
From the documentation...
Your template will need to use $tc() instead of $t().
You can also improve / shorten your code somewhat by using {n} or {count} in your translation strings...
en: {
message: {
imageMessage: "{n} image downloaded | {n} images downloaded"
}
}
and in your templates
$tc("message.imageMessage", imageCount)
With vue#3 and vue-i18n#9 and Composition API, with locale key being:
{
message: {
imageMessage: "no images | 1 image downloaded | {n} images downloaded"
}
}
It's enough to do:
$t('message.imageMessage', { n: images.length })
// OR
$t('message.imageMessage', images.length)
I am trying to get Core Motion data from an Apple Watch 3 (WatchOS 5.1) but although the DeviceMotion is available (isDeviceMotionAvailable property is true), the handler is never triggered. I get the following message in the console right after parsing super.willActivate():
[Gyro] Manually set gyro-interrupt-calibration to 800
I am using the following function to get Device Motion updates:
func startQueuedUpdates() {
if motion.isDeviceMotionAvailable {
self.motion.deviceMotionUpdateInterval = 1.0 / 100.0
self.motion.showsDeviceMovementDisplay = true
self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical, to: self.queue, withHandler:{
(data, error) in
// Make sure the data is valid before accessing it.
if let validData = data {
print(String(validData.userAcceleration.x))
}
})
}
}
In the InterfaceController I have declared
let motion = CMMotionManager()
let queue : OperationQueue = OperationQueue.main
Has anyone met this message before and managed to resolve it?
Note: I have checked the isGyroAvailable property and it is false.
The trick here is to match the startDeviceMotionUpdates(using: CMAttitudeReferenceFrame parameter to your device's capabilities. If it has no magnetometer, it cannot relate to magnetic north, and even if it has a magnetometer, it cannot relate to true north unless it knows where you are (i.e. has latitude & longitude). If it hasn't got the capabilities to comply with the parameter you select, the update will be called, but the data will be nil.
If you start it up with the minimum .xArbitraryZVertical you will get updates from the accelerometer, but you won't get a meaningful heading, just a relative one, through the CMDeviceMotion.attitude property ...
if motion.isDeviceMotionAvailable {
print("Motion available")
print(motion.isGyroAvailable ? "Gyro available" : "Gyro NOT available")
print(motion.isAccelerometerAvailable ? "Accel available" : "Accel NOT available")
print(motion.isMagnetometerAvailable ? "Mag available" : "Mag NOT available")
motion.deviceMotionUpdateInterval = 1.0 / 60.0
motion.showsDeviceMovementDisplay = true
motion.startDeviceMotionUpdates(using: .xArbitraryZVertical) // *******
// Configure a timer to fetch the motion data.
self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
if let data = self.motion.deviceMotion {
print(data.attitude.yaw)
}
}
}
I am using bootstrap-treeview 1.2.0 (from Jon Miles).
My goal is to add custom data-attributes to my list items' markup, e.g.
<li class="list-group-item node-tree" data-id="100" data-type="user" ...>
I tried to follow these instructions see here and here is part of my JSON:
[{"text":"Root","icon":null,"data-id":1,"data-type":"branch","nodes":[{"text":"Steve","icon":null,"data-id":17, "data-type":"user","nodes":...
To me the JSON looks good. But none of my data-attributes gets rendered in the markup.
Any ideas?
Sorry, I see it's too late. I searched about this and couldn't find anything. But you can
change bootstrap-treeview.js file a bit. There is some attribute set code in buildTree function. It's looking like this:
Tree.prototype.buildTree = function (nodes, level) {
if (!nodes) return;
level += 1;
var _this = this;
$.each(nodes, function addNodes(id, node) {
var treeItem = $(_this.template.item)
.addClass('node-' + _this.elementId)
.addClass(node.state.checked ? 'node-checked' : '')
.addClass(node.state.disabled ? 'node-disabled': '')
.addClass(node.state.selected ? 'node-selected' : '')
.addClass(node.searchResult ? 'search-result' : '')
.attr('data-nodeid', node.nodeId)
.attr('style', _this.buildStyleOverride(node));
......................SOME CODES ........SOME CODES..........................}
You can add :
.attr('data-type', node.dataType)
.attr('data-id', node.dataId)
And then change the object(json) like this:
[{"text":"Root","icon":null,"dataId":1,"dataType":"branch","nodes":
[{"text":"Steve","icon":null,"dataId":17, "dataType":"user","nodes":...
The link provided simply instructs how to expand the node object with additional properties. There is no correlation between a node's properties and the attributes assigned in HTML.
You might want to do something like this:
var allNodes = $('#tree').treeview('getNodes);
$(allNodes).each(function(index, element) {
$(this.$el[0]).attr('data-attribute-name', this.data-attribute-name);
});
I have a Grid.
Get Data Code
Code:
var myParam = {
typeId : 1,
xxxx : 'xxxx' //some else
}
grid.store.load(myParam);
When to do something such as time renovate
Code:
grid.store.reload();
But this lost param.
In ExtJs3 have a Config of LastParam .
How to do in Extjs4.
thanks.
use the proxy's extraParams config.
grid.store.getProxy().extraParams = myParam;
grid.store.load();
grid.store.reload();
This way the params will be sent until you modify the extra param again with code.