Greasy Fork is available in English.

PTH Preview Tracks

Embed youtube clips for the tracks of a torrent group

// ==UserScript==
// @name         PTH Preview Tracks
// @version      3.0
// @description  Embed youtube clips for the tracks of a torrent group
// @author       Chameleon
// @include      http*://redacted.ch/torrents.php?*id=*
// @include      http*://redacted.ch/index.php
// @include      http*://redacted.ch/*threadid=1837*
// @grant        GM_xmlhttpRequest
// @connect      youtube.com
// @namespace https://greasyfork.org/users/87476
// ==/UserScript==

(function() {
  'use strict';

  if(!document.hidden)
    run();
  else
    document.addEventListener('visibilitychange', visibilityChanged);
}());

var scriptLoaded=false;

function visibilityChanged()
{
  if(!document.hidden && !scriptLoaded)
  {
    run();
    scriptLoaded=true;
  }
}

function run()
{
  //console.log(document.hidden);
  var settings=getSettings();

  if(settings.useYoutubeAPI)
  {
    // include youtube's elephant of an API
    var tag = document.createElement('script');

    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    // stop including
  }

  var wH=window.location.href;
  if(wH.indexOf('index.php') != -1 && settings.useYoutubeAPI && settings.masterPlayer)
  {
    loadPlayer();
  }
  else if(wH.indexOf('torrents.php') != -1)
    loadTorrent();
  else if(wH.indexOf('threadid=1837') != -1)
    showSettings();
}

function showSettings()
{
  var div=document.getElementById('ChameleonSettings');
  if(!div)
  {
    var before = document.getElementsByClassName('forum_post')[0];
    div = document.createElement('div');
    div.setAttribute('id', 'ChameleonSettings');
    before.parentNode.insertBefore(div, before);
    div.setAttribute('style', 'width: 100%; text-align: center; padding-bottom: 10px;');
    div.setAttribute('class', 'box');
  }
  div.innerHTML = '<h2>Preview Tracks Settings</h2><br />';
  var settings = getSettings();

  var a=document.createElement('a');
  a.href='javascript:void(0);';
  a.innerHTML = 'Master player on /index.php: '+(settings.masterPlayer ? 'On':'Off');
  a.addEventListener('click', changeSettings.bind(undefined, a, div), false);
  div.appendChild(a);
  div.appendChild(document.createElement('br'));

  var a=document.createElement('a');
  a.href='javascript:void(0);';
  a.innerHTML = 'Youtube API: '+(settings.useYoutubeAPI ? 'On':'Off');
  a.addEventListener('click', changeSettings.bind(undefined, a, div), false);
  div.appendChild(a);
  div.appendChild(document.createElement('br'));

  var a=document.createElement('a');
  a.href='javascript:void(0);';
  a.innerHTML = 'Minimize Track Preview: '+(settings.hideTrackPreview ? 'On':'Off');
  a.addEventListener('click', changeSettings.bind(undefined, a, div), false);
  div.appendChild(a);
  div.appendChild(document.createElement('br'));

  var a=document.createElement('a');
  a.href='javascript:void(0);';
  a.innerHTML = 'Force show separate preview area: '+(settings.alwaysShowExtraBox ? 'On':'Off');
  a.addEventListener('click', changeSettings.bind(undefined, a, div), false);
  div.appendChild(a);
  div.appendChild(document.createElement('br'));

  var input=document.createElement('input');
  input.placeholder = 'Youtube quality';
  input.value=settings.quality ? settings.quality:'';
  input.addEventListener('change', changeSettings.bind(undefined, undefined, div), false);
  div.appendChild(input);
  div.appendChild(document.createElement('br'));

  var input=document.createElement('input');
  input.placeholder = 'Youtube volume';
  input.type='number';
  input.value=settings.volume ? settings.volume:'';
  input.addEventListener('change', changeSettings.bind(undefined, undefined, div), false);
  div.appendChild(input);
  div.appendChild(document.createElement('br'));

  var input=document.createElement('input');
  input.placeholder = 'API Key';
  input.value=settings.apiKey ? settings.apiKey:'AIzaSyBkMKh0dR1lWSrr2Bia_JdRc1kv7Nue8H8';
  input.addEventListener('change', changeSettings.bind(undefined, undefined, div), false);
  div.appendChild(input);
  div.appendChild(document.createElement('br'));

  var a=document.createElement('a');
  div.appendChild(a);
  a.href='javascript:void(0);';
  a.innerHTML = 'Save';
}

