From 4fa38da17c64ee8f90297cc1fd8ab40d81a10d44 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 30 Aug 2017 00:13:38 +0300 Subject: [PATCH] refactoring imagegrid/data + docs... Signed-off-by: Alex A. Naanou --- ui (gen4)/features/collections.js | 6 +- ui (gen4)/imagegrid/data.js | 309 ++++++++++++++++-------------- 2 files changed, 164 insertions(+), 151 deletions(-) diff --git a/ui (gen4)/features/collections.js b/ui (gen4)/features/collections.js index c4966d73..80746a1c 100755 --- a/ui (gen4)/features/collections.js +++ b/ui (gen4)/features/collections.js @@ -530,8 +530,7 @@ var CollectionActions = actions.Actions({ delete this.data.tags this.data - .removeGIDs(gids) - .removeEmptyRibbons() + .clear(gids) .run(function(){ this.tags = tags this.sortTags() @@ -544,8 +543,7 @@ var CollectionActions = actions.Actions({ // need to protect them... if(this.data !== this.collections[collection].data){ this.collections[collection].data - .removeGIDs(gids) - .removeEmptyRibbons() + .clear(gids) } }], diff --git a/ui (gen4)/imagegrid/data.js b/ui (gen4)/imagegrid/data.js index 28e8747e..c60f8e49 100755 --- a/ui (gen4)/imagegrid/data.js +++ b/ui (gen4)/imagegrid/data.js @@ -200,6 +200,7 @@ var DataPrototype = { // NOTE: ribbons are sparse... // NOTE: ribbons can be compact when serialized... // + // /*****************************************************************/ get current(){ @@ -358,19 +359,33 @@ var DataPrototype = { // Iterate through image lists... // + // .eachImageList(func) + // -> this + // + // // This accepts a function: - // func(list, key, set) + // func(list, key, set) // // Where: - // list - the sparse list of gids - // key - the list key in set - // set - the set name + // list - the sparse list of gids + // key - the list key in set + // set - the set name // // The function is called in the context of the data object. // // The arguments can be used to access the list directly like this: // this[set][key] -> list // + // + // Set order attribute is used if available to determine the key + // iteration order. + // For 'ribbons' the order is determined as follows: + // .ribbons_order + any missing keys + // .ribbon_order + any missing keys + // Object.keys(this[ribbons]) + // + // XXX not sure if we should keep ._order processing as-is, + // might a good idea just to drop it... eachImageList: function(func){ var that = this this.__gid_lists.forEach(function(k){ @@ -378,9 +393,15 @@ var DataPrototype = { if(lst == null){ return } - Object.keys(lst).forEach(function(l){ - func.call(that, lst[l], l, k) - }) + var keys = (that[k + '_order'] + || that[k.replace(/s$/, '') + '_order'] + || []) + .concat(Object.keys(lst)) + .unique() + //Object.keys(lst) + keys + .forEach(function(l){ + func.call(that, lst[l], l, k) }) }) return this }, @@ -426,19 +447,25 @@ var DataPrototype = { return gid }, + // Clear elements from data... // - // Clear all data: + // Clear all data... // .clear() // .clear('*') // .clear('all') // -> data // - // Clear empty ribbons: + // Clear empty ribbons... // .clear('empty') // -> data // - // Clear gid(s) form data: + // Clear duplicate gids... + // .clear('dup') + // .clear('duplicates') + // -> data + // + // Clear gid(s) form data... // .clear(gid) // .clear([gid, gid, ..]) // -> data @@ -459,12 +486,8 @@ var DataPrototype = { // cleared... // thus setting appropriate .base and .current values is the // responsibility of the caller. - // - // XXX not sure this should be here... - // XXX should this reset .base and .current to appropriate values - // other than null? - // XXX should this return this or the removed gids??? clear: function(gids, deep, clear_empty){ + var that = this gids = gids || 'all' deep = deep == null ? true : false clear_empty = clear_empty == null ? true : false @@ -473,6 +496,28 @@ var DataPrototype = { if(gids == '*' || gids == 'all'){ this._reset() + } else if(gids == 'dup' || gids == 'duplicates'){ + // horizontal... + this.removeDuplicates(this.order) + this.updateImagePositions() + + // vertical... + // if a gid is in more than one ribbon keep only the top + // occurrence... + this.order.forEach(function(gid, i){ + var found = false + that.ribbon_order.forEach(function(r){ + r = that.ribbons[r] + + if(found){ + delete r[i] + + } else if(r[i] != null){ + found = true + } + }) + }) + // clear empty ribbons only... } else if(gids == 'empty'){ for(var r in this.ribbons){ @@ -483,58 +528,123 @@ var DataPrototype = { // clear gids... } else { - gids = gids.constructor === Array ? gids : [gids] - var that = this - gids.forEach(function(gid){ - var r = that.ribbon_order.indexOf(gid) - var i = that.order.indexOf(gid) - // gid is a ribbon... - if(r >= 0){ - // clear from order... - that.ribbon_order.splice(r, 1) + var ribbons = [] + gids = gids instanceof Array ? gids : [gids] + // split ribbon and image gids... + gids = gids + .filter(function(gid){ + return gid in that.ribbons ? + !ribbons.push(gid) + : true }) - // clear from ribbons... - var images = that.ribbons[gid] - delete that.ribbons[gid] - // remove ribbon images... - if(deep){ - images.forEach(function(gid){ that.clear(gid) }) - } + // remove ribbons... + ribbons.forEach(function(gid){ + var i = that.ribbon_order.indexOf(gid) - // no more ribbons left... - if(that.ribbon_order.length == 0){ - delete that.__base + // clear from order... + that.ribbon_order.splice(i, 1) - // shift base up or to first image... - } else if(that.base == gid){ - that.setBase(Math.max(0, r-1)) - } + // clear from ribbons... + var images = that.ribbons[gid] + delete that.ribbons[gid] - // gid is an image... - } else if(i >= 0) { - // remove from order... - that.order.splice(i, 1) + // remove ribbon images... + if(deep){ + gids = gids.concat(images) + } - that.eachImageList(function(lst){ - lst.splice(i, 1) - }) + // no more ribbons left... + if(that.ribbon_order.length == 0){ + delete that.__base - if(that.current == gid){ - delete that.__current - } + // shift base up or to first image... + } else if(that.base == gid){ + that.setBase(Math.max(0, i-1)) } }) - // cleanup... - if(clear_empty){ - this.clear('empty') + + // remove images... + var order = this.order + .filter(function(g){ return gids.indexOf(g) < 0 }) + + // handle current image... + if(gids.indexOf(this.current) >= 0){ + var r = this.getImages('current') + .filter(function(g){ return order.indexOf(g) >= 0 }) + + // attempt to first get next/prev within the current ribbon... + r = r.length > 0 ? r : order + + this.current = + this.getImage(this.current, 'after', r) + || this.getImage(this.current, 'before', r) } + + // do the actual removal... + // NOTE: splicing fixed image indexes is faster than + // .updateImagePositions('remove') + gids.forEach(function(gid){ + var i = that.order.indexOf(gid) + that.eachImageList(function(lst){ + lst.splice(i, 1) }) + }) + this.order = order + + + // cleanup... + clear_empty + && this.clear('empty') } return this }, + // Remove duplicate gids... + // + // If a gid is in more than one ribbon, this will keep the top + // occurrence only... + // + // NOTE: this may result in empty ribbons... + // NOTE: this is slow-ish... + removeDuplicateGIDs: function(){ + var that = this + + // horizontal... + this.removeDuplicates(this.order) + this.updateImagePositions() + + // vertical... + // if a gid is in more than one ribbon keep only the top occurence... + this.order.forEach(function(gid, i){ + var found = false + that.ribbon_order.forEach(function(r){ + r = that.ribbons[r] + + if(found){ + delete r[i] + + } else if(r[i] != null){ + found = true + } + }) + }) + return this + }, + + // Remove unloaded gids... + // + // This removes: + // - images from .data that are not in any ribbon + // + // NOTE: this may result in empty ribbons... + removeUnloadedGIDs: function(){ + this.order = this.getImages('loaded') + this.updateImagePositions('remove') + return this + }, + // Replace image gid... // // XXX should this work for ribbon gids??? @@ -2335,7 +2445,7 @@ var DataPrototype = { base // XXX this is slow-ish... .removeDuplicateGIDs() - .removeEmptyRibbons() + .clear('empty') return base }, @@ -2631,101 +2741,6 @@ var DataPrototype = { - /***************************************** Cleanup and removal ***/ - - // Remove empty ribbons... - // - removeEmptyRibbons: function(){ - var that = this - this.ribbon_order = this.ribbon_order - .filter(function(r){ - if(that.ribbons[r].len == 0){ - delete that.ribbons[r] - return false - } - return true - }) - return this - }, - - // Remove duplicate gids... - // - // If a gid is in more than one ribbon, this will keep the top - // occurrence only... - // - // NOTE: this may result in empty ribbons... - // NOTE: this is slow-ish... - removeDuplicateGIDs: function(){ - var that = this - this.removeDuplicates(this.order) - this.updateImagePositions() - // if a gid is in more than one ribbon keep only the top occurence... - this.order.forEach(function(gid, i){ - var found = false - that.ribbon_order.forEach(function(r){ - r = that.ribbons[r] - - if(found){ - delete r[i] - - } else if(r[i] != null){ - found = true - } - }) - }) - return this - }, - - // Remove unloaded gids... - // - // This removes: - // - images from .data that are not in any ribbon - // - // NOTE: this may result in empty ribbons... - removeUnloadedGIDs: function(){ - this.order = this.getImages('loaded') - this.updateImagePositions('remove') - return this - }, - - // Remove GIDs... - // - // NOTE: this may result in empty ribbons... - // NOTE: to remove gids from lists but keep them in order use: - // .updateImagePositions(gids, 'hide') - removeGIDs: function(gids, direction){ - var that = this - gids = gids || [] - gids = (gids instanceof Array ? gids : [gids]) - .map(function(gid){ return that.getImage(gid) }) - - if(gids.length == 0){ - return - } - - var order = this.order.filter(function(g){ return gids.indexOf(g) < 0 }) - - // handle current image... - if(gids.indexOf(this.current) >= 0){ - var r = this.getImages('current') - .filter(function(g){ return order.indexOf(g) >= 0 }) - - // attempt to first get next/prev within the current ribbon... - r = r.length > 0 ? r : order - - this.current = this.getImage(this.current, direction || 'before', r) - || this.getImage(this.current, direction == 'after' ? 'before' : 'after', r) - } - - this.order = order - - this.updateImagePositions('remove') - - return this - }, - - - /****************************************** JSON serialization ***/ // Load data from JSON...