merge updates in VideoEditor, AnnotationsPanel, Editable, Input, etc

This commit is contained in:
rolux 2012-01-04 13:15:48 +05:30
commit 4ca01b2bfa
8 changed files with 279 additions and 119 deletions

View file

@ -628,7 +628,7 @@ OxArrayEditable
*/ */
.OxArrayEditable { .OxArrayEditable {
display: table-cell; //display: table-cell;
padding: 4px; padding: 4px;
} }
@ -784,6 +784,8 @@ div.OxInput > .OxInputLabel {
input.OxInput { input.OxInput {
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
}
div.OxInput > input.OxInput {
float: left; float: left;
} }
/* /*

View file

@ -9,41 +9,87 @@ Ox.ArrayEditable = function(options, self) {
self = self || {}; self = self || {};
var that = Ox.Element(options.editable === false ? {} : { var that = Ox.Element(options.editable === false ? {} : {
tooltip: 'Doubleclick to add ' + (options.itemName || 'item') tooltip: 'Doubleclick to add ' + (options.itemName || 'item')
}) }, self)
.defaults({ .defaults({
editable: true, editable: true,
itemName: 'item', itemName: 'item',
items: [], items: [],
position: -1, position: -1,
selected: -1, selected: '',
width: 256 width: 256
}) })
.options(options || {}) .options(options || {})
.addClass('OxArrayEditable') .addClass('OxArrayEditable')
.css({width: self.options.width - 8 + 'px'}) // 2 x 4 px padding .css({width: self.options.width - 8 + 'px'}) // 2 x 4 px padding
.bindEvent({ .bindEvent({
doubleclick: doubleclick anyclick: anyclick,
doubleclick: doubleclick,
key_delete: deleteItem,
key_enter: editItem,
key_escape: selectNone,
key_down: selectLast,
key_left: selectPrevious,
key_right: selectNext,
key_up: selectFirst
}); });
self.$items = []; self.$items = [];
self.values = []; self.selected = getSelectedPosition();
renderItems();
function anyclick(e) {
var $target = $(e.target),
$parent = $target.parent();
$target.is(':not(input)') && that.gainFocus();
if ($parent.is('.OxEditableElement')) {
selectItem($parent.data('position'));
} else {
selectNone();
}
}
function deleteItem() {
self.options.items.splice(self.selected, 1);
renderItems();
that.triggerEvent('delete', {
id: self.options.selected
});
}
function doubleclick(e) { function doubleclick(e) {
var $target = $(e.target); var $parent = $(e.target).parent();
if ($target.is('.OxEditable')) { if ($parent.is('.OxEditableElement')) {
that.editItem($target.data('position')); that.editItem(self.options.selected);
} else { } else {
that.addItem(position == -1 ? self.options.items.length : position); that.triggerEvent('add');
} }
} }
function editItem() {
if (self.selected > -1) {
Ox.forEach(self.$items, function($item) {
if ($item.data('position') == self.selected) {
$item.triggerEvent('doubleclick');
return false;
}
});
}
}
function getSelectedId() {
return self.selected > -1 ? self.options.items[self.selected].id : '';
}
function getSelectedPosition() {
return Ox.getPositionById(self.options.items, self.options.selected);
}
function renderItems() { function renderItems() {
that.empty(); that.empty();
self.options.items.forEach(function(item, i) { self.options.items.forEach(function(item, i) {
self.values[i] = item.value; i && $('<span>')
i && $('<div>') .html(', ')
.css({float: 'left'})
.html(',&nbsp;')
.appendTo(that); .appendTo(that);
self.$items[i] = Ox.Editable({ self.$items[i] = Ox.Editable({
editable: item.editable, editable: item.editable,
@ -55,49 +101,92 @@ Ox.ArrayEditable = function(options, self) {
), ),
value: item.value value: item.value
}) })
.css({float: 'left'}) .addClass(item.id == self.options.selected ? 'OxSelected' : '')
.data({position: i}) .data({position: i})
.bindEvent({ .bindEvent({
anyclick: function() {
that.find('.OxSelected').removeClass('.OxSelected');
self.$items[i].addClass('OxSelected');
},
cancel: function(data) { cancel: function(data) {
}, },
submit: function(data) { submit: function(data) {
submit(position, data.value); submit(i, data.value);
} }
}) })
.appendTo(that); .appendTo(that);
}); });
} }
function submit(position, value) { function selectFirst() {
if (value === '') { self.selected > -1 && selectItem(0);
self.values.splice(position, 1);
} else {
Array.prototype.splice.apply(self.values, Ox.merge(
[position, 1],
value.split(',').map(function(v) {
return v.trim();
})
));
}
renderItems();
} }
that.addItem = function(position) { function selectItem(position) {
self.selected = position;
self.options.selected = getSelectedId();
that.selectItem(self.options.selected);
}
function selectLast() {
self.selected > -1 && selectItem(self.options.items.length - 1);
}
function selectNext() {
self.selected > -1
&& self.selected < self.options.items.length - 1
&& selectItem(self.selected + 1);
}
function selectNone() {
selectItem(-1);
}
function selectPrevious() {
self.selected > 0 && selectItem(self.selected - 1);
}
function submit(position, value) {
var item = self.options.items[position];
if (value === '') {
deleteItem();
} else {
item.value != value && that.triggerEvent('submit', {
id: item.id,
value: value
});
item.value = value;
}
}
self.setOption = function(key, value) {
if (key == 'items') {
renderItems();
}
}
that.addItem = function(position, item) {
self.options.items.splice(position, 0, item);
renderItems();
//that.triggerEvent('add');
/*
self.values = Ox.filter(values, function(value) { self.values = Ox.filter(values, function(value) {
return value; return value;
}); });
self.values.push(''); self.values.push('');
renderItems(); renderItems();
Ox.last(self.$items).triggerEvent('doubleclick'); Ox.last(self.$items).triggerEvent('doubleclick');
*/
}; };
that.editItem = function(position) { that.editItem = function(position) {
selectItem(position);
editItem();
};
that.selectItem = function(id) {
self.options.selected = id;
self.selected = getSelectedPosition();
that.find('.OxSelected').removeClass('OxSelected');
self.selected > -1 && self.$items[self.selected].addClass('OxSelected');
that.triggerEvent('select', {id: self.options.selected});
}; };
that.removeItem = function(position) { that.removeItem = function(position) {

View file

@ -15,7 +15,7 @@ Ox.Editable = function(options, self) {
self = self || {}; self = self || {};
var that = Ox.Element({ var that = Ox.Element({
element: '<div>', element: options.type == 'textarea' ? '<div>' : '<span>',
tooltip: options.tooltip tooltip: options.tooltip
}, self) }, self)
.defaults({ .defaults({
@ -25,6 +25,7 @@ Ox.Editable = function(options, self) {
format: null, format: null,
height: 0, height: 0,
placeholder: '', placeholder: '',
submitOnBlur: true,
tooltip: '', tooltip: '',
value: '', value: '',
width: 0, width: 0,
@ -125,18 +126,19 @@ Ox.Editable = function(options, self) {
.appendTo(that.$element); .appendTo(that.$element);
self.$input = Ox.Input({ self.$input = Ox.Input({
changeOnKeypress: true, changeOnKeypress: true,
element: self.options.type == 'input' ? '<span>' : '<div>',
style: 'square', style: 'square',
type: self.options.type, type: self.options.type,
value: formatInputValue(), value: formatInputValue(),
}) })
.css(self.css) .css(self.css)
.bindEvent({ .bindEvent({
blur: submit,
cancel: cancel, cancel: cancel,
change: change, change: change,
submit: submit submit: submit
}) })
.appendTo(that.$element); .appendTo(that.$element);
self.options.submitOnBlur && self.$input.bindEvent({blur: submit});
self.$input.find('input').css(self.css); self.$input.find('input').css(self.css);
} }
self.$input.options({ self.$input.options({

View file

@ -65,7 +65,9 @@ Ox.Input <f:Ox.Element> Input Element
Ox.Input = function(options, self) { Ox.Input = function(options, self) {
self = self || {}; self = self || {};
var that = Ox.Element({}, self) var that = Ox.Element({
element: options.element || '<div>'
}, self)
.defaults({ .defaults({
arrows: false, arrows: false,
arrowStep: 1, arrowStep: 1,

View file

@ -1409,25 +1409,33 @@ Ox.List = function(options, self) {
} }
function updateSort() { function updateSort() {
var key = self.options.sort[0].key, var length = self.options.sort.length,
map = self.options.sort[0].map, operator = [],
operator = self.options.sort[0].operator, sort = [];
selectedIds,
sort = {};
//if (self.listLength > 1) { //if (self.listLength > 1) {
if (!self.isAsync) { if (!self.isAsync) {
getSelectedIds(function(selectedIds) { getSelectedIds(function(selectedIds) {
self.options.items.forEach(function(item) { self.options.sort.forEach(function(v, i) {
sort[item.id] = map ? map(item[key], item) : item[key]; operator.push(v.operator);
sort.push({});
self.options.items.forEach(function(item) {
sort[i][item.id] = v.map
? v.map(item[v.key], item)
: item[v.key]
});
}); });
self.options.items.sort(function(a, b) { self.options.items.sort(function(a, b) {
var aValue = sort[a.id], var aValue, bValue, index = 0, ret = 0;
bValue = sort[b.id], while (ret == 0 && index < length) {
ret = 0; aValue = sort[index][a.id];
if (aValue < bValue) { bValue = sort[index][b.id];
ret = operator == '+' ? -1 : 1; if (aValue < bValue) {
} else if (aValue > bValue) { ret = operator[index] == '+' ? -1 : 1;
ret = operator == '+' ? 1 : -1; } else if (aValue > bValue) {
ret = operator[index] == '+' ? 1 : -1;
} else {
index++;
}
} }
return ret; return ret;
}); });

View file

@ -26,13 +26,27 @@ Ox.AnnotationPanel = function(options, self) {
id: '', id: '',
items: [], items: [],
range: 'all', range: 'all',
selected: -1,
sort: 'position',
title: '', title: '',
type: 'text', type: 'text',
width: 0 width: 0
}) })
.options(options || {}); .options(options || {});
self.selected = -1; self.sort = self.options.sort == 'duration' ? [
{key: 'duration', operator: '-'},
{key: 'position', operator: '+'},
{key: 'value', operator: '+'}
] : self.options.sort == 'position' ? [
{key: 'position', operator: '+'},
{key: 'duration', operator: '-'},
{key: 'value', operator: '+'}
] : [ // 'text'
{key: 'value', operator: '+'},
{key: 'position', operator: '+'},
{key: 'duration', operator: '-'}
];
that.setElement( that.setElement(
Ox.CollapsePanel({ Ox.CollapsePanel({
@ -60,59 +74,86 @@ Ox.AnnotationPanel = function(options, self) {
); );
that.$content = that.$element.$content; that.$content = that.$element.$content;
self.$annotations = Ox.List({ if (self.options.type == 'event') {
construct: function(data) { self.$annotations = Ox.Element();
var $item = Ox.Element() } else if (self.options.type == 'place') {
.addClass('OxAnnotation OxTarget') self.$annotations = Ox.Element();
.css({padding: '4px 4px 0 4px'}) } else if (self.options.type == 'string') {
.append( self.$annotations = Ox.ArrayEditable({
Ox.Editable({ editable: self.options.editable,
type: 'textarea', items: getAnnotations(),
width: self.options.width - 8, sort: self.sort,
value: data.value width: pandora.user.ui.annotationsSize - Ox.UI.SCROLLBAR_SIZE
}) })
.bindEvent({ .bindEvent({
edit: function() { add: function(data) {
$item.removeClass('OxTarget'); that.triggerEvent('add', {
}, value: data.value || ''
submit: function(newData) { });
$item.addClass('OxTarget'); },
updateAnnotation({ 'delete': function(data) {
id: data.id, that.triggerEvent('remove', {id: data.id});
value: newData.value },
}); select: function(data) {
} selectAnnotation({ids: [data.id]});
}) },
) submit: updateAnnotation
.append($('<div>').css({height: '4px'})); });
return $item; } else if (self.options.type == 'text') {
}, self.$annotations = Ox.List({
items: getAnnotations(), construct: function(data) {
max: 1, var $item = Ox.Element()
min: 0, .addClass('OxAnnotation OxTarget')
sort: [{key: 'in', operator: '+'}], .css({padding: '4px 4px 0 4px'})
type: 'none', // fixme .append(
unique: 'id' Ox.Editable({
}) type: 'textarea',
.bindEvent({ width: self.options.width - 8,
cancel: function(item) { value: data.value
//reset in/out points })
selectAnnotation({}, {ids: [item.id]}); .bindEvent({
}, edit: function() {
open: function(data) { $item.removeClass('OxTarget');
return; },
if (data.ids.length == 1) { submit: function(newData) {
var pos = Ox.getPositionById(self.$annotations.options('items'), data.ids[0]); $item.addClass('OxTarget');
self.$annotations.editItem(pos); updateAnnotation({
} id: data.id,
}, value: newData.value
'delete': function(data) { });
that.triggerEvent('remove', {id: data.ids[0]}); }
}, })
select: selectAnnotation, )
submit: updateAnnotation .append($('<div>').css({height: '4px'}));
}) return $item;
.appendTo(that.$content); },
items: getAnnotations(),
max: 1,
min: 0,
sort: self.sort,
type: 'none', // fixme
unique: 'id'
})
.bindEvent({
cancel: function(item) {
//reset in/out points
selectAnnotation({ids: [item.id]});
},
open: function(data) {
return;
if (data.ids.length == 1) {
var pos = Ox.getPositionById(self.$annotations.options('items'), data.ids[0]);
self.$annotations.editItem(pos);
}
},
'delete': function(data) {
that.triggerEvent('remove', {id: data.ids[0]});
},
select: selectAnnotation,
submit: updateAnnotation
});
}
self.$annotations.appendTo(that.$content);
/* /*
self.$annotations = Ox.Element() self.$annotations = Ox.Element()
@ -139,7 +180,7 @@ Ox.AnnotationPanel = function(options, self) {
self.options.range == 'position' self.options.range == 'position'
&& item['in'] <= self.options.position && item['in'] <= self.options.position
&& item.out > self.options.position && item.out > self.options.position
); )
}); });
} }
@ -180,6 +221,8 @@ Ox.AnnotationPanel = function(options, self) {
self.$annotations.options({ self.$annotations.options({
items: getAnnotations() items: getAnnotations()
}); });
} else if (key == 'sort') {
self.$annotations.options({sort: value});
} }
}; };
@ -189,7 +232,11 @@ Ox.AnnotationPanel = function(options, self) {
that.addItem = function(item) { that.addItem = function(item) {
var pos = 0; var pos = 0;
self.options.items.splice(pos, 0, item); self.options.items.splice(pos, 0, item);
self.$annotations.addItems(pos, [item]); if (self.$annotations.addItem) {
self.$annotations.addItem(pos, item);
} else {
self.$annotations.addItems(pos, [item]);
}
self.$annotations.editItem(pos); self.$annotations.editItem(pos);
}; };
@ -204,7 +251,9 @@ Ox.AnnotationPanel = function(options, self) {
removeItems <f> removeItems removeItems <f> removeItems
@*/ @*/
that.removeItem = function(id) { that.removeItem = function(id) {
self.$annotations.removeItems([id]); var pos = Ox.getPositionById(self.options.items, id);
self.options.items.splice(pos, 1);
self.$annotations.removeItems && self.$annotations.removeItems([id]);
}; };
return that; return that;

View file

@ -21,6 +21,7 @@ Ox.VideoEditor = function(options, self) {
annotationsFont: 'small', annotationsFont: 'small',
annotationsRange: 'all', annotationsRange: 'all',
annotationsSize: 0, annotationsSize: 0,
annotationsSort: 'position',
censored: [], censored: [],
cuts: [], cuts: [],
duration: 0, duration: 0,
@ -312,6 +313,7 @@ Ox.VideoEditor = function(options, self) {
out: self.options.out, out: self.options.out,
position: self.options.position, position: self.options.position,
range: self.options.annotationsRange, range: self.options.annotationsRange,
sort: self.options.annotationsSort,
width: self.options.annotationsSize - Ox.UI.SCROLLBAR_SIZE width: self.options.annotationsSize - Ox.UI.SCROLLBAR_SIZE
}, layer) }, layer)
) )
@ -637,6 +639,13 @@ Ox.VideoEditor = function(options, self) {
{id: 'all', title: 'All', checked: self.options.annotationsRange == 'all'} {id: 'all', title: 'All', checked: self.options.annotationsRange == 'all'}
]}, ]},
{}, {},
{id: 'sortannotations', title: 'Sort Annotations', disabled: true},
{group: 'sort', min: 1, max: 1, items: [
{id: 'position', title: 'By Position', checked: self.options.annotationsSort == 'position'},
{id: 'duration', title: 'By Duration', checked: self.options.annotationsSort == 'duration'},
{id: 'text', title: 'By Text', checked: self.options.annotationsSort == 'text'}
]},
{},
{id: 'fontsize', title: 'Font Size', disabled: true}, {id: 'fontsize', title: 'Font Size', disabled: true},
{group: 'font', min: 1, max: 1, items: [ {group: 'font', min: 1, max: 1, items: [
{id: 'small', title: 'Small', checked: self.options.annotationsFont == 'small'}, {id: 'small', title: 'Small', checked: self.options.annotationsFont == 'small'},
@ -911,7 +920,7 @@ Ox.VideoEditor = function(options, self) {
} }
function selectAnnotation(data) { function selectAnnotation(data) {
setPosition(data['in']); //setPosition(data['in']);
setPoint('in', data['in']); setPoint('in', data['in']);
setPoint('out', data.out); setPoint('out', data.out);
} }

View file

@ -1,19 +1,19 @@
'use strict'; 'use strict';
/*@ /*@
Ox.compact <f> Returns an array w/o <code>null</code> or <code>undefined</code> Ox.compact <f> Returns an array w/o <code>undefined</code> values
> Ox.compact([null,,1,,2,,3]) > Ox.compact([null,,1,,2,,3])
[1, 2, 3] [1, 2, 3]
@*/ @*/
Ox.compact = function(arr) { Ox.compact = function(arr) {
return Ox.map(arr, function(val) { return arr.filter(function(val) {
return Ox.isUndefined(val) ? null : val; return !Ox.isNull(val) && !Ox.isUndefined(val);
}); });
}; };
/*@ /*@
Ox.flatten <f> Flattens an array Ox.flatten <f> Flattens an array
> Ox.flatten([1, [2, [3], 2], 1]) > Ox.flatten([1, [2, [3], 2], 1])
[1, 2, 3, 2, 1] [1, 2, 3, 2, 1]
@*/ @*/
@ -40,11 +40,11 @@ Ox.merge <f> Merges an array with one or more other arrays
[1, 2, 3, 2, 1] [1, 2, 3, 2, 1]
@*/ @*/
Ox.merge = function(arr) { Ox.merge = function(arr) {
arr = Ox.isArray(arr) ? arr : [arr]; arr = Ox.toArray(arr);
Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg) { Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg) {
Ox.isArray(arg) ? Ox.forEach(arg, function(val) { Ox.forEach(Ox.toArray(arg), function(val) {
arr.push(val); arr.push(val);
}) : arr.push(arg); });
}); });
return arr; return arr;
}; };
@ -98,10 +98,9 @@ Ox.unique <f> Returns an array without duplicate values
> Ox.unique([NaN, NaN]) > Ox.unique([NaN, NaN])
[] []
@*/ @*/
Ox.unique = function(arr) { Ox.unique = function(arr) {
return Ox.map(arr, function(val, i) { return Ox.filter(arr, function(val, i) {
return arr.indexOf(val) == i ? val : null; return arr.indexOf(val) == i;
}); });
}; };