function changeSettings(a, div)
{
  var settings=getSettings();
  var as=div.getElementsByTagName('a');

  if(a == as[0])
  {
    if(as[0].innerHTML.indexOf('Off') != -1) 
    {
      settings.masterPlayer = true;
    }
    else
      settings.masterPlayer = false;
  }

  if(a == as[1])
  {
    if(as[1].innerHTML.indexOf('Off') != -1) 
    {
      settings.useYoutubeAPI = true;
    }
    else
      settings.useYoutubeAPI = false;
  }

  if(a == as[2])
  {
    if(as[2].innerHTML.indexOf('Off') != -1) 
    {
      settings.hideTrackPreview = true;
    }
    else
      settings.hideTrackPreview = false;
  }

  if(a == as[3])
  {
    if(as[3].innerHTML.indexOf('Off') != -1)
    {
      settings.alwaysShowExtraBox = true;
    }
    else
      settings.alwaysShowExtraBox = false;
  }

  var inputs=div.getElementsByTagName('input');
  settings.quality=inputs[0].value;
  settings.volume=inputs[1].value;
  settings.apiKey=inputs[2].value;

  window.localStorage.previewTracksSettings = JSON.stringify(settings);
  showSettings();
}

function getSettings()
{
  var settings = window.localStorage.previewTracksSettings;
  if(!settings)
  {
    settings = {masterPlayer:false, useYoutubeAPI:true, alwaysShowExtraBox:false};
  }
  else
    settings = JSON.parse(settings);
  if(settings.useYoutubeAPI !== false)
    settings.useYoutubeAPI=true;
  return settings;
}

function waitForYT(messageDiv)
{
  messageDiv.innerHTML = 'Waiting on Youtube API to load';
  window.setTimeout(loadPlayer.bind(undefined, messageDiv), 1000);
}

function loadPlayer(messageDiv)
{
  var div=document.getElementById('youtubePlayerDiv');
  var thin=document.getElementsByClassName('thin')[0];
  if(!div)
  {
    div=document.createElement('div');
    div.setAttribute('id', 'youtubePlayerDiv');
    div.setAttribute('style', 'background: rgba(0,0,200,0.5); text-align: center; border-radius: 20px; padding-bottom: 10px;');
    thin.insertBefore(div, thin.firstElementChild);

    var messageDiv=document.createElement('div');
    div.appendChild(messageDiv);
  }

  if(typeof(YT) == "undefined")
  {
    waitForYT(messageDiv);
    return;
  }
  messageDiv.innerHTML = '';

  var header=document.createElement('div');
  div.appendChild(header);

  var youtubeDiv=document.createElement('div');
  youtubeDiv.setAttribute('id', 'playlistPlayer');
  div.appendChild(youtubeDiv);

  var playlist=getPlaylist();
  var youtube;
  if(playlist.length === 0)
  {
    messageDiv.innerHTML = 'no videos to play ';
    var a=document.createElement('a');
    messageDiv.appendChild(a);
    a.innerHTML = 'Reload playlist';
    a.href='javascript:void(0);';
    a.addEventListener('click', loadPlayer.bind(undefined, messageDiv), false);
    return;
  }
  else if(!playlist[0].track)
  {
    messageDiv.innerHTML = 'Old playlist, ';
    var a=document.createElement('a');
    messageDiv.appendChild(a);
    a.innerHTML = 'clear it and rebuild';
    a.href='javascript:void(0);';
    a.addEventListener('click', clearAndLoadPlayer.bind(undefined, messageDiv), false);
    return;
  }
  else
  {

    /*var width = thin.clientWidth-20;
    var height = Math.round(width/(16/9));
    youtube=new YT.Player('playlistPlayer', {
      height: height,
      width: width,
      events: {'onReady': playerReady, 'onStateChange': playerStateChanged.bind(undefined, messageDiv)}});*/

    playPlaylistVideo(messageDiv, youtube);
  }

  var a=document.createElement('a');
  a.innerHTML = 'Go to start of playlist';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', playlistResetIndex.bind(undefined, messageDiv, youtube), false);

  header.appendChild(document.createTextNode(' | '));
  var a=document.createElement('a');
  a.innerHTML = 'Clear playlist';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', playlistReset.bind(undefined, messageDiv, youtube), false);

  header.appendChild(document.createTextNode(' | '));
  var a=document.createElement('a');
  a.innerHTML = 'Play';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', playPlaylistVideo.bind(undefined, messageDiv, youtube), false);

  header.appendChild(document.createTextNode(' | '));
  var a=document.createElement('a');
  a.innerHTML = 'Next';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', playNextPlaylistVideo.bind(undefined, messageDiv, youtube), false);

  header.appendChild(document.createTextNode(' | '));
  var a=document.createElement('a');
  a.innerHTML = 'Previous';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', playPrevPlaylistVideo.bind(undefined, messageDiv, youtube), false);

  header.appendChild(document.createTextNode(' | '));
  var a=document.createElement('a');
  a.innerHTML = 'Show playlist';
  a.href='javascript:void(0);';
  header.appendChild(a);
  a.addEventListener('click', showPlaylist.bind(undefined, messageDiv), false);
}

