mirror of
https://github.com/infinition/Bjorn.git
synced 2026-03-10 06:31:59 +00:00
- Implemented methods for fetching AI stats, training history, and recent experiences. - Added functionality to set operation mode (MANUAL, AUTO, AI) with appropriate handling. - Included helper methods for querying the database and sending JSON responses. - Integrated model metadata extraction for visualization purposes.
98 lines
3.0 KiB
JavaScript
98 lines
3.0 KiB
JavaScript
/**
|
|
* Safe DOM utilities — avoids innerHTML with untrusted content.
|
|
*/
|
|
import { trLoose } from './i18n.js';
|
|
|
|
/**
|
|
* Create an element with attributes and children (safe, no innerHTML).
|
|
* @param {string} tag
|
|
* @param {object} attrs - className, style, data-*, event handlers (onclick, etc.)
|
|
* @param {Array} children - strings or HTMLElements
|
|
* @returns {HTMLElement}
|
|
*/
|
|
export function el(tag, attrs = {}, children = []) {
|
|
const node = document.createElement(tag);
|
|
for (const [k, v] of Object.entries(attrs)) {
|
|
if (v == null || v === false) continue;
|
|
if (k === 'class' || k === 'className') node.className = v;
|
|
else if (k === 'style' && typeof v === 'string') node.style.cssText = v;
|
|
else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);
|
|
else if (k.startsWith('on') && typeof v === 'function') {
|
|
node.addEventListener(k.slice(2).toLowerCase(), v);
|
|
}
|
|
else node.setAttribute(k, String(v));
|
|
}
|
|
for (const child of (Array.isArray(children) ? children : [children])) {
|
|
if (child == null || child === false) continue;
|
|
if (typeof child === 'string' || typeof child === 'number') {
|
|
node.appendChild(document.createTextNode(String(child)));
|
|
} else if (child instanceof Node) {
|
|
node.appendChild(child);
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
/**
|
|
* Shorthand selectors.
|
|
*/
|
|
export const $ = (s, root = document) => root.querySelector(s);
|
|
export const $$ = (s, root = document) => Array.from(root.querySelectorAll(s));
|
|
|
|
/**
|
|
* Escape HTML entities to prevent XSS when rendering untrusted text.
|
|
* @param {string} str
|
|
* @returns {string}
|
|
*/
|
|
export function escapeHtml(str) {
|
|
const div = document.createElement('div');
|
|
div.appendChild(document.createTextNode(str));
|
|
return div.innerHTML;
|
|
}
|
|
|
|
/**
|
|
* Set text content safely (never innerHTML with untrusted data).
|
|
* @param {HTMLElement} el
|
|
* @param {string} text
|
|
*/
|
|
export function setText(el, text) {
|
|
if (el) el.textContent = text;
|
|
}
|
|
|
|
/**
|
|
* Show a toast notification.
|
|
* @param {string} message - plain text (safe)
|
|
* @param {number} duration - ms
|
|
* @param {string} type - 'info' | 'success' | 'error' | 'warning'
|
|
*/
|
|
export function toast(message, duration = 2600, type = 'info') {
|
|
const container = document.getElementById('toasts');
|
|
if (!container) return;
|
|
|
|
const t = el('div', { class: `toast toast-${type}` }, [trLoose(String(message))]);
|
|
container.appendChild(t);
|
|
|
|
setTimeout(() => {
|
|
t.style.transition = 'transform .2s ease, opacity .2s';
|
|
t.style.transform = 'translateY(10px)';
|
|
t.style.opacity = '0';
|
|
setTimeout(() => t.remove(), 220);
|
|
}, duration);
|
|
}
|
|
|
|
/**
|
|
* Empty a container safely.
|
|
* @param {HTMLElement} container
|
|
*/
|
|
export function empty(container) {
|
|
while (container.firstChild) container.removeChild(container.firstChild);
|
|
}
|
|
|
|
export function confirmT(message) {
|
|
return window.confirm(trLoose(String(message)));
|
|
}
|
|
|
|
export function promptT(message, defaultValue = '') {
|
|
return window.prompt(trLoose(String(message)), defaultValue);
|
|
}
|