ipywidgets
ipywidgets copied to clipboard
Provide `ActiveHTMLWidget` that allows users to properly interact with HTML as rendered in the DOM
Problem
Across my few weeks using it, ipywidgets has been consistently added unnecessary restrictions to my desired workflow.
At the end of the day, I'd really just like ipywidgets to provide a proxy by which I can interact with the DOM, since JupyterLab is best for prototyping which means I'd like to be able to iterate fast and not need to churn out random custom widgets for every possible case of anything I'd ever like to do with my research code.
I can generate HTML in python no problem. I can generate very nice HTML in python no problem. I can make it look and be laid out however I might want, which is something I certainly cannot easily do with ipywidgets (trust me, I tried).
At the end of the day, I really just want ipywidgets to be my tunnel between my python code and the DOM. That's it. Given what I want to do (and what I'm guessing many researchers want to do based on the comments in this thread: https://github.com/jupyterlab/jupyterlab/issues/5660) I think the path of least resistance all around would be to have an extension to the basic HTML widget that does more than just allow one to set the innerHTML attribute and instead allows one to query parts of the actual live DOM element generated.
This would solve 100% of my issues with ipywidgets by allowing me to create my layouts and interactions myself, never needing to try to cobble together 80 different custom widgets to create the kind of layout that HTML & CSS supports naturally.
Proposed Solution
I think it's overkill to ask you all to support the entire DOM API out of the box, but I can imagine a few small changes that would allow this to work much better:
- Provide access to the
childNodesattribute of anHTMLelement. These could be represented easily as some kind ofNodeProxythat simply describes that relation between the child node and the element created by theActiveHTMLWidget. The element itself could have an empty path as the proxy element. - Provide access to a small number of attributes, maybe even just the
classList,style,andvalueattributes. With these, 95% of web-related stuff can be managed and creating some kind of tunnel to pass just them along would be easy. - Optionally, integrate interactivity through the approach taken by the
ipyeventsextension. It's a phenomenal extension for getting around the general lack of rich interactions in the baseipywidgetssuite.
A functioning implementation of this idea is here: https://github.com/b3m2a1/ActiveHTMLWidget
It attempts to provide a tunnel to the DOM and then get out of the way.
It currently supports attributes, styles, events, using non-div tags, and borrows code from ipywidgets.Box to allow for embedding other widgets inside the widget.
A fun minimal example:
dump = ipywidgets.Output()
def log(*e):
with dump:
print(*e)
header = HTMLElement(innerHTML="<h1>Input Field with Event Listeners</h1>", classList=["card-header"])
button = HTMLElement(tagName="button", textContent="????", classList=['input-group-text'], eventPropertiesDict={'click':['button', 'shiftKey']})
button.bind_callback(log)
input_group = HTMLElement(
children=[
button,
HTMLElement(tagName="input", classList=["form-control"], elementAttributes={'placeholder':'input'}, trackInput=True)
],
classList=['input-group', 'mb-3']
)
body = HTMLElement(
children=[
input_group,
HTMLElement(tagName="div", classList=["alert", "alert-info"], textContent="Event output is printed below"),
HTMLElement(tagName="hr"),
dump
],
classList=['card-body']
)
HTMLElement(children=[header, body], classList=["card"])
An initial peek at where this idea has gone: https://b3m2a1.github.io/jhtml-a-web-framework-for-jupyter#body
@b3m2a1 Thanks for creating a library for this, and for sharing! Your original post included some potential improvements to ipywidgets to make it easier to write such a third party widget. With the experience of having written that library, are there any of those points that still remain? If so, maybe you can open separate issues and/or PRs for them?
@vidartf Unfortunately it's been so long since I wrote the widget library I've forgotten, but I think the biggest complaint was that the documentation makes it seem like the dev environment needs to be clunkier than it is (and I think I had to write my own scripts to install the widget to avoid expensive jupyter widgets rebuilds or something)
For anyone coming to this page, AnyWidget might be a good replacement for this library. It lets you render arbitrary JS with a widget, allowing you to set custom HTML if you like easily.