-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Marco Zocca
committed
Jan 8, 2024
1 parent
ce8f889
commit 32da210
Showing
6 changed files
with
40 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# 0.3 | ||
|
||
* the HTMX swap mechanism works once more as expected: this extension now receives an *object* from the server, which | ||
is unpacked into Plotly restyle data and HTML markup. | ||
|
||
# 0.2 | ||
|
||
* use [`plotly_utils.py`](https://cdn.jsdelivr.net/gh/ocramz/[email protected]/plotly_utils.py) to convert between | ||
Plotly objects and restyle-friendly JSON. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ Possible applications include: simple dashboards, data apps, and similar. | |
Load the script from CDN into the head of your HTML file: | ||
|
||
```html | ||
<script src="https://cdn.jsdelivr.net/gh/ocramz/[email protected]/htmx-plotly.js" integrity="sha256-0lbEDYe4H+Z2f/YMKEgbTnyvT2Wa837+a+D7XaPcKIo=" crossorigin="anonymous"></script>``` | ||
|
||
``` | ||
|
||
and of course also HTMX and Plotly: | ||
|
@@ -26,15 +26,17 @@ and of course also HTMX and Plotly: | |
Add these attributes to a page element: | ||
* `hx-ext="htmx-plotly"` means this element uses the extension | ||
* `hx-post="/get-data"` the HTTP endpoint that returns the new plot data | ||
* `hx-swap="none"` don't mutate the DOM with the result (we need to call the Plotly API instead) | ||
* `plot-id="my-plot"` ID of the DOM element that hosts the Plotly chart. | ||
|
||
Example: here we make an `<a>` text link trigger the update of the plot within element `my-plot`: | ||
|
||
```html | ||
<a href="#" hx-ext="htmx-plotly" hx-post="/get-data" hx-swap="none" plot-id="my-plot"><h1>UPDATE</h1></a> | ||
<a href="#" hx-ext="htmx-plotly" hx-post="/get-data" plot-id="my-plot"><h1>UPDATE</h1></a> | ||
``` | ||
|
||
NB: As of `v0.3` the HTMX swap mechanism works once more as expected: this extension now receives an *object* from the server, which | ||
is unpacked into Plotly restyle data and HTML markup. | ||
|
||
### Setup (frontend) | ||
|
||
Plotly charts need an empty div element as well as a script tag for initialization: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,23 @@ | ||
// adapted from https://unpkg.com/[email protected]/dist/ext/client-side-templates.js | ||
|
||
function htmlUnescape(input) { | ||
// // HTML-in-JSON should be escaped on the wire, and decoded safely here with DOMParser to avoid XSS | ||
var doc = new DOMParser().parseFromString(input, "text/html"); | ||
return doc.documentElement.textContent | ||
} | ||
|
||
htmx.defineExtension('htmx-plotly', { | ||
transformResponse : (text, xhr, elt) => { | ||
|
||
const verbose = true | ||
const pedantic = false | ||
|
||
var plotEl = htmx.closest(elt, "[plot-id]"); // closest including div element | ||
const payload = JSON.parse(text) | ||
const dataNew = payload['restyle_data'] | ||
n = dataNew.length | ||
const markup = htmlUnescape(payload['markup']) // to be passed back to HTMX for swapping | ||
if (plotEl) { | ||
const dataNew = JSON.parse(text) | ||
n = dataNew.length | ||
const plotId = plotEl.getAttribute('plot-id'); // lookup value of ? in < .. plot-id="?"> | ||
var plotDiv = htmx.find("#" + plotId); // div element pointed at | ||
if (plotDiv) { | ||
|
@@ -31,7 +39,7 @@ htmx.defineExtension('htmx-plotly', { | |
console.log('No plot-id attribute defined') | ||
} | ||
|
||
return '' | ||
return markup | ||
|
||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,19 @@ | ||
import json | ||
from markupsafe import Markup, escape | ||
|
||
def plotlyToRestyle(x): | ||
def plotlyToRestyle(x, htmlStr): | ||
""" | ||
:param x: a Plotly object with a .to_json() implem, e.g. a Figure | ||
:param htmlStr: HTML string that will be passed to HTMX for swapping | ||
:return: data that can be passed to restyle in Plotly.js | ||
""" | ||
z = x.to_json() # .to_json() is Plotly implem | ||
def duplicate(w): | ||
w['x'] = [w['x']] # the .restyle() nested array bs | ||
w['y'] = [w['y']] | ||
return w | ||
return [duplicate(w) for w in json.loads(z)['data']] | ||
obj = { | ||
'restyle_data': [duplicate(w) for w in json.loads(z)['data']], | ||
'markup': str(escape(htmlStr)) | ||
} | ||
return obj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters