mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
refactoring + work on kb editors...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
f78c56a8c5
commit
5050537966
@ -241,6 +241,26 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* new item... */
|
||||
.browse-widget .list>.action {
|
||||
margin-top: 0.2em;
|
||||
border-top: solid 1px rgba(255,255,255, 0.2);
|
||||
}
|
||||
.browse-widget .list>.action .text {
|
||||
font-style: italic;
|
||||
}
|
||||
/* do not show top border if after another action or separator... */
|
||||
.browse-widget .list>.action+.action,
|
||||
.browse-widget .list>.separator+.action {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* do not show top border if after another action or separator... */
|
||||
.browse-widget .list>.warn {
|
||||
background-color: yellow !important;
|
||||
color: red !important;
|
||||
font-weight: bolder !important;
|
||||
}
|
||||
|
||||
|
||||
/* Dialog highlight experiment... */
|
||||
|
||||
@ -594,21 +594,7 @@ var URLHistoryUIActions = actions.Actions({
|
||||
o.redraw()
|
||||
}],
|
||||
// mark for removal...
|
||||
['×',
|
||||
function(p, cur){
|
||||
cur.toggleClass('strike-out')
|
||||
|
||||
if(cur.hasClass('strike-out')){
|
||||
to_remove.indexOf(p) < 0
|
||||
&& to_remove.push(p)
|
||||
|
||||
} else {
|
||||
var i = to_remove.indexOf(p)
|
||||
if(i >= 0){
|
||||
to_remove.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}],
|
||||
widgets.makeRemoveItemButton(to_remove)
|
||||
],
|
||||
})
|
||||
.open(function(evt, path){
|
||||
|
||||
@ -147,6 +147,8 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
'on this page.',
|
||||
pattern: '*',
|
||||
|
||||
F1: 'browseActions: "/Help/" -- Help menu...',
|
||||
|
||||
alt_X: 'close',
|
||||
alt_F4: 'close',
|
||||
meta_Q: 'close',
|
||||
@ -176,7 +178,7 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
// XXX should this be all here or in respective sections???
|
||||
alt_A: 'browseActions',
|
||||
|
||||
//alt_S: 'browseActions: "/Sort/"',
|
||||
//alt_S: 'browseActions: "/Sort/" -- Sort menu...',
|
||||
alt_shift_A: 'listActions',
|
||||
|
||||
|
||||
@ -201,7 +203,7 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
ctrl_Z: 'undo',
|
||||
shift_U: 'redo',
|
||||
ctrl_shift_Z: 'redo',
|
||||
alt_H: 'browseActions: "/History/" -- Open history menu',
|
||||
alt_H: 'browseActions: "/History/" -- History menu...',
|
||||
|
||||
|
||||
// tilt...
|
||||
@ -293,8 +295,8 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
|
||||
|
||||
// ribbon image stuff...
|
||||
alt_I: 'browseActions: "/Image/" -- Show image menu',
|
||||
alt_R: 'browseActions: "/Ribbon/" -- Open ribbon menu',
|
||||
alt_I: 'browseActions: "/Image/" -- Image menu...',
|
||||
alt_R: 'browseActions: "/Ribbon/" -- Ribbon menu...',
|
||||
|
||||
|
||||
// ranges...
|
||||
@ -332,7 +334,7 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
shift_F2: 'cropRibbonAndAbove',
|
||||
ctrl_F2: 'cropMarked',
|
||||
alt_F2: 'cropBookmarked',
|
||||
C: 'browseActions: "/Crop/" -- Show crop menu',
|
||||
C: 'browseActions: "/Crop/" -- Crop menu...',
|
||||
|
||||
|
||||
// metadata...
|
||||
@ -347,14 +349,14 @@ module.GLOBAL_KEYBOARD2 = {
|
||||
ctrl_I: 'toggleMark!: "ribbon" -- Invert marks in ribbon',
|
||||
',': 'prevMarked',
|
||||
'.': 'nextMarked',
|
||||
alt_M: 'browseActions: "/Mark/" -- Show mark menu',
|
||||
alt_M: 'browseActions: "/Mark/" -- Mark menu...',
|
||||
|
||||
|
||||
// bookmarking...
|
||||
B: 'toggleBookmark',
|
||||
'[': 'prevBookmarked',
|
||||
']': 'nextBookmarked',
|
||||
alt_B: 'browseActions: "/Bookmark/" -- Show bookmark menu',
|
||||
alt_B: 'browseActions: "/Bookmark/" -- Bookmark menu...',
|
||||
|
||||
|
||||
|
||||
@ -425,6 +427,9 @@ var KeyboardActions = actions.Actions({
|
||||
// for changes to take effect.
|
||||
// XXX EXPERIMENTAL
|
||||
'keyboard-key-pressed-action': 'off',
|
||||
|
||||
// XXX make this generic...
|
||||
'confirm-delete-timeout': 2000,
|
||||
},
|
||||
|
||||
get keybindings(){
|
||||
@ -717,11 +722,27 @@ var KeyboardActions = actions.Actions({
|
||||
|
||||
// Interface stuff ------------------------------------------------
|
||||
|
||||
// options format:
|
||||
// {
|
||||
// cls: 'edit',
|
||||
// show_non_actions: true,
|
||||
// empty_section_text: false,
|
||||
//
|
||||
// mode_buttons:
|
||||
// mode_actions:
|
||||
//
|
||||
// key_buttons:
|
||||
//
|
||||
// drop_buttons:
|
||||
//
|
||||
// }
|
||||
//
|
||||
// XXX BUG sections with doc do not show up in title...
|
||||
// XXX sub-group by path (???)
|
||||
// XXX place this in /Doc/.. (???)
|
||||
browseKeyboardBindings: ['Interface|Help/Keyboard bindings...',
|
||||
widgets.makeUIDialog(function(path, edit, get_text){
|
||||
widgets.makeUIDialog(function(path, options){
|
||||
options = options || {}
|
||||
|
||||
var actions = this
|
||||
var keybindings = this.keybindings
|
||||
var kb = this.keyboard
|
||||
@ -729,14 +750,13 @@ var KeyboardActions = actions.Actions({
|
||||
var keys = kb.keys('*')
|
||||
|
||||
// get doc...
|
||||
get_text = get_text === undefined && !edit ?
|
||||
function(action){
|
||||
var getKeyText = options.get_key_text
|
||||
|| function(action){
|
||||
var doc = action.doc ? action.doc
|
||||
: action.action in this ? this.getDocTitle(action.action)
|
||||
: action.action
|
||||
return doc.length == 0 ? action.action : doc
|
||||
}
|
||||
: get_text
|
||||
|
||||
var dialog = browse.makeLister(null,
|
||||
function(path, make){
|
||||
@ -744,16 +764,8 @@ var KeyboardActions = actions.Actions({
|
||||
.forEach(function(mode){
|
||||
var dropped = keybindings[mode].drop || []
|
||||
var bound_ignored = []
|
||||
var buttons = edit ?
|
||||
[
|
||||
// XXX up
|
||||
['⏶', function(){}],
|
||||
// XXX down
|
||||
['⏷', function(){}],
|
||||
].concat(dialog.options.itemButtons)
|
||||
: undefined
|
||||
|
||||
// section heading...
|
||||
// section heading (mode)...
|
||||
make(keybindings[mode].doc ?
|
||||
$('<span>')
|
||||
// NOTE: at this time adding a br
|
||||
@ -769,7 +781,7 @@ var KeyboardActions = actions.Actions({
|
||||
not_filtered_out: true,
|
||||
// XXX should sections be searchable???
|
||||
not_searchable: true,
|
||||
buttons: buttons,
|
||||
buttons: options.mode_buttons,
|
||||
})
|
||||
.attr('mode', mode)
|
||||
.addClass('mode')
|
||||
@ -780,9 +792,9 @@ var KeyboardActions = actions.Actions({
|
||||
|
||||
var o = keyboard.parseActionCall(action)
|
||||
|
||||
if(get_text){
|
||||
if(getKeyText){
|
||||
var doc = ''
|
||||
var text = get_text.call(actions, o)
|
||||
var text = getKeyText.call(actions, o)
|
||||
|
||||
} else {
|
||||
var doc = o.doc
|
||||
@ -792,10 +804,14 @@ var KeyboardActions = actions.Actions({
|
||||
(': '+ o.arguments.map(JSON.stringify).join(' '))
|
||||
: '')
|
||||
}
|
||||
var hidden = !edit
|
||||
&& !(o.action in actions)
|
||||
&& !(kb.handler(mode, keys[mode][action][0])
|
||||
instanceof Function)
|
||||
|
||||
var hidden = !options.show_non_actions
|
||||
// hide all non-actions...
|
||||
&& !(o.action in actions
|
||||
// except: functions represented by their doc...
|
||||
|| keybindings[mode][action] == null
|
||||
&& kb.handler(mode, keys[mode][action][0])
|
||||
instanceof Function)
|
||||
|
||||
// NOTE: wee need the button spec to be
|
||||
// searchable, thus we are not using
|
||||
@ -820,6 +836,8 @@ var KeyboardActions = actions.Actions({
|
||||
// hide stuff that is not an action...
|
||||
hidden: hidden,
|
||||
disabled: hidden,
|
||||
|
||||
buttons: options.key_buttons,
|
||||
})
|
||||
.attr({
|
||||
'mode': mode,
|
||||
@ -842,8 +860,8 @@ var KeyboardActions = actions.Actions({
|
||||
// no keys in view mode...
|
||||
// XXX is adding info stuff like this a correct
|
||||
// thing to do in code?
|
||||
c == 0 && !edit
|
||||
&& make('No bindings...',
|
||||
c == 0 && options.empty_section_text !== false
|
||||
&& make(options.empty_section_text || 'No bindings...',
|
||||
{
|
||||
disabled: true,
|
||||
hide_on_search: true,
|
||||
@ -860,30 +878,18 @@ var KeyboardActions = actions.Actions({
|
||||
dropped
|
||||
.filter(function(k){
|
||||
return bound_ignored.indexOf(k) == -1 })
|
||||
.join(' / ')])
|
||||
.join(' / ')],
|
||||
{
|
||||
buttons: options.drop_buttons,
|
||||
})
|
||||
.addClass('drop-list')
|
||||
.attr('mode', mode)
|
||||
|
||||
// controls...
|
||||
if(edit){
|
||||
if(options.mode_actions){
|
||||
var elem = make('new', {
|
||||
buttons: [
|
||||
// XXX
|
||||
['key',
|
||||
function(){
|
||||
//elem.before( XXX )
|
||||
actions.editKeyBinding(mode)
|
||||
// XXX update when done???
|
||||
}],
|
||||
// XXX
|
||||
['mode',
|
||||
function(){
|
||||
//elem.after( XXX )
|
||||
// XXX need to pass order info...
|
||||
actions.editKeyboardMode()
|
||||
// XXX update when done???
|
||||
}],
|
||||
]})
|
||||
buttons: options.mode_actions,
|
||||
})
|
||||
.addClass('new')
|
||||
}
|
||||
})
|
||||
@ -900,40 +906,13 @@ var KeyboardActions = actions.Actions({
|
||||
hide_on_search: true,
|
||||
})
|
||||
.addClass('info')
|
||||
}, {
|
||||
},
|
||||
{
|
||||
cls: [
|
||||
'key-bindings',
|
||||
'no-item-numbers',
|
||||
(edit ? 'edit' : 'browse'),
|
||||
options.cls,
|
||||
].join(' '),
|
||||
|
||||
itemButtons: edit ?
|
||||
[
|
||||
// NOTE: ordering within one section is purely
|
||||
// aesthetic and has no function...
|
||||
// XXX do wee actually need ordering???
|
||||
// XXX up
|
||||
//['⏶', function(){}],
|
||||
// XXX down
|
||||
//['⏷', function(){}],
|
||||
|
||||
// XXX edit -- launch the editor...
|
||||
// ...do we actually need this as a button????
|
||||
['⋯', function(_, cur){
|
||||
// key...
|
||||
if(cur.hasClass('key')){
|
||||
actions.editKeyBinding(cur.attr('mode'), cur.attr('code'))
|
||||
|
||||
// mode...
|
||||
} else if(cur.hasClass('mode')){
|
||||
actions.editKeyboardMode(cur.attr('mode'))
|
||||
}
|
||||
}],
|
||||
//*/
|
||||
//['edit', function(){}],
|
||||
//['🖉', function(){}],
|
||||
]
|
||||
: [],
|
||||
})
|
||||
|
||||
return dialog
|
||||
@ -942,24 +921,77 @@ var KeyboardActions = actions.Actions({
|
||||
editKeyboardBindings: ['Interface/Keyboard bindings editor...',
|
||||
widgets.uiDialog(function(path){
|
||||
var that = this
|
||||
var dialog = this.browseKeyboardBindings(path, true)
|
||||
var dialog = this.browseKeyboardBindings(
|
||||
path,
|
||||
{
|
||||
cls: 'edit',
|
||||
show_non_actions: true,
|
||||
empty_section_text: false,
|
||||
|
||||
// mode...
|
||||
mode_buttons: [
|
||||
// XXX up
|
||||
['⏶', function(_, cur){
|
||||
}],
|
||||
// XXX down
|
||||
['⏷', function(_, cur){
|
||||
}],
|
||||
['⋯', function(_, cur){
|
||||
that.editKeyboardMode(cur.attr('mode'))
|
||||
.close(function(){ dialog.update() }) }],
|
||||
],
|
||||
mode_actions: [
|
||||
['key', function(_, cur){
|
||||
//elem.before( XXX )
|
||||
that.editKeyBinding(cur.attr('mode'))
|
||||
.close(function(){ dialog.update() }) }],
|
||||
['mode', function(_, cur){
|
||||
//elem.after( XXX )
|
||||
// XXX need to pass order info...
|
||||
that.editKeyboardMode()
|
||||
.close(function(){ dialog.update() }) }],
|
||||
],
|
||||
|
||||
// keys...
|
||||
key_buttons: [
|
||||
['⋯', function(_, cur){
|
||||
that.editKeyBinding(cur.attr('mode'), cur.attr('code'))
|
||||
.close(function(){ dialog.update() }) }],
|
||||
],
|
||||
|
||||
// dropped key list...
|
||||
drop_buttons: [
|
||||
['⋯', function(_, cur){
|
||||
that.editKeyboardModeDroppedKeys(cur.attr('mode'))
|
||||
.close(function(){ dialog.update() }) }],
|
||||
],
|
||||
})
|
||||
// XXX should this be only a button thing (done in .browseKeyboardBindings(..))
|
||||
// or also the main action???
|
||||
.open(function(){
|
||||
var cur = dialog.select('!')
|
||||
var sub_dialog
|
||||
|
||||
// key...
|
||||
if(cur.hasClass('key')){
|
||||
that.editKeyBinding(cur.attr('mode'), cur.attr('code'))
|
||||
sub_dialog = that
|
||||
.editKeyBinding(cur.attr('mode'), cur.attr('code'))
|
||||
|
||||
// mode...
|
||||
// XXX BUG: for some reason modes are unclickable...
|
||||
} else if(cur.hasClass('mode')){
|
||||
that.editKeyboardMode(cur.attr('mode'))
|
||||
sub_dialog = that
|
||||
.editKeyboardMode(cur.attr('mode'))
|
||||
|
||||
// dropped...
|
||||
} else if(cur.hasClass('drop-list')){
|
||||
that.editKeyboardModeDroppedKeys(cur.attr('mode'))
|
||||
sub_dialog = that
|
||||
.editKeyboardModeDroppedKeys(cur.attr('mode'))
|
||||
}
|
||||
|
||||
sub_dialog
|
||||
&& sub_dialog
|
||||
.close(function(){ dialog.update() })
|
||||
})
|
||||
return dialog
|
||||
})],
|
||||
@ -970,8 +1002,8 @@ var KeyboardActions = actions.Actions({
|
||||
// ---
|
||||
// <list of keys>
|
||||
// new key
|
||||
// XXX
|
||||
editKeyBinding: ['- Interface/Key binding editor...',
|
||||
// XXX need a way to abort edits...
|
||||
editKeyBinding: ['- Interface/Key mapping...',
|
||||
widgets.makeUIDialog(function(mode, code){
|
||||
var that = this
|
||||
// XXX
|
||||
@ -990,81 +1022,87 @@ var KeyboardActions = actions.Actions({
|
||||
keys[mode][code]
|
||||
: []
|
||||
|
||||
var to_remove = []
|
||||
keys
|
||||
.forEach(function(key){
|
||||
// XXX make editable...
|
||||
make(key, { buttons: [
|
||||
['×', function(){}],
|
||||
widgets.makeRemoveItemButton(to_remove),
|
||||
], })
|
||||
})
|
||||
|
||||
make('New key')
|
||||
// XXX stub...
|
||||
.css({ fontStyle: 'italic' })
|
||||
var new_button = make('New key')
|
||||
.addClass('action')
|
||||
.on('open', function(){
|
||||
widgets.editItem(dialog, new_button)
|
||||
})
|
||||
|
||||
make('---')
|
||||
|
||||
make('', { buttons: [
|
||||
['Delete mapping', function(){}],
|
||||
], })
|
||||
widgets.makeConfirmActionItem(make('Delete'),
|
||||
function(){
|
||||
// XXX
|
||||
dialog.close()
|
||||
}, that.config['confirm-delete-timeout'] || 2000)
|
||||
},
|
||||
{
|
||||
cls: 'metadata-view',
|
||||
})
|
||||
|
||||
return dialog
|
||||
})],
|
||||
// XXX
|
||||
editKeyboardMode: ['- Interface/keyboard mode editor...',
|
||||
widgets.makeUIDialog(function(mode){
|
||||
var that = this
|
||||
var dialog = browse.makeLister(null,
|
||||
function(path, make){
|
||||
make(['Mode:', mode || ''])
|
||||
make(['Doc:', that.keybindings[mode].doc || ''])
|
||||
make(['Pattern:', that.keybindings[mode].pattern || mode])
|
||||
|
||||
make('---')
|
||||
|
||||
make('', { buttons: [
|
||||
['Delete mode', function(){}],
|
||||
], })
|
||||
})
|
||||
|
||||
return dialog
|
||||
})],
|
||||
// XXX
|
||||
editKeyboardModeDroppedKeys: ['- Interface/keyboard mode dropped key editor...',
|
||||
// XXX make fields editable...
|
||||
// XXX need a way to abort edits...
|
||||
editKeyboardMode: ['- Interface/Mode...',
|
||||
widgets.makeUIDialog(function(mode){
|
||||
var that = this
|
||||
|
||||
var dialog = browse.makeLister(null,
|
||||
function(path, make){
|
||||
// XXX make these editable....
|
||||
make(['Mode:', mode || ''])
|
||||
make(['Doc:', (that.keybindings[mode] || {}).doc || ''])
|
||||
make(['Pattern:', (that.keybindings[mode] || {}).pattern || mode])
|
||||
|
||||
make('---')
|
||||
|
||||
var drop = that.keybindings[mode].drop || []
|
||||
drop = drop == '*' ? [drop] : drop
|
||||
|
||||
drop
|
||||
.forEach(function(key){
|
||||
// XXX make editable...
|
||||
make(key, { buttons: [
|
||||
['×', function(){}],
|
||||
], })
|
||||
})
|
||||
|
||||
make('New key')
|
||||
// XXX stub...
|
||||
.css({ fontStyle: 'italic' })
|
||||
|
||||
make('---')
|
||||
|
||||
make('', { buttons: [
|
||||
['Clear dropped keys', function(){}],
|
||||
], })
|
||||
widgets.makeConfirmActionItem(make('Delete'),
|
||||
function(){
|
||||
if(mode in that.keybindings){
|
||||
delete that.keybindings[mode]
|
||||
}
|
||||
dialog.close()
|
||||
}, that.config['confirm-delete-timeout'] || 2000)
|
||||
},
|
||||
{
|
||||
cls: 'metadata-view',
|
||||
})
|
||||
|
||||
return dialog
|
||||
})],
|
||||
// XXX need a way to abort edits...
|
||||
// XXX need a way to set a special '*' key...
|
||||
editKeyboardModeDroppedKeys: ['- Interface/Dropped keys...',
|
||||
widgets.makeUIDialog(function(mode){
|
||||
var that = this
|
||||
|
||||
// XXX need a way to set a special '*' key...
|
||||
var dialog = widgets.makeListEditor(function(keys){
|
||||
// get...
|
||||
if(keys === undefined){
|
||||
return that.keybindings[mode].drop || []
|
||||
|
||||
// set...
|
||||
} else {
|
||||
that.keybindings[mode].drop = keys
|
||||
}
|
||||
},
|
||||
{
|
||||
unique: true,
|
||||
})
|
||||
|
||||
return dialog
|
||||
})],
|
||||
|
||||
|
||||
// XXX move to gen2
|
||||
|
||||
@ -148,15 +148,15 @@ var SlideshowActions = actions.Actions({
|
||||
o.parent.close()
|
||||
})
|
||||
.addClass('selected')
|
||||
},
|
||||
{
|
||||
cls: 'metadata-view tail-action',
|
||||
})
|
||||
.on('close', function(){
|
||||
// reset the timer if it was not suspended outside...
|
||||
suspended_timer || that.resetSlideshowTimer()
|
||||
})
|
||||
|
||||
o.dom
|
||||
.addClass('metadata-view tail-action')
|
||||
|
||||
return o
|
||||
})],
|
||||
|
||||
|
||||
@ -144,24 +144,92 @@ function(cls, cfg, parent){
|
||||
// XXX make the selector more accurate...
|
||||
// ...at this point this will select the first elem with text which
|
||||
// can be a different elem...
|
||||
var makeEditableItem =
|
||||
module.makeEditableItem =
|
||||
function(list, item, elem, callback, options){
|
||||
var editItem =
|
||||
module.editItem =
|
||||
function(list, elem, callback, options){
|
||||
return elem
|
||||
.makeEditable({
|
||||
activate: true,
|
||||
})
|
||||
.makeEditable(options
|
||||
|| {
|
||||
activate: true,
|
||||
clear_on_edit: true,
|
||||
blur_on_abort: false,
|
||||
blur_on_commit: false,
|
||||
})
|
||||
.on('edit-done', callback || function(){})
|
||||
.on('edit-aborted edit-done', function(_, text){
|
||||
list.update()
|
||||
// XXX make the selector more accurate...
|
||||
// ...at this point this will select the first elem
|
||||
// with text which can be a different elem...
|
||||
.then(function(){ list.select(item.text()) })
|
||||
.then(function(){ list.select(elem.text()) })
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
var makeRemoveItemButton =
|
||||
module.makeRemoveItemButton =
|
||||
function makeRemoveItemButton(list, html){
|
||||
return [html || '×',
|
||||
function(p, e){
|
||||
e.toggleClass('strike-out')
|
||||
|
||||
if(e.hasClass('strike-out')){
|
||||
list.indexOf(p) < 0
|
||||
&& list.push(p)
|
||||
|
||||
} else {
|
||||
var i = list.indexOf(p)
|
||||
if(i >= 0){
|
||||
list.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
var makeConfirmActionItem =
|
||||
module.makeConfirmActionItem =
|
||||
function makeConfirmActionItem(elem, callback, timeout, confirm_text){
|
||||
confirm_text = confirm_text ?
|
||||
confirm_text
|
||||
: 'Confirm '+ elem.text().toLowerCase() +'?'
|
||||
var text
|
||||
|
||||
return elem
|
||||
.addClass('action')
|
||||
.on('open', function(){
|
||||
var item = $(this)
|
||||
var elem = item.find('.text')
|
||||
|
||||
// ready to delete...
|
||||
if(elem.text() != confirm_text){
|
||||
text = elem.text()
|
||||
|
||||
elem.text(confirm_text)
|
||||
|
||||
item.addClass('warn')
|
||||
|
||||
// reset...
|
||||
setTimeout(function(){
|
||||
elem.text(text)
|
||||
|
||||
item.removeClass('warn')
|
||||
}, timeout || 2000)
|
||||
|
||||
// confirmed...
|
||||
} else {
|
||||
callback && callback()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
var makeNewEditableItem =
|
||||
module.makeNewEditableItem =
|
||||
function makeNewEditableItem(elem){
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Options format:
|
||||
// {
|
||||
@ -190,15 +258,15 @@ function(list, item, elem, callback, options){
|
||||
// }
|
||||
//
|
||||
// XXX add sort buttons: up/down/top/bottom...
|
||||
// XXX make this more generic...
|
||||
// XXX currently using this also requires the use of makeUIDialog(..),
|
||||
// can this be simpler???
|
||||
var makeConfigListEditor =
|
||||
module.makeConfigListEditor =
|
||||
function(actions, list_key, options){
|
||||
// XXX this is generic, move to browse...
|
||||
var makeListEditor =
|
||||
module.makeListEditor =
|
||||
function(list, options){
|
||||
options = options || {}
|
||||
|
||||
var new_button = options.new_button
|
||||
var new_button = options.new_button || true
|
||||
new_button = new_button === true ? 'New...' : new_button
|
||||
|
||||
var _makeEditable = function(elem){
|
||||
@ -210,15 +278,15 @@ function(actions, list_key, options){
|
||||
blur_on_commit: false,
|
||||
})
|
||||
.on('edit-aborted', function(){
|
||||
list.select(null)
|
||||
list.update()
|
||||
dialog.select(null)
|
||||
dialog.update()
|
||||
})
|
||||
.on('edit-done', function(evt, text){
|
||||
var txt = $(this).text()
|
||||
|
||||
// invalid format...
|
||||
if(options.check && !options.check(txt)){
|
||||
list.update()
|
||||
dialog.update()
|
||||
return
|
||||
}
|
||||
|
||||
@ -226,83 +294,76 @@ function(actions, list_key, options){
|
||||
if(options.length_limit
|
||||
&& (lst.length >= options.length_limit)){
|
||||
|
||||
options.callback && options.callback.call(list, txt)
|
||||
options.callback && options.callback.call(dialog, txt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// prevent editing non-arrays...
|
||||
if(!(actions.config[list_key] instanceof Array)){
|
||||
if(!editable || !lst){
|
||||
return
|
||||
}
|
||||
|
||||
// save the new version...
|
||||
actions.config[list_key] = actions.config[list_key].slice()
|
||||
// add new value and sort list...
|
||||
actions.config[list_key]
|
||||
.push(txt)
|
||||
lst.push(txt)
|
||||
|
||||
// unique...
|
||||
if(options.unique == null || options.unique === true){
|
||||
actions.config[list_key] = actions.config[list_key]
|
||||
.unique()
|
||||
lst = lst.unique()
|
||||
|
||||
// unique normalized...
|
||||
} else if( typeof(options.unique) == typeof(function(){})){
|
||||
actions.config[list_key] = actions.config[list_key]
|
||||
.unique(options.unique)
|
||||
} else if(typeof(options.unique) == typeof(function(){})){
|
||||
lst = lst.unique(options.unique)
|
||||
}
|
||||
|
||||
// sort...
|
||||
if(options.sort){
|
||||
actions.config[list_key] = actions.config[list_key]
|
||||
lst = lst
|
||||
.sort(typeof(options.sort) == typeof(function(){}) ?
|
||||
options.sort
|
||||
: undefined)
|
||||
}
|
||||
|
||||
_write(lst)
|
||||
|
||||
// update the list data...
|
||||
list.options.data
|
||||
= actions.config[list_key]
|
||||
.concat(new_button ? [ new_button ] : [])
|
||||
dialog.options.data = lst.concat(new_button ? [ new_button ] : [])
|
||||
|
||||
// update list and select new value...
|
||||
list.update()
|
||||
dialog.update()
|
||||
.done(function(){
|
||||
list.select('"'+txt+'"')
|
||||
dialog.select('"'+txt+'"')
|
||||
})
|
||||
})
|
||||
}
|
||||
var _write = function(lst){
|
||||
// write back the list...
|
||||
return list instanceof Function ?
|
||||
// call the writer...
|
||||
list(lst)
|
||||
// in-place replace list elements...
|
||||
// NOTE: this is necessary as not everything we do with lst
|
||||
// is in-place...
|
||||
: list.splice.apply(list, [0, list.length].concat(lst))
|
||||
}
|
||||
|
||||
var to_remove = []
|
||||
|
||||
var lst = list_key instanceof Function ? list_key()
|
||||
: list_key instanceof Array ? list_key
|
||||
: actions.config[list_key]
|
||||
lst = lst instanceof Array ? lst : Object.keys(lst)
|
||||
var lst = list instanceof Function ?
|
||||
list()
|
||||
: list
|
||||
var editable = lst instanceof Array
|
||||
|
||||
var list = browse.makeList(null,
|
||||
// view objects...
|
||||
lst = !editable ? Object.keys(lst) : lst.slice()
|
||||
|
||||
var dialog = browse.makeList(null,
|
||||
lst.concat(new_button ? [ new_button ] : []),
|
||||
{
|
||||
path: options.path,
|
||||
itemButtons: options.itemButtons || [
|
||||
// mark for removal...
|
||||
['×',
|
||||
function(p){
|
||||
var e = this.filter('"'+p+'"', false)
|
||||
.toggleClass('strike-out')
|
||||
|
||||
if(e.hasClass('strike-out')){
|
||||
to_remove.indexOf(p) < 0
|
||||
&& to_remove.push(p)
|
||||
|
||||
} else {
|
||||
var i = to_remove.indexOf(p)
|
||||
if(i >= 0){
|
||||
to_remove.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}],
|
||||
makeRemoveItemButton(to_remove)
|
||||
// XXX add shift up/down/top/bottom and other buttons (optional)...
|
||||
]
|
||||
})
|
||||
@ -315,43 +376,71 @@ function(actions, list_key, options){
|
||||
// restore striked-out items...
|
||||
.on('update', function(){
|
||||
to_remove.forEach(function(e){
|
||||
list.filter('"'+ e +'"')
|
||||
dialog.filter('"'+ e +'"')
|
||||
.toggleClass('strike-out')
|
||||
})
|
||||
})
|
||||
.open(function(evt, path){
|
||||
// we clicked the 'New' button -- select it...
|
||||
if(new_button && (path == new_button || path == '')){
|
||||
list.select(new_button)
|
||||
dialog.select(new_button)
|
||||
|
||||
} else {
|
||||
options.callback && options.callback.call(list, path)
|
||||
options.callback && options.callback.call(dialog, path)
|
||||
}
|
||||
})
|
||||
.on('close', function(){
|
||||
// prevent editing non-arrays...
|
||||
if(!(actions.config[list_key] instanceof Array)){
|
||||
if(!editable){
|
||||
return
|
||||
}
|
||||
|
||||
// remove striked items...
|
||||
to_remove.forEach(function(e){
|
||||
var lst = actions.config[list_key].slice()
|
||||
lst.splice(lst.indexOf(e), 1)
|
||||
|
||||
actions.config[list_key] = lst
|
||||
_write(lst)
|
||||
})
|
||||
|
||||
// sort...
|
||||
if(options.sort){
|
||||
actions.config[list_key] = actions.config[list_key]
|
||||
.sort(options.sort !== true ? options.sort : undefined)
|
||||
lst.sort(options.sort !== true ? options.sort : undefined)
|
||||
|
||||
_write(lst)
|
||||
}
|
||||
})
|
||||
|
||||
new_button && list.dom.addClass('tail-action')
|
||||
// XXX
|
||||
new_button && dialog.dom.addClass('tail-action')
|
||||
|
||||
return list
|
||||
return dialog
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
var makeConfigListEditor =
|
||||
module.makeConfigListEditor =
|
||||
function(actions, path, options){
|
||||
path = path.split('.')
|
||||
var key = path.pop()
|
||||
|
||||
return makeListEditor(function(lst){
|
||||
var target = actions.config
|
||||
path.forEach(function(p){
|
||||
target = target[p] = target[p] || {}
|
||||
})
|
||||
|
||||
// get...
|
||||
if(lst === undefined){
|
||||
return target[key]
|
||||
|
||||
// set...
|
||||
} else {
|
||||
target[key] = lst
|
||||
}
|
||||
}, options)
|
||||
}
|
||||
|
||||
|
||||
@ -372,7 +461,7 @@ function(actions, list, list_key, value_key, options){
|
||||
// NOTE: this is called when adding a new value and
|
||||
// list maximum length is reached...
|
||||
callback: function(value){
|
||||
if(typeof(value_key) == typeof(function(){})){
|
||||
if(value_key instanceof Function){
|
||||
value_key(value)
|
||||
} else {
|
||||
actions.config[value_key] = value
|
||||
@ -392,7 +481,7 @@ function(actions, list, list_key, value_key, options){
|
||||
})
|
||||
// select default...
|
||||
o.on('update', function(){
|
||||
if(typeof(value_key) == typeof(function(){})){
|
||||
if(value_key instanceof Function){
|
||||
o.select(value_key())
|
||||
|
||||
} else {
|
||||
|
||||
@ -1131,6 +1131,7 @@ var BrowserPrototype = {
|
||||
|
||||
// custom buttons...
|
||||
buttons && buttons
|
||||
.slice()
|
||||
// make the order consistent for the user -- first
|
||||
// in list, first in item (from left), and should
|
||||
// be added last...
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user