From 688ae65cf1a34144d1db617d2a85b8bfb8f98678 Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Sun, 15 Jan 2012 20:35:17 +0530 Subject: [PATCH] update video editor --- source/Ox.UI/js/Form/Ox.ArrayEditable.js | 185 ++++++++++++------- source/Ox.UI/js/Form/Ox.Editable.js | 47 +++-- source/Ox.UI/js/Map/Ox.ListMap.js | 81 +++++++- source/Ox.UI/js/Map/Ox.Map.js | 38 ++-- source/Ox.UI/js/Video/Ox.AnnotationFolder.js | 94 +++++++--- source/Ox.UI/js/Video/Ox.AnnotationPanel.js | 18 +- source/Ox.UI/js/Video/Ox.VideoEditor.js | 119 +++++++----- source/Ox.UI/themes/classic/css/classic.css | 7 + 8 files changed, 413 insertions(+), 176 deletions(-) diff --git a/source/Ox.UI/js/Form/Ox.ArrayEditable.js b/source/Ox.UI/js/Form/Ox.ArrayEditable.js index 8c49747c..1171ec0f 100644 --- a/source/Ox.UI/js/Form/Ox.ArrayEditable.js +++ b/source/Ox.UI/js/Form/Ox.ArrayEditable.js @@ -14,8 +14,10 @@ Ox.ArrayEditable = function(options, self) { editable: true, itemName: 'item', items: [], + placeholder: '', position: -1, selected: '', + separator: ',', sort: [], submitOnBlur: true, type: 'input', @@ -39,33 +41,35 @@ Ox.ArrayEditable = function(options, self) { }); self.$items = []; + self.editing = false; renderItems(); self.selected = getSelectedPosition(); function anyclick(e) { + Ox.print('SELF EDITING', self.editing) var $target = $(e.target), $parent = $target.parent(), position = $parent.data('position'); - //ignore clicks while editing if (!$target.is('.OxInput')) { - if (self.selected > -1) { - //end editing but keep selected if clicked next to a keyword - if (self.editing || self.$items[self.selected].options('editing')) { - self.editing = false; - self.$items[self.selected].options({editing: false}); - //deselect if not editing and not going to select antoher one - } else if (!$parent.is('.OxEditableElement')) { - selectNone(); - } - } - //select if clicked on other editable element + Ox.print('BLURRED EDITING', self.blurred, self.editing) if ($parent.is('.OxEditableElement')) { + // select another item + Ox.print('AAAAA') selectItem( e.metaKey && position == self.selected ? '' : $parent.data('position') ); + } else if (!self.blurred) { + // if there wasn't an active input element + if (self.editing) { + // blur if still in editing mode + that.blurItem(); + } else { + // othewise deselect selected + selectNone(); + } } that.gainFocus(); } @@ -78,6 +82,8 @@ Ox.ArrayEditable = function(options, self) { that.triggerEvent('delete', { id: self.options.selected }); + self.selected = -1; + self.options.selected = ''; } } @@ -99,50 +105,83 @@ Ox.ArrayEditable = function(options, self) { return Ox.getIndexById(self.options.items, self.options.selected); } - function renderItems() { + function renderItems(blur) { + if (self.editing) { + self.options.items[getSelectedPosition()].value = that.find('input:visible').val(); + } that.empty(); - sortItems(); - self.options.items.forEach(function(item, i) { - i && self.options.type == 'input' - && $('') - .html(', ') + if (self.options.items.length == 0) { + Ox.Editable({ + editable: false, + type: 'text', + value: self.options.placeholder + }) + .addClass('OxPlaceholder') + .appendTo(that); + } else { + sortItems(); + self.options.items.forEach(function(item, i) { + if (i && self.options.type == 'input') { + $('') + .addClass('OxSeparator') + .html(self.options.separator + ' ') + .appendTo(that); + } + self.$items[i] = Ox.Editable({ + blurred: self.editing && i == self.selected ? blur : false, + editable: self.options.editable && item.editable, + editing: self.editing && i == self.selected, + format: function(value) { + return value || ' ' + }, + submitOnBlur: self.options.submitOnBlur, + tooltip: 'Click to select' + ( + item.editable ? ', doubleclick to edit' : '' + ), + type: self.options.type, + value: item.value, + width: self.options.type == 'input' ? 0 : self.options.width - 8 + }) + .addClass(item.id == self.options.selected ? 'OxSelected' : '') + .data({position: i}) + .bindEvent({ + blur: function(data) { + // fixme: remove data + that.gainFocus(); + that.triggerEvent('blur', { + id: item.id, + value: data.value + }); + self.blurred = true; + setTimeout(function() { + self.blurred = false; + }, 250); + }, + cancel: function(data) { + self.editing = false; + that.gainFocus(); + that.triggerEvent('blur', data); + }, + change: function(data) { + that.triggerEvent('change', { + id: item.id, + value: data.value + }); + }, + edit: function(data) { + self.editing = true; + that.triggerEvent('edit', data); + }, + submit: function(data) { + self.editing = false; + that.gainFocus(); + submitItem(i, data.value); + } + }) .appendTo(that); - self.$items[i] = Ox.Editable({ - editable: self.options.editable && item.editable, - format: function(value) { - return value || ' ' - }, - submitOnBlur: self.options.submitOnBlur, - tooltip: 'Click to select' + ( - item.editable ? ', doubleclick to edit' : '' - ), - type: self.options.type, - value: item.value, - width: self.options.type == 'input' ? 0 : self.options.width - 8 - }) - .addClass(item.id == self.options.selected ? 'OxSelected' : '') - .data({position: i}) - .bindEvent({ - blur: function(data) { - that.gainFocus(); - that.triggerEvent('blur', data); - }, - cancel: function(data) { - that.gainFocus(); - Ox.print("GAINING FOCUS!") - that.triggerEvent('blur', data); - }, - edit: function(data) { - self.editing = true; - that.triggerEvent('edit', data); - }, - submit: function(data) { - that.gainFocus(); - submitItem(i, data.value); - } - }) - .appendTo(that); - }); + }); + } + //self.editing && that.editItem(blur); } function selectFirst() { @@ -150,7 +189,6 @@ Ox.ArrayEditable = function(options, self) { } function selectItem(idOrPosition) { - Ox.print('???????', self.editing) if (Ox.isString(idOrPosition)) { self.options.selected = idOrPosition; self.selected = getSelectedPosition(); @@ -197,10 +235,8 @@ Ox.ArrayEditable = function(options, self) { var item = self.options.items[position]; if (value === '') { deleteItem(); - } else if (item.value === value) { - that.triggerEvent('blur'); } else { - that.triggerEvent('submit', { + that.triggerEvent(item.value === value ? 'blur' : 'submit', { id: item.id, value: value }); @@ -224,7 +260,7 @@ Ox.ArrayEditable = function(options, self) { self.setOption = function(key, value) { if (key == 'items') { - renderItems(); + renderItems(true); } else if (key == 'selected') { selectItem(value); } else if (key == 'sort') { @@ -242,6 +278,7 @@ Ox.ArrayEditable = function(options, self) { self.options.items.splice(position, 0, item); renderItems(); } + return that; //that.triggerEvent('add'); /* self.values = Ox.filter(values, function(value) { @@ -259,34 +296,44 @@ Ox.ArrayEditable = function(options, self) { self.$items[self.selected].options({editing: false}); } else { */ - self.$items.forEach(function($item) { - $item.options({editing: false}); - }); + self.editing = false; + self.$items.forEach(function($item) { + $item.options({editing: false}); + }); //} + return that; }; that.editItem = function() { + Ox.print('AE EDIT ITEM') if (self.options.editable && self.options.selected) { - Ox.forEach(self.$items, function($item) { - if ($item.data('position') == self.selected) { - Ox.print('DBLCLICK') - $item.triggerEvent('doubleclick'); - return false; - } - }); + self.editing = true; + self.$items[self.selected].options({editing: true}); } + return that; }; that.reloadItems = function() { renderItems(); + return that; }; that.removeItem = function(position) { if (self.options.editable) { } + return that; }; + /* + that.submitItem = function() { + if (self.editing) { + self.editing = false; + self.$items[self.selected].options({editing: false}); + } + } + */ + return that; }; diff --git a/source/Ox.UI/js/Form/Ox.Editable.js b/source/Ox.UI/js/Form/Ox.Editable.js index 1f100eb9..923b8601 100644 --- a/source/Ox.UI/js/Form/Ox.Editable.js +++ b/source/Ox.UI/js/Form/Ox.Editable.js @@ -19,6 +19,7 @@ Ox.Editable = function(options, self) { tooltip: options.tooltip }, self) .defaults({ + blurred: false, clickLink: null, editable: true, editing: false, @@ -62,13 +63,22 @@ Ox.Editable = function(options, self) { .appendTo(that); if (self.options.editing) { - // edit will toggle self.options.editing - self.options.editing = false; - edit(); + // need timeout so that when determining height + // the element is actually in the DOM + setTimeout(function() { + // edit will toggle self.options.editing + self.options.editing = false; + edit(); + }, 0); } - function blur() { - that.triggerEvent('blur'); + function blur(data) { + self.options.value = parseValue(); + if (self.options.value !== self.originalValue) { + self.originalValue = self.options.value; + that.triggerEvent('change', {value: self.options.value}); + } + that.triggerEvent('blur', data); } function cancel() { @@ -104,14 +114,10 @@ Ox.Editable = function(options, self) { width: width + 'px' }); } - /* - that.triggerEvent('change', { - value: event.value - }); - */ } function edit() { + Ox.print('E EDIT! editable editing', self.options.editable, self.options.editing) var height, width; if (self.options.editable && !self.options.editing) { self.options.editing = true; @@ -166,12 +172,15 @@ Ox.Editable = function(options, self) { }); } // fixme: why can't this be chained? - setTimeout(function() { - self.$input.focusInput(self.options.type == 'input'); - }, 0); - that.$tooltip && that.$tooltip.options({title: ''}); - that.triggerEvent('edit'); + if (!self.options.blurred) { + setTimeout(function() { + self.$input.focusInput(self.options.type == 'input'); + }, 0); + that.$tooltip && that.$tooltip.options({title: ''}); + that.triggerEvent('edit'); + } } + self.options.blurred = false; } function formatInputValue() { @@ -204,9 +213,15 @@ Ox.Editable = function(options, self) { return value; } + function parseValue() { + return self.options.type == 'input' + ? Ox.encodeHTML(self.$input.value()) + : Ox.parseHTML(self.$input.value()); + } + function submit() { self.options.editing = false; - self.options.value = Ox.parseHTML(self.$input.value()); + self.options.value = parseValue(); self.$input.value(formatInputValue()).hide(); self.$test.html(formatTestValue()); self.$value.html(formatValue()).show(); diff --git a/source/Ox.UI/js/Map/Ox.ListMap.js b/source/Ox.UI/js/Map/Ox.ListMap.js index 9e436d77..a7efa8fc 100644 --- a/source/Ox.UI/js/Map/Ox.ListMap.js +++ b/source/Ox.UI/js/Map/Ox.ListMap.js @@ -10,6 +10,7 @@ Ox.ListMap ListMap object options Options object height Height in px labels If true, show labels + names Array or names (undefined places), or function places Array of places, or function that returns places selected Selected places width Width in px @@ -26,10 +27,11 @@ Ox.ListMap = function(options, self) { getMatches: null, height: 256, labels: false, + names: null, pageLength: 100, places: null, removePlace: null, - selected: [], + selected: '', showControls: false, showLabels: false, showTypes: false, @@ -220,6 +222,59 @@ Ox.ListMap = function(options, self) { size: 24 }); + if (self.options.names) { + + self.$listSelect = Ox.Select({ + items: [ + {id: 'places', title: 'Show Places'}, + {id: 'names', title: 'Show Names'} + ], + max: 1, + min: 1, + style: 'symbol', + title: 'set', + type: 'image', + value: 'places' + }) + .css({float: 'left', margin: '4px 0 4px 4px'}) + .bindEvent({ + change: toggleList + }) + .appendTo(self.$listToolbar); + + self.$namesList = Ox.TextList({ + columns: [ + { + id: 'name', + operator: '+', + title: 'Name', + visible: true, + width: 256 + }, + { + align: 'right', + id: 'matches', + operator: '-', + title: 'Matches', + visible: true, + width: 64, + } + ], + columnsVisible: true, + items: [], + max: 1, + min: 0, + scrollbarVisible: true, + sort: [{key: 'name', operator: '+'}] + }) + .bindEvent({ + select: function(data) { + + } + }); + + } + self.$findElement = Ox.FormElementGroup({ elements: [ self.$findSelect = Ox.Select({ @@ -242,7 +297,7 @@ Ox.ListMap = function(options, self) { self.$findInput = Ox.Input({ clear: true, placeholder: 'Find in List', - width: 234 + width: self.options.names ? 214 : 234 }) .bindEvent({ submit: function(data) { @@ -267,8 +322,11 @@ Ox.ListMap = function(options, self) { columnsVisible: true, //items: Ox.clone(self.options.places), items: self.options.places, + max: 1, + min: 0, pageLength: self.options.pageLength, scrollbarVisible: true, + selected: self.options.selected ? [self.options.selected] : [], sort: self.options.sort }) .bindEvent({ @@ -308,6 +366,7 @@ Ox.ListMap = function(options, self) { findPlaceholder: 'Find on Map', height: self.options.height, places: self.options.places, + selected: self.options.selected, //statusbar: true, showControls: self.options.showControls, showLabels: self.options.showLabels, @@ -622,7 +681,7 @@ Ox.ListMap = function(options, self) { elements: [ { collapsible: true, - element: Ox.SplitPanel({ + element: self.$listPanel = Ox.SplitPanel({ elements: [ { element: self.$listToolbar, @@ -821,6 +880,22 @@ Ox.ListMap = function(options, self) { return Ox.isNumber(val) ? val.toFixed(8) : val; // fixme: why can a string be passed ?? } + function toggleList() { + var list = self.$listSelect.options('value'); + list == 'names' && !self.namesLoaded ? load() : toggle(); + function load() { + self.options.names(function(data) { + Ox.print('DATA IS', data); + self.$namesList.options({items: data}); + self.namesLoaded = true; + toggle(); + }); + } + function toggle() { + self.$listPanel.replaceElement(1, self[list == 'places' ? '$list' : '$namesList']); + } + } + function updateList(key, value) { var query = { conditions: Ox.merge( diff --git a/source/Ox.UI/js/Map/Ox.Map.js b/source/Ox.UI/js/Map/Ox.Map.js index e104842d..a1138666 100644 --- a/source/Ox.UI/js/Map/Ox.Map.js +++ b/source/Ox.UI/js/Map/Ox.Map.js @@ -777,7 +777,7 @@ Ox.Map = function(options, self) { getMapBounds(function(mapBounds) { - Ox.Log('Map', 'init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) + //Ox.Log('Map', 'init', mapBounds.getSouthWest(), mapBounds.getNorthEast(), mapBounds.getCenter()) self.elevationService = new google.maps.ElevationService(); self.geocoder = new google.maps.Geocoder(); @@ -855,22 +855,6 @@ Ox.Map = function(options, self) { Ox.forEach(self.$placeControls, function($placeControl) { $placeControl.appendTo(self.$map); }); - setTimeout(function() { - var $element; - try { - $element = $(self.$map.find('a[href$="terms_maps.html"]').parent()).css({ - color: 'rgb(192, 192, 192)', - textShadow: '1px 1px 0 rgb(64, 64, 64)' - }); - ['moz', 'o', 'webkit'].forEach(function(browser) { - $element.css({ - backgroundImage: '-' + browser - + '-linear-gradient(left, rgba(255, 255, 255, 0) 0px, rgba(255, 255, 255, 0.1) 50px)', - }); - }); - $element.children().css({color: 'rgb(192, 192, 192)'}); - } catch (e) {} - }, 0) } } @@ -882,6 +866,25 @@ Ox.Map = function(options, self) { && southWest.lng() == northEast.lng(); } + function formatTerms() { + setTimeout(function() { + var $element; + try { + $element = $(self.$map.find('a[href$="terms_maps.html"]').parent()).css({ + color: 'rgb(192, 192, 192)', + textShadow: '1px 1px 0 rgb(64, 64, 64)' + }); + ['moz', 'o', 'webkit'].forEach(function(browser) { + $element.css({ + backgroundImage: '-' + browser + + '-linear-gradient(left, rgba(255, 255, 255, 0) 0px, rgba(255, 255, 255, 0.1) 50px)', + }); + }); + $element.children().css({color: 'rgb(192, 192, 192)'}); + } catch (e) {} + }, 0); + } + function mapChanged() { // gets called after panning or zooming Ox.Log('Map', 'mapChanged'); @@ -971,6 +974,7 @@ Ox.Map = function(options, self) { if (self.zoomChanged) { self.zoomChanged = false; } + formatTerms(); } function pan(x, y) { diff --git a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js index bfd51047..3e99e159 100644 --- a/source/Ox.UI/js/Video/Ox.AnnotationFolder.js +++ b/source/Ox.UI/js/Video/Ox.AnnotationFolder.js @@ -57,7 +57,12 @@ Ox.AnnotationFolder = function(options, self) { }) .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 + }); } }); } @@ -127,6 +132,7 @@ Ox.AnnotationFolder = function(options, self) { } else { // place self.$widget = self.$map = Ox.Map({ places: getPlaces(), + showTypes: true, // FIXME: should be showZoombar zoombar: true // showLabels: true @@ -168,7 +174,9 @@ Ox.AnnotationFolder = function(options, self) { self.$annotations = Ox.ArrayEditable({ editable: self.options.editable, items: getAnnotations(), + placeholder: 'No ' + self.options.title, selected: self.options.selected, + separator: ';', sort: self.sort, submitOnBlur: false, width: self.options.type == 'text' ? self.options.width + 8 : self.options.width, @@ -177,12 +185,19 @@ Ox.AnnotationFolder = function(options, self) { //.css({marginTop: '256px'}) .bindEvent({ add: function(data) { - that.triggerEvent('add', {value: data.value || ''}); + if (self.editing) { + // FIXME: changed value will not be saved! + } + that.triggerEvent('add', {value: data.value || ''}); }, blur: function() { + // the video editor will, if it has not received focus, + // call blurItem that.triggerEvent('blur'); }, + change: changeAnnotation, 'delete': function(data) { + self.editing = false; that.triggerEvent('remove', {id: data.id}); }, edit: function() { @@ -208,6 +223,12 @@ Ox.AnnotationFolder = function(options, self) { showWarnings(); + function changeAnnotation(data) { + var item = Ox.getObjectById(self.options.items, data.id); + item.value = data.value; + that.triggerEvent('change', item); + } + function dragstart() { if (self.options.showWidget) { self.drag = { @@ -298,7 +319,7 @@ Ox.AnnotationFolder = function(options, self) { function selectAnnotation(data) { var item = Ox.getObjectById(self.options.items, data.id); self.options.selected = item ? data.id : ''; - self.$defineButton.options({disabled: !self.options.selected}); + self.widget && self.$defineButton.options({disabled: !self.options.selected}); ///* if (self.options.type == 'place') { self.$map.options({ @@ -315,14 +336,16 @@ Ox.AnnotationFolder = function(options, self) { } function showWarnings() { - if (self.widget) { + if (self.widget && self.options.items.length) { self.$annotations.find('.OxValue').each(function() { var $element = $(this); - if (!Ox.getObject( - self.options.items, 'value', $element.html() - )[self.options.type]) { - $element.css({color: 'rgb(192, 64, 64)'}); - } + try { // FIXME: bad data, remove later!! + if (!Ox.getObject( + self.options.items, 'value', $element.html() + )[self.options.type]) { + $element.css({color: 'rgb(192, 64, 64)'}); + } + } catch(e) {} }); } } @@ -331,7 +354,6 @@ Ox.AnnotationFolder = function(options, self) { var item = Ox.getObjectById(self.options.items, data.id); item.value = data.value; self.editing = false; - Ox.print('??:', self.options.items[0], self.$annotations.options('items')[0]) //self.$annotations.options({items: self.options.items}); self.options.sort == 'text' && self.$annotations.reloadItems(); that.triggerEvent('submit', item); @@ -353,6 +375,17 @@ Ox.AnnotationFolder = function(options, self) { that.triggerEvent('togglewidget', {collapsed: !self.options.showWidget}); } + function updateAnnotations() { + self.$annotations.options({items: getAnnotations()}); + showWarnings(); + } + + function updateWidget() { + self.options.type == 'event' + ? self.$calendar.options({events: getEvents()}) + : self.$map.options({places: getPlaces()}); + } + self.setOption = function(key, value) { if (['in', 'out'].indexOf(key) > -1 && self.editing) { var index = Ox.getIndexById(self.options.items, self.options.selected); @@ -361,19 +394,19 @@ Ox.AnnotationFolder = function(options, self) { } if (key == 'in') { //fixme: array editable should support item updates while editing - if (self.editing || self.options.range == 'selection') { - self.options.type == 'place' ? self.$map.options({places: getPlaces()}) - : self.$annotations.options({items: getAnnotations()}); + if (self.options.range == 'selection') { + self.widget && updateWidget(); + updateAnnotations(); } } else if (key == 'out') { - if (self.editing || self.options.range == 'selection') { - self.options.type == 'place' ? self.$map.options({places: getPlaces()}) - : self.$annotations.options({items: getAnnotations()}); + if (self.options.range == 'selection') { + self.widget && updateWidget(); + updateAnnotations(); } } else if (key == 'position') { - if (self.editing || self.options.range == 'position') { - self.options.type == 'place' ? self.$map.options({places: getPlaces()}) - : self.$annotations.options({items: getAnnotations()}); + if (self.options.range == 'position') { + self.widget && updateWidget(); + updateAnnotations(); } } else if (key == 'range') { self.$annotations.options({items: getAnnotations()}); @@ -387,8 +420,7 @@ Ox.AnnotationFolder = function(options, self) { self.$annotations.options({sort: self.sort}); showWarnings(); } else if (key == 'users') { - self.$annotations.options({items: getAnnotations()}); - showWarnings(); + updateAnnotations(); } else if (key == 'width') { Ox.print('RESIZE!!!!') if (self.widget) { @@ -406,18 +438,26 @@ Ox.AnnotationFolder = function(options, self) { addItem addItem @*/ that.addItem = function(item) { + Ox.print('FOLDER ADD ITEM', item) var pos = 0; self.options.items.splice(pos, 0, item); - self.$annotations.addItem(pos, item); - self.$annotations.editItem(item.id); + self.$annotations + .addItem(pos, item) + .options({selected: item.id}) + .editItem(); + //selectAnnotation(item); + //that.triggerEvent('edit'); + return that; }; that.blurItem = function() { self.$annotations.blurItem(); + return that; }; that.editItem = function() { self.$annotations.editItem(); + return that; }; /*@ @@ -431,6 +471,14 @@ Ox.AnnotationFolder = function(options, self) { }; */ + that.updateItem = function(item) { + var index = Ox.getIndexById(self.options.items, item.id); + self.options.items[index] = item; + self.widget && updateWidget(); + updateAnnotations(); + return that; + } + return that; }; diff --git a/source/Ox.UI/js/Video/Ox.AnnotationPanel.js b/source/Ox.UI/js/Video/Ox.AnnotationPanel.js index eabe14f1..4387cd0f 100644 --- a/source/Ox.UI/js/Video/Ox.AnnotationPanel.js +++ b/source/Ox.UI/js/Video/Ox.AnnotationPanel.js @@ -174,8 +174,14 @@ Ox.AnnotationPanel = function(options, self) { blur: function() { that.triggerEvent('blur'); }, + change: function(data) { + that.triggerEvent('change', Ox.extend({layer: layer.id}, data)); + }, + define: function(data) { + that.triggerEvent('define', data); + }, edit: function() { - that.triggerEvent('edit') + that.triggerEvent('edit'); }, paused: function() { that.triggerEvent('paused') @@ -192,7 +198,7 @@ Ox.AnnotationPanel = function(options, self) { selectAnnotation(data, i); }, submit: function(data) { - that.triggerEvent('submit', data); + that.triggerEvent('submit', Ox.extend({layer: layer.id}, data)); }, togglelayer: function(data) { that.triggerEvent('togglelayer', Ox.extend({layer: layer.id}, data)); @@ -290,11 +296,11 @@ Ox.AnnotationPanel = function(options, self) { }; that.addItem = function(layer, item) { + Ox.print('ADD ITEM', layer, item); var i = Ox.getIndexById(self.options.layers, layer); self.$folder[i].addItem(item); }; - that.blurItem = function() { getFolder(self.options.selected).blurItem(); }; @@ -303,9 +309,9 @@ Ox.AnnotationPanel = function(options, self) { getFolder(self.options.selected).editItem(); }; - that.updateItem = function(layer, item) { - var i = Ox.getIndexById(self.options.layers, layer); - self.$folder[i].updateItem(item); + that.updateItem = function(item) { + Ox.print('UPDATE ITEM', item); + getFolder(item.id).updateItem(item); }; return that; diff --git a/source/Ox.UI/js/Video/Ox.VideoEditor.js b/source/Ox.UI/js/Video/Ox.VideoEditor.js index 440edd82..7d12f2d6 100644 --- a/source/Ox.UI/js/Video/Ox.VideoEditor.js +++ b/source/Ox.UI/js/Video/Ox.VideoEditor.js @@ -58,9 +58,6 @@ Ox.VideoEditor = function(options, self) { width: 0 }) .options(options || {}) - .mousedown(function() { - that.gainFocus(); - }) .bindEvent({ key_0: toggleMuted, key_shift_0: function() { @@ -90,8 +87,9 @@ Ox.VideoEditor = function(options, self) { movePositionBy(self.sizes.timeline[0].width); }, key_enter: function() { - if (self.editiing) { - submitAnnotation(); + if (self.editing) { + // submitAnnotation(); + blurAnnotation(); } else if (self.options.selected) { editAnnotation(); } @@ -211,8 +209,12 @@ Ox.VideoEditor = function(options, self) { // the following is needed to determine // how to handle annotation input blur if (self.editing) { + Ox.print('FOCUSED') self.focused = true; setTimeout(function() { + // annotation folder will gain focus on blur + // so we need to get focus back + that.gainFocus(); self.focused = false; }, 25); } @@ -614,18 +616,26 @@ Ox.VideoEditor = function(options, self) { addAnnotation(data.layer); }, annotationsfont: function(data) { + self.options.annotationsFont = data.font; that.triggerEvent('annotationsfont', data); }, annotationsrange: function(data) { + self.options.annotationsRange = data.range; that.triggerEvent('annotationsrange', data); }, annotationssort: function(data) { + self.options.annotationsSort = data.sort; that.triggerEvent('annotationssort', data); }, - blur: function() { - Ox.print('VE-BLUR') - self.editing = false; - setTimelineState(); + blur: function(data) { + Ox.print('VIDEO EDITOR BLUR') + !self.focused && blurAnnotation(); + }, + change: function(data) { + that.triggerEvent('editannotation', data); + }, + define: function(data) { + that.triggerEvent('define', data); }, edit: function() { self.editing = true; @@ -633,10 +643,14 @@ Ox.VideoEditor = function(options, self) { }, paused: togglePaused, remove: function(data) { - that.triggerEvent('removeannotation', { - id: data.id, - layer: data.layer - }); + Ox.print('?>???', data) + var layer = Ox.getObjectById(self.options.layers, data.layer), + index = Ox.getIndexById(layer.items, data.id); + layer.items.splice(index, 1); + self.editing = false; + self.options.selected = ''; + setTimelineState(); + that.triggerEvent('removeannotation', data); }, resize: resizeAnnotations, resizeend: resizeendAnnotations, @@ -650,6 +664,7 @@ Ox.VideoEditor = function(options, self) { submit: submitAnnotation, toggle: toggleAnnotations, togglecalendar: function(data) { + self.options.showAnnotationsCalendar = !data.collapsed; that.triggerEvent('togglecalendar', data); }, togglelayer: function(data) { @@ -659,6 +674,7 @@ Ox.VideoEditor = function(options, self) { }); }, togglemap: function(data) { + self.options.showAnnotationsMap = !data.collapsed; that.triggerEvent('togglemap', data); } }); @@ -685,7 +701,7 @@ Ox.VideoEditor = function(options, self) { collapsible: true, element: self.$annotationPanel, resizable: true, - resize: [192, 256, 320, 384], + resize: [192, 256, 320, 384, 448, 512], size: self.options.annotationsSize, tooltip: self.options.tooltips ? 'annotations' : false } @@ -712,7 +728,17 @@ Ox.VideoEditor = function(options, self) { function blurAnnotation() { self.editing = false; setTimelineState(); - self.$annotationPanel.blurItem(); + if ( + self.options.annotationsRange == 'position' && ( + self.options.position < self.options['in'] + || self.options.position > self.options.out + ) + ) { + setPosition(self.options['in']); + } + // setPosition causes a folder redraw + // so blur once that's done + setTimeout(self.$annotationPanel.blurItem, 0); } function editAnnotation() { @@ -932,7 +958,6 @@ Ox.VideoEditor = function(options, self) { } function selectAnnotation(data) { - //Ox.print('VE.sA') if (Ox.isUndefined(data)) { // doubleclick on small timeline data = getAnnotation(); @@ -941,13 +966,10 @@ Ox.VideoEditor = function(options, self) { } self.editing = false; self.options.selected = data.id; - // fixme: what is the following supposed to do? - if (self.options.selected && self.options.annotationsRange != 'position') { - setPosition(data['in']); - } if (self.options.selected) { - setPoint('in', data['in']); - setPoint('out', data.out); + self.options.annotationsRange != 'position' && setPosition(data['in']); + setPoint('in', data['in'], true); + setPoint('out', data.out, true); } self.$annotationPanel.options({selected: self.options.selected}); setTimelineState(); @@ -976,16 +998,12 @@ Ox.VideoEditor = function(options, self) { setPoint('out', points.out); } - function setPoint(point, position, annotation) { + function setPoint(point, position, keepSelected) { var otherPoint = point == 'in' ? 'out' : 'in'; self.options[point] = position; - /* - // should only happen through interaction - if (self.options.selected && !self.editing) { - self.options.selected = ''; - setTimelineState(); + if (self.options.selected && !self.editing && !keepSelected) { + selectAnnotation({id: ''}); } - */ self.$player.forEach(function($player) { $player.options(point, self.options[point]); }); @@ -996,22 +1014,22 @@ Ox.VideoEditor = function(options, self) { $timeline.options(point, self.options[point]); }); if (self.options['in'] > self.options.out) { - setPoint(point == 'in' ? 'out' : 'in', position); - } - self.$annotationPanel.options({ - 'in': self.options['in'], - out: self.options.out - }); - that.triggerEvent('points', { - 'in': self.options['in'], - out: self.options.out - }); - if (self.editing) { - that.triggerEvent('editannotation', { - id: self.options.selected, + setPoint(point == 'in' ? 'out' : 'in', position, keepSelected); + } else { + self.$annotationPanel.options({ 'in': self.options['in'], out: self.options.out }); + that.triggerEvent('points', { + 'in': self.options['in'], + out: self.options.out + }); + self.editing && that.triggerEvent('editannotation', { + id: self.options.selected, + 'in': self.options['in'], + out: self.options.out, + value: $('.OxEditableElement input:visible').val() + }); } } @@ -1068,6 +1086,17 @@ Ox.VideoEditor = function(options, self) { function submitAnnotation(data) { self.editing = false; setTimelineState(); + Ox.print('....', self.options.annotationsRange == 'position', + self.options.position < self.options['in'], + self.options.position > self.options.out) + if ( + self.options.annotationsRange == 'position' && ( + self.options.position < self.options['in'] + || self.options.position > self.options.out + ) + ) { + setPosition(self.options['in']); + } data['in'] = self.options['in']; data.out = self.options.out; that.triggerEvent('editannotation', data); @@ -1149,9 +1178,15 @@ Ox.VideoEditor = function(options, self) { annotation annotation to add @*/ that.addAnnotation = function(layer, annotation) { + // called from addannotation callback self.$annotationPanel.addItem(layer, annotation); }; + that.updateAnnotation = function(annotation) { + // called from editannotation callback + self.$annotationPanel.updateItem(annotation); + } + /*@ removeAnnotation remove annotation (layer, ids) -> remove annotation from layer diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index 35740e19..f2edd359 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -740,6 +740,13 @@ Video background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 1), rgba(192, 192, 192, 1)); } +/* FIXME: the first two should apply for every ArrayEditable */ +.OxThemeClassic .OxAnnotationFolder .OxArrayEditable .OxSeparator { + color: rgb(96, 96, 96); +} +.OxThemeClassic .OxAnnotationFolder .OxEditableElement.OxPlaceholder .OxValue { + color: rgb(160, 160, 160); +} .OxThemeClassic .OxAnnotationFolder .OxEditableElement.OxSelected { background: rgb(192, 192, 255); box-shadow: 0 0 1px rgb(64, 64, 64);