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', }) .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(); Ox.loop(self.lines, function(i) { addLine(i); }); self.$positionMarker = $('') .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] = $('') .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] = $('
') .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] = Ox.SmallVideoTimelineImages({ 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 }) .css({ position: 'absolute', marginLeft: (-i * self.options.width) + 'px' }) .appendTo(self.$lines[i]); self.$interfaces[i] = $('
').addClass('OxInterface') .css({ position: 'absolute', top: '2px', width: Math.ceil(self.options.duration) + 'px', height: '20px', marginLeft: (-i * self.options.width) + 'px', 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 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 ? '' + Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '
') + '

' + Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) : Ox.formatDuration(position, 3) }) .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]); Ox.print('$$ position', position) 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; };