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