From 087254328c6b3ac3c01407a2e3f1be2159abf101 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Mon, 7 Aug 2023 17:16:24 +0300 Subject: [PATCH] added file drag and drom... Signed-off-by: Alex A. Naanou --- grid-n-view.html | 6 +++- grid-n-view.js | 88 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/grid-n-view.html b/grid-n-view.html index 9d89ba9..f126e32 100644 --- a/grid-n-view.html +++ b/grid-n-view.html @@ -93,7 +93,7 @@ var restoreScroll = function(){ - actions: - "from selection" - Gallery: drag-n-drop - - drop files/images + - drop files/images - drag to sort - Gallery: remove image - UI: mark images for deletion + delete marked @@ -103,6 +103,10 @@ var restoreScroll = function(){ - Gallery: element (???) - Would be nice to retain the scroll position on refresh... - ... + +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)
diff --git a/grid-n-view.js b/grid-n-view.js index d3910fc..168d7cc 100644 --- a/grid-n-view.js +++ b/grid-n-view.js @@ -15,12 +15,15 @@ //--------------------------------------------------------------------- +// This compansates for any resize rounding errors in patchFlexRows(..). +var PATCH_MARGIN = 2 + var patchFlexRows = function(elems, prevent_row_expansion=false, last_row_resize=1.5){ if(elems.length == 0){ return } // NOTE: -1 here is to compensate for rounding errors... - var W = elems[0].parentElement.clientWidth - 1 + var W = elems[0].parentElement.clientWidth - PATCH_MARGIN var w = 0 var h var row = [] @@ -57,7 +60,10 @@ function(elems, prevent_row_expansion=false, last_row_resize=1.5){ // patch the row... var nw = 0 for(var e of row){ - e.style.height = (h * r) + 'px' + if(r == 0 || h == 0){ + e.style.height = '' + } else { + e.style.height = (h * r) + 'px' } nw += e.offsetWidth } return !!expanded } // NOTE: this will by design skip the last row... @@ -573,10 +579,28 @@ var Gallery = { this.details.show() return this }, + __update_grid_size_timeout: undefined, + __update_grid_size_running: false, __update_grid_size: function(){ - patchFlexRows(this.images, - !this.allow_row_expansion, - this.last_row_resize ?? 1.2) + // if still running then delay untill done... + // NOTE: this will keep only one call no matter how many times + // the method was actually called... + if(this.__update_grid_size_running){ + var that = this + this.__update_grid_size_timeout + && clearTimeout(this.__update_grid_size_timeout) + this.__update_grid_size_timeout = setTimeout(function(){ + that.__update_grid_size() + delete that.__update_grid_size_timeout }, 10) + return this } + // do the update... + this.__update_grid_size_running = true + try{ + patchFlexRows(this.images, + !this.allow_row_expansion, + this.last_row_resize ?? 1.2) + }catch(err){ } + delete this.__update_grid_size_running return this }, update: function(){ this.__update_grid_size() @@ -603,6 +627,7 @@ var Gallery = { // gallery.load(gallery.json('marked')) // XXX do we handle previews here??? load: function(images, index=undefined){ + var that = this images = images instanceof Array ? images : [images] @@ -610,12 +635,17 @@ var Gallery = { var elems = [] for(var data of images){ if(typeof(data) == 'string'){ - var [url] = [data] + var [url, data] = [data, {}] } else if(data instanceof Array){ - var [url, ...data] = data + var [url, caption] = data + data = {} + caption + ?? (data.caption = caption) } else { var {url, ...data} = data } var elem = document.createElement('img') + elem.onload = function(){ + that.update() } elem.src = url elem.setAttribute('draggable', 'true') for(var [key, value] of Object.entries(data)){ @@ -719,16 +749,50 @@ var Gallery = { .addEventListener('click', function(evt){ that.unmark_current && (that.current = null) }) - // drag... + // drag/drop... + // XXX add a local drag mode... this.dom .addEventListener('dragover', function(evt){ - // XXX - }) + evt.preventDefault() + evt.stopPropagation() + evt.dataTransfer.dropEffect = 'copy' + }, false) this.dom .addEventListener('drop', function(evt){ evt.preventDefault() - // XXX - }) + evt.stopPropagation() + var files = + evt.dataTransfer.items ? + [...evt.dataTransfer.items] + .map(function(elem){ + return elem.kind == 'file' ? + [elem.getAsFile()] + : [] }) + .flat() + : [...evt.dataTransfer.files] + + Promise.all(files + .map(function(file){ + if(!file.type.match('image.*')){ + return [] } + if(file.path){ + return file.path + } else { + return new Promise(function(resolve, reject){ + var reader = new FileReader() + reader.onload = function(f){ + resolve(f.target.result) } + reader.readAsDataURL(file) }) } }) + .flat()) + .then( + function(images){ + // no images... + if(images.length == 0){ + return } + return that.load(images) }, + function(err){ + // XXX handle errors... + }) }, false) // XXX for(var img of this.images){