function showPlaylist(messageDiv, onlyifopen)
{
  var div=document.getElementById('playlistDiv');
  if(!div && onlyifopen=="yes")
  {
    div=document.createElement('div');
    div.setAttribute('id', 'playlistDiv');
    div.setAttribute('style', 'margin: 10px; background: rgba(0,0,0,0.6); padding: 10px; border-radius: 10px;');
    var thin=document.getElementsByClassName('thin')[0];
    thin.insertBefore(div, thin.firstElementChild.nextElementSibling);
  }
  div.innerHTML = '';
  var headers=["", "", "Track", "Artist", "Album"];
  var baseHeaderStyle="display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;";
  var headersStyle=["width: 80px;", "width: 30px;", "width: 300px;", "width: 200px; text-align: center;", "width:200px; text-align: center;"];
  var hStyle="text-align: center;";
  var header=document.createElement('div');
  div.appendChild(header);
  for(var i=0; i<headers.length; i++)
  {
    var span=document.createElement('span');
    header.appendChild(span);
    span.innerHTML=headers[i];
    span.setAttribute('style', baseHeaderStyle+headersStyle[i]+hStyle);
  }
  var playlist=getPlaylist();
  var playlistIndex=getPlaylistIndex();
  for(var i=0; i<playlist.length; i++)
  {
    var p=playlist[i];

    var pDiv=document.createElement('div');
    pDiv.setAttribute('playlistItem', JSON.stringify(p));
    if(i===parseInt(playlistIndex))
    {
      pDiv.setAttribute('style', 'background: rgba(0,128,128,0.5);');
    }
    div.appendChild(pDiv);

    var span=document.createElement('span');
    span.setAttribute('style', baseHeaderStyle+headersStyle[0]);
    pDiv.appendChild(span);
    //span.innerHTML = "Up / Down";
    var a=document.createElement('a');
    span.appendChild(a);
    a.innerHTML = '-';
    a.href='javascript:void(0);';
    a.addEventListener('click', removePlaylist.bind(undefined, messageDiv, i), false);
    span.appendChild(document.createTextNode(' / '));
    var a=document.createElement('a');
    span.appendChild(a);
    a.innerHTML = 'Up';
    a.href='javascript:void(0);';
    a.addEventListener('click', movePlaylistUp.bind(undefined, messageDiv, i), false);
    span.appendChild(document.createTextNode(' / '));
    var a=document.createElement('a');
    span.appendChild(a);
    a.innerHTML = 'Down';
    a.href='javascript:void(0);';
    a.addEventListener('click', movePlaylistDown.bind(undefined, messageDiv, i), false);

    var span=document.createElement('span');
    span.setAttribute('style', baseHeaderStyle+headersStyle[1]);
    pDiv.appendChild(span);
    span.innerHTML = i+1;

    var span=document.createElement('a');
    span.setAttribute('style', baseHeaderStyle+headersStyle[2]);
    pDiv.appendChild(span);
    span.innerHTML = p.track;
    span.href='javascript:void(0);';
    span.addEventListener('click', playIndex.bind(undefined, messageDiv, i), false);

    var span=document.createElement('span');
    span.setAttribute('style', baseHeaderStyle+headersStyle[3]);
    pDiv.appendChild(span);
    span.innerHTML = p.artist === '' ? '<Unknown>':p.artist;

    var span=document.createElement('span');
    span.setAttribute('style', baseHeaderStyle+headersStyle[4]);
    pDiv.appendChild(span);
    span.innerHTML = p.album;
  }
}

