File size: 3,065 Bytes
870ab6b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
import embed from "https://cdn.jsdelivr.net/npm/vega-embed@6/+esm";
import debounce from "https://cdn.jsdelivr.net/npm/[email protected]/debounce/+esm";
export async function render({ model, el }) {
let finalize;
function showError(error){
el.innerHTML = (
'<div style="color:red;">'
+ '<p>JavaScript Error: ' + error.message + '</p>'
+ "<p>This usually means there's a typo in your chart specification. "
+ "See the javascript console for the full traceback.</p>"
+ '</div>'
);
}
const reembed = async () => {
if (finalize != null) {
finalize();
}
let spec = model.get("spec");
let api;
try {
api = await embed(el, spec);
} catch (error) {
showError(error)
return;
}
finalize = api.finalize;
// Debounce config
const wait = model.get("debounce_wait") ?? 10;
const maxWait = wait;
const initialSelections = {};
for (const selectionName of Object.keys(model.get("_vl_selections"))) {
const storeName = `${selectionName}_store`;
const selectionHandler = (_, value) => {
const newSelections = cleanJson(model.get("_vl_selections") ?? {});
const store = cleanJson(api.view.data(storeName) ?? []);
newSelections[selectionName] = {value, store};
model.set("_vl_selections", newSelections);
model.save_changes();
};
api.view.addSignalListener(selectionName, debounce(selectionHandler, wait, {maxWait}));
initialSelections[selectionName] = {
value: cleanJson(api.view.signal(selectionName) ?? {}),
store: cleanJson(api.view.data(storeName) ?? [])
}
}
model.set("_vl_selections", initialSelections);
const initialParams = {};
for (const paramName of Object.keys(model.get("_params"))) {
const paramHandler = (_, value) => {
const newParams = JSON.parse(JSON.stringify(model.get("_params"))) || {};
newParams[paramName] = value;
model.set("_params", newParams);
model.save_changes();
};
api.view.addSignalListener(paramName, debounce(paramHandler, wait, {maxWait}));
initialParams[paramName] = api.view.signal(paramName) ?? null
}
model.set("_params", initialParams);
model.save_changes();
// Param change callback
model.on('change:_params', async (new_params) => {
for (const [param, value] of Object.entries(new_params.changed._params)) {
api.view.signal(param, value);
}
await api.view.runAsync();
});
}
model.on('change:spec', reembed);
model.on('change:debounce_wait', reembed);
await reembed();
}
function cleanJson(data) {
return JSON.parse(JSON.stringify(data))
} |