blastoise/public/trackComponent.js

86 lines
2.5 KiB
JavaScript

// MusicRoom - Track Component
// Pure rendering for track rows - no event handlers attached
(function() {
const M = window.MusicRoom;
/**
* Render a track row element (pure rendering, no handlers)
* @param {Object} track - Track object with id, title, filename, duration
* @param {Object} config - Configuration options
* @param {string} config.view - 'queue' | 'library' | 'playlist'
* @param {number} config.index - Index in the list
* @param {number} [config.displayIndex] - Display number (1-based)
* @param {boolean} config.isSelected - Whether track is selected
* @param {boolean} config.isCached - Whether track is cached locally
* @param {boolean} config.isActive - Whether this is the currently playing track
* @param {boolean} config.draggable - Whether element is draggable
* @returns {HTMLElement}
*/
function render(track, config) {
const {
view,
index,
displayIndex,
isSelected,
isCached,
isActive,
draggable
} = config;
const div = document.createElement("div");
const trackId = track.id || track.filename;
// Build class list
const classes = ["track"];
if (isActive) classes.push("active");
if (isCached) classes.push("cached");
else classes.push("not-cached");
if (isSelected) classes.push("selected");
div.className = classes.join(" ");
// Store data attributes
div.dataset.index = index;
div.dataset.trackId = trackId;
div.dataset.view = view;
// Build title
const title = track.title?.trim() || (track.filename || trackId || "Unknown").replace(/\.[^.]+$/, "");
div.title = title;
// Build HTML
const checkmark = isSelected ? '<span class="track-checkmark">✓</span>' : '';
const trackNum = displayIndex != null ? `<span class="track-number">${displayIndex}.</span>` : '';
div.innerHTML = `
${checkmark}
<span class="cache-indicator"></span>
${trackNum}
<span class="track-title">${escapeHtml(title)}</span>
<span class="track-actions">
<span class="duration">${M.fmt(track.duration)}</span>
</span>
`;
if (draggable) {
div.draggable = true;
}
return div;
}
// HTML escape helper
function escapeHtml(str) {
if (!str) return '';
return str.replace(/[&<>"']/g, c => ({
'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
})[c]);
}
// Export
M.trackComponent = {
render,
escapeHtml
};
})();