New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
custom ReactiveHTML unable to render and process MouseEvent correctly #5195
Comments
My hypothesis is that cytoscape.js does not work well inside shadow root. I've created an issue with cytoscape.js in 3133. You will find more detail and a working example there. |
I don't know too much about ShadowDOM, but when review the mouse click event, I noticed the Target Element was on the outer div instead of the canvas,; thus, the coordinate information were not the same as in the other version of panel(v0.14.1). |
Could you share a screenshot of that click event? With the Target element? And also share it in the issue I created with Cytoscape (link in post above) |
Can the srcElement and target be the canvas instead of its parent element? Is this within panel's control or it's has to do with bokeh web framework? |
Maybe this article is useful. Something about events inside shadowroot being retargetted to the "host". This can maybe be avoided if put inside a "slot" https://javascript.info/shadow-dom-events |
@MarcSkovMadsen awesome find - I wrapped the div with |
I'm so happy to hear that @derrickmcs Could you post a minimum, working example such that its easy for any one to learn from? Thanks |
I would suggest Documenting the use of "slot" for events when using ReactiveHTML. |
Wow indeed, great find. |
I'm so sorry about this. I've spoken too soon. I was testing on the older version of panel (0.14.2) and that's why it worked. Using slot doesn't solve the problem. |
Nevermind on that, for whatever reason, Cytoscape received the mouseEvent from the outer layer, thus the offsetX and offsetY are incorrect.
|
I found a way around this issue, which is to trigger Cytoscape to recalculate its positions in the event of a scroll. (NOTE: not all browsers support scroll event)
Here's a working code:
|
Would it work if you set a timeout to trigger the resize after 100ms or something? |
I'm not sure it will buy me much. I think trigger on a "scrollend" event is OK. |
Now I also think import param
import panel as pn
from panel.reactive import ReactiveHTML
class Cytoscape(ReactiveHTML):
object = param.List()
layout = param.Selector(default="cose", objects=["breadthfirst", "circle", "concentric", "cose", "grid", "preset", "random"])
style = param.String("", doc="Use to set the styles of the nodes/edges")
zoom = param.Number(1, bounds=(0,100))
pan = param.Dict({"x": 0, "y": 0})
data = param.List(doc="Use to send node's data/attributes to Cytoscape")
selected_nodes = param.List()
selected_edges = param.List()
_template = """
<div id="cy" style="width: 100%; height: 100%; position: relative; border: 1px solid"></div>
"""
__javascript__ = ['https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.23.0/cytoscape.umd.js']
_scripts = {
'render': """
self.create()
""",
"create": """
if (state.cy == undefined){
state.cy = cytoscape({
container: cy,
layout: {name: data.layout},
elements: data.object,
zoom: data.zoom,
pan: data.pan,
});
state.cy.on('select unselect', function (evt) {
data.selected_nodes = state.cy.elements('node:selected').map((el)=>{return el.id()})
data.selected_edges = state.cy.elements('edge:selected').map((el)=>{return el.id()})
});
self.style()
const mainEle = document.querySelector("body")
mainEle.addEventListener("scrollend", (event) => {state.cy.resize().fit()})
};
""",
'remove': """
state.cy.destroy()
delete state.cy
""",
"object": "state.cy.json({elements: data.object});state.cy.resize().fit()",
'layout': "state.cy.layout({name: data.layout}).run()",
"zoom": "state.cy.zoom(data.zoom)",
"pan": "state.cy.pan(data.pan)",
"style": """
state.cy.style().resetToDefault().append(data.style).update()
""",
}
_extension_name = 'cytoscape'
pn.extension('cytoscape', sizing_mode='stretch_width')
elements = [{"data":{"id":'A', "label":'A'}},{"data":{"id":'B', "label":'B'}}, {"data":{"id": "A-B", "source":'A', "target":'B'}}]
graph = Cytoscape(object=elements, sizing_mode="stretch_width", height=600)
app = pn.Row(
pn.Param(graph, parameters=["object", "zoom", "pan", "layout", "style", "selected_nodes", "selected_edges"], sizing_mode="fixed", width=300),
graph
).servable() |
panel version 1.1.1 - Cytoscape.js ver. 3.25.0 rendered using ReactiveHTML, MacOS12.1, Safari 15.2
When using Panel v0.14.1, the component rendered correctly. Mouse clicks were functional and on target.
When using Panel v1.1.1, the component can only render on certain layouts and mouse click did not work until manually resize the window. However, when the window scrolled away from original position, the mouse clicks were off target (usually by the same amount of pixels from the original position.
Complete, minimal, self-contained example code that reproduces the issue
Initial render - Click on the top node (blue) - note the X-Y coord
Scroll the window the right - Click on the same node - It is off target to the left (note the x-y coord).
The text was updated successfully, but these errors were encountered: