dynamic loading and like one animation, closes #1!

This commit is contained in:
flash 2020-10-30 13:43:48 +00:00
parent 0af2b7303a
commit 493ad2cb9b
6 changed files with 248 additions and 56 deletions

View file

@ -1,14 +1,15 @@
<?php <?php
$quotes = isset($quotes) && is_array($quotes) ? $quotes : FM_FEET; $quotes = isset($quotes) && is_array($quotes) ? $quotes : FM_FEET;
$baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST']; $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
if(empty($is_index)):
?> ?>
</div> </div>
<?php endif; if(empty($hide)): ?>
<div class="footer"> <div class="footer">
<div class="footer-text">&copy; flashwave 2010-<?=date('Y');?> - <?=($quotes[array_rand($quotes)]);?></div> <div class="footer-text">&copy; flashwave 2010-<?=date('Y');?> - <?=($quotes[array_rand($quotes)]);?></div>
</div> </div>
<?php if(isset($onload) && is_array($onload)): ?>
<script type="text/javascript">
window.fm = { onload: <?=json_encode($onload);?> };
</script>
<?php endif; ?> <?php endif; ?>
<script src="<?=$baseUrl;?>/assets/2020v2.js" charset="utf-8" type="text/javascript"></script> <script src="<?=$baseUrl;?>/assets/2020v2.js" charset="utf-8" type="text/javascript"></script>
<?php if(isset($scripts) && is_array($scripts)) foreach($scripts as $script): ?> <?php if(isset($scripts) && is_array($scripts)) foreach($scripts as $script): ?>

View file

@ -2,6 +2,7 @@
$menu = isset($menu) && is_array($menu) ? $menu : FM_NAV; $menu = isset($menu) && is_array($menu) ? $menu : FM_NAV;
$backgrounds = isset($backgrounds) && is_array($backgrounds) ? $backgrounds : FM_BGS; $backgrounds = isset($backgrounds) && is_array($backgrounds) ? $backgrounds : FM_BGS;
$baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST']; $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
$showNowPlaying = !empty($is_index) || !empty($do_fullscreen_header);
?> ?>
<!doctype html> <!doctype html>
<html> <html>
@ -16,20 +17,20 @@ $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST'];
<link href="<?=$style;?>" type="text/css" rel="stylesheet"/> <link href="<?=$style;?>" type="text/css" rel="stylesheet"/>
<?php endforeach;?> <?php endforeach;?>
</head> </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">
<div class="header-background"> <div class="header-background">
<img src="<?=($backgrounds[array_rand($backgrounds)]);?>" alt=""/> <img src="<?=($backgrounds[array_rand($backgrounds)]);?>" alt=""/>
</div> </div>
<div class="header-foreground"<?php if(isset($offset) && $offset > 0) echo " style=\"padding-bottom: {$offset}px\""; ?>> <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-flash">flash</div>
<div class="header-wave">wave</div> <div class="header-wave">wave</div>
</a> </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 header-now-playing-hidden">
<div class="header-now-playing-icon" title="Now listening to..."> <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>
<div class="header-now-playing-cover"> <div class="header-now-playing-cover">
<img src="//now.flash.moe/resources/no-cover.png" alt=""/> <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 class="header-now-playing-artist"><a href="#" target="_blank" rel="noopener"></a></div>
</div> </div>
</div> </div>
<?php else: ?>
<div class="header-menu"> <div class="header-menu">
<?php foreach($menu as $link): ?> <?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; ?> <?php endforeach; ?>
</div> </div>
<?php endif; ?>
</div> </div>
</div> </div>
<?php if(empty($is_index) && empty($do_fullscreen_header)): ?> </div>
<div class="container"> <div class="container">
<?php endif; ?>

View file

