d718c5a372
CI / windows_test (push) Waiting to run
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / docker_push (duckdb) (push) Waiting to run
CI / docker_push (minimal) (push) Waiting to run
CI / hurl (${{ matrix.example }}) (push) Has been skipped
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
/* !include https://cdn.jsdelivr.net/npm/tom-select@2.6.1/dist/js/tom-select.popular.min.js */
|
|
|
|
function sqlpage_select_dropdown() {
|
|
for (const s of document.querySelectorAll(
|
|
"[data-pre-init=select-dropdown]",
|
|
)) {
|
|
try {
|
|
sqlpage_select_dropdown_individual(s);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize a select dropdown for a single element
|
|
* @param {HTMLSelectElement} s - The select element to initialize
|
|
*/
|
|
function sqlpage_select_dropdown_individual(s) {
|
|
s.removeAttribute("data-pre-init");
|
|
// See: https://github.com/orchidjs/tom-select/issues/716
|
|
// By default, TomSelect will not retain the focus if s is already focused
|
|
// This is a workaround to fix that
|
|
const is_focused = s === document.activeElement;
|
|
|
|
const tom = new TomSelect(s, {
|
|
load: sqlpage_load_options_source(s.dataset.options_source),
|
|
valueField: "value",
|
|
labelField: "label",
|
|
searchField: "label",
|
|
create: s.dataset.create_new,
|
|
maxOptions: null,
|
|
onItemAdd: function () {
|
|
this.setTextboxValue("");
|
|
this.refreshOptions();
|
|
},
|
|
});
|
|
if (is_focused) tom.focus();
|
|
s.form?.addEventListener("reset", async () => {
|
|
// The reset event is fired before the form is reset, so we need to wait for the next event loop
|
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
// Sync the options with the new reset value
|
|
tom.sync();
|
|
// Wait for the options to be updated
|
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
// "sync" also focuses the input, so we need to blur it to remove the focus
|
|
tom.blur();
|
|
tom.close();
|
|
});
|
|
}
|
|
|
|
function sqlpage_load_options_source(options_source) {
|
|
if (!options_source) return;
|
|
return async (query, callback) => {
|
|
const err = (label) => callback([{ label, value: "" }]);
|
|
const resp = await fetch(
|
|
`${options_source}?search=${encodeURIComponent(query)}`,
|
|
);
|
|
if (!resp.ok) {
|
|
return err(
|
|
`Error loading options from "${options_source}": ${resp.status} ${resp.statusText}`,
|
|
);
|
|
}
|
|
const resp_type = resp.headers.get("content-type");
|
|
if (resp_type !== "application/json") {
|
|
return err(
|
|
`Invalid response type: ${resp_type} from "${options_source}". Make sure to use the 'json' component in the SQL file that generates the options.`,
|
|
);
|
|
}
|
|
const results = await resp.json();
|
|
if (!Array.isArray(results)) {
|
|
return err(
|
|
`Invalid response from "${options_source}". The response must be an array of objects with a 'label' and a 'value' property.`,
|
|
);
|
|
}
|
|
if (results.length === 1 && results[0].error) {
|
|
return err(results[0].error);
|
|
}
|
|
if (results.length > 0) {
|
|
const keys = Object.keys(results[0]);
|
|
if (
|
|
keys.length !== 2 ||
|
|
!keys.includes("label") ||
|
|
!keys.includes("value")
|
|
) {
|
|
return err(
|
|
`Invalid response from "${options_source}". The response must be an array of objects with a 'label' and a 'value' property. Got: ${JSON.stringify(results[0])} in the first object instead.`,
|
|
);
|
|
}
|
|
}
|
|
callback(results);
|
|
};
|
|
}
|
|
add_init_fn(sqlpage_select_dropdown);
|