Simple gallery with continuous scroll
<?php
define('BASE_PATH', '/home/rgalka/Pictures');
$image = @$_GET['image'];
if (!empty($image)) {
$file = BASE_PATH . '/' . $image;
if (!is_file($file)) {
echo "Sorry, no file matching request";
exit;
}
header('Content-type:' . mime_content_type($file));
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
function getDirectories($dir) {
$ret = array();
foreach (new DirectoryIterator($dir) as $fileInfo) {
if($fileInfo->isDot() || $fileInfo->isFile())
continue;
$ret[] = $fileInfo->getFilename();
}
return $ret;
}
function getImages($dir, $page = 0, $perPage = 10) {
$images = array();
foreach (new DirectoryIterator($dir) as $fileInfo) {
if($fileInfo->isDir())
continue;
$images[] = $fileInfo->getFilename();
}
return array_slice($images, $perPage * $page, $perPage);
}
?>
<html>
<head>
<title>Infinite gallery</title>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
}
body {
padding: 10px;
}
.container {
width: 1000px;
margin: 0 auto;
}
img {
width: 100%;
min-height: 600px;
margin-bottom: 10px;
border-radius: 10px;
-webkit-box-shadow: 0px 0px 18px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 18px 0px rgba(0,0,0,0.75);
box-shadow: 0px 0px 18px 0px rgba(0,0,0,0.75);
border: 1px solid #000;
opacity: 1;
transition: opacity 1s linear;
}
img.empty {
opacity: 0;
}
</style>
</head>
<body>
<div class="container">
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$dir = @$_GET['dir'];
$page = (int)@$_GET['page'];
if (empty($dir)) {
foreach (getDirectories(BASE_PATH) as $item) {
echo '<a href="?dir=' . $item . '">' . $item . '</a><br>';
}
} else {
echo '<div id="images">';
foreach (getImages(BASE_PATH . '/' . $dir, $page) as $k => $image) {
if ($k < 2) {
echo '<img src="?image=' . $dir . '/' . $image . '">';
} else {
echo '<img class="empty" data-src="?image=' . $dir . '/' . $image . '">';
}
}
echo '</div>';
}
?>
</div>
<script type="text/javascript">
(function () {
var page = 0,
viewportHeight = window.innerHeight,
pageHeight = document.documentElement.clientHeight,
scrollPosition,
loadLock = false,
xmlhttp = new XMLHttpRequest();
function load() {
page++;
var url = window.location.search + '&page=' + page;
xmlhttp.open('GET', url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
var div = document.createElement('div');
div.innerHTML = xmlhttp.responseText;
var images = div.querySelectorAll('#images img');
if (images.length == 0) {
return;
}
var cont = document.querySelector('#images');
for (var i = 0, max = images.length; i < max; i++) {
if (images[i].src) {
images[i].setAttribute('data-src', images[i].getAttribute('src'));
images[i].removeAttribute('src');
}
cont.appendChild(images[i]);
}
loadLock = false;
}
};
};
function onScroll() {
pageHeight = document.documentElement.clientHeight
scrollPosition = window.pageYOffset;
if ((pageHeight - viewportHeight - scrollPosition) < viewportHeight && !loadLock) {
loadLock = true;
load();
}
};
window.addEventListener('scroll', onScroll);
var checkLock = false;
function checkImgVisibility () {
if (checkLock) {
return;
}
checkLock = true;
var images = document.querySelectorAll('#images img');
for (var i = 0, max = images.length; i < max; i++) {
if (images[i].src) {
continue;
}
var windowLeft = window.scrollX,
windowTop = window.scrollY,
windowHeight = window.innerHeight,
bodyRect = document.body.getBoundingClientRect(),
imgRect = images[i].getBoundingClientRect(),
left = imgRect.left,
top = imgRect.top - bodyRect.top;
if (top + images[i].height >= windowTop && top <= windowTop + windowHeight) {
images[i].setAttribute('src', images[i].getAttribute('data-src'));
images[i].removeAttribute('data-src');
images[i].addEventListener('load', function (e) {
e.srcElement.classList.remove('empty');
});
}
}
checkLock = false;
}
window.addEventListener('scroll', checkImgVisibility);
window.addEventListener('resize', checkImgVisibility);
setTimeout(checkImgVisibility, 200);
}());
</script>
</body>
</html>