added removal queue API + cleanup and notes...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
5ffdaeb100
commit
804bceee46
@ -10,8 +10,8 @@
|
||||
:root {
|
||||
/* dimensions */
|
||||
--gallery-image-margin: 0;
|
||||
--gallery-current-image-border: 0.7em;
|
||||
--gallery-padding: 3em;
|
||||
--gallery-current-image-border: 0.7rem;
|
||||
--gallery-padding: 3rem;
|
||||
--gallery-padding-horizontal: var(--gallery-padding);
|
||||
--gallery-padding-vertical: var(--gallery-current-image-border);
|
||||
--gallery-padding-top: var(--gallery-padding-vertical);
|
||||
@ -19,8 +19,8 @@
|
||||
--gallery-padding-left: var(--gallery-padding-horizontal);
|
||||
--gallery-padding-right: var(--gallery-padding-horizontal);
|
||||
--gallery-image-scroll-margin: calc(2 * var(--gallery-current-image-border));
|
||||
--gallery-scrollbar-width: 0.5em;
|
||||
--gallery-empty-height: 20em;
|
||||
--gallery-scrollbar-width: 0.5rem;
|
||||
--gallery-empty-height: 20rem;
|
||||
|
||||
--lightbox-frame: 5vmin;
|
||||
--lightbox-image-margin-top: 0.75;
|
||||
@ -96,19 +96,33 @@ body {
|
||||
align-content: flex-start;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
/* empty... */
|
||||
.gallery .images:empty {
|
||||
height: var(--gallery-empty-height);
|
||||
border: dashed 1px black;
|
||||
}
|
||||
.gallery .images:empty:after {
|
||||
content: "Empty...";
|
||||
.gallery .images:empty:after,
|
||||
.gallery .images:empty:before {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding: calc((var(--gallery-empty-height) - 1em) / 2) 0;
|
||||
line-height: var(--gallery-empty-height);
|
||||
text-align: center;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.gallery .images:empty:before {
|
||||
content: "Empty";
|
||||
}
|
||||
.gallery .images:empty:after {
|
||||
content: "(drag new images here)";
|
||||
font-size: small;
|
||||
margin-top: 1.1em;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/* image... */
|
||||
.gallery .images img {
|
||||
height: 300px;
|
||||
width: auto;
|
||||
|
||||
@ -112,7 +112,7 @@ var restoreScroll = function(){
|
||||
|
||||
</pre>
|
||||
<pre>
|
||||
Controls:
|
||||
Keyboard controls:
|
||||
Left / Reight - Previos / next image
|
||||
Up / Down - Image above / below
|
||||
Space - Mark image (also shift-click)
|
||||
@ -127,10 +127,32 @@ Controls:
|
||||
NOTE: if the grid behaves in an odd way on resize tweak PATCH_MARGIN value,
|
||||
though this sould not be necessary.
|
||||
(optimal range >1 and <3)
|
||||
NOTE: the "basic actions" below are to be moved to the toolbar...
|
||||
|
||||
For more info see: <a href="./README.md">README.md</a>
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
Basic actions:<br>
|
||||
<a href="javascript:gallery.toggleMark()">toggle mark current (space)</a> |
|
||||
<a href="javascript:gallery.markAll()">mark all (ctrl-a)</a> |
|
||||
<a href="javascript:gallery.unmarkAll()">unmark all (ctrl-d)</a> |
|
||||
<a href="javascript:gallery.markInverse()">reverse mark (ctrl-i)</a> |
|
||||
<a href="javascript:gallery.remove('marked')">remove marked</a>
|
||||
<br>
|
||||
<br>
|
||||
<a href="javascript:gallery.toggleQueueRemoval()">toggle removal</a> |
|
||||
<a href="javascript:gallery.queueRemoval('marked')">queue marked removal</a> |
|
||||
<a href="javascript:gallery.unqueueRemoval('marked')">unqueue marked removal</a> |
|
||||
<a href="javascript:gallery.toggleQueueRemoval('marked')">toggle marked removal</a> |
|
||||
<a href="javascript:gallery.removeQueued()">remove queued</a>
|
||||
<br>
|
||||
<br>
|
||||
<a href="javascript:gallery.clear()">clear</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="gallery">
|
||||
<!-- gallery: content -->
|
||||
<div class="images">
|
||||
|
||||
130
grid-n-view.js
130
grid-n-view.js
@ -15,6 +15,9 @@
|
||||
var PATCH_MARGIN = 2
|
||||
|
||||
// a timeout to let the resize settle before we handle dragover...
|
||||
// XXX this is too long -- we can pickup and drag an image within this
|
||||
// timeout...
|
||||
// need to make it more specific (handle only vertical drag???)
|
||||
var RESIZE_SETTLE_TIMEOUT = 16
|
||||
|
||||
|
||||
@ -178,19 +181,18 @@ var keyboard = {
|
||||
Delete: function(evt){
|
||||
// remove...
|
||||
if(evt.shiftKey){
|
||||
// XXX focus crrect image...
|
||||
to_remove = [...gallery.dom.querySelectorAll('.images img.to-remove')]
|
||||
var to_remove = gallery.toBeRemoved
|
||||
// remove marked...
|
||||
if(to_remove.length > 0){
|
||||
gallery.remove(...to_remove)
|
||||
gallery.removeQueued()
|
||||
// remove current...
|
||||
} else if(gallery.current){
|
||||
var to_remove = gallery.current
|
||||
to_remove = gallery.current
|
||||
if(gallery.marked.includes(to_remove)){
|
||||
gallery.remove(...gallery.marked)
|
||||
} else {
|
||||
// move focus...
|
||||
gallery.next()
|
||||
// XXX this is a bit crude...
|
||||
gallery.current === to_remove
|
||||
&& gallery.prev()
|
||||
gallery.remove(to_remove) } }
|
||||
@ -199,14 +201,10 @@ var keyboard = {
|
||||
var cur = gallery.current
|
||||
// toggle marked...
|
||||
if(gallery.marked.includes(cur)){
|
||||
var toggle_remove = !cur.classList.contains('to-remove')
|
||||
for(var img of gallery.marked){
|
||||
toggle_remove ?
|
||||
img.classList.add('to-remove')
|
||||
: img.classList.remove('to-remove') }
|
||||
gallery.toggleQueueRemoval('marked')
|
||||
// toggle current...
|
||||
} else {
|
||||
gallery.current.classList.toggle('to-remove') } } },
|
||||
gallery.toggleQueueRemoval() } } },
|
||||
// selection...
|
||||
' ': function(evt){
|
||||
gallery.current
|
||||
@ -216,7 +214,7 @@ var keyboard = {
|
||||
'a': function(evt){
|
||||
evt.preventDefault()
|
||||
if(evt.ctrlKey){
|
||||
gallery.selectAll() } },
|
||||
gallery.markAll() } },
|
||||
'd': function(evt){
|
||||
evt.preventDefault()
|
||||
if(evt.ctrlKey){
|
||||
@ -501,6 +499,67 @@ var Gallery = {
|
||||
: i
|
||||
var target = row[i] }
|
||||
return target },
|
||||
//
|
||||
// .getImages()
|
||||
// -> []
|
||||
//
|
||||
// .getImages('*')
|
||||
// .getImages('all')
|
||||
// -> <all-images>
|
||||
//
|
||||
// .getImages('marked')
|
||||
// -> <marked-images>
|
||||
//
|
||||
// .getImages(<img>, ..)
|
||||
// .getImages([<img>, ..])
|
||||
// -> <images>
|
||||
//
|
||||
// .getImages('sorted', ..)
|
||||
// .getImages(.., 'sorted')
|
||||
// -> <sorted-images>
|
||||
//
|
||||
// <img> ::=
|
||||
// ImageElement
|
||||
// | <index>
|
||||
// | 'current'
|
||||
//
|
||||
getImages: function(...images){
|
||||
var that = this
|
||||
var sorted =
|
||||
images.at(-1) == 'sorted' ?
|
||||
!!images.pop()
|
||||
: images[0] == 'sorted' ?
|
||||
!!images.shift()
|
||||
: false
|
||||
images = images.flat()
|
||||
if(images.includes('all')
|
||||
|| images.includes('*')){
|
||||
return this.images }
|
||||
images = [...new Set(images
|
||||
.map(function(img){
|
||||
return ((typeof(img) == 'string'
|
||||
&& img.trim() == '') ?
|
||||
[]
|
||||
: !isNaN(img*1) ?
|
||||
that.images.at(img*1)
|
||||
: img == 'marked' ?
|
||||
that.marked
|
||||
: img == 'current' ?
|
||||
that.current
|
||||
: typeof(img) == 'string' ?
|
||||
[]
|
||||
: img)
|
||||
?? [] })
|
||||
.flat())]
|
||||
if(sorted){
|
||||
var order = new Map(
|
||||
Object.entries(this.images)
|
||||
.map(function(e){
|
||||
return e.reverse() }))
|
||||
images
|
||||
.sort(function(a, b){
|
||||
return order.get(a) - order.get(b) }) }
|
||||
return images },
|
||||
|
||||
// XXX cache image list???
|
||||
prev: function(images){
|
||||
@ -598,7 +657,7 @@ var Gallery = {
|
||||
img?.classList.toggle('marked')
|
||||
this.updateMarkers()
|
||||
return this },
|
||||
selectAll: function(){
|
||||
markAll: function(){
|
||||
for(var img of this.images){
|
||||
img.classList.add('marked') }
|
||||
return this.updateMarkers() },
|
||||
@ -726,15 +785,7 @@ var Gallery = {
|
||||
// XXX do we handle previews here???
|
||||
json: function(images=undefined){
|
||||
var that = this
|
||||
images =
|
||||
(images == 'all' || images == '*') ?
|
||||
this.images
|
||||
: images == 'marked' ?
|
||||
this.marked
|
||||
: !images ?
|
||||
this.images
|
||||
: images
|
||||
return images
|
||||
return this.getImages(images ?? this.images)
|
||||
.map(function(img, i){
|
||||
var res = { url: img.src }
|
||||
for(var key of that.__image_attributes__ ?? []){
|
||||
@ -752,13 +803,42 @@ var Gallery = {
|
||||
// XXX
|
||||
},
|
||||
|
||||
// removal queue...
|
||||
get toBeRemoved(){
|
||||
return [...gallery.dom.querySelectorAll('.images img.to-remove')] },
|
||||
set toBeRemoved(lst){
|
||||
this.queueRemoval(lst) },
|
||||
queueRemoval: function(...images){
|
||||
images = images.length == 0 ?
|
||||
['current']
|
||||
: images
|
||||
for(var img of this.getImages(...images)){
|
||||
img.classList.add('to-remove') }
|
||||
return this },
|
||||
unqueueRemoval: function(...images){
|
||||
images = images.length == 0 ?
|
||||
['current']
|
||||
: images
|
||||
for(var img of this.getImages(...images)){
|
||||
img.classList.remove('to-remove') }
|
||||
return this },
|
||||
toggleQueueRemoval: function(...images){
|
||||
images = images.length == 0 ?
|
||||
['current']
|
||||
: images
|
||||
for(var img of this.getImages(...images)){
|
||||
img.classList.toggle('to-remove') }
|
||||
return this },
|
||||
removeQueued: function(){
|
||||
return this.remove(...this.toBeRemoved) },
|
||||
|
||||
remove: function(...images){
|
||||
if(images.includes('all')){
|
||||
if(images.includes('all')
|
||||
|| images.includes('*')){
|
||||
return this.clear() }
|
||||
// NOTE: we need to remove images from the end so as not to be
|
||||
// affected by shifed indexes...
|
||||
images
|
||||
.sort()
|
||||
images = this.getImages('sorted', ...images)
|
||||
.reverse()
|
||||
for(var img of images){
|
||||
typeof(img) == 'number' ?
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user