function removePlaylist(messageDiv, index)
{
  var playlist=getPlaylist();
  playlist.splice(index, 1);
  savePlaylist(playlist);
  showPlaylist(messageDiv);
}

function movePlaylistUp(messageDiv, index)
{
  if(index === 0)
    return;

  var playlist=getPlaylist();
  playlist.splice(index-1, 0, playlist.splice(index, 1)[0]);
  if(index === parseInt(getPlaylistIndex()))
    setPlaylistIndex(index-1);
  savePlaylist(playlist);
  showPlaylist(messageDiv);
}

function movePlaylistDown(messageDiv, index)
{
  var playlist=getPlaylist();
  if(index > playlist.length-2)
    return;

  playlist.splice(index+1, 0, playlist.splice(index, 1)[0]);
  if(index === parseInt(getPlaylistIndex()))
    setPlaylistIndex(index+1);
  savePlaylist(playlist);
  showPlaylist(messageDiv); 
}

function playIndex(messageDiv, index)
{
  setPlaylistIndex(index);
  playPlaylistVideo(messageDiv);
}

function clearAndLoadPlayer(messageDiv)
{
  playlistReset(messageDiv);
  loadPlayer(messageDiv);
}

function playNextPlaylistVideo(messageDiv)
{
  setPlaylistIndex(parseInt(getPlaylistIndex())+1);
  playPlaylistVideo(messageDiv);
}

function playPrevPlaylistVideo(messageDiv)
{
  var index=parseInt(getPlaylistIndex())-1;
  if(index<0)
    index=0;
  setPlaylistIndex(index);
  playPlaylistVideo(messageDiv);
}

function playlistReset(messageDiv)
{
  savePlaylist([]);
  setPlaylistIndex(0);
}

function playlistResetIndex(messageDiv)
{
  setPlaylistIndex(0);
  playPlaylistVideo(messageDiv);
}

function playPlaylistVideo(messageDiv)
{
  messageDiv.innerHTML = 'loading video';
  var index=getPlaylistIndex();
  var playlist=getPlaylist();
  if(index >= playlist.length)
  {
    messageDiv.innerHTML = 'Finished playlist';
    return;
  }
  showPlaylist(messageDiv, "yes");
  var settings=getSettings();
  var search=encodeURIComponent((playlist[index].artist+' '+playlist[index].track).trim());
  var xhr = new XMLHttpRequest();
  var apikey=settings.apiKey?settings.apiKey:'AIzaSyBkMKh0dR1lWSrr2Bia_JdRc1kv7Nue8H8';
  xhr.open('GET', "https://www.googleapis.com/youtube/v3/search?part=snippet&order=relevance&type=video&key="+apikey+"&q="+search);
  xhr.onreadystatechange = xhr_func.bind(undefined, messageDiv, xhr, playPlayer.bind(undefined, messageDiv), playPlaylistVideo.bind(undefined, messageDiv));
  xhr.send();
}

function playPlayer(messageDiv, response)
{
  messageDiv.innerHTML = 'Got videos';
  /*if(typeof(youtube.loadVideoById) == "undefined")
  {
    window.setTimeout(playPlayer.bind(undefined, messageDiv, youtube, response), 500);
    return;
  }*/
  var data=JSON.parse(response);
  if(data.items.length === 0)
  {
    messageDiv.innerHTML = "Couldn't find any videos :(";
    window.setTimeout(clear.bind(undefined, messageDiv), 5000);
    setPlaylistIndex(parseInt(getPlaylistIndex())+1);
    return;
  }

  var videoId=data.items[0].id.videoId;

  var iframe = document.getElementById('playlistPlayer');
  var t=iframe.parentNode;
  var prev=document.getElementById('playlistPlayer');
  if(prev)
    prev.parentNode.removeChild(prev);
  iframe=document.createElement('div');
  iframe.setAttribute('id', 'playlistPlayer');
  t.appendChild(iframe);
  var width = iframe.parentNode.clientWidth-20;
  var height = Math.round(width/(16/9));
  console.log(videoId);
  console.log(YT);
  new YT.Player('playlistPlayer', {
    height: height,
    width: width,
    videoId: videoId,
    events: {'onReady': playerReady, 'onStateChange': playerStateChanged.bind(undefined, messageDiv)}});
}

