Improve 8bcDump

Improve the interface of the public 8bitcollective archive on brkbrkbrk.com.

目前为 2017-03-29 提交的版本。查看 最新版本

// ==UserScript==
// @name        Improve 8bcDump
// @namespace   Improve8bcDump
// @description Improve the interface of the public 8bitcollective archive on brkbrkbrk.com.
// @include     http://brkbrkbrk.com/8bcdump/
// @include     https://brkbrkbrk.com/8bcdump/
// @include     http://www.brkbrkbrk.com/8bcdump/
// @include     https://www.brkbrkbrk.com/8bcdump/
// @version     0.3.1
// @grant       none
// ==/UserScript==

(function() {
  console.log('Improve8bcDump v0.3.1 is active.');

  // Fix a wrong attribute on the page's external stylesheet.
  var stylesheet = document.querySelector('link[type="text/stylesheet"]');
  stylesheet.setAttribute('type', 'text/css');

  // The currently playing song should appear bold in the last played list.
  
  var newStyles = document.createElement('style');
  newStyles.textContent += '.lastPlayed li:first-child { font-weight: bold; }';
  newStyles.textContent += '.lastPlayed li:first-child:after { content: " (playing)" }';
  document.body.appendChild(newStyles);
  
  // Create a stack for the last played songs.
  // The stack is realized in an <ol>, contained in parentElement.
  
  function LastPlayedList(maxLength, parentElement) {
    // Create a heading for the last played list
    var heading = document.createElement('h2');
    heading.textContent = 'Last played';
    parentElement.appendChild(heading);
    
    // Create the list itself
    var list = document.createElement('ol');
    list.classList.add('lastPlayed');
    parentElement.appendChild(list);
    
    // Push songs through the stack
    this.push = function(song) {
      var nodes = list.childNodes;
      
      if (nodes.length == maxLength) {
        list.removeChild(nodes[nodes.length - 1]);
      }
      
      var newItem = document.createElement('li');
      newItem.textContent = song;
      
      list.insertBefore(newItem, nodes[0]);
    }
  }
  
  // Create a list at the bottom of the page to hold the last 10 songs
  var lastPlayedDiv = document.createElement('div');
  document.body.appendChild(lastPlayedDiv);
  var lastPlayedList = new LastPlayedList(10, lastPlayedDiv);
  
  // The player at the bottom of the page should also show the filename when playing songs,
  // and the song's information should be added to the last played list.
  
  // Override the existing updateID3 method
  
  window.updateID3Mutex = true;

  window.updateID3 = function(id3) {
    if (!window.updateID3Mutex) return;
    window.updateID3Mutex = false;

    var filename = document.querySelector('li.playing a').textContent;
    var songDesc = 'Title: ' + id3.title + ', Artist: ' + id3.artist + ', Album: ' + id3.album + ', Filename: ' + filename;
    
    window.liID3.textContent = songDesc;
    lastPlayedList.push(songDesc);

    window.updateID3Mutex = true;
  }

  // Add more buttons to the player interface

  // The <audio> element
  var audio = window.tP.el;

  var tPControls = document.querySelector('ul.tpControls');

  var ffLi = document.createElement('li');
  ffLi.classList.add('ff');

  // The player control buttons use Font Awesome icons
  var fastForwardButton = document.createElement('i');
  fastForwardButton.classList.add('fa', 'fa-fast-forward');

  ffLi.style.marginLeft = '0.25em';

  ffLi.appendChild(fastForwardButton);
  tPControls.appendChild(ffLi);

  // Shuffle button uses a checkbox
  var shuffleLi = document.createElement('li');
  shuffleLi.classList.add('shuffle');

  var shuffleButton = document.createElement('input');
  shuffleButton.setAttribute('type', 'checkbox');

  var shuffleText = document.createTextNode('Shuffle?');
  shuffleLi.style.marginLeft = '1em';

  shuffleLi.appendChild(shuffleText);
  shuffleLi.appendChild(shuffleButton);
  tPControls.appendChild(shuffleLi);

  // The fast forward button triggers the 'ended' event on the audio player.
  fastForwardButton.addEventListener('click', function() {
    audio.dispatchEvent(new CustomEvent('ended'));
  });

  // The <a> of the song currently being played
  var currentSongLinkEl = function() {
    return document.getElementById(window.index).querySelector('a');
  };

  var randomSongLinkEl = function() {
    var xs = window.archiveAs;
    return xs[Math.floor(Math.random() * xs.length)];
  };

  audio.addEventListener('ended', function() {
    // Manually triggering a click event on the next song fixes an issue with updating the ID3 information.
    // This is a hack -- since Javascript doesn't provide an interface for removing the old event listeners,
    // I'll just wait 50ms to ensure mine runs last.
    // At this point, window.index has already been incremented, so currentSongLinkEl() will point to an unplayed song.
    setTimeout(function() {
      var nextSong = shuffleButton.checked ? randomSongLinkEl() : currentSongLinkEl();
      nextSong.click();
    }, 50);
  });
}());