Pluto notebooks: defining Javascript function in <script> for call by onclick

I’m creating truth tables in a Pluto notebook in html, and want to use javascript/CSS to show result columns when one clicks on the headers, as in this jsfiddle example,
(Note the <th onclick="toggleColumn(2)"> calls to the javascript function toggleColumn(n).)
I can define this function in html"<script>...</script>" in Pluto, but when I inspect the html, I find

<script>{
        window.____FUNCTION_TO_RUN_INSIDE_SCRIPT.result = window.____FUNCTION_TO_RUN_INSIDE_SCRIPT.function_to_run(window.____FUNCTION_TO_RUN_INSIDE_SCRIPT.currentScript)
    }</script>

and clicking fails to find toggleColumn(2). (Console error: Uncaught ReferenceError: toggleColumn is not defined at HTMLTableCellElement.onclick (edit?id=bf519f00-f7c8-11ec-00ac-937614ae1677:1:1))

So my fundamental confusion is what is allowed to be inside the <script> tags for html in Pluto? And where can I find the documentation for that?/
Javascript in Pluto examples I’ve seen all define eventListeners in javascript (rather than html) and use anonymous functions. I think I could do this with a new function for each column, but I am eager to learn how I should think about this to find a better way.

Omitting the Julia to generate the truth table html, how would I get the following html to toggle column visibility when clicking on the column headers, as in the jsfiddle?

Here is a minimal non-working attempt to do this in a Pluto cell using HypertextLiteral.

using HypertextLiteral
htl"""
<div>
<script>
function toggleColumn(n) {
    var div = currentScript.parentElement
    var TT = div.querySelector(".truthtable")
    var currentClass = TT.className;
    if (currentClass.includes("c"+n+"hide")) 
        TT.className = currentClass.replace("c"+n+"hide", "").trim();
    else 
        TT.className += " c"+n+"hide";
}
</script>

<table class="truthtable c1hide c2hide c3hide c4hide"><thead><tr>
	<td onclick="() => (toggleColumn(0);)"><label>p</label></td><td onclick="toggleColumn(0);"><label>q</label></td><th onclick="toggleColumn(1);"><label>p → q</label></th><th onclick="toggleColumn(2);"><label>¬q → ¬p</label></th><th onclick="toggleColumn(3);"><label>q → p</label></th><th onclick="toggleColumn(4);"><label>¬p → ¬q</label></th></tr></thead><tbody><tr><td class="col0" style="background-color:#EEFFEE">T</td><td class="col0" style="background-color:#EEFFEE">T</td><th class="col1" style="background-color:#EEFFEE">T</th><th class="col2" style="background-color:#EEFFEE">T</th><th class="col3" style="background-color:#EEFFEE">T</th><th class="col4" style="background-color:#EEFFEE">T</th></tr><tr><td class="col0" style="background-color:#EEFFEE">T</td><td class="col0">F</td><th class="col1">F</th><th class="col2">F</th><th class="col3" style="background-color:#EEFFEE">T</th><th class="col4" style="background-color:#EEFFEE">T</th></tr><tr><td class="col0">F</td><td class="col0" style="background-color:#EEFFEE">T</td><th class="col1" style="background-color:#EEFFEE">T</th><th class="col2" style="background-color:#EEFFEE">T</th><th class="col3">F</th><th class="col4">F</th></tr><tr><td class="col0">F</td><td class="col0">F</td><th class="col1" style="background-color:#EEFFEE">T</th><th class="col2" style="background-color:#EEFFEE">T</th><th class="col3" style="background-color:#EEFFEE">T</th><th class="col4" style="background-color:#EEFFEE">T</th></tr></tbody></table>

<style>
 table.c0hide .col0 { visibility: hidden; }
 table.c1hide .col1 { visibility: hidden; }
 table.c2hide .col2 { visibility: hidden; }
 table.c3hide .col3 { visibility: hidden; }
 table.c4hide .col4 { visibility: hidden; }

 label:hover {
	            outline: thin solid;
	            cursor: cell;
	            }
</style>
</div>
"""

I believe that in Pluto scripts are isolated, so you can’t access variables created inside scripts from other scripts or other parts of the DOM by default.
The JS internals of Pluto are not very much documented so it’s not easy to understand what happens especially if you are not proficient in JS and Preact.

Now, if you really want to make your function available in the rest of the browser and working with your code, you have to attach it to the window (at least that’s a way that I know of).
You can easily do that by adding window.toggleColumn = toggleColumn before your closing </script> tag and your code works.

That being said, use of onclick is usually discouraged and the addEventListener is the recommended method.
This is especially true in Pluto where you need to pollute the window object to make functions.

In general I think the html code example you picked for the truth table is not the best in terms of design and readibility of the code.

If you want to see more examples on how to use JS inside pluto to make nice widgets you can look at the various notebooks in the PlutoUI package

2 Likes

Thanks for your helpful reply. I esp. appreciate it since I had been reading your contributions and your package for numbering equations in latex. I will look at PlutoUI, though I’m also wanting some interaction in the static HTML versions of my slides.

And, yes, that example html was not designed for readability, but is what my Julia code emits for my TruthTable type. I could have constructed a simpler example, but this had the features of a complex enough tree that it is beyond my limited knowledge of preact, though I’d love to learn. (I was also experimenting with the hidden checkbox trick, which is why the <label> tags are there. I may still go with that, since it avoids javascript entirely.) I welcome suggestions for a better design.

1 Like

If you want interactivity in the static html then JS is the way to go. Preact was just put as an example above because Pluto internals are using that. For creating widgets like you are planning to do vanilla JS is more than enough.

I also knew nothing about JS before starting to use Pluto and only started learning parts of it to create widgets and hack out the display in Pluto the way I wanted.
I think knowing basics of JS/CSS/HTML gives you huge flexibility in customizing your pluto notebook experience so it’s worth spending the time on it if you plan on using Pluto a lot.
Personally I am so hooked with Pluto that I can’t really think to do my Julia stuff without it! I also develop my own packages directly in Pluto :smiley:

2 Likes