diff --git a/css/grid-n-view.css b/css/grid-n-view.css
index 795aabb..8b68674 100644
--- a/css/grid-n-view.css
+++ b/css/grid-n-view.css
@@ -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;
diff --git a/grid-n-view.html b/grid-n-view.html
index 68bcdb6..a2b61be 100644
--- a/grid-n-view.html
+++ b/grid-n-view.html
@@ -112,7 +112,7 @@ var restoreScroll = function(){
-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: README.md
+Basic actions:
+toggle mark current (space) |
+mark all (ctrl-a) |
+unmark all (ctrl-d) |
+reverse mark (ctrl-i) |
+remove marked
+
+
+toggle removal |
+queue marked removal |
+unqueue marked removal |
+toggle marked removal |
+remove queued
+
+
+clear
+
+
+
diff --git a/grid-n-view.js b/grid-n-view.js
index 15340ec..29c68f8 100644
--- a/grid-n-view.js
+++ b/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')
+ // ->
+ //
+ // .getImages('marked')
+ // ->
+ //
+ // .getImages(
, ..)
+ // .getImages([
, ..])
+ // ->
+ //
+ // .getImages('sorted', ..)
+ // .getImages(.., 'sorted')
+ // ->
+ //
+ //
::=
+ // ImageElement
+ // |
+ // | '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' ?