diff --git a/source/Ox.UI/js/Form/Ox.ArrayEditable.js b/source/Ox.UI/js/Form/Ox.ArrayEditable.js index 7374396f..37b6384c 100644 --- a/source/Ox.UI/js/Form/Ox.ArrayEditable.js +++ b/source/Ox.UI/js/Form/Ox.ArrayEditable.js @@ -59,6 +59,7 @@ Ox.ArrayEditable = function(options, self) { that.triggerEvent('delete', { id: self.options.selected }); + self.editing = false; self.selected = -1; self.options.selected = ''; } @@ -367,9 +368,9 @@ Ox.ArrayEditable = function(options, self) { return that; }; - that.removeItem = function(position) { - if (self.options.editable) { - + that.removeItem = function() { + if (self.options.editable && self.options.selected) { + deleteItem(); } return that; }; diff --git a/source/Ox.UI/js/Menu/Ox.MenuButton.js b/source/Ox.UI/js/Menu/Ox.MenuButton.js index c14a53ff..5fda7209 100644 --- a/source/Ox.UI/js/Menu/Ox.MenuButton.js +++ b/source/Ox.UI/js/Menu/Ox.MenuButton.js @@ -91,6 +91,7 @@ Ox.MenuButton = function(options, self) { function hideMenu(data) { that.loseFocus(); that.removeClass('OxSelected'); + that.triggerEvent('hide'); } function showMenu() { @@ -98,6 +99,7 @@ Ox.MenuButton = function(options, self) { that.addClass('OxSelected'); self.options.tooltip && that.$tooltip.hide(); self.$menu.showMenu(); + that.triggerEvent('show'); } self.setOption = function(key, value) { diff --git a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js index 9407c43b..9e97afee 100644 --- a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js +++ b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js @@ -52,27 +52,6 @@ Ox.AnnotationFolder = function(options, self) { self.widget = self.options.type == 'event' ? 'Calendar' : self.options.type == 'place' ? 'Map' : ''; - if (self.widget) { - self.$defineButton = Ox.Button({ - disabled: !self.options.selected, - id: 'define', - style: 'symbol', - title: 'click', - tooltip: 'Define ' + Ox.toTitleCase(self.options.type), - type: 'image' - }) - .bindEvent({ - click: function() { - var item = Ox.getObjectById(self.options.items, self.options.selected); - that.triggerEvent('define', item.place ? { - id: item.place.id - } : { - name: item.value - }); - } - }); - } - self.$addButton = Ox.Button({ id: 'add', style: 'symbol', @@ -99,10 +78,7 @@ Ox.AnnotationFolder = function(options, self) { self.$panel = Ox.CollapsePanel({ collapsed: self.options.collapsed, - extras: Ox.merge( - self.widget ? [self.$defineButton] : [], - [self.options.editable ? self.$addButton : self.$infoButton] - ), + extras: [self.options.editable ? self.$addButton : self.$infoButton], size: 16, title: self.options.title }) @@ -404,7 +380,7 @@ Ox.AnnotationFolder = function(options, self) { function getSort() { return ({ - duration: ['+duration', '+in', '+value'], + duration: ['-duration', '+in', '+value'], position: ['+in', '+duration', '+value'], text: ['+value', '+in', '+duration'] })[self.options.sort]; @@ -602,6 +578,10 @@ Ox.AnnotationFolder = function(options, self) { return that; }; + that.removeItem = function() { + self.$annotations.removeItem(); + }; + that.selectItem = function(position) { // selects the first (0) or last (-1) visible annotation if (self.annotations.length) { diff --git a/source/Ox.UI/js/Video/Ox.AnnotationPanel.js b/source/Ox.UI/js/Video/Ox.AnnotationPanel.js index 45301b75..6851fa96 100644 --- a/source/Ox.UI/js/Video/Ox.AnnotationPanel.js +++ b/source/Ox.UI/js/Video/Ox.AnnotationPanel.js @@ -29,6 +29,8 @@ Ox.AnnotationPanel = function(options, self) { .options(options || {}) .addClass('OxAnnotationPanel'); + self.editing = false; + if (self.options.showUsers) { self.users = Ox.sort(Ox.unique(Ox.flatten( self.options.layers.map(function(layer) { @@ -110,39 +112,6 @@ Ox.AnnotationPanel = function(options, self) { }) .appendTo(self.$menubar); - if (self.options.editable) { - self.$editMenuButton = Ox.MenuButton({ - items: [ - {id: 'edit', title: 'Edit Annotation', disabled: !self.options.selected, keyboard: 'return'}, - {id: 'delete', title: 'Delete Annotation', disabled: !self.options.selected, keyboard: 'delete'}, - {id: 'deselect', title: 'Deselect Annotation', disabled: !self.options.selected, keyboard: 'escape'}, - {}, - {id: 'save', title: 'Save Changes', disabled: true, keyboard: 'shift return'}, - {id: 'undo', title: 'Undo Changes', disabled: true, keyboard: 'escape'}, - {}, - {id: 'find', title: 'Find Annotation', disabled: true}, - {id: 'manage', title: 'Edit Place/Event', disabled: true} - ], - style: 'square', - title: 'edit', - tooltip: 'Editing Options', - type: 'image' - }) - .css({float: 'right'}) - .bindEvent({ - click: function(data) { - if (data.id == 'delete') { - - } else if (data.id == 'deselect') { - - } else if (data.id == 'edit') { - - } - } - }) - .appendTo(self.$menubar); - } - self.$folders = Ox.Element().css({overflowY: 'auto'}); self.$folder = []; @@ -176,15 +145,16 @@ Ox.AnnotationPanel = function(options, self) { that.triggerEvent('add', Ox.extend({layer: layer.id}, data)); }, blur: function() { + self.editing = false; + renderEditMenu(); that.triggerEvent('blur'); }, change: function(data) { that.triggerEvent('change', Ox.extend({layer: layer.id}, data)); }, - define: function(data) { - that.triggerEvent('define', data); - }, edit: function() { + self.editing = true; + renderEditMenu(); that.triggerEvent('edit'); }, info: function(data) { @@ -249,10 +219,27 @@ Ox.AnnotationPanel = function(options, self) { }) ); + self.options.editable && renderEditMenu(); + self.options.selected && scrollToSelected( getFolder(self.options.selected).options('type') ); + function getAnnotation(annotationId) { + var found = false, annotation; + Ox.forEach(self.options.layers, function(layer, i) { + Ox.forEach(layer.items, function(item) { + if (item.id == annotationId) { + annotation = item; + found = true; + return false; + } + }); + return !found; + }); + return annotation; + } + function getFolder(annotationId) { var found = false, folder; Ox.forEach(self.options.layers, function(layer, i) { @@ -268,6 +255,74 @@ Ox.AnnotationPanel = function(options, self) { return folder; } + function renderEditMenu() { + Ox.print('RENDER EDIT MENU') + var annotation, findTitle, folder, + isDefined, isEditable, isEvent, isEventOrPlace, isPlace, isString, + key, manageTitle, type, value + if (self.options.selected) { + annotation = getAnnotation(self.options.selected); + folder = getFolder(self.options.selected); + key = folder.options('id'); + type = folder.options('type'); + value = annotation.value; + isEditable = annotation.editable; + isEvent = type == 'event'; + isPlace = type == 'place'; + isEventOrPlace = isEvent || isPlace; + isString = type != 'text'; + // fixme: absence of annotation[type] may be an error + isDefined = isEventOrPlace && !!annotation[type] && !!annotation[type].type; + } + findTitle = 'Find ' + (isString ? '"' + value + '"' : 'Annotation'); + manageTitle = (isDefined ? 'Edit' : 'Define') + ' ' + + (isPlace ? 'Place' : isEvent ? 'Event' : 'Place or Event') + '...' + self.$editMenuButton && self.$editMenuButton.remove(); + self.$editMenuButton = Ox.MenuButton({ + items: [ + {id: 'deselect', title: 'Deselect Annotation', disabled: !self.options.selected || self.editing, keyboard: 'escape'}, + {id: 'edit', title: 'Edit Annotation', disabled: !self.options.selected || !isEditable || self.editing, keyboard: 'return'}, + {id: 'delete', title: 'Delete Annotation', disabled: !self.options.selected || !isEditable, keyboard: 'delete'}, + {}, + {id: 'insert', title: 'Insert...', disabled: isString || !self.editing}, + {id: 'undo', title: 'Undo Changes', disabled: !self.editing, keyboard: 'escape'}, + {id: 'save', title: 'Save Changes', disabled: !self.editing, keyboard: isString ? 'return' : 'shift return'}, + {}, + {id: 'manage', title: manageTitle, disabled: !self.options.selected || !isEventOrPlace}, + {id: 'find', title: findTitle, disabled: !self.options.selected || !isString} + ], + maxWidth: 256, + style: 'square', + title: 'edit', + tooltip: 'Editing Options', + type: 'image' + }) + .css({float: 'right'}) + .bindEvent({ + click: function(data) { + if (data.id == 'delete') { + getFolder(self.options.selected).removeItem(); + } else if (data.id == 'deselect') { + getFolder(self.options.selected).options({selected: ''}); + } else if (data.id == 'edit') { + getFolder(self.options.selected).editItem(); + } else if (data.id == 'find') { + that.triggerEvent('find', {key: key, value: value}); + } else if (data.id == 'manage') { + that.triggerEvent('define', { + id: self.options.selected, + type: type + }); + } else if (data.id == 'save') { + // ... + } else if (data.id == 'undo') { + // ... + } + } + }) + .appendTo(self.$menubar); + } + function scrollToSelected(type) { var $item = that.find('.OxEditableElement.OxSelected'), itemHeight = $item.height() + (type == 'text' ? 8 : 0), @@ -289,15 +344,23 @@ Ox.AnnotationPanel = function(options, self) { } function selectAnnotation(data, index) { - Ox.print('selectAnnotation', index) - self.options.selected = data.id; if (data.id) { - self.$folder.forEach(function($folder, i) { - i != index && $folder.options({selected: ''}); + Ox.forEach(self.$folder, function($folder, i) { + if (i != index && $folder.options('selected')) { + self.deselecting = true; + $folder.options({selected: ''}); + self.deselecting = false; + return false; + } }); scrollToSelected(self.options.layers[index].type); } - that.triggerEvent('select', data); + if (!self.deselecting) { + self.options.selected = data.id; + Ox.print('selectAnnotation', index, data.id) + self.options.editable && renderEditMenu(); + that.triggerEvent('select', data); + } } function selectNone() { @@ -347,22 +410,28 @@ Ox.AnnotationPanel = function(options, self) { }; that.addItem = function(layer, item) { - Ox.Log('AP', 'ADD ITEM', layer, item); + // called from addannotation callback var i = Ox.getIndexById(self.options.layers, layer); + renderEditMenu(); self.$folder[i].addItem(item); }; that.blurItem = function() { + self.editing = false; + renderEditMenu(); getFolder(self.options.selected).blurItem(); }; that.editItem = function() { + self.editing = true; + renderEditMenu(); getFolder(self.options.selected).editItem(); }; that.updateItem = function(id, item) { - Ox.Log('AP', 'UPDATE ITEM', id, item); + // called from editannotation callback self.options.selected = item.id; + renderEditMenu(); getFolder(id).updateItem(id, item); }; diff --git a/source/Ox.UI/js/Video/Ox.VideoEditor.js b/source/Ox.UI/js/Video/Ox.VideoEditor.js index 42e61472..e458b3d9 100644 --- a/source/Ox.UI/js/Video/Ox.VideoEditor.js +++ b/source/Ox.UI/js/Video/Ox.VideoEditor.js @@ -603,7 +603,11 @@ Ox.VideoEditor = function(options, self) { }, blur: function(data) { Ox.print('VIDEO EDITOR BLUR') - !self.focused && blurAnnotation(); + // Only blur if neither the video editor + // nor an active menu layer received the click + if (!self.focused && !$('.OxMenuLayer').length) { + blurAnnotation(); + } }, change: function(data) { that.triggerEvent('editannotation', data); @@ -617,6 +621,9 @@ Ox.VideoEditor = function(options, self) { self.editing = true; setTimelineState(); }, + find: function(data) { + that.triggerEvent('findannotation', data); + }, info: function(data) { that.triggerEvent('info', data); }, @@ -723,7 +730,7 @@ Ox.VideoEditor = function(options, self) { } // setPosition causes a folder redraw // so blur once that's done - setTimeout(self.$annotationPanel.blurItem, 0); + setTimeout(self.$annotationPanel.blurItem); } function editAnnotation() { @@ -1232,7 +1239,9 @@ Ox.VideoEditor = function(options, self) { } function updateWords(action) { + // action can be 'add' or 'remove' var words = []; + Ox.print('#^#$^#$^#$^#$', self.options.selected, getAnnotationValue(self.options.selected)) Ox.forEach(Ox.count(Ox.words( getAnnotationValue(self.options.selected) )), function(count, value) {