Hi All
I would like to have a floating panel in Panel. For example for having a floating panel of widgets on top of a map.
I’ve seen @nghenzi experiment with this. But I’ve also found jsPanel which provides a lot of possibilities.
Starting Point
As a starting point I can create something like
import panel as pn
import param
RAW_CSS = """
body {
margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
_template = """
<div id="floating-panel"></div>
"""
__css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
__javascript__ = [
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
]
_scripts = {
"render": """
var config = {
position: 'right-top',
content: '<p>I want my widgets here!</p>',
contentSize: '500 350',
headerTitle: 'Settings',
theme: 'primary',
callback: function(panel) {
// do something if needed ...
}
}
jsPanel.create(config);
"""
}
pn.Column(
pn.Spacer(background="lightblue", sizing_mode="stretch_both", margin=0),
JsPanel(),
sizing_mode="stretch_both",
).servable()
Adding the widget to the app
I can add a widget to the app like shown below
import panel as pn
import param
RAW_CSS = """
body {
margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
object = param.Parameter()
_template = """
<div id="element">${object}</div>
"""
__css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
__javascript__ = [
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
]
_scripts = {
"render": """
var config = {
position: 'right-top',
content: '<p>I want my widget here!</p>',
contentSize: '500 350',
headerTitle: 'Settings',
theme: 'primary',
callback: function(panel) {
// do something if needed ...
}
}
jsPanel.create(config);
"""
}
pn.Column(
JsPanel(object=pn.widgets.Button(name="My Widget")),
pn.Spacer(sizing_mode="stretch_both", margin=0),
sizing_mode="stretch_both",background="lightblue"
).servable()
I can use a div
as content
of the Panel
If I set
_template = """
<div id="element">Some Text I've added to a div element that is used inside the jsPanel</div>
"""
and content
to element
, the div
is shown inside the Panel.
import panel as pn
import param
RAW_CSS = """
body {
margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
_template = """
<div id="element">Some Text I've added to a div element that is used inside the jsPanel</div>
"""
__css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
__javascript__ = [
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
]
_scripts = {
"render": """
var config = {
position: 'right-top',
content: element,
contentSize: '500 350',
headerTitle: 'Settings',
theme: 'primary',
callback: function(panel) {
// do something if needed ...
}
}
jsPanel.create(config);
"""
}
pn.Column(
JsPanel(object=pn.widgets.Button(name="My Widget")),
pn.Spacer(sizing_mode="stretch_both", margin=0),
sizing_mode="stretch_both",background="lightblue"
).servable()
Move the widget inside the div
element
If I set
_template = """
<div id="element">${object}</div>
"""
where object=pn.widgets.Button(name="My Widget")
then I get the error
'element' is not defined
import panel as pn
import param
RAW_CSS = """
body {
margin: 0px;}
"""
if not RAW_CSS in pn.config.raw_css:
pn.config.raw_css.append(RAW_CSS)
pn.extension()
class JsPanel(pn.reactive.ReactiveHTML):
object = param.Parameter()
_template = """
<div id="element">${object}</div>
"""
__css__ = ["https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.css"]
__javascript__ = [
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js",
"https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js",
]
_scripts = {
"render": """
var config = {
position: 'right-top',
content: element,
contentSize: '500 350',
headerTitle: 'Settings',
theme: 'primary',
callback: function(panel) {
// do something if needed ...
}
}
jsPanel.create(config);
"""
}
pn.Column(
JsPanel(object=pn.widgets.Button(name="My Widget")),
pn.Spacer(sizing_mode="stretch_both", margin=0),
sizing_mode="stretch_both",background="lightblue"
).servable()