JavaScript plugins¶
Datasette can run custom JavaScript in several different ways:
Datasette plugins written in Python can use the extra_js_urls() or extra_body_script() plugin hooks to inject JavaScript into a page
Datasette instances with custom templates can include additional JavaScript in those templates
The
extra_js_urls
key indatasette.yaml
can be used to include extra JavaScript
There are no limitations on what this JavaScript can do. It is executed directly by the browser, so it can manipulate the DOM, fetch additional data and do anything else that JavaScript is capable of.
Warning
Custom JavaScript has security implications, especially for authenticated Datasette instances where the JavaScript might run in the context of the authenticated user. It's important to carefully review any JavaScript you run in your Datasette instance.
The datasette_init event¶
Datasette emits a custom event called datasette_init
when the page is loaded. This event is dispatched on the document
object, and includes a detail
object with a reference to the datasetteManager object.
Your JavaScript code can listen out for this event using document.addEventListener()
like this:
document.addEventListener("datasette_init", function (evt) {
const manager = evt.detail;
console.log("Datasette version:", manager.VERSION);
});
datasetteManager¶
The datasetteManager
object
VERSION
- stringThe version of Datasette
plugins
-Map()
A Map of currently loaded plugin names to plugin implementations
registerPlugin(name, implementation)
Call this to register a plugin, passing its name and implementation
selectors
- objectAn object providing named aliases to useful CSS selectors, listed below
JavaScript plugin objects¶
JavaScript plugins are blocks of code that can be registered with Datasette using the registerPlugin()
method on the datasetteManager object.
The implementation
object passed to this method should include a version
key defining the plugin version, and one or more of the following named functions providing the implementation of the plugin:
makeAboveTablePanelConfigs()¶
This method should return a JavaScript array of objects defining additional panels to be added to the top of the table page. Each object should have the following:
id
- stringA unique string ID for the panel, for example
map-panel
label
- stringA human-readable label for the panel
render(node)
- functionA function that will be called with a DOM node to render the panel into
This example shows how a plugin might define a single panel:
document.addEventListener('datasette_init', function(ev) {
ev.detail.registerPlugin('panel-plugin', {
version: 0.1,
makeAboveTablePanelConfigs: () => {
return [
{
id: 'first-panel',
label: 'First panel',
render: node => {
node.innerHTML = '<h2>My custom panel</h2><p>This is a custom panel that I added using a JavaScript plugin</p>';
}
}
]
}
});
});
When a page with a table loads, all registered plugins that implement makeAboveTablePanelConfigs()
will be called and panels they return will be added to the top of the table page.
makeColumnActions(columnDetails)¶
This method, if present, will be called when Datasette is rendering the cog action menu icons that appear at the top of the table view. By default these include options like "Sort ascending/descending" and "Facet by this", but plugins can return additional actions to be included in this menu.
The method will be called with a columnDetails
object with the following keys:
columnName
- stringThe name of the column
columnNotNull
- booleanTrue if the column is defined as NOT NULL
columnType
- stringThe SQLite data type of the column
isPk
- booleanTrue if the column is part of the primary key
It should return a JavaScript array of objects each with a label
and onClick
property:
label
- stringThe human-readable label for the action
onClick(evt)
- functionA function that will be called when the action is clicked
The evt
object passed to the onClick
is the standard browser event object that triggered the click.
This example plugin adds two menu items - one to copy the column name to the clipboard and another that displays the column metadata in an alert()
window:
document.addEventListener('datasette_init', function(ev) {
ev.detail.registerPlugin('column-name-plugin', {
version: 0.1,
makeColumnActions: (columnDetails) => {
return [
{
label: 'Copy column to clipboard',
onClick: async (evt) => {
await navigator.clipboard.writeText(columnDetails.columnName)
}
},
{
label: 'Alert column metadata',
onClick: () => alert(JSON.stringify(columnDetails, null, 2))
}
];
}
});
});
Selectors¶
These are available on the selectors
property of the datasetteManager object.
const DOM_SELECTORS = {
/** Should have one match */
jsonExportLink: ".export-links a[href*=json]",
/** Event listeners that go outside of the main table, e.g. existing scroll listener */
tableWrapper: ".table-wrapper",
table: "table.rows-and-columns",
aboveTablePanel: ".above-table-panel",
// These could have multiple matches
/** Used for selecting table headers. Use makeColumnActions if you want to add menu items. */
tableHeaders: `table.rows-and-columns th`,
/** Used to add "where" clauses to query using direct manipulation */
filterRows: ".filter-row",
/** Used to show top available enum values for a column ("facets") */
facetResults: ".facet-results [data-column]",
};