function playerReady(event)
{
  event.target.playVideo();
  var settings=getSettings();
  if(settings.quality && settings.quality.length > '')
    event.target.setPlaybackQuality(settings.quality);
}

function playerStateChanged(messageDiv, event)
{
  if(event.target.getPlayerState() === 0)
  {
    setPlaylistIndex(parseInt(getPlaylistIndex())+1);
    playPlaylistVideo(messageDiv);
  }
  if(event.data == YT.PlayerState.BUFFERING)
  {
    var settings=getSettings();
    if(settings.quality && settings.quality.length > '')
      event.target.setPlaybackQuality(settings.quality);
    if(settings.volume)
      event.target.setVolume(settings.volume);
  }
}

function getPlaylistIndex()
{
  var playlistIndex=window.localStorage.youtubeIndex;
  if(!playlistIndex)
    playlistIndex=0;
  return playlistIndex;
}

function setPlaylistIndex(index)
{
  window.localStorage.youtubeIndex=index;
}

function getPlaylist()
{
  var playlist=window.localStorage.youtubePlaylist;
  if(!playlist)
    playlist=[];
  else
    playlist=JSON.parse(playlist);
  return playlist;
}

function savePlaylist(playlist)
{
  window.localStorage.youtubePlaylist = JSON.stringify(playlist);
}

function loadTorrent()
{
  var settings=getSettings();
  var h2 = document.getElementsByTagName('h2')[0];
  var artist = h2.getElementsByTagName('a');
  if(artist.length > 0)
    artist = artist[0].innerHTML;
  else
    artist = '';
  var tracks = document.getElementsByClassName('torrent_description')[0].getElementsByClassName('postlist');
  var tD=document.getElementsByClassName('torrent_description')[0].textContent;
  if(tD.indexOf('discogs.com') != -1 && tD.indexOf('/release/') != -1)
  {
    var discogs_release=parseInt(tD.split('/release/')[1]);
    doDiscogs(discogs_release);
  }
  else if(tracks.length > 0 && !settings.alwaysShowExtraBox)
  {
    var s=document.createElement('span');
    var a=document.createElement('a');
    s.appendChild(a);
    a.innerHTML = 'Close Videos';
    a.href='javascript:void(0);';
    a.addEventListener('click', closeIframes, false);
    tracks[0].parentNode.insertBefore(s, tracks[0]);
    tracks=tracks[0].getElementsByTagName('li');

    if(settings.useYoutubeAPI)
    {
      var a=document.createElement('a');
      s.appendChild(document.createTextNode(' '));
      s.appendChild(a);
      a.innerHTML = '(enqueue all)';
      a.href='javascript:void(0);';
      var album=h2.getElementsByTagName('span')[0].textContent;
      a.addEventListener('click', enqueueTracks.bind(undefined, a, tracks, artist, album), false);
    }
    doTracks(artist, tracks);
  }
  else
  {
    tracks=makePreview(getTracks);
    doTracks(artist, tracks);
  }
}

function doDiscogs(id)
{
  var messageDiv=document.getElementById('previewTracksMessages');
  if(!messageDiv)
  {
    messageDiv=document.createElement('div');
    messageDiv.setAttribute('style', 'position: fixed; background: rgba(0,0,0,0.7); top: 50px; margin: auto; left: 0; right: 0; text-align: center; font-size: 2em;');
    messageDiv.setAttribute('id', 'previewTracksMessages');
    document.body.appendChild(messageDiv);
  }
  messageDiv.innerHTML = 'Getting tracklist from discogs.com';

  var xhr = new XMLHttpRequest();
  xhr.open('GET', "https://api.discogs.com/releases/"+id);
  xhr.onreadystatechange = xhr_func.bind(undefined, messageDiv, xhr, gotDiscogs.bind(undefined, messageDiv), doDiscogs.bind(undefined, id));
  xhr.send();
}

function gotDiscogs(messageDiv, response)
{
  messageDiv.innerHTML = '';
  var r=JSON.parse(response);
  console.log(r.tracklist);

  var tracks=makePreview(getDiscogTracks.bind(undefined, r.tracklist));

  doTracks(r.artists[0].name.split('(')[0], tracks);
}

function getDiscogTracks(tracks)
{
  var result=[];
  for(var i=0; i<tracks.length; i++)
  {
    if(tracks[i].title.length > 0)
      result.push(tracks[i].title);
  }
  return result;
}

