')
+ .css({
+ left: self.center + 'px'
+ })
+ .appendTo(that.$element)
+
+ $.each(self.options.subtitles, function(i, v) {
+ self.$subtitles[i] = $('
')
+ .addClass('OxSubtitle' + (self.options.matches.indexOf(i) > -1 ? ' OxHighlight' : ''))
+ .css({
+ left: (v['in'] * self.fps) + 'px',
+ width: (((v['out'] - v['in']) * self.fps) - 4) + 'px'
+ })
+ .html(Ox.highlight(v.text, self.options.find))
+ .appendTo(self.$timeline)
+ });
+
+ $.each(self.options.cuts, function(i, v) {
+ self.$cuts[i] = $('
')
+ .addClass('OxCut')
+ .attr({
+ src: '/static/oxjs/build/png/ox.ui/videoMarkerCut.png'
+ })
+ .css({
+ left: (v * self.fps) + 'px'
+ })
+ .appendTo(self.$timeline)
+ });
+
+ self.$markerPosition = $('
')
+ .addClass('OxMarkerPosition')
+ .attr({
+ src: '/static/oxjs/build/png/ox.ui/videoMarkerPlay.png'
+ })
+ .appendTo(that.$element);
+ setMarker();
+
+ $.each(['In', 'Out'], function(i, v) {
+ self.$markerPoint[i] = $('
')
+ .addClass('OxMarkerPoint' + v)
+ .attr({
+ src: '/static/oxjs/build/png/ox.ui/videoMarker' + v + '.png'
+ })
+ .appendTo(self.$timeline);
+ setMarkerPoint(i);
+ });
+
+ setWidth();
+ setPosition();
+
+ function click(event, e) {
+ self.options.position = Ox.limit(
+ self.options.position + (e.clientX - that.$element.offset().left - self.center) / self.fps,
+ 0, self.options.duration
+ );
+ setPosition();
+ triggerChangeEvent();
+ }
+
+ function dragstart(event, e) {
+ self.drag = {x: e.clientX};
+ }
+
+ function drag(event, e) {
+ self.options.position = Ox.limit(
+ self.options.position + (self.drag.x - e.clientX) / self.fps,
+ 0, self.options.duration
+ );
+ self.drag.x = e.clientX;
+ setPosition();
+ triggerChangeEvent();
+ }
+
+ function mouseleave(e) {
+ self.clientX = 0;
+ self.clientY = 0;
+ self.$tooltip.hide();
+ }
+
+ function mousemove(e) {
+ self.clientX = e.clientX;
+ self.clientY = e.clientY;
+ updateTooltip();
+ }
+
+ function setMarkerPoint(i) {
+ self.$markerPoint[i].css({
+ left: (self.options.points[i] * self.fps) + 'px'
+ });
+ }
+
+ function setMarker() {
+ self.$markerPosition.css({
+ left: (self.center - 4) + 'px',
+ });
+ }
+
+ function setPosition() {
+ self.tile = parseInt(self.options.position * self.fps / self.tileWidth);
+ self.$timeline.css({
+ marginLeft: (-self.options.position * self.fps) + 'px'
+ });
+ $.each(Ox.range(Math.max(self.tile - 1, 0), Math.min(self.tile + 2, self.tiles)), function(i, v) {
+ if (!self.$tiles[v]) {
+ self.$tiles[v] = $('
')
+ .attr({
+ src: '/' + self.options.videoId + '/timelines/' +
+ (self.options.style == 'default' ? 'timeline' : self.options.style) + '.64.' + v + '.png'
+ })
+ .css({
+ left: (v * self.tileWidth) + 'px'
+ })
+ .appendTo(self.$timeline);
+ }
+ });
+ if (self.clientX && self.clientY) {
+ updateTooltip();
+ }
+ }
+
+ function setWidth() {
+ self.center = parseInt(self.options.width / 2);
+ that.css({
+ width: self.options.width + 'px'
+ });
+ self.$timeline.css({
+ left: self.center + 'px'
+ });
+ setMarker();
+ }
+
+ function triggerChangeEvent() {
+ that.triggerEvent('change', {
+ position: self.options.position
+ });
+ }
+
+ function updateTooltip() {
+ var position = self.options.position + (self.clientX - that.offset().left - self.center) / self.fps;
+ if (position >= 0 && position <= self.options.duration) {
+ self.$tooltip
+ .options({
+ title: Ox.formatDuration(position, 3)
+ })
+ .show(self.clientX, self.clientY);
+ } else {
+ self.$tooltip.hide();
+ }
+ }
+
+ self.onChange = function(key, value) {
+ if (key == 'points') {
+ setMarkerPoint(0);
+ setMarkerPoint(1);
+ } else if (key == 'position') {
+ setPosition();
+ } else if (key == 'width') {
+ setWidth();
+ }
+ };
+
+ return that;
+
+ };
+
+ Ox.SmallTimeline = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element('div', self)
+ .defaults({
+ duration: 0,
+ find: '',
+ matches: [],
+ points: [0, 0],
+ position: 0,
+ subtitles: [],
+ videoId: '',
+ width: 0
+ })
+ .options(options || {})
+ .addClass('OxTimelineSmall')
+ .mousedown(mousedown)
+ .mouseleave(mouseleave)
+ .mousemove(mousemove)
+ .bindEvent({
+ drag: function(event, e) {
+ mousedown(e);
+ }
+ });
+
+ $.extend(self, {
+ $images: [],
+ $markerPoint: [],
+ $subtitles: [],
+ hasSubtitles: self.options.subtitles.length,
+ height: 16,
+ margin: 8
+ });
+
+ that.css({
+ width: (self.options.width + self.margin) + 'px',
+ height: (self.height + self.margin) + 'px'
+ });
+
+ self.$line = $('
')
+ .attr({
+ src: '/' + self.options.videoId + '/timelines/timeline.16.0.png'
+ })
+ .css({
+ position: 'absolute',
+ left: '4px',
+ width: self.options.width,
+ height: '16px'
+ })
+ .appendTo(that.$element);
+
+ self.$markerPosition = $('
')
+ .addClass('OxMarkerPosition')
+ .attr({
+ src: '/static/oxjs/build/png/ox.ui/videoMarkerPlay.png'
+ })
+ .css({
+ position: 'absolute',
+ width: '9px',
+ height: '5px',
+ zIndex: 10
+ })
+ .appendTo(that.$element);
+
+ setPosition();
+
+ $.each(['in', 'out'], function(i, v) {
+ var titleCase = Ox.toTitleCase(v);
+ self.$markerPoint[i] = $('
')
+ .addClass('OxMarkerPoint' + titleCase)
+ .attr({
+ src: '/static/oxjs/build/png/ox.ui/videoMarker' + titleCase + '.png'
+ })
+ .appendTo(that.$element);
+ setMarkerPoint(i);
+ });
+
+ function getPosition(e) {
+ //FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
+ return (e.offsetX ? e.offsetX : e.clientX - $(e.target).offset().left);
+ }
+
+ function getSubtitle(position) {
+ var subtitle = null;
+ $.each(self.options.subtitles, function(i, v) {
+ if (v['in'] <= position && v['out'] >= position) {
+ subtitle = v;
+ return false;
+ }
+ });
+ return subtitle;
+ }
+
+ function mousedown(e) {
+ var $target = $(e.target);
+ if (
+ $target.hasClass('OxTimelineSmallImage') ||
+ $target.hasClass('OxTimelineSmallSubtitles')
+ ) {
+ self.options.position = getPosition(e);
+ setPosition();
+ that.triggerEvent('change', {
+ position: self.options.position
+ });
+ }
+ e.preventDefault();
+ }
+
+ function mouseleave(e) {
+ self.$tooltip && self.$tooltip.hide();
+ }
+
+ function mousemove(e) {
+ var $target = $(e.target),
+ position,
+ subtitle;
+ if (
+ $target.hasClass('OxTimelineSmallImage') ||
+ $target.hasClass('OxTimelineSmallSubtitles')
+ ) {
+ position = getPosition(e),
+ subtitle = getSubtitle(position);
+ self.$tooltip = new Ox.Tooltip({
+ title: subtitle ?
+ '
' +
+ Ox.highlight(subtitle.text, self.options.find).replace(/\n/g, '
') + '' +
+ Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
+ Ox.formatDuration(position, 3)
+ })
+ .css({
+ textAlign: 'center'
+ })
+ .show(e.clientX, e.clientY);
+ } else {
+ self.$tooltip && self.$tooltip.hide();
+ }
+
+ }
+
+ function setMarker() {
+ self.$markerPosition
+ .css({
+ left: (self.options.position % self.options.width) + 'px',
+ top: (parseInt(self.options.position / self.options.width) * (self.height + self.margin) + 2) + 'px',
+ });
+ }
+
+ function setMarkerPoint(i) {
+ var position = self.options.points[i];
+ self.$markerPoint[i]
+ .css({
+ left: (position % self.options.width) + 'px',
+ top: (parseInt(position / self.options.width) * (self.height + self.margin) + 16) + 'px',
+ });
+ }
+
+ function setPosition() {
+ self.options.position = Ox.limit(self.options.position, 0, self.options.duration);
+ setMarker();
+ }
+
+ function setWidth() {
+ self.lines = Math.ceil(self.options.duration / self.options.width);
+ that.css({
+ width: (self.options.width + self.margin) + 'px',
+ height: (self.height + self.margin) + 'px'
+ });
+ setMarker();
+ setMarkerPoint(0);
+ setMarkerPoint(1);
+ }
+
+ self.onChange = function(key, value) {
+ //Ox.print('onChange:', key, value)
+ if (key == 'points') {
+ //Ox.print('key', key, 'value', value)
+ setMarkerPoint(0);
+ setMarkerPoint(1);
+ } else if (key == 'position') {
+ setPosition();
+ } else if (key == 'width') {
+ setWidth();
+ }
+ };
+
+ return that;
+
+ };
/**
*/
Ox.VideoEditor = function(options, self) {
@@ -10766,7 +10954,7 @@ requires
self.sizes = getSizes();
$.each(['play', 'in', 'out'], function(i, type) {
- self.$player[i] = new Ox.VideoPlayer({
+ self.$player[i] = new Ox.VideoEditorPlayer({
duration: self.options.duration,
find: self.options.find,
height: self.sizes.player[i].height,
@@ -10796,7 +10984,7 @@ requires
}
});
self.$player[0].bindEvent({
- change: changePlayer,
+ playing: changePlayer,
togglesize: togglePlayerSize
});
@@ -10820,7 +11008,7 @@ requires
.bindEvent('changeEnd', changeTimelineLarge)
.appendTo(that);
- self.$timeline[1] = new Ox.SmallTimeline({
+ self.$timeline[1] = new Ox.BlockTimeline({
cuts: self.options.cuts,
duration: self.options.duration,
find: self.options.find,
@@ -11169,7 +11357,7 @@ requires
/**
*/
- Ox.VideoPlayer = function(options, self) {
+ Ox.VideoEditorPlayer = function(options, self) {
var self = self || {},
that = new Ox.Element('div', self)
@@ -11194,17 +11382,20 @@ requires
self.controlsHeight = 16;
if (self.options.type == 'play') {
- self.$video = $('