diff --git a/Viewer/features/base.js b/Viewer/features/base.js
index 30ca7401..33e961d5 100755
--- a/Viewer/features/base.js
+++ b/Viewer/features/base.js
@@ -1806,9 +1806,19 @@ module.Crop = core.ImageGridFeatures.Feature({
tag: 'crop',
depends: [
'base',
+ //'cache',
],
actions: CropActions,
+
+ handlers: [
+ [[
+ 'crop',
+ 'uncrop',
+ 'removeFromCrop',
+ ],
+ 'clearCache: "view(-.*)?" "*" -- Clear view cache'],
+ ],
})
diff --git a/Viewer/features/collections.js b/Viewer/features/collections.js
index 7140e666..2e3201b6 100755
--- a/Viewer/features/collections.js
+++ b/Viewer/features/collections.js
@@ -1779,6 +1779,13 @@ module.Collection = core.ImageGridFeatures.Feature({
// XXX
})
}],
+
+ // invalidate caches...
+ [[
+ 'loadCollection',
+ 'uncollect',
+ ],
+ 'clearCache: "view(-.*)?" "*" -- Clear view cache'],
],
})
diff --git a/Viewer/features/core.js b/Viewer/features/core.js
index dc47e1df..e66a992a 100755
--- a/Viewer/features/core.js
+++ b/Viewer/features/core.js
@@ -1027,9 +1027,21 @@ module.Serialization = ImageGridFeatures.Feature({
// Cache...
// XXX should this be in actions.js???
-// XXX should we invalidate the cache automatically???
-// XXX the cache can also be saved to localStorage and loaded until either
-// the version changes or the feature list...
+// XXX revise: cache group naming...
+// currently the used groups are:
+// Session groups -- cleared on .clear() ('cache')
+// session-*
+// view-*
+// View groups -- cleared by crop/collection ('crop', 'collections')
+// view-*
+// Changes groups -- cleared when specific changes are made ('changes')
+// *-data
+// *-images
+// ...
+// This approach seems not flexible enough...
+// Ideas:
+// - use keywords in group names??
+// XXX should we consider persistent caches -- localStorage???
var CacheActions = actions.Actions({
config: {
// Enable/disable caching...
@@ -1062,11 +1074,30 @@ var CacheActions = actions.Actions({
// action is available...
'pre-cache-progress': 3000,
+
+ // Groups to be cleared at the longest on session change...
+ //
+ // These include by default:
+ // 'session' - will live through the whole session.
+ // 'view' - cleared when view changes
+ //
+ 'cache-session-groups': [
+ 'session',
+ 'view',
+ ],
+
// XXX handler cache..
},
// Cache utility method...
//
+ // .cache(title, handler)
+ // -> value
+ //
+ // .cache(group, title, handler)
+ // -> value
+ //
+ //
// Example use:
// someAction: [
// function(){
@@ -1086,18 +1117,106 @@ var CacheActions = actions.Actions({
// return data
// }) }],
//
- cache: function(title, lister){
+ // XXX what should the default group be???
+ // XXX should this be an action???
+ __cache: null,
+ cache: function(title, handler){
+ var group = 'global'
+ // caching disabled...
if(!(this.config || {}).cache){
- return lister.call(this)
- }
+ return handler.call(this) }
+ arguments.length > 2
+ && ([group, title, handler] = arguments)
var cache = this.__cache = this.__cache || {}
+ cache = cache[group] = cache[group] || {}
return (cache[title] =
title in cache ?
- // pass the cached data for cloning/update to the lister...
- lister.call(this, cache[title])
- : lister.call(this))
- },
+ // pass the cached data for cloning/update to the handler...
+ handler.call(this, cache[title])
+ : handler.call(this)) },
+ clearCache: ['System/Clear cache',
+ doc`
+ Clear cache fully...
+ .clearCache()
+
+ Clear title (global group)...
+ .clearCache(title)
+
+ Clear title from group...
+ .clearCache(group, title)
+
+ Clear out the full group...
+ .clearCache(group, '*')
+
+
+ NOTE: a group can be a string, list or a regexp object.
+ `,
+ function(title){
+ var that = this
+ // full clear...
+ if(arguments.length == 0
+ || (arguments[0] == '*'
+ && arguments[1] == '*')){
+ delete this.__cache
+ // partial clear...
+ } else {
+ var group = 'global'
+ // both group and title given...
+ arguments.length > 1
+ && ([group, title] = arguments)
+
+ // regexp...
+ // NOTE: these are only supported in groups...
+ if(group != '*' && group.includes('*')){
+ group = new RegExp('^'+ group +'$', 'i')
+ group = Object.keys(this.__cache || {})
+ .filter(function(g){
+ return group.test(g) }) }
+
+ // clear title from each group...
+ if(group == '*' || group instanceof Array || group instanceof RegExp){
+ ;(group instanceof Array ?
+ group
+ : group instanceof RegExp ?
+ Object.keys(this.__cache || {})
+ .filter(function(g){
+ return group.test(g) })
+ : Object.keys(this.__cache || {}))
+ .forEach(function(group){
+ that.clearCache(group, title) })
+ // clear multiple titles...
+ } else if(title instanceof Array){
+ title.forEach(function(title){
+ delete ((that.__cache || {})[group] || {})[title] })
+ // clear group...
+ } else if(title == '*'){
+ delete (this.__cache || {})[group]
+ // clear title from group...
+ } else {
+ delete ((this.__cache || {})[group] || {})[title] } } }],
+
+ // special caches...
+ //
+ sessionCache: ['- System/',
+ doc`Add to session cache...
+
+ .sessionCache(title, handler)
+ -> value
+
+
+ This is a shorthand to:
+
+ .cache('session', title, handler)
+ -> value
+
+
+ NOTE: also see .cache(..)
+ `,
+ 'cache: "session" ...'],
+
+
+ // XXX doc: what are we precaching???
preCache: ['System/Run pre-cache',
doc`Run pre-cache...
@@ -1120,8 +1239,7 @@ var CacheActions = actions.Actions({
var done = 0
var attrs = []
for(var k in this){
- attrs.push(k)
- }
+ attrs.push(k) }
var l = attrs.length
var started = Date.now()
@@ -1131,45 +1249,25 @@ var CacheActions = actions.Actions({
var a = Date.now()
var b = a
if(attrs.length == 0){
- return
- }
-
+ return }
while(b - a < c){
this[attrs.pop()]
b = Date.now()
done += 1
-
this.showProgress
&& (show === true || (show && b - started > show))
- && this.showProgress('Caching', done, l)
- }
-
+ && this.showProgress('Caching', done, l) }
t === true ?
tick()
- : setTimeout(tick, t)
- }.bind(this)
+ : setTimeout(tick, t) }.bind(this)
- tick()
- }
- }],
- clearCache: ['System/Clear cache',
- function(title){
- if(title){
- delete (this.__cache|| {})[title]
-
- } else {
- delete this.__cache
- }
- }],
-
- // XXX do we need this...
+ tick() } }],
reCache: ['System/Re-cache',
function(t){
this
.clearCache()
.preCache(t) }],
-
toggleHandlerCache: ['System/Action handler cache',
makeConfigToggler('action-handler-cache',
['off', 'on']/*,
@@ -1192,15 +1290,16 @@ module.Cache = ImageGridFeatures.Feature({
actions: CacheActions,
handlers: [
+ // System...
['start.pre',
function(){
+ this.clearCache()
var t = this.config['pre-cache']
t === true ?
this.preCache('now')
: t >= 0 ?
this.preCache()
- : false
- }],
+ : false }],
['start',
function(){
// XXX this breaks loading...
@@ -1208,7 +1307,6 @@ module.Cache = ImageGridFeatures.Feature({
// there seems to be no problems...
//this.toggleHandlerCache(this.config['action-handler-cache'] || 'on')
}],
-
/*/ XXX clear cache when feature/action topology changes...
[[
'inlineMixin',
@@ -1222,6 +1320,16 @@ module.Cache = ImageGridFeatures.Feature({
this.clearCache()
}],
//*/
+
+
+ // clear session cache...
+ ['clear',
+ //'clearCache: "(session|view)(-.*)?" "*" -- Clear session cache'],
+ function(){
+ this.clearCache(`(${
+ (this.config['cache-session-groups']
+ || ['session', 'view'])
+ .join('|') })(-.*)?`) }],
],
})
@@ -2148,6 +2256,16 @@ module.Changes = ImageGridFeatures.Feature({
this.changes = JSON.parse(JSON.stringify(data.changes))
}
}],
+
+ // clear caches relating to stuff we just changed...
+ ['markChanged',
+ function(_, section){
+ section = (section instanceof Array ?
+ section
+ : [section])
+ .map(function(section){
+ return '.*-'+section })
+ this.clearCache(section, '*') }],
],
})
diff --git a/Viewer/features/ui-status.js b/Viewer/features/ui-status.js
index 0b3e1fd1..de6a752c 100755
--- a/Viewer/features/ui-status.js
+++ b/Viewer/features/ui-status.js
@@ -25,8 +25,7 @@ var base = require('features/base')
var makeStateIndicator = function(type){
return $('
')
- .addClass('state-indicator-container ' + type || '')
-}
+ .addClass('state-indicator-container ' + type || '') }
// XXX do we need this???
var makeStateIndicatorItem = function(container, type, text){
@@ -35,8 +34,7 @@ var makeStateIndicatorItem = function(container, type, text){
.attr('text', text)
this.dom.find('.state-indicator-container.'+container)
.append(item)
- return item
-}
+ return item }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -102,6 +100,13 @@ var StatusBarActions = actions.Actions({
},
},
+
+ get __statusbar_cache(){
+ return this.cache('view-data', 'statusbar',
+ function(data){
+ return data || {}}) },
+
+
__statusbar_elements__: {
/* item template...
item: function(item){
@@ -133,8 +138,7 @@ var StatusBarActions = actions.Actions({
index: function(item, gid, img){
// cleanup...
if(item == null){
- return
- }
+ return }
var that = this
gid = gid || this.current
@@ -162,8 +166,7 @@ var StatusBarActions = actions.Actions({
// toggle index state...
.click(function(){
that.toggleStatusBarIndexMode()
- that.updateStatusBar()
- })
+ that.updateStatusBar() })
// editable...
: $('')
.addClass('position editable')
@@ -182,40 +185,35 @@ var StatusBarActions = actions.Actions({
//event.stopPropagation()
(that.config['status-bar-index'] || {})['live-update-on-edit']
- && go(parseInt($(this).text()))
- })
+ && go(parseInt($(this).text())) })
.focus(function(){
- $(this).selectText()
- })
+ $(this).selectText() })
.blur(function(){
- that.updateStatusBar()
- }))
+ that.updateStatusBar() }))
.append($('')
.addClass('length')
.attr('info', 'Image count (click to toggle ribbon/global)')
// toggle index state...
.click(function(){
that.toggleStatusBarIndexMode()
- that.updateStatusBar()
- }))
+ that.updateStatusBar() }))
} else {
- var type = item.attr('type')
- }
+ var type = item.attr('type') }
// NOTE: using .toggleStatusBarIndexMode(..) here will fall
// into an infinite recursion...
var cls = (that.config['status-bar-index'] || {})['mode'] || 'normal'
- // XXX get the cached length...
- // XXX make this part of the status bar cache...
- var cache = this.__statusbar_index_length_cache || []
- cache = cache[0] == cls ?
- cache[1]
+ // get the cached length...
+ var cache = this.__statusbar_cache.index_total
+ cache = cache ?
+ (cache[0] == cls
+ && cache[1])
: null
// empty view...
- if(this.data){
+ if(!this.data){
var i = -1
var l = 0
@@ -234,11 +232,16 @@ var StatusBarActions = actions.Actions({
// ribbon index...
} else {
var i = this.data.getImageOrder('ribbon', gid)
- var l = cache =
- cache || this.data.getImages(gid).len }
+ var r = this.current_ribbon
+ var l = cache
+ && cache instanceof Array
+ && cache[0] == r
+ && cache[1]
+ l = l || this.data.getImages(gid).len
+ cache = [r, l] }
- // XXX save cache...
- this.__statusbar_index_length_cache = [cls, cache]
+ // save cache...
+ this.__statusbar_cache.index_total = [cls, cache]
// update...
item
@@ -250,13 +253,11 @@ var StatusBarActions = actions.Actions({
.find('.length')
.text(l > 0 ? ('/' + l) : '')
- return item
- },
+ return item },
ribbon: function(item, gid, img){
// cleanup...
if(item == null){
- return
- }
+ return }
var that = this
@@ -294,8 +295,7 @@ var StatusBarActions = actions.Actions({
}))
.append($('')
.addClass('ribbon-count')
- .attr('info', 'Ribbon count'))
- }
+ .attr('info', 'Ribbon count')) }
item
.find('.ribbon-number')
@@ -312,22 +312,18 @@ var StatusBarActions = actions.Actions({
item[0].setAttribute('base', '')
} else {
- item[0].removeAttribute('base')
- }
+ item[0].removeAttribute('base') }
- return item
- },
+ return item },
changes: function(item, gid, img){
// cleanup...
if(item == null){
- return
- }
+ return }
if(typeof(item) == typeof('str')){
item = $('')
.addClass('changes')
- .attr('info', 'Unsaved changes')
- }
+ .attr('info', 'Unsaved changes') }
//item.html(this.changes !== false ?
// this.config['status-bar-changes-text'] || '*'
@@ -337,14 +333,12 @@ var StatusBarActions = actions.Actions({
this.config['status-bar-changes-text'] || '*'
: '')
- return item
- },
+ return item },
// XXX handle path correctly...
gid: function(item, gid, img){
// cleanup...
if(item == null){
- return
- }
+ return }
var that = this
gid = gid || this.current
@@ -363,12 +357,10 @@ var StatusBarActions = actions.Actions({
// select the text...
// XXX should this also copy???
.click(function(){
- $(this).selectText()
- }))
+ $(this).selectText() }))
} else {
- var type = item.attr('type')
- }
+ var type = item.attr('type') }
// update...
var txt = ''
@@ -386,14 +378,14 @@ var StatusBarActions = actions.Actions({
text = (img && img.path && ((img.base_path || '') +'/'+ img.path) || '---')
// remove /./
.replace(/[\\\/]\.[\\\/]/, '/')
- txt = img && ((img.name || '') + (img.ext || '')) || text.split(/[\\\/]/).pop()
- }
+ txt = img
+ && ((img.name || '') + (img.ext || ''))
+ || text.split(/[\\\/]/).pop() }
item.find('.shown').text(txt)
item.find('.hidden').text(text)
- return item
- },
+ return item },
path: 'gid',
'edit-mode': function(item){
// cleanup...
@@ -401,21 +393,20 @@ var StatusBarActions = actions.Actions({
this.__edit_mode_indicator_update
&& this.off('keyPress', this.__edit_mode_indicator_update)
delete this.__edit_mode_indicator_update
- return
- }
+ return }
- var update = this.__edit_mode_indicator_update = this.__edit_mode_indicator_update
- || (function(){
- var caps = this.keyboard.capslock
- caps = typeof(event) != 'undefined' && event.getModifierState ?
- event.getModifierState('CapsLock')
- : caps
- item
- .attr('info', 'Edit mode '
- + (caps ? 'on' : 'off')
- + ' (Click to update / Press CapsLock to toggle)')
- [caps ? 'addClass' : 'removeClass']('on')
- }).bind(this)
+ var update = this.__edit_mode_indicator_update =
+ this.__edit_mode_indicator_update
+ || (function(){
+ var caps = this.keyboard.capslock
+ caps = typeof(event) != 'undefined' && event.getModifierState ?
+ event.getModifierState('CapsLock')
+ : caps
+ item
+ .attr('info', 'Edit mode '
+ + (caps ? 'on' : 'off')
+ + ' (Click to update / Press CapsLock to toggle)')
+ [caps ? 'addClass' : 'removeClass']('on') }).bind(this)
// cleanup interval handling...
this.__edit_mode_indicator_update_interval
@@ -426,8 +417,7 @@ var StatusBarActions = actions.Actions({
if(item == null){
this.off('keyPress', update)
this.dom.off('focus', update)
- return
- }
+ return }
// setup...
if(typeof(item) == typeof('str')){
@@ -441,8 +431,7 @@ var StatusBarActions = actions.Actions({
.click(update)
this.on('keyPress', update)
- this.dom.focus(update)
- }
+ this.dom.focus(update) }
// update timer...
// NOTE: this is needed so as to reflect changes to settings...
@@ -454,15 +443,13 @@ var StatusBarActions = actions.Actions({
// update state...
update()
- return item
- },
+ return item },
// XXX show menu in the appropriate corner...
// XXX remove the type+ed class...
mark: function(item, gid, img){
// cleanup...
if(item == null){
- return
- }
+ return }
gid = gid || this.current
var that = this
@@ -484,12 +471,10 @@ var StatusBarActions = actions.Actions({
evt.preventDefault()
evt.stopPropagation()
- that.browseActions('/'+ type.capitalize() +'/')
- })
+ that.browseActions('/'+ type.capitalize() +'/') })
} else {
- var type = item.attr('type')
- }
+ var type = item.attr('type') }
// NOTE: we are not using .toggleMark('?') and friends
// here to avoid recursion as we might be handling
@@ -503,8 +488,7 @@ var StatusBarActions = actions.Actions({
'removeClass'
: 'addClass']('on')
- return item
- },
+ return item },
bookmark: 'mark',
},
@@ -520,8 +504,7 @@ var StatusBarActions = actions.Actions({
function(){
// no viewer yet...
if(!this.ribbons || !this.dom){
- return $()
- }
+ return $() }
var bar = this.dom.find('.state-indicator-container.global-info')
if(bar.length == 0){
@@ -543,17 +526,14 @@ var StatusBarActions = actions.Actions({
.on('mouseout', function(){
bar.find('.info').empty()
})
- .appendTo(this.dom)
- }
- return bar
- },
+ .appendTo(this.dom) }
+ return bar },
function(){ return Object.keys(this.config['status-bars']).concat(['none']) },
// XXX check if we will be getting gid reliably...
function(state, bar, gid){
// do not do anything unless the status bar exists...
if(bar.length == 0){
- return
- }
+ return }
var that = this
this.config['status-bar'] = state
@@ -564,8 +544,7 @@ var StatusBarActions = actions.Actions({
var handler = elems[key] || base_elems[key]
if(handler == null){
- return
- }
+ return }
// handle aliases...
var seen = []
@@ -576,15 +555,13 @@ var StatusBarActions = actions.Actions({
if(seen.indexOf(handler) >= 0){
console.error('state indicator alias loop detected at:', key)
handler = null
- break
- }
- }
+ break } }
- return handler
- }
+ return handler }
// clear...
if(state == 'none' || !bar.hasClass(state)){
+ this.clearStatusBarCache()
// notify items that they are removed...
bar.children()
.each(function(i, item){
@@ -592,25 +569,21 @@ var StatusBarActions = actions.Actions({
var type = item.attr('type')
if(type == null){
- return
- }
+ return }
var handler = _getHandler(type)
if(handler != null){
- handler.call(that, null)
- }
+ handler.call(that, null) }
})
- bar.empty()
- }
+ bar.empty() }
if(state == 'none'){
!('none' in this.config['status-bars'])
// XXX this feels like a hack...
&& setTimeout(function(){ this.toggleStatusBar(0) }.bind(this), 0)
//return Object.keys(this.config['status-bars'])[0]
- return
- }
+ return }
// build/update...
gid = gid || this.current
@@ -642,11 +615,9 @@ var StatusBarActions = actions.Actions({
item = (handler ?
handler.call(that, item, gid, img)
: $(''))
- .attr('type', item)
- }
+ .attr('type', item) }
- bar.append(item)
- })
+ bar.append(item) })
// update...
} else {
@@ -656,17 +627,12 @@ var StatusBarActions = actions.Actions({
var type = item.attr('type')
if(type == null){
- return
- }
+ return }
var handler = _getHandler(type)
if(handler != null){
- handler.call(that, item, gid, img)
- }
- })
- }
- },
+ handler.call(that, item, gid, img) } }) } },
null)],
updateStatusBar: ['- Interface/Update satus bar',
'toggleStatusBar: "!"'],
@@ -675,8 +641,10 @@ var StatusBarActions = actions.Actions({
function(){
var mode = this.toggleStatusBar('?')
this.toggleStatusBar('none')
- this.toggleStatusBar(mode)
- }],
+ this.toggleStatusBar(mode) }],
+ clearStatusBarCache: ['- Interface/Clear status bar cache',
+ 'clearCache: "*" "statusbar"'],
+
// XXX should this blink the on state only???
statusItemBlink: ['- Interface/',
@@ -685,8 +653,7 @@ var StatusBarActions = actions.Actions({
NOTE: type is the same as in .__statusbar_elements__`,
function(type){
if(type == null){
- return
- }
+ return }
var gid = this.current
var item = this.dom.find(`.state-indicator-container.global-info [type=${type}]`)
@@ -695,42 +662,36 @@ var StatusBarActions = actions.Actions({
item
.removeClass('blink')
.addClass('blink')
- .on('animationend', function(){ item.removeClass('blink') })
- }],
+ .on('animationend', function(){ item.removeClass('blink') }) }],
// XXX should these be here???
// XXX should this show a dialog???
editStatusBarIndex: ['- Interface/Edit image focus position in statusbar',
function(){
if((this.config['status-bar-index'] || {} )['editable']){
- this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
-
+ this.toggleStatusBar('?') == 'none'
+ && this.toggleStatusBar()
// XXX do this better...
- this.dom.find('.global-info .index .position').focus().click()
- }
- }],
+ this.dom.find('.global-info .index .position').focus().click() } }],
editStatusBarRibbon: ['- Interface/Edit ribbon focus position in statusbar',
function(){
- this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
-
+ this.toggleStatusBar('?') == 'none'
+ && this.toggleStatusBar()
// XXX do this better...
- this.dom.find('.global-info .ribbon-number').focus().click()
- }],
+ this.dom.find('.global-info .ribbon-number').focus().click() }],
toggleStatusBarIndexMode: ['Interface/Status bar index mode',
toggler.CSSClassToggler(
function(){
return this.dom.find('.global-info .index') },
['normal', 'loaded', 'global'],
function(state){
- this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
-
+ this.toggleStatusBar('?') == 'none'
+ && this.toggleStatusBar()
// prepare for saving the config...
this.config['status-bar-index'] =
JSON.parse(JSON.stringify(this.config['status-bar-index']))
this.config['status-bar-index']['mode'] = state
-
- this.updateStatusBar()
- })],
+ this.updateStatusBar() })],
// XXX revise...
showStatusBarInfo: ['- Interface/',
@@ -807,12 +768,10 @@ module.StatusBar = core.ImageGridFeatures.Feature({
handlers: [
['start',
function(){
- this.toggleStatusBar(this.config['status-bar'])
- }],
+ this.toggleStatusBar(this.config['status-bar']) }],
['focusImage clear markChanged refresh',
function(){
- this.updateStatusBar()
- }],
+ this.updateStatusBar() }],
[[
'tag',
'untag',
@@ -823,14 +782,12 @@ module.StatusBar = core.ImageGridFeatures.Feature({
&& (gids.indexOf('current') >= 0
|| gids.indexOf(this.current) >= 0)
|| this.data.getImage(gids) == this.current){
- this.updateStatusBar()
- }
- }],
+ this.updateStatusBar() } }],
['ribbonPanning.post',
function(_, gid){
- gid == this.data.getRibbon() && this.updateStatusBar()
- }],
+ gid == this.data.getRibbon()
+ && this.updateStatusBar() }],
// blink status mark indicators on toggle...
['toggleMark',
@@ -853,13 +810,11 @@ module.StatusBar = core.ImageGridFeatures.Feature({
],
function(workspace){
if(!workspace || workspace in this.workspaces){
- return
- }
+ return }
this.config['status-bar'] =
(this.config['status-bar-workspace-defaults'][workspace]
- || this.config['status-bar'])
- }],
+ || this.config['status-bar']) }],
['loadWorkspace',
core.makeWorkspaceConfigLoader(
function(){
@@ -871,9 +826,7 @@ module.StatusBar = core.ImageGridFeatures.Feature({
} else {
'status-bar' in workspace ?
this.toggleStatusBar(workspace['status-bar'])
- : this.toggleStatusBar(this.config['status-bar'])
- }
- })],
+ : this.toggleStatusBar(this.config['status-bar']) } })],
],
})
diff --git a/Viewer/imagegrid/data.js b/Viewer/imagegrid/data.js
index 98889a36..c8ec6333 100755
--- a/Viewer/imagegrid/data.js
+++ b/Viewer/imagegrid/data.js
@@ -13,6 +13,7 @@
var sha1 = require('ext-lib/sha1')
+var types = require('lib/types')
var object = require('lib/object')
var tags = require('imagegrid/tags')
@@ -223,6 +224,7 @@ var DataPrototype = {
ribbon_order: null,
ribbons: null,
+ //__current: null,
get current(){
return this.__current = this.__current
|| this.getImages(this.ribbon_order[0])[0]
@@ -230,6 +232,7 @@ var DataPrototype = {
set current(value){
this.focusImage(value) },
+ //__base: null,
get base(){
return this.__base || this.ribbon_order[0] },
set base(value){
@@ -237,13 +240,18 @@ var DataPrototype = {
this.getRibbon(value)
: value },
+ // NOTE: experiments with wrapping data in Proxy yielded a
+ // significant slowdown on edits...
+ //__order: null,
get order(){
return this.__order },
set order(value){
delete this.__order_index
this.__order = value },
+ //__order_index: null,
get order_index(){
- return this.__order_index = this.__order_index || this.order.toKeys() },
+ return this.__order_index =
+ this.__order_index || this.order.toKeys() },
@@ -1027,16 +1035,16 @@ var DataPrototype = {
// order.
getImageOrder: function(context, target, mode, list){
if(context == 'loaded' || context == 'global'){
- return this.getImages('loaded').indexOf(this.getImage(target, mode, list))
+ return this.getImages('loaded').lastIndexOf(this.getImage(target, mode, list))
} else if(context == 'ribbon'){
var gid = this.getImage(target, mode, list)
- return this.getImages(gid).indexOf(gid)
+ return this.getImages(gid).lastIndexOf(gid)
} else if(context == 'all'){
- return this.order.indexOf(this.getImage(target, mode, list)) }
+ return this.order.lastIndexOf(this.getImage(target, mode, list)) }
- return this.order.indexOf(this.getImage(context, target, mode)) },
+ return this.order.lastIndexOf(this.getImage(context, target, mode)) },
// Get a list of image gids...
//
@@ -1183,7 +1191,6 @@ var DataPrototype = {
target = this.getImage(target)
|| this.getImage(target, 'after')
- var i = list.indexOf(target)
// prepare to slice the list...
if(mode == 'around' || mode == 'total'){
@@ -1204,6 +1211,10 @@ var DataPrototype = {
var res = [target]
+ // XXX can we avoid .indexOf(..) here???
+ //var i = list.indexOf(target)
+ //var i = list.index(target)
+ var i = list.lastIndexOf(target)
// pre...
for(var n = i-1; n >= 0 && pre > 0; n--){
// NOTE: list may be sparse so we skip the items that are not
@@ -1227,7 +1238,9 @@ var DataPrototype = {
// in the post section...
if(mode == 'total' && post > 0){
var pad = count - res.length
- var i = list.indexOf(res[0])
+ //var i = list.indexOf(res[0])
+ //var i = list.index(res[0])
+ var i = list.lastIndexOf(res[0])
res.reverse()
for(var n = i-1; n >= 0 && pad > 0; n--){
diff --git a/Viewer/package-lock.json b/Viewer/package-lock.json
index 16d9be8d..ae6cdfb3 100755
--- a/Viewer/package-lock.json
+++ b/Viewer/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "ImageGrid.Viewer.g4",
- "version": "4.0.0a",
+ "version": "4.0.0-a",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1110,9 +1110,9 @@
"integrity": "sha512-9kZM80Js9/eTwXN9VXwLDC1wDJ7gIAdYU9GIzb5KJmNcLAMaW+zhgFrwFFMrcSfggUuadgnqSrS41E4XLe8JZw=="
},
"ig-types": {
- "version": "5.0.18",
- "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-5.0.18.tgz",
- "integrity": "sha512-8c16slG/J0qC9oYW1Mx6oSriEYKEY/HLs4SvgWDLqac/qx/nMaa6HlEUA/fi+whGxvTk03t4s/IKca+MKWV9oQ==",
+ "version": "5.0.20",
+ "resolved": "https://registry.npmjs.org/ig-types/-/ig-types-5.0.20.tgz",
+ "integrity": "sha512-d2IEwY3ZDSWxn2PY0e7XxMzuOPWzeK/py0sBgqfoCNbKlc4IHEogFwoQIv0C4EZdcXL0cJOsCo74NwbetoSWiA==",
"requires": {
"ig-object": "^5.4.12",
"object-run": "^1.0.1"
diff --git a/Viewer/package.json b/Viewer/package.json
index a6ab2f98..4ea92719 100755
--- a/Viewer/package.json
+++ b/Viewer/package.json
@@ -32,7 +32,7 @@
"ig-argv": "^2.15.0",
"ig-features": "^3.4.2",
"ig-object": "^5.4.12",
- "ig-types": "^5.0.18",
+ "ig-types": "^5.0.20",
"moment": "^2.29.1",
"object-run": "^1.0.1",
"requirejs": "^2.3.6",