2022-02-05 03:35:42 +00:00
|
|
|
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){
|
|
|
|
var url = new URL(dc.href),
|
|
|
|
hash = url.hash.substring(1);
|
|
|
|
url.hash = '';
|
|
|
|
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);
|
|
|
|
if(hash) {
|
|
|
|
var targetEl = document.getElementById(hash);
|
|
|
|
if(targetEl) {
|
|
|
|
setTimeout(function() {
|
|
|
|
window.scrollTo({
|
|
|
|
top: targetEl.getBoundingClientRect().top,
|
|
|
|
behavior: 'smooth'
|
|
|
|
});
|
|
|
|
}, 500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
xhr.onerror = function(ev) {
|
|
|
|
location.assign(dc.href);
|
|
|
|
};
|
|
|
|
xhr.open('GET', url);
|
|
|
|
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 || {});
|