diff --git a/Viewer/css/experimenting.css b/Viewer/css/experimenting.css
index 99aa944b..9bd0f343 100755
--- a/Viewer/css/experimenting.css
+++ b/Viewer/css/experimenting.css
@@ -323,7 +323,7 @@ body {
font-style: italic;
}
.browse-widget.tail-action .list .item:last-child .button {
- display: none;
+ /*display: none;*/
}
/* do not show top border if after another action or separator... */
diff --git a/Viewer/features/filesystem.js b/Viewer/features/filesystem.js
index ba0bb811..7698b80c 100755
--- a/Viewer/features/filesystem.js
+++ b/Viewer/features/filesystem.js
@@ -3001,6 +3001,8 @@ var FileSystemWriterUIActions = actions.Actions({
.exportDialog(mode)
.exportDialog(settings)
+
+ NOTE: when saving a preset the dialog will trigger a 'save-preset' event.
`,
widgets.makeUIDialog(function(mode){
var that = this
@@ -3075,8 +3077,23 @@ var FileSystemWriterUIActions = actions.Actions({
var mode =
that.config['export-dialog-modes'][settings['mode']]
that[mode.action](settings)
- dialog.close()
- },
+ dialog.close() },
+ buttons: [
+ ['Save preset',
+ function(_, elem){
+ that.exportPresetSave()
+
+ // button press feedback...
+ var e = elem.find('.button small')
+ var text = e.text()
+ var reset = function(){
+ e.text(text) }
+ e.text('Saved.')
+ e.one('mouseout', reset)
+ setTimeout(reset, 2000)
+
+ make.dialog.trigger('save-preset')
+ }] ],
})
make.done()
@@ -3100,6 +3117,7 @@ var FileSystemWriterUIActions = actions.Actions({
// XXX add a 'name' field to the exportDialog(..)???
// XXX button icons...
// XXX button shortcuts...
+ // XXX handle presets with repeating titles...
exportPresets: ['- File/Export history...',
widgets.makeUIDialog(function(mode){
var that = this
@@ -3109,29 +3127,32 @@ var FileSystemWriterUIActions = actions.Actions({
var getName = function(preset){
return preset.name
|| `${ preset.mode }: "${ preset.path }"` }
+ var buildIndex = function(presets){
+ var index
+ return [
+ // index...
+ (index = presets
+ .reduce(function(res, e, i){
+ res[getName(e)] = i
+ return res }, {})),
+ // keys...
+ Object.keys(index), ] }
+ var getPreset = function(title, presets, index){
+ return presets[index[title]] }
// presets...
var presets = that.config['export-presets'] || []
- var index = presets
- .reduce(function(res, e, i){
- res[getName(e)] = i
- return res }, {})
- var keys = Object.keys(index)
+ var [index, keys] = buildIndex(presets)
// history...
// XXX
var history = []
- var history_index = {}
- var history_keys = Object.keys(history_index)
-
- var getPreset = function(title, presets, index){
- return presets[index[title]] }
+ var [history_index, history_keys] = buildIndex(history)
return browse.makeLister(null, function(path, make){
// preset list...
- keys.length == 0 ?
- make.Empty('No presets...')
- : make.EditableList(keys, {
+ keys.length > 0
+ && make.EditableList(keys, {
list_id: 'presets',
sortable: true,
update_merge: 'live',
@@ -3140,7 +3161,7 @@ var FileSystemWriterUIActions = actions.Actions({
allow_empty: true,
itemedit: function(evt, from, to){
var preset = getPreset(from, presets, index)
- // clear...
+ // reset...
if(to.trim() == ''){
delete preset.name
to = keys[keys.indexOf(from)] = getName(preset)
@@ -3158,18 +3179,32 @@ var FileSystemWriterUIActions = actions.Actions({
function(){
make.dialog.select(to) }) },
buttons: [
- ['edit', function(title){
- var preset = getPreset(title, presets, index)
- that.exportDialog(preset)
- .close(function(){
- var n = getName(preset)
- // update the list if name is affected...
- if(n != title){
- keys[keys.indexOf(title)] = n
- index[n] = index[title]
- delete index[title]
- make.dialog.select(n)
- make.dialog.update() } })}],
+ // edit...
+ ['edit',
+ function(title){
+ var preset = getPreset(title, presets, index)
+ that.exportDialog(preset)
+ .close(function(){
+ var n = getName(preset)
+ // update the list if name is affected...
+ if(n != title){
+ keys[keys.indexOf(title)] = n
+ index[n] = index[title]
+ delete index[title]
+ make.dialog.select(n)
+ make.dialog.update() } })}],
+ // duplicate...
+ ['❏',
+ function(title){
+ var preset = JSON.parse(
+ JSON.stringify(
+ getPreset(title, presets, index) ))
+ preset.name = title + ' (copy)'
+ // place preset in list...
+ var i = index[preset.name] = index[title]+1
+ presets.splice(i, 0, preset)
+ keys.splice(keys.indexOf(title)+1, 0, preset.name)
+ make.dialog.update() }],
['♦', 'TO_TOP'],
'REMOVE'],
// export...
@@ -3188,6 +3223,14 @@ var FileSystemWriterUIActions = actions.Actions({
make('E$xport...', {
open: function(){
that.exportDialog()
+ // new preset saved...
+ .on('save-preset', function(){
+ var [idx, k] = buildIndex(presets)
+ index = idx
+ // NOTE: keys must be updated in-place...
+ keys.splice(0, keys.length, ...k)
+ make.dialog.update() })
+ // close dialog on export...
.close(function(evt, reason){
reason != 'reject'
&& make.dialog.close() }) }, })
@@ -3196,16 +3239,17 @@ var FileSystemWriterUIActions = actions.Actions({
make.Separator()
history.length == 0 ?
make.Empty('No export history...')
- : ake.EditableList(history, {
+ : ake.EditableList(history_keys, {
list_id: 'history',
sortable: false,
new_item: false,
editable_items: false,
buttons: [
// to preset...
- ['P', function(){
- // XXX
- }],
+ ['save',
+ function(){
+ // XXX
+ }],
'REMOVE',
],
// XXX export...
@@ -3220,7 +3264,17 @@ var FileSystemWriterUIActions = actions.Actions({
this.keyboard.on('E', function(){
console.log('!!!!!!!!!!!!!', that.selected)
})
- }) })],
+ })
+ .close(function(){
+ // update preset order and count...
+ that.config['export-presets'] = keys
+ .map(function(e){
+ return getPreset(e, presets, index) })
+ // handle history delete...
+ history.length != that.config['export-history']
+ && that.config['export-history'] = history_keys
+ .map(function(e){
+ return getPreset(e, history, history_index) }) }) })],
// XXX these do note need the ui -- move to a separate feature...
// XXX these are essentially the same as the history API, make a
@@ -3235,7 +3289,7 @@ var FileSystemWriterUIActions = actions.Actions({
&& (this.config['export-presets'] =
this.config['export-presets']
|| [])
- .push(settings) }],
+ .push(JSON.parse(JSON.stringify( settings ))) }],
// XXX need a way to reference a preset...
exportPresetDelete: ['- File/',
@@ -3255,7 +3309,7 @@ var FileSystemWriterUIActions = actions.Actions({
// add...
// XXX need to check item uniqueness...
settings
- && history.push(settings)
+ && history.push(JSON.parse(JSON.stringify( settings )))
// trim the history...
history.length > l
&& history.splice(0, history.length - l) }],
diff --git a/Viewer/lib/widget/browse.js b/Viewer/lib/widget/browse.js
index d964b277..f555605f 100755
--- a/Viewer/lib/widget/browse.js
+++ b/Viewer/lib/widget/browse.js
@@ -102,8 +102,7 @@ function(msg, options){
: true
options.cls = (options.cls || '') + ' empty-msg'
msg = msg || options.message || 'Empty...'
- return this(msg, options)
-}
+ return this(msg, options) }
// NOTE: this is the same as make('---'[, options])
@@ -141,8 +140,7 @@ Items.Action =
function(text, options){
options = Object.create(options || {})
options.cls = (options.cls || '') + ' action'
- return this(text, options)
-}
+ return this(text, options) }
// Action requiring confirmation...
//
@@ -205,10 +203,7 @@ function(text, options){
// confirmed...
} else {
- callback && callback()
- }
- })
-}
+ callback && callback() } }) }
// Item with auto selected text on select...
//
@@ -245,8 +240,7 @@ function(text, options){
text.selectText()
})
- return elem
-}
+ return elem }
// Editable item or it's part...
//
@@ -385,8 +379,7 @@ function(text, options){
&& elem
.on(stop_propagation, function(e){ e.stopPropagation() })
- return elem
-}
+ return elem }
@@ -419,8 +412,7 @@ function(list){
.addClass('item-group')
.appendTo($(res).parent())
.append($(res))
- return group
-}
+ return group }
// List of elements...
@@ -516,19 +508,14 @@ function(data, options){
// no match -- restore text...
} else {
- txt = k
- }
- }
- })
+ txt = k } } })
if(opts.disabled && opts.disabled instanceof Array){
- opts.disabled = opts.disabled.indexOf(txt || k) >= 0
- }
+ opts.disabled = opts.disabled.indexOf(txt || k) >= 0 }
if((opts.disabled && opts.skipDisabledItems)
|| (opts.hidden && opts.skipHiddenItems)){
- return
- }
+ return }
var elem = make(txt || k, opts)
@@ -538,13 +525,11 @@ function(data, options){
opts.each
&& opts.each.call(elem, txt || k)
- res.push(elem[0])
- })
+ res.push(elem[0]) })
return options.groupList ?
make.Group(res).children()
- : $(res)
-}
+ : $(res) }
// Editable list of elements...
@@ -1296,23 +1281,20 @@ function(list, pins, options){
// unpin...
} else {
- pins.splice(pins.indexOf(p), 1)
- }
+ pins.splice(pins.indexOf(p), 1) }
// XXX this is slow...
that.dialog
.update()
.then(function(){
- that.dialog.trigger('pin_button', p, cur)
- })
+ that.dialog.trigger('pin_button', p, cur) })
}]
;[buttons, pins_buttons]
.forEach(function(b){
var i = b.indexOf('PIN')
i < 0 ?
b.push(pin)
- : (b[i] = pin)
- })
+ : (b[i] = pin) })
options.isItemHidden = function(e){ return pins.indexOf(e) >= 0 }
options.skipHiddenItems = options.skipHiddenItems !== false ? true : false
@@ -1333,8 +1315,7 @@ function(list, pins, options){
if(!sortable){
pins_options.sort = options.sort instanceof Function ?
options.sort
- : pins.sortAs(dialog.__list[id])
- }
+ : pins.sortAs(dialog.__list[id]) }
//---------------------------------------------- build the list ---
var res = this.EditableList(pins, pins_options)
@@ -1350,8 +1331,7 @@ function(list, pins, options){
options)
.toArray())
- return $(res)
-}
+ return $(res) }
@@ -1383,10 +1363,7 @@ Buttons.markForRemoval = function(list, html){
} else {
var i = list.indexOf(p)
i >= 0
- && list.splice(i, 1)
- }
- }]
-}
+ && list.splice(i, 1) } }] }
@@ -1688,6 +1665,7 @@ var BrowserPrototype = {
'open',
'menu',
'update',
+ 'close',
],
// Shorthand elements...
@@ -2252,6 +2230,7 @@ var BrowserPrototype = {
// open: ,
// menu: ,
// update: ,
+ // close: ,
//
// // event handlers...
// events: {