dynamic loading and like one animation, closes #1!
This commit is contained in:
parent
0af2b7303a
commit
493ad2cb9b
6 changed files with 248 additions and 56 deletions
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
$quotes = isset($quotes) && is_array($quotes) ? $quotes : FM_FEET;
|
||||
$baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
|
||||
|
||||
if(empty($is_index)):
|
||||
?>
|
||||
</div>
|
||||
<?php endif; if(empty($hide)): ?>
|
||||
<div class="footer">
|
||||
<div class="footer-text">© flashwave 2010-<?=date('Y');?> - <?=($quotes[array_rand($quotes)]);?></div>
|
||||
</div>
|
||||
<?php if(isset($onload) && is_array($onload)): ?>
|
||||
<script type="text/javascript">
|
||||
window.fm = { onload: <?=json_encode($onload);?> };
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
<script src="<?=$baseUrl;?>/assets/2020v2.js" charset="utf-8" type="text/javascript"></script>
|
||||
<?php if(isset($scripts) && is_array($scripts)) foreach($scripts as $script): ?>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
$menu = isset($menu) && is_array($menu) ? $menu : FM_NAV;
|
||||
$backgrounds = isset($backgrounds) && is_array($backgrounds) ? $backgrounds : FM_BGS;
|
||||
$baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
|
||||
$showNowPlaying = !empty($is_index) || !empty($do_fullscreen_header);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
@ -16,20 +17,20 @@ $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
|
|||
<link href="<?=$style;?>" type="text/css" rel="stylesheet"/>
|
||||
<?php endforeach;?>
|
||||
</head>
|
||||
<body class="<?php if(isset($is_index)) { echo 'index';} if(isset($do_fullscreen_header)) { echo 'fullscreen-header';} ?>">
|
||||
<body class="<?php if(isset($is_index)) { echo 'index ';} if(isset($do_fullscreen_header)) { echo 'fullscreen-header ';} if(isset($is_now_playing)) { echo 'now-playing ';} ?>">
|
||||
<div class="header">
|
||||
<div class="header-background">
|
||||
<img src="<?=($backgrounds[array_rand($backgrounds)]);?>" alt=""/>
|
||||
</div>
|
||||
<div class="header-foreground"<?php if(isset($offset) && $offset > 0) echo " style=\"padding-bottom: {$offset}px\""; ?>>
|
||||
<a class="header-logo" href="/">
|
||||
<a class="header-logo" href="/" data-fm-dynload="">
|
||||
<div class="header-flash">flash</div>
|
||||
<div class="header-wave">wave</div>
|
||||
</a>
|
||||
<?php if(!empty($is_index) || !empty($do_fullscreen_header)): ?>
|
||||
<div class="header-right">
|
||||
<div class="header-now-playing header-now-playing-hidden">
|
||||
<div class="header-now-playing-icon" title="Now listening to...">
|
||||
<a href="/now-listening"><div class="fmi fmi-music"></div></a>
|
||||
<a href="/now-listening" data-fm-dynload=""><div class="fmi fmi-music"></div></a>
|
||||
</div>
|
||||
<div class="header-now-playing-cover">
|
||||
<img src="//now.flash.moe/resources/no-cover.png" alt=""/>
|
||||
|
@ -39,15 +40,12 @@ $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
|
|||
<div class="header-now-playing-artist"><a href="#" target="_blank" rel="noopener"></a></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="header-menu">
|
||||
<?php foreach($menu as $link): ?>
|
||||
<a href="<?=$link['link'];?>"><?=$link['title'];?></a>
|
||||
<a href="<?=$link['link'];?>"<?php if($link['link'][0] === '/' && substr($link['link'], 0, 2) !== '//') { echo ' data-fm-dynload=""'; } ?>><?=$link['title'];?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if(empty($is_index) && empty($do_fullscreen_header)): ?>
|
||||
</div>
|
||||
<div class="container">
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -30,13 +30,14 @@ if($reqPath === '/now-listening') {
|
|||
fm_component('header', [
|
||||
'title' => 'flash.moe / now listening',
|
||||
'do_fullscreen_header' => true,
|
||||
'is_now_playing' => true,
|
||||
'offset' => $offset,
|
||||
]);
|
||||
?>
|
||||
<script>window.addEventListener('load', function() { window.fm.initIndex(10); });</script>
|
||||
<?php
|
||||
fm_component('footer', [
|
||||
'hide' => true,
|
||||
'onload' => [
|
||||
['fm.initIndex', 10],
|
||||
],
|
||||
]);
|
||||
|
||||
return FM_HIT;
|
||||
|
@ -88,11 +89,14 @@ if($reqPath === '/home') {
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script>window.addEventListener('load', function() { window.fm.initClock(); window.fm.initIndex(10); });</script>
|
||||
<?php
|
||||
fm_component('footer', [
|
||||
'hide' => true,
|
||||
'skip_analytics' => true,
|
||||
'onload' => [
|
||||
['fm.initClock'],
|
||||
['fm.initIndex', 10],
|
||||
],
|
||||
]);
|
||||
|
||||
return FM_HIT;
|
||||
|
@ -180,7 +184,7 @@ if($reqPath === '/') {
|
|||
?>
|
||||
<div class="index-menu">
|
||||
<?php for($i = 1; $i < count(FM_NAV); ++$i): ?>
|
||||
<a href="<?=(FM_NAV[$i]['link']);?>"><?=(FM_NAV[$i]['title']);?></a>
|
||||
<a href="<?=(FM_NAV[$i]['link']);?>"<?php if(FM_NAV[$i]['link'][0] === '/' && substr(FM_NAV[$i]['link'], 0, 2) !== '//') { echo ' data-fm-dynload=""'; } ?>><?=(FM_NAV[$i]['title']);?></a>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<div class="index-featured">
|
||||
|
@ -267,10 +271,12 @@ foreach($projInfo as $proj):
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>window.addEventListener('load', function() { window.fm.initIndex(); });</script>
|
||||
<?php
|
||||
fm_component('footer', [
|
||||
'is_index' => true,
|
||||
'onload' => [
|
||||
['fm.initIndex'],
|
||||
],
|
||||
]);
|
||||
|
||||
return FM_HIT;
|
||||
|
|
|
@ -16,6 +16,10 @@ html {
|
|||
scrollbar-color: #4a3650 #111;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* an attempt to replicate scrollbar-color for chromosome */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
|
@ -46,6 +50,7 @@ body {
|
|||
width: 100%;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
transition: height .5s;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
.header { height: auto; }
|
||||
|
@ -120,10 +125,21 @@ body {
|
|||
background-image: linear-gradient(0deg, #281430 0%, #392540 50%, #4a3650 50%, #6c5871 100%);
|
||||
-webkit-background-clip: text;
|
||||
}
|
||||
.header-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.header-menu {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex: 0 0 auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.index .header-menu,
|
||||
.fullscreen-header .header-menu,
|
||||
.now-playing .header-menu {
|
||||
display: none;
|
||||
}
|
||||
.header-menu a {
|
||||
display: block;
|
||||
|
@ -167,6 +183,11 @@ body {
|
|||
}
|
||||
|
||||
.footer {}
|
||||
.index .footer,
|
||||
.fullscreen-header .footer,
|
||||
.now-playing .footer {
|
||||
display: none;
|
||||
}
|
||||
.footer-text {
|
||||
opacity: .2;
|
||||
font-size: .9em;
|
||||
|
|
|
@ -12,14 +12,43 @@ Date.prototype.getWeekYear = function() {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -32,6 +61,83 @@ window.fm = (function() {
|
|||
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) {
|
||||
|
@ -86,14 +192,16 @@ window.fm = (function() {
|
|||
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.indexPlayingArtist.textContent = this.indexPlayingArtist.title = (info.artist || {}).name || '';
|
||||
this.indexPlayingArtist.href = (info.artist || {}).url || '';
|
||||
this.switchHeaderBackground(
|
||||
info.now_playing && info.cover !== this.defaultCoverImage
|
||||
info.now_playing && !this.indexPlayingDefaultCover
|
||||
? this.indexPlayingCover.src
|
||||
: this.originalHeaderBackground
|
||||
);
|
||||
|
@ -104,20 +212,27 @@ window.fm = (function() {
|
|||
var set = JSON.parse(sessionStorage.getItem('header-bgs'));
|
||||
if(!set)
|
||||
return '/assets/errors/404.jpg';
|
||||
return set[parseInt(Math.random() * set.length)];
|
||||
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.getCurrentHeaderBackground() === 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;
|
||||
|
@ -131,10 +246,12 @@ window.fm = (function() {
|
|||
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);
|
||||
};
|
||||
|
@ -143,6 +260,7 @@ window.fm = (function() {
|
|||
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() {
|
||||
|
@ -150,11 +268,21 @@ window.fm = (function() {
|
|||
}.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();
|
||||
setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000);
|
||||
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'),
|
||||
|
@ -169,7 +297,13 @@ window.fm = (function() {
|
|||
dateMonth = dateZone.querySelector('.php-date-month'),
|
||||
dateYear = dateZone.querySelector('.php-date-year');
|
||||
|
||||
setInterval(function() {
|
||||
this.homeInterval = setInterval(function() {
|
||||
if(!document.body.contains(digitalClock)) {
|
||||
clearInterval(this.homeInterval);
|
||||
this.homeInterval = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var time = new Date;
|
||||
|
||||
var dHour = time.getHours(),
|
||||
|
@ -196,7 +330,7 @@ window.fm = (function() {
|
|||
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');
|
||||
}, 200);
|
||||
}.bind(this), 200);
|
||||
};
|
||||
|
||||
return this;
|
||||
|
|
|
@ -67,7 +67,17 @@ define('FM_ERRS' , [
|
|||
],
|
||||
]);
|
||||
|
||||
define('FM_DYNLOAD', filter_input(INPUT_SERVER, 'HTTP_ACCEPT') === 'application/x-fdynload+json');
|
||||
|
||||
function fm_component(string $_component_name, array $vars = []) {
|
||||
if(FM_DYNLOAD) {
|
||||
global $fmComponentVars;
|
||||
if(!isset($fmComponentVars))
|
||||
$fmComponentVars = [];
|
||||
$fmComponentVars[$_component_name] = $vars;
|
||||
return;
|
||||
}
|
||||
|
||||
extract($vars);
|
||||
require __DIR__ . '/../components/' . $_component_name . '.php';
|
||||
}
|
||||
|
@ -129,6 +139,9 @@ if($reqMethod == 'HEAD') {
|
|||
$reqHead = true;
|
||||
}
|
||||
|
||||
if(FM_DYNLOAD)
|
||||
ob_start();
|
||||
|
||||
if(substr($reqPath, 0, 7) === '/error/') {
|
||||
$statusCode = intval(substr($reqPath, 7, 3));
|
||||
} else {
|
||||
|
@ -138,17 +151,24 @@ if(substr($reqPath, 0, 7) === '/error/') {
|
|||
if(($result & FM_HIT) === FM_HIT) {
|
||||
if($statusCode >= 100 && $statusCode <= 999)
|
||||
http_response_code($statusCode);
|
||||
return;
|
||||
else
|
||||
$statusCode = 200;
|
||||
break;
|
||||
}
|
||||
if(($result & FM_ERR) === FM_ERR)
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we have a valid error code
|
||||
if($statusCode < 100)
|
||||
$statusCode = 404;
|
||||
}
|
||||
|
||||
$errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404];
|
||||
http_response_code($errorInfo['code']);
|
||||
if($statusCode >= 400 && $statusCode <= 599 && ob_get_length() < 1) {
|
||||
$errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404];
|
||||
http_response_code($errorInfo['code']);
|
||||
|
||||
if(!$reqHead) {
|
||||
if(!$reqHead) {
|
||||
fm_component('header', ['title' => $errorInfo['title']]);
|
||||
?>
|
||||
<div class="http-error">
|
||||
|
@ -158,4 +178,16 @@ if(!$reqHead) {
|
|||
</div>
|
||||
<?php
|
||||
fm_component('footer');
|
||||
}
|
||||
}
|
||||
|
||||
if(FM_DYNLOAD) {
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
header('Content-Type: application/x-fdynload+json');
|
||||
echo json_encode([
|
||||
'components' => $fmComponentVars ?? [],
|
||||
'raw_html' => $contents,
|
||||
]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue