rowid,title,content,sections_fts,rank 782,Table-level metadata,"""Table-level"" metadata refers to fields that can be specified for each table in a Datasette instance. These attributes should be listed under a specific table using the ""tables"" field. The following metadata fields are supported at the table level: source source_url license license_url about about_url columns (see Column descriptions ) Additionally, tables support a number of configuration options ( sort , sort_desc , size , sortable_columns , label_column , hidden , facets , facet_size , fts_table , fts_pk , searchmode , column_types ). See table configuration for full details.",154, 781,Database-level metadata,"""Database-level"" metadata refers to fields that can be specified for each database in a Datasette instance. These attributes should be listed under a database inside the ""databases"" field. The following are the full list of allowed database-level metadata fields: source source_url license license_url about about_url",154, 780,Top-level metadata,"""Top-level"" metadata refers to fields that can be specified at the root level of a metadata file. These attributes are meant to describe the entire Datasette instance. The following are the full list of allowed top-level metadata fields: title description description_html license license_url source source_url",154, 779,Metadata reference,A full reference of every supported option in a metadata.json or metadata.yaml file.,154, 778,Table configuration,"Datasette supports a range of table-level configuration options including sort order, page size, facets, full-text search, column types, and more. These are now documented in the table configuration section of the configuration reference. For backwards compatibility these options can be specified in either metadata.yaml or datasette.yaml .",154, 777,Column descriptions,"You can include descriptions for your columns by adding a ""columns"": {""name-of-column"": ""description-of-column""} block to your table metadata: [[[cog metadata_example(cog, { ""databases"": { ""database1"": { ""tables"": { ""example_table"": { ""columns"": { ""column1"": ""Description of column 1"", ""column2"": ""Description of column 2"" } } } } } }) ]]] [[[end]]] These will be displayed at the top of the table page, and will also show in the cog menu for each column. You can see an example of how these look at latest.datasette.io/fixtures/roadside_attractions .",154, 776,"Source, license and about","The three visible metadata fields you can apply to everything, specific databases or specific tables are source, license and about. All three are optional. source and source_url should be used to indicate where the underlying data came from. license and license_url should be used to indicate the license under which the data can be used. about and about_url can be used to link to further information about the project - an accompanying blog entry for example. For each of these you can provide just the *_url field and Datasette will treat that as the default link label text and display the URL directly on the page.",154, 775,Per-database and per-table metadata,"Metadata at the top level of the file will be shown on the index page and in the footer on every page of the site. The license and source is expected to apply to all of your data. You can also provide metadata at the per-database or per-table level, like this: [[[cog metadata_example(cog, { ""databases"": { ""database1"": { ""source"": ""Alternative source"", ""source_url"": ""http://example.com/"", ""tables"": { ""example_table"": { ""description_html"": ""Custom table description"", ""license"": ""CC BY 3.0 US"", ""license_url"": ""https://creativecommons.org/licenses/by/3.0/us/"" } } } } }) ]]] [[[end]]] Each of the top-level metadata fields can be used at the database and table level.",154, 774,Metadata,"Data loves metadata. Any time you run Datasette you can optionally include a YAML or JSON file with metadata about your databases and tables. Datasette will then display that information in the web UI. Run Datasette like this: datasette database1.db database2.db --metadata metadata.yaml Your metadata.yaml file can look something like this: [[[cog from metadata_doc import metadata_example metadata_example(cog, { ""title"": ""Custom title for your index page"", ""description"": ""Some description text can go here"", ""license"": ""ODbL"", ""license_url"": ""https://opendatacommons.org/licenses/odbl/"", ""source"": ""Original Data Source"", ""source_url"": ""http://example.com/"" }) ]]] [[[end]]] Choosing YAML over JSON adds support for multi-line strings and comments. The above metadata will be displayed on the index page of your Datasette-powered site. The source and license information will also be included in the footer of every page served by Datasette. Any special HTML characters in description will be escaped. If you want to include HTML in your description, you can use a description_html property instead.",154, 773,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]"", };",154, 772,Accessibility,"Custom fields are responsible for preserving the accessibility of the form: The visible field label should name the control. Use field.labelId with aria-labelledby when wrapping or replacing the visible input. Field metadata should remain available to assistive technology. Use field.descriptionId with aria-describedby . Keyboard users must be able to operate every part of the custom field. If the field opens an inline picker or other nested UI, Escape should close that nested UI first and return focus to a sensible element. If a control performs asynchronous loading, expose loading and error states in the UI. Use appropriate ARIA live regions where the state change is important to understand the field. If a plugin hides field.input , the replacement UI must still make the current value and available actions clear. Plugins should not submit the row themselves from inside makeColumnField() controls. Datasette owns the insert/edit dialog lifecycle, form submission, API call, error handling and row refresh.",154, 771,Example: textarea-backed custom element,"This example handles a markdown-editor column type by asking Datasette for a textarea and wrapping that textarea in a custom Web Component element: document.addEventListener(""datasette_init"", function (event) { event.detail.registerPlugin(""markdown-editor"", { version: ""0.1"", makeColumnField(context) { if (!context.columnType || context.columnType.type !== ""markdown-editor"") { return; } return { useTextarea: true, render(field) { const editor = document.createElement(""my-markdown-editor""); editor.appendChild(field.input); if (field.labelId) { field.input.setAttribute(""aria-labelledby"", field.labelId); } if (field.descriptionId) { field.input.setAttribute(""aria-describedby"", field.descriptionId); } return editor; }, focus(field) { const editor = field.root.querySelector(""my-markdown-editor""); if (editor && editor.focus) { editor.focus(); } else { field.input.focus(); } } }; } }); });",154, 770,Lazy loading large controls,"The JavaScript file that registers makeColumnField() should be small. If the actual control is large, load it from inside render() using dynamic import() . That way the heavier code is only downloaded after a user opens an insert/edit dialog containing a matching column type. const editorUrl = new URL(""./editor.js"", import.meta.url).href; document.addEventListener(""datasette_init"", function (event) { event.detail.registerPlugin(""my-editor"", { version: ""0.1"", makeColumnField(context) { if (!context.columnType || context.columnType.type !== ""my-editor"") { return; } return { useTextarea: true, render(field) { import(editorUrl).then(function () { // Enhance field.input here. }); return field.input; } }; } }); });",154, 769,Value helpers,"Custom fields should use field.getValue() and field.setValue(value) for value handling: const currentValue = field.getValue(); field.setValue(""new value""); field.setValue(null); Plugins can keep the core input visible, wrap it in a custom element, or hide it and provide a richer interface. If the input is hidden, the custom UI must still expose an accessible name, state and keyboard interaction. field.setValue() updates both field.input and the value used in the insert/update request. For example, a file picker that stores a selected file ID can hide the backing input and call field.setValue() when the selection changes: field.input.type = ""hidden""; field.setValue(fileId); For insert forms with a SQLite default, field.isUsingSqliteDefault() indicates whether Datasette will omit that column from the insert payload. Calling field.setValue(value) automatically stops using the SQLite default.",154, 768,Submitted value contract,"The field.setValue() method accepts the following value types: string number boolean null These values are used as column values in requests to the insert rows and update row JSON APIs. Plugins should not pass objects or arrays to field.setValue() . If a column stores structured data in SQLite, such as JSON in a TEXT column, the plugin should serialize that data first and submit the serialized string. Client-side parsing can still be useful for validation or editor state, but the submitted value should match the SQLite value Datasette should write.",154, 767,The field helper object,"The field object passed to render(field) , focus(field) and destroy(field) provides stable IDs, DOM elements and value helpers for integrating with the row insert/edit dialog: context - object The original context object passed to makeColumnField() . id - string The ID Datasette assigned to field.input , the backing or