8bb3619ddc
- Add fmtBytes() and csvToArr() helpers to hoover/helpers.js - Replace inline async patterns with ActionButton/ConfirmDelete in wireguard.js - Convert addDomain/editDomain to QuickModal + apiSubmit in proxy.js - Convert settingsModal handlers to formAction in certs.js - Remove redundant synced handling from dhcp.js apply button - Add onComplete callback to ConfirmDelete (fixes users.js onRefresh bug) - Fix passkeys.js ActionCell/Table usage (invalid component API) - Remove duplicate fmtBytes from dashboard.js
91 lines
2.2 KiB
JavaScript
91 lines
2.2 KiB
JavaScript
/**
|
|
* Hoover — helpers.js
|
|
*
|
|
* Shared utilities: text escaping, attribute escaping, DOM value helpers,
|
|
* zone parsing, form utilities.
|
|
*/
|
|
|
|
/**
|
|
* Escape text for safe HTML output.
|
|
* Appends the string to a temporary div and reads innerHTML,
|
|
* which safely escapes all HTML special characters.
|
|
*/
|
|
export function esc(s) {
|
|
const d = document.createElement('div');
|
|
d.append(String(s ?? ''));
|
|
return d.innerHTML;
|
|
}
|
|
|
|
/**
|
|
* Escape a string for safe use in HTML attributes.
|
|
*/
|
|
export function att_esc(s) {
|
|
return String(s ?? '')
|
|
.replace(/&/g, '&')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
}
|
|
|
|
/**
|
|
* URL-encode a string.
|
|
*/
|
|
export const enc = encodeURIComponent;
|
|
|
|
/**
|
|
* Get the value of a DOM element by ID.
|
|
*/
|
|
export function $val(id) {
|
|
return document.getElementById(id)?.value;
|
|
}
|
|
|
|
/**
|
|
* Parse zone data from various API response shapes into a flat string array.
|
|
*/
|
|
export function parseZones(data) {
|
|
let z = data?.active || data?.zones || [];
|
|
if (typeof z === 'object' && !Array.isArray(z))
|
|
z = Object.values(z).map(i => i?.name || i);
|
|
return Array.isArray(z) ? z : [];
|
|
}
|
|
|
|
/**
|
|
* Trigger a browser file download from a Blob.
|
|
*
|
|
* @param {Blob} blob
|
|
* @param {string} filename
|
|
*/
|
|
/**
|
|
* Format bytes to human-readable string.
|
|
* @param {number} bytes
|
|
*/
|
|
export function fmtBytes(bytes) {
|
|
if (bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return (bytes / Math.pow(k, i)).toFixed(i > 0 ? 1 : 0) + ' ' + sizes[i];
|
|
}
|
|
|
|
/**
|
|
* Split a comma-separated string into trimmed, non-empty values.
|
|
* @param {string} [value]
|
|
* @returns {string[]}
|
|
*/
|
|
export function csvToArr(value) {
|
|
if (!value || !value.trim()) return [];
|
|
return value.split(',').map(s => s.trim()).filter(Boolean);
|
|
}
|
|
|
|
export function downloadBlob(blob, filename) {
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
}
|