# Notification when cell is re-run by the user?

**URL:** <https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414>\
**Category:** Pluto\
**Tags:** pluto, audio\
**Created:** [October 28, 2022, 1:11am UTC](https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414 "2022-10-28T01:11:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [October 28, 2022, 1:11am UTC](https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414/1 "2022-10-28T01:11:31Z")

</div>

I’m playing around a bit with Pluto and web-audio. Right now I’m just creating an oscillator with the frequency controlled by a slider. The code I have to do this is:

```julia
htl"""
<script id="osctest">
const div = this == null ? document.createElement("div") : this
const ctx = this == null ? new AudioContext() : div.ctx
const osc = this == null ? new OscillatorNode(ctx) : div.osc
osc.frequency.setValueAtTime($freq, ctx.currentTime)
if(this == null) {osc.connect(ctx.destination); osc.start()}
// invalidation.then(() => {
// osc.stop()
// ctx.close()
// console.log("invalidated")
// })

div.osc = osc
div.ctx = ctx
return div
</script>
"""

```

This works well, but the problem is that if I re-run the cell, `this` is `null` again so I end up creating a brand new oscillator and context, and now both are playing, rather than replacing the original.

As you can see in the commented section, I tried using the `invalidate` promise, but then realized that it gets called on a value update, not just a user-generated re-run. One solution I think would be to attach the context upstream in the DOM or to a global variable or something, but then it can’t be a re-useable function.

If there were something like `invalidate` that only got triggered on a user update, I could do the cleanup there.

---

<div class="post-metadata">

**Author:** ![disberd](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@disberd](https://discourse.julialang.org/u/disberd)\
**Post date:** [October 29, 2022, 10:06am UTC](https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414/2 "2022-10-29T10:06:55Z")

</div>

@ssfrr

Here is a minimal working example I managed to make work using the [MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)

```julia
@htl """
<script id="osctest">
let div = this ?? document.createElement("div")
if (this == null) {
	div.classList.toggle('oscillator-container',true)
	let id = $(join(rand("abcdefghilmnopqrstuvz",8)))
	div.id = id

	div.ctx = new AudioContext()
	div.osc = new OscillatorNode(div.ctx)
	div.osc.connect(div.ctx.destination); div.osc.start()

	
	const observer = new MutationObserver((entries) => {
		for (const entry of entries) {
			for (const added of entry.addedNodes) {
				if (added instanceof Element && added.classList.contains('oscillator-container') && added.id != id) {
					console.log('Found a manual rerun! Disconnecting...')
					div.osc.stop()
					div.ctx.close()
					observer.disconnect()
				}
			}
		}
	})
	observer.observe(currentScript.closest('div.raw-html-wrapper'), {childList: true})
}
div.osc.frequency.setValueAtTime($freq, div.ctx.currentTime)

return div
</script>
"""

```

The main idea is to assign a unique id to the div you are generating in the script only upon manual re-run (when this == null) and then attach a MutationObserver to the pluto-output wrapper that monitors addition and deletion of children.  
As soon as a new div with the `oscillator-container` class is added and has an id which is different from the one you generated together with the MutationObserver, I assume that a manual rerun has been triggered and I can disconnect everything.

Seems to work, don’t know if there are better ways to achieve this though.

---

<div class="post-metadata">

**Author:** ![j-fu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j-fu/32/11373_2.png) [@j-fu](https://discourse.julialang.org/u/j-fu)\
**Post date:** [October 29, 2022, 7:44pm UTC](https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414/3 "2022-10-29T19:44:22Z")

</div>

Had a similar problem with plotting - wanted to have movable isosurfaces etc. My solution is [here (Julia)](https://github.com/j-fu/PlutoVista.jl/blob/4824c06df8e698a016e82bc24e77b4419d345a35/src/plutovtkplot.jl#L66) and [here (JS)](https://github.com/j-fu/PlutoVista.jl/blob/4824c06df8e698a016e82bc24e77b4419d345a35/assets/plutovtkplot.js#L169).  
Essentially you create a div labeled with an uuid which you can later refer to in the javascript.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [October 30, 2022, 2:11am UTC](https://discourse.julialang.org/t/notification-when-cell-is-re-run-by-the-user/89414/4 "2022-10-30T02:11:19Z")

</div>

Thanks both! @disberd that seems pretty clean.

On the one hand it seems like it might be nice for Pluto to have some built-in support for this kind of thing, but also it probably is only coming up here because of the weird way that the lifetime of WebAudio objects works.
