2011-11-05 16:46:53 +00:00
|
|
|
'use strict';
|
|
|
|
|
2011-05-16 08:24:46 +00:00
|
|
|
/*@
|
2012-05-31 10:32:54 +00:00
|
|
|
Ox.VideoEditor <f> VideoEditor Object
|
2012-07-04 11:29:18 +00:00
|
|
|
options <o> Options object
|
|
|
|
self <o> Shared private variable
|
2012-05-31 10:32:54 +00:00
|
|
|
([options[, self]]) -> <o:Ox.SplitPanel> VideoEditor Object
|
2012-06-17 22:38:26 +00:00
|
|
|
addannotation <!> addannotation
|
|
|
|
annotationsfont <!> annotationsfont
|
|
|
|
annotationsrange <!> annotationsrange
|
|
|
|
annotationssize <!> annotationssize
|
|
|
|
annotationssort <!> annotationssort
|
|
|
|
censored <!> censored
|
|
|
|
define <!> define
|
|
|
|
downloadselection <!> downloadselection
|
|
|
|
downloadvideo <!> downloadvideo
|
|
|
|
editannotation <!> editannotation
|
|
|
|
editannotation <!> editannotation
|
|
|
|
embedselection <!> embedselection
|
|
|
|
findannotations <!> findannotations
|
|
|
|
find <!> find
|
|
|
|
importannotations <!> importannotations
|
|
|
|
info <!> info
|
|
|
|
key_* <!> key_*
|
|
|
|
muted <!> muted
|
|
|
|
paused <!> paused
|
|
|
|
points <!> points
|
|
|
|
position <!> position
|
|
|
|
posterframe <!> posterframe
|
|
|
|
removeannotation <!> removeannotation
|
|
|
|
resizecalendar <!> resizecalendar
|
|
|
|
resizemap <!> resizemap
|
|
|
|
resolution <!> resolution
|
|
|
|
select <!> select
|
|
|
|
subtitles <!> subtitles
|
|
|
|
timeline <!> timeline
|
|
|
|
toggleannotations <!> toggleannotations
|
|
|
|
togglecalendar <!> togglecalendar
|
|
|
|
togglelayer <!> togglelayer
|
|
|
|
togglemap <!> togglemap
|
|
|
|
volume <!> volume
|
2011-05-16 08:24:46 +00:00
|
|
|
@*/
|
|
|
|
|
2011-10-27 13:13:28 +00:00
|
|
|
// fixme: should be VideoAnnotationEditor
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
Ox.VideoEditor = function(options, self) {
|
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
self = self || {};
|
|
|
|
var that = Ox.Element({}, self)
|
2011-04-22 22:03:10 +00:00
|
|
|
.defaults({
|
2012-01-13 16:25:47 +00:00
|
|
|
annotationsCalendarSize: 256,
|
2012-01-02 19:06:36 +00:00
|
|
|
annotationsFont: 'small',
|
2012-01-13 16:25:47 +00:00
|
|
|
annotationsMapSize: 256,
|
2012-01-02 19:06:36 +00:00
|
|
|
annotationsRange: 'all',
|
2012-01-12 10:39:05 +00:00
|
|
|
annotationsSize: 256,
|
2012-01-03 19:41:50 +00:00
|
|
|
annotationsSort: 'position',
|
2011-10-22 21:03:42 +00:00
|
|
|
censored: [],
|
2012-04-22 09:57:17 +00:00
|
|
|
censoredIcon: '',
|
|
|
|
censoredTooltip: '',
|
2012-01-17 15:43:46 +00:00
|
|
|
clickLink: null,
|
2011-04-22 22:03:10 +00:00
|
|
|
cuts: [],
|
|
|
|
duration: 0,
|
2012-01-30 23:27:27 +00:00
|
|
|
enableDownload: false,
|
2012-02-17 09:06:26 +00:00
|
|
|
enableImport: false,
|
2012-04-23 09:53:29 +00:00
|
|
|
enableSetPosterFrame: false,
|
2011-12-22 15:47:46 +00:00
|
|
|
enableSubtitles: false,
|
2011-04-22 22:03:10 +00:00
|
|
|
find: '',
|
2011-05-18 16:00:29 +00:00
|
|
|
fps: 25,
|
2011-05-18 18:30:58 +00:00
|
|
|
getFrameURL: null,
|
2012-04-18 07:43:32 +00:00
|
|
|
getLargeTimelineURL: null,
|
|
|
|
getSmallTimelineURL: null,
|
2011-05-18 16:00:29 +00:00
|
|
|
'in': 0,
|
2011-04-22 22:03:10 +00:00
|
|
|
height: 0,
|
|
|
|
layers: [],
|
2011-11-05 15:01:18 +00:00
|
|
|
muted: false,
|
2011-05-18 16:00:29 +00:00
|
|
|
out: 0,
|
2012-05-26 11:52:08 +00:00
|
|
|
paused: true,
|
2011-04-22 22:03:10 +00:00
|
|
|
position: 0,
|
|
|
|
posterFrame: 0,
|
2011-12-20 13:09:26 +00:00
|
|
|
resolution: 0,
|
2012-01-04 17:27:32 +00:00
|
|
|
selected: '',
|
2011-04-22 22:03:10 +00:00
|
|
|
showAnnotations: false,
|
2012-01-13 16:25:47 +00:00
|
|
|
showAnnotationsCalendar: false,
|
|
|
|
showAnnotationsMap: false,
|
2011-05-24 19:19:27 +00:00
|
|
|
showLargeTimeline: true,
|
2012-01-11 07:52:01 +00:00
|
|
|
showLayers: {},
|
2012-01-12 10:39:05 +00:00
|
|
|
showUsers: false,
|
2011-04-22 22:03:10 +00:00
|
|
|
subtitles: [],
|
2012-04-18 07:43:32 +00:00
|
|
|
timeline: '',
|
|
|
|
timelines: [],
|
2011-09-04 21:15:16 +00:00
|
|
|
tooltips: false,
|
2011-08-19 14:44:03 +00:00
|
|
|
videoRatio: 16/9,
|
2011-04-22 22:03:10 +00:00
|
|
|
videoSize: 'small',
|
2011-05-19 17:58:00 +00:00
|
|
|
video: '',
|
2011-11-05 15:01:18 +00:00
|
|
|
volume: 1,
|
2011-04-22 22:03:10 +00:00
|
|
|
width: 0
|
|
|
|
})
|
|
|
|
.options(options || {})
|
2012-05-28 19:35:41 +00:00
|
|
|
.update({
|
|
|
|
height: setSizes,
|
|
|
|
'in': function() {
|
|
|
|
setPoint('in', self.options['in']);
|
|
|
|
},
|
|
|
|
out: function() {
|
|
|
|
setPoint('out', self.options.out);
|
|
|
|
},
|
|
|
|
paused: function() {
|
|
|
|
self.$player[0].options({
|
|
|
|
paused: self.options.paused
|
|
|
|
});
|
|
|
|
},
|
|
|
|
position: function() {
|
|
|
|
setPosition(self.options.position);
|
|
|
|
},
|
|
|
|
selected: function() {
|
|
|
|
selectAnnotation(
|
|
|
|
self.options.selected
|
|
|
|
? Ox.getObjectById(self.annotations, self.options.selected)
|
|
|
|
: {id: ''}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
showAnnotations: function() {
|
|
|
|
that.$element.toggle(1);
|
|
|
|
},
|
2012-06-15 13:20:07 +00:00
|
|
|
timeline: function() {
|
|
|
|
self.$menuButton.checkItem(self.options.timeline);
|
|
|
|
updateTimelines();
|
|
|
|
},
|
2012-05-28 19:35:41 +00:00
|
|
|
width: setSizes
|
|
|
|
})
|
2011-04-22 22:03:10 +00:00
|
|
|
.bindEvent({
|
2011-05-18 16:00:29 +00:00
|
|
|
key_0: toggleMuted,
|
2011-04-22 22:03:10 +00:00
|
|
|
key_alt_left: function() {
|
|
|
|
},
|
|
|
|
key_alt_right: function() {
|
|
|
|
},
|
|
|
|
key_alt_shift_left: function() {
|
|
|
|
},
|
|
|
|
key_alt_shift_right: function() {
|
|
|
|
},
|
2012-02-04 08:58:46 +00:00
|
|
|
key_b: function() {
|
2012-04-22 08:54:44 +00:00
|
|
|
self.annotations.length && selectAnnotation(
|
|
|
|
getNextAnnotation('annotation', -1)
|
|
|
|
);
|
2012-02-04 08:58:46 +00:00
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_backslash: function() {
|
2012-02-15 13:16:03 +00:00
|
|
|
self.annotations.length && selectAnnotation();
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_closebracket: function() {
|
2012-02-15 12:03:18 +00:00
|
|
|
self.annotations.length && movePositionTo('annotation', 1);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_comma: function() {
|
|
|
|
movePositionTo('cut', -1);
|
|
|
|
},
|
2012-02-19 14:37:55 +00:00
|
|
|
key_delete: function() {
|
|
|
|
self.$annotationPanel.removeItem(true);
|
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_dot: function() {
|
|
|
|
movePositionTo('cut', 1);
|
|
|
|
},
|
|
|
|
key_down: function() {
|
|
|
|
movePositionBy(self.sizes.timeline[0].width);
|
|
|
|
},
|
2012-01-10 14:49:28 +00:00
|
|
|
key_enter: function() {
|
2012-01-15 15:05:17 +00:00
|
|
|
if (self.editing) {
|
|
|
|
// submitAnnotation();
|
|
|
|
blurAnnotation();
|
2012-02-19 07:21:40 +00:00
|
|
|
} else if (isEditable()) {
|
2012-01-10 14:49:28 +00:00
|
|
|
editAnnotation();
|
|
|
|
}
|
|
|
|
},
|
2012-01-11 07:52:01 +00:00
|
|
|
key_equal: function() {
|
2012-02-19 11:21:52 +00:00
|
|
|
self.$player[0].changeVolume(0.1);
|
2012-01-11 07:52:01 +00:00
|
|
|
},
|
2012-01-10 14:49:28 +00:00
|
|
|
key_escape: function() {
|
|
|
|
if (self.editing) {
|
|
|
|
blurAnnotation();
|
|
|
|
} else if (self.options.selected) {
|
2012-01-12 10:39:05 +00:00
|
|
|
selectAnnotation({id: ''});
|
2012-01-10 14:49:28 +00:00
|
|
|
}
|
|
|
|
},
|
2011-05-19 18:34:53 +00:00
|
|
|
key_f: function() {
|
|
|
|
setTimeout(function() {
|
2011-12-18 09:44:11 +00:00
|
|
|
self.$findInput.focusInput(true);
|
2011-05-19 18:34:53 +00:00
|
|
|
});
|
|
|
|
},
|
|
|
|
key_g: function() {
|
2012-04-22 08:54:44 +00:00
|
|
|
self.results.length && selectAnnotation(
|
|
|
|
getNextAnnotation('result', 1)
|
|
|
|
);
|
2011-05-19 18:34:53 +00:00
|
|
|
},
|
2012-02-08 10:22:22 +00:00
|
|
|
key_h: showKeyboardShortcuts,
|
2011-04-22 22:03:10 +00:00
|
|
|
key_i: function() {
|
2011-05-19 10:18:39 +00:00
|
|
|
setPoint('in', self.options.position);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_left: function() {
|
2011-05-18 18:30:58 +00:00
|
|
|
movePositionBy(-0.04);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
2012-01-11 07:52:01 +00:00
|
|
|
key_minus: function() {
|
2012-02-19 11:21:52 +00:00
|
|
|
self.$player[0].changeVolume(-0.1);
|
2012-01-11 07:52:01 +00:00
|
|
|
},
|
2012-02-04 08:58:46 +00:00
|
|
|
key_n: function() {
|
2012-04-22 08:54:44 +00:00
|
|
|
self.annotations.length && selectAnnotation(
|
|
|
|
getNextAnnotation('annotation', 1)
|
|
|
|
);
|
2012-02-04 08:58:46 +00:00
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_o: function() {
|
2011-05-19 10:18:39 +00:00
|
|
|
setPoint('out', self.options.position);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_openbracket: function() {
|
2012-02-15 12:03:18 +00:00
|
|
|
self.annotations.length && movePositionTo('annotation', -1);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_p: playInToOut,
|
|
|
|
key_right: function() {
|
2011-05-18 18:30:58 +00:00
|
|
|
movePositionBy(0.04);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
2012-02-15 22:20:19 +00:00
|
|
|
key_shift_0: function() {
|
|
|
|
movePositionBy(-self.options.position);
|
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_shift_down: function() {
|
|
|
|
movePositionBy(self.options.duration);
|
|
|
|
},
|
2012-02-19 11:21:52 +00:00
|
|
|
key_shift_equal: function() {
|
|
|
|
self.options.videoSize == 'small' && toggleSize();
|
|
|
|
},
|
2011-05-19 18:34:53 +00:00
|
|
|
key_shift_g: function() {
|
2012-04-22 08:54:44 +00:00
|
|
|
self.results.length && selectAnnotation(
|
|
|
|
getNextAnnotation('result', -1)
|
|
|
|
);
|
2011-05-19 18:34:53 +00:00
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_shift_left: function() {
|
2011-05-19 17:58:00 +00:00
|
|
|
movePositionBy(-1);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_shift_i: function() {
|
|
|
|
goToPoint('in');
|
|
|
|
},
|
2012-02-19 11:21:52 +00:00
|
|
|
key_shift_minus: function() {
|
|
|
|
self.options.videoSize == 'large' && toggleSize();
|
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_shift_o: function() {
|
|
|
|
goToPoint('out');
|
|
|
|
},
|
2011-05-19 07:06:42 +00:00
|
|
|
key_shift_p: function() {
|
|
|
|
// go to poster frame
|
|
|
|
},
|
2011-04-22 22:03:10 +00:00
|
|
|
key_shift_right: function() {
|
2011-05-18 18:30:58 +00:00
|
|
|
movePositionBy(1);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_shift_up: function() {
|
2011-05-18 18:30:58 +00:00
|
|
|
movePositionBy(-self.options.position);
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
|
|
|
key_slash: function() {
|
2012-01-10 14:49:28 +00:00
|
|
|
selectCut();
|
2011-04-22 22:03:10 +00:00
|
|
|
},
|
2011-05-18 16:00:29 +00:00
|
|
|
key_space: togglePaused,
|
2011-04-22 22:03:10 +00:00
|
|
|
key_up: function() {
|
|
|
|
movePositionBy(-self.sizes.timeline[0].width);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2012-02-05 11:08:56 +00:00
|
|
|
self.options.layers.forEach(function(layer, i) {
|
|
|
|
that.bindEvent('key_' + (i + 1), function() {
|
2012-02-04 11:44:19 +00:00
|
|
|
layer.editable
|
|
|
|
? addAnnotation(layer.id)
|
|
|
|
: that.triggerEvent('info', {layer: layer.id});
|
2012-01-10 14:49:28 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2012-01-31 10:57:09 +00:00
|
|
|
self.$player = [];
|
|
|
|
self.$timeline = [];
|
2012-02-04 08:58:46 +00:00
|
|
|
self.annotations = getAnnotations();
|
2012-01-31 10:57:09 +00:00
|
|
|
self.controlsHeight = 16;
|
|
|
|
self.editing = false;
|
|
|
|
self.margin = 8;
|
2012-02-04 08:58:46 +00:00
|
|
|
self.positions = getPositions();
|
|
|
|
self.results = [];
|
2012-01-31 10:57:09 +00:00
|
|
|
self.words = getWords();
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
self.$editor = Ox.Element()
|
2011-04-22 22:03:10 +00:00
|
|
|
.addClass('OxVideoEditor')
|
2012-01-09 20:25:38 +00:00
|
|
|
.mousedown(function(e) {
|
2011-05-19 13:09:59 +00:00
|
|
|
var $target = $(e.target);
|
|
|
|
!$target.is('.OxPosition') && !$target.is('input') && that.gainFocus();
|
2012-01-09 20:25:38 +00:00
|
|
|
// the following is needed to determine
|
|
|
|
// how to handle annotation input blur
|
|
|
|
if (self.editing) {
|
|
|
|
self.focused = true;
|
|
|
|
setTimeout(function() {
|
2012-01-15 15:05:17 +00:00
|
|
|
// annotation folder will gain focus on blur
|
|
|
|
// so we need to get focus back
|
|
|
|
that.gainFocus();
|
2012-01-09 20:25:38 +00:00
|
|
|
self.focused = false;
|
|
|
|
}, 25);
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
self.sizes = getSizes();
|
|
|
|
|
|
|
|
['play', 'in', 'out'].forEach(function(type, i) {
|
2011-06-19 17:48:32 +00:00
|
|
|
self.$player[i] = Ox.VideoPlayer({
|
2011-10-22 21:03:42 +00:00
|
|
|
censored: self.options.censored,
|
2012-04-22 09:57:17 +00:00
|
|
|
censoredIcon: self.options.censoredIcon,
|
|
|
|
censoredTooltip: self.options.censoredTooltip,
|
2011-05-18 16:00:29 +00:00
|
|
|
controlsBottom: type == 'play' ?
|
2011-05-20 14:11:42 +00:00
|
|
|
['play', 'playInToOut', 'volume', 'size', 'space', 'position'] :
|
2011-05-18 16:00:29 +00:00
|
|
|
['goto', 'set', 'space', 'position'],
|
2011-04-22 22:03:10 +00:00
|
|
|
duration: self.options.duration,
|
2011-08-18 14:03:48 +00:00
|
|
|
enableMouse: true,
|
2011-12-19 21:13:11 +00:00
|
|
|
enablePosition: true,
|
2011-12-22 15:47:46 +00:00
|
|
|
enableSubtitles: self.options.enableSubtitles,
|
2011-05-18 16:00:29 +00:00
|
|
|
externalControls: true,
|
2011-04-22 22:03:10 +00:00
|
|
|
find: self.options.find,
|
|
|
|
height: self.sizes.player[i].height,
|
|
|
|
id: 'player' + Ox.toTitleCase(type),
|
2011-05-18 16:00:29 +00:00
|
|
|
'in': self.options['in'],
|
2011-11-05 15:01:18 +00:00
|
|
|
muted: self.options.muted,
|
2011-05-18 16:00:29 +00:00
|
|
|
out: self.options.out,
|
2012-05-26 11:52:08 +00:00
|
|
|
paused: self.options.paused,
|
2011-05-18 16:00:29 +00:00
|
|
|
position: type == 'play' ? self.options.position : self.options[type],
|
2011-04-22 22:03:10 +00:00
|
|
|
posterFrame: self.options.posterFrame,
|
2011-12-20 13:09:26 +00:00
|
|
|
resolution: self.options.resolution,
|
2011-05-18 16:00:29 +00:00
|
|
|
showMarkers: true,
|
2011-05-19 17:58:00 +00:00
|
|
|
showMilliseconds: 3,
|
2011-08-19 06:41:48 +00:00
|
|
|
sizeIsLarge: self.options.videoSize == 'large',
|
2011-04-22 22:03:10 +00:00
|
|
|
subtitles: self.options.subtitles,
|
|
|
|
type: type,
|
2011-05-18 18:30:58 +00:00
|
|
|
video: type == 'play' ? self.options.video : self.options.getFrameURL,
|
2011-11-05 15:01:18 +00:00
|
|
|
volume: self.options.volume,
|
2011-04-22 22:03:10 +00:00
|
|
|
width: self.sizes.player[i].width
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
left: self.sizes.player[i].left + 'px',
|
|
|
|
top: self.sizes.player[i].top + 'px'
|
|
|
|
})
|
2012-04-22 09:57:17 +00:00
|
|
|
.bindEvent(
|
|
|
|
Ox.extend({
|
|
|
|
censored: function() {
|
|
|
|
that.triggerEvent('censored');
|
|
|
|
}
|
|
|
|
}, type == 'play' ? {
|
|
|
|
muted: function(data) {
|
|
|
|
that.triggerEvent('muted', data);
|
|
|
|
},
|
|
|
|
paused: function(data) {
|
2012-05-26 11:52:08 +00:00
|
|
|
self.options.paused = data.paused;
|
2012-04-22 09:57:17 +00:00
|
|
|
that.triggerEvent('paused', data);
|
|
|
|
},
|
|
|
|
playing: function(data) {
|
|
|
|
setPosition(data.position, true);
|
|
|
|
},
|
|
|
|
position: function(data) {
|
|
|
|
setPosition(data.position);
|
|
|
|
},
|
|
|
|
resolution: function(data) {
|
|
|
|
that.triggerEvent('resolution', data);
|
|
|
|
},
|
|
|
|
size: function() {
|
|
|
|
toggleSize();
|
|
|
|
},
|
|
|
|
subtitles: function(data) {
|
|
|
|
that.triggerEvent('subtitles', data);
|
|
|
|
},
|
|
|
|
volume: function(data) {
|
|
|
|
that.triggerEvent('volume', data);
|
|
|
|
}
|
|
|
|
} : {
|
|
|
|
gotopoint: function() {
|
|
|
|
goToPoint(type);
|
|
|
|
},
|
|
|
|
position: function(data) {
|
|
|
|
setPoint(type, data.position);
|
|
|
|
},
|
|
|
|
setpoint: function() {
|
|
|
|
setPoint(type, self.options.position);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
2011-04-22 22:03:10 +00:00
|
|
|
.appendTo(self.$editor);
|
|
|
|
});
|
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
self.$timeline[0] = Ox.LargeVideoTimeline({
|
2011-04-22 22:03:10 +00:00
|
|
|
cuts: self.options.cuts,
|
|
|
|
duration: self.options.duration,
|
|
|
|
find: self.options.find,
|
2012-04-18 07:43:32 +00:00
|
|
|
getImageURL: self.options.getLargeTimelineURL,
|
2011-04-22 22:03:10 +00:00
|
|
|
id: 'timelineLarge',
|
2011-05-18 16:00:29 +00:00
|
|
|
'in': self.options['in'],
|
|
|
|
//matches: self.options.matches,
|
|
|
|
out: self.options.out,
|
2011-04-22 22:03:10 +00:00
|
|
|
position: self.options.position,
|
2012-02-19 18:26:57 +00:00
|
|
|
subtitles: self.options.enableSubtitles ? self.options.subtitles : [],
|
2012-04-18 07:43:32 +00:00
|
|
|
type: self.options.timeline,
|
2011-04-22 22:03:10 +00:00
|
|
|
width: self.sizes.timeline[0].width
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
left: self.sizes.timeline[0].left + 'px',
|
|
|
|
top: self.sizes.timeline[0].top + 'px'
|
|
|
|
})
|
2011-08-17 19:34:34 +00:00
|
|
|
.bindEvent({
|
2012-01-02 19:06:36 +00:00
|
|
|
position: function(data) {
|
|
|
|
setPosition(data.position);
|
|
|
|
}
|
2011-08-17 19:34:34 +00:00
|
|
|
})
|
2011-04-22 22:03:10 +00:00
|
|
|
.appendTo(self.$editor);
|
|
|
|
|
2011-06-19 17:48:32 +00:00
|
|
|
self.$timeline[1] = Ox.BlockVideoTimeline({
|
2011-04-22 22:03:10 +00:00
|
|
|
cuts: self.options.cuts,
|
|
|
|
duration: self.options.duration,
|
|
|
|
find: self.options.find,
|
2012-04-18 07:43:32 +00:00
|
|
|
getImageURL: self.options.getSmallTimelineURL,
|
2011-04-22 22:03:10 +00:00
|
|
|
id: 'timelineSmall',
|
2011-05-18 16:00:29 +00:00
|
|
|
'in': self.options['in'],
|
|
|
|
out: self.options.out,
|
2011-04-22 22:03:10 +00:00
|
|
|
position: self.options.position,
|
2011-10-20 13:32:53 +00:00
|
|
|
results: find(self.options.find),
|
2011-10-17 10:23:16 +00:00
|
|
|
showPointMarkers: true,
|
2012-01-09 20:25:38 +00:00
|
|
|
state: self.options.selected ? 'selected' : 'default',
|
2012-02-19 18:26:57 +00:00
|
|
|
subtitles: self.options.enableSubtitles ? self.options.subtitles : [],
|
2012-04-18 07:43:32 +00:00
|
|
|
type: self.options.timeline,
|
2011-04-22 22:03:10 +00:00
|
|
|
videoId: self.options.videoId,
|
|
|
|
width: self.sizes.timeline[1].width
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
left: self.sizes.timeline[1].left + 'px',
|
2012-05-26 15:48:19 +00:00
|
|
|
top: self.sizes.timeline[1].top + 'px'
|
2011-04-22 22:03:10 +00:00
|
|
|
})
|
2011-08-17 19:34:34 +00:00
|
|
|
.bindEvent({
|
2012-02-19 09:06:57 +00:00
|
|
|
edit: function() {
|
|
|
|
if (isEditable() && !self.editing) {
|
|
|
|
editAnnotation();
|
|
|
|
}
|
|
|
|
},
|
2012-01-02 19:06:36 +00:00
|
|
|
position: function(data) {
|
|
|
|
setPosition(data.position);
|
2012-01-10 14:49:28 +00:00
|
|
|
},
|
|
|
|
select: function() {
|
2012-02-04 11:44:19 +00:00
|
|
|
selectAnnotation(void 0, true);
|
2012-01-02 19:06:36 +00:00
|
|
|
}
|
2011-08-17 19:34:34 +00:00
|
|
|
})
|
2011-04-22 22:03:10 +00:00
|
|
|
.appendTo(self.$editor);
|
|
|
|
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$menubar = Ox.Bar({
|
|
|
|
size: 16
|
|
|
|
})
|
|
|
|
.addClass('OxVideoPlayer');
|
2011-05-19 17:58:00 +00:00
|
|
|
|
|
|
|
self.resolutions = [];
|
|
|
|
Ox.forEach(self.options.video, function(url, resolution) {
|
2011-12-20 13:09:26 +00:00
|
|
|
Ox.Log('Video', url, resolution);
|
2012-01-12 10:39:05 +00:00
|
|
|
self.resolutions.push({
|
|
|
|
id: resolution + '',
|
|
|
|
title: resolution + 'p',
|
|
|
|
checked: self.options.resolution == resolution
|
|
|
|
});
|
2011-05-19 17:58:00 +00:00
|
|
|
});
|
|
|
|
|
2011-11-03 12:14:18 +00:00
|
|
|
self.$keyboardShortcuts = $('<div>').css({margin: '16px'});
|
2012-05-24 07:45:33 +00:00
|
|
|
[
|
2011-05-20 14:11:42 +00:00
|
|
|
{key: Ox.UI.symbols.space, action: 'Play/Pause'},
|
|
|
|
{key: 'P', action: 'Play In to Out'},
|
|
|
|
{key: '0', action: 'Mute/Unmute'},
|
|
|
|
{key: '-', action: 'Turn Volume Down'},
|
|
|
|
{key: '+', action: 'Turn Volume Up'},
|
2012-02-19 11:21:52 +00:00
|
|
|
{key: Ox.UI.symbols.shift + '-', action: 'Small Player'},
|
|
|
|
{key: Ox.UI.symbols.shift + '+', action: 'Large Player'},
|
2011-05-20 14:11:42 +00:00
|
|
|
{key: Ox.UI.symbols.arrow_left, action: 'Go One Frame Back'},
|
|
|
|
{key: Ox.UI.symbols.arrow_right, action: 'Go One Frame Forward'},
|
|
|
|
{key: Ox.UI.symbols.shift + Ox.UI.symbols.arrow_left, action: 'Go One Second Back'},
|
|
|
|
{key: Ox.UI.symbols.shift + Ox.UI.symbols.arrow_right, action: 'Go One Second Forward'},
|
|
|
|
{key: Ox.UI.symbols.arrow_up, action: 'Go One Line Up'},
|
|
|
|
{key: Ox.UI.symbols.arrow_down, action: 'Go One Line Down'},
|
|
|
|
{key: Ox.UI.symbols.shift + Ox.UI.symbols.arrow_up, action: 'Go to First Frame'},
|
|
|
|
{key: Ox.UI.symbols.shift + Ox.UI.symbols.arrow_down, action: 'Go to Last Frame'},
|
|
|
|
{key: 'I', action: 'Set In Point'},
|
|
|
|
{key: 'O', action: 'Set Out Point'},
|
2012-02-15 20:27:28 +00:00
|
|
|
{key: Ox.UI.symbols.shift + 'I', action: 'Go to In Point'},
|
2011-05-20 14:11:42 +00:00
|
|
|
{key: Ox.UI.symbols.shift + 'O', action: 'Go to Out Point'},
|
|
|
|
{key: '[', action: 'Go to Previous Annotation'},
|
|
|
|
{key: ']', action: 'Go to Next Annotation'},
|
|
|
|
{key: '\\', action: 'Select Current Annotation'},
|
2012-02-04 08:58:46 +00:00
|
|
|
{key: 'B', action: 'Select Previous Annotation'},
|
|
|
|
{key: 'N', action: 'Select Next Annotation'},
|
2011-05-20 14:11:42 +00:00
|
|
|
{key: '<', action: 'Go to Previous Cut'},
|
|
|
|
{key: '>', action: 'Go to Next Cut'},
|
2011-10-05 17:07:21 +00:00
|
|
|
{key: '/', action: 'Select Current Cut'},
|
2011-05-20 14:11:42 +00:00
|
|
|
{key: 'F', action: 'Find'},
|
|
|
|
{key: Ox.UI.symbols.shift + 'G', action: 'Go to Previous Result'},
|
|
|
|
{key: 'G', action: 'Go to Next Result'},
|
2012-02-04 08:58:46 +00:00
|
|
|
{key: Ox.UI.symbols['return'], action: 'Edit/Submit'},
|
|
|
|
{key: Ox.UI.symbols.escape, action: 'Cancel/Deselect'}
|
2012-05-24 07:45:33 +00:00
|
|
|
].concat(
|
|
|
|
Ox.filter(self.options.layers.map(function(layer, i) {
|
|
|
|
return layer.editable
|
|
|
|
? {key: i + 1, action: 'Add ' + layer.item}
|
|
|
|
: null;
|
|
|
|
}))
|
|
|
|
).forEach(function(shortcut) {
|
2011-05-20 14:11:42 +00:00
|
|
|
self.$keyboardShortcuts.append(
|
|
|
|
$('<div>').css({display: 'table-row'})
|
|
|
|
.append(
|
|
|
|
$('<div>').css({
|
|
|
|
display: 'table-cell',
|
|
|
|
height: '16px',
|
|
|
|
paddingRight: '16px',
|
|
|
|
//fontWeight: 'bold',
|
|
|
|
textAlign: 'right'
|
|
|
|
})
|
|
|
|
.html(shortcut.key)
|
|
|
|
)
|
|
|
|
.append(
|
|
|
|
$('<div>').css({display: 'table-cell'})
|
|
|
|
.html(shortcut.action)
|
|
|
|
)
|
|
|
|
);
|
2011-06-19 17:48:32 +00:00
|
|
|
});
|
2011-05-20 14:11:42 +00:00
|
|
|
|
2012-04-17 11:59:08 +00:00
|
|
|
self.$menuButton = Ox.MenuButton({
|
2012-05-24 07:45:33 +00:00
|
|
|
items: [].concat(
|
2012-02-19 18:26:57 +00:00
|
|
|
[
|
2012-04-18 07:43:32 +00:00
|
|
|
{id: 'size', title: 'Large Player', checked: self.options.videoSize == 'large'},
|
2012-02-19 18:26:57 +00:00
|
|
|
{},
|
|
|
|
{group: 'resolution', min: 1, max: 1, items: self.resolutions}
|
|
|
|
],
|
|
|
|
self.options.subtitles.length ? [
|
|
|
|
{},
|
|
|
|
{id: 'subtitles', title: 'Show Subtitles', checked: self.options.enableSubtitles}
|
|
|
|
] : [],
|
|
|
|
[
|
2012-04-18 07:43:32 +00:00
|
|
|
{},
|
|
|
|
{id: 'timelines', title: 'Timeline', disabled: true},
|
|
|
|
{group: 'timeline', min: 1, max: 1, items: Ox.map(
|
|
|
|
self.options.timelines,
|
|
|
|
function(timeline) {
|
|
|
|
return Ox.extend({
|
2012-06-15 13:20:07 +00:00
|
|
|
checked: timeline.id == self.options.timeline
|
2012-04-18 07:43:32 +00:00
|
|
|
}, timeline);
|
|
|
|
}
|
|
|
|
)},
|
2012-02-19 18:26:57 +00:00
|
|
|
{},
|
|
|
|
{id: 'downloadVideo', title: 'Download Video...', disabled: !self.options.enableDownload },
|
|
|
|
{id: 'downloadSelection', title: 'Download Selection...', disabled: !self.options.enableDownload},
|
|
|
|
{id: 'embedSelection', title: 'Embed Selection...'}
|
|
|
|
],
|
2012-02-17 09:06:26 +00:00
|
|
|
self.options.enableImport ? [
|
|
|
|
{},
|
2012-02-19 18:26:57 +00:00
|
|
|
{id: 'importAnnotations', title: 'Import Annotations...'}
|
2012-02-17 09:06:26 +00:00
|
|
|
] : [],
|
2012-04-23 09:53:29 +00:00
|
|
|
[
|
2012-02-19 18:26:57 +00:00
|
|
|
{},
|
|
|
|
{id: 'gotoPosterFrame', title: 'Go to Poster Frame'},
|
2012-04-23 09:53:29 +00:00
|
|
|
{id: 'setPosterFrame', title: 'Set Poster Frame', disabled: !self.options.enableSetPosterFrame},
|
2012-02-19 18:26:57 +00:00
|
|
|
{},
|
|
|
|
{id: 'keyboard', title: 'Keyboard Shortcuts...', keyboard: 'h'}
|
|
|
|
]
|
|
|
|
),
|
2012-01-02 19:06:36 +00:00
|
|
|
style: 'square',
|
2011-11-03 12:14:18 +00:00
|
|
|
title: 'set',
|
2012-04-18 07:43:32 +00:00
|
|
|
tooltip: 'Options',
|
2011-05-19 17:58:00 +00:00
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.css({float: 'left'})
|
|
|
|
.bindEvent({
|
2011-05-20 14:11:42 +00:00
|
|
|
click: function(data) {
|
|
|
|
var id = data.id;
|
2012-01-03 07:54:29 +00:00
|
|
|
if (id == 'keyboard') {
|
2012-02-08 10:22:22 +00:00
|
|
|
showKeyboardShortcuts();
|
2012-01-30 22:26:38 +00:00
|
|
|
} else if (id == 'downloadVideo') {
|
2012-02-03 14:43:20 +00:00
|
|
|
that.triggerEvent('downloadvideo');
|
2012-01-30 22:11:05 +00:00
|
|
|
} else if (id == 'downloadSelection') {
|
2012-02-03 14:43:20 +00:00
|
|
|
that.triggerEvent('downloadselection', {
|
2012-01-30 22:11:05 +00:00
|
|
|
'in': self.options['in'],
|
2012-05-26 15:48:19 +00:00
|
|
|
out: self.options.out
|
2012-01-30 22:11:05 +00:00
|
|
|
});
|
|
|
|
} else if (id == 'embedSelection') {
|
2012-02-03 14:43:20 +00:00
|
|
|
that.triggerEvent('embedselection', {
|
2012-01-30 22:11:05 +00:00
|
|
|
'in': self.options['in'],
|
2012-05-26 15:48:19 +00:00
|
|
|
out: self.options.out
|
2012-01-30 22:11:05 +00:00
|
|
|
});
|
2012-02-14 19:06:51 +00:00
|
|
|
} else if (id == 'importAnnotations') {
|
|
|
|
that.triggerEvent('importannotations');
|
2012-02-02 05:15:12 +00:00
|
|
|
} else if (id == 'gotoPosterFrame') {
|
|
|
|
setPosition(self.options.posterFrame);
|
|
|
|
} else if (id == 'setPosterFrame') {
|
|
|
|
self.options.posterFrame = self.options.position;
|
2012-02-16 15:44:46 +00:00
|
|
|
self.$player.forEach(function($player) {
|
|
|
|
$player.options('posterFrame', self.options.posterFrame);
|
|
|
|
});
|
2012-02-02 05:15:12 +00:00
|
|
|
that.triggerEvent('posterframe', {
|
|
|
|
position: self.options.posterFrame
|
|
|
|
});
|
2012-01-03 07:35:22 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
change: function(data) {
|
2012-01-03 07:54:29 +00:00
|
|
|
var id = data.id;
|
2012-02-15 17:29:58 +00:00
|
|
|
if (id == 'resolution') {
|
2012-06-13 08:28:21 +00:00
|
|
|
self.options.resolution = parseInt(data.checked[0].id, 10);
|
2011-12-20 13:45:24 +00:00
|
|
|
self.$player[0].options({resolution: self.options.resolution});
|
2012-02-15 17:29:58 +00:00
|
|
|
} else if (id == 'size') {
|
|
|
|
toggleSize();
|
2012-02-19 18:26:57 +00:00
|
|
|
} else if (id == 'subtitles') {
|
|
|
|
toggleSubtitles();
|
2012-04-18 07:43:32 +00:00
|
|
|
} else if (id == 'timeline') {
|
2012-06-15 13:20:07 +00:00
|
|
|
self.options.timeline = data.checked[0].id;
|
|
|
|
updateTimelines();
|
|
|
|
that.triggerEvent('timeline', {
|
|
|
|
timeline: self.options.timeline
|
|
|
|
});
|
2011-05-20 14:11:42 +00:00
|
|
|
}
|
2012-02-16 12:32:52 +00:00
|
|
|
},
|
|
|
|
hide: function() {
|
|
|
|
that.gainFocus();
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
|
|
|
})
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar);
|
2011-11-03 15:42:41 +00:00
|
|
|
|
2011-05-19 17:58:00 +00:00
|
|
|
self.$clearButton = Ox.Button({
|
2011-10-30 13:57:01 +00:00
|
|
|
disabled: self.options.find === '',
|
2011-05-19 17:58:00 +00:00
|
|
|
style: 'symbol',
|
|
|
|
title: 'close',
|
|
|
|
tooltip: 'Clear',
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.css({float: 'right'})
|
|
|
|
.bindEvent({
|
|
|
|
click: function() {
|
|
|
|
self.$findInput.clearInput();
|
|
|
|
submitFindInput('');
|
|
|
|
}
|
|
|
|
})
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar);
|
2011-05-19 17:58:00 +00:00
|
|
|
|
|
|
|
self.$findInput = Ox.Input({
|
2012-01-31 10:57:09 +00:00
|
|
|
autocomplete: self.words.map(function(word) {
|
|
|
|
return word.value;
|
|
|
|
}),
|
2011-05-20 07:14:24 +00:00
|
|
|
autocompleteReplace: true,
|
2011-05-19 19:03:35 +00:00
|
|
|
autocompleteSelect: true,
|
|
|
|
autocompleteSelectHighlight: true,
|
2011-05-20 06:19:55 +00:00
|
|
|
autocompleteSelectMax: 10,
|
2011-05-19 19:03:35 +00:00
|
|
|
autocompleteSelectSubmit: true,
|
2011-05-19 17:58:00 +00:00
|
|
|
changeOnKeypress: true,
|
|
|
|
placeholder: 'Find...',
|
2011-10-20 13:32:53 +00:00
|
|
|
value: self.options.find,
|
2012-02-01 12:47:59 +00:00
|
|
|
width: 128
|
2011-05-19 17:58:00 +00:00
|
|
|
})
|
2011-10-30 09:49:58 +00:00
|
|
|
.css({float: 'right', background: 'transparent'})
|
2011-05-19 17:58:00 +00:00
|
|
|
.bindEvent({
|
|
|
|
change: function(data) {
|
|
|
|
submitFindInput(data.value, false);
|
|
|
|
},
|
|
|
|
submit: function(data) {
|
|
|
|
submitFindInput(data.value, true);
|
|
|
|
}
|
|
|
|
})
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar);
|
2011-05-19 17:58:00 +00:00
|
|
|
|
|
|
|
self.$nextButton = Ox.Button({
|
|
|
|
disabled: true,
|
|
|
|
style: 'symbol',
|
|
|
|
title: 'arrowRight',
|
|
|
|
tooltip: 'Next Result',
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.css({float: 'right'})
|
|
|
|
.bindEvent({
|
|
|
|
click: function() {
|
2012-02-04 08:58:46 +00:00
|
|
|
selectAnnotation(getNextAnnotation('result', 1));
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
|
|
|
})
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar);
|
2011-05-19 17:58:00 +00:00
|
|
|
|
|
|
|
self.$previousButton = Ox.Button({
|
|
|
|
disabled: true,
|
|
|
|
style: 'symbol',
|
|
|
|
title: 'arrowLeft',
|
|
|
|
tooltip: 'Previous Result',
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.css({float: 'right'})
|
|
|
|
.bindEvent({
|
|
|
|
click: function() {
|
2012-02-04 08:58:46 +00:00
|
|
|
selectAnnotation(getNextAnnotation('result', -1));
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
|
|
|
})
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar);
|
2011-05-19 17:58:00 +00:00
|
|
|
|
|
|
|
self.$results = $('<div>')
|
|
|
|
.css({float: 'right', width: '36px', padding: '2px 4px 0 0', fontSize: '9px', textAlign: 'right', cursor: 'default', opacity: 0.25})
|
|
|
|
.html('0')
|
2012-01-12 10:39:05 +00:00
|
|
|
.appendTo(self.$menubar.$element);
|
2011-05-20 14:11:42 +00:00
|
|
|
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$annotationPanel = Ox.AnnotationPanel({
|
2012-01-13 16:25:47 +00:00
|
|
|
calendarSize: self.options.annotationsCalendarSize,
|
2012-01-17 15:43:46 +00:00
|
|
|
clickLink: self.options.clickLink,
|
2012-01-12 10:39:05 +00:00
|
|
|
editable: true,
|
|
|
|
font: self.options.annotationsFont,
|
2012-02-01 05:21:29 +00:00
|
|
|
highlight: self.options.find,
|
2012-01-12 10:39:05 +00:00
|
|
|
'in': self.options['in'],
|
|
|
|
layers: self.options.layers,
|
2012-01-13 16:25:47 +00:00
|
|
|
mapSize: self.options.annotationsMapSize,
|
2012-01-12 10:39:05 +00:00
|
|
|
out: self.options.out,
|
|
|
|
position: self.options.position,
|
|
|
|
range: self.options.annotationsRange,
|
|
|
|
selected: self.options.selected,
|
2012-01-13 16:25:47 +00:00
|
|
|
showCalendar: self.options.showAnnotationsCalendar,
|
2012-02-20 21:51:08 +00:00
|
|
|
showLayers: Ox.clone(self.options.showLayers),
|
2012-01-13 16:25:47 +00:00
|
|
|
showMap: self.options.showAnnotationsMap,
|
2012-01-12 10:39:05 +00:00
|
|
|
showUsers: self.options.showUsers,
|
2012-01-17 09:25:58 +00:00
|
|
|
sort: self.options.annotationsSort,
|
2012-01-12 10:39:05 +00:00
|
|
|
width: self.options.annotationsSize
|
2011-05-20 14:11:42 +00:00
|
|
|
})
|
2012-01-02 19:06:36 +00:00
|
|
|
.bindEvent({
|
2012-01-12 10:39:05 +00:00
|
|
|
add: function(data) {
|
|
|
|
addAnnotation(data.layer);
|
|
|
|
},
|
|
|
|
annotationsfont: function(data) {
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.annotationsFont = data.font;
|
2012-01-12 10:39:05 +00:00
|
|
|
that.triggerEvent('annotationsfont', data);
|
|
|
|
},
|
|
|
|
annotationsrange: function(data) {
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.annotationsRange = data.range;
|
2012-01-12 10:39:05 +00:00
|
|
|
that.triggerEvent('annotationsrange', data);
|
|
|
|
},
|
|
|
|
annotationssort: function(data) {
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.annotationsSort = data.sort;
|
2012-01-12 10:39:05 +00:00
|
|
|
that.triggerEvent('annotationssort', data);
|
|
|
|
},
|
2012-01-15 15:05:17 +00:00
|
|
|
blur: function(data) {
|
2012-02-16 16:35:59 +00:00
|
|
|
// Only blur if the video editor did not receive the click,
|
|
|
|
// no dialog is open, and no menu was visible
|
|
|
|
if (
|
|
|
|
!self.focused
|
|
|
|
&& !$('.OxDialogLayer').length
|
|
|
|
&& !$('.OxMenuLayer').length
|
|
|
|
) {
|
2012-02-16 11:35:03 +00:00
|
|
|
blurAnnotation();
|
|
|
|
}
|
2012-01-15 15:05:17 +00:00
|
|
|
},
|
|
|
|
change: function(data) {
|
|
|
|
that.triggerEvent('editannotation', data);
|
|
|
|
},
|
|
|
|
define: function(data) {
|
|
|
|
that.triggerEvent('define', data);
|
2012-01-12 10:39:05 +00:00
|
|
|
},
|
2012-01-31 10:57:09 +00:00
|
|
|
edit: function(data) {
|
2012-02-01 05:21:29 +00:00
|
|
|
updateWords('remove');
|
2012-01-12 10:39:05 +00:00
|
|
|
self.editing = true;
|
|
|
|
setTimelineState();
|
|
|
|
},
|
2012-02-16 11:35:03 +00:00
|
|
|
find: function(data) {
|
2012-02-16 12:32:52 +00:00
|
|
|
self.$findInput.options({value: data.value});
|
|
|
|
submitFindInput(data.value, true);
|
|
|
|
},
|
|
|
|
findannotations: function(data) {
|
|
|
|
that.triggerEvent('findannotations', data);
|
2012-02-16 11:35:03 +00:00
|
|
|
},
|
2012-02-16 12:32:52 +00:00
|
|
|
focus: that.gainFocus,
|
2012-01-27 14:29:11 +00:00
|
|
|
info: function(data) {
|
|
|
|
that.triggerEvent('info', data);
|
|
|
|
},
|
2012-02-19 11:06:03 +00:00
|
|
|
open: function() {
|
|
|
|
setPosition(self.options['in']);
|
|
|
|
},
|
2012-02-04 08:58:46 +00:00
|
|
|
remove: removeAnnotation,
|
2012-01-12 19:04:32 +00:00
|
|
|
resize: resizeAnnotations,
|
|
|
|
resizeend: resizeendAnnotations,
|
2012-01-14 11:39:55 +00:00
|
|
|
resizecalendar: function(data) {
|
|
|
|
that.triggerEvent('resizecalendar', data);
|
|
|
|
},
|
|
|
|
resizemap: function(data) {
|
|
|
|
that.triggerEvent('resizemap', data);
|
|
|
|
},
|
2012-02-04 11:44:19 +00:00
|
|
|
select: function(data) {
|
|
|
|
selectAnnotation(data, true);
|
|
|
|
},
|
2012-01-12 10:39:05 +00:00
|
|
|
submit: submitAnnotation,
|
2012-01-12 19:04:32 +00:00
|
|
|
toggle: toggleAnnotations,
|
2012-01-14 11:39:55 +00:00
|
|
|
togglecalendar: function(data) {
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.showAnnotationsCalendar = !data.collapsed;
|
2012-01-14 11:39:55 +00:00
|
|
|
that.triggerEvent('togglecalendar', data);
|
|
|
|
},
|
2012-01-12 19:04:32 +00:00
|
|
|
togglelayer: function(data) {
|
2012-01-12 10:39:05 +00:00
|
|
|
that.triggerEvent('togglelayer', {
|
|
|
|
collapsed: data.collapsed,
|
|
|
|
layer: data.layer
|
2012-01-02 19:06:36 +00:00
|
|
|
});
|
2012-01-14 11:39:55 +00:00
|
|
|
},
|
|
|
|
togglemap: function(data) {
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.showAnnotationsMap = !data.collapsed;
|
2012-01-14 11:39:55 +00:00
|
|
|
that.triggerEvent('togglemap', data);
|
2012-05-26 15:48:19 +00:00
|
|
|
}
|
2012-01-12 10:39:05 +00:00
|
|
|
});
|
2012-01-11 07:52:01 +00:00
|
|
|
|
2012-02-15 22:20:19 +00:00
|
|
|
[
|
2012-02-15 22:41:49 +00:00
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
2012-02-19 11:21:52 +00:00
|
|
|
'b', 'backslash', 'closebracket', 'comma', 'dot',
|
|
|
|
'equal', 'f', 'g', 'h', 'i', 'minus', 'n', 'o',
|
|
|
|
'openbracket', 'p', 'shift_0', 'shift_equal',
|
|
|
|
'shift_g', 'shift_i', 'shift_minus', 'shift_o',
|
|
|
|
'slash', 'space'
|
2012-02-15 22:20:19 +00:00
|
|
|
].forEach(function(key) {
|
|
|
|
key = 'key_' + key;
|
|
|
|
self.$annotationPanel.bindEvent(key, function() {
|
|
|
|
that.triggerEvent(key);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2012-01-04 17:27:32 +00:00
|
|
|
that.setElement(
|
|
|
|
Ox.SplitPanel({
|
|
|
|
elements: [
|
|
|
|
{
|
|
|
|
element: Ox.SplitPanel({
|
|
|
|
elements: [
|
|
|
|
{
|
2012-01-12 10:39:05 +00:00
|
|
|
element: self.$menubar,
|
2012-01-04 17:27:32 +00:00
|
|
|
size: 16
|
|
|
|
},
|
|
|
|
{
|
|
|
|
element: self.$editor
|
|
|
|
}
|
|
|
|
],
|
|
|
|
orientation: 'vertical'
|
|
|
|
})
|
|
|
|
},
|
|
|
|
{
|
|
|
|
collapsed: !self.options.showAnnotations,
|
|
|
|
collapsible: true,
|
2012-01-12 10:39:05 +00:00
|
|
|
element: self.$annotationPanel,
|
2012-01-04 17:27:32 +00:00
|
|
|
resizable: true,
|
2012-01-15 15:05:17 +00:00
|
|
|
resize: [192, 256, 320, 384, 448, 512],
|
2012-01-04 17:27:32 +00:00
|
|
|
size: self.options.annotationsSize,
|
|
|
|
tooltip: self.options.tooltips ? 'annotations' : false
|
|
|
|
}
|
|
|
|
],
|
|
|
|
orientation: 'horizontal'
|
|
|
|
})
|
|
|
|
);
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2011-10-30 13:57:01 +00:00
|
|
|
// we need a timeout so that a chained bindEvent
|
|
|
|
// actually catches the event
|
|
|
|
self.options.find && setTimeout(function() {
|
2012-02-05 01:56:23 +00:00
|
|
|
// only submit if no annotation is selected
|
|
|
|
submitFindInput(self.options.find, !self.options.selected);
|
2011-10-30 13:57:01 +00:00
|
|
|
}, 0);
|
|
|
|
|
2012-01-10 14:49:28 +00:00
|
|
|
function addAnnotation(layer) {
|
|
|
|
that.triggerEvent('addannotation', {
|
|
|
|
'in': self.options['in'],
|
|
|
|
layer: layer,
|
|
|
|
out: self.options.out,
|
|
|
|
value: ''
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function blurAnnotation() {
|
2012-02-01 05:21:29 +00:00
|
|
|
updateWords('add');
|
2012-01-09 20:25:38 +00:00
|
|
|
self.editing = false;
|
2012-01-10 14:49:28 +00:00
|
|
|
setTimelineState();
|
2012-01-15 15:05:17 +00:00
|
|
|
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
|
2012-02-16 11:35:03 +00:00
|
|
|
setTimeout(self.$annotationPanel.blurItem);
|
2012-01-10 14:49:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function editAnnotation() {
|
2012-02-01 05:21:29 +00:00
|
|
|
updateWords('remove');
|
2012-01-10 14:49:28 +00:00
|
|
|
self.editing = true;
|
|
|
|
setTimelineState();
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$annotationPanel.editItem();
|
2012-01-03 10:26:15 +00:00
|
|
|
}
|
|
|
|
|
2011-05-19 17:58:00 +00:00
|
|
|
function find(query) {
|
|
|
|
var results = [];
|
|
|
|
if (query.length) {
|
|
|
|
query = query.toLowerCase();
|
2012-02-04 11:44:19 +00:00
|
|
|
results = self.annotations.filter(function(annotation) {
|
2012-05-27 10:40:02 +00:00
|
|
|
return Ox.decodeHTMLEntities(Ox.stripTags(
|
2012-02-04 11:44:19 +00:00
|
|
|
annotation.value.toLowerCase()
|
|
|
|
)).indexOf(query) > -1;
|
|
|
|
});
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2012-01-10 14:49:28 +00:00
|
|
|
function getAnnotation() {
|
|
|
|
// Get annotation at current position
|
2012-02-04 08:58:46 +00:00
|
|
|
var annotations = self.annotations.filter(function(annotation) {
|
|
|
|
return annotation['in'] <= self.options.position
|
|
|
|
&& annotation.out >= self.options.position
|
|
|
|
}).sort(function(a, b) {
|
2012-01-10 14:49:28 +00:00
|
|
|
var aValue = self.options.position - a['in'],
|
|
|
|
bValue = self.options.position - b['in'],
|
|
|
|
ret = 0;
|
|
|
|
if (aValue < bValue) {
|
|
|
|
ret = -1;
|
|
|
|
} else if (aValue > bValue) {
|
|
|
|
ret = 1;
|
|
|
|
} else if (a.duration < b.duration) {
|
|
|
|
ret = -1
|
|
|
|
} else if (a.duration > b.duration) {
|
|
|
|
ret = 1;
|
|
|
|
} else if (a.value < b.value) {
|
|
|
|
ret = -1
|
|
|
|
} else if (a.value > b.value) {
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
});
|
|
|
|
return annotations.length ? annotations[0] : {id: ''};
|
|
|
|
}
|
|
|
|
|
2012-02-04 08:58:46 +00:00
|
|
|
function getAnnotations() {
|
2012-05-24 07:45:33 +00:00
|
|
|
return Ox.flatten(self.options.layers.map(function(layer) {
|
2012-02-04 08:58:46 +00:00
|
|
|
return layer.items;
|
2012-05-24 07:45:33 +00:00
|
|
|
})).sort(sortAnnotations);
|
2012-02-04 08:58:46 +00:00
|
|
|
}
|
|
|
|
|
2012-02-01 05:21:29 +00:00
|
|
|
function getAnnotationValue(annotationId) {
|
|
|
|
var found = false, value;
|
|
|
|
Ox.forEach(self.options.layers, function(layer, i) {
|
|
|
|
Ox.forEach(layer.items, function(item) {
|
|
|
|
if (item.id == annotationId) {
|
|
|
|
value = item.value;
|
|
|
|
found = true;
|
2012-07-05 08:58:08 +00:00
|
|
|
return false; // break
|
2012-02-01 05:21:29 +00:00
|
|
|
}
|
|
|
|
});
|
2012-07-05 08:58:08 +00:00
|
|
|
if (found) {
|
|
|
|
return false; // break
|
|
|
|
}
|
2012-02-01 05:21:29 +00:00
|
|
|
});
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2012-02-04 08:58:46 +00:00
|
|
|
function getNextAnnotation(type, direction) {
|
|
|
|
// type can be 'annotation' or 'result
|
|
|
|
var annotation,
|
|
|
|
annotations = type == 'annotation' ? self.annotations : self.results,
|
|
|
|
index,
|
|
|
|
position;
|
|
|
|
if (self.options.selected) {
|
|
|
|
index = Ox.getIndexById(annotations, self.options.selected);
|
|
|
|
if (index > -1 && self.options.position == annotations[index]['in']) {
|
|
|
|
annotation = annotations[Ox.mod(index + direction, annotations.length)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!annotation) {
|
|
|
|
position = getNextPosition(type, direction);
|
|
|
|
annotations = annotations.filter(function(annotation) {
|
|
|
|
return annotation['in'] == position;
|
|
|
|
});
|
|
|
|
annotation = annotations[direction == 1 ? 0 : annotations.length - 1];
|
|
|
|
}
|
|
|
|
return annotation;
|
|
|
|
}
|
|
|
|
|
2011-05-19 18:34:53 +00:00
|
|
|
// fixme: why not goToNextPosition()?
|
2011-04-22 22:03:10 +00:00
|
|
|
function getNextPosition(type, direction) {
|
2012-02-04 08:58:46 +00:00
|
|
|
// type can be 'annotation', 'cut' or 'result'
|
2011-04-22 22:03:10 +00:00
|
|
|
var found = false,
|
|
|
|
position = 0,
|
|
|
|
positions;
|
2012-01-10 14:49:28 +00:00
|
|
|
if (type == 'annotation') {
|
2012-02-04 08:58:46 +00:00
|
|
|
positions = self.positions;
|
2012-01-10 14:49:28 +00:00
|
|
|
} else if (type == 'cut') {
|
2012-05-24 07:45:33 +00:00
|
|
|
positions = [0].concat(self.options.cuts, self.options.duration);
|
2012-02-04 08:58:46 +00:00
|
|
|
} else if (type == 'result') {
|
|
|
|
positions = Ox.unique(self.results.map(function(result) {
|
|
|
|
return result['in'];
|
|
|
|
}));
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
direction == -1 && positions.reverse();
|
|
|
|
Ox.forEach(positions, function(v) {
|
2012-02-01 05:21:29 +00:00
|
|
|
if (
|
|
|
|
direction == 1
|
|
|
|
? v > self.options.position
|
|
|
|
: v < self.options.position
|
|
|
|
) {
|
2011-04-22 22:03:10 +00:00
|
|
|
position = v;
|
|
|
|
found = true;
|
2012-07-05 08:58:08 +00:00
|
|
|
return false; // break
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
direction == -1 && positions.reverse();
|
|
|
|
if (!found) {
|
|
|
|
position = positions[direction == 1 ? 0 : positions.length - 1];
|
|
|
|
}
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
2012-02-04 08:58:46 +00:00
|
|
|
function getPositions() {
|
|
|
|
return Ox.unique(self.annotations.map(function(annotation) {
|
|
|
|
return annotation['in'];
|
|
|
|
}));
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getSizes(scrollbarIsVisible) {
|
|
|
|
var scrollbarWidth = Ox.UI.SCROLLBAR_SIZE,
|
2011-11-03 15:42:41 +00:00
|
|
|
contentWidth = self.options.width
|
|
|
|
- (self.options.showAnnotations * self.options.annotationsSize) - 1
|
|
|
|
- (scrollbarIsVisible ? scrollbarWidth : 0),
|
2011-04-22 22:03:10 +00:00
|
|
|
height,
|
|
|
|
lines,
|
|
|
|
size = {
|
|
|
|
player: [],
|
|
|
|
timeline: []
|
|
|
|
},
|
|
|
|
width, widths;
|
2012-01-09 20:25:38 +00:00
|
|
|
function getHeight() {
|
|
|
|
return size.player[0].height + self.controlsHeight
|
|
|
|
+ size.timeline[0].height + lines * 16
|
|
|
|
+ (lines + 3) * self.margin;
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
if (self.options.videoSize == 'small') {
|
|
|
|
width = 0;
|
2012-06-25 14:43:03 +00:00
|
|
|
widths = Ox.splitInt(contentWidth - 4 * self.margin, 3);
|
2011-04-22 22:03:10 +00:00
|
|
|
[1, 0, 2].forEach(function(v, i) {
|
|
|
|
size.player[v] = {
|
|
|
|
left: (i + 0.5) * self.margin + width,
|
|
|
|
top: self.margin / 2,
|
|
|
|
width: widths[i],
|
2011-08-19 14:44:03 +00:00
|
|
|
height: Math.round(widths[1] / self.options.videoRatio)
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
width += widths[i];
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
size.player[0] = {
|
|
|
|
left: self.margin / 2,
|
|
|
|
top: self.margin / 2,
|
2012-05-26 15:48:19 +00:00
|
|
|
width: Math.round((contentWidth - 3 * self.margin + (self.controlsHeight + self.margin) / 2 * self.options.videoRatio) * 2/3)
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-08-19 14:44:03 +00:00
|
|
|
size.player[0].height = Math.round(size.player[0].width / self.options.videoRatio);
|
2011-04-22 22:03:10 +00:00
|
|
|
size.player[1] = {
|
|
|
|
left: size.player[0].left + size.player[0].width + self.margin,
|
|
|
|
top: size.player[0].top,
|
|
|
|
width: contentWidth - 3 * self.margin - size.player[0].width
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-08-19 14:44:03 +00:00
|
|
|
size.player[1].height = Math.ceil(size.player[1].width / self.options.videoRatio);
|
2011-04-22 22:03:10 +00:00
|
|
|
size.player[2] = {
|
|
|
|
left: size.player[1].left,
|
|
|
|
top: size.player[0].top + size.player[1].height + self.controlsHeight + self.margin,
|
|
|
|
width: size.player[1].width,
|
|
|
|
height: size.player[0].height - size.player[1].height - self.controlsHeight - self.margin
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
size.timeline[0] = {
|
|
|
|
left: self.margin / 2,
|
|
|
|
top: size.player[0].height + self.controlsHeight + 1.5 * self.margin,
|
|
|
|
width: contentWidth - 2 * self.margin,
|
|
|
|
height: 64
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
size.timeline[1] = {
|
|
|
|
left: size.timeline[0].left,
|
|
|
|
top: size.timeline[0].top + size.timeline[0].height + self.margin,
|
|
|
|
width: size.timeline[0].width
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
lines = Math.ceil(self.options.duration / size.timeline[1].width);
|
|
|
|
height = getHeight();
|
|
|
|
self.$editor.css({
|
2011-05-19 17:58:00 +00:00
|
|
|
overflowY: (scrollbarIsVisible && height <= self.options.height - 16) ? 'scroll' : 'auto'
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2011-05-19 17:58:00 +00:00
|
|
|
return (!scrollbarIsVisible && height > self.options.height - 16) ? getSizes(true) : size;
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-31 10:57:09 +00:00
|
|
|
function getWords() {
|
|
|
|
var words = [];
|
|
|
|
Ox.forEach(Ox.count(Ox.words(
|
2012-02-04 11:44:19 +00:00
|
|
|
self.annotations.map(function(annotation) {
|
2012-05-27 10:40:02 +00:00
|
|
|
return Ox.decodeHTMLEntities(
|
|
|
|
Ox.stripTags(annotation.value.toLowerCase())
|
|
|
|
);
|
2012-02-04 11:44:19 +00:00
|
|
|
}).join(' ')
|
2012-01-31 10:57:09 +00:00
|
|
|
)), function(count, value) {
|
|
|
|
words.push({count: count, value: value});
|
|
|
|
})
|
|
|
|
return words.sort(function(a, b) {
|
|
|
|
return b.count - a.count;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
function goToPoint(point) {
|
2011-05-19 10:18:39 +00:00
|
|
|
setPosition(self.options[point]);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-02-19 07:21:40 +00:00
|
|
|
function isEditable() {
|
|
|
|
var annotation = Ox.getObjectById(self.annotations, self.options.selected);
|
|
|
|
return annotation && annotation.editable;
|
|
|
|
}
|
|
|
|
|
2011-04-22 22:03:10 +00:00
|
|
|
function movePositionBy(sec) {
|
2011-05-19 10:18:39 +00:00
|
|
|
setPosition(Ox.limit(self.options.position + sec, 0, self.options.duration));
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function movePositionTo(type, direction) {
|
2011-05-19 10:18:39 +00:00
|
|
|
setPosition(getNextPosition(type, direction));
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function playInToOut() {
|
|
|
|
self.$player[0].playInToOut();
|
|
|
|
}
|
|
|
|
|
2012-02-04 08:58:46 +00:00
|
|
|
function removeAnnotation(data) {
|
|
|
|
var layer = Ox.getObjectById(self.options.layers, data.layer),
|
|
|
|
index = Ox.getIndexById(layer.items, data.id);
|
2012-02-18 07:22:31 +00:00
|
|
|
// deselect event will have fired before
|
|
|
|
self.options.selected = data.id;
|
2012-02-04 08:58:46 +00:00
|
|
|
updateWords('remove');
|
2012-02-18 07:22:31 +00:00
|
|
|
self.options.selected = '';
|
2012-02-04 08:58:46 +00:00
|
|
|
layer.items.splice(index, 1);
|
|
|
|
self.annotations = getAnnotations();
|
|
|
|
self.positions = getPositions();
|
2012-02-04 11:44:19 +00:00
|
|
|
self.options.find && submitFindInput(self.options.find);
|
2012-02-04 08:58:46 +00:00
|
|
|
self.editing = false;
|
|
|
|
setTimelineState();
|
2012-02-19 08:59:27 +00:00
|
|
|
self.$annotationPanel.removeItem();
|
2012-02-04 08:58:46 +00:00
|
|
|
that.triggerEvent('removeannotation', data);
|
|
|
|
}
|
|
|
|
|
2011-09-17 17:39:38 +00:00
|
|
|
function resizeAnnotations(data) {
|
|
|
|
self.options.annotationsSize = data.size;
|
2011-04-22 22:03:10 +00:00
|
|
|
setSizes();
|
2012-01-12 19:04:32 +00:00
|
|
|
self.$annotationPanel.options({width: data.size});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-02 19:06:36 +00:00
|
|
|
function resizeendAnnotations(data) {
|
2012-01-12 19:04:32 +00:00
|
|
|
that.triggerEvent('annotationssize', {size: data.size});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-02-04 11:44:19 +00:00
|
|
|
function selectAnnotation(data, stayAtPosition) {
|
2012-01-10 14:49:28 +00:00
|
|
|
if (Ox.isUndefined(data)) {
|
2012-01-12 10:39:05 +00:00
|
|
|
// doubleclick on small timeline
|
2012-01-10 14:49:28 +00:00
|
|
|
data = getAnnotation();
|
2012-01-12 19:04:32 +00:00
|
|
|
} else if (!data.id) {
|
|
|
|
that.gainFocus();
|
2012-01-10 14:49:28 +00:00
|
|
|
}
|
2012-02-01 05:21:29 +00:00
|
|
|
// FIXME
|
|
|
|
// self.editing = false;
|
2012-02-04 11:44:19 +00:00
|
|
|
if (data.id) {
|
|
|
|
if (!stayAtPosition
|
|
|
|
|| self.options.annotationsRange != 'position'
|
|
|
|
|| self.options.position < data['in']
|
|
|
|
|| self.options.position > data.out
|
|
|
|
) {
|
|
|
|
setPosition(data['in']);
|
|
|
|
// if annotationsRange is 'position',
|
|
|
|
// this may cause a deselect
|
|
|
|
}
|
2012-01-15 15:05:17 +00:00
|
|
|
setPoint('in', data['in'], true);
|
|
|
|
setPoint('out', data.out, true);
|
2012-01-04 17:27:32 +00:00
|
|
|
}
|
2012-02-04 11:44:19 +00:00
|
|
|
self.options.selected = data.id;
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$annotationPanel.options({selected: self.options.selected});
|
2012-01-10 14:49:28 +00:00
|
|
|
setTimelineState();
|
2012-02-01 12:47:59 +00:00
|
|
|
that.triggerEvent('select', {id: self.options.selected});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-10 14:49:28 +00:00
|
|
|
function selectCut() {
|
|
|
|
var points = {
|
|
|
|
'in': Ox.last(self.options.cuts),
|
|
|
|
out: self.options.duration
|
|
|
|
};
|
|
|
|
Ox.forEach(self.options.cuts, function(cut, i) {
|
|
|
|
if (cut > self.options.position) {
|
|
|
|
points = {
|
|
|
|
'in': i ? self.options.cuts[i - 1] : 0,
|
|
|
|
out: cut - 1 / self.options.fps
|
|
|
|
};
|
2012-07-05 08:58:08 +00:00
|
|
|
return false; // break
|
2012-01-10 14:49:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
setPoint('in', points['in']);
|
|
|
|
setPoint('out', points.out);
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-15 15:05:17 +00:00
|
|
|
function setPoint(point, position, keepSelected) {
|
2011-05-18 18:30:58 +00:00
|
|
|
var otherPoint = point == 'in' ? 'out' : 'in';
|
2011-05-19 10:18:39 +00:00
|
|
|
self.options[point] = position;
|
2012-01-15 15:05:17 +00:00
|
|
|
if (self.options.selected && !self.editing && !keepSelected) {
|
|
|
|
selectAnnotation({id: ''});
|
2012-01-04 17:27:32 +00:00
|
|
|
}
|
2011-05-18 18:30:58 +00:00
|
|
|
self.$player.forEach(function($player) {
|
|
|
|
$player.options(point, self.options[point]);
|
|
|
|
});
|
2011-05-18 16:00:29 +00:00
|
|
|
self.$player[point == 'in' ? 1 : 2].options({
|
|
|
|
position: self.options[point]
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2011-05-18 16:00:29 +00:00
|
|
|
self.$timeline.forEach(function($timeline) {
|
|
|
|
$timeline.options(point, self.options[point]);
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2011-05-18 16:00:29 +00:00
|
|
|
if (self.options['in'] > self.options.out) {
|
2012-01-15 15:05:17 +00:00
|
|
|
setPoint(point == 'in' ? 'out' : 'in', position, keepSelected);
|
|
|
|
} else {
|
|
|
|
self.$annotationPanel.options({
|
|
|
|
'in': self.options['in'],
|
|
|
|
out: self.options.out
|
|
|
|
});
|
|
|
|
that.triggerEvent('points', {
|
2012-01-09 20:25:38 +00:00
|
|
|
'in': self.options['in'],
|
2012-04-22 08:54:44 +00:00
|
|
|
out: self.options.out,
|
|
|
|
position: self.options.position
|
2012-01-09 20:25:38 +00:00
|
|
|
});
|
2012-02-05 02:07:22 +00:00
|
|
|
if (self.editing && self.options.selected[0] != '_') {
|
|
|
|
that.triggerEvent('editannotation', {
|
|
|
|
id: self.options.selected,
|
|
|
|
'in': self.options['in'],
|
|
|
|
out: self.options.out,
|
|
|
|
value: $('.OxEditableElement input:visible').val()
|
|
|
|
});
|
|
|
|
}
|
2012-01-09 20:25:38 +00:00
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-02 19:06:36 +00:00
|
|
|
function setPosition(position, playing) {
|
2012-06-13 08:28:21 +00:00
|
|
|
var minute = Math.floor(position / 60),
|
|
|
|
previousMinute = Math.floor(self.options.position / 60);
|
2011-05-19 10:18:39 +00:00
|
|
|
self.options.position = position;
|
2012-01-02 19:06:36 +00:00
|
|
|
!playing && self.$player[0].options({
|
2011-04-22 22:03:10 +00:00
|
|
|
position: self.options.position
|
|
|
|
});
|
2012-01-02 19:06:36 +00:00
|
|
|
self.$timeline.forEach(function($timeline) {
|
|
|
|
$timeline.options({
|
|
|
|
position: self.options.position
|
|
|
|
});
|
|
|
|
});
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$annotationPanel.options({
|
|
|
|
position: self.options.position
|
2011-04-22 22:03:10 +00:00
|
|
|
});
|
2012-03-25 21:45:39 +00:00
|
|
|
if (!playing || minute != previousMinute) {
|
|
|
|
that.triggerEvent('position', {
|
2012-03-25 21:49:36 +00:00
|
|
|
position: !playing ? self.options.position : minute * 60
|
2012-03-25 21:45:39 +00:00
|
|
|
});
|
|
|
|
}
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function setSizes() {
|
|
|
|
self.sizes = getSizes();
|
2011-05-18 16:00:29 +00:00
|
|
|
self.$player.forEach(function($player, i) {
|
|
|
|
$player.options({
|
2011-04-22 22:03:10 +00:00
|
|
|
height: self.sizes.player[i].height,
|
|
|
|
width: self.sizes.player[i].width
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
left: self.sizes.player[i].left + 'px',
|
|
|
|
top: self.sizes.player[i].top + 'px'
|
|
|
|
});
|
|
|
|
});
|
2011-05-18 16:00:29 +00:00
|
|
|
self.$timeline.forEach(function($timeline, i) {
|
|
|
|
$timeline.options({
|
2011-04-22 22:03:10 +00:00
|
|
|
width: self.sizes.timeline[i].width
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
left: self.sizes.timeline[i].left + 'px',
|
|
|
|
top: self.sizes.timeline[i].top + 'px'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-02-08 10:22:22 +00:00
|
|
|
function showKeyboardShortcuts() {
|
|
|
|
var dialog = Ox.Dialog({
|
|
|
|
buttons: [
|
|
|
|
Ox.Button({id: 'close', title: 'Close'})
|
|
|
|
.bindEvent({click: function() { dialog.close(); }})
|
|
|
|
],
|
|
|
|
content: self.$keyboardShortcuts,
|
|
|
|
height: 384,
|
|
|
|
keys: {enter: 'close', escape: 'close'},
|
|
|
|
title: 'Keyboard Shortcuts',
|
|
|
|
width: 256
|
|
|
|
}).open();
|
|
|
|
}
|
|
|
|
|
2012-01-10 14:49:28 +00:00
|
|
|
function setTimelineState() {
|
2012-01-09 20:25:38 +00:00
|
|
|
self.$timeline[1].options({
|
|
|
|
state: self.editing ? 'editing'
|
2012-02-19 07:21:40 +00:00
|
|
|
: isEditable() ? 'editable'
|
2012-01-09 20:25:38 +00:00
|
|
|
: self.options.selected ? 'selected'
|
|
|
|
: 'default'
|
|
|
|
});
|
2012-02-04 08:58:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function sortAnnotations(a, b) {
|
|
|
|
var ret = 0;
|
|
|
|
if (a['in'] < b['in']) {
|
|
|
|
ret = -1;
|
|
|
|
} else if (a['in'] > b['in']) {
|
|
|
|
ret = 1;
|
|
|
|
} else if (a.out < b.out) {
|
|
|
|
ret = -1;
|
|
|
|
} else if (a.out > b.out) {
|
|
|
|
ret = 1;
|
|
|
|
} else if (a.value < b.value) {
|
|
|
|
ret = -1;
|
|
|
|
} else if (a.value > b.value) {
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
return ret;
|
2012-01-04 17:27:32 +00:00
|
|
|
}
|
|
|
|
|
2012-01-10 14:49:28 +00:00
|
|
|
function submitAnnotation(data) {
|
2012-02-04 08:58:46 +00:00
|
|
|
self.annotations = getAnnotations();
|
|
|
|
self.positions = getPositions();
|
2012-02-01 05:21:29 +00:00
|
|
|
updateWords('add');
|
2012-02-04 11:44:19 +00:00
|
|
|
self.options.find && submitFindInput(self.options.find);
|
2012-01-10 14:49:28 +00:00
|
|
|
self.editing = false;
|
|
|
|
setTimelineState();
|
2012-01-15 15:05:17 +00:00
|
|
|
if (
|
2012-02-04 08:58:46 +00:00
|
|
|
self.options.annotationsRange == 'position'
|
|
|
|
&& (
|
2012-01-15 15:05:17 +00:00
|
|
|
self.options.position < self.options['in']
|
|
|
|
|| self.options.position > self.options.out
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
setPosition(self.options['in']);
|
|
|
|
}
|
2012-01-10 14:49:28 +00:00
|
|
|
data['in'] = self.options['in'];
|
|
|
|
data.out = self.options.out;
|
|
|
|
that.triggerEvent('editannotation', data);
|
|
|
|
}
|
|
|
|
|
2011-05-19 17:58:00 +00:00
|
|
|
function submitFindInput(value, hasPressedEnter) {
|
|
|
|
self.options.find = value;
|
|
|
|
self.results = find(self.options.find);
|
2011-12-23 06:08:41 +00:00
|
|
|
self.$results
|
|
|
|
.css({opacity: self.results.length ? 1 : 0.25})
|
|
|
|
.html(self.results.length);
|
2011-05-19 17:58:00 +00:00
|
|
|
self.$previousButton.options({
|
|
|
|
disabled: self.results.length <= 1
|
|
|
|
});
|
|
|
|
self.$nextButton.options({
|
|
|
|
disabled: self.results.length <= 1
|
|
|
|
});
|
|
|
|
self.$clearButton.options({
|
|
|
|
disabled: !self.options.find
|
|
|
|
});
|
2011-12-23 06:08:41 +00:00
|
|
|
self.$player.forEach(function($player) {
|
|
|
|
$player.options({find: self.options.find});
|
2011-05-19 17:58:00 +00:00
|
|
|
});
|
2011-12-23 06:08:41 +00:00
|
|
|
self.$timeline.forEach(function($timeline) {
|
|
|
|
$timeline.options({find: self.options.find});
|
2011-05-19 17:58:00 +00:00
|
|
|
});
|
2011-12-23 06:08:41 +00:00
|
|
|
self.$timeline[1].options({results: self.results});
|
2011-05-19 17:58:00 +00:00
|
|
|
if (hasPressedEnter) {
|
2011-10-30 09:49:58 +00:00
|
|
|
that.triggerEvent('find', {find: self.options.find});
|
2011-10-30 13:57:01 +00:00
|
|
|
if (self.results.length) {
|
2012-02-04 08:58:46 +00:00
|
|
|
selectAnnotation(getNextAnnotation('result', 1));
|
2012-02-19 18:51:53 +00:00
|
|
|
that.gainFocus();
|
2011-10-30 13:57:01 +00:00
|
|
|
} else {
|
2011-12-18 09:44:11 +00:00
|
|
|
self.$findInput.focusInput(true);
|
2011-10-30 13:57:01 +00:00
|
|
|
}
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
2012-02-16 12:46:57 +00:00
|
|
|
self.$annotationPanel.options({highlight: self.options.find});
|
2011-05-19 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2011-09-17 17:39:38 +00:00
|
|
|
function toggleAnnotations(data) {
|
2011-04-22 22:03:10 +00:00
|
|
|
self.options.showAnnotations = !data.collapsed;
|
|
|
|
setSizes();
|
2011-08-17 19:34:34 +00:00
|
|
|
that.triggerEvent('toggleannotations', {
|
|
|
|
showAnnotations: self.options.showAnnotations
|
2011-08-17 15:20:17 +00:00
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2011-05-18 16:00:29 +00:00
|
|
|
function toggleMuted() {
|
|
|
|
self.$player[0].toggleMuted();
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2011-05-18 16:00:29 +00:00
|
|
|
function togglePaused() {
|
|
|
|
self.$player[0].togglePaused();
|
2011-09-26 19:45:36 +00:00
|
|
|
self.$player[0].options('paused') && that.triggerEvent('position', {
|
2012-01-11 11:54:58 +00:00
|
|
|
position: self.$player[0].options('position')
|
2011-09-26 19:45:36 +00:00
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
}
|
|
|
|
|
2011-05-19 17:58:00 +00:00
|
|
|
function toggleSize() {
|
2012-02-15 20:21:17 +00:00
|
|
|
self.options.videoSize = self.options.videoSize == 'small'
|
|
|
|
? 'large' : 'small';
|
2011-04-22 22:03:10 +00:00
|
|
|
setSizes();
|
2012-04-18 07:57:59 +00:00
|
|
|
self.$menuButton[
|
|
|
|
self.options.videoSize == 'small' ? 'uncheckItem' : 'checkItem'
|
|
|
|
]('size');
|
2012-02-15 17:29:58 +00:00
|
|
|
self.$player[0].options({
|
|
|
|
sizeIsLarge: self.options.videoSize == 'large'
|
|
|
|
});
|
2011-04-22 22:03:10 +00:00
|
|
|
that.triggerEvent('togglesize', {
|
|
|
|
size: self.options.videoSize
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-02-19 18:26:57 +00:00
|
|
|
function toggleSubtitles() {
|
|
|
|
self.options.enableSubtitles = !self.options.enableSubtitles;
|
|
|
|
self.$player.forEach(function($player) {
|
|
|
|
$player.options({
|
|
|
|
enableSubtitles: self.options.enableSubtitles
|
|
|
|
});
|
|
|
|
});
|
|
|
|
self.$timeline.forEach(function($timeline) {
|
|
|
|
$timeline.options({
|
|
|
|
subtitles: self.options.enableSubtitles ? self.options.subtitles : []
|
|
|
|
});
|
|
|
|
});
|
|
|
|
that.triggerEvent('subtitles', {
|
|
|
|
subtitles: self.options.enableSubtitles
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-06-15 13:20:07 +00:00
|
|
|
function updateTimelines() {
|
|
|
|
self.$timeline[0].options({type: self.options.timeline});
|
|
|
|
self.$timeline[1].options({type: self.options.timeline});
|
|
|
|
}
|
|
|
|
|
2012-02-01 05:21:29 +00:00
|
|
|
function updateWords(action) {
|
2012-02-16 11:35:03 +00:00
|
|
|
// action can be 'add' or 'remove'
|
2012-02-01 05:21:29 +00:00
|
|
|
var words = [];
|
|
|
|
Ox.forEach(Ox.count(Ox.words(
|
|
|
|
getAnnotationValue(self.options.selected)
|
|
|
|
)), function(count, value) {
|
|
|
|
words.push({count: count, value: value});
|
|
|
|
});
|
|
|
|
words.forEach(function(word) {
|
2012-05-21 06:41:57 +00:00
|
|
|
var index = Ox.indexOf(self.words, function(w) {
|
|
|
|
return w.value === word.value;
|
|
|
|
});
|
2012-02-01 05:21:29 +00:00
|
|
|
if (action == 'add') {
|
|
|
|
if (index == -1) {
|
|
|
|
self.words.push({count: 1, value: word.value});
|
|
|
|
} else {
|
|
|
|
self.words[index].count++;
|
|
|
|
}
|
2012-02-04 08:58:46 +00:00
|
|
|
} else if (index > -1) {
|
|
|
|
// index is -1 when removing an annotation by editing
|
|
|
|
// (which removes the words) and clearing its value
|
2012-02-01 05:21:29 +00:00
|
|
|
if (self.words[index].count == 1) {
|
|
|
|
self.words.splice(index, 1);
|
|
|
|
} else {
|
|
|
|
self.words[index].count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
self.words.sort(function(a, b) {
|
|
|
|
return b.count - a.count;
|
|
|
|
});
|
|
|
|
self.$findInput.options({
|
|
|
|
autocomplete: self.words.map(function(word) {
|
|
|
|
return word.value;
|
|
|
|
})
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-09-14 14:34:33 +00:00
|
|
|
/*@
|
|
|
|
addAnnotation <f> add annotation
|
|
|
|
(layer, item) -> <o> add annotation to layer
|
|
|
|
layer <s> layer id
|
2012-01-12 10:39:05 +00:00
|
|
|
annotation <o> annotation to add
|
2011-09-14 14:34:33 +00:00
|
|
|
@*/
|
2012-01-12 10:39:05 +00:00
|
|
|
that.addAnnotation = function(layer, annotation) {
|
2012-01-15 15:05:17 +00:00
|
|
|
// called from addannotation callback
|
2012-01-12 10:39:05 +00:00
|
|
|
self.$annotationPanel.addItem(layer, annotation);
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2011-04-22 22:03:10 +00:00
|
|
|
|
2012-05-21 10:38:18 +00:00
|
|
|
/*@
|
|
|
|
updateAnnotation <f> updateAnnotation
|
|
|
|
(id, annotation) -> <o> update annotation with id
|
|
|
|
@*/
|
2012-01-31 10:57:09 +00:00
|
|
|
that.updateAnnotation = function(id, annotation) {
|
2012-01-15 15:05:17 +00:00
|
|
|
// called from editannotation callback
|
2012-02-04 08:58:46 +00:00
|
|
|
self.options.selected = annotation.id; // fixme: needed?
|
2012-01-31 10:57:09 +00:00
|
|
|
self.$annotationPanel.updateItem(id, annotation);
|
2012-02-17 16:13:08 +00:00
|
|
|
};
|
2012-01-15 15:05:17 +00:00
|
|
|
|
2011-09-14 14:34:33 +00:00
|
|
|
/*@
|
2012-01-03 10:26:15 +00:00
|
|
|
removeAnnotation <f> remove annotation
|
2011-09-14 14:34:33 +00:00
|
|
|
(layer, ids) -> <o> remove annotation from layer
|
|
|
|
layer <s> layer id
|
|
|
|
ids <a> array of item ids to remove
|
|
|
|
@*/
|
2012-01-12 10:39:05 +00:00
|
|
|
/*
|
2012-01-03 10:26:15 +00:00
|
|
|
that.removeAnnotation = function(layer, id) {
|
2012-01-04 08:11:05 +00:00
|
|
|
var i = Ox.getIndexById(self.options.layers, layer);
|
2012-01-03 10:26:15 +00:00
|
|
|
self.$annotationPanel[i].removeItem(id);
|
2011-06-19 17:48:32 +00:00
|
|
|
};
|
2012-01-12 10:39:05 +00:00
|
|
|
*/
|
2011-04-22 22:03:10 +00:00
|
|
|
|
|
|
|
return that;
|
|
|
|
|
|
|
|
};
|