From 8fe529df81455259ace6fb72454961c1a29ff8aa Mon Sep 17 00:00:00 2001 From: rolux Date: Wed, 18 May 2011 15:02:02 +0200 Subject: [PATCH] move css to css file, add markers (in/out/poster) --- demos/video/js/video.js | 14 +- source/Ox.UI/css/Ox.UI.css | 224 +++- source/Ox.UI/js/Core/Ox.Theme.js | 2 +- source/Ox.UI/js/Video/Ox.VideoPlayer.js | 1064 ++++++++----------- source/Ox.UI/themes/classic/css/classic.css | 24 +- source/Ox.UI/themes/modern/css/modern.css | 32 +- 6 files changed, 709 insertions(+), 651 deletions(-) diff --git a/demos/video/js/video.js b/demos/video/js/video.js index 854f67a0..40182404 100644 --- a/demos/video/js/video.js +++ b/demos/video/js/video.js @@ -38,6 +38,7 @@ Ox.load('UI', { enableFullscreen: true, enableKeyboard: true, enableVolume: true, + find: 'brick', focus: 'mouseenter', height: 192, 'in': 3128.72, @@ -49,7 +50,7 @@ Ox.load('UI', { poster: poster, posterFrame: 3168.04, //showIconOnLoad: true, - showProgress: false, + showMarkers: true, subtitles: 'srt/' + id + '.srt', timeline: 'png/timeline.16.png', title: 'Brick - Rian Johnson - 2005', @@ -67,9 +68,9 @@ Ox.load('UI', { Ox.VideoPlayer({ enableKeyboard: true, height: videoSize.height, - 'in': 3128.725, + 'in': 3128.72, //keepIconVisible: true, - out: 3130.725, + out: 3130.72, paused: true, playInToOut: true, //preload: 'none', @@ -90,12 +91,15 @@ Ox.load('UI', { enableVolume: true, externalControls: true, height: 192, - 'in': 3128.725, + 'in': 3128.72, largeTimeline: function(i) { return 'http://next.0xdb.org/' + id + '/timelines/timeline.64.' + i + '.png'; }, - out: 3130.725, + out: 3130.72, paused: true, + position: 3168.04, + posterFrame: 3168.04, + showMarkers: true, showMilliseconds: 2, subtitles: 'srt/' + id + '.srt', timeline: timeline, diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index c39c0353..5e458ea8 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -1647,80 +1647,234 @@ Video margin-left: 4px; } -.OxVideoPlayer > .OxBar .OxInputGroup { - //width: 98px; + +.OxVideoPlayer { + position: absolute; } -.OxVideoPlayer > .OxBar .OxButton { - margin-right: -1px; +.OxVideoPlayer.OxFocus { + -moz-box-shadow: 0 0 2px rgb(128, 128, 128); + -webkit-box-shadow: 0 0 2px rgb(128, 128, 128); } -.OxVideoPlayer > .OxBar .OxButton, -.OxVideoPlayer > .OxBar .OxInput, -.OxVideoPlayer > .OxBar .OxLabel { - -moz-border-radius: 0; - -webkit-border-radius: 0; + +.OxVideoPlayer .OxControls { + position: absolute; } -.OxVideoPlayer > .OxBar .OxInput, -.OxVideoPlayer > .OxBar .OxLabel { - padding: 0; +.OxVideoPlayer .OxControls.OxOnScreen { + background-image: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); } -.OxVideoPlayer > .OxBar .OxLabel { - //width: 22px; - //background: rgb(32, 32, 32); +.OxVideoPlayer .OxControls > * { + float: left; } + +.OxVideoPlayer .OxFind { + position: absolute; + right: 0; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + background-image: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + display: none; +} +.OxVideoPlayer .OxFind > * { + float: left; +} +.OxVideoPlayer .OxFind .OxResults { + width: 24px; + padding-top: 2px; + font-size: 9px; + text-align: center; + color: rgb(255, 255, 255); +} + .OxVideoPlayer .OxLoadingIcon { position: absolute; left: 0; top: 0; right: 0; - bottom: 16px; + bottom: 0; margin: auto; + opacity: 1; } -.OxVideoPlayer .OxMarkerFrame { + +.OxVideoPlayer .OxLogo { + position: absolute; + opacity: 0.25; +} + +.OxVideoPlayer .OxPlayIcon { position: absolute; left: 0; top: 0; right: 0; - bottom: 16px; -} -.OxVideoPlayer .OxMarkerFrame > div { - float: left; -} -.OxVideoPlayer .OxMarkerFrame > .OxFrame { + bottom: 0; + margin: auto; + border: 2px solid rgb(255, 255, 255); background: rgba(0, 0, 0, 0.5); + opacity: 0; } -.OxVideoPlayer .OxMarkerFrame > .OxPoster { - border: 1px solid rgba(255, 255, 255, 0.5); -} -.OxVideoPlayer .OxMarkerPoint { + +.OxVideoPlayer .OxPointMarker { position: absolute; width: 16px; height: 16px; + display: none; } -.OxVideoPlayer .OxMarkerInTop { +.OxVideoPlayer .OxPointMarkerInTop { left: 4px; top: 4px; } -.OxVideoPlayer .OxMarkerInBottom { +.OxVideoPlayer .OxPointMarkerInBottom { left: 4px; - bottom: 20px; + bottom: 4px; } -.OxVideoPlayer .OxMarkerOutTop { +.OxVideoPlayer .OxPointMarkerOutTop { right: 4px; top: 4px; } -.OxVideoPlayer .OxMarkerOutBottom { +.OxVideoPlayer .OxPointMarkerOutBottom { right: 4px; - bottom: 20px; + bottom: 4px; } + +.OxVideoPlayer .OxPosition { + height: 12px; + padding: 2px; + font-size: 9px; + text-align: center; + color: rgb(255, 255, 255); +} + +.OxVideoPlayer .OxPositionInput { + display: none; +} + +.OxVideoPlayer .OxPoster { + position: absolute; +} + +.OxVideoPlayer .OxPosterMarker { + position: absolute; + display: none; +} +.OxVideoPlayer .OxPosterMarkerCenter { + position: absolute; + border: 1px solid rgba(255, 255, 255, 0.1); + background: transparent; +} +.OxVideoPlayer .OxPosterMarkerLeft, +.OxVideoPlayer .OxPosterMarkerRight { + position: absolute; + background: rgba(0, 0, 0, 0.5); +} + +.OxVideoPlayer .OxResolution { + position: absolute; + right: 0; + bottom: 16px; + background: transparent; // fixme: needed?; + display: none; +} +.OxVideoPlayer .OxResolution > div { + width: 52px; + height: 16px; + background: rgba(32, 32, 32, 0.5); +} +.OxVideoPlayer .OxResolution > div:first-child { + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} +.OxVideoPlayer .OxResolution > div.OxSelected { + background-image: -moz-linear-gradient(top, rgba(48, 48, 48, 0.5), rgba(16, 16, 16, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(48, 48, 48, 0.5), rgba(16, 16, 16, 0.5)); +} +.OxVideoPlayer .OxResolution > div > * { + float: left; +} +.OxVideoPlayer .OxResolution > div > div { + width: 36px; + height: 14px; + padding-top: 2px; + font-size: 9px; + text-align: right; + color: rgb(255, 255, 255); + cursor: default; +} +.OxVideoPlayer .OxResolution > div > img { + width: 9px; + height: 9px; + padding: 3px 3px 4px 4px; +} + + +.OxVideoPlayer .OxResolutionButton { + width: 32px; + height: 12px; + padding: 2px; + font-size: 9px; + text-align: center; + color: rgb(255, 255, 255); + cursor: default; +} + .OxVideoPlayer .OxSubtitle { position: absolute; left: 0; right: 0; text-align: center; - //text-shadow: rgba(0, 0, 0, 1) 2px 2px 0px; text-shadow: rgba(0, 0, 0, 1) 0 0 4px; color: rgb(255, 255, 255); - z-index: 10; +} + +.OxVideoPlayer .OxTitle { + padding-top: 1px; + text-align: center; + color: rgb(255, 255, 255); + overflow: hidden; + text-overflow: ellipsis; +} + +.OxVideoPlayer .OxVideoContainer { + position: absolute; + background: rgb(0, 0, 0); + overflow: hidden; +} + +.OxVideoPlayer .OxVolume { + position: absolute; + left: 0; + height: 16px; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + background-image: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + display: none; +} +.OxVideoPlayer .OxVolume > * { + float: left; +} +.OxVideoPlayer .OxVolume .OxRange .OxTrack { + padding: 1px; + border: 0; + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); +} +.OxVideoPlayer .OxVolume .OxRange .OxThumb { + padding: 1px 7px 1px 7px; + border: 0; + background-image: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); +} +.OxVideoPlayer .OxVolume .OxRange .OxThumb:active { + background-image: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); +} +.OxVideoPlayer .OxVolume .OxVolumeValue { + width: 24px; + padding-top: 2px; + font-size: 9px; + text-align: center; + color: rgb(255, 255, 255); } /* diff --git a/source/Ox.UI/js/Core/Ox.Theme.js b/source/Ox.UI/js/Core/Ox.Theme.js index 488aa708..35c69c1d 100644 --- a/source/Ox.UI/js/Core/Ox.Theme.js +++ b/source/Ox.UI/js/Core/Ox.Theme.js @@ -32,7 +32,7 @@ Ox.Theme = function(theme) { Ox.UI.$body .addClass('OxTheme' + Ox.toTitleCase(theme)) .removeClass('OxTheme' + Ox.toTitleCase(currentTheme)); - $('img').add('input[type=image]').each(function() { + $('img:not(.OxVideo)').add('input[type=image]:not(.OxVideo)').each(function() { var $this = $(this); $this.attr({ src: $this.attr('src').replace( diff --git a/source/Ox.UI/js/Video/Ox.VideoPlayer.js b/source/Ox.UI/js/Video/Ox.VideoPlayer.js index e4bfdf09..08443e1a 100644 --- a/source/Ox.UI/js/Video/Ox.VideoPlayer.js +++ b/source/Ox.UI/js/Video/Ox.VideoPlayer.js @@ -42,14 +42,14 @@ Ox.VideoPlayer Generic Video Player out Out point (sec) resolution resolution scaleToFill If true, scale to fill (otherwise, scale to fit) + showControlsOnLoad If true, show controls on load showFind If true, show find input showHours If true, don't show hours for videos shorter than one hour showIcon If true, show play icon showIconOnLoad If true, show icon on load - showInterfaceOnLoad If true, show controls and title on load showLargeTimeline If true, show large timeline showMilliseconds Number of decimals to show - showPointMarkers If true, show in/out markers + showMarkers If true, show in/out/poster markers showProgress <|false> If true, show buffering progress sizeIsLarge If true, initial state of the size control is large subtitles URL or SRT or array of subtitles @@ -87,7 +87,6 @@ Ox.VideoPlayer = function(options, self) { keepIconVisible: false, keepLargeTimelineVisible: false, keepLogoVisible: false, - largeTimeline: false, logo: '', logoLink: '', logoTitle: '', @@ -101,14 +100,14 @@ Ox.VideoPlayer = function(options, self) { out: 0, resolution: 0, scaleToFill: false, + showControlsOnLoad: false, showFind: false, showHours: false, showIcon: false, showIconOnLoad: false, - showInterfaceOnLoad: false, showLargeTimeline: false, + showMarkers: false, showMilliseconds: 0, - showPointMarkers: false, showProgress: false, subtitles: [], timeline: '', @@ -119,10 +118,7 @@ Ox.VideoPlayer = function(options, self) { width: 256 }) .options(options || {}) - .addClass('OxVideo') - .css({ - position: 'absolute' - }); + .addClass('OxVideoPlayer'); Ox.UI.$window.bind({ resize: function() { @@ -137,13 +133,17 @@ Ox.VideoPlayer = function(options, self) { if (!(self.options.resolution in self.options.video)) { self.options.resolution = self.resolutions[0]; } - Ox.print('resolutions', self.resolutions) self.video = self.options.video[self.options.resolution]; } - self['in'] = self.options.playInToOut ? self.options['in'] : 0, - self.out = self.options.playInToOut ? self.options.out : self.options.duration; - self.options.duration = self.out - self['in']; + if (self.options.playInToOut) { + self['in'] = self.options['in']; + self.out = self.options.out; + self.options.duration = self.out - self['in']; + } else { + self['in'] = 0; + self.out = self.options.duration || 86399; + } self.options.position = Ox.limit(self.options.position, self['in'], self.out); self.millisecondsPerFrame = 1000 / self.options.fps; @@ -151,6 +151,14 @@ Ox.VideoPlayer = function(options, self) { self.barHeight = 16; self.width = self.options.fullscreen ? window.innerWidth : self.options.width; self.height = self.options.fullscreen ? window.innerHeight : self.options.height; + self.videoWidth = self.options.width; + self.videoHeight = self.options.height; + + /* + ---------------------------------------------------------------------------- + Keyboard + ---------------------------------------------------------------------------- + */ if (self.options.enableKeyboard) { that.bindEvent({ @@ -159,7 +167,7 @@ Ox.VideoPlayer = function(options, self) { key_equal: function() { changeVolumeBy(0.1); }, - key_escape: hideControls, + key_escape: hideControlMenus, key_f: focusFind, key_g: function() { goToNextResult(1); @@ -189,10 +197,7 @@ Ox.VideoPlayer = function(options, self) { setPosition(self.options.position + 1); }, key_space: togglePaused - }) - } - - if (self.options.enableKeyboard) { + }); if (self.options.focus == 'mouseenter') { that.bind({ mouseenter: function() { @@ -211,6 +216,12 @@ Ox.VideoPlayer = function(options, self) { } } + /* + ---------------------------------------------------------------------------- + Mouse + ---------------------------------------------------------------------------- + */ + if ( (!self.options.externalControls && (self.options.controlsTop.length || self.options.controlsBottom.length)) || @@ -218,51 +229,28 @@ Ox.VideoPlayer = function(options, self) { ) { that.bind({ mouseenter: function() { - showInterface(); + showControls(); self.mouseHasLeft = false; Ox.print('MOUSE HAS ENTERED') }, mouseleave: function() { - hideInterface(); + hideControls(); self.mouseHasLeft = true; Ox.print('MOUSE HAS LEFT') } }); } - if (Ox.isString(self.options.subtitles)) { - if (self.options.subtitles.indexOf('\n') > -1) { - self.options.subtitles = Ox.parseSRT(self.options.subtitles); - } 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) { - // video has loaded - self.$timeline && self.$timeline.options({ - results: self.results, - subtitles: self.options.subtitles - }); - self.$largeTimeline && self.$largeTimeline.options({ - subtitles: self.options.subtitles - }); - } - }); - self.options.subtitles = []; - } - } - self.results = find(self.options.find); - - self.buffered = []; - self.controlsTimeout; + /* + ---------------------------------------------------------------------------- + Video + ---------------------------------------------------------------------------- + */ self.$videoContainer = $('
') + .addClass('OxVideoContainer') .css({ - position: 'absolute', top: self.options.externalControls && self.options.controlsTop ? '16px' : 0, - background: 'rgb(0, 0, 0)', - overflow: 'hidden' }) .bind({ click: function() { @@ -294,27 +282,36 @@ Ox.VideoPlayer = function(options, self) { .appendTo(self.$videoContainer); self.video = self.$video[0]; + /* + ---------------------------------------------------------------------------- + Poster + ---------------------------------------------------------------------------- + */ + if (self.options.poster) { self.$poster = $('') + .addClass('OxPoster') .attr({ src: self.options.poster }) - .css({ - position: 'absolute' - }) .appendTo(self.$videoContainer); self.posterIsVisible = true; } + /* + ---------------------------------------------------------------------------- + Logo + ---------------------------------------------------------------------------- + */ + if (self.options.logo) { self.$logo = $('') + .addClass('OxLogo') .attr({ src: self.options.logo }) .css({ - position: 'absolute', - cursor: self.options.logoLink ? 'pointer' : 'default', - opacity: 0.25, + cursor: self.options.logoLink ? 'pointer' : 'default' }) .appendTo(self.$videoContainer); if (self.options.logoTitle) { @@ -324,29 +321,28 @@ Ox.VideoPlayer = function(options, self) { } } + /* + ---------------------------------------------------------------------------- + Icons + ---------------------------------------------------------------------------- + */ + self.$loadingIcon = $('') + .addClass('OxLoadingIcon OxVideo') .attr({ src: Ox.UI.getImagePath('symbolLoadingAnimated.svg') .replace('/classic/', '/modern/') }) - .css({ - position: 'absolute' - }) .appendTo(self.$videoContainer); if (self.options.showIcon || self.options.showIconOnLoad) { self.$playIcon = $('') + .addClass('OxPlayIcon OxVideo') .attr({ src: Ox.UI.getImagePath( 'symbol' + (self.options.paused ? 'Play' : 'Pause') + '.svg' ).replace('/classic/', '/modern/') }) - .css({ - position: 'absolute', - border: '2px solid rgb(255, 255, 255)', - background: 'rgba(0, 0, 0, 0.5)', - opacity: 0 - }) .appendTo(self.$videoContainer); if (self.options.showIcon) { self.$playIcon.addClass('OxInterface'); @@ -356,252 +352,78 @@ Ox.VideoPlayer = function(options, self) { } } - self.$posterMarker = $('
') - .css({ - position: 'absolute', - left: 0, - top: 0, - right: 0, - bottom: 0, - }) - .hide() - .appendTo(self.$videoContainer); + /* + ---------------------------------------------------------------------------- + Markers + ---------------------------------------------------------------------------- + */ - self.$posterMarkerLeft = $('
') - .css({ - float: 'left', - background: 'rgba(0, 0, 0, 0.5)' - }) - .css({ - width: Math.floor((self.options.width - self.options.height) / 2) + 'px', - height: self.options.height + 'px' - }) - .appendTo(self.$posterMarker); + if (self.options.showMarkers) { - self.$posterMarkerCenter = $('
') - .css({ - border: '1px solid rgba(255, 255, 255, 0.1)' - }) - .css({ - float: 'left', - width: (self.options.height - 2) + 'px', - height: (self.options.height - 2) + 'px' - }) - .appendTo(self.$posterMarker); - - self.$posterMarkerRight = $('
') - .css({ - background: 'rgba(0, 0, 0, 0.5)' - }) - .css({ - float: 'left', - width: Math.ceil((self.options.width - self.options.height) / 2) + 'px', - height: self.options.height + 'px' - }) - .appendTo(self.$posterMarker); - - self.$pointMarker = {}; - ['in', 'out'].forEach(function(point) { - self.$pointMarker[point] = {}; - ['top', 'bottom'].forEach(function(edge) { - var titleCase = Ox.toTitleCase(point) + Ox.toTitleCase(edge); - self.$pointMarker[point][edge] = $('') - .addClass('OxMarkerPoint OxMarker' + titleCase) - .attr({ - src: Ox.UI.PATH + 'png/videoMarker' + titleCase + '.png' - }) - .hide() + self.$posterMarker = {}; + ['left', 'center', 'right'].forEach(function(position) { + var titleCase = Ox.toTitleCase(position); + self.$posterMarker[position] = $('
') + .addClass('OxPosterMarker OxPosterMarker' + titleCase) .appendTo(self.$videoContainer); - /* - if (self.options.points[i] == self.options.position) { - self.$pointMarker[point][edge].show(); - } - */ }); - }); + + self.$pointMarker = {}; + ['in', 'out'].forEach(function(point) { + self.$pointMarker[point] = {}; + ['top', 'bottom'].forEach(function(edge) { + var titleCase = Ox.toTitleCase(point) + Ox.toTitleCase(edge); + self.$pointMarker[point][edge] = $('') + .addClass('OxPointMarker OxPointMarker' + titleCase) + .attr({ + src: Ox.UI.PATH + 'png/videoMarker' + titleCase + '.png' + }) + .appendTo(self.$videoContainer); + /* + if (self.options.points[i] == self.options.position) { + self.$pointMarker[point][edge].show(); + } + */ + }); + }); + + } + + /* + ---------------------------------------------------------------------------- + Subtitles + ---------------------------------------------------------------------------- + */ if (self.options.subtitles.length || true) { // fixme self.$subtitle = $('
') - //.addClass('OxSubtitle') - .css({ - position: 'absolute', - left: 0, - right: 0, - textAlign: 'center', - textShadow: 'rgba(0, 0, 0, 1) 0 0 4px', - color: 'rgb(255, 255, 255)' - }) + .addClass('OxSubtitle') .appendTo(self.$videoContainer); } - if (self.options.enableFind) { - - self.$find = $('
') - .addClass('OxControls') - .css({ - position: 'absolute', - right: 0, - top: self.options.controlsTop.length ? '16px' : 0, - borderBottomLeftRadius: '8px', - borderBottomRightRadius: '8px' - }) - .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))' - }) - .hide() - .appendTo(that.$element); - - self.$results = $('
') - .css({ - float: 'left', - width: '24px', - paddingTop: '2px', - fontSize: '9px', - textAlign: 'center' - }) - .html('0') - .appendTo(self.$find); - - self.$previousButton = Ox.Button({ - style: 'symbol', - title: 'arrowLeft', - tooltip: 'Previous [Shift+G]', - type: 'image' - }) - .css({float: 'left'}) - .bindEvent({ - click: function() { - goToNextResult(-1); - } - }) - .appendTo(self.$find); - - self.$nextButton = Ox.Button({ - style: 'symbol', - title: 'arrowRight', - tooltip: 'Next [G]', - type: 'image' - }) - .css({float: 'left'}) - .bindEvent({ - click: function() { - goToNextResult(1); - } - }) - .appendTo(self.$find); - - self.$findInput = Ox.Input({ - changeOnKeypress: true, - value: self.options.find - }) - .css({ - float: 'left', - background: 'rgba(0, 0, 0, 0)', - MozBoxShadow: '0 0 0', - WebkitBoxShadow: '0 0 0' - }) - .bindEvent({ - blur: function() { - self.inputHasFocus = false; - }, - focus: function() { - self.inputHasFocus = true; - }, - change: function(data) { - submitFindInput(data.value, false); - }, - submit: function(data) { - self.inputHasFocus = false; - submitFindInput(data.value, true); - } - }) - .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: 'delete', - tooltip: 'Clear', - type: 'image' - }) - .css({float: 'left'}) - .bindEvent({ - click: function() { - self.options.find = ''; - self.results = []; - self.$results.html('0'); - self.$findInput.clearInput(); - self.subtitle && setSubtitleText(); - self.$timeline && self.$timeline.options({ - find: self.options.find, - results: self.results - }); - //setTimeout(self.$findInput.focusInput, 10); - } - }) - .appendTo(self.$find); - //*/ - - self.$hideFindButton = Ox.Button({ - style: 'symbol', - title: 'close', - tooltip: 'Hide', - type: 'image' - }) - .css({float: 'left'}) - .bindEvent({ - click: toggleFind - }) - .appendTo(self.$find); - - } + /* + ---------------------------------------------------------------------------- + Controls + ---------------------------------------------------------------------------- + */ ['top', 'bottom'].forEach(function(edge) { - var titlecase = Ox.toTitleCase(edge); + var titleCase = Ox.toTitleCase(edge); - if (self.options['controls' + titlecase].length) { + if (self.options['controls' + titleCase].length) { - self['$controls' + titlecase] = Ox.Bar({ + self['$controls' + titleCase] = Ox.Bar({ size: self.barHeight }) - .addClass('OxControls OxInterface') + .addClass('OxControls' + (self.options.externalControls ? '' : ' OxOnScreen')) .css({ - position: 'absolute', opacity: self.options.externalControls ? 1 : 0 }) .css(edge, 0) .appendTo(that.$element); - if (!self.options.externalControls) { - self['$controls' + titlecase].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))' - }); - } - - self.options['controls' + titlecase].forEach(function(control) { + self.options['controls' + titleCase].forEach(function(control) { if (control == 'find') { @@ -611,9 +433,11 @@ Ox.VideoPlayer = function(options, self) { tooltip: 'Find', type: 'image' }) - .css({float: 'left'}) - .bindEvent('click', toggleFind) - .appendTo(self['$controls' + titlecase]); + .addClass('OxVideo') + .bindEvent({ + click: toggleFind + }) + .appendTo(self['$controls' + titleCase]); } else if (control == 'fullscreen') { @@ -626,11 +450,13 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Enter Fullscreen', 'Exit Fullscreen'], type: 'image' }) - .css({float: 'left'}) - .bindEvent('click', function() { - toggleFullscreen('button'); + .addClass('OxVideo') + .bindEvent({ + click: function() { + toggleFullscreen('button'); + } }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } else if (control == 'mute') { @@ -643,11 +469,13 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Mute', 'Unmute'], type: 'image' }) - .css({float: 'left'}) - .bindEvent('click', function() { - toggleMuted('button'); + .addClass('OxVideo') + .bindEvent({ + click: function() { + toggleMuted('button'); + } }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } else if (control == 'play') { @@ -661,11 +489,13 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Play', 'Pause'], type: 'image' }) - .css({float: 'left'}) - .bindEvent('click', function() { - togglePaused('button'); + .addClass('OxVideo') + .bindEvent({ + click: function() { + togglePaused('button'); + } }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } else if (control == 'playInToOut') { @@ -675,9 +505,11 @@ Ox.VideoPlayer = function(options, self) { tooltip: 'Play In to Out', type: 'image' }) - .css({float: 'left'}) - .bindEvent('click', playInToOut) - .appendTo(self['$controls' + titlecase]); + .addClass('OxVideo') + .bindEvent({ + click: playInToOut + }) + .appendTo(self['$controls' + titleCase]); } else if (control == 'position') { @@ -685,17 +517,14 @@ Ox.VideoPlayer = function(options, self) { !!self.options.showMilliseconds * 2 + self.options.showMilliseconds * 6; - self.$position = $('
') - .css({ - float: 'left', - width: (self.positionWidth - 4) + 'px', - height: '12px', - padding: '2px', - fontSize: '9px', - textAlign: 'center', - color: 'rgb(255, 255, 255)' + self.$position = Ox.Element({ + tooltip: 'Position' }) - .html(formatPosition) + .addClass('OxPosition') + .css({ + width: (self.positionWidth - 4) + 'px', + }) + .html(formatPosition()) .bind({ click: function() { if (!self.options.paused) { @@ -716,18 +545,13 @@ Ox.VideoPlayer = function(options, self) { .focusInput(false); } }) - .appendTo(self['$controls' + titlecase].$element); + .appendTo(self['$controls' + titleCase]); self.$positionInput = Ox.Input({ value: formatPosition(), width: self.positionWidth }) - .css({ - float: 'left', - background: 'rgba(0, 0, 0, 0)', - MozBoxShadow: '0 0 0', - WebkitBoxShadow: '0 0 0' - }) + .addClass('OxPositionInput') .bindEvent({ focus: function() { self.inputHasFocus = true; @@ -737,23 +561,11 @@ Ox.VideoPlayer = function(options, self) { submitPositionInput(); } }) - .hide() - .appendTo(self['$controls' + titlecase].$element); + .appendTo(self['$controls' + titleCase].$element); self.$positionInput.children('input').css({ width: (self.positionWidth - 6) + 'px', - height: '16px', - padding: '0 3px 0 3px', - border: '0px', - borderRadius: '8px', - fontSize: '9px', - 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))' + fontSize: '9px' }); } else if (control == 'resolution') { @@ -761,32 +573,19 @@ Ox.VideoPlayer = function(options, self) { self.$resolutionButton = Ox.Element({ tooltip: 'Resolution' }) - .css({ - float: 'left', - width: '32px', - height: '12px', - padding: '2px', - fontSize: '9px', - textAlign: 'center', - color: 'rgb(255, 255, 255)', - cursor: 'default' - }) + .addClass('OxResolutionButton') .html(self.options.resolution + 'p') .bind({ click: function() { self.$resolution.toggle(); } }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); self.$resolution = $('
') - .addClass('OxControls') + .addClass('OxResolution') .css({ - position: 'absolute', - right: 0, - bottom: '16px', - height: (self.resolutions.length * 16) + 'px', - background: 'transparent' + height: (self.resolutions.length * 16) + 'px' }) .bind({ click: function(e) { @@ -806,68 +605,33 @@ Ox.VideoPlayer = function(options, self) { } } }) - .hide() .appendTo(that.$element); self.resolutions.forEach(function(resolution, i) { var $item = $('
') - .css({ - width: '52px', - height: '16px', - background: 'rgba(32, 32, 32, 0.5)' - }) .data({ resolution: resolution }) .bind({ mouseenter: function() { - $(this) - .css({ - backgroundImage: '-moz-linear-gradient(top, rgba(48, 48, 48, 0.5), rgba(16, 16, 16, 0.5))' - }) - .css({ - backgroundImage: '-webkit-linear-gradient(top, rgba(48, 48, 48, 0.5), rgba(16, 16, 16, 0.5))' - }) + $(this).addClass('OxSelected'); }, mouseleave: function() { - $(this).css({ - background: 'rgba(32, 32, 32, 0.5)' - }); + $(this).removeClass('OxSelected'); } }) .appendTo(self.$resolution); - if (i == 0) { - $item.css({ - borderTopLeftRadius: '8px', - borderTopRightRadius: '8px' - }) - } $('
') - .css({ - float: 'left', - width: '36px', - height: '14px', - paddingTop: '2px', - fontSize: '9px', - textAlign: 'right', - cursor: 'default' - }) .html(resolution + 'p') .appendTo($item); $('') + .addClass('OxVideo') .attr({ src: resolution == self.options.resolution ? - Ox.UI.getImagePath('symbolCheck.svg') : + Ox.UI.getImagePath('symbolCheck.svg').replace('/classic/', '/modern/') : Ox.UI.PATH + 'png/transparent.png' }) - .css({ - float: 'left', - width: '9px', - height: '9px', - padding: '3px 3px 4px 4px' - }) .appendTo($item); - - }) + }); } else if (control == 'scale') { @@ -880,11 +644,11 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Scale to Fill', 'Scale to Fit'], type: 'image' }) - .css({float: 'left'}) + .addClass('OxVideo') .bindEvent('click', function() { toggleScale('button'); }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } else if (control == 'size') { @@ -897,16 +661,15 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Larger', 'Smaller'], type: 'image' }) - .css({float: 'left'}) + .addClass('OxVideo') .bindEvent('click', toggleSize) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } else if (control == 'space') { - self['$space' + titlecase] = $('
') - .css({float: 'left'}) + self['$space' + titleCase] = $('
') .html(' ') // fixme: ?? - .appendTo(self['$controls' + titlecase].$element); + .appendTo(self['$controls' + titleCase].$element); } else if (control == 'timeline') { @@ -928,27 +691,16 @@ Ox.VideoPlayer = function(options, self) { self.$timeline = getTimeline() } else { self.$timeline = Ox.Element() - .css({ - float: 'left' - }) .html(' '); } - self.$timeline.appendTo(self['$controls' + titlecase]); + self.$timeline.appendTo(self['$controls' + titleCase]); } else if (control == 'title') { self.$title = $('
') - .addClass('OxInterface') - .css({ - float: 'left', - paddingTop: '1px', - textAlign: 'center', - color: 'rgb(255, 255, 255)', - overflow: 'hidden', - textOverflow: 'ellipsis' - }) + .addClass('OxTitle') .html(self.options.title) - .appendTo(self['$controls' + titlecase].$element); + .appendTo(self['$controls' + titleCase].$element); } else if (control == 'volume') { @@ -958,11 +710,11 @@ Ox.VideoPlayer = function(options, self) { tooltip: 'Volume', type: 'image' }) - .css({float: 'left'}) + .addClass('OxVideo') .bindEvent({ click: toggleVolume }) - .appendTo(self['$controls' + titlecase]); + .appendTo(self['$controls' + titleCase]); } @@ -972,25 +724,134 @@ Ox.VideoPlayer = function(options, self) { }); + /* + ---------------------------------------------------------------------------- + Find + ---------------------------------------------------------------------------- + */ + + if (self.options.enableFind) { + + self.$find = $('
') + .addClass('OxControls OxFind') + .css({ + top: self.options.controlsTop.length ? '16px' : 0 + }) + .appendTo(that.$element); + + self.$results = Ox.Element({ + tooltip: 'Results' + }) + .addClass('OxResults') + .html('0') + .appendTo(self.$find); + + self.$previousButton = Ox.Button({ + disabled: true, + style: 'symbol', + title: 'arrowLeft', + tooltip: 'Previous', + type: 'image' + }) + .addClass('OxVideo') + .bindEvent({ + click: function() { + goToNextResult(-1); + } + }) + .appendTo(self.$find); + + self.$nextButton = Ox.Button({ + disabled: true, + style: 'symbol', + title: 'arrowRight', + tooltip: 'Next', + type: 'image' + }) + .addClass('OxVideo') + .bindEvent({ + click: function() { + goToNextResult(1); + } + }) + .appendTo(self.$find); + + self.$findInput = Ox.Input({ + changeOnKeypress: true, + value: self.options.find + }) + .bindEvent({ + blur: function() { + self.inputHasFocus = false; + }, + focus: function() { + self.inputHasFocus = true; + }, + change: function(data) { + submitFindInput(data.value, false); + }, + submit: function(data) { + self.inputHasFocus = false; + submitFindInput(data.value, true); + } + }) + .appendTo(self.$find); + + self.$findInput.children('input').css({ + width: (self.positionWidth - 6) + 'px', + }) + + self.$clearButton = Ox.Button({ + disabled: !self.options.find, + style: 'symbol', + title: 'delete', + tooltip: 'Clear', + type: 'image' + }) + .addClass('OxVideo') + .bindEvent({ + click: function() { + self.options.find = ''; + self.results = []; + self.$results.html('0'); + self.$findInput.clearInput(); + self.subtitle && setSubtitleText(); + self.$timeline && self.$timeline.options({ + find: self.options.find, + results: self.results + }); + //setTimeout(self.$findInput.focusInput, 10); + } + }) + .appendTo(self.$find); + + self.$hideFindButton = Ox.Button({ + style: 'symbol', + title: 'close', + tooltip: 'Hide', + type: 'image' + }) + .addClass('OxVideo') + .bindEvent({ + click: toggleFind + }) + .appendTo(self.$find); + + } + + /* + ---------------------------------------------------------------------------- + Volume + ---------------------------------------------------------------------------- + */ + if (self.options.enableVolume) { self.$volume = $('
') - .addClass('OxControls') + .addClass('OxControls OxVolume') .css({ - position: 'absolute', - left: 0, - bottom: self.options.controlsBottom.length ? '16px' : 0, - height: '16px', - borderTopLeftRadius: '8px', - borderTopRightRadius: '8px' + bottom: self.options.controlsBottom.length ? '16px' : 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))' - }) - .hide() .appendTo(that.$element); self.$hideVolumeButton = Ox.Button({ @@ -999,7 +860,7 @@ Ox.VideoPlayer = function(options, self) { tooltip: 'Hide', type: 'image' }) - .css({float: 'left'}) + .addClass('OxVideo') .bindEvent({ click: toggleVolume }) @@ -1014,7 +875,7 @@ Ox.VideoPlayer = function(options, self) { tooltip: ['Mute', 'Unmute'], type: 'image' }) - .css({float: 'left'}) + .addClass('OxVideo') .bindEvent({ click: function() { toggleMuted(); @@ -1028,9 +889,6 @@ Ox.VideoPlayer = function(options, self) { step: 0.001, value: self.options.muted ? 0 : self.options.volume }) - .css({ - float: 'left' - }) .bindEvent({ change: function(data) { setVolume(data.value); @@ -1038,58 +896,29 @@ Ox.VideoPlayer = function(options, self) { }) .appendTo(self.$volume); - self.$volumeInput.find('.OxTrack') - .css({ - //border: '1px solid rgba(64, 64, 64, 1)' - padding: '1px', - border: 0 - }) - .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.$volumeInput.find('.OxThumb') - .css({ - //border: '1px solid rgba(64, 64, 64, 1)' - padding: '1px 7px 1px 7px', - border: 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))' - }); - self.$volumeValue = $('
') - .css({ - float: 'left', - width: '24px', - paddingTop: '2px', - fontSize: '9px', - textAlign: 'center' - }) + .addClass('OxVolumeValue') .html(self.options.muted ? 0 : Math.round(self.options.volume * 100)) .appendTo(self.$volume); } - if (self.options.largeTimeline) { - - if (self.options.duration) { - self.$largeTimeline = getLargeTimeline() + self.results = []; + if (self.options.subtitles) { + if (Ox.isArray(self.options.subtitles)) { + loadedsubtitles(); } else { - self.$largeTimeline = Ox.Element() - .css({ - float: 'left' - }) - .html(' '); + if (self.options.subtitles.indexOf('\n') > -1) { + self.options.subtitles = Ox.parseSRT(self.options.subtitles); + loadedsubtitles(); + } else { + Ox.get(self.options.subtitles, function(data) { + self.options.subtitles = Ox.parseSRT(data); + loadedsubtitles(); + }); + self.options.subtitles = []; + } } - self.$largeTimeline.appendTo(that); - } setSizes(); @@ -1136,9 +965,7 @@ Ox.VideoPlayer = function(options, self) { } function focusFind() { - if (!self.interfaceIsVisible) { - showInterface(); - } + !self.interfaceIsVisible && showControls(); // need timeout so the "f" doesn't appear in the input field setTimeout(function() { if (self.$find.is(':hidden')) { @@ -1166,8 +993,6 @@ Ox.VideoPlayer = function(options, self) { }; } else if (element == 'loadingIcon') { css = { - left: self.iconLeft + 'px', - top: self.iconTop + 'px', width: self.iconSize + 'px', height: self.iconSize + 'px' }; @@ -1187,9 +1012,6 @@ Ox.VideoPlayer = function(options, self) { !!self.options.controlsBottom.length ) * self.barHeight; } - if (self.options.largeTimeline) { - height += 64; - } css = Ox.extend({ width: self.width + 'px', height: height + 'px' @@ -1204,37 +1026,11 @@ Ox.VideoPlayer = function(options, self) { var playIconPadding = Math.round(self.iconSize * 1/8), playIconSize = self.iconSize - 2 * playIconPadding - 4; css = { - left: self.iconLeft + 'px', - top: self.iconTop + 'px', width: playIconSize + 'px', height: playIconSize + 'px', padding: playIconPadding + 'px', borderRadius: Math.round(self.iconSize / 2) + 'px' }; - } else if (element == 'poster' || element == 'video') { - var playerWidth = self.width, - playerHeight = self.height, - playerRatio = playerWidth / playerHeight, - videoWidth = self.video.videoWidth, - videoHeight = self.video.videoHeight, - videoRatio = videoWidth / videoHeight, - videoIsWider = videoRatio > playerRatio, - width, height; - if (self.options.scaleToFill) { - width = videoIsWider ? playerHeight * videoRatio : playerWidth; - height = videoIsWider ? playerHeight : playerWidth / videoRatio; - } else { - width = videoIsWider ? playerWidth : playerHeight * videoRatio; - height = videoIsWider ? playerWidth / videoRatio : playerHeight; - } - width = Math.round(width); - height = Math.round(height); - css = { - width: width + 'px', - height: height + 'px', - marginLeft: parseInt((playerWidth - width) / 2), - marginTop: parseInt((playerHeight - height) / 2) - }; } else if (element == 'progress') { css = { width: self.timelineImageWidth + 'px', @@ -1288,6 +1084,32 @@ Ox.VideoPlayer = function(options, self) { } } + function getPosterMarkerCSS() { + self.videoCSS = getVideoCSS(); + var left = Math.floor((self.videoCSS.width - self.videoCSS.height) / 2), + right = Math.ceil((self.videoCSS.width - self.videoCSS.height) / 2); + return { + center: { + left: self.videoCSS.left + left + 'px', + top: self.videoCSS.top + 'px', + width: (self.videoCSS.height - 2) + 'px', + height: (self.videoCSS.height - 2) + 'px' + }, + left: { + left: self.videoCSS.left + 'px', + top: self.videoCSS.top + 'px', + width: left + 'px', + height: self.videoCSS.height + 'px' + }, + right: { + left: self.videoCSS.left + left + self.videoCSS.height + 'px', + top: self.videoCSS.top + 'px', + width: right + 'px', + height: self.videoCSS.height + 'px' + } + }; + } + function getProgressImageURL() { Ox.print('---', self.timelineImageWidth) if (!self.timelineImageWidth) return; @@ -1332,31 +1154,6 @@ Ox.VideoPlayer = function(options, self) { return subtitle; } - function getLargeTimeline() { - var $timeline = Ox.LargeVideoTimeline({ - duration: self.options.duration, - find: self.options.find, - getImageURL: self.options.largeTimeline, - 'in': self.options['in'], - out: self.options.out, - position: self.options.position, - subtitles: self.options.subtitles, - type: 'player', - width: self.options.width - }) - .css({ - position: 'absolute', - bottom: '12px', - marginLeft: 0, - }) - .bindEvent({ - position: function(data) { - setPosition(data.position, 'largeTimeline'); - } - }); - return $timeline; - } - function getTimeline() { var $timeline = Ox.SmallVideoTimeline({ _offset: getTimelineLeft(), @@ -1427,6 +1224,32 @@ Ox.VideoPlayer = function(options, self) { }, 0); } + function getVideoCSS() { + var playerWidth = self.width, + playerHeight = self.height, + playerRatio = playerWidth / playerHeight, + videoWidth = self.videoWidth, + videoHeight = self.videoHeight, + videoRatio = videoWidth / videoHeight, + videoIsWider = videoRatio > playerRatio, + width, height; + if (self.options.scaleToFill) { + width = videoIsWider ? playerHeight * videoRatio : playerWidth; + height = videoIsWider ? playerHeight : playerWidth / videoRatio; + } else { + width = videoIsWider ? playerWidth : playerHeight * videoRatio; + height = videoIsWider ? playerWidth / videoRatio : playerHeight; + } + width = Math.round(width); + height = Math.round(height); + return { + left: parseInt((playerWidth - width) / 2), + top: parseInt((playerHeight - height) / 2), + width: width, + height: height + }; + } + function getVolumeImageURL() { var symbol; if (self.options.muted || self.options.volume == 0) { @@ -1441,8 +1264,7 @@ Ox.VideoPlayer = function(options, self) { return Ox.UI.getImagePath('symbol' + symbol + '.svg').replace('/classic/', '/modern/'); } - function hideControls() { - // fixme: slightly wrong name, this is about secondary controls + function hideControlMenus() { ['find', 'volume', 'resolution'].forEach(function(element) { var $element = self['$' + element]; $element && $element.is(':visible') && $element.animate({ @@ -1451,11 +1273,11 @@ Ox.VideoPlayer = function(options, self) { $element.hide().css({opacity: 1}); }); }); - self.options.fullscreen && hideInterface(); + self.options.fullscreen && hideControls(); } - function hideInterface() { - Ox.print('hideInterface'); + function hideControls() { + Ox.print('hideControls'); clearTimeout(self.interfaceTimeout); self.interfaceTimeout = setTimeout(function() { if (!self.exitFullscreen && !self.inputHasFocus && !self.mouseIsInControls) { @@ -1468,15 +1290,7 @@ Ox.VideoPlayer = function(options, self) { self.$controlsBottom && self.$controlsBottom.animate({ opacity: 0 }, 250); - self.$find && self.$find.is(':visible') && self.$find.animate({ - opacity: 0 - }, 250); - self.$volume && self.$volume.is(':visible') && self.$volume.animate({ - opacity: 0 - }, 250); - self.$resolution && self.$resolution.is(':visible') && self.$resolution.animate({ - opacity: 0 - }, 250); + hideControlMenus(); self.$logo && self.$logo.animate({ top: getCSS('logo').top, opacity: 0.25 @@ -1499,21 +1313,46 @@ Ox.VideoPlayer = function(options, self) { }); } + function hideMarkers() { + Ox.forEach(self.$posterMarker, function(marker) { + marker.hide(); + }); + Ox.forEach(self.$pointMarker, function(markers) { + Ox.forEach(markers, function(marker) { + marker.hide(); + }); + }); + } + function loadedmetadata() { Ox.print('LOADEDMETADATA') var hadDuration = !!self.options.duration; - self.loaded = true; + self.loadedMetadata = true; + + self.videoWidth = self.video.videoWidth; + self.videoHeight = self.video.videoHeight; + self.videoCSS = getVideoCSS(); + self.posterMarkerCSS = getPosterMarkerCSS(); + self.$video.css(self.videoCSS); + self.$poster && self.$poster.css(self.videoCSS); + self.$posterMarker && Ox.forEach(self.$posterMarker, function(marker, position) { + marker.css(self.posterMarkerCSS[position]); + }); + self.out = self.options.playInToOut && self.options.out < self.video.duration ? self.options.out : self.video.duration; self.options.duration = self.out - self['in']; - self.$video.css(getCSS('video')); self.video.currentTime = self.options.position; - self.playOnLoad && self.options.paused && togglePaused(); - //self.$poster && self.$poster.css(getCSS('poster')); + + self.options.paused && self.options.showMarkers && setMarkers(); + self.options.paused && self.playOnLoad && togglePaused('button'); + self.$playButton && self.$playButton.options({ + disabled: false + }); hideLoadingIcon(); if (self.options.showIcon || self.options.showIconOnLoad) { @@ -1525,14 +1364,9 @@ Ox.VideoPlayer = function(options, self) { } } - if (!hadDuration) { - self.$timeline && self.$timeline.replaceWith( - self.$timeline = getTimeline() - ); - self.$largeTimeline && self.$largeTimeline.replaceWith( - self.$largeTimeline = getLargeTimeline() - ); - } + !hadDuration && self.$timeline && self.$timeline.replaceWith( + self.$timeline = getTimeline() + ); if (self.options.enableKeyboard && self.options.focus == 'load') { that.gainFocus(); @@ -1540,6 +1374,19 @@ Ox.VideoPlayer = function(options, self) { } + function loadedsubtitles() { + if (self.options.find) { + submitFindInput(self.options.find); + if (self.options.duration) { + // duration was known or video has loaded before subtitles + self.$timeline && self.$timeline.options({ + results: self.results, + subtitles: self.options.subtitles + }); + } + } + } + function parsePositionInput(str) { var split = str.split(':').reverse(); while (split.length > 3) { @@ -1613,8 +1460,10 @@ Ox.VideoPlayer = function(options, self) { } function setMarkers() { - self.options.position == self.options.posterFrame ? - self.$posterMarker.show() : self.$posterMarker.hide(); + Ox.forEach(self.$posterMarker, function(marker) { + self.options.position == self.options.posterFrame ? + marker.show() : marker.hide(); + }); Ox.forEach(self.$pointMarker, function(markers, point) { Ox.forEach(markers, function(marker) { self.options.position == self.options[point] ? @@ -1623,21 +1472,12 @@ Ox.VideoPlayer = function(options, self) { }); } - function hideMarkers() { - self.$posterMarker.hide(); - Ox.forEach(self.$pointMarker, function(markers) { - Ox.forEach(markers, function(marker) { - marker.hide(); - }); - }); - } - function setPosition(position, from) { position = Ox.limit(position, self['in'], self['out']); self.options.position = Math.round( position * self.options.fps ) / self.options.fps; - if (self.loaded && from != 'video') { + if (self.loadedMetadata && from != 'video') { self.video.currentTime = self.options.position; } if (self.iconIsVisible) { @@ -1652,34 +1492,33 @@ Ox.VideoPlayer = function(options, self) { }, 250); self.posterIsVisible = false; } - self.options.paused && setMarkers(); + self.options.paused && self.options.showMarkers && setMarkers(); self.$subtitle && setSubtitle(); self.$timeline /*&& from != 'timeline'*/ && self.$timeline.options({ position: self.options.position }); - self.$largeTimeline && from != 'largeTimeline' && self.$largeTimeline.options({ - position: self.options.position - }); self.$position && self.$position.html(formatPosition()); } function setResolution() { if (!self.options.paused) { self.playOnLoad = true; - togglePaused(); + togglePaused('button'); } - self.loaded = false; + self.loadedMetadata = false; showLoadingIcon(); self.video.src = self.options.video[self.options.resolution]; + self.$playButton && self.$playButton.options({ + disabled: true + }); } function setSizes(callback) { var ms = callback ? 250 : 0; self.width = self.options.fullscreen ? window.innerWidth : self.options.width; self.height = self.options.fullscreen ? window.innerHeight : self.options.height; - self.iconSize = Math.max(Math.round(self.height / 10), 16), - self.iconLeft = parseInt((self.width - self.iconSize) / 2), - self.iconTop = parseInt((self.height - self.iconSize) / 2); + self.videoCSS = getVideoCSS(); + self.iconSize = Math.max(Math.round(self.height / 10), 16); if (self.$timeline || self.$spaceBottom) { self.timelineWidth = getTimelineWidth(); if (self.$timeline) { @@ -1688,8 +1527,8 @@ Ox.VideoPlayer = function(options, self) { } that.animate(getCSS('player'), ms, callback); self.$videoContainer.animate(getCSS('videoContainer'), ms); - self.loaded && self.$video.animate(getCSS('video'), ms); - self.$poster && self.$poster.animate(getCSS('poster'), ms); + self.$video.animate(self.videoCSS, ms); + self.$poster && self.$poster.animate(self.videoCSS, ms); self.$logo && self.$logo.animate(getCSS('logo'), ms); self.$loadingIcon.animate(getCSS('loadingIcon'), ms); self.$playIcon && self.$playIcon.animate(getCSS('playIcon'), ms); @@ -1718,9 +1557,12 @@ Ox.VideoPlayer = function(options, self) { size: Math.min(128, self.width - 56) // fixme: should be width in Ox.Range }); } - self.$largeTimeline && self.$largeTimeline.options({ - width: self.width - }); + if (self.$posterMarker) { + self.posterMarkerCSS = getPosterMarkerCSS(); + Ox.forEach(self.$posterMarker, function(marker, position) { + marker.animate(self.posterMarkerCSS[position], ms); + }); + } } function setSubtitle() { @@ -1765,8 +1607,8 @@ Ox.VideoPlayer = function(options, self) { self.$volumeValue.html(self.options.muted ? 0 : Math.round(self.options.volume * 100)); } - function showInterface() { - Ox.print('showInterface'); + function showControls() { + Ox.print('showControls'); clearTimeout(self.interfaceTimeout); if (!self.interfaceIsVisible) { self.interfaceIsVisible = true; @@ -1823,14 +1665,25 @@ Ox.VideoPlayer = function(options, self) { } function showVolume() { - !self.interfaceIsVisible && showInterface(); + !self.interfaceIsVisible && showControls(); self.$volume && self.$volume.is(':hidden') && toggleVolume(); } function submitFindInput(value, hasPressedEnter) { + Ox.print('submitFindInput', value, hasPressedEnter) self.options.find = value; self.results = find(self.options.find, hasPressedEnter); + Ox.print('results', self.results.length) self.$results.html(self.results.length); + self.$previousButton.options({ + disabled: self.results.length <= 1 + }); + self.$nextButton.options({ + disabled: self.results.length <= 1 + }); + self.$clearButton.options({ + disabled: !self.options.find + }); self.subtitle && setSubtitleText(); self.$timeline && self.$timeline.options({ find: self.options.find, @@ -1871,7 +1724,7 @@ Ox.VideoPlayer = function(options, self) { if (self.focus == 'mouseenter' && !self.mouseHasLeft) { that.gainFocus(); } - self.mouseHasLeft && hideInterface(); + self.mouseHasLeft && hideControls(); } function toggleFind() { @@ -1908,8 +1761,8 @@ Ox.VideoPlayer = function(options, self) { playOnFullscreen && self.video.play(); that.bind({ mousemove: function() { - showInterface(); - hideInterface(); + showControls(); + hideControls(); } }); that.find('.OxControls').bind({ @@ -1920,8 +1773,8 @@ Ox.VideoPlayer = function(options, self) { self.mouseIsInControls = false; } }); - showInterface(); - hideInterface(); + showControls(); + hideControls(); that.gainFocus(); }); } else { @@ -1944,7 +1797,7 @@ Ox.VideoPlayer = function(options, self) { .appendTo(self.$parent); playOnFullscreen && self.video.play(); self.options.enableKeyboard && that.gainFocus(); - //showInterface(); + //showControls(); }); } if (self.$fullscreenButton && from != 'button') { @@ -1999,7 +1852,7 @@ Ox.VideoPlayer = function(options, self) { opacity: 0 }, 250, togglePlayIcon); } - hideMarkers(); + self.options.showMarkers && hideMarkers(); } if (self.$playButton && from != 'button') { self.$playButton.toggleTitle(); @@ -2016,11 +1869,18 @@ Ox.VideoPlayer = function(options, self) { function toggleScale(from) { self.options.scaleToFill = !self.options.scaleToFill; - self.$video.animate(getCSS('video'), 250); - self.$poster && self.$poster.animate(getCSS('poster'), 250); + self.videoCSS = getVideoCSS(); + self.$video.animate(self.videoCSS, 250); + self.$poster && self.$poster.animate(self.videoCSS, 250); if (self.$scaleButton && from != 'button') { self.$scaleButton.toggleTitle(); } + if (self.$posterMarker) { + self.posterMarkerCSS = getPosterMarkerCSS(); + Ox.forEach(self.$posterMarker, function(marker, position) { + marker.animate(self.posterMarkerCSS[position], 250); + }); + } } function toggleSize() { diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index e1752a1a..350be26d 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -456,9 +456,29 @@ Video ================================================================================ */ -.OxThemeClassic .OxVideoPlayer { - background: rgb(255, 255, 255); +.OxThemeClassic .OxVideoPlayer .OxInput { + background: rgba(0, 0, 0, 0); + -moz-box-shadow: 0 0 0; + -webkit-box-shadow: 0 0 0; } +.OxThemeClassic .OxVideoPlayer div.OxInput.OxFocus { + -moz-box-shadow: 0 0 0; + -webkit-box-shadow: 0 0 0; +} +.OxThemeClassic .OxVideoPlayer input.OxInput { + height: 16px; + padding: 0 3px 0 3px; + border: 0; + border-radius: 8px; + color: rgb(255, 255, 255); + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); +} +.OxThemeClassic .OxVideoPlayer .OxRange .OxThumb:active { + background: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background: -webkit-linear-gradient(top, rgba(255, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); +} + /* ================================================================================ diff --git a/source/Ox.UI/themes/modern/css/modern.css b/source/Ox.UI/themes/modern/css/modern.css index f486f570..b8b827d9 100644 --- a/source/Ox.UI/themes/modern/css/modern.css +++ b/source/Ox.UI/themes/modern/css/modern.css @@ -459,15 +459,35 @@ Video background: rgb(48, 48, 48); } -.OxThemeModern .OxVideo.OxFocus { - -moz-box-shadow: 0 0 2px rgb(128, 128, 128); - -webkit-box-shadow: 0 0 2px rgb(128, 128, 128); + +.OxThemeModern .OxVideoPlayer .OxButton.OxDisabled { + background: transparent; + opacity: 0.25; } - -.OxThemeModern .OxVideoPlayer { - background: rgb(0, 0, 0); +.OxThemeModern .OxVideoPlayer .OxInput { + background: transparent; + -moz-box-shadow: 0 0 0; + -webkit-box-shadow: 0 0 0; } +.OxThemeModern .OxVideoPlayer div.OxInput.OxFocus { + -moz-box-shadow: 0 0 0; + -webkit-box-shadow: 0 0 0; +} +.OxThemeModern .OxVideoPlayer input.OxInput { + height: 16px; + padding: 0 3px 0 3px; + border: 0; + border-radius: 8px; + color: rgb(255, 255, 255); + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5)); +} +.OxThemeModern .OxVideoPlayer .OxRange .OxThumb:active { + background: -moz-linear-gradient(top, rgba(64, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); + background: -webkit-linear-gradient(top, rgba(255, 64, 64, 0.5), rgba(0, 0, 0, 0.5)); +} + /* ================================================================================