function doTracks(artist, tracks)
{
  var settings=getSettings();
  for(var i=0; i<tracks.length; i++)
  {
    var input=document.createElement('input');
    var t=tracks[i];
    var track=t.textContent;
    input.value=(artist+' '+track).trim();
    t.innerHTML = '';
    var span=document.createElement('span');
    var a=document.createElement('a');
    a.href='javascript:void(0);';
    a.setAttribute('class', 'previewLinks');
    a.innerHTML = track;
    a.addEventListener('click', preview.bind(undefined, a, t, span, artist, track, i, input), false);
    t.appendChild(a);
    t.appendChild(document.createTextNode(' '));
    if(settings.useYoutubeAPI)
    {
      var a=document.createElement('a');
      a.href='javascript:void(0);';
      a.innerHTML = '(enqueue)';
      var album=document.getElementsByTagName('h2')[0].getElementsByTagName('span')[0].textContent;
      a.addEventListener('click', enqueueTrack.bind(undefined, a, artist, track, album), false);
      t.appendChild(a);
      t.appendChild(document.createTextNode(' '));
    }
    var a=document.createElement('a');
    a.href='javascript:void(0);';
    a.innerHTML = '(show search)';
    a.addEventListener('click', toggleShow.bind(undefined, input, a), false);
    t.appendChild(a);
    t.appendChild(document.createTextNode(' '));
    t.appendChild(input);
    input.style.display='none';
    t.appendChild(span);
  }
}

function toggleShow(el, link)
{
  if(el.style.display=='none')
  {
    link.innerHTML=link.innerHTML.replace(/show/, 'hide');
    el.style.display='';
  }
  else
  {
    link.innerHTML=link.innerHTML.replace(/hide/, 'show');
    el.style.display='none';    
  }
}

function enqueueTrack(a, artist, track, album)
{
  var playlist=getPlaylist();
  playlist.push({artist:artist, album:album, track:track});
  savePlaylist(playlist);
  a.innerHTML = '(enqueued)';
}

function enqueueTracks(a, trackLis, artist, album)
{
  var playlist=getPlaylist();
  for(var i=0; i<trackLis.length; i++)
  {
    playlist.push({artist:artist, album:album, track:trackLis[i].getElementsByTagName('a')[0].textContent.trim()});
  }
  savePlaylist(playlist);
  a.innerHTML='(enqueued all)';
}

function closeIframes()
{
  var prev=document.getElementById('previewIframe');
  if(prev)
    prev.parentNode.removeChild(prev);
}

function toggle(div)
{
  if(div.style.display == 'none')
    div.style.display = 'initial';
  else
    div.style.display = 'none';
}

function makePreview(getTracksFunc)
{
  var settings=getSettings();
  var div=document.createElement('div');
  div.setAttribute('class', 'box torrent_description');
  var before=document.getElementsByClassName('torrent_description')[0];
  before.parentNode.insertBefore(div, before);
  var clone=before.getElementsByClassName('head')[0].cloneNode(true);
  div.appendChild(clone);
  clone.getElementsByTagName('strong')[0].innerHTML = 'Track Preview';
  var body=document.createElement('div');
  if(settings.hideTrackPreview)
    body.style.display='none';
  var a=document.createElement('a');
  a.href='javascript:void(0);';
  a.innerHTML = '(toggle)';
  clone.appendChild(document.createTextNode(' '));
  clone.appendChild(a);
  a.addEventListener('click', toggle.bind(undefined, body), false);
  var a=document.createElement('a');
  a.setAttribute('style', 'float: right;');
  a.innerHTML='Settings';
  a.href='/forums.php?action=viewthread&threadid=1837';
  clone.appendChild(a);
  div.appendChild(body);
  body.setAttribute('class', 'body');
  body.innerHTML = 'Track List:<br />';
  var a=document.createElement('a');
  a.innerHTML = 'Close Videos';
  a.href='javascript:void(0);';
  a.addEventListener('click', closeIframes, false);
  body.appendChild(a);
  var tracks=getTracksFunc();

  if(settings.useYoutubeAPI)
  {
    var a=document.createElement('a');
    body.appendChild(document.createTextNode(' '));
    body.appendChild(a);
    a.innerHTML = '(enqueue all)';
    a.href='javascript:void(0);';
  }

  var ol=document.createElement('ol');
  ol.setAttribute('class', 'postlist');
  body.appendChild(ol);
  var result = [];
  for(var i=0; i<tracks.length; i++)
  {
    var li=document.createElement('li');
    li.innerHTML = tracks[i];
    ol.appendChild(li);
    result.push(li);
  }

  if(settings.useYoutubeAPI)
  {
    var h2 = document.getElementsByTagName('h2')[0];
    var artist = h2.getElementsByTagName('a');
    if(artist.length > 0)
      artist = artist[0].innerHTML;
    else
      artist = '';
    var album=h2.getElementsByTagName('span')[0].textContent;
    a.addEventListener('click', enqueueTracks.bind(undefined, a, result, artist, album), false);
  }

  return result;
}

