mirror of
https://github.com/sissbruecker/linkding
synced 2025-02-16 20:38:24 +00:00
* extract generic behaviors * preserve query string when refreshing content * refactor details modal refresh * refactor bulk edit * update tests * restore tag modal * Make IntelliJ aware of custom attributes * improve e2e test coverage
85 lines
2.2 KiB
JavaScript
85 lines
2.2 KiB
JavaScript
const behaviorRegistry = {};
|
|
|
|
export function registerBehavior(name, behavior) {
|
|
behaviorRegistry[name] = behavior;
|
|
applyBehaviors(document, [name]);
|
|
}
|
|
|
|
export function applyBehaviors(container, behaviorNames = null) {
|
|
if (!behaviorNames) {
|
|
behaviorNames = Object.keys(behaviorRegistry);
|
|
}
|
|
|
|
behaviorNames.forEach((behaviorName) => {
|
|
const behavior = behaviorRegistry[behaviorName];
|
|
const elements = Array.from(
|
|
container.querySelectorAll(`[${behaviorName}]`),
|
|
);
|
|
|
|
// Include the container element if it has the behavior
|
|
if (container.hasAttribute && container.hasAttribute(behaviorName)) {
|
|
elements.push(container);
|
|
}
|
|
|
|
elements.forEach((element) => {
|
|
element.__behaviors = element.__behaviors || [];
|
|
const hasBehavior = element.__behaviors.some(
|
|
(b) => b instanceof behavior,
|
|
);
|
|
|
|
if (hasBehavior) {
|
|
return;
|
|
}
|
|
|
|
const behaviorInstance = new behavior(element);
|
|
element.__behaviors.push(behaviorInstance);
|
|
});
|
|
});
|
|
}
|
|
|
|
export function swap(element, html, options) {
|
|
const dom = new DOMParser().parseFromString(html, "text/html");
|
|
|
|
let targetElement = element;
|
|
let strategy = "innerHTML";
|
|
if (options.target) {
|
|
const parts = options.target.split("|");
|
|
targetElement =
|
|
parts[0] === "self" ? element : document.querySelector(parts[0]);
|
|
strategy = parts[1] || "innerHTML";
|
|
}
|
|
|
|
let contents = Array.from(dom.body.children);
|
|
if (options.select) {
|
|
contents = Array.from(dom.querySelectorAll(options.select));
|
|
}
|
|
|
|
switch (strategy) {
|
|
case "append":
|
|
targetElement.append(...contents);
|
|
break;
|
|
case "outerHTML":
|
|
targetElement.parentElement.replaceChild(contents[0], targetElement);
|
|
break;
|
|
case "innerHTML":
|
|
default:
|
|
targetElement.innerHTML = "";
|
|
targetElement.append(...contents);
|
|
}
|
|
contents.forEach((content) => applyBehaviors(content));
|
|
}
|
|
|
|
export function fireEvents(events) {
|
|
if (!events) {
|
|
return;
|
|
}
|
|
events.split(",").forEach((eventName) => {
|
|
const targets = Array.from(
|
|
document.querySelectorAll(`[ld-on='${eventName}']`),
|
|
);
|
|
targets.push(document);
|
|
targets.forEach((target) => {
|
|
target.dispatchEvent(new CustomEvent(eventName));
|
|
});
|
|
});
|
|
}
|