diff --git a/client/src/annotator_ui.js b/client/src/annotator_ui.js index 43d5bbb49..478bd1ffd 100644 --- a/client/src/annotator_ui.js +++ b/client/src/annotator_ui.js @@ -165,9 +165,18 @@ var AnnotatorUI = (function($, window, undefined) { var binding = keymap[prefix + code]; if (!binding) binding = keymap[prefix + String.fromCharCode(code)]; if (binding) { + var isAutocomplete = function(htmlNode) { + return htmlNode.nodeName === 'input' && typeof htmlNode.autocomplete !== 'undefined'; + }; var boundInput = $('#' + binding)[0]; if (boundInput && !boundInput.disabled) { - boundInput.click(); + if (boundInput.nodeName === 'select' && isAutocomplete(boundInput.nextSibling)) { + // special case for autocomplete cells for multi-valued attributes + // (this is maybe a slightly fragile way to go about this) + boundInput.nextSibling.focus(); + } else { + boundInput.click(); + } evt.preventDefault(); return false; } @@ -1909,6 +1918,22 @@ var AnnotatorUI = (function($, window, undefined) { addSpanTypesToDivInner($scroller, types); }; var addAttributeTypesToDiv = function($top, types, category) { + + var highlightHotkey = function(origName, hotkey, prefix, suffix) { + var replace = true; + return origName.replace(new RegExp("(&[^;]*?)?(" + hotkey + ")", 'gi'), + function(all, entity, letter) { + if (replace && !entity) { + replace = false; + var hotkeyMatch = hotkey.toLowerCase() == letter + ? hotkey.toLowerCase() + : hotkey.toUpperCase(); + return prefix + Util.escapeHTML(hotkeyMatch) + suffix; + } + return all; + }); + } + $.each(types, function(attrNo, attr) { var escapedType = Util.escapeQuotes(attr.type); var attrId = category+'_attr_'+escapedType; @@ -1917,6 +1942,10 @@ var AnnotatorUI = (function($, window, undefined) { $('').appendTo($span); } else if (attr.bool) { var escapedName = Util.escapeQuotes(attr.name); + if (attr.hotkey) { + spanKeymap[attr.hotkey] = attrId; + escapedName = highlightHotkey(escapedName, attr.hotkey, '[', ']'); + } var $input = $(''); @@ -1928,7 +1957,12 @@ var AnnotatorUI = (function($, window, undefined) { $input.change(onBooleanAttrChange); } else { // var $div = $('
'); - $span.text(attr.name); + var name = attr.name; + if (attr.hotkey) { + spanKeymap[attr.hotkey] = attrId; + name = highlightHotkey(name, attr.hotkey, '', ''); + } + $span.html(name); $span.append(': '); var $select = $(''); var $option = $('').text('?'); diff --git a/server/src/document.py b/server/src/document.py index 199fbdc03..76bc0aff9 100644 --- a/server/src/document.py +++ b/server/src/document.py @@ -223,7 +223,7 @@ def _fill_relation_configuration(nodes, project_conf, hotkey_by_type): # TODO: this may not be a good spot for this -def _fill_attribute_configuration(nodes, project_conf): +def _fill_attribute_configuration(nodes, project_conf, hotkey_by_type): items = [] for node in nodes: if node == SEPARATOR_STR: @@ -235,6 +235,10 @@ def _fill_attribute_configuration(nodes, project_conf): item['type'] = _type item['unused'] = node.unused item['labels'] = project_conf.get_labels_by_type(_type) + try: + item['hotkey'] = hotkey_by_type[_type] + except KeyError: + pass attr_drawing_conf = project_conf.get_drawing_config_by_type(_type) if attr_drawing_conf is None: @@ -372,14 +376,17 @@ def get_base_types(directory): def get_attribute_types(directory): project_conf = ProjectConfiguration(directory) + keymap = project_conf.get_kb_shortcuts() + hotkey_by_type = dict((v, k) for k, v in keymap.iteritems()) + entity_attribute_hierarchy = project_conf.get_entity_attribute_type_hierarchy() - entity_attribute_types = _fill_attribute_configuration(entity_attribute_hierarchy, project_conf) + entity_attribute_types = _fill_attribute_configuration(entity_attribute_hierarchy, project_conf, hotkey_by_type) relation_attribute_hierarchy = project_conf.get_relation_attribute_type_hierarchy() - relation_attribute_types = _fill_attribute_configuration(relation_attribute_hierarchy, project_conf) + relation_attribute_types = _fill_attribute_configuration(relation_attribute_hierarchy, project_conf, hotkey_by_type) event_attribute_hierarchy = project_conf.get_event_attribute_type_hierarchy() - event_attribute_types = _fill_attribute_configuration(event_attribute_hierarchy, project_conf) + event_attribute_types = _fill_attribute_configuration(event_attribute_hierarchy, project_conf, hotkey_by_type) return entity_attribute_types, relation_attribute_types, event_attribute_types