function getTracks(offset)
{
  if(!offset)
    offset=0;
  var torrent_row = document.getElementsByClassName('torrent_row')[offset];
  var type = torrent_row.getElementsByTagName('a');
  type = type[type.length-1].innerHTML.split(' / ')[0].toLowerCase();
  var filelist = document.getElementsByClassName('filelist_table')[offset].getElementsByTagName('tr');
  var files=[];
  for(var i=1; i<filelist.length; i++)
  {
    var f=filelist[i].getElementsByTagName('td')[0].innerHTML;
    if(f.indexOf(type) != f.length-type.length)
      continue;
    var f1 = f.split('/');
    if(f1.length > 1)
      f=f1[f1.length-1];
    f1 = f.split(f.match(/\d+/));
    if(f1.length > 1)
      f=f1[1];
    f = f.replace(/^[0-9]+\.?/, '').replace(/ - /g, ' ').replace(new RegExp("."+type), '').replace(/_/g, ' ').replace(/-/g, ' ');
    var artist = document.getElementsByTagName('h2')[0].getElementsByTagName('a');
    if(artist.length > 0)
      artist = artist[0].innerHTML;
    else
      artist='';
    var l=f.toLowerCase().indexOf(artist.toLowerCase());
    if( l != -1)
      f=f.substr(0, l)+f.substr(l+artist.length);
    //f = f.split('(')[0];
    files.push(f);
  }
  if(files.length === 0)
    return getTracks(offset+1);
  return files;
}

function preview(a, t, span, artist, track, index1, input)
{
  var existingSearch=a.getAttribute('search');
  if(existingSearch == input.value)
  {
    var videoIds = t.getAttribute('videoIds');
    if(videoIds)
    {
      var index = parseInt(t.getAttribute('index'));
      videoIds = JSON.parse(videoIds);
      if(index >= videoIds.length)
      {
        span.innerHTML = 'Already on last video';
        window.setTimeout(clear.bind(undefined, span), 5000);
        return;
      }
      addEmbed(t, span, videoIds[index]);
      t.setAttribute('index', index+1);
      return;
    }
  }
  a.setAttribute('search', input.value);
  t.parentNode.setAttribute('index', index1);
  span.innerHTML = 'Getting videos';
  //track = track.split('(')[0];
  var xhr = new XMLHttpRequest();
  var settings=getSettings();
  var apikey=settings.apiKey?settings.apiKey:'AIzaSyBkMKh0dR1lWSrr2Bia_JdRc1kv7Nue8H8';
  var search=input.value.trim();
  //xhr.open('GET', "https://gdata.youtube.com/feeds/api/videos?v=2&alt=json&orderby=relevance&q="+encodeURIComponent(artist+' '+track));
  //xhr.open('GET', "https://www.googleapis.com/youtube/v3/search?part=snippet&order=relevance&type=video&key="+apikey+"&q="+encodeURIComponent(search));
  /*console.log('https://www.youtube.com/results?search_query='+encodeURIComponent(search));
  return;
  xhr.open('GET', 'https://www.youtube.com/results?search_query='+encodeURIComponent(search));
  xhr.onreadystatechange = xhr_func.bind(undefined, span, xhr, previewing.bind(undefined, t, span), preview.bind(undefined, a, t, span, artist, track, input));
  xhr.send();
  */
  GM_xmlhttpRequest({
    method:'GET',
    url:'https://www.youtube.com/results?search_query='+encodeURIComponent(search),
    onload:function(xhr)
    {
      if(xhr.readyState == 4 && xhr.status==200)
      {
        previewing(t, span, xhr);
      }
    }
  });
}

