Date.prototype.getWeek = function() { var date = new Date(this.getTime()); date.setHours(0, 0, 0, 0); date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); var week1 = new Date(date.getFullYear(), 0, 4); return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7); } Date.prototype.getWeekYear = function() { var date = new Date(this.getTime()); date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); return date.getFullYear(); } window.fm = (function() { var fm = this; this.container = document.querySelector('.container'); this.headerBackground = null; this.originalHeaderBackground = null; this.defaultCoverImage = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png'; this.indexIsPlaying = false; this.indexPlayingDefaultCover = false; this.indexPlayingContainer = null; this.indexPlayingCover = null; this.indexPlayingTitle = null; this.indexPlayingArtist = null; this.indexLastNp = null; this.indexPlayingInterval = null; this.homeInterval = null; this.callByName = function(name, args) { var ref = window, parent = null, parts = name.split('.'); for(var i = 0; i < parts.length; ++i) { parent = ref; if(typeof ref[parts[i]] !== 'undefined') ref = ref[parts[i]]; else return; } if(typeof ref !== 'function') return; return ref.apply(parent, args); }; this.runFuncs = function(funcs) { for(var i = 0; i < funcs.length; ++i) fm.callByName(funcs[i][0], funcs[i].slice(1)); }; if(this.onload && Array.isArray(this.onload)) window.addEventListener('load', function() { fm.runFuncs(fm.onload); }); if(sessionStorage.getItem('header-bgs') === null || sessionStorage.getItem('header-bgs-loaded') < Date.now() - 86400000) { var hXhr = new XMLHttpRequest; hXhr.onload = function() { sessionStorage.setItem('header-bgs', hXhr.responseText); sessionStorage.setItem('header-bgs-loaded', Date.now()); }; hXhr.open('GET', '/header-bgs.json'); hXhr.send(); } this.dynloadCurrent = function() { return { components: { header: { title: document.title, is_index: document.body.classList.contains('index'), do_fullscreen_header: document.body.classList.contains('fullscreen-header'), is_now_playing: document.body.classList.contains('now-playing'), }, footer: { onload: this.onload || [], } }, raw_html: fm.container.innerHTML, }; }; this.dynloadApply = function(state) { if((state.components || {}).header) { document.title = state.components.header.title || ''; document.body.classList[state.components.header.is_index ? 'add' : 'remove']('index'); document.body.classList[state.components.header.do_fullscreen_header ? 'add' : 'remove']('fullscreen-header'); document.body.classList[state.components.header.is_now_playing ? 'add' : 'remove']('now-playing'); } if(typeof state.raw_html !== 'undefined') this.container.innerHTML = state.raw_html; if((state.components || {}).footer) { this.runFuncs(state.components.footer.onload || []); } fm.dynloadInit(); fm.setRandomHeaderBackgroundIfNotPlaying(); }; this.dynloadInit = function(initial) { if(initial) { history.replaceState(this.dynloadCurrent(), document.title, location.toString()); window.addEventListener('popstate', function(ev) { fm.dynloadApply(ev.state || {}); }); } var dynload = document.querySelectorAll('[data-fm-dynload]'); for(var i = 0; i < dynload.length; ++i) (function(dc){ dc.removeAttribute('data-fm-dynload'); dc.addEventListener('click', function(ev) { ev.stopPropagation(); ev.preventDefault(); var xhr = new XMLHttpRequest; xhr.onload = function() { try { var obj = JSON.parse(xhr.responseText); } catch(ex) {} if(!obj) { location.assign(dc.href); return; } var title = ((obj.components || {}).header || {}).title || ''; history.pushState(obj, title, dc.href); fm.dynloadApply(obj); }; xhr.onerror = function(ev) { location.assign(dc.href); }; xhr.open('GET', dc.href); xhr.setRequestHeader('Accept', 'application/x-fdynload+json'); xhr.send(); }, true); })(dynload[i]); }; this.dynloadInit(true); this.selectTextInElement = function(elem) { // MSIE if(document.body.createTextRange) { var range = document.body.createTextRange(); range.moveToElementText(elem); range.select(); return; } // Mozilla if(window.getSelection) { var select = window.getSelection(), range = document.createRange(); range.selectNodeContents(elem); select.removeAllRanges(); select.addRange(range); return; } console.warn('Unable to select text.'); }; this.copySelectedText = function() { if(document.execCommand) { document.execCommand('copy'); return; } console.warn('Unable to copy text.'); }; this.getNowListening = function(callback) { if(!callback) return; var xhr = new XMLHttpRequest; xhr.onreadystatechange = function() { if(xhr.readyState !== 4 || xhr.status !== 200) return; callback.call(this, JSON.parse(xhr.responseText)); }.bind(this); xhr.open('GET', '/now-listening.json'); xhr.send(); }; this.updateIndexNowListening = function() { window.fm.getNowListening(function(info) { if(this.indexLastNp === null || this.indexLastNp.url != info.url || this.indexLastNp.now_playing != info.now_playing) { if(this.indexLastNp !== null) this.originalHeaderBackground = this.getRandomHeaderBackground(); this.indexLastNp = info; } else return; this.indexIsPlaying = info.now_playing; this.indexPlayingDefaultCover = !info.cover || info.cover === this.defaultCoverImage; this.indexPlayingContainer.classList[info.now_playing ? 'remove' : 'add']('header-now-playing-hidden'); this.indexPlayingCover.alt = this.indexPlayingCover.src = (info.cover !== this.defaultCoverImage ? info.cover : '//now.flash.moe/resources/no-cover.png'); this.indexPlayingTitle.textContent = this.indexPlayingTitle.title = info.name; this.indexPlayingTitle.href = info.url; this.indexPlayingArtist.textContent = this.indexPlayingArtist.title = (info.artist || {}).name || ''; this.indexPlayingArtist.href = (info.artist || {}).url || ''; this.switchHeaderBackground( info.now_playing && !this.indexPlayingDefaultCover ? this.indexPlayingCover.src : this.originalHeaderBackground ); }); }; this.getRandomHeaderBackground = function() { var set = JSON.parse(sessionStorage.getItem('header-bgs')); if(!set) return '/assets/errors/404.jpg'; return set[parseInt(Math.random() * set.length) - 1]; }; this.setRandomHeaderBackground = function() { this.switchHeaderBackground(this.getRandomHeaderBackground()); }; this.setRandomHeaderBackgroundIfNotPlaying = function() { if(!this.indexIsPlaying || this.indexPlayingDefaultCover) this.setRandomHeaderBackground(); }; this.getCurrentHeaderBackground = function() { return this.headerBackground.querySelector('img').src; }; this.headerBackgroundIsChanging = false; this.switchHeaderBackground = function(url) { if(this.headerBackgroundIsChanging || this.getCurrentHeaderBackground() === url) return; this.headerBackgroundIsChanging = true; var newImg = document.createElement('img'), oldImg = this.headerBackground.querySelector('img'); newImg.alt = newImg.src = url; newImg.style.opacity = '0'; oldImg.style.zIndex = '-1'; newImg.style.zIndex = '0'; this.headerBackground.appendChild(newImg); newImg.onload = function() { setTimeout(function() { newImg.style.opacity = null; setTimeout(function() { newImg.style.zIndex = null; this.headerBackground.removeChild(oldImg); this.headerBackgroundIsChanging = false; }.bind(this), 500); }.bind(this), 50); }.bind(this); newImg.onerror = function() { this.headerBackgroundIsChanging = false; this.switchHeaderBackground(this.originalHeaderBackground); }.bind(this); }; this.headerBackground = document.querySelector('.header-background'); this.originalHeaderBackground = this.headerBackground.querySelector('img').src; this.initIndex = function(npInterval) { if(!this.indexPlayingContainer) { this.indexPlayingContainer = document.querySelector('.header-now-playing'); this.indexPlayingCover = window.fm.indexPlayingContainer.querySelector('.header-now-playing-cover img'); this.indexPlayingCover.onerror = function() { this.indexPlayingCover.src = '//now.flash.moe/resources/no-cover.png'; }.bind(this); this.indexPlayingTitle = window.fm.indexPlayingContainer.querySelector('.header-now-playing-title a'); this.indexPlayingArtist = window.fm.indexPlayingContainer.querySelector('.header-now-playing-artist a'); } if(this.indexPlayingInterval) { clearInterval(this.indexPlayingInterval); this.indexPlayingInterval = null; } this.updateIndexNowListening(); this.indexPlayingInterval = setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000); }; this.initClock = function() { if(this.homeInterval) return; var digitalClock = document.querySelector('.php-time-digital'), analogClock = document.querySelector('.php-time-analog'), dateZone = document.querySelector('.php-time-date'), digHours = digitalClock.querySelector('.php-time-digital-hours'), digSeparator = digitalClock.querySelector('.php-time-digital-separator'), digMinutes = digitalClock.querySelector('.php-time-digital-minutes'), angHours = analogClock.querySelector('.clock-hand-hours'), angMinutes = analogClock.querySelector('.clock-hand-minutes'), angSeconds = analogClock.querySelector('.clock-hand-seconds') dateWeek = dateZone.querySelector('.php-date-week'), dateDay = dateZone.querySelector('.php-date-day'), dateMonth = dateZone.querySelector('.php-date-month'), dateYear = dateZone.querySelector('.php-date-year'); this.homeInterval = setInterval(function() { if(!document.body.contains(digitalClock)) { clearInterval(this.homeInterval); this.homeInterval = null; return; } var time = new Date; var dHour = time.getHours(), dMin = time.getMinutes(); if(dHour < 10) dHour = '0' + dHour; if(dMin < 10) dMin = '0' + dMin; dateWeek.textContent = time.getWeek(); dateDay.textContent = time.getDate(); dateMonth.textContent = time.getMonth() + 1; dateYear.textContent = time.getFullYear(); digHours.textContent = dHour; digMinutes.textContent = dMin; digSeparator.classList[time.getSeconds() % 2 ? 'add' : 'remove']('php-time-digital-separator-hidden'); var rSec = time.getSeconds() / 60, rMin = (time.getMinutes() + Math.min(.99, rSec)) / 60, rHour = (time.getHours() + Math.min(.99, rMin)) / 12; angHours.style.setProperty('--hand-rotation', (rHour * 360).toString() + 'deg'); angMinutes.style.setProperty('--hand-rotation', (rMin * 360).toString() + 'deg'); angSeconds.style.setProperty('--hand-rotation', (rSec * 360).toString() + 'deg'); }.bind(this), 200); }; return this; }).call(window.fm || {});