started making editor components modular and generic...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2016-04-17 00:58:21 +03:00
parent 261a8690f4
commit b5011ffaa5
3 changed files with 197 additions and 82 deletions

View File

@ -1168,6 +1168,31 @@ var FileSystemWriterUIActions = actions.Actions({
// Export dialog...
//
// Export <mode> is set by:
// .config['export-mode']
//
// The fields used and their order is determined by:
// .config['export-modes'][<mode>].data (list)
//
// The action used to export is determined by:
// .config['export-modes'][<mode>].action
//
//
// Dialog fields...
//
// Format:
// {
// // Arguments:
// // actions - the actions object
// // make - browse item constructor
// // (see: browse.Browser.update(..) for more info)
// // overlay - the containing overlay object
// <key>: function(actions, make, overlay){ ... },
// ...
// }
//
// NOTE: .__export_dialog_fields__ can be defined both in the feature
// as well as in the instance.
__export_dialog_fields__: {
'pattern': function(actions, make, overlay){
return make(['Filename pattern: ',
@ -1201,7 +1226,7 @@ var FileSystemWriterUIActions = actions.Actions({
// XXX make this editable on open and remove "new" from history...
// XXX add "history" button...
'target_dir': function(actions, make, overlay){
return make(['To: ',
var elem = make(['To: ',
function(){ return actions.config['export-path'] || './' }],
{ buttons: [
['browse', function(p){
@ -1232,14 +1257,28 @@ var FileSystemWriterUIActions = actions.Actions({
})],
]})
// XXX make this editable???
.on('open',
widgets.makeNestedConfigListEditor(actions, overlay,
'export-paths',
'export-path',
{
// XXX add 'edit' button...
//itemButtons: []
}))
.on('open', function(){
event.preventDefault()
var path = elem.find('.text').last()
.makeEditable({
clear_on_edit: false,
abort_keys: [
'Esc',
],
})
.on('edit-done', function(_, path){
actions.config['export-path'] = path
actions.config['export-paths'].splice(0, 0, path)
})
.on('edit-aborted edit-done', function(evt, path){
overlay.client.update()
.then(function(){
overlay.client.select(path)
})
})
})
}
},
// XXX indicate export state: index, crop, image...
@ -1280,9 +1319,10 @@ var FileSystemWriterUIActions = actions.Actions({
// XXX indicate export state: index, crop, image...
return 'Export'}])
.on('open', function(){
var mode = that.config['export-dialog-modes'][that.config['export-dialog-mode']]
// XXX is this correct???
// XXX handle relative paths!!!
that[that.config['export-mode'].action](
that[mode.action](
that.config['export-path'] || that.location.path)
o.close()
})

View File

@ -69,79 +69,67 @@ function(actions, list_key, options){
new_button = new_button === true ? 'New...' : new_button
var _makeEditable = function(elem){
$(elem).find('.text')
.prop('contenteditable', true)
.text('')
.selectText()
.keydown(function(){
event.stopPropagation()
var n = keyboard.toKeyName(event.keyCode)
// reset to original value...
if(n == 'Esc'){
list.update()
// save value...
} else if(n == 'Enter'){
event.preventDefault()
var txt = $(this).text()
// invalid format...
if(options.check && !options.check(txt)){
list.update()
return
}
// list length limit
if(options.length_limit
&& (lst.length >= options.length_limit)){
options.callback && options.callback.call(list, txt)
return
}
// prevent editing non-arrays...
if(!(actions.config[list_key] instanceof Array)){
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)
// unique...
if(options.unique == null || options.unique){
actions.config[list_key] = actions.config[list_key]
.unique(typeof(options.unique) == typeof(function(){}) ?
options.unique
: undefined)
}
// sort...
if(options.sort){
actions.config[list_key] = actions.config[list_key]
.sort(typeof(options.sort) == typeof(function(){}) ?
options.sort
: undefined)
}
// update the list data...
list.options.data
= actions.config[list_key]
.concat(new_button ? [ new_button ] : [])
// update list and select new value...
list.update()
.done(function(){
list.select('"'+txt+'"')
})
}
return $(elem).find('.text')
.makeEditable()
.on('edit-aborted', function(){
list.update()
})
.on('edit-done', function(evt, text){
var txt = $(this).text()
// invalid format...
if(options.check && !options.check(txt)){
list.update()
return
}
// list length limit
if(options.length_limit
&& (lst.length >= options.length_limit)){
options.callback && options.callback.call(list, txt)
return
}
// prevent editing non-arrays...
if(!(actions.config[list_key] instanceof Array)){
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)
// unique...
if(options.unique == null || options.unique){
actions.config[list_key] = actions.config[list_key]
.unique(typeof(options.unique) == typeof(function(){}) ?
options.unique
: undefined)
}
// sort...
if(options.sort){
actions.config[list_key] = actions.config[list_key]
.sort(typeof(options.sort) == typeof(function(){}) ?
options.sort
: undefined)
}
// update the list data...
list.options.data
= actions.config[list_key]
.concat(new_button ? [ new_button ] : [])
// update list and select new value...
list.update()
.done(function(){
list.select('"'+txt+'"')
})
})
return $(elem)
}
var to_remove = []
@ -177,6 +165,13 @@ function(actions, list_key, options){
_makeEditable(elem)
}
})
// restore striked-out items...
.on('update', function(){
to_remove.forEach(function(e){
list.filter('"'+ e +'"')
.toggleClass('strike-out')
})
})
.open(function(evt, path){
// we clicked the 'New' button -- select it...
if(new_button && (path == new_button || path == '')){

View File

@ -9,6 +9,7 @@ define(function(require){ var module = {}
//var DEBUG = DEBUG != null ? DEBUG : true
/*********************************************************************/
String.prototype.capitalize = function(){
@ -220,6 +221,7 @@ if(typeof(jQuery) != typeof(undefined)){
})
}
jQuery.fn.selectText = function(){
var range = document.createRange()
@ -235,6 +237,84 @@ if(typeof(jQuery) != typeof(undefined)){
}
var keyboard = require('lib/keyboard')
// Make element editable...
//
// Options format:
// {
// multiline: false,
//
// reset_on_abort: true,
// clear_on_edit: true,
//
// abort_keys: [
// 'Esc',
// ...
// ],
// }
//
// XXX should we just use form elements???
// ...it's a trade-off, here we add editing functionality and fight
// a bit the original function, in an input we'll need to fight part
// of the editing functionality and add our own navigation...
// XXX move this to a more generic spot...
jQuery.fn.makeEditable = function(options){
options = options || {}
var that = this
var original = this.text()
if(options.clear_on_edit == null || options.clear_on_edit){
this.text('')
}
this
.prop('contenteditable', true)
// make the element focusable and selectable...
.attr('tabindex', '0')
// NOTE: this will also focus the element...
.selectText()
.keydown(function(){
if(!that.prop('contenteditable')){
return
}
event.stopPropagation()
var n = keyboard.toKeyName(event.keyCode)
// abort...
if((options.abort_keys || ['Esc']).indexOf(n) >= 0){
// reset original value...
(options.reset_on_abort == null || options.reset_on_abort)
&& that.text(original)
that
.trigger('edit-aborted', original)
// done -- single line...
} else if(n == 'Enter'
&& !options.multiline){
event.preventDefault()
that.trigger('edit-done', that.text())
// done -- multiline...
} else if(n == 'Enter'
&& (event.ctrlKey || event.metaKey)
&& options.multiline){
event.preventDefault()
that.trigger('edit-done', that.text())
}
})
return this
}
}