Bandcamp Album Duration

Calculates and displays the total duration of a Bandcamp album on its page.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Bandcamp Album Duration
// @namespace   Violentmonkey Scripts
// @match       https://*.bandcamp.com/album/*
// @grant       none
// @version     1.0
// @author      Gemini
// @description Calculates and displays the total duration of a Bandcamp album on its page.
// @license     MIT
// ==/UserScript==

(() => {
  // --- SCRIPT START ---

  // Find the table containing the track list.
  const trackTable = document.getElementById('track_table');
  if (!trackTable) {
    console.log("Bandcamp Album Duration: Could not find track table.");
    return;
  }

  // Find the body of the table where tracks are listed.
  const trackTableBody = trackTable.querySelector('tbody');
  if (!trackTableBody) {
    console.log("Bandcamp Album Duration: Could not find track table body.");
    return;
  }

  // Select all elements that contain track durations.
  // Bandcamp uses a <span> with the class 'time' for this.
  const timeElements = trackTable.querySelectorAll('tr.track_row_view .time');
  if (timeElements.length === 0) {
    console.log("Bandcamp Album Duration: No track times found on this page.");
    return;
  }

  let totalSeconds = 0;

  // Iterate over each time element to sum up the duration.
  timeElements.forEach(timeEl => {
    // Get the time string (e.g., "03:40") and remove whitespace.
    const timeString = timeEl.textContent.trim();
    const parts = timeString.split(':');

    // Make sure the format is correct (MM:SS) before parsing.
    if (parts.length === 2) {
      const minutes = parseInt(parts[0], 10);
      const seconds = parseInt(parts[1], 10);

      // Add the duration of the current track (in seconds) to the total.
      if (!isNaN(minutes) && !isNaN(seconds)) {
        totalSeconds += (minutes * 60) + seconds;
      }
    }
  });

  // Function to format the total seconds back into a readable HH:MM:SS or MM:SS format.
  function formatDuration(totalSeconds) {
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor((totalSeconds % 3600) / 60);
    const seconds = totalSeconds % 60;

    // Helper to pad numbers with a leading zero if they are less than 10 (e.g., 5 -> "05").
    const pad = (num) => num.toString().padStart(2, '0');

    let formattedString = `${pad(minutes)}:${pad(seconds)}`;
    if (hours > 0) {
      formattedString = `${pad(hours)}:${formattedString}`;
    }

    return formattedString;
  }

  const formattedTime = formatDuration(totalSeconds);

  // --- Create and insert the new element ---

  // Create a new table row `<tr>` to hold our total duration info.
  const totalRow = document.createElement('tr');
  totalRow.style.borderTop = '1px solid rgba(255, 255, 255, 0.1)'; // Add a subtle separator line.

  // Create a table cell `<td>`. We use colspan="3" so it spans across
  // the play button, track number, and title columns.
  const totalCell = document.createElement('td');
  totalCell.colSpan = 3;

  // Style the cell to align the text to the right, similar to the track times.
  totalCell.style.textAlign = 'right';
  totalCell.style.padding = '8px 8px 8px 0'; // Give it some spacing.
  totalCell.style.fontWeight = 'bold';

  // Create a `<span>` for the text itself.
  const textSpan = document.createElement('span');

  // Use the 'secondaryText' class from Bandcamp to match the font color and style.
  textSpan.className = 'secondaryText';
  textSpan.textContent = `Total duration: ${formattedTime}`;

  // Assemble the elements: span -> cell -> row.
  totalCell.appendChild(textSpan);
  totalRow.appendChild(totalCell);

  // Add an empty cell to align with the "buy track" column.
  const emptyCell = document.createElement('td');
  emptyCell.colSpan = 2;
  totalRow.appendChild(emptyCell);

  // Append the newly created row to the end of the track list.
  trackTableBody.appendChild(totalRow);

  // --- SCRIPT END ---
})();