added a basic loading screen...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
a6d04eff3b
commit
1f3adbbfb1
@ -45,7 +45,7 @@
|
||||
- actions:
|
||||
- "from selection"
|
||||
- ~~Gallery: drag-n-drop~~
|
||||
- ~~drop files/images~~ -- add loading indicator
|
||||
- ~~drop files/images~~
|
||||
- ~~drag to sort~~
|
||||
- **drag marked**
|
||||
- touch...
|
||||
|
||||
@ -84,6 +84,8 @@ body {
|
||||
.gallery {
|
||||
--base-layer: 10;
|
||||
|
||||
position: relative;
|
||||
|
||||
padding-top: var(--gallery-padding-top);
|
||||
padding-bottom: var(--gallery-padding-bottom);
|
||||
padding-left: calc(
|
||||
@ -93,6 +95,7 @@ body {
|
||||
|
||||
color: var(--gallery-text-color);
|
||||
background: var(--gallery-background-color);
|
||||
font-family: sans-serif;
|
||||
|
||||
overflow-x: clip;
|
||||
}
|
||||
@ -580,6 +583,49 @@ body {
|
||||
|
||||
|
||||
|
||||
/********************************************************* Splash ****/
|
||||
|
||||
.gallery .loading {
|
||||
position: absolute;
|
||||
display: block;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height:100%;
|
||||
|
||||
text-align: center;
|
||||
|
||||
z-index: calc(var(--base-layer) * 2);
|
||||
|
||||
background: white;
|
||||
}
|
||||
.gallery.ready .loading {
|
||||
animation: fadeOutAnimation ease 2s;
|
||||
animation-iteration-count: 1;
|
||||
animation-fill-mode: forwards;
|
||||
pointer-events: none;
|
||||
}
|
||||
@keyframes fadeOutAnimation {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.gallery.ready .loading * {
|
||||
display: none;
|
||||
}
|
||||
.gallery:not(.ready) .images img {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************** Utils ****/
|
||||
|
||||
.gallery:not(.lightboxed):not(.detailed) .hide-in-gallery,
|
||||
@ -588,6 +634,40 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* loading animation... */
|
||||
.gallery .loading>div {
|
||||
--bar-size: 0.2rem;
|
||||
|
||||
position: sticky;
|
||||
top: var(--bar-size);
|
||||
}
|
||||
.gallery .loading>div:before,
|
||||
.gallery .loading>div:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(var(--bar-size) * -1);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: var(--bar-size);
|
||||
opacity: 0.3;
|
||||
}
|
||||
.gallery .loading>div:after {
|
||||
background: gray;
|
||||
animation: loadingBarAnimation ease infinite alternate 2s;
|
||||
}
|
||||
.gallery .loading>div:before {
|
||||
width: 50%;
|
||||
background: gray;
|
||||
animation: loadingBarAnimation ease infinite alternate 1.5s;
|
||||
}
|
||||
@keyframes loadingBarAnimation {
|
||||
0% {
|
||||
translate: -100%;
|
||||
}
|
||||
100% {
|
||||
translate: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
@ -16,7 +16,7 @@ body.splash {
|
||||
}
|
||||
|
||||
/* fade-in body... */
|
||||
/* XXX add real splash screen... */
|
||||
/* XXX add real splash screen...
|
||||
body:not(.splash) {
|
||||
animation: fadeInAnimation ease 2s;
|
||||
animation-iteration-count: 1;
|
||||
@ -31,6 +31,7 @@ body:not(.splash) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@ -89,6 +90,7 @@ For more info see: <a href="./README.md">README.md</a>
|
||||
<h3>Settings</h3>
|
||||
|
||||
<button onclick="gallery.toolbar.movable()">toggle toolbar drag</button>
|
||||
<button onclick="gallery.toggleLoading()">toggle splash screen</button>
|
||||
|
||||
<hr>
|
||||
|
||||
@ -175,6 +177,10 @@ For more info see: <a href="./README.md">README.md</a>
|
||||
<div class="button close"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- loading screen -->
|
||||
<div class="loading">
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
113
grid-n-view.js
113
grid-n-view.js
@ -22,6 +22,7 @@ var RESIZE_SETTLE_TIMEOUT = 16
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Generic stuff...
|
||||
|
||||
var patchFlexRows =
|
||||
function(elems,
|
||||
@ -133,7 +134,6 @@ function(elem) {
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
// XXX move to types.js...
|
||||
var ruler
|
||||
var px2rem = function(px){
|
||||
if(!ruler){
|
||||
@ -150,9 +150,11 @@ var rem2px = function(rem){
|
||||
var px = ruler.offsetWidth
|
||||
return px }
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
var getTouch = function(evt, id){
|
||||
var getTouch =
|
||||
function(evt, id){
|
||||
if(id != null && id !== false && evt.targetTouches){
|
||||
for(var k in evt.targetTouches){
|
||||
if(evt.targetTouches[k]?.identifier == id){
|
||||
@ -171,41 +173,63 @@ var getTouch = function(evt, id){
|
||||
// - scroll into view the dragged element
|
||||
// - bound it by screen
|
||||
// XXX need to check if element already set as movable...
|
||||
var moveable = function(elem, options={}){
|
||||
// XXX docs...
|
||||
HTMLElement.prototype.moveable =
|
||||
function(options={}){
|
||||
var elem = this
|
||||
if(elem.dataset.movable){
|
||||
throw new Error('element already movable.') }
|
||||
elem.dataset.movable = true
|
||||
// options...
|
||||
var {
|
||||
cls,
|
||||
handle,
|
||||
// CSS class added to element while it is dragged...
|
||||
cls = 'movable',
|
||||
// Drag handle element -- watches the drag events...
|
||||
handle = elem,
|
||||
// Blement bounding box used to check bounds...
|
||||
box = elem,
|
||||
// Bounds object...
|
||||
// can be:
|
||||
// false
|
||||
// {
|
||||
// top: <top>,
|
||||
// left: <left>,
|
||||
// bottom: <bottom>,
|
||||
// <right>: <right>,
|
||||
// }
|
||||
// XXX add support for:
|
||||
// css selector
|
||||
// element
|
||||
bounds,
|
||||
// can be:
|
||||
// 'x'
|
||||
// 'y'
|
||||
// undefined
|
||||
lock,
|
||||
start = function(elem, data){
|
||||
bounds
|
||||
?? (data.bounds = bounds)
|
||||
return data },
|
||||
beforeMove,
|
||||
// start(<elem>, <data>)
|
||||
// -> undefined
|
||||
// -> <data>
|
||||
start,
|
||||
// can be:
|
||||
// 'strict'
|
||||
// 'scroll' / true
|
||||
// false
|
||||
keepInView = true,
|
||||
// move(<elem>, <data>)
|
||||
move = function(elem, data){
|
||||
data.x != null
|
||||
&& (elem.style.left = data.x + 'px')
|
||||
data.y != null
|
||||
&& (elem.style.top = data.y + 'px') },
|
||||
// end(<elem>, <data>)
|
||||
end,
|
||||
ignoreBounds = false,
|
||||
} = options
|
||||
handle = typeof(handle) == 'string' ?
|
||||
handle =
|
||||
typeof(handle) == 'string' ?
|
||||
elem.querySelector(handle)
|
||||
: handle instanceof Element ?
|
||||
handle
|
||||
: elem
|
||||
: handle
|
||||
|
||||
var data
|
||||
|
||||
var handleMoveStart = function(evt){
|
||||
@ -219,7 +243,7 @@ var moveable = function(elem, options={}){
|
||||
var y = evt.clientY
|
||||
?? evt.targetTouches[0].clientY
|
||||
data = {
|
||||
bounds: false,
|
||||
bounds: bounds,
|
||||
offset: {
|
||||
x: x - elem.offsetLeft,
|
||||
y: y - elem.offsetTop,
|
||||
@ -248,7 +272,8 @@ var moveable = function(elem, options={}){
|
||||
data.x =
|
||||
lock == 'x' ?
|
||||
null
|
||||
: data.bounds != null ?
|
||||
: (!ignoreBounds
|
||||
&& data.bounds != null) ?
|
||||
Math.min(
|
||||
data.bounds.right,
|
||||
Math.max(
|
||||
@ -258,7 +283,8 @@ var moveable = function(elem, options={}){
|
||||
data.y =
|
||||
lock == 'y' ?
|
||||
null
|
||||
: data.bounds != null ?
|
||||
: (!ignoreBounds
|
||||
&& data.bounds != null) ?
|
||||
Math.min(
|
||||
data.bounds.bottom,
|
||||
Math.max(
|
||||
@ -266,13 +292,15 @@ var moveable = function(elem, options={}){
|
||||
y - data.offset.y))
|
||||
: y - data.offset.y
|
||||
// restrict to viewport...
|
||||
if(keepInView == 'strict'){
|
||||
if(!ignoreBounds
|
||||
&& keepInView == 'strict'){
|
||||
var t, l
|
||||
var bb = elem.getBoundingClientRect()
|
||||
var screen = {
|
||||
top: t = elem.offsetTop - bb.top,
|
||||
left: l = elem.offsetLeft - bb.left,
|
||||
bottom: window.innerHeight + t - elem.offsetHeight,
|
||||
right: window.innerWidth + l - elem.offsetWidth,
|
||||
top: t = box.offsetTop - bb.top,
|
||||
left: l = box.offsetLeft - bb.left,
|
||||
bottom: window.innerHeight + t - box.offsetHeight,
|
||||
right: window.innerWidth + l - box.offsetWidth,
|
||||
}
|
||||
data.x = Math.min(
|
||||
screen.right,
|
||||
@ -294,7 +322,8 @@ var moveable = function(elem, options={}){
|
||||
&& move(elem, data)
|
||||
// keep in view...
|
||||
// NOTE: this works best with CSS's scroll-margin...
|
||||
;(keepInView == 'scroll'
|
||||
!ignoreBounds
|
||||
&& (keepInView == 'scroll'
|
||||
|| keepInView === true)
|
||||
&& elem.scrollIntoView({ block: 'nearest' })
|
||||
delete data.animate }) } } }
|
||||
@ -872,6 +901,18 @@ var Gallery = {
|
||||
img.classList.toggle('marked') }
|
||||
return this.updateMarkers() },
|
||||
|
||||
get loading(){
|
||||
return !this.dom.classList.contains('ready') },
|
||||
showLoading: function(){
|
||||
this.dom.classList.remove('ready')
|
||||
return this },
|
||||
hideLoading: function(){
|
||||
this.dom.classList.add('ready')
|
||||
return this },
|
||||
toggleLoading: function(){
|
||||
this.dom.classList.toggle('ready')
|
||||
return this },
|
||||
|
||||
show: function(){
|
||||
return this.showLightbox() },
|
||||
showLightbox: function(){
|
||||
@ -1189,6 +1230,8 @@ var Gallery = {
|
||||
|
||||
// non-local drag...
|
||||
if(!dragged){
|
||||
that.showLoading()
|
||||
|
||||
var expand = (evt.shiftKey && dragged_over) ?
|
||||
that.images.indexOf(dragged_over)
|
||||
: undefined
|
||||
@ -1231,12 +1274,14 @@ var Gallery = {
|
||||
.flat())
|
||||
.then(
|
||||
function(images){
|
||||
that.hideLoading()
|
||||
// no images...
|
||||
if(images.length == 0){
|
||||
return }
|
||||
return that.load(images, expand) },
|
||||
function(err){
|
||||
// XXX handle errors...
|
||||
that.hideLoading()
|
||||
}) }
|
||||
dragged
|
||||
&& dragged.classList.remove('dragged')
|
||||
@ -1259,7 +1304,8 @@ var Gallery = {
|
||||
|
||||
return this
|
||||
.updateMarkers()
|
||||
.update() },
|
||||
.update()
|
||||
.hideLoading() },
|
||||
}
|
||||
|
||||
|
||||
@ -1270,8 +1316,10 @@ var Toolbar = {
|
||||
gallery: undefined,
|
||||
cls: 'toolbar',
|
||||
|
||||
// time to hold the handle to toggle autohide...
|
||||
hold: 300,
|
||||
|
||||
// autohide timeout...
|
||||
toolbar_autohide: 2000,
|
||||
|
||||
// XXX make these generic...
|
||||
@ -1354,10 +1402,7 @@ var Toolbar = {
|
||||
// toolbar: move...
|
||||
// XXX to drag anywhere on the elem we need to prevent
|
||||
// clicks while dragging...
|
||||
// XXX prevent from scrolling off screen when placed a bottom
|
||||
// and scrolling up -- i.e. keep within viewport and gallery
|
||||
// at all times...
|
||||
moveable(toolbar, {
|
||||
toolbar.moveable({
|
||||
cls: 'moving',
|
||||
handle: '.drag-handle',
|
||||
// set bounds...
|
||||
@ -1378,6 +1423,15 @@ var Toolbar = {
|
||||
data.y != null
|
||||
&& elem.style.setProperty('--move-y', data.y + 'px') }, })
|
||||
|
||||
// keep toolbar in view while scrolling...
|
||||
// NOTE: top is taken care of by position: sticky...
|
||||
window.addEventListener('scroll', function(evt){
|
||||
var bb = toolbar.getBoundingClientRect()
|
||||
if(window.innerHeight <= bb.bottom){
|
||||
var top = toolbar.offsetTop - bb.top
|
||||
var bottom = window.innerHeight + top - toolbar.offsetHeight
|
||||
toolbar.style.setProperty('--move-y', bottom + 'px') } })
|
||||
|
||||
return this },
|
||||
}
|
||||
|
||||
@ -1618,6 +1672,7 @@ var Details = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
var setupGallery = function(gallery){
|
||||
@ -1631,6 +1686,8 @@ var setup = function(){
|
||||
window.gallery = setupGallery(gallery) }
|
||||
// keyboard...
|
||||
document.addEventListener('keydown', function(evt){
|
||||
if(window.gallery.loading){
|
||||
return }
|
||||
var key = evt.key
|
||||
if(key in keyboard){
|
||||
keyboard[key](evt) } }) }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user