From ce33d3650a3114fa6d68e693d02b41e20b2c5c04 Mon Sep 17 00:00:00 2001 From: rolux Date: Mon, 16 May 2011 13:29:26 +0200 Subject: [PATCH] add new timeline and find input to video player --- demos/video/js/video.js | 9 +- demos/video/png/logo.png | Bin 0 -> 32274 bytes .../Ox.UI/js/Video/Ox.SmallVideoTimeline.js | 21 +- .../js/Video/Ox.SmallVideoTimelineImage.js | 35 +- source/Ox.UI/js/Video/Ox.VideoPlayer.js | 418 ++++++++++++------ source/Ox.js | 5 +- 6 files changed, 326 insertions(+), 162 deletions(-) create mode 100644 demos/video/png/logo.png diff --git a/demos/video/js/video.js b/demos/video/js/video.js index 5325365d..e1bbbbd8 100644 --- a/demos/video/js/video.js +++ b/demos/video/js/video.js @@ -27,14 +27,15 @@ Ox.load('UI', { {'in': 5780.235, out: 5782.435}, {'in': 5881.365, out: 5886.635} ], - timeline = 'http://next.0xdb.org/' + id + '/timeline.16.png', + timeline = 'png/timeline.16.png', url = 'http://next.0xdb.org/' + id + '/96p.webm', videoSize = getVideoSize(), $videos = [ Ox.VideoPlayer({ controls: ['play', 'mute', 'fullscreen', 'scale', 'timeline', 'position'], + enableFind: true, + enableFullscreen: true, enableKeyboard: true, - find: 'brick', focus: 'mouseenter', height: 192, 'in': 3128.725, @@ -47,7 +48,9 @@ Ox.load('UI', { showIconOnLoad: true, showProgress: false, subtitles: 'srt/' + id + '.srt', - timeline: timeline, + timeline: function(i) { + return 'png/timeline.16.' + i + '.png'; + }, title: 'Brick - Rian Johnson - 2005', video: url + '?' + + Ox.random(1000000), width: 360 diff --git a/demos/video/png/logo.png b/demos/video/png/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ce3e720202f297d30b9e14d5e85dd58941e10f15 GIT binary patch literal 32274 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

Sg(}M-4bKk$` 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Ɏx*taXtII{Nz~PDlRQYr^V!(#oN@xOhQ>Gs!{e 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 OBlGM!n1(niIk(;Tytt;1 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 X') + if (Ox.isString(self.options.timeline)) { + $image = $('') .attr({ - src: self.options.getTimelineURL(i) + src: self.options.getTimelineURL(0) }) .load(function() { - context.drawImage($image[0], i * 3600, top); - if (++counter == images) { - callback(canvas.toDataURL()); - } + context.drawImage($image[0]) + callback(canvas.toDataURL()); }); - }) + } else { + counter = 0; + images = Math.ceil(self.options.duration / 3600); + Ox.loop(images, function(i) { + var $image = $('') + .attr({ + src: self.options.getTimelineURL(i) + }) + .load(function() { + context.drawImage($image[0], i * 3600, top); + if (++counter == images) { + callback(canvas.toDataURL()); + } + }); + }); + } } if (image != 'timeline') { context.putImageData(imageData, 0, 0); diff --git a/source/Ox.UI/js/Video/Ox.VideoPlayer.js b/source/Ox.UI/js/Video/Ox.VideoPlayer.js index 70e91a6c..3c985aa1 100644 --- a/source/Ox.UI/js/Video/Ox.VideoPlayer.js +++ b/source/Ox.UI/js/Video/Ox.VideoPlayer.js @@ -14,6 +14,8 @@ Ox.VideoPlayer Generic Video Player is just empty space that separates left-aligned from right-aligned controls duration Duration (sec) + enableFind If true, enable find + enableFullscreen If true, enable fullscreen enableKeyboard If true, enable keyboard controls externalControls If true, controls are outside the video find Query string @@ -66,7 +68,9 @@ Ox.VideoPlayer = function(options, self) { .defaults({ annotations: [], controls: [], - duration: 86399, + duration: 0, + enableFind: false, + enableFullscreen: false, enableKeyboard: false, externalControls: false, find: '', @@ -135,6 +139,13 @@ Ox.VideoPlayer = function(options, self) { key_1: function() { toggleScale(); }, + key_f: function() { + // need timeout so the "f" doesn't appear in the input field + setTimeout(self.$findInput.focusInput, 0); + }, + key_g: function() { + goToNextResult(1); + }, key_left: function() { setPosition(self.options.position - self.secondsPerFrame, true); }, @@ -145,7 +156,10 @@ Ox.VideoPlayer = function(options, self) { setPosition(self.options.position + self.secondsPerFrame, true); }, key_shift_f: function() { - toggleFullscreen(true); + self.options.enableFullscreen && toggleFullscreen(true); + }, + key_shift_g: function() { + goToNextResult(-1); }, key_space: function() { togglePaused(true); @@ -196,15 +210,24 @@ Ox.VideoPlayer = function(options, self) { } else { Ox.get(self.options.subtitles, function(data) { self.options.subtitles = Ox.parseSRT(data); + self.results = find(self.options.find); + Ox.print('--setting results--', self.$timeline) + if (self.options.duration) { + self.$timeline && self.$timeline.options({ + results: self.results, + subtitles: self.options.subtitles + }); + } else { + + } }); - //self.options.subtitles = []; + self.options.subtitles = []; } } - + self.results = find(self.options.find); self.buffered = []; self.controlsTimeout; - self.dragTimeout; self.$videoContainer = $('

') .css({ @@ -304,7 +327,7 @@ Ox.VideoPlayer = function(options, self) { } } - if (self.options.subtitles.length) { + if (self.options.subtitles.length || true) { // fixme self.$subtitle = $('
') //.addClass('OxSubtitle') .css({ @@ -339,6 +362,114 @@ Ox.VideoPlayer = function(options, self) { .appendTo(that.$element); } + if (self.options.enableFind) { + + self.$find = $('
') + .addClass('OxInterface') + .css({ + position: 'absolute', + right: '16px', + top: (self.options.title ? 32 : 16) + 'px', + width: '128px', + borderRadius: '8px', + opacity: 0 + }) + .css({ + backgroundImage: '-moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))' + }) + .css({ + backgroundImage: '-webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5))' + }) + .appendTo(that.$element); + + self.$previousButton = Ox.Button({ + style: 'symbol', + title: 'arrowLeft', + tooltip: 'Previous [Shift+G]', + type: 'image' + }) + .css({float: 'left', opacity: 0.25}) + .bindEvent({ + click: function() { + goToNextResult(-1); + } + }) + .appendTo(self.$find); + + self.$nextButton = Ox.Button({ + style: 'symbol', + title: 'arrowRight', + tooltip: 'Next [G]', + type: 'image' + }) + .css({float: 'left', opacity: 0.25}) + .bindEvent({ + click: function() { + goToNextResult(1); + } + }) + .appendTo(self.$find); + + self.$findInput = Ox.Input({ + placeholder: 'Find', + value: self.options.find, + width: 86 + }) + .css({ + float: 'left', + background: 'rgba(0, 0, 0, 0)', + MozBoxShadow: '0 0 0', + WebkitBoxShadow: '0 0 0' + }) + .bindEvent({ + focus: function() { + self.inputHasFocus = true; + }, + blur: function() { + self.inputHasFocus = false; + submitFindInput(); + } + }) + .appendTo(self.$find); + + self.$findInput.children('input').css({ + width: (self.positionWidth - 6) + 'px', + height: '16px', + padding: '0 3px 0 3px', + border: '0px', + borderRadius: '8px', + fontSize: '11px', + color: 'rgb(255, 255, 255)' + }) + .css({ + background: '-moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))' + }) + .css({ + background: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))' + }); + + self.$clearButton = Ox.Button({ + style: 'symbol', + title: 'close', + tooltip: 'Clear', + type: 'image' + }) + .css({float: 'left'}) + .bindEvent({ + click: function() { + self.$findInput + .options({value: ''}) + .focusInput(); + self.results = []; + self.$timeline && self.$timeline.options({ + results: self.results + }); + } + }) + .appendTo(self.$find); + + } + if (self.options.controls.length) { self.$controls = Ox.Bar({ @@ -463,39 +594,9 @@ Ox.VideoPlayer = function(options, self) { .bindEvent('click', toggleSize) .appendTo(self.$controls); - }else if (control == 'timeline') { + } else if (control == 'timeline') { - self.$timeline = Ox.Element() - .addClass('timeline') - .css({ - float: 'left', - height: self.barHeight + 'px', - background: 'rgba(0, 0, 0, 0.75)', - borderRadius: self.barHeight / 2 + 'px' - }) - .appendTo(self.$controls); - - self.$timelineImages = Ox.Element() - .addClass('timelineimages') - .css({ - float: 'left', - height: self.barHeight + 'px', - marginLeft: self.barHeight / 2 + 'px' - }) - .appendTo(self.$timeline); - - self.$timelineImage = $('') - .addClass('timelineimage') - .attr({ - src: self.options.timeline - }) - .css({ - float: 'left', - height: self.barHeight + 'px' - }) - .appendTo(self.$timelineImages.$element); - - ///* + /* if (self.options.showProgress) { self.$progress = $('') .attr({ @@ -507,46 +608,18 @@ Ox.VideoPlayer = function(options, self) { }) .appendTo(self.$timelineImages.$element); } - //*/ + */ - self.$positionMarker = $('
') - .css({ - float: 'left', - width: '14px', - height: '14px', - border: '1px solid rgba(0, 0, 0, 0.5)', - borderRadius: '8px' - }) - .append( - self.$positionMarkerRing = $('
') - .css({ - width: '10px', - height: '10px', - border: '2px solid rgba(255, 255, 255, 0.5)', - borderRadius: '7px', - }) - .append( - $('
') - .css({ - width: '8px', - height: '8px', - border: '1px solid rgba(0, 0, 0, 0.5)', - borderRadius: '5px', - }) - ) - ) - .appendTo(self.$timeline.$element); - - self.$timelineInterface = Ox.Element() - .css({ - float: 'left', - height: self.barHeight + 'px', - }) - .appendTo(self.$controls); - - self.$tooltip = Ox.Tooltip({ - animate: false - }); + if (self.options.duration) { + self.$timeline = getTimeline() + } else { + self.$timeline = Ox.Element() + .css({ + float: 'left' + }) + .html(' '); + } + self.$timeline.appendTo(self.$controls); } else if (control == 'space') { @@ -659,6 +732,16 @@ Ox.VideoPlayer = function(options, self) { } } + function find(query) { + query = query.toLowerCase(); + return query.length ? Ox.map(self.options.subtitles, function(subtitle) { + return subtitle.text.toLowerCase().indexOf(query) > -1 ? { + 'in': subtitle['in'], + out: subtitle.out + } : null; + }) : []; + } + function formatPosition(position) { position = Ox.isUndefined(position) ? self.options.position : position; return Ox.formatDuration(position, self.options.showMilliseconds); @@ -712,13 +795,6 @@ Ox.VideoPlayer = function(options, self) { padding: playIconPadding + 'px', borderRadius: Math.round(self.iconSize / 2) + 'px' }; - } else if (element == 'positionMarker') { - var position = self.options.duration ? - (self.options.position - self['in']) / self.options.duration : 0; - css = { - marginLeft: position * self.timelineImageWidth - - self.timelineImageWidth - 8 + 'px', - }; } else if (element == 'poster' || element == 'video') { var playerWidth = self.width, playerHeight = self.height, @@ -759,15 +835,6 @@ Ox.VideoPlayer = function(options, self) { css = { width: self.timelineWidth + 'px' }; - } else if (element == 'timelineImage' || element == 'timelineImages') { - css = { - width: self.timelineImageWidth + 'px' - }; - } else if (element == 'timelineInterface') { - css = { - width: self.timelineWidth + 'px', - marginLeft: -self.timelineWidth + 'px' - }; } else if (element == 'videoContainer') { css = { width: self.width + 'px', @@ -841,6 +908,61 @@ Ox.VideoPlayer = function(options, self) { return subtitle; } + function getTimeline() { + var $timeline = Ox.SmallVideoTimeline({ + _offset: getTimelineLeft(), + duration: self.options.duration, + getTimelineURL: Ox.isString(self.options.timeline) ? + function() { return self.options.timeline; } : + self.options.timeline, + 'in': self.options['in'], + out: self.options.out, + paused: self.options.paused, + results: self.results, + showMilliseconds: self.options.showMilliseconds, + subtitles: self.options.subtitles, + type: 'player', + width: getTimelineWidth() + }) + .css({ + float: 'left' + }) + .bindEvent({ + position: function(data) { + setPosition(data.position, true); + } + }); + //Ox.print('??', $timeline.find('.OxInterface')) + $timeline.children().css({ + marginLeft: getTimelineLeft() + 'px' + }); + $timeline.find('.OxInterface').css({ + marginLeft: getTimelineLeft() + 'px' + }); + return $timeline; + } + + function getTimelineLeft() { + var left = 0; + Ox.forEach(self.options.controls, function(control) { + if (control == 'timeline') { + return false; + } + left += control == 'position' ? self.positionWidth : 16 + }); + return left; + } + + function getTimelineWidth() { + return (self.options.fullscreen ? window.innerWidth : self.options.width) - + self.options.controls.reduce(function(prev, curr) { + return prev + ( + curr == 'timeline' || curr == 'space' ? 0 : + curr == 'position' ? self.positionWidth : 16 + ); + }, 0); + } + function hideInterface() { Ox.print('hideInterface'); self.interfaceTimeout = setTimeout(function() { @@ -874,6 +996,8 @@ Ox.VideoPlayer = function(options, self) { function loadedmetadata() { + var hadDuration = !!self.options.duration; + self.loaded = true; self.out = self.options.playInToOut && self.options.out < self.video.duration ? @@ -893,46 +1017,19 @@ Ox.VideoPlayer = function(options, self) { } } + if (self.$timeline) { + if (!hadDuration) { + self.$timeline.replaceWith(self.$timeline = getTimeline()); + } + self.$timeline.options({ + duration: self.options.duration + }); + } + if (self.options.enableKeyboard && self.options.focus == 'load') { that.gainFocus(); } - self.$timeline && self.$timelineInterface - .bind({ - mousedown: mousedownTrack, - mouseleave: mouseleaveTrack, - mousemove: mousemoveTrack, - }) - .bindEvent({ - drag: dragTrack, - dragpause: dragpauseTrack, - dragend: dragpauseTrack - }); - } - function dragTrack(e) { - setPosition(getPosition(e), true); - if (self.dragTimeout) { - clearTimeout(self.dragTimeout); - self.dragTimeout = 0; - } - } - - function dragpauseTrack(e) { - self.video.currentTime = self.options.position; - } - - function mousedownTrack(e) { - setPosition(getPosition(e), true); - } - - function mouseleaveTrack(e) { - self.$tooltip.hide(); - } - - function mousemoveTrack(e) { - self.$tooltip.options({ - title: formatPosition(getPosition(e)) - }).show(e); } function parsePositionInput(str) { @@ -1019,7 +1116,9 @@ Ox.VideoPlayer = function(options, self) { self.posterIsVisible = false; } self.$subtitle && setSubtitle(); - self.$timeline && self.$positionMarker.css(getCSS('positionMarker')); + self.$timeline && self.$timeline.options({ + position: self.options.position + }); self.$position && self.$position.html(formatPosition()); } @@ -1031,12 +1130,13 @@ Ox.VideoPlayer = function(options, self) { self.iconLeft = parseInt((self.width - self.iconSize) / 2), self.iconTop = parseInt((self.height - self.iconSize) / 2); if (self.$timeline || self.$space) { - self.timelineWidth = self.width - self.options.controls.reduce(function(prev, curr) { - return prev + ( - curr == 'timeline' || curr == 'space' ? 0 : - curr == 'position' ? self.positionWidth : 16 - ); - }, 0); + self.timelineWidth = self.width - + self.options.controls.reduce(function(prev, curr) { + return prev + ( + curr == 'timeline' || curr == 'space' ? 0 : + curr == 'position' ? self.positionWidth : 16 + ); + }, 0); if (self.$timeline) { self.timelineImageWidth = self.timelineWidth - self.barHeight; } @@ -1052,12 +1152,11 @@ Ox.VideoPlayer = function(options, self) { self.$title && self.$title.animate(getCSS('title'), ms); self.$controls && self.$controls.animate(getCSS('controls'), ms); if (self.$timeline) { - self.$timeline.animate(getCSS('timeline'), ms); - self.$timelineImages.animate(getCSS('timelineImages'), ms); - self.$timelineImage.animate(getCSS('timelineImage'), ms); - self.$progress && self.$progress.animate(getCSS('progress'), ms); - self.$positionMarker.animate(getCSS('positionMarker'), ms); - self.$timelineInterface.animate(getCSS('timelineInterface'), ms); + self.$timeline.animate(getCSS('timeline'), ms, function() { + self.$timeline.options({ + width: self.timelineWidth + }) + }); } self.$space && self.$space.animate(getCSS('space'), ms); } @@ -1115,6 +1214,37 @@ Ox.VideoPlayer = function(options, self) { }).show(); } + function submitFindInput() { + self.options.find = self.$findInput.options('value'); + self.results = find(self.options.find); + self.$timeline && self.$timeline.options({ + results: self.results + }); + if (self.results.length) { + setPosition(self.results[0]['in'] + self.secondsPerFrame, true); + self.currentResult = 0; + } + } + + function goToNextResult(direction) { + var found = false, + position = 0; + direction == -1 && self.results.reverse(); + Ox.forEach(self.results, function(v) { + if (direction == 1 ? v['in'] > self.options.position : v['out'] < self.options.position) { + position = v['in']; + found = true; + return false; + } + }); + direction == -1 && self.results.reverse(); + if (!found) { + position = self.results[direction == 1 ? 0 : self.results.length - 1]['in']; + } + Ox.print('>>', self.results, position) + setPosition(position + self.secondsPerFrame, true); + } + function submitPositionInput() { self.$positionInput.hide(); self.$position.html('').show(); @@ -1211,8 +1341,8 @@ Ox.VideoPlayer = function(options, self) { function togglePaused(toggleButton) { self.options.paused = !self.options.paused; - self.$timeline && self.$positionMarkerRing.css({ - borderColor: 'rgba(255, 255, 255, ' + (self.options.paused ? 0.5 : 1) + ')' + self.$timeline && self.$timeline.options({ + paused: self.options.paused }); if (self.options.paused) { self.video.pause(); diff --git a/source/Ox.js b/source/Ox.js index f2d5f3cf..184502de 100644 --- a/source/Ox.js +++ b/source/Ox.js @@ -3864,11 +3864,12 @@ Ox.highlight Highlight matches in a string > Ox.highlight('foobar', 'foo', 'match') 'foobar' @*/ +// fixme: with regexp, special chars would have to be escaped Ox.highlight = function(txt, str, classname) { - return txt.replace( + return str.length ? txt.replace( new RegExp('(' + str + ')', 'ig'), '$1' - ); + ) : txt; }; /*@