var fnp = { defaultCoverFnp: '/resources/no-cover.png', defaultCoverLfm: 'https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png', watch: { interval: 15 * 1000, userName: '', timeOut: 0, stopping: false, }, ui: { mode: '', bgSwitch: false, currBg: '', coverSwitch: false, currCover: '', }, }; fnp.goIndex = function() { location.hash = ''; }; fnp.switchUser = function(userName) { location.hash = '#/' + encodeURIComponent((userName ?? '').toString()); }; fnp.updateHash = function() { var userName = decodeURIComponent(location.hash.substring(2)); this.ui.setBackgroundFade(); this.ui.goLoading(); if(userName.length > 0) { this.watch.start(userName, function(response) { if(response.error) { this.goIndex(); alert(response.error); return; } var coverUrl = response[0].images.extralarge; if(coverUrl.length < 1 || coverUrl === this.defaultCoverLfm) coverUrl = this.defaultCoverFnp; this.ui.setBackground(coverUrl); this.ui.setCover(coverUrl); this.ui.setTitle(response[0].name, response[0].url); this.ui.setArtist(response[0].artist.name, response[0].artist.url); this.ui.setCurrentUser(userName, 'https://www.last.fm/user/' + encodeURIComponent(userName)); this.ui.setNowListening(response[0].nowplaying || false); this.ui.goUser(); }.bind(this)); } else { this.watch.stop(function() { this.ui.goIndex(); }.bind(this)); } }; fnp.watch.start = function(userName, callback) { this.stop(); this.userName = userName = (userName || '').toString(); this.callback = function(response) { if(this.stopping) return; if(response.error) this.stop(); else this.timeOut = setTimeout(this.fetch.bind(this), this.interval); callback(response); }; this.callback.bind(this); this.fetch(); }; fnp.watch.stop = function(callback) { if(this.stopping) return; this.stopping = true; if(this.timeOut !== 0) { clearTimeout(this.timeOut); this.timeOut = 0; } this.userName = ''; if(callback) callback(); this.stopping = false; }; fnp.watch.fetch = function() { if(typeof this.callback !== 'function') return; var xhr = new XMLHttpRequest; xhr.onreadystatechange = function() { if(xhr.readyState !== 4) return; this.callback(JSON.parse(xhr.responseText)); }.bind(this); xhr.open('GET', '/get.php?u=' + encodeURIComponent(this.userName)); xhr.send(); }; fnp.ui.setMode = function(modeName) { modeName = (modeName || '').toString(); if(this.mode === modeName) return; this.mode = modeName; for(var i = 0; i < this.modes.length; ++i) { var mode = this.modes[i]; mode.elem.classList[mode.name === modeName ? 'remove' : 'add']('hidden'); } }; fnp.ui.goIndex = function() { this.setMode('index'); }; fnp.ui.goUser = function() { this.setMode('user'); }; fnp.ui.goLoading = function() { this.setMode('loading'); }; fnp.ui.setBackground = function(bgPath) { if(bgPath === '::fade') { this.setBackgroundFade(); return; } if(this.iColourFade !== 0) { clearInterval(this.iColourFade); this.iColourFade = 0; } this.eBg.style.backgroundColor = null; this.switchBackground(bgPath); }; fnp.ui.switchBackground = function(bgPath) { if(bgPath === this.currBg) return; if(this.bgSwitch) { setTimeout(this.switchBackground.bind(this, bgPath), 1000); return; } this.bgSwitch = true; this.currBg = bgPath; while(this.eBg.children.length > 2) this.eBg.removeChild(this.eBg.firstChild); var newBg = null, hasNewBg = !!bgPath, oldBg = this.eBg.firstChild, hasOldBg = !!oldBg; if(hasOldBg) oldBg.style.zIndex = '-1'; if(hasNewBg) { newBg = document.createElement('img'); newBg.alt = newBg.src = bgPath; newBg.style.opacity = '0'; newBg.style.zIndex = '1'; newBg.onload = function() { setTimeout(function() { newBg.style.opacity = null; setTimeout(function() { newBg.style.zIndex = null; if(hasOldBg) this.eBg.removeChild(oldBg); this.bgSwitch = false; }.bind(this), 500); }.bind(this), 50); }.bind(this); newBg.onerror = function() { this.eBg.removeChild(newBg); newBg = null; hasNewBg = false; this.bgSwitch = false; }.bind(this); this.eBg.appendChild(newBg); } else if(hasOldBg) { oldBg.style.opacity = '0'; setTimeout(function() { this.eBg.removeChild(oldBg); this.bgSwitch = false; }.bind(this), 500); } else { this.bgSwitch = false; } }; fnp.ui.removeBackground = function() { this.switchBackground(''); }; fnp.ui.setBackgroundFade = function() { if(this.iColourFade !== 0) return; this.removeBackground(); var fader = function() { var colour = Math.floor(Math.random() * 0xFFFFFF).toString(16); if(colour.length !== 6 && colour.length !== 3) colour = '000000'.substring(colour.length) + colour; this.eBg.style.backgroundColor = '#' + colour; }.bind(this); this.iColourFade = setInterval(fader, 2000); fader(); }; fnp.ui.setCover = function(coverUrl) { this.switchCover(coverUrl); }; fnp.ui.switchCover = function(coverUrl) { if(coverUrl === this.currCover) return; if(this.coverSwitch) { setTimeout(this.switchCover.bind(this, coverUrl), 1000); return; } this.coverSwitch = true; this.currCover = coverUrl; while(this.eInfoCover.children.length > 2) this.eInfoCover.removeChild(this.eInfoCover.firstChild); var newCover = null, hasNewCover = !!coverUrl, oldCover = this.eInfoCover.firstChild, hasOldCover = !!oldCover; if(hasOldCover) oldCover.style.zIndex = '-1'; if(hasNewCover) { newCover = document.createElement('img'); newCover.alt = newCover.src = coverUrl; newCover.style.opacity = '0'; newCover.style.zIndex = '1'; newCover.onload = function() { setTimeout(function() { newCover.style.opacity = null; setTimeout(function() { newCover.style.zIndex = null; if(hasOldCover) this.eInfoCover.removeChild(oldCover); this.coverSwitch = false; }.bind(this), 500); }.bind(this), 50); }.bind(this); newCover.onerror = function() { this.eInfoCover.removeChild(newCover); newCover = null; hasNewBg = false; this.coverSwitch = false; }.bind(this); this.eInfoCover.appendChild(newCover); } else if(hasOldCover) { oldCover.style.opacity = '0'; setTimeout(function() { this.eInfoCover.removeChild(oldCover); this.coverSwitch = false; }.bind(this), 500); } else { this.coverSwitch = false; } }; fnp.ui.removeCover = function() { this.switchCover(''); }; fnp.ui.setTitle = function(title, url) { this.eInfoTitle.textContent = (title || '').toString(); if(url) this.eInfoTitle.href = url.toString(); }; fnp.ui.setArtist = function(title, url) { this.eInfoArtist.textContent = (title || '').toString(); if(url) this.eInfoArtist.href = url.toString(); }; fnp.ui.setCurrentUser = function(title, url) { this.eInfoUser.textContent = (title || '').toString(); if(url) this.eInfoUser.href = url.toString(); }; fnp.ui.setNowListening = function(state) { this.eInfoFlags.innerHTML = ''; if(state) { var nowIcon = document.createElement('span'); nowIcon.className = 'fa fa-music'; nowIcon.title = 'Now playing'; this.eInfoFlags.appendChild(nowIcon); } }; window.onload = function() { fnp.ui.eIndex = document.getElementById('index'); fnp.ui.eUser = document.getElementById('user'); fnp.ui.eLoading = document.getElementById('loading'); fnp.ui.eBg = document.getElementById('background'); fnp.ui.eFormUser = document.getElementById('username'); fnp.ui.eFormSend = document.getElementById('submit'); fnp.ui.eInfoCover = document.getElementById('np_cover'); fnp.ui.eInfoTitle = document.getElementById('np_title'); fnp.ui.eInfoArtist = document.getElementById('np_artist'); fnp.ui.eInfoUser = document.getElementById('np_user'); fnp.ui.eInfoBack = document.getElementById('np_back'); fnp.ui.eInfoFlags = document.getElementById('np_flags'); fnp.ui.iColourFade = 0; fnp.ui.modes = [ { name: 'index', elem: fnp.ui.eIndex }, { name: 'user', elem: fnp.ui.eUser }, { name: 'loading', elem: fnp.ui.eLoading }, ]; fnp.ui.eInfoBack.onclick = function() { fnp.goIndex(); }; window.onhashchange = function() { fnp.updateHash(); }; fnp.ui.eFormSend.onclick = function() { fnp.switchUser(fnp.ui.eFormUser.value); }; fnp.ui.eFormUser.onkeydown = function(ev) { if(typeof ev.key === 'undefined') ev.key = ev.keyCode === 13 ? 'Enter' : '?'; if(ev.key === 'Enter' || ev.key === 'NumpadEnter') fnp.switchUser(fnp.ui.eFormUser.value); }; fnp.updateHash(); };