I am trying to make a gr.HTML
component to be clickable in order to set the display:block
of a second gr.HTML
component. For this I define a <script>
block and add it the the head
argument of gr.Block
. Unfortunately it does not seem to work. For investigating what happens, I added some debug log messages.
Gradio app:
import gradio as gr
head = """
<script>
console.log("Script loaded!");
document.addEventListener("DOMContentLoaded", function() {
console.log("DOM loaded!");
var firstDiv = document.getElementById("first_div");
var secondDiv = document.getElementById("second_div");
if (firstDiv && secondDiv) {
firstDiv.addEventListener("click", function() {
console.log("First div clicked!");
secondDiv.style.display = "block";
});
}
});
</script>
"""
with gr.Blocks(head=head) as demo:
gr.HTML(
"""
<div id="first_div" style="cursor:pointer; background-color:#eee; padding:10px; margin-bottom:10px;">
Click Me!
</div>
"""
)
gr.HTML(
"""
<div id="second_div" style="display:none; background-color:#ddd; padding:10px;">
You clicked, I am visible!
</div>
"""
)
demo.launch()
I see the log message "Script loaded!"
but not "DOM loaded"
nor "First div clicked!"
.
However, when putting the same into a pure HTML as:
<!DOCTYPE html>
<html>
<head>
<script>
console.log("Scripts loaded!");
document.addEventListener("DOMContentLoaded", function() {
console.log("DOM loaded!");
var firstDiv = document.getElementById("first_div");
var secondDiv = document.getElementById("second_div");
if (firstDiv && secondDiv) {
firstDiv.addEventListener("click", function() {
console.log("First div clicked!");
secondDiv.style.display = "block";
});
}
});
</script>
</head>
<body>
<div id="first_div" style="cursor:pointer; background-color:#eee; padding:10px; margin-bottom:10px;">
Click Me!
</div>
<div id="second_div" style="display:none; background-color:#ddd; padding:10px; margin-bottom:10px;">
You clicked, I am visible
</div>
</body>
</html>
it works as expected.
Also changing the concept from "DOMContentLoaded"
to window.onload
as:
head = """
<script>
console.log("Script loaded!");
window.onload = function() {
console.log("Window onload fired!");
const element = document.getElementById("first_div");
if (element) {
console.log("Element found!");
} else {
console.log("Element not found!");
};
};
</script>
"""
or to document.readyState
as:
head = """
<script>
console.log("Script loaded!");
if (document.readyState === "interactive" || document.readyState === "complete") {
console.log("Document ready")
const element = document.getElementById("first_div");
if (element) {
console.log("Element found immediately!");
} else {
console.log("Element not found immediately!");
};
}
</script>
"""
does not help.
What am I missing? Can anybody help, that would absolutely be awesome!
I never used Gradio before, but after looking a bit at the docs I found out a potentially good solution, although with a slightly different approach. The steps are:
head
the definition of the function that will be run when the first div
is clicked.onclick
attribute to the first div
, which will be calling the function defined in step 1.After running this snippet, it worked for me:
import gradio as gr
head = """
<script>
function clickHandler() {
console.log("First div clicked!");
var secondDiv = document.getElementById("second_div");
secondDiv.style.display = "block";
}
</script>
"""
with gr.Blocks(head=head) as demo:
gr.HTML(
"""
<div id="first_div" onclick="clickHandler()" style="cursor:pointer; background-color:#eee; padding:10px; margin-bottom:10px;">
Click Me!
</div>
"""
)
gr.HTML(
"""
<div id="second_div" style="display:none; background-color:#ddd; padding:10px;">
You clicked, I am visible!
</div>
"""
)
demo.launch()
Hope it works for you, too!