@ -30,13 +30,14 @@ if($reqPath === '/now-listening') {
fm_component('header', [ fm_component('header', [
'title' => 'flash.moe / now listening', 'title' => 'flash.moe / now listening',
'do_fullscreen_header' => true, 'do_fullscreen_header' => true,
'is_now_playing' => true,
'offset' => $offset, 'offset' => $offset,
]); ]);
?>
<script>window.addEventListener('load', function() { window.fm.initIndex(10); });</script>
<?php
fm_component('footer', [ fm_component('footer', [
'hide' => true, 'hide' => true,
'onload' => [
['fm.initIndex', 10],
],
]); ]);
return FM_HIT; return FM_HIT;
@ -88,11 +89,14 @@ if($reqPath === '/home') {
</div> </div>
</form> </form>
</div> </div>
<script>window.addEventListener('load', function() { window.fm.initClock(); window.fm.initIndex(10); });</script>
<?php <?php
fm_component('footer', [ fm_component('footer', [
'hide' => true, 'hide' => true,
'skip_analytics' => true, 'skip_analytics' => true,
'onload' => [
['fm.initClock'],
['fm.initIndex', 10],
],
]); ]);
return FM_HIT; return FM_HIT;
@ -180,7 +184,7 @@ if($reqPath === '/') {
?> ?>
<div class="index-menu"> <div class="index-menu">
<?php for($i = 1; $i < count(FM_NAV); ++$i): ?> <?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; ?> <?php endfor; ?>
</div> </div>
<div class="index-featured"> <div class="index-featured">
@ -267,10 +271,12 @@ foreach($projInfo as $proj):
</div> </div>
</div> </div>
</div> </div>
<script>window.addEventListener('load', function() { window.fm.initIndex(); });</script>
<?php <?php
fm_component('footer', [ fm_component('footer', [
'is_index' => true, 'is_index' => true,
'onload' => [
['fm.initIndex'],
],
]); ]);
return FM_HIT; return FM_HIT;

View file

@ -16,6 +16,10 @@ html {
scrollbar-color: #4a3650 #111; scrollbar-color: #4a3650 #111;
} }
.hidden {
display: none !important;
}
/* an attempt to replicate scrollbar-color for chromosome */ /* an attempt to replicate scrollbar-color for chromosome */
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 6px; width: 6px;
@ -46,6 +50,7 @@ body {
width: 100%; width: 100%;
height: 200px; height: 200px;
overflow: hidden; overflow: hidden;
transition: height .5s;
} }
@media (max-width: 700px) { @media (max-width: 700px) {
.header { height: auto; } .header { height: auto; }
@ -120,10 +125,21 @@ body {
background-image: linear-gradient(0deg, #281430 0%, #392540 50%, #4a3650 50%, #6c5871 100%); background-image: linear-gradient(0deg, #281430 0%, #392540 50%, #4a3650 50%, #6c5871 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
} }
.header-right {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.header-menu { .header-menu {
display: flex; display: flex;
justify-content: center; justify-content: center;
flex: 0 0 auto; flex: 0 0 auto;
margin-top: 10px;
}
.index .header-menu,
.fullscreen-header .header-menu,
.now-playing .header-menu {
display: none;
} }
.header-menu a { .header-menu a {
display: block; display: block;
@ -167,6 +183,11 @@ body {
} }
.footer {} .footer {}
.index .footer,
.fullscreen-header .footer,
.now-playing .footer {
display: none;
}
.footer-text { .footer-text {
opacity: .2; opacity: .2;
font-size: .9em; font-size: .9em;

View file

@ -12,14 +12,43 @@ Date.prototype.getWeekYear = function() {
} }
window.fm = (function() { window.fm = (function() {
var fm = this;
this.container = document.querySelector('.container');
this.headerBackground = null; this.headerBackground = null;
this.originalHeaderBackground = null; this.originalHeaderBackground = null;
this.defaultCoverImage = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png'; this.defaultCoverImage = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png';
this.indexIsPlaying = false;
this.indexPlayingDefaultCover = false;
this.indexPlayingContainer = null; this.indexPlayingContainer = null;
this.indexPlayingCover = null; this.indexPlayingCover = null;
this.indexPlayingTitle = null; this.indexPlayingTitle = null;
this.indexPlayingArtist = null; this.indexPlayingArtist = null;
this.indexLastNp = 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 if(sessionStorage.getItem('header-bgs') === null
|| sessionStorage.getItem('header-bgs-loaded') < Date.now() - 86400000) { || sessionStorage.getItem('header-bgs-loaded') < Date.now() - 86400000) {
@ -32,6 +61,83 @@ window.fm = (function() {
hXhr.send(); 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) { this.selectTextInElement = function(elem) {
// MSIE // MSIE
if(document.body.createTextRange) { if(document.body.createTextRange) {
@ -86,14 +192,16 @@ window.fm = (function() {
this.indexLastNp = info; this.indexLastNp = info;
} else return; } 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.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.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.textContent = this.indexPlayingTitle.title = info.name;
this.indexPlayingTitle.href = info.url; this.indexPlayingTitle.href = info.url;
this.indexPlayingArtist.textContent = this.indexPlayingArtist.title = info.artist.name; this.indexPlayingArtist.textContent = this.indexPlayingArtist.title = (info.artist || {}).name || '';
this.indexPlayingArtist.href = info.artist.url; this.indexPlayingArtist.href = (info.artist || {}).url || '';
this.switchHeaderBackground( this.switchHeaderBackground(
info.now_playing && info.cover !== this.defaultCoverImage info.now_playing && !this.indexPlayingDefaultCover
? this.indexPlayingCover.src ? this.indexPlayingCover.src
: this.originalHeaderBackground : this.originalHeaderBackground
); );
@ -104,20 +212,27 @@ window.fm = (function() {
var set = JSON.parse(sessionStorage.getItem('header-bgs')); var set = JSON.parse(sessionStorage.getItem('header-bgs'));
if(!set) if(!set)
return '/assets/errors/404.jpg'; return '/assets/errors/404.jpg';
return set[parseInt(Math.random() * set.length)]; return set[parseInt(Math.random() * set.length) - 1];
}; };
this.setRandomHeaderBackground = function() { this.setRandomHeaderBackground = function() {
this.switchHeaderBackground(this.getRandomHeaderBackground()); this.switchHeaderBackground(this.getRandomHeaderBackground());
}; };
this.setRandomHeaderBackgroundIfNotPlaying = function() {
if(!this.indexIsPlaying || this.indexPlayingDefaultCover)
this.setRandomHeaderBackground();
};
this.getCurrentHeaderBackground = function() { this.getCurrentHeaderBackground = function() {
return this.headerBackground.querySelector('img').src; return this.headerBackground.querySelector('img').src;
}; };
this.headerBackgroundIsChanging = false;
this.switchHeaderBackground = function(url) { this.switchHeaderBackground = function(url) {
if(this.getCurrentHeaderBackground() === url) if(this.headerBackgroundIsChanging || this.getCurrentHeaderBackground() === url)
return; return;
this.headerBackgroundIsChanging = true;
var newImg = document.createElement('img'), var newImg = document.createElement('img'),
oldImg = this.headerBackground.querySelector('img'); oldImg = this.headerBackground.querySelector('img');
newImg.alt = newImg.src = url; newImg.alt = newImg.src = url;
@ -131,10 +246,12 @@ window.fm = (function() {
setTimeout(function() { setTimeout(function() {
newImg.style.zIndex = null; newImg.style.zIndex = null;
this.headerBackground.removeChild(oldImg); this.headerBackground.removeChild(oldImg);
this.headerBackgroundIsChanging = false;
}.bind(this), 500); }.bind(this), 500);
}.bind(this), 50); }.bind(this), 50);
}.bind(this); }.bind(this);
newImg.onerror = function() { newImg.onerror = function() {
this.headerBackgroundIsChanging = false;
this.switchHeaderBackground(this.originalHeaderBackground); this.switchHeaderBackground(this.originalHeaderBackground);
}.bind(this); }.bind(this);
}; };
@ -143,6 +260,7 @@ window.fm = (function() {
this.originalHeaderBackground = this.headerBackground.querySelector('img').src; this.originalHeaderBackground = this.headerBackground.querySelector('img').src;
this.initIndex = function(npInterval) { this.initIndex = function(npInterval) {
if(!this.indexPlayingContainer) {
this.indexPlayingContainer = document.querySelector('.header-now-playing'); this.indexPlayingContainer = document.querySelector('.header-now-playing');
this.indexPlayingCover = window.fm.indexPlayingContainer.querySelector('.header-now-playing-cover img'); this.indexPlayingCover = window.fm.indexPlayingContainer.querySelector('.header-now-playing-cover img');
this.indexPlayingCover.onerror = function() { this.indexPlayingCover.onerror = function() {
@ -150,11 +268,21 @@ window.fm = (function() {
}.bind(this); }.bind(this);
this.indexPlayingTitle = window.fm.indexPlayingContainer.querySelector('.header-now-playing-title a'); this.indexPlayingTitle = window.fm.indexPlayingContainer.querySelector('.header-now-playing-title a');
this.indexPlayingArtist = window.fm.indexPlayingContainer.querySelector('.header-now-playing-artist a'); this.indexPlayingArtist = window.fm.indexPlayingContainer.querySelector('.header-now-playing-artist a');
}
if(this.indexPlayingInterval) {
clearInterval(this.indexPlayingInterval);
this.indexPlayingInterval = null;
}
this.updateIndexNowListening(); this.updateIndexNowListening();
setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000); this.indexPlayingInterval = setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000);
}; };
this.initClock = function() { this.initClock = function() {
if(this.homeInterval)
return;
var digitalClock = document.querySelector('.php-time-digital'), var digitalClock = document.querySelector('.php-time-digital'),
analogClock = document.querySelector('.php-time-analog'), analogClock = document.querySelector('.php-time-analog'),
dateZone = document.querySelector('.php-time-date'), dateZone = document.querySelector('.php-time-date'),
@ -169,7 +297,13 @@ window.fm = (function() {
dateMonth = dateZone.querySelector('.php-date-month'), dateMonth = dateZone.querySelector('.php-date-month'),
dateYear = dateZone.querySelector('.php-date-year'); 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 time = new Date;
var dHour = time.getHours(), var dHour = time.getHours(),
@ -196,7 +330,7 @@ window.fm = (function() {
angHours.style.setProperty('--hand-rotation', (rHour * 360).toString() + 'deg'); angHours.style.setProperty('--hand-rotation', (rHour * 360).toString() + 'deg');
angMinutes.style.setProperty('--hand-rotation', (rMin * 360).toString() + 'deg'); angMinutes.style.setProperty('--hand-rotation', (rMin * 360).toString() + 'deg');
angSeconds.style.setProperty('--hand-rotation', (rSec * 360).toString() + 'deg'); angSeconds.style.setProperty('--hand-rotation', (rSec * 360).toString() + 'deg');
}, 200); }.bind(this), 200);
}; };
return this; return this;

View file

@ -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 = []) { function fm_component(string $_component_name, array $vars = []) {
if(FM_DYNLOAD) {
global $fmComponentVars;
if(!isset($fmComponentVars))
$fmComponentVars = [];
$fmComponentVars[$_component_name] = $vars;
return;
}
extract($vars); extract($vars);
require __DIR__ . '/../components/' . $_component_name . '.php'; require __DIR__ . '/../components/' . $_component_name . '.php';
} }
@ -129,6 +139,9 @@ if($reqMethod == 'HEAD') {
$reqHead = true; $reqHead = true;
} }
if(FM_DYNLOAD)
ob_start();
if(substr($reqPath, 0, 7) === '/error/') { if(substr($reqPath, 0, 7) === '/error/') {
$statusCode = intval(substr($reqPath, 7, 3)); $statusCode = intval(substr($reqPath, 7, 3));
} else { } else {
@ -138,17 +151,24 @@ if(substr($reqPath, 0, 7) === '/error/') {
if(($result & FM_HIT) === FM_HIT) { if(($result & FM_HIT) === FM_HIT) {
if($statusCode >= 100 && $statusCode <= 999) if($statusCode >= 100 && $statusCode <= 999)
http_response_code($statusCode); http_response_code($statusCode);
return; else
$statusCode = 200;
break;
} }
if(($result & FM_ERR) === FM_ERR) if(($result & FM_ERR) === FM_ERR)
break; break;
} }
// Make sure we have a valid error code
if($statusCode < 100)
$statusCode = 404;
} }
$errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404]; if($statusCode >= 400 && $statusCode <= 599 && ob_get_length() < 1) {
http_response_code($errorInfo['code']); $errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404];
http_response_code($errorInfo['code']);
if(!$reqHead) { if(!$reqHead) {
fm_component('header', ['title' => $errorInfo['title']]); fm_component('header', ['title' => $errorInfo['title']]);
?> ?>
<div class="http-error"> <div class="http-error">
@ -158,4 +178,16 @@ if(!$reqHead) {
</div> </div>
<?php <?php
fm_component('footer'); 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,
]);
} }