refactor: centralize context-menu attribute and element helpers
Replace scattered inline encodeURIComponent(JSON.stringify(...)) and
manual oncontextmenu/dataset assignments with unified helpers added to
renderFormatMethods:
- encodeContextMenuModel(context): safe JSON serialization for data-model
- getContextMenuAttrs(context, tooltip): HTML attribute string for
template literals (used in 5 files)
- getContextMenuProps(context, tooltip): props object for imperative
element assignment (used in missingBrowserMethods)
- setContextMenuElement(element, context, tooltip): sets or clears
data-model, data-tooltip, and oncontextmenu on a DOM element
Reduces duplication across 5 modules, adds try/catch around JSON
serialization, and removes 14 lines of repeated oncontextmenu wiring.
This commit is contained in:
@@ -3,6 +3,59 @@ import { api } from "../../../../../scripts/api.js";
|
||||
import { $el } from "../../../../../scripts/ui.js";
|
||||
import { getSvgIcon } from "../../utils/icon_utils.js";
|
||||
export const renderFormatMethods = {
|
||||
encodeContextMenuModel(context = null) {
|
||||
if (!context) return '';
|
||||
try {
|
||||
return encodeURIComponent(JSON.stringify(context));
|
||||
} catch (error) {
|
||||
console.warn('Model Resolver: failed to encode context menu model', error);
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
getContextMenuAttrs(context = null, tooltip = '') {
|
||||
const data = this.encodeContextMenuModel(context);
|
||||
if (!data) return '';
|
||||
const tooltipAttr = tooltip ? ` data-tooltip="${this.escapeHtml(tooltip)}"` : '';
|
||||
return ` data-model="${this.escapeHtml(data)}" oncontextmenu="window.MLOpenContextMenu(event, this)"${tooltipAttr}`;
|
||||
},
|
||||
|
||||
getContextMenuProps(context = null, tooltip = '') {
|
||||
const data = this.encodeContextMenuModel(context);
|
||||
if (!data) return {};
|
||||
const props = {
|
||||
"data-model": data,
|
||||
oncontextmenu: (event) => {
|
||||
window.MLOpenContextMenu?.(event, event.currentTarget);
|
||||
}
|
||||
};
|
||||
if (tooltip) {
|
||||
props["data-tooltip"] = tooltip;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
setContextMenuElement(element, context = null, tooltip = '') {
|
||||
if (!element) return;
|
||||
const data = this.encodeContextMenuModel(context);
|
||||
if (!data) {
|
||||
element.removeAttribute('data-model');
|
||||
element.removeAttribute('data-tooltip');
|
||||
element.oncontextmenu = null;
|
||||
return;
|
||||
}
|
||||
|
||||
element.dataset.model = data;
|
||||
if (tooltip) {
|
||||
element.dataset.tooltip = tooltip;
|
||||
} else {
|
||||
element.removeAttribute('data-tooltip');
|
||||
}
|
||||
element.oncontextmenu = (event) => {
|
||||
window.MLOpenContextMenu?.(event, event.currentTarget);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a colored confidence badge HTML
|
||||
* @param {number} confidence - Confidence percentage (0-100)
|
||||
@@ -110,13 +163,8 @@ export const renderFormatMethods = {
|
||||
const icon = icons[type] || icons.info;
|
||||
const contextMenuModel = options?.contextMenuModel || null;
|
||||
const contextMenuTooltip = options?.contextMenuTooltip || 'Right-click to open download folder';
|
||||
const contextMenuData = contextMenuModel
|
||||
? this.escapeHtml(encodeURIComponent(JSON.stringify(contextMenuModel)))
|
||||
: '';
|
||||
const contextMenuAttrs = contextMenuData
|
||||
? ` data-model="${contextMenuData}" oncontextmenu="window.MLOpenContextMenu(event, this)" data-tooltip="${this.escapeHtml(contextMenuTooltip)}"`
|
||||
: '';
|
||||
const className = contextMenuData
|
||||
const contextMenuAttrs = this.getContextMenuAttrs(contextMenuModel, contextMenuTooltip);
|
||||
const className = contextMenuAttrs
|
||||
? `mr-status mr-status-${type} mr-download-folder-context`
|
||||
: `mr-status mr-status-${type}`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user