Can vanilla JS/TS in a Quarto doc be monitored (reacted to) in OJS like an OJS value? #6415
-
DescriptionHey folks! Got a bit of an OJS deep dive that I wanted to throw to the community and team before I went too deep on it. @andrewpbray and I are working on a Quarto extension in which we have an injected JS dependency (which is available as a global in the doc). That extension includes an initialiser function that we'd like to wrap. What I would love is if that initialiser returned an object with fields that could be reacted to in OJS. For example, say my regular JS function returned an object like this: let extensionState = {
x: 2
} I would like to be able to then have a user write an OJS cell like: // generate x random numbers between 0 and 1 whenever extensionState.x changes
myArray = [...Array(extensionState.x).keys()].map(x => Math.random()) And have In short, I suppose I want to create an object in JS (or TS maybe?) whose fields can act like Observable cells, having a value that can be monitored. I've seen and done examples of writing your own viewofs inside Observable (eg. writing a cell that yields and then updates its |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
I'm hoping that something of the OJS runtime might be available for me to register an OJS value outside OJS! |
Beta Was this translation helpful? Give feedback.
-
Unfortunately I am not that familiar with Observable and how it can interact with pure JavaScript. |
Beta Was this translation helpful? Give feedback.
-
Got this to a state where I think it works for my use case! 🥳 Code: https://jimjam-slam.github.io/quarto-experiments/inject-variable/ ✅ Was able to define a variable as a constant, then repeatedly redefine it as a new constant (eg. here, using Here's essentially what I did in an ```{=html}
<script>
// wait 'til dom content is loaded before trying to touch the ojs module
addEventListener("DOMContentLoaded", (event) => {
// check for the ojs connector's presence first
const ojsModule = window._ojs?.ojsConnector?.mainModule
if (ojsModule === undefined) {
console.error("Quarto OJS module not found")
} else {
console.log("Quarto OJS module found!")
}
// let's try calling variable.define() on the timer instead
const anotherVar = ojsModule.variable();
anotherVar.define("anotherVar", 23);
// every second, redefine the variable to be a new random number
setInterval(() => {
anotherVar.define("anotherVar", Math.random());
}, 1000);
});
</script>
``` Then, in OJS (wither a chunk or inline):
|
Beta Was this translation helpful? Give feedback.
Got this to a state where I think it works for my use case! 🥳
Code: https://jimjam-slam.github.io/quarto-experiments/inject-variable/
Rendered: https://jimjam-slam.github.io/quarto-experiments/inject-variable/
✅ Was able to define a variable as a constant, then repeatedly redefine it as a new constant (eg. here, using
Promises.delay
to set it to a new random constant every second)❌ Didn't work out how to set a variable to a generator function (as I would if I was writing directly in OJS), but given I need to give a callback to a JS framework and have that callback update the variable, I don't think this approach makes too much sense anyway.
Here's essentially what I did in an
{=html}
block: