diff --git a/ui (gen4)/features/keyboard.js b/ui (gen4)/features/keyboard.js index 554c7955..a1da8808 100755 --- a/ui (gen4)/features/keyboard.js +++ b/ui (gen4)/features/keyboard.js @@ -1202,7 +1202,10 @@ var KeyboardActions = actions.Actions({ } }, { - unique: true + unique: true, + + normalize: keyboard.normalizeKey, + check: keyboard.isKey, }) make.Separator() diff --git a/ui (gen4)/lib/keyboard.js b/ui (gen4)/lib/keyboard.js index 113bed6f..ec038e5b 100755 --- a/ui (gen4)/lib/keyboard.js +++ b/ui (gen4)/lib/keyboard.js @@ -103,6 +103,12 @@ for(var k in SPECIAL_KEYS){ } +var SPECIAL_KEYS_DICT = {} +for(var k in SPECIAL_KEYS){ + SPECIAL_KEYS_DICT[SPECIAL_KEYS[k].toLowerCase()] = SPECIAL_KEYS[k] +} + + /*********************************************************************/ @@ -216,6 +222,9 @@ function code2key(code){ var isKey = module.isKey = function isKey(key){ + if(!key || key.length == 0 || key.trim() == ''){ + return false + } var modifiers = MODIFIERS var mod = normalizeKey(splitKey(key)) @@ -279,6 +288,14 @@ function normalizeKey(key){ var k = key.pop() k = parseInt(k) ? code2key(parseInt(k)) : k + + if(!k){ + return k + } + + // get the propper name... + k = SPECIAL_KEYS_DICT[k.toLowerCase()] || k + k = modifiers.indexOf(k.toLowerCase()) >= 0 ? k.toLowerCase() : k.capitalize() @@ -758,7 +775,8 @@ var KeyboardPrototype = { // if key in .drop then ignore the rest... if(drop // explicit go to next section... - && handler != 'NEXT' + && (!handler + || handler.slice(0, 4) != 'NEXT') && (bindings.drop == '*' // XXX should this be more flexible by adding a // specific key combo? diff --git a/ui (gen4)/lib/util.js b/ui (gen4)/lib/util.js index de71f948..9c047570 100755 --- a/ui (gen4)/lib/util.js +++ b/ui (gen4)/lib/util.js @@ -383,6 +383,11 @@ if(typeof(jQuery) != typeof(undefined)){ // blur_on_abort: false, // blur_on_commit: false, // + // // restore focus before disabling the editor... + // keep_focus_on_parent: true, + // + // stop_propagation: false, + // // // clear selection on abort/commit... // clear_selection_on_abort: true, // clear_selection_on_commit: true, @@ -399,6 +404,10 @@ if(typeof(jQuery) != typeof(undefined)){ // 'abort' - will reset field and trigger 'edit-aborted' // with original (before edit started) field text // + // + // NOTE: removing tabindex will reset focus, so this will attempt to + // focus the first [tabindex] element up the tree... + // // 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 @@ -407,15 +416,24 @@ if(typeof(jQuery) != typeof(undefined)){ // XXX should this reset field to it's original state after // commit/abort??? jQuery.fn.makeEditable = function(options){ + var that = this + if(options == false){ this - .prop('contenteditable', false) + .removeProp('contenteditable') + .removeProp('tabindex') + .removeClass('editable-field') + + var events = this.data('editable-field-events') + for(var e in events){ + this.off(e, events[e]) + } + this.removeData('editable-field-events') return this } options = options || {} - var that = this var original = this.text() @@ -430,11 +448,12 @@ if(typeof(jQuery) != typeof(undefined)){ // do not setup handlers more than once... if(!this.hasClass('editable-field')){ + var events = {} this // make the element focusable and selectable... .attr('tabindex', '0') .addClass('editable-field') - .keydown(function(){ + .keydown(events.keydown = function(evt){ if(!that.prop('contenteditable')){ return } @@ -445,10 +464,6 @@ if(typeof(jQuery) != typeof(undefined)){ // 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('abort') // done -- single line... @@ -465,12 +480,16 @@ if(typeof(jQuery) != typeof(undefined)){ event.preventDefault() that.trigger('commit') + + // continue handling... + } else { + $(this).parent().trigger(evt) } }) - .blur(function(){ + .blur(events.blur = function(){ window.getSelection().removeAllRanges() }) - .on('focus click', function(evt){ + .on('focus click', events['focus click'] = function(evt){ evt.stopPropagation() options.clear_on_edit && $(this) @@ -478,22 +497,46 @@ if(typeof(jQuery) != typeof(undefined)){ .selectText() }) // user triggerable events... - .on('abort', function(){ + .on('abort', events.abort = function(){ that.trigger('edit-aborted', original) options.clear_selection_on_abort !== false && window.getSelection().removeAllRanges() - options.blur_on_abort !== false && this.blur() + // reset original value... + options.reset_on_abort !== false + && that.text(original) + + options.blur_on_abort !== false + && this.blur() + + // restore focus on parent... + options.keep_focus_on_parent !== false + && that.parents('[tabindex]').first().focus() + + that.makeEditable(false) }) - .on('commit', function(){ + .on('commit', events.commit = function(){ that.trigger('edit-done', that.text()) options.clear_selection_on_commit !== false && window.getSelection().removeAllRanges() - options.blur_on_commit !== false && this.blur() + // reset original value... + options.reset_on_commit !== false + && that.text(original) + + options.blur_on_commit !== false + && this.blur() + + // restore focus on parent... + options.keep_focus_on_parent !== false + && that.parents('[tabindex]').first().focus() + + that.makeEditable(false) }) + + this.data('editable-field-events', events) } return this diff --git a/ui (gen4)/lib/widget/browse.js b/ui (gen4)/lib/widget/browse.js index c59257ed..f176d86c 100755 --- a/ui (gen4)/lib/widget/browse.js +++ b/ui (gen4)/lib/widget/browse.js @@ -152,9 +152,10 @@ Items.Editable = function(text, options){ options = options || {} var dialog = this.dialog + var editable var elem = (options.action ? this.Action : this).call(this, text, options) .on('select', function(){ - var editable = elem.find('.text') + editable = elem.find('.text') .makeEditable({ activate: true, clear_on_edit: options.clear_on_edit, @@ -164,7 +165,6 @@ function(text, options){ // deselect on abort... .on('edit-aborted', function(){ dialog.select(null) - dialog.update() }) options.editaborted @@ -172,6 +172,9 @@ function(text, options){ options.editdone && editable.on('edit-done', options.editdone) }) + .on('deselect', function(){ + editable.trigger('abort') + }) return elem } @@ -223,10 +226,12 @@ function(list, options){ // // check input value... // check: function(value){ ... }, // +// normalize: function(value){ ... }, +// // // if true only unique values will be stored... // // if a function this will be used to normalize the values before // // uniqueness check is performed... -// unique: |function(value){ ... }, +// unique: | function(value){ ... }, // // // if true sort values... // // if function will be used as cmp for sorting... @@ -266,7 +271,7 @@ function(list, options){ || lst } - var to_remove = [] + var to_remove = options.to_remove = options.to_remove || [] // make a copy of options, to keep it safe from changes we are going // to make... @@ -313,6 +318,10 @@ function(list, options){ .on('edit-done', function(evt, text){ var txt = $(this).text() + txt = options.normalize ? + options.normalize(txt) + : txt + // invalid format... if(options.check && !options.check(txt)){ dialog.update() @@ -748,7 +757,6 @@ var BrowserPrototype = { // keep text editing action from affecting the selection... drop: '*', - // XXX this does not seem to work... Up: 'NEXT!', Down: 'NEXT!', Tab: 'NEXT!', @@ -2117,6 +2125,7 @@ var BrowserPrototype = { elems = elems .filter('.selected') .removeClass('selected') + .trigger('deselect') this.trigger('deselect', elems) return $() }