oxjs/source/Ox.UI/js/Video/Ox.BlockVideoTimeline.js

254 lines
No EOL
7.6 KiB
JavaScript

Ox.BlockVideoTimeline = function(options, self) {
self = self || {};
var that = new Ox.Element({}, self)
.defaults({
duration: 0,
find: '',
getTimelineURL: null,
'in': 0,
out: 0,
position: 0,
results: [],
subtitles: [],
width: 0
})
.options(options || {})
.css({
position: 'absolute',
//background: 'rgba(192, 192, 192, 0.1)'
})
.bind({
mousedown: mousedown,
mouseleave: mouseleave,
mousemove: mousemove
})
.bindEvent({
drag: function(event, e) {
mousedown(e);
}
});
self.$images = [];
self.$interfaces = [];
self.$lines = [];
self.$tooltip = new Ox.Tooltip({
animate: false
}).css({
textAlign: 'center'
});
self.height = 16;
self.lines = getLines();
self.margin = 8;
setCSS();
self.$image = Ox.SmallVideoTimelineImage({
duration: self.options.duration,
editing: self.options.editing,
getTimelineURL: self.options.getTimelineURL,
'in': self.options['in'],
out: self.options.out,
results: self.options.results,
subtitles: self.options.subtitles,
width: Math.ceil(self.options.duration),
type: self.options.type
})
.bindEvent('load', function() {
// wait until the timeline image (the one image that is async)
// has loaded, so we can clone the element
Ox.loop(self.lines, function(i) {
addLine(i);
});
})
self.$positionMarker = $('<img>')
.attr({
src: Ox.UI.PATH + 'png/videoMarkerPlay.png'
})
.css({
position: 'absolute',
width: '9px',
height: '5px',
zIndex: 10
})
.appendTo(that.$element);
setPositionMarker();
self.$pointMarker = {};
['in', 'out'].forEach(function(point) {
var titleCase = Ox.toTitleCase(point);
self.$pointMarker[point] = $('<img>')
.addClass('OxPointMarker' + titleCase)
.attr({
src: Ox.UI.PATH + 'png/videoMarker' + titleCase + '.png'
})
.css({
position: 'absolute',
width: '6px',
height: '6px',
marginLeft: (point == 'in' ? -1 : 4) + 'px',
zIndex: 10
})
.appendTo(that.$element);
setPointMarker(point);
});
function addLine(i) {
self.$lines[i] = $('<div>')
.css({
position: 'absolute',
left: (self.margin / 2) + 'px',
top: i * (self.height + self.margin) + 'px',
width: self.options.width + 'px',
height: '24px',
overflow: 'hidden'
})
.appendTo(that.$element);
self.$images[i] = self.$image.clone()
.css({
position: 'absolute',
marginLeft: (-i * self.options.width) + 'px'
})
.appendTo(self.$lines[i]);
self.$interfaces[i] = $('<div>')
.addClass('OxInterface')
.css({
position: 'absolute',
top: '2px',
width: Math.ceil(self.options.duration) + 'px',
height: '20px',
marginLeft: (-i * self.options.width) + 'px',
//background: 'rgba(255, 0, 0, 0.1)',
zIndex: 11
})
.appendTo(self.$lines[i]);
}
function getLines() {
return Math.ceil(self.options.duration / self.options.width);
}
function getPosition(e) {
//FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
Ox.print('offsetX', e.offsetX)
return (e.offsetX ? e.offsetX : e.clientX - $(e.target).offset().left);
}
function getSubtitle(position) {
var subtitle = '';
Ox.forEach(self.options.subtitles, function(v) {
if (v['in'] <= position && v.out > position) {
subtitle = v;
return false;
}
});
return subtitle;
}
function mousedown(e) {
if ($(e.target).is('.OxInterface')) {
self.options.position = getPosition(e);
setPositionMarker();
// fixme: check if this pattern is better
// than the one used for list selection
if (!self.triggered) {
Ox.print('$$$$$$$$$$$$$$$')
that.triggerEvent('position', {
position: self.options.position
});
self.triggered = true;
setTimeout(function() {
self.triggered = false;
}, 250);
}
}
}
function mouseleave() {
self.$tooltip.hide();
}
function mousemove(e) {
var position, subtitle;
if ($(e.target).is('.OxInterface')) {
position = getPosition(e);
subtitle = getSubtitle(position);
self.$tooltip.options({
title: subtitle ?
'<span class=\'OxBright\'>' +
Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '<br/>') +
'</span><br/>' +
Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
Ox.formatDuration(position)
})
.show(e.clientX, e.clientY);
} else {
self.$tooltip.hide();
}
}
function setCSS() {
that.css({
width: (self.options.width + self.margin) + 'px',
height: ((self.height + self.margin) * self.lines) + 'px'
});
}
function setPointMarker(point) {
var position = Math.round(self.options[point]);
self.$pointMarker[point].css({
left: (position % self.options.width) + 'px',
top: (parseInt(position / self.options.width) *
(self.height + self.margin) + 16) + 'px'
});
}
function setPositionMarker() {
self.$positionMarker.css({
left: (self.options.position % self.options.width) + 'px',
top: (parseInt(self.options.position / self.options.width) *
(self.height + self.margin) + 2) + 'px'
});
}
function setWidth() {
self.lines = getLines();
setCSS();
Ox.loop(self.lines, function(i) {
if (self.$lines[i]) {
self.$lines[i].css({
width: self.options.width + 'px'
});
self.$images[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
self.$interfaces[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
} else {
addLine(i);
}
});
while (self.$lines.length > self.lines) {
self.$lines[self.$lines.length - 1].remove();
self.$lines.pop();
self.$images.pop();
}
setPositionMarker();
setPointMarker('in');
setPointMarker('out');
}
self.setOption = function(key, value) {
if (key == 'position') {
setPositionMarker();
} else if (key == 'width') {
setWidth();
}
}
return that;
};