-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathinputMBID.js
More file actions
69 lines (61 loc) · 2.6 KB
/
Copy pathinputMBID.js
File metadata and controls
69 lines (61 loc) · 2.6 KB
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
import { extractEntityFromURL, getEntityTooltip } from './entity.js';
import { fetchEntity } from './publicAPI.js';
import { toScalar } from '@kellnerd/es-utils/array/scalar.js';
import { kebabToTitleCase } from '@kellnerd/es-utils/string/casingStyle.js';
/**
* Creates an input element where you can paste an MBID or an MB entity URL.
* It automatically validates the content on paste, loads the name of the entity and sets the MBID as a data attribute.
* @param {string} id ID and name of the input element.
* @param {CoreEntityTypeT[]} [allowedEntityTypes] Entity types which are allowed for this input, defaults to all.
* @param {string} [initialValue] Initial value of the input element.
*/
export function createMBIDInput(id, allowedEntityTypes, initialValue) {
/** @type {HTMLInputElement} */
const mbidInput = document.createElement('input');
mbidInput.className = 'mbid';
mbidInput.name = mbidInput.id = id;
mbidInput.placeholder = `MBID or URL (${allowedEntityTypes?.join('/') ?? 'any entity'})`;
const mbidAttribute = 'data-mbid';
const defaultEntityTypeRoute = toScalar(allowedEntityTypes) ?? 'mbid';
if (initialValue) {
setInputValue(initialValue);
}
mbidInput.addEventListener('input', async function () {
const entity = await setInputValue(this.value.trim());
if (entity) {
mbidInput.dispatchEvent(new CustomEvent('mbid-input', { detail: entity }));
}
});
return mbidInput;
/** @param {string} entityURL */
async function setInputValue(entityURL) {
// create a complete entity identifier for an MBID only input
if (entityURL.match(/^[0-9a-f-]{36}$/)) {
entityURL = [defaultEntityTypeRoute, entityURL].join('/');
}
// reset previous validation results
mbidInput.removeAttribute(mbidAttribute);
mbidInput.classList.remove('error', 'success');
mbidInput.title = '';
// validate entity type and MBID
try {
const entity = extractEntityFromURL(entityURL);
if (entity) {
if (typeof allowedEntityTypes === 'undefined' || allowedEntityTypes.includes(entity.type)) {
const result = await fetchEntity(entityURL);
result.type ||= kebabToTitleCase(entity.type); // fallback for missing type
mbidInput.setAttribute(mbidAttribute, result.id);
mbidInput.value = result.name || result.title; // releases only have a title attribute
mbidInput.classList.add('success');
mbidInput.title = getEntityTooltip(result);
return result;
} else {
throw new Error(`Entity type '${kebabToTitleCase(entity.type)}' is not allowed`);
}
}
} catch (error) {
mbidInput.classList.add('error');
mbidInput.title = error.message ?? error.statusText;
}
}
}