'use strict'; /*@ Ox.LargeVideoTimeline LargeTimeline Object options Options object self Shared private variable ([options[, self]]) -> LargeTimeline Object position position @*/ Ox.LargeVideoTimeline = function(options, self) { self = self || {}; var that = Ox.Element({}, self) .defaults({ chapters: [], cuts: [], disabled: false, duration: 0, find: '', getImageURL: null, 'in': 0, matches: [], out: 0, position: 0, showInToOut: false, subtitles: [], type: '', width: 0 }) .options(options || {}) .update({ find: setSubtitles, 'in': function() { setPointMarker('in'); }, out: function() { setPointMarker('out'); }, position: setPosition, subtitles: setSubtitles, type: setType, width: setWidth }) .addClass('OxLargeVideoTimeline OxMedia') .on({ mouseleave: mouseleave, mousemove: mousemove }); if (!self.options.disabled) { that.bindEvent({ anyclick: click, dragstart: dragstart, drag: drag, dragend: dragend }); } self.$cuts = []; self.$pointMarker = {}; self.$tiles = {}; self.$tooltip = Ox.Tooltip({animate: false}); self.center = Math.floor(self.options.width / 2); self.fps = 25; self.height = 64; self.isAsync = self.options.getImageURL.length == 3; self.tileWidth = 1500; self.tiles = self.options.duration * self.fps / self.tileWidth; self.$timeline = $('
') .css({left: self.center + 'px'}) .appendTo(that); setTimeout(setSubtitles); if (self.options.showInToOut) { if (self.options['in']) { $('
') .addClass('OxOverlay') .css({ left: 0, width: self.options['in'] * self.fps + 'px', }) .appendTo(self.$timeline); } if (self.options.out) { $('
') .addClass('OxOverlay') .css({ left: self.options.out * self.fps + 'px', width: (self.options.duration - self.options.out) * self.fps + 'px', }) .appendTo(self.$timeline); } } setTimeout(function() { var $cut = $('') .addClass('OxCut') .attr({src: Ox.getImageURL('markerCut')}), $chapter = $('') .addClass('OxChapter') .attr({src: Ox.getImageURL('markerChapter')}), chapters = self.options.chapters.slice(1).map(function(chapter) { return chapter.position; }); Ox.unique(chapters.concat(self.options.cuts)).forEach(function(v, i) { self.$cuts[i] = (Ox.contains(chapters, v) ? $chapter : $cut) .clone() .css({left: (v * self.fps) + 'px'}) .appendTo(self.$timeline); }); }); self.$markerPosition = $('') .addClass('OxMarkerPosition') .attr({src: Ox.getImageURL('markerPosition')}) .appendTo(that); setMarker(); ['in', 'out'].forEach(function(point) { var titlecase = Ox.toTitleCase(point); self.$pointMarker[point] = $('') .addClass('OxMarkerPoint' + titlecase) .attr({src: Ox.getImageURL('marker' + titlecase)}) .appendTo(self.$timeline); setPointMarker(point); }); setWidth(); setPosition(); function click(data) { self.options.position = Ox.round(Ox.limit( getPosition(data), 0, self.options.duration ), 3); setPosition(); that.triggerEvent('position', {position: self.options.position}); } function dragstart(data) { Ox.$body.addClass('OxDragging'); self.drag = {x: data.clientX}; } function drag(data) { self.options.position = Ox.round(Ox.limit( self.options.position + (self.drag.x - data.clientX) / self.fps, 0, self.options.duration ), 3); self.drag.x = data.clientX; setPosition(); that.triggerEvent('positioning', {position: self.options.position}); } function dragend() { Ox.$body.removeClass('OxDragging'); that.triggerEvent('position', {position: self.options.position}); } function getImageURL(i, callback) { if (!self.isAsync) { callback(self.options.getImageURL(self.options.type, i)); } else { self.options.getImageURL(self.options.type, i, callback); } } function getPosition(e) { return self.options.position + ( e.clientX - that.offset().left - self.center - 1 ) / self.fps; } 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 setMarker() { self.$markerPosition.css({left: self.center + 'px'}); } function setPointMarker(point) { self.$pointMarker[point].css({ left: (self.options[point] * self.fps) + 'px' }); } function setPosition() { self.tile = Math.floor(self.options.position * self.fps / self.tileWidth); self.$timeline.css({ marginLeft: (-self.options.position * self.fps) + 'px' }); Ox.loop( Math.max(self.tile - 1, 0), Math.min(self.tile + 2, self.tiles), function(i) { if (!self.$tiles[i]) { if (self.isAsync) { self.$tiles[i] = true; } getImageURL(i, function(url) { self.$tiles[i] = $('') .attr({src: url}) .css({left: (i * self.tileWidth) + 'px'}) .appendTo(self.$timeline); }); } } ); if (self.clientX && self.clientY) { updateTooltip(); } } function setSubtitles() { that.find('.OxSubtitle').remove(); self.$subtitles = []; self.options.subtitles.forEach(function(subtitle, i) { var found = self.options.find && subtitle.text.toLowerCase().indexOf(self.options.find.toLowerCase()) > -1; self.$subtitles[i] = $('
') .addClass('OxSubtitle' + (found ? ' OxHighlight' : '')) .css({ left: Math.round(subtitle['in'] * self.fps) + 'px', width: Math.round(((subtitle.out - subtitle['in']) * self.fps) - 2) + 'px' }) .html(Ox.highlight( subtitle.text, self.options.find, 'OxHighlight', true )) .appendTo(self.$timeline); }); } function setType() { Ox.forEach(self.$tiles, function($tile, i) { getImageURL(i, function(url) { $tile.attr({src: url}); }); }); } function setWidth() { self.center = Math.floor(self.options.width / 2); that.css({ width: self.options.width + 'px' }); self.$timeline.css({ left: self.center + 'px' }); setMarker(); } function triggerPositionEvent() { that.triggerEvent('position', {position: self.options.position}); } function updateTooltip() { var position = getPosition(self); if (position >= 0 && position <= self.options.duration) { self.$tooltip .options({ title: Ox.formatDuration(position, 3) }) .show(self.clientX, self.clientY); } else { self.$tooltip.hide(); } } return that; };