function previewing(t, span, response)
{
  span.innerHTML = 'Got videos';
  /*
  var data=JSON.parse(response);
  if(data.items.length === 0)
  {
    span.innerHTML = "Couldn't find any videos :(";
    window.setTimeout(clear.bind(undefined, span), 5000);
    return;
  }
  var videoIds = [];
  for(var i=0; i<data.items.length; i++)
  {
    videoIds.push(data.items[i].id.videoId);
  }
  */
  var videoIds=[];
  /*var newDoc=document.implementation.createHTMLDocument();
  newDoc.body.innerHTML=response.responseText;
  var as=newDoc.querySelectorAll('a.ytd-thumbnail');
  console.log(response.responseText);
  for(var i=0; i<as.length; i++)
  {
    var a=as[i];
    if(a.href.indexOf('watch?v=')==-1)
      continue;
    videoIds.push(a.href.split('watch?v=')[1]);
  }
  */
  var splits=response.responseText.split('"videoId":"');
  for(var i=1; i<splits.length-1; i++)
  {
    videoIds.push(splits[i].split('"')[0]);
  }
  if(videoIds.length === 0)
  {
    span.innerHTML = "Couldn't find any videos :(";
    window.setTimeout(clear.bind(undefined, span), 5000);
    return;
  }
  t.setAttribute('videoIds', JSON.stringify(videoIds));
  t.setAttribute('index', 1);

  addEmbed(t, span, videoIds[0]);
}

function addEmbed(t, span, videoId)
{
  var settings=getSettings();
  var iframe = t.getElementsByTagName('iframe');
  if(iframe.length === 0)
  {
    var prev=document.getElementById('previewIframe');
    if(prev)
      prev.parentNode.removeChild(prev);
    if(settings.useYoutubeAPI)
    {
      iframe=document.createElement('div');
      iframe.setAttribute('id', 'previewIframe');
      t.appendChild(iframe);
      var width = t.parentNode.clientWidth-20;
      var height = Math.round(width/(16/9));
      new YT.Player('previewIframe', {
        height: height,
        width: width,
        videoId: videoId,
        events: {'onReady': previewReady, 'onStateChange': previewStateChanged}});
    }
    else
    {
      iframe = document.createElement('iframe');
      iframe.setAttribute('id', 'previewIframe');
      t.appendChild(iframe);
      iframe.width = t.parentNode.clientWidth-20;
      iframe.height = iframe.width/(16/9);
      iframe.setAttribute('allowfullscreen', 'true');
      iframe.frameBorder='0';
    }
  }
  else
    iframe = iframe[0];
  iframe.src='https://www.youtube.com/embed/'+videoId+'?autoplay=1';
  //iframe.setAttribute('autoplay', true);
  span.innerHTML = ' Added youtube embed';
  var link=document.getElementById('youtubeLink');
  if(link)
    link.parentNode.removeChild(link);
  link=document.createElement('a');
  span.parentNode.insertBefore(link, span);
  link.href='https://youtu.be/'+videoId;
  link.innerHTML='(Link)';
  link.id='youtubeLink';
  window.setTimeout(clear.bind(undefined, span), 5000);
}

function previewReady(event)
{
  event.target.playVideo();
  var settings=getSettings();
  if(settings.quality && settings.quality.length > '')
    event.target.setPlaybackQuality(settings.quality);
}

function previewStateChanged(event)
{
  if(event.target.getPlayerState() === 0)
  {
    //console.log('ended');
    var as=document.getElementsByClassName('previewLinks');
    var index=parseInt(as[0].parentNode.parentNode.getAttribute('index'))+1;
    if(index < as.length)
      as[index].click();
  }
  if(event.data == YT.PlayerState.BUFFERING)
  {
    var settings=getSettings();
    if(settings.quality && settings.quality.length > '')
      event.target.setPlaybackQuality(settings.quality);
    if(settings.volume)
      event.target.setVolume(settings.volume);
  }
}

function clear(span)
{
  span.innerHTML = '';
}

function xhr_func(messageDiv, xhr, func, repeatFunc)
{
  if(xhr.readyState == 4)
  {
    if(xhr.status == 200)
      func(xhr.responseText);
    else
    {
      messageDiv.innerHTML = 'Error: '+xhr.status+'<br />retrying in 1 second';
      window.setTimeout(repeatFunc, 1000);
    }
  }
}