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

2553 lines
89 KiB
JavaScript
Raw Normal View History

2011-11-05 22:18:26 +00:00
'use strict';
2011-05-12 22:12:41 +00:00
/*@
2012-05-31 10:32:54 +00:00
Ox.VideoPlayer <f> Generic Video Player
2011-05-12 22:12:41 +00:00
options <o> Options
annotations <[]> Array of annotations
id <s> Optional id
in <n> In point (sec)
out <n> Out point (sec)
text <s> Text
2011-10-22 21:03:42 +00:00
censored <a|[]> Array of censored ranges
censoredIcon <s|''> 'Censored' icon
censoredTooltip <s|''> Tooltip for 'censored' icon
2011-08-20 09:48:28 +00:00
controlsBottom <[s]|[]> Bottom controls, from left to right
2011-12-23 10:51:35 +00:00
Can be 'close', fullscreen', 'scale', 'title', 'find', 'open',
2011-12-22 12:40:01 +00:00
'play', 'playInToOut', 'previous', 'next', 'mute', 'volume', 'size',
'timeline', 'position', 'settings', and 'space[int]'. A 'space16'
control, for example, is empty space that is 16px wide, and a
'space' control is empty space that separates left-aligned from
right-aligned controls.
2013-02-12 08:05:30 +00:00
controlsTooltips <o|{}> Tooltip text per control id
2011-08-20 09:48:28 +00:00
controlsTop <[s]|[]> Top controls, from left to right
duration <n|-1> Duration (sec)
2012-02-19 19:06:25 +00:00
enableDownload <b|false> If true, enable download
enableFind <b|false> If true, enable find
enableFullscreen <b|false> If true, enable fullscreen
enableKeyboard <b|false> If true, enable keyboard controls
enableMouse <b|false> If true, click toggles paused and drag changes position
2013-02-12 07:08:53 +00:00
enablePosition <b|false> If true, enable position control
2013-02-12 08:27:22 +00:00
enableSubtitles <b|false> If true, enable subtitles
externalControls <b|false> If true, controls are outside the video
2012-04-19 14:09:28 +00:00
enableTimeline <b|false> If true, show timeline
2011-05-15 16:18:58 +00:00
find <s|''> Query string
focus <s|'click'> focus on 'click', 'load' or 'mouseover'
2011-08-19 10:45:36 +00:00
format <s|''> video format (like 'webm')
fps <n|25> Frames per second
2011-05-15 07:26:00 +00:00
fullscreen <b|false> If true, video is in fullscreen
height <n|144> Height in px (excluding external controls)
in <n> In point (sec)
invertHighlight <b|false> If true, invert selection highlight on timeline
keepIconVisible <b|false> If true, play icon stays visible after mouseleave
keepLargeTimelineVisible <b|false> If true, large timeline stays visible after mouseleave
keepLogoVisible <b|false> If true, logo stays visible after mouseleave
logo <s|''> Logo image URL
logoLink <s|''> Logo link URL
logoTitle <s|''> Text for Logo tooltip // fixme: shouldn't this be logoTooltip then?s
muted <b|false> If true, video is muted
paused <b|false> If true, video is paused
playInToOut <b|false> If true, video plays only from in to out
position <n|0> Initial position (sec)
poster <s|''> Poster URL
posterFrame <n|-1> Position of poster frame (sec)
preload <s|'auto'> 'auto', 'metadata' or 'none'
out <n> Out point (sec)
resolution <n|0> resolution
2011-10-03 10:59:09 +00:00
rewind <b|false> If true, video will rewind when ended
scaleToFill <b|false> If true, scale to fill (otherwise, scale to fit)
showControlsOnLoad <b|false> If true, show controls on load
showFind <b|false> If true, show find input
showHours <b|false> If true, don't show hours for videos shorter than one hour
showIcon <b|false> If true, show play icon
showIconOnLoad <b|false> If true, show icon on load
showLargeTimeline <b|false> If true, show large timeline
2011-05-14 19:32:49 +00:00
showMilliseconds <n|0> Number of decimals to show
showMarkers <b|false> If true, show in/out/poster markers
2011-05-14 19:32:49 +00:00
showProgress <|false> If true, show buffering progress
sizeIsLarge <b|false> If true, initial state of the size control is large
subtitles <s|[o]|[]> URL or SRT or array of subtitles
id <s> Optional id
in <n> In point (sec)
out <n> Out point (sec)
2011-05-12 22:12:41 +00:00
text <s> Text
timeline <s> Timeline image URL
timelineType <s|''> Current timeline type id
timelineTypes <[o]|[]> Array of timeline type objects (id and title)
title <s|''> Video title
type <s|'play'> 'play', 'in' or 'out'
2011-08-19 16:04:59 +00:00
video <s|[s]|o|''> Video URL
String or array of strings ([part1, part2, ...]) or object
({resolution: url, ...} or {resolution: [part1, part2, ...], ...})
volume <n|1> Volume (0-1)
width <n|256> Width in px
2012-03-26 19:26:28 +00:00
self <o> shared private variable
([options[, self]]) -> <o:Ox.Element> Video Player
censored <!> censored
close <!> close
download <!> download
ended <!> ended
find <!> find
fullscreen <!> fullscreen
gotopoint <!> gotopoint
loadedmetadata <!> loadedmetadata
muted <!> muted
open <!> open
paused <!> paused
playing <!> playing
position <!> position
resolution <!> resolution
scale <!> scale
select <!> select
setpoint <!> setpoint
size <!> size
subtitles <!> subtitles
timeline <!> timeline
volume <!> volume
zap <!> zap
2011-05-12 22:12:41 +00:00
@*/
Ox.VideoPlayer = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
annotations: [],
2011-10-22 21:03:42 +00:00
brightness: 1,
censored: [],
censoredIcon: '',
censoredTooltip: '',
2011-05-16 18:05:29 +00:00
controlsBottom: [],
controlsTooltips: {},
2011-05-16 18:05:29 +00:00
controlsTop: [],
duration: 0,
2011-12-22 12:40:01 +00:00
enableDownload: false,
enableFind: false,
enableFullscreen: false,
enableKeyboard: false,
2011-12-19 21:13:11 +00:00
enableMouse: false,
enablePosition: false,
2011-12-22 12:40:01 +00:00
enableSubtitles: false,
2011-12-19 21:13:11 +00:00
enableTimeline: false,
externalControls: false,
2011-05-15 16:18:58 +00:00
find: '',
focus: 'click',
2011-08-19 10:45:36 +00:00
format: '',
fps: 25,
2011-05-15 07:26:00 +00:00
fullscreen: false,
height: 144,
2011-05-14 19:32:49 +00:00
'in': 0,
keepIconVisible: false,
keepLargeTimelineVisible: false,
keepLogoVisible: false,
logo: '',
2011-05-12 22:12:41 +00:00
logoLink: '',
logoTitle: '',
muted: false,
paused: false,
playInToOut: false,
position: 0,
poster: '',
2011-05-18 07:38:11 +00:00
posterFrame: -1,
preload: 'auto',
2011-05-14 19:32:49 +00:00
out: 0,
resolution: 0,
2011-10-03 10:59:09 +00:00
rewind: false,
scaleToFill: false,
showControlsOnLoad: false,
showFind: false,
showHours: false,
showIcon: false,
showIconOnLoad: false,
showLargeTimeline: false,
showMarkers: false,
2011-05-14 19:32:49 +00:00
showMilliseconds: 0,
showProgress: false,
sizeIsLarge: false,
2011-05-12 22:12:41 +00:00
subtitles: [],
timeline: '',
timelineType: '',
timelineTypes: [],
2011-05-12 22:12:41 +00:00
title: '',
type: 'play',
video: '',
volume: 1,
width: 256
})
.options(options || {})
2012-05-28 19:35:41 +00:00
.update({
enableSubtitles: function() {
self.options.enableSubtitles = !self.options.enableSubtitles;
toggleSubtitles();
},
find: setSubtitleText,
fullscreen: function() {
self.options.fullscreen = !self.options.fullscreen;
toggleFullscreen();
},
height: setSizes,
'in': function() {
self.options.paused && setMarkers();
self.$timeline && self.$timeline.options('in', self.options['in']);
},
out: function() {
self.options.paused && setMarkers();
self.$timeline && self.$timeline.options('out', self.options.out);
},
muted: function() {
self.options.muted = !self.options.muted;
toggleMuted();
},
paused: function() {
self.options.paused = !self.options.paused;
togglePaused();
},
position: function() {
setPosition(self.options.position);
},
posterFrame: function() {
self.options.paused && setMarkers();
},
resolution: setResolution,
scaleToFill: function() {
self.options.scaleToFill = !self.options.scaleToFill;
toggleScale();
},
sizeIsLarge: function() {
self.$sizeButton.toggle();
},
volume: function() {
setVolume(self.options.volume);
},
width: setSizes
})
.addClass('OxVideoPlayer');
Ox.Log('VIDEO', 'VIDEO PLAYER OPTIONS', self.options)
2011-08-19 14:44:03 +00:00
2012-05-28 14:06:22 +00:00
Ox.UI.$window.on({
2011-05-15 07:26:00 +00:00
resize: function() {
self.options.fullscreen && setSizes();
}
});
Ox.Fullscreen.bind('change', function() {
//FIXME: is change fired before window size is updated to fullscreen?
self.options.fullscreen && setTimeout(function() {
setSizes(true);
}, 250);
});
if (Ox.isEmpty(self.options.annotations)) {
self.options.annotations = self.options.subtitles;
}
2011-08-19 17:02:38 +00:00
if (Ox.isObject(self.options.video)) {
self.resolutions = Ox.sort(Object.keys(self.options.video));
if (!(self.options.resolution in self.options.video)) {
self.options.resolution = self.resolutions[0];
}
self.video = self.options.video[self.options.resolution];
2011-08-19 17:02:38 +00:00
} else {
2011-08-20 09:48:28 +00:00
self.isPlaylist = Ox.isFunction(self.options.video);
2011-08-19 17:02:38 +00:00
self.video = self.options.video;
}
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; // fixme: ugly
}
2011-05-14 19:32:49 +00:00
self.options.position = Ox.limit(self.options.position, self['in'], self.out);
2011-05-17 18:44:53 +00:00
self.hasVolumeControl = self.options.controlsTop.indexOf('volume') > -1
|| self.options.controlsBottom.indexOf('volume') > -1;
2011-05-14 19:32:49 +00:00
self.millisecondsPerFrame = 1000 / self.options.fps;
self.secondsPerFrame = 1 / self.options.fps;
self.barHeight = 16;
2011-05-15 07:26:00 +00:00
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;
self.results = [];
/*
----------------------------------------------------------------------------
Keyboard
----------------------------------------------------------------------------
*/
2011-05-14 19:32:49 +00:00
if (self.options.enableKeyboard) {
that.bindEvent({
key_0: toggleMuted,
key_1: toggleScale,
2011-05-17 10:34:55 +00:00
key_equal: function() {
changeVolume(0.1);
2011-05-17 10:34:55 +00:00
},
key_escape: hideControlMenus,
key_f: focusFind,
key_g: function() {
goToNextResult(1);
},
2011-05-14 19:32:49 +00:00
key_left: function() {
setPosition(self.options.position - self.secondsPerFrame);
2011-05-15 08:35:00 +00:00
},
2011-05-17 10:34:55 +00:00
key_minus: function() {
changeVolume(-0.1);
2011-05-16 18:05:29 +00:00
},
2011-05-15 08:35:00 +00:00
key_p: function() {
playInToOut();
2011-05-14 19:32:49 +00:00
},
key_right: function() {
setPosition(self.options.position + self.secondsPerFrame);
2011-05-14 19:32:49 +00:00
},
2011-05-15 07:52:37 +00:00
key_shift_f: function() {
self.options.enableFullscreen && toggleFullscreen();
},
key_shift_g: function() {
goToNextResult(-1);
2011-05-15 07:52:37 +00:00
},
key_shift_left: function() {
setPosition(self.options.position - 1);
},
key_shift_right: function() {
setPosition(self.options.position + 1);
},
key_space: togglePaused
});
2011-05-14 19:32:49 +00:00
if (self.options.focus == 'mouseenter') {
2012-05-28 14:06:22 +00:00
that.on({
2011-05-15 16:18:58 +00:00
mouseenter: function() {
if (!self.inputHasFocus) {
that.gainFocus();
}
},
mouseleave: function() {
that.loseFocus();
}
2011-05-14 19:32:49 +00:00
});
} else {
2012-05-28 14:06:22 +00:00
that.on({
click: function() {
var focused = Ox.Focus.focused();
if (
!focused
|| !Ox.UI.elements[focused].is('.OxInput')
) {
that.gainFocus();
}
}
2011-05-14 19:32:49 +00:00
});
}
}
/*
----------------------------------------------------------------------------
Mouse
----------------------------------------------------------------------------
*/
2011-05-15 16:18:58 +00:00
if (
2011-05-16 18:05:29 +00:00
(!self.options.externalControls &&
(self.options.controlsTop.length || self.options.controlsBottom.length)) ||
self.options.showIcon
2011-05-15 16:18:58 +00:00
) {
2012-05-28 14:06:22 +00:00
that.on({
2011-05-15 16:18:58 +00:00
mouseenter: function() {
showControls();
2011-05-15 16:18:58 +00:00
self.mouseHasLeft = false;
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', 'MOUSE HAS ENTERED')
2011-05-15 16:18:58 +00:00
},
mouseleave: function() {
hideControls();
2011-05-15 16:18:58 +00:00
self.mouseHasLeft = true;
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', 'MOUSE HAS LEFT')
2011-05-15 16:18:58 +00:00
}
});
}
/*
----------------------------------------------------------------------------
Video
----------------------------------------------------------------------------
*/
2011-08-24 21:05:39 +00:00
self.$videoContainer = Ox.Element()
.addClass('OxVideoContainer')
.css({
2012-05-26 15:48:19 +00:00
top: self.options.externalControls && self.options.controlsTop.length ? '16px' : 0
2011-05-14 19:32:49 +00:00
})
.appendTo(that)
2011-05-18 16:00:29 +00:00
if (self.options.type == 'play') {
2011-08-24 21:05:39 +00:00
self.options.enableMouse && self.$videoContainer.bindEvent({
anyclick: function(e) {
var $target = $(e.target);
if (!$target.is('.OxLogo') && !$target.is('.OxCensoredIcon')) {
2011-05-18 16:00:29 +00:00
togglePaused();
}
2011-09-04 21:36:41 +00:00
},
dragstart: dragstart,
drag: drag,
dragend: dragend
2011-05-18 16:00:29 +00:00
});
2011-08-19 10:45:36 +00:00
self.$video = Ox.VideoElement(
// autoplay seems to always play from the beginning,
// and poster doesn't seem to work at all
2011-08-19 10:45:36 +00:00
Ox.extend({
preload: self.options.preload,
2012-05-26 15:48:19 +00:00
src: self.video
}, !self.options.paused && !self.options.playInToOut ? {
2011-12-19 21:13:11 +00:00
/*autoplay: 'autoplay'*/
2011-08-19 10:45:36 +00:00
} : {}/*, self.options.poster ? {
poster: self.options.poster
} : {}*/)
)
.bindEvent(Ox.extend({
2011-05-18 16:00:29 +00:00
ended: ended,
loadedmetadata: loadedmetadata,
2011-08-20 09:48:28 +00:00
pointschange: pointschange,
2011-05-18 16:00:29 +00:00
seeked: seeked,
2011-08-20 09:48:28 +00:00
seeking: seeking,
sizechange: sizechange
2011-05-18 16:00:29 +00:00
}, self.options.progress ? {
progress: progress
} : {}))
.appendTo(self.$videoContainer);
2011-08-19 10:45:36 +00:00
self.$video.$element.css({position: 'absolute'});
2011-05-18 16:00:29 +00:00
} else {
2012-05-28 14:06:22 +00:00
self.options.enableMouse && self.$videoContainer.on({
2011-05-18 16:00:29 +00:00
click: function(e) {
if (!$(e.target).is('.OxLogo')) {
goToPoint();
}
}
});
2011-10-22 21:03:42 +00:00
self.$video = $('<div>')
.appendTo(self.$videoContainer);
self.$image = $('<img>')
2011-05-18 16:00:29 +00:00
.attr({
src: Ox.UI.PATH + 'png/transparent.png'
})
2011-10-22 21:03:42 +00:00
.css({
position: 'absolute',
width: '100%',
height: '100%'
})
.appendTo(self.$video)
self.$brightness = $('<div>')
.css({
position: 'absolute',
width: '100%',
height: '100%',
background: 'rgb(0, 0, 0)',
opacity: 1 - self.options.brightness
})
.appendTo(self.$video);
2011-05-18 16:00:29 +00:00
}
/*
----------------------------------------------------------------------------
Poster
----------------------------------------------------------------------------
*/
2011-05-14 19:32:49 +00:00
if (self.options.poster) {
self.$poster = $('<img>')
.addClass('OxPoster')
2011-05-14 19:32:49 +00:00
.attr({
src: self.options.poster
2011-05-12 20:02:22 +00:00
})
.hide()
2013-02-14 07:12:18 +00:00
.one({
load: function() {
self.$poster
.css(getVideoCSS(
self.$poster[0].width,
self.$poster[0].height
))
.show();
2013-02-14 07:12:18 +00:00
self.posterIsVisible = true;
}
})
.appendTo(self.$videoContainer);
2011-05-12 20:02:22 +00:00
}
/*
----------------------------------------------------------------------------
Logo
----------------------------------------------------------------------------
*/
if (self.options.logo) {
self.$logo = $('<img>')
.addClass('OxLogo')
.attr({
src: self.options.logo
})
.css({
cursor: self.options.logoLink ? 'pointer' : 'default'
})
2011-05-14 19:32:49 +00:00
.appendTo(self.$videoContainer);
if (self.options.logoTitle) {
self.$logoTooltip = Ox.Tooltip({
title: self.options.logoTitle
});
}
}
/*
----------------------------------------------------------------------------
Icons
----------------------------------------------------------------------------
*/
self.$loadingIcon = Ox.LoadingIcon({video: true})
.appendTo(self.$videoContainer)
.start();
2011-05-12 10:51:17 +00:00
2011-05-14 19:32:49 +00:00
if (self.options.showIcon || self.options.showIconOnLoad) {
self.$playIcon = $('<img>')
.addClass('OxPlayIcon OxVideo')
2011-05-14 19:32:49 +00:00
.attr({
2011-08-09 17:00:39 +00:00
src: Ox.UI.getImageURL('symbol' + (
self.options.paused ? 'Play' : 'Pause'
2012-12-28 16:58:01 +00:00
), 'video')
2011-05-14 19:32:49 +00:00
})
.appendTo(self.$videoContainer);
2011-05-15 07:26:00 +00:00
if (self.options.showIcon) {
self.$playIcon.addClass('OxInterface');
}
2011-05-14 19:32:49 +00:00
if (self.options.showIconOnLoad) {
self.iconIsVisible = true;
}
}
2011-05-12 22:12:41 +00:00
2011-10-22 21:03:42 +00:00
if (self.options.censored.length) {
self.$copyrightIcon = Ox.Element({
element: '<img>',
tooltip: self.options.censoredTooltip
2011-10-22 21:03:42 +00:00
})
.addClass('OxCensoredIcon OxVideo')
2011-10-22 21:03:42 +00:00
.attr({
2012-12-28 16:58:01 +00:00
src: Ox.UI.getImageURL(
'symbol' + self.options.censoredIcon, 'video'
)
2011-10-22 21:03:42 +00:00
})
.hide()
.bindEvent({
singleclick: function() {
that.triggerEvent('censored');
}
})
2011-10-22 21:03:42 +00:00
.appendTo(self.$videoContainer);
}
/*
----------------------------------------------------------------------------
Markers
----------------------------------------------------------------------------
*/
2011-05-18 07:38:11 +00:00
if (self.options.showMarkers) {
2011-05-18 07:38:11 +00:00
self.$posterMarker = {};
['left', 'center', 'right'].forEach(function(position) {
var titleCase = Ox.toTitleCase(position);
self.$posterMarker[position] = $('<div>')
.addClass('OxPosterMarker OxPosterMarker' + titleCase)
2011-05-18 07:38:11 +00:00
.appendTo(self.$videoContainer);
});
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] = $('<img>')
.addClass('OxPointMarker OxPointMarker' + titleCase)
.attr({
2011-09-02 00:32:23 +00:00
src: Ox.UI.getImageURL('marker' + titleCase)
})
.appendTo(self.$videoContainer);
});
});
2011-05-16 18:05:29 +00:00
}
/*
----------------------------------------------------------------------------
Subtitles
----------------------------------------------------------------------------
*/
2011-12-22 12:40:01 +00:00
if (self.options.subtitles.length || true) { // FIXME
self.$subtitle = $('<div>')
.addClass('OxSubtitle')
.appendTo(self.$videoContainer);
}
/*
----------------------------------------------------------------------------
Controls
----------------------------------------------------------------------------
*/
2011-05-16 18:05:29 +00:00
['top', 'bottom'].forEach(function(edge) {
var titleCase = Ox.toTitleCase(edge);
2011-05-16 18:05:29 +00:00
if (self.options['controls' + titleCase].length) {
2011-05-16 18:05:29 +00:00
self['$controls' + titleCase] = Ox.Bar({
2011-05-14 19:32:49 +00:00
size: self.barHeight
})
.addClass('OxControls' + (self.options.externalControls ? '' : ' OxOnScreen'))
2011-05-14 19:32:49 +00:00
.css({
opacity: self.options.externalControls ? 1 : 0
})
2011-05-16 18:05:29 +00:00
.css(edge, 0)
.appendTo(that);
2011-05-14 19:32:49 +00:00
self.options['controls' + titleCase].forEach(function(control) {
2011-12-19 21:13:11 +00:00
if (control == 'close') {
self.$closeButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-19 21:13:11 +00:00
title: 'close',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Close'),
2011-12-19 21:13:11 +00:00
type: 'image'
})
.bindEvent({
click: function() {
that.triggerEvent('close');
}
})
.appendTo(self['$controls' + titleCase]);
} else if (control == 'find') {
2011-05-16 18:05:29 +00:00
self.$findButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
title: 'find',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Find'),
2011-05-16 18:05:29 +00:00
type: 'image'
})
.bindEvent({
click: toggleFind
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'fullscreen') {
self.$fullscreenButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Enter Fullscreen'), Ox._('Exit Fullscreen')],
2011-12-22 07:24:20 +00:00
type: 'image',
2011-12-22 12:40:01 +00:00
value: self.options.fullscreen ? 'shrink' : 'grow',
2011-12-22 07:24:20 +00:00
values: ['grow', 'shrink']
2011-05-16 18:05:29 +00:00
})
.bindEvent({
click: function() {
toggleFullscreen('button');
}
2011-05-16 18:05:29 +00:00
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
2011-05-18 16:00:29 +00:00
} else if (control == 'goto') {
self.$setButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-05-18 16:00:29 +00:00
title: 'goTo' + Ox.toTitleCase(self.options.type),
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Go to ' + Ox.toTitleCase(self.options.type) + ' Point'),
2011-05-18 16:00:29 +00:00
type: 'image'
})
.bindEvent({
click: goToPoint
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'mute') {
self.$muteButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Mute'), Ox._('Unmute')],
2011-12-22 07:24:20 +00:00
type: 'image',
value: self.options.muted ? 'unmute' : 'mute',
values: ['mute', 'unmute']
2011-05-16 18:05:29 +00:00
})
.bindEvent({
click: function() {
toggleMuted('button');
}
2011-05-16 18:05:29 +00:00
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
2011-08-20 09:48:28 +00:00
} else if (control == 'next') {
self.$nextClipButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-08-20 09:48:28 +00:00
title: 'arrowRight',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Next'),
2011-08-20 09:48:28 +00:00
type: 'image'
})
.bindEvent({
click: function() {
goToNextClip(1);
}
})
.appendTo(self['$controls' + titleCase]);
2011-12-23 10:51:35 +00:00
} else if (control == 'open') {
self.$openButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-23 10:51:35 +00:00
title: 'arrowRight',
tooltip: self.options.controlsTooltips.open || '',
2011-12-23 10:51:35 +00:00
type: 'image'
})
.bindEvent({
click: function() {
that.triggerEvent('open');
}
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'play') {
self.$playButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-05-16 18:05:29 +00:00
// FIXME: this is retarded, fix Ox.Button
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Play'), Ox._('Pause')],
2011-12-22 07:24:20 +00:00
type: 'image',
value: self.options.paused ? 'play' : 'pause',
values: ['play', 'pause']
2011-05-16 18:05:29 +00:00
})
.bindEvent({
click: function() {
togglePaused('button');
}
2011-05-16 18:05:29 +00:00
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'playInToOut') {
2011-05-16 18:05:29 +00:00
self.$playInToOutButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-05-16 18:05:29 +00:00
title: 'playInToOut',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Play In to Out'),
2011-05-16 18:05:29 +00:00
type: 'image'
})
.bindEvent({
click: playInToOut
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'position') {
self.positionWidth = getPositionWidth();
self.$position = Ox.Element({
tooltip: self.options.type == 'play' ? 'Position'
: self.options.type == 'in' ? 'In Point'
: 'Out Point'
})
.addClass('OxPosition')
2011-05-16 18:05:29 +00:00
.css({
2012-05-26 15:48:19 +00:00
width: self.positionWidth - 4 + 'px'
2011-05-16 18:05:29 +00:00
})
.html(formatPosition())
2012-05-28 14:06:22 +00:00
.on({
2011-05-16 18:05:29 +00:00
click: function() {
2011-12-19 21:13:11 +00:00
if (self.options.enablePosition) {
if (self.options.type == 'play') {
if (!self.options.paused) {
self.playOnSubmit = true;
togglePaused();
} else if (self.playOnLoad) {
// if clicked during resolution switch,
// don't play on load
self.playOnLoad = false;
self.playOnSubmit = true;
}
2011-05-18 16:00:29 +00:00
}
2011-12-19 21:13:11 +00:00
self.$position.hide();
self.$positionInput
2011-12-21 15:33:52 +00:00
.value(formatPosition())
2011-12-19 21:13:11 +00:00
.show()
.focusInput(false);
2011-05-16 18:05:29 +00:00
}
}
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
self.$positionInput = Ox.Input({
value: formatPosition(),
width: self.positionWidth
2011-05-14 19:32:49 +00:00
})
.addClass('OxPositionInput')
2011-05-16 18:05:29 +00:00
.bindEvent({
focus: function() {
self.inputHasFocus = true;
},
blur: function() {
self.inputHasFocus = false;
submitPositionInput();
},
submit: function() {
self.inputHasFocus = false;
submitPositionInput();
2011-05-16 18:05:29 +00:00
}
})
.appendTo(self['$controls' + titleCase].$element);
2011-05-16 18:05:29 +00:00
self.$positionInput.children('input').css({
width: (self.positionWidth - 6) + 'px',
fontSize: '9px'
2011-05-16 18:05:29 +00:00
});
2011-08-20 09:48:28 +00:00
} else if (control == 'previous') {
self.$previousClipButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-08-20 09:48:28 +00:00
title: 'arrowLeft',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Previous'),
2011-08-20 09:48:28 +00:00
type: 'image'
})
.bindEvent({
click: function() {
goToNextClip(-1);
}
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'scale') {
self.$scaleButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Scale to Fill'), Ox._('Scale to Fit')],
2011-12-22 07:24:20 +00:00
type: 'image',
value: self.options.scaleToFill ? 'fit' : 'fill',
values: ['fill', 'fit']
2011-05-16 18:05:29 +00:00
})
2011-12-22 12:40:01 +00:00
.bindEvent('change', function() {
toggleScale('button');
2011-05-16 18:05:29 +00:00
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
2011-05-18 16:00:29 +00:00
} else if (control == 'set') {
self.$setButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-05-18 16:00:29 +00:00
title: 'set' + Ox.toTitleCase(self.options.type),
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Set ' + Ox.toTitleCase(self.options.type) + ' Point'),
2011-05-18 16:00:29 +00:00
type: 'image'
})
.bindEvent({
click: setPoint
})
.appendTo(self['$controls' + titleCase]);
2011-12-22 12:40:01 +00:00
} else if (control == 'settings') {
self.$settingsButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-22 12:40:01 +00:00
title: 'set',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Settings'),
2011-12-22 12:40:01 +00:00
type: 'image'
})
.bindEvent({
click: function() {
self.$settings.toggle();
}
})
.appendTo(self['$controls' + titleCase]);
self.$settings = renderSettings().appendTo(that);
2011-12-22 12:40:01 +00:00
2011-05-16 18:05:29 +00:00
} else if (control == 'size') {
self.$sizeButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Larger'), Ox._('Smaller')],
2011-12-22 07:24:20 +00:00
type: 'image',
value: self.options.sizeIsLarge ? 'shrink' : 'grow',
values: ['grow', 'shrink']
2011-05-16 18:05:29 +00:00
})
2011-12-22 12:40:01 +00:00
.bindEvent('change', toggleSize)
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'space') {
self['$space' + titleCase] = $('<div>')
2011-05-16 18:05:29 +00:00
.html('&nbsp;') // fixme: ??
.appendTo(self['$controls' + titleCase].$element);
2011-05-16 18:05:29 +00:00
} else if (Ox.startsWith(control, 'space')) {
$('<div>')
.css({
width: parseInt(control.substr(5)) + 'px',
height: '16px'
})
.appendTo(self['$controls' + titleCase].$element);
2011-05-16 18:05:29 +00:00
} else if (control == 'timeline') {
/*
if (self.options.showProgress) {
self.$progress = $('<img>')
.attr({
src: getProgressImageURL()
})
.css({
float: 'left',
height: self.barHeight + 'px',
})
.appendTo(self.$timelineImages.$element);
}
*/
if (self.options.duration) {
self.$timeline = getTimeline()
} else {
self.$timeline = Ox.Element()
.html('&nbsp;');
}
self.$timeline.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
} else if (control == 'title') {
self.$title = $('<div>')
.addClass('OxTitle')
2011-05-16 18:05:29 +00:00
.html(self.options.title)
.appendTo(self['$controls' + titleCase].$element);
2011-05-16 18:05:29 +00:00
} else if (control == 'volume') {
2011-05-14 19:32:49 +00:00
2011-05-16 18:05:29 +00:00
self.$volumeButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-23 05:19:02 +00:00
title: getVolumeImage(),
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Volume'),
2011-05-16 18:05:29 +00:00
type: 'image'
})
2011-05-17 07:43:20 +00:00
.bindEvent({
click: toggleVolume
2011-05-16 18:05:29 +00:00
})
.appendTo(self['$controls' + titleCase]);
2011-05-14 19:32:49 +00:00
2011-12-24 06:07:50 +00:00
} else if (control == 'zapHome') {
self.$zapHomeButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-24 06:07:50 +00:00
title: 'up',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Home Channel'),
2011-12-24 06:07:50 +00:00
type: 'image'
})
.bindEvent({
click: function() {
that.triggerEvent('zap', {direction: 0});
}
})
.appendTo(self['$controls' + titleCase]);
} else if (control == 'zapNext') {
self.$zapNextButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-24 06:07:50 +00:00
title: 'right',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Next Channel'),
2011-12-24 06:07:50 +00:00
type: 'image'
})
.bindEvent({
click: function() {
that.triggerEvent('zap', {direction: 1});
}
})
.appendTo(self['$controls' + titleCase]);
} else if (control == 'zapPrevious') {
self.$zapPreviousButton = Ox.Button({
2013-01-31 11:58:35 +00:00
style: 'video',
2011-12-24 06:07:50 +00:00
title: 'left',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Previous Channel'),
2011-12-24 06:07:50 +00:00
type: 'image'
})
.bindEvent({
click: function() {
that.triggerEvent('zap', {direction: -1});
}
})
.appendTo(self['$controls' + titleCase]);
2011-05-16 18:05:29 +00:00
}
2011-05-16 18:05:29 +00:00
});
2011-05-14 19:32:49 +00:00
2011-05-16 18:05:29 +00:00
}
2011-05-16 18:05:29 +00:00
});
/*
----------------------------------------------------------------------------
Find
----------------------------------------------------------------------------
*/
2011-05-12 20:02:22 +00:00
if (self.options.enableFind) {
self.$find = $('<div>')
.addClass('OxControls OxFind')
2011-05-16 18:05:29 +00:00
.css({
top: self.options.controlsTop.length ? '16px' : 0
2011-05-16 18:05:29 +00:00
})
.appendTo(that);
self.$results = Ox.Element({
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Results')
})
.addClass('OxResults')
.html('0')
.appendTo(self.$find);
2011-08-20 09:48:28 +00:00
self.$previousResultButton = Ox.Button({
disabled: true,
style: 'symbol',
title: 'arrowLeft',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Previous'),
type: 'image'
})
.bindEvent({
click: function() {
goToNextResult(-1);
}
})
.appendTo(self.$find);
2011-08-20 09:48:28 +00:00
self.$nextResultButton = Ox.Button({
disabled: true,
style: 'symbol',
title: 'arrowRight',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Next'),
type: 'image'
})
.bindEvent({
click: function() {
goToNextResult(1);
}
2011-05-16 18:05:29 +00:00
})
.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.$clearButton = Ox.Button({
disabled: !self.options.find,
style: 'symbol',
title: 'delete',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Clear'),
type: 'image'
})
.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',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Hide'),
type: 'image'
})
.bindEvent({
click: toggleFind
})
.appendTo(self.$find);
}
/*
----------------------------------------------------------------------------
Volume
----------------------------------------------------------------------------
*/
if (self.hasVolumeControl) {
self.$volume = $('<div>')
.addClass('OxControls OxVolume')
2011-05-16 18:05:29 +00:00
.css({
bottom: self.options.controlsBottom.length ? '16px' : 0
2011-05-16 18:05:29 +00:00
})
.appendTo(that);
2011-05-16 18:05:29 +00:00
self.$hideVolumeButton = Ox.Button({
style: 'symbol',
title: 'close',
2013-05-09 13:03:33 +00:00
tooltip: Ox._('Hide'),
type: 'image'
})
.bindEvent({
2011-05-17 07:43:20 +00:00
click: toggleVolume
})
.appendTo(self.$volume);
2011-05-16 18:05:29 +00:00
self.$muteButton = Ox.Button({
style: 'symbol',
2013-05-09 13:03:33 +00:00
tooltip: [Ox._('Mute'), Ox._('Unmute')],
2011-12-22 12:40:01 +00:00
type: 'image',
2011-12-22 07:24:20 +00:00
value: self.options.muted ? 'unmute' : 'mute',
values: ['mute', 'unmute']
2011-05-16 18:05:29 +00:00
})
.bindEvent({
click: function() {
toggleMuted('button');
2011-05-16 18:05:29 +00:00
}
})
.appendTo(self.$volume);
self.$volumeInput = Ox.Range({
2011-12-21 15:33:52 +00:00
changeOnDrag: true,
2011-05-16 18:05:29 +00:00
max: 1,
min: 0,
step: 0.001,
value: self.options.muted ? 0 : self.options.volume
})
.bindEvent({
2011-05-17 10:34:55 +00:00
change: function(data) {
setVolume(data.value);
}
2011-05-16 18:05:29 +00:00
})
.appendTo(self.$volume);
self.$volumeValue = $('<div>')
.addClass('OxVolumeValue')
2011-05-16 18:05:29 +00:00
.html(self.options.muted ? 0 : Math.round(self.options.volume * 100))
.appendTo(self.$volume);
2011-05-12 20:02:22 +00:00
}
2011-10-22 21:03:42 +00:00
self.options.type != 'play' && setPosition(self.options.position);
2011-05-18 18:30:58 +00:00
self.results = [];
if (self.options.subtitles) {
if (Ox.isArray(self.options.subtitles)) {
loadedsubtitles();
2011-05-17 08:58:03 +00:00
} else {
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 = [];
}
2011-05-17 08:58:03 +00:00
}
}
2011-05-16 18:05:29 +00:00
2011-12-23 05:19:02 +00:00
setSizes(false, function() {
self.options.fullscreen && enterFullscreen();
});
2011-05-14 19:32:49 +00:00
2011-10-22 21:03:42 +00:00
function censor() {
if (self.options.type == 'play') {
self.$video
2011-10-24 16:38:19 +00:00
.brightness(self.censored ? 0.05 : self.options.brightness)
2011-10-22 21:03:42 +00:00
.volume(self.censored ? 0.01 : self.options.volume);
} else {
self.$brightness.css({
2011-10-24 16:38:19 +00:00
opacity: 1 - (self.censored ? 0.05 : self.options.brightness)
2011-10-22 21:03:42 +00:00
});
}
self.$copyrightIcon[self.censored ? 'show' : 'hide']();
}
function changeVolume(num) {
self.hasVolumeControl && showVolume();
self.options.volume = Ox.limit(self.options.volume + num, 0, 1);
setVolume(self.options.volume);
self.$volumeInput && self.$volumeInput.value(self.options.volume);
}
2011-05-15 16:18:58 +00:00
function clearInterfaceTimeout() {
clearTimeout(self.interfaceTimeout);
self.interfaceTimeout = 0;
}
2011-09-04 21:36:41 +00:00
function dragstart() {
self.drag = {
position: self.options.position,
paused: self.options.paused
2011-05-14 19:32:49 +00:00
}
2011-09-04 21:36:41 +00:00
!self.options.paused && togglePaused();
}
function drag(e) {
setPosition(self.drag.position - e.clientDX / 25);
that.triggerEvent('position', {
position: self.options.position
});
}
function dragend() {
!self.drag.paused && togglePaused();
}
function ended() {
!self.options.paused && togglePaused();
2011-05-14 19:32:49 +00:00
if (self.options.poster) {
self.$poster.animate({
opacity: 1
}, 250);
self.posterIsVisible = true;
}
if (self.options.showIconOnLoad) {
self.$playIcon.animate({
opacity: 1
}, 250);
self.iconIsVisible = true;
}
2011-10-03 10:59:09 +00:00
self.options.rewind && rewind();
that.triggerEvent('ended');
2011-05-12 20:02:22 +00:00
}
function enterFullscreen() {
2012-05-28 14:06:22 +00:00
that.on({
mousemove: function() {
showControls();
hideControls();
}
});
2011-12-23 07:15:40 +00:00
showControls();
hideControls();
2012-05-28 14:06:22 +00:00
that.find('.OxControls').on({
mouseenter: function() {
self.mouseIsInControls = true;
},
mouseleave: function() {
self.mouseIsInControls = false;
}
});
that.gainFocus();
}
function find(query) {
2011-05-16 18:05:29 +00:00
var results = [];
if (query.length) {
query = query.toLowerCase();
2012-05-22 14:29:37 +00:00
results = Ox.filter(self.options.annotations, function(annotation) {
return Ox.decodeHTMLEntities(Ox.stripTags(
annotation.text.toLowerCase()
2012-05-22 14:29:37 +00:00
)).indexOf(query) > -1;
}).map(function(annotation) {
return {
id: annotation.id,
'in': annotation['in'],
out: annotation.out
2012-05-22 14:29:37 +00:00
};
})
results = Ox.filter(self.options.annotations, function(annotation) {
return Ox.decodeHTMLEntities(Ox.stripTags(
2012-05-22 14:29:37 +00:00
annotation.text.toLowerCase()
)).indexOf(query) > -1;
}).map(function(annotation) {
return {
id: annotation.id,
'in': annotation['in'],
out: annotation.out
};
2011-05-16 18:05:29 +00:00
});
}
return results;
}
function focusFind() {
!self.interfaceIsVisible && showControls();
// need timeout so the "f" doesn't appear in the input field
setTimeout(function() {
if (self.$find.is(':hidden')) {
toggleFind();
} else {
2011-12-18 09:44:11 +00:00
self.$findInput.focusInput(true);
}
}, 0);
}
2011-05-14 19:32:49 +00:00
function formatPosition(position) {
position = Ox.isUndefined(position) ? self.options.position : position;
return Ox.formatDuration(position, self.options.showMilliseconds);
}
2011-10-22 21:03:42 +00:00
function getCensored() {
var censored = false;
Ox.forEach(self.options.censored, function(v) {
if (
v['in'] < self.options.position
&& v.out > self.options.position
) {
censored = true;
2012-07-05 08:58:08 +00:00
return false; // break
2011-10-22 21:03:42 +00:00
}
});
return censored;
}
2011-05-15 08:35:00 +00:00
function getCSS(element) {
var css;
2011-10-22 21:03:42 +00:00
if (element == 'copyrightIcon') {
css = {
width: self.iconSize + 'px',
height: self.iconSize + 'px'
};
} else if (element == 'controlsTop' || element == 'controlsBottom') {
2011-05-15 08:35:00 +00:00
css = {
width: self.width + 'px'
};
2011-05-16 18:05:29 +00:00
} else if (element == 'find') {
css = {
width: Math.min(216, self.width) + 'px' // 128 + 4 * 16 + 24
2011-05-16 18:05:29 +00:00
};
2011-05-15 08:35:00 +00:00
} else if (element == 'loadingIcon') {
css = {
width: self.iconSize + 'px',
height: self.iconSize + 'px'
};
} else if (element == 'logo') {
2011-05-15 16:18:58 +00:00
var logoHeight = Math.round(self.height / 10),
logoMargin = Math.round(self.height / 20);
2011-05-15 08:35:00 +00:00
css = {
2011-05-15 16:18:58 +00:00
left: logoMargin + 'px',
2011-05-16 18:05:29 +00:00
top: logoMargin + (self.controlsTopAreVisible ? 16 : 0) + 'px',
2012-05-26 15:48:19 +00:00
height: logoHeight + 'px'
2011-05-15 08:35:00 +00:00
};
} else if (element == 'player') {
2011-05-17 07:43:20 +00:00
var height = self.options.fullscreen ? window.innerHeight : self.height;
if (self.options.externalControls) {
height += (
!!self.options.controlsTop.length +
!!self.options.controlsBottom.length
) * self.barHeight;
}
2011-05-15 08:35:00 +00:00
css = Ox.extend({
width: self.width + 'px',
2011-05-17 07:43:20 +00:00
height: height + 'px'
2011-05-15 08:35:00 +00:00
}, self.options.fullscreen ? {
left: 0,
top: 0
} : {}, self.exitFullscreen ? {
left: self.absoluteOffset.left,
top: self.absoluteOffset.top
} : {});
} else if (element == 'playIcon') {
var playIconPadding = Math.round(self.iconSize * 1/8),
playIconSize = self.iconSize - 2 * playIconPadding - 4;
css = {
width: playIconSize + 'px',
height: playIconSize + 'px',
padding: playIconPadding + 'px',
borderRadius: Math.round(self.iconSize / 2) + 'px'
};
} else if (element == 'progress') {
css = {
width: self.timelineImageWidth + 'px',
marginLeft: -self.timelineImageWidth + 'px'
};
} else if (element == 'subtitle') {
css = {
bottom: (Math.floor(self.height / 16) + !!self.controlsBottomAreVisible * 16) + 'px',
2011-05-15 08:35:00 +00:00
width: self.width + 'px',
fontSize: Math.floor(self.height / 20) + 'px',
2011-05-15 08:35:00 +00:00
WebkitTextStroke: (self.height / 1000) + 'px rgb(0, 0, 0)'
};
2011-05-16 18:05:29 +00:00
} else if (element == 'spaceBottom' || element == 'timeline') {
2011-05-15 08:35:00 +00:00
css = {
width: self.timelineWidth + 'px'
};
2011-05-16 18:05:29 +00:00
} else if (element == 'spaceTop' || element == 'title') {
css = {
width: getTitleWidth() + 'px'
};
2011-05-15 08:35:00 +00:00
} else if (element == 'videoContainer') {
css = {
width: self.width + 'px',
height: self.height + 'px'
};
2011-05-16 18:05:29 +00:00
} else if (element == 'volume') {
css = {
width: Math.min(184, self.width)
2011-05-16 18:05:29 +00:00
};
2011-05-15 08:35:00 +00:00
}
return css;
}
2011-05-14 19:32:49 +00:00
function getPosition(e) {
// fixme: no offsetX in firefox???
if ($.browser.mozilla) {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', e, e.layerX - 56)
2011-05-14 19:32:49 +00:00
return Ox.limit(
2011-08-19 10:45:36 +00:00
(e.layerX - 48 - self.barHeight / 2) / self.timelineImageWidth * self.$video.duration(),
0, self.$video.duration()
2011-05-14 19:32:49 +00:00
);
} else {
2011-11-04 15:54:28 +00:00
/*Ox.Log('Video', e.offsetX, Ox.limit(
2011-05-14 19:32:49 +00:00
(e.offsetX - self.barHeight / 2) / self.timelineImageWidth * self.video.duration,
0, self.video.duration
))*/
return Ox.limit(
2011-08-19 10:45:36 +00:00
(e.offsetX - self.barHeight / 2) / self.timelineImageWidth * self.$video.duration(),
0, self.$video.duration()
2011-05-14 19:32:49 +00:00
);
}
2011-05-14 19:32:49 +00:00
}
function getPositionWidth() {
return 48 + !!self.options.showMilliseconds * 2
+ self.options.showMilliseconds * 6;
}
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'
}
};
}
2011-05-14 19:32:49 +00:00
function getProgressImageURL() {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', '---', self.timelineImageWidth)
2011-05-14 19:32:49 +00:00
if (!self.timelineImageWidth) return;
var width = self.timelineImageWidth,
height = self.barHeight,
2011-05-14 19:32:49 +00:00
canvas = $('<canvas>')
.attr({
width: width,
2011-05-14 19:32:49 +00:00
height: height
})[0],
context = canvas.getContext('2d'),
imageData, data;
context.fillStyle = 'rgba(255, 0, 0, 0.5)';
context.fillRect(0, 0, width, height);
2011-05-14 19:32:49 +00:00
imageData = context.getImageData(0, 0, width, height),
data = imageData.data;
self.buffered.forEach(function(range) {
2011-08-19 10:45:36 +00:00
var left = Math.round(range[0] * width / self.$video.duration()),
right = Math.round(range[1] * width / self.$video.duration());
Ox.loop(left, right, function(x) {
Ox.loop(height, function(y) {
index = x * 4 + y * 4 * width;
data[index + 3] = 0;
});
});
});
context.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
2011-05-12 22:12:41 +00:00
function getSubtitle() {
var subtitle = '';
2011-12-22 12:40:01 +00:00
self.options.enableSubtitles && Ox.forEach(self.options.subtitles, function(v) {
2011-05-12 22:12:41 +00:00
if (
2011-10-22 21:03:42 +00:00
v['in'] <= self.options.position
&& v.out >= self.options.position
2011-05-12 22:12:41 +00:00
) {
2011-05-17 19:30:49 +00:00
subtitle = v.text;
2012-07-05 08:58:08 +00:00
return false; // break
2011-05-12 22:12:41 +00:00
}
});
return subtitle;
}
function getTimeline() {
var $timeline = Ox.SmallVideoTimeline({
2012-01-12 19:04:32 +00:00
//_offset: getTimelineLeft(),
2011-12-19 21:13:11 +00:00
disabled: !self.options.enableTimeline,
duration: self.options.duration,
2011-05-17 18:04:26 +00:00
find: self.options.find,
imageURL: self.options.timeline,
'in': self.options['in'],
invertHighlight: self.options.invertHighlight,
mode: 'player',
out: self.options.out,
paused: self.options.paused,
2011-12-23 07:15:40 +00:00
position: self.options.position,
results: self.results,
showInToOut: self.options.playInToOut,
showMilliseconds: self.options.showMilliseconds,
subtitles: self.options.enableSubtitles ? self.options.subtitles : [],
width: getTimelineWidth()
})
.css({float: 'left'})
.css({background: '-moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'})
.css({background: '-o-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))'})
.bindEvent({
position: function(data) {
setPosition(data.position, 'timeline');
2011-08-19 20:37:58 +00:00
that.triggerEvent('position', {
position: self.options.position
});
}
});
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', '??', $timeline.find('.OxInterface'))
$timeline.children().css({
marginLeft: getTimelineLeft() + 'px'
});
$timeline.find('.OxInterface').css({
marginLeft: getTimelineLeft() + 'px'
});
return $timeline;
}
function getTimelineLeft() {
var left = 0;
2011-05-16 18:05:29 +00:00
Ox.forEach(self.options.controlsBottom, function(control) {
if (control == 'timeline') {
2012-07-05 08:58:08 +00:00
return false; // break
}
left += control == 'position' ? self.positionWidth : 16
});
return left;
}
function getTimelineWidth() {
return (self.options.fullscreen ? window.innerWidth : self.options.width) -
2011-05-16 18:05:29 +00:00
self.options.controlsBottom.reduce(function(prev, curr) {
return prev + (
curr == 'timeline' || curr == 'space' ? 0
: Ox.startsWith(curr, 'space') ? parseInt(curr.substr(5))
: curr == 'position' ? getPositionWidth()
: 16
);
}, 0);
}
2011-05-16 18:05:29 +00:00
function getTitleWidth() {
return (self.options.fullscreen ? window.innerWidth : self.options.width) -
self.options.controlsTop.reduce(function(prev, curr) {
return prev + (
curr == 'title' || curr == 'space' ? 0
: Ox.startsWith(curr, 'space') ? parseInt(curr.substr(5))
: 16
2011-05-16 18:05:29 +00:00
);
}, 0);
}
2013-02-14 07:12:18 +00:00
function getVideoCSS(videoWidth, videoHeight) {
// optional arguments allow for this function to be used for poster CSS
var playerWidth = self.width,
playerHeight = self.height,
playerRatio = playerWidth / playerHeight,
2013-02-14 07:12:18 +00:00
videoWidth = videoWidth || self.videoWidth,
videoHeight = 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: Math.floor((playerWidth - width) / 2),
top: Math.floor((playerHeight - height) / 2),
width: width,
height: height
};
}
2011-12-23 05:19:02 +00:00
function getVolumeImage() {
2011-05-16 18:05:29 +00:00
var symbol;
if (self.options.muted || self.options.volume == 0) {
symbol = 'Unmute';
2011-05-16 18:05:29 +00:00
} else if (self.options.volume < 1/3) {
symbol = 'VolumeUp';
} else if (self.options.volume < 2/3) {
symbol = 'VolumeDown';
} else {
symbol = 'Mute';
2011-05-16 18:05:29 +00:00
}
2011-12-23 05:19:02 +00:00
return symbol;
2011-05-16 18:05:29 +00:00
}
2011-08-20 09:48:28 +00:00
function goToNextClip(direction) {
self.$video[direction == 1 ? 'playNext' : 'playPrevious']();
}
function goToNextResult(direction) {
var found = false,
result;
if (self.results.length) {
direction == -1 && self.results.reverse();
Ox.forEach(self.results, function(v) {
if (
direction == 1
? v['in'] > self.options.position
: v.out < self.options.position
) {
result = v
found = true;
2012-07-05 08:58:08 +00:00
return false; // break
}
});
direction == -1 && self.results.reverse();
if (!found) {
result = self.results[direction == 1 ? 0 : self.results.length - 1];
2011-08-20 09:48:28 +00:00
}
setPosition(result['in'] + self.secondsPerFrame);
that.triggerEvent('position', {
position: self.options.position
});
result.id && that.triggerEvent('select', result);
2011-08-20 09:48:28 +00:00
}
}
2011-05-18 16:00:29 +00:00
function goToPoint() {
that.triggerEvent('gotopoint');
}
function hideControlMenus() {
2011-12-22 12:40:01 +00:00
['find', 'settings', 'volume'].forEach(function(element) {
var $element = self['$' + element];
$element && $element.is(':visible') && $element.animate({
opacity: 0
}, 250, function() {
$element.hide().css({opacity: 1});
});
});
//self.options.fullscreen && hideControls();
}
function hideControls() {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', 'hideControls');
clearTimeout(self.interfaceTimeout);
2011-05-15 16:18:58 +00:00
self.interfaceTimeout = setTimeout(function() {
if (!self.exitFullscreen && !self.inputHasFocus && !self.mouseIsInControls) {
self.interfaceIsVisible = false;
2011-05-16 18:05:29 +00:00
self.controlsTopAreVisible = false;
self.controlsBottomAreVisible = false;
self.$controlsTop && self.$controlsTop.animate({
opacity: 0
}, 250);
self.$controlsBottom && self.$controlsBottom.animate({
opacity: 0
}, 250);
hideControlMenus();
self.$logo && self.$logo.animate({
2011-05-15 16:18:58 +00:00
top: getCSS('logo').top,
opacity: 0.25
}, 250, function() {
2012-05-28 14:06:22 +00:00
self.options.logoLink && self.$logo.off('click');
self.options.logoTitle &&
2012-05-28 14:06:22 +00:00
self.$logo.off('mouseenter mouseleave');
});
2011-05-14 19:32:49 +00:00
self.$subtitle && self.$subtitle.animate({
2012-05-26 15:48:19 +00:00
bottom: getCSS('subtitle').bottom
2011-05-15 16:18:58 +00:00
}, 250);
}
}, self.options.fullscreen ? 2500 : 1000);
}
function hideLoadingIcon() {
self.$loadingIcon.hide().stop();
2011-05-12 10:51:17 +00:00
}
function hideMarkers() {
self.$posterMarker && Ox.forEach(self.$posterMarker, function(marker) {
marker.hide();
});
self.$pointMarker && Ox.forEach(self.$pointMarker, function(markers) {
Ox.forEach(markers, function(marker) {
marker.hide();
});
});
}
2011-05-18 18:30:58 +00:00
function isEqual(a, b) {
return Math.abs(a - b) < 0.001;
}
function isResolution(str) {
return str.slice(0, -1).match(/^\d+$/) && str.slice(-1) == 'p';
}
2011-05-18 16:00:29 +00:00
function loadImage() {
2011-10-22 21:03:42 +00:00
self.$image
2011-05-18 16:00:29 +00:00
.one({
load: function() {
hideLoadingIcon();
}
})
.attr({
src: self.options.video(
// fixme: this keeps the frame from being beyond the end,
// but what should be avoided is setting position to a point
// beyond the beginning of the last frame
Math.min(
self.options.position,
Math.floor(self.options.duration * self.options.fps) / self.options.fps
),
self.options.width
)
2011-05-18 16:00:29 +00:00
});
}
function loadedmetadata() {
2011-11-04 15:54:28 +00:00
Ox.Log('Video', 'LOADEDMETADATA')
var hadDuration = !!self.options.duration;
self.loadedMetadata = true;
2011-08-19 10:45:36 +00:00
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.out < self.$video.duration()
? self.out : self.$video.duration();
2011-05-14 19:32:49 +00:00
self.options.duration = self.out - self['in'];
2011-11-04 15:54:28 +00:00
Ox.Log('Video', '---------------------------------------- POS', self.options.position)
2011-08-19 16:49:00 +00:00
//self.options.position = Ox.limit(self.options.position, self['in'], self.out);
2011-10-22 21:03:42 +00:00
//self.$video.currentTime(self.options.position);
setPosition(self.options.position);
self.$video.muted(self.options.muted).volume(self.options.volume);
2011-12-19 21:13:11 +00:00
if (!self.options.paused) {
self.options.paused = true;
togglePaused('button');
2011-12-19 21:13:11 +00:00
} else if (self.options.paused && self.playOnLoad) {
togglePaused('button');
}
2011-12-22 07:24:20 +00:00
self.$playButton && self.$playButton.options({disabled: false});
hideLoadingIcon();
2011-05-14 19:32:49 +00:00
if (self.options.showIcon || self.options.showIconOnLoad) {
//!self.options.keepIconVisible && self.$playIcon.addClass('OxInterface');
if (self.options.showIconOnLoad) {
self.$playIcon.animate({
opacity: 1
}, 250);
}
2011-05-14 19:32:49 +00:00
}
!hadDuration && self.$timeline && self.$timeline.replaceWith(
self.$timeline = getTimeline()
);
if (self.options.enableKeyboard && self.options.focus == 'load') {
that.gainFocus();
}
that.triggerEvent('loadedmetadata');
}
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 playing() {
2011-08-19 10:45:36 +00:00
self.options.position = self.$video.currentTime();
if (
(self.playInToOut && self.options.position >= self.options.out)
|| (self.options.playInToOut && self.options.position >= self.out)
) {
2011-08-20 09:48:28 +00:00
if (self.isPlaylist) {
self.$video.playNext();
} else {
togglePaused();
2011-10-03 10:59:09 +00:00
if (self.options.rewind) {
rewind();
} else {
setPosition(self.playInToOut ? self.options.out : self.out/*, 'video'*/);
}
self.playInToOut = false;
2011-10-03 10:59:09 +00:00
//ended();
that.triggerEvent('ended');
2011-08-20 09:48:28 +00:00
}
} else {
setPosition(self.options.position, 'video');
}
that.triggerEvent('playing', {
position: self.options.position
});
}
2011-05-14 19:32:49 +00:00
function playInToOut() {
if (self.options.out > self.options['in']) {
self.playInToOut = true;
setPosition(self.options['in']);
self.options.paused && togglePaused();
2011-05-14 19:32:49 +00:00
}
}
2011-08-20 09:48:28 +00:00
function pointschange() {
var points = self.$video.points();
self['in'] = points[0];
self.out = points[1];
self.options.duration = self.out - self['in'];
setPosition(self['in']);
2011-11-04 15:54:28 +00:00
Ox.Log('Video', 'POINTSCHANGE', self['in'], self.out, self.options.position, self.options.duration)
2011-08-20 09:48:28 +00:00
}
function progress() {
2011-08-19 10:45:36 +00:00
var buffered = self.$video.buffered();
for (var i = 0; i < buffered.length; i++) {
self.buffered[i] = [buffered.start(i), buffered.end(i)];
// fixme: firefox weirdness
if (self.buffered[i][0] > self.buffered[i][1]) {
self.buffered[i][0] = 0;
}
}
2011-05-14 19:32:49 +00:00
self.$progress.attr({
src: getProgressImageURL()
});
}
2011-12-22 12:40:01 +00:00
function renderSettings() {
var $settings = $('<div>')
2011-12-23 08:26:51 +00:00
.addClass('OxControls OxSettings')
2012-05-28 14:06:22 +00:00
.on({
2011-12-22 12:40:01 +00:00
click: function(e) {
var $target = $(e.target), resolution, title, type;
2011-12-22 12:40:01 +00:00
self.$settings.hide();
if (!$target.is('.OxLine') && !$target.is('.OxSpace')) {
title = $(e.target).parent().children()[0].innerHTML;
2013-05-10 10:45:24 +00:00
if (title == Ox._('Download')) {
2011-12-22 12:40:01 +00:00
that.triggerEvent('download');
2013-05-10 10:45:24 +00:00
} else if (title == Ox._('Subtitles')) {
toggleSubtitles();
} else if (isResolution(title)) {
resolution = parseInt(title, 10);
2011-12-22 12:40:01 +00:00
if (resolution != self.options.resolution) {
self.options.resolution = resolution;
setResolution();
}
} else {
type = self.options.timelineTypes[
Ox.indexOf(self.options.timelineTypes, function(type) {
return type.title == title;
})
].id;
if (type != self.options.timelineType) {
self.options.timelineType = type;
2013-02-21 07:41:20 +00:00
setTimelineType();
}
2011-12-22 12:40:01 +00:00
}
self.$settings.children('.OxItem').each(function() {
var children = $(this).children(),
title = children[0].innerHTML,
checked = (
2013-05-10 11:59:39 +00:00
title == Ox._('Subtitles')
2011-12-22 12:40:01 +00:00
&& self.options.enableSubtitles
) || (
isResolution(title)
&& parseInt(title, 10) == self.options.resolution
2013-02-20 20:24:18 +00:00
) || (
self.options.timelineTypes.length
&& title == Ox.getObjectById(
self.options.timelineTypes,
self.options.timelineType
2013-02-20 20:25:24 +00:00
).title
);
2011-12-22 12:40:01 +00:00
$(children[1]).attr({
src: Ox.UI.getImageURL(
'symbol' + (checked ? 'Check' : 'None')
)
});
});
}
}
}),
items = [{
disabled: true,
2013-05-10 10:45:24 +00:00
title: Ox._('Resolution')
}].concat(
2011-12-22 12:40:01 +00:00
self.resolutions.map(function(resolution) {
return {
checked: resolution == self.options.resolution,
title: resolution + 'p'
};
2011-12-22 12:40:01 +00:00
}),
2011-12-22 17:37:31 +00:00
self.options.subtitles.length
2011-12-22 12:40:01 +00:00
? [{}, {
checked: self.options.enableSubtitles,
2013-05-10 10:45:24 +00:00
title: Ox._('Subtitles')
2011-12-22 12:40:01 +00:00
}]
: [],
2013-02-20 20:14:12 +00:00
self.options.timelineTypes.length
? [{}, {
disabled: true,
2013-05-10 10:45:24 +00:00
title: Ox._('Timeline')
}] : [],
2013-02-20 20:14:12 +00:00
self.options.timelineTypes.length
? self.options.timelineTypes.map(function(type) {
return {
checked: type.id == self.options.timelineType,
title: type.title
};
})
: [],
2011-12-22 12:40:01 +00:00
self.options.enableDownload
2013-05-10 10:45:24 +00:00
? [{}, {title: Ox._('Download')}]
2011-12-22 12:40:01 +00:00
: []
),
height = 0;
items.forEach(function(item) {
var $item;
if (item.title) {
$item = $('<div>')
.addClass('OxItem' + (item.disabled ? ' OxDisabled' : ''))
.appendTo($settings);
if (!item.disabled) {
$item.on({
2011-12-22 12:40:01 +00:00
mouseenter: function() {
$(this).addClass('OxSelected');
},
mouseleave: function() {
$(this).removeClass('OxSelected');
}
});
}
2011-12-22 12:40:01 +00:00
$('<div>').html(item.title).appendTo($item);
$('<img>').attr({
src: Ox.UI.getImageURL(
'symbol' + (item.checked ? 'Check' : 'None')
)
}).appendTo($item);
height += 16;
} else {
$('<div>').addClass('OxSpace').appendTo($settings);
$('<div>').addClass('OxLine').appendTo($settings);
$('<div>').addClass('OxSpace').appendTo($settings);
height += 1
}
});
$settings.css({height: height + 'px'});
return $settings;
}
2011-10-03 10:59:09 +00:00
function rewind() {
setTimeout(function() {
2011-10-09 21:13:16 +00:00
setPosition(self.options.playInToOut ? self.options['in'] : 0);
2011-10-03 10:59:09 +00:00
}, 250);
}
function seeked() {
Ox.Log('Video', 'seeked')
2011-05-15 07:26:00 +00:00
clearTimeout(self.seekTimeout);
self.seekTimeout = 0;
Ox.Log('Video', 'hide loading icon')
hideLoadingIcon();
2011-05-15 07:26:00 +00:00
self.$playIcon && self.$playIcon.show();
}
function seeking() {
2011-11-04 15:54:28 +00:00
Ox.Log('Video', 'XX seeking')
if (!self.seekTimeout) {
self.seekTimeout = setTimeout(function() {
self.$playIcon && self.$playIcon.hide();
2011-11-04 15:54:28 +00:00
Ox.Log('Video', 'XX show')
showLoadingIcon();
}, 250);
}
}
function setCensored() {
var censored = getCensored();
if (censored != self.censored) {
self.censored = censored;
censor();
}
}
2011-05-18 07:38:11 +00:00
function setMarkers() {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', 'SET MARKERS', self.options.position, self.options['in'], self.options.out, self.$pointMarker);
self.$posterMarker && Ox.forEach(self.$posterMarker, function(marker) {
2012-05-22 07:11:26 +00:00
isEqual(self.options.position, self.options.posterFrame)
? marker.show() : marker.hide();
});
self.$pointMarker && Ox.forEach(self.$pointMarker, function(markers, point) {
2011-05-18 07:38:11 +00:00
Ox.forEach(markers, function(marker) {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', self.options.position, self.options[point], isEqual(self.options.position, self.options[point]))
// fixme: there's a bug in jquery and/or webkit
// on load, show() doesn't work
2012-05-22 07:11:26 +00:00
isEqual(self.options.position, self.options[point])
? marker.css({display: 'block'}) : marker.hide();
2011-05-18 07:38:11 +00:00
});
});
}
2011-05-18 16:00:29 +00:00
function setPoint() {
that.triggerEvent('setpoint');
}
function setPosition(position, from) {
2011-08-20 09:48:28 +00:00
self.options.position = Ox.limit(position, self['in'], self.out);
/*
// disabled
2011-05-14 19:32:49 +00:00
self.options.position = Math.round(
2011-05-15 08:35:00 +00:00
position * self.options.fps
2011-05-14 19:32:49 +00:00
) / self.options.fps;
*/
self.options.paused && self.options.showMarkers && setMarkers();
2011-10-22 21:03:42 +00:00
self.options.censored.length && setCensored();
2011-12-22 12:40:01 +00:00
self.options.enableSubtitles && self.$subtitle && setSubtitle();
2011-05-14 19:32:49 +00:00
self.$position && self.$position.html(formatPosition());
2011-05-18 16:00:29 +00:00
if (self.options.type == 'play') {
if (self.loadedMetadata && from != 'video') {
2011-08-19 10:45:36 +00:00
self.$video.currentTime(self.options.position);
2011-05-18 16:00:29 +00:00
}
if (self.iconIsVisible) {
self.$playIcon.animate({
opacity: 0
}, 250);
self.iconIsVisible = false;
}
if (self.posterIsVisible) {
self.$poster.animate({
opacity: 0
}, 250);
self.posterIsVisible = false;
}
self.$timeline /*&& from != 'timeline'*/ && self.$timeline.options({
position: self.options.position
});
} else {
//showLoadingIcon();
loadImage();
}
2011-05-14 19:32:49 +00:00
}
function setResolution() {
2011-05-17 16:18:44 +00:00
if (!self.options.paused) {
self.playOnLoad = true;
togglePaused('button');
2011-05-17 16:18:44 +00:00
}
self.loadedMetadata = false;
showLoadingIcon();
2011-08-19 10:45:36 +00:00
self.$video.src(self.options.video[self.options.resolution]);
2011-12-22 07:24:20 +00:00
self.$playButton && self.$playButton.options({disabled: true});
that.triggerEvent('resolution', {
resolution: self.options.resolution
});
}
2011-05-18 16:00:29 +00:00
function setSize($element, css, animate, callback) {
if ($element) {
if (animate) {
$element.animate(css, 250, function() {
callback && callback();
});
} else {
$element.css(css);
callback && callback();
}
}
}
2011-12-23 05:19:02 +00:00
function setSizes(animate, callback) {
2011-05-15 07:26:00 +00:00
self.width = self.options.fullscreen ? window.innerWidth : self.options.width;
self.height = self.options.fullscreen ? window.innerHeight : self.options.height;
self.videoCSS = getVideoCSS();
2011-10-22 21:03:42 +00:00
self.iconSize = Ox.limit(Math.round(self.height / 10), 16, 32);
2011-05-16 18:17:22 +00:00
if (self.$timeline || self.$spaceBottom) {
self.timelineWidth = getTimelineWidth();
2011-05-14 19:32:49 +00:00
if (self.$timeline) {
2011-05-15 07:26:00 +00:00
self.timelineImageWidth = self.timelineWidth - self.barHeight;
2011-05-14 19:32:49 +00:00
}
}
2011-05-18 16:00:29 +00:00
setSize(that, getCSS('player'), animate, callback);
setSize(self.$videoContainer, getCSS('videoContainer'), animate);
setSize(self.$video, self.videoCSS, animate);
setSize(self.$poster, self.videoCSS, animate);
setSize(self.$logo, getCSS('logo'), animate);
setSize(self.$loadingIcon, getCSS('loadingIcon'), animate);
setSize(self.$playIcon, getCSS('playIcon'), animate);
2011-10-22 21:03:42 +00:00
setSize(self.$copyrightIcon, getCSS('copyrightIcon'), animate);
2011-05-18 16:00:29 +00:00
setSize(self.$subtitle, getCSS('subtitle'), animate);
setSize(self.$controlsTop, getCSS('controlsTop'), animate);
setSize(self.$title, getCSS('title'), animate);
setSize(self.$spaceTop, getCSS('spaceTop'), animate);
setSize(self.$controlsBottom, getCSS('controlsBottom'), animate);
setSize(self.$timeline, getCSS('timeline'), animate, function() {
2012-01-02 13:55:15 +00:00
self.$timeline && self.$timeline.options({
2011-05-18 16:00:29 +00:00
width: self.timelineWidth
});
2011-05-18 16:00:29 +00:00
});
setSize(self.$spaceBottom, getCSS('spaceBottom'), animate);
setSize(self.$find, getCSS('find'), animate, function() {
var width = Math.min(128, self.width - 88); // 4 * 16 + 24
2011-05-16 18:05:29 +00:00
self.$findInput.options({
2011-08-19 20:37:58 +00:00
width: width
2011-05-16 18:05:29 +00:00
});
2011-08-19 20:37:58 +00:00
self.$findInput.children('input').css({
2012-05-26 15:48:19 +00:00
width: (width - 12) + 'px'
2011-08-19 20:37:58 +00:00
});
2011-05-18 16:00:29 +00:00
});
setSize(self.$volume, getCSS('volume'), animate, function() {
2011-05-16 18:05:29 +00:00
self.$volumeInput.options({
2011-05-18 16:00:29 +00:00
size: Math.min(128, self.width - 56)
2011-05-16 18:05:29 +00:00
});
2011-05-18 16:00:29 +00:00
});
if (self.$posterMarker) {
self.posterMarkerCSS = getPosterMarkerCSS();
Ox.forEach(self.$posterMarker, function(marker, position) {
2011-05-18 16:00:29 +00:00
setSize(marker, self.posterMarkerCSS[position], animate);
});
}
}
2011-05-12 22:12:41 +00:00
function setSubtitle() {
var subtitle = getSubtitle();
if (subtitle != self.subtitle) {
self.subtitle = subtitle;
2011-05-17 19:30:49 +00:00
setSubtitleText();
2011-05-12 22:12:41 +00:00
}
}
2011-05-17 19:30:49 +00:00
function setSubtitleText() {
self.$subtitle.html(
2011-12-22 12:40:01 +00:00
self.subtitle
? Ox.highlight(self.subtitle, self.options.find, 'OxHighlight', true)
2011-12-22 12:40:01 +00:00
.replace(/\n/g, '<br/>')
: '&nbsp;<br/>&nbsp;'
// FIXME: weird bug, only in fullscreen, only in chrome
2011-05-17 19:30:49 +00:00
);
}
function setTimelineType() {
2013-02-21 07:41:20 +00:00
that.triggerEvent('timeline', {timeline: self.options.timelineType});
}
2011-08-20 09:48:28 +00:00
2011-05-17 10:34:55 +00:00
function setVolume(volume) {
self.options.volume = volume;
if (!!self.options.volume == self.options.muted) {
toggleMuted();
} else {
self.$volumeButton && self.$volumeButton.options({
2011-12-23 05:19:02 +00:00
title: getVolumeImage()
});
self.$volumeValue && self.$volumeValue.html(
self.options.muted ? 0 : Math.round(self.options.volume * 100)
);
}
2011-10-22 21:03:42 +00:00
!self.censored && self.$video.volume(self.options.volume);
2011-08-17 19:34:34 +00:00
that.triggerEvent('volume', {
volume: self.options.volume
});
2011-05-16 18:05:29 +00:00
}
function showControls() {
2011-11-04 15:54:28 +00:00
//Ox.Log('Video', 'showControls');
2011-05-15 16:18:58 +00:00
clearTimeout(self.interfaceTimeout);
if (!self.interfaceIsVisible) {
self.interfaceIsVisible = true;
if (self.$controlsTop) {
self.controlsTopAreVisible = true;
}
if (self.$controlsBottom) {
self.controlsBottomAreVisible = true;
}
self.$controlsTop && self.$controlsTop.animate({
opacity: 1
}, 250);
self.$controlsBottom && self.$controlsBottom.animate({
opacity: 1
}, 250);
2011-12-22 12:40:01 +00:00
['find', 'settings', 'volume'].forEach(function(element) {
var $element = self['$' + element];
$element && $element.is(':visible') && $element.animate({
opacity: 1
}, 250);
});
self.$logo && self.$logo.animate({
top: getCSS('logo').top,
opacity: 0.5
}, 250, function() {
self.options.logoLink && self.$logo
2012-05-28 14:06:22 +00:00
.on({
click: function() {
document.location.href = self.options.logoLink;
}
});
self.options.logoTitle && self.$logo
2012-05-28 14:06:22 +00:00
.on({
mouseenter: function(e) {
self.$logoTooltip.show(e);
},
mouseleave: self.$logoTooltip.hide
});
});
self.$subtitle && self.$subtitle.animate({
2012-05-26 15:48:19 +00:00
bottom: getCSS('subtitle').bottom
}, 250);
2011-05-15 16:18:58 +00:00
}
2011-05-12 10:51:17 +00:00
}
function showLoadingIcon() {
self.$loadingIcon.start().show();
}
function showVolume() {
if (self.$volume) {
!self.interfaceIsVisible && showControls();
self.$volume.is(':hidden') && toggleVolume();
}
}
function sizechange() {
self.videoWidth = self.$video.videoWidth();
self.videoHeight = self.$video.videoHeight();
self.videoCSS = getVideoCSS();
self.$video.css(self.videoCSS);
};
2011-05-17 19:08:25 +00:00
function submitFindInput(value, hasPressedEnter) {
self.options.find = value;
self.results = find(self.options.find);
2011-05-18 16:00:29 +00:00
if (self.$find) {
self.$results.html(self.results.length);
2011-08-20 09:48:28 +00:00
self.$previousResultButton.options({
2011-05-18 16:00:29 +00:00
disabled: self.results.length <= 1
});
2011-08-20 09:48:28 +00:00
self.$nextResultButton.options({
2011-05-18 16:00:29 +00:00
disabled: self.results.length <= 1
});
self.$clearButton.options({
disabled: !self.options.find
});
}
2011-05-17 19:30:49 +00:00
self.subtitle && setSubtitleText();
self.$timeline && self.$timeline.options({
2011-05-17 18:04:26 +00:00
find: self.options.find,
results: self.results
});
if (hasPressedEnter) {
if (self.results.length) {
goToNextResult(1);
that.gainFocus();
} else {
self.$findInput.focusInput(true);
}
}
that.triggerEvent('find', {find: self.options.find});
}
function submitPositionInput() {
self.$positionInput.hide();
self.$position.html('').show();
2011-12-31 12:57:02 +00:00
setPosition(Ox.parseDuration(self.$positionInput.value()));
if (self.playOnSubmit) {
togglePaused();
2011-08-19 10:45:36 +00:00
self.$video.play();
self.playOnSubmit = false;
}
2011-05-15 16:18:58 +00:00
if (self.focus == 'mouseenter' && !self.mouseHasLeft) {
that.gainFocus();
}
self.mouseHasLeft && hideControls();
that.triggerEvent('position', {
position: self.options.position
});
}
2011-05-16 18:05:29 +00:00
function toggleFind() {
2011-05-17 07:43:20 +00:00
var show = self.$find.is(':hidden');
!show && self.$findInput.blurInput();
2011-05-16 18:05:29 +00:00
self.$find.toggle();
2011-05-17 07:43:20 +00:00
show && self.$findInput.focusInput(false);
2011-05-16 18:05:29 +00:00
}
function toggleFullscreen(from) {
var parentOffset, playOnFullscreen;
2011-05-15 07:26:00 +00:00
self.options.fullscreen = !self.options.fullscreen;
if (!self.options.paused) {
2011-05-15 16:18:58 +00:00
// video won't keep playing accross detach/append
2011-08-19 10:45:36 +00:00
self.$video.pause();
playOnFullscreen = true;
2011-05-15 07:26:00 +00:00
}
if (self.options.fullscreen) {
self.$parent = that.parent();
2011-05-15 07:52:37 +00:00
parentOffset = self.$parent.offset();
self.absoluteOffset = that.offset();
self.relativeOffset = {
left: self.absoluteOffset.left - parentOffset.left,
top: self.absoluteOffset.top - parentOffset.top
};
2011-05-15 07:26:00 +00:00
that.detach()
2011-11-02 20:58:44 +00:00
.addClass('OxFullscreen')
2011-05-15 07:26:00 +00:00
.css({
2011-05-15 07:52:37 +00:00
left: self.absoluteOffset.left + 'px',
top: self.absoluteOffset.top + 'px',
2011-05-15 07:26:00 +00:00
zIndex: 1000
})
.appendTo(Ox.UI.$body);
2011-12-23 05:19:02 +00:00
setSizes(true, function() {
2011-08-19 10:45:36 +00:00
playOnFullscreen && self.$video.play();
enterFullscreen();
2011-05-15 07:26:00 +00:00
});
} else {
2011-12-23 07:15:40 +00:00
// exitFullscreen flag makes the animation end on absolute position
2011-05-15 07:52:37 +00:00
self.exitFullscreen = true;
2012-05-28 14:06:22 +00:00
that.off('mousemove');
2011-05-16 18:05:29 +00:00
that.find('.OxControls')
2011-05-15 16:18:58 +00:00
.trigger('mouseleave')
2012-05-28 14:06:22 +00:00
.off('mouseenter mouseleave');
clearTimeout(self.interfaceTimeout);
2011-12-23 05:19:02 +00:00
setSizes(true, function() {
2011-05-15 16:18:58 +00:00
self.exitFullscreen = false;
2011-05-15 07:26:00 +00:00
that.detach()
2011-11-02 20:58:44 +00:00
.removeClass('OxFullscreen')
2011-05-15 07:26:00 +00:00
.css({
2011-05-15 07:52:37 +00:00
left: self.relativeOffset.left + 'px',
2011-05-16 18:05:29 +00:00
top: self.relativeOffset.top + 'px',
zIndex: 1
2011-05-15 07:26:00 +00:00
})
.appendTo(self.$parent);
2011-08-19 10:45:36 +00:00
playOnFullscreen && self.$video.play();
2011-05-15 16:18:58 +00:00
self.options.enableKeyboard && that.gainFocus();
//showControls();
2011-05-15 07:26:00 +00:00
});
}
if (self.$fullscreenButton && from != 'button') {
2011-12-22 07:24:20 +00:00
self.$fullscreenButton.toggle();
2011-05-15 16:18:58 +00:00
}
that.triggerEvent('fullscreen', {
fullscreen: self.options.fullscreen
});
2011-05-15 07:26:00 +00:00
}
function toggleMuted(from) {
self.hasVolumeControl && showVolume();
self.options.muted = !self.options.muted;
2011-08-19 10:45:36 +00:00
self.$video.muted(self.options.muted);
if (!self.options.muted && !self.options.volume) {
self.options.volume = 1;
2011-08-19 10:45:36 +00:00
self.$video.volume(1);
}
if (self.$muteButton && from != 'button') {
2011-12-22 07:24:20 +00:00
self.$muteButton.toggle();
2011-05-15 16:18:58 +00:00
}
2011-12-23 05:19:02 +00:00
self.$volumeButton && self.$volumeButton.options({
title: getVolumeImage()
2011-05-16 18:05:29 +00:00
});
2011-12-21 15:33:52 +00:00
self.$volumeInput && self.$volumeInput.value(
self.options.muted ? 0 : self.options.volume
);
self.$volumeValue && self.$volumeValue.html(
self.options.muted ? 0 : Math.round(self.options.volume * 100)
);
2011-08-17 19:34:34 +00:00
that.triggerEvent('muted', {
muted: self.options.muted
});
}
function togglePaused(from) {
self.options.paused = !self.options.paused;
self.$timeline && self.$timeline.options({
paused: self.options.paused
});
if (!self.loadedMetadata) {
return;
}
if (self.options.paused) {
2011-08-19 10:45:36 +00:00
self.$video.pause();
clearInterval(self.playInterval);
2011-05-14 19:32:49 +00:00
if (self.options.showIcon) {
togglePlayIcon();
self.options.showIcon && self.$playIcon.animate({
opacity: 1
}, 250);
}
} else {
2011-05-14 19:32:49 +00:00
if (self.options.playInToOut && self.options.position > self.options.out - self.secondsPerFrame) {
setPosition(self.options['in']);
2011-05-14 19:32:49 +00:00
}
2011-08-19 10:45:36 +00:00
self.$video.play();
self.playInterval = setInterval(playing, self.millisecondsPerFrame);
2011-05-14 19:32:49 +00:00
if (self.options.showIcon) {
self.options.showIcon && self.$playIcon.animate({
opacity: 0
2011-05-15 07:26:00 +00:00
}, 250, togglePlayIcon);
2011-05-14 19:32:49 +00:00
}
self.options.showMarkers && hideMarkers();
}
if (self.$playButton && from != 'button') {
2011-12-22 07:24:20 +00:00
self.$playButton.toggle();
2011-05-15 08:35:00 +00:00
}
that.triggerEvent('paused', {
paused: self.options.paused
});
self.options.paused && that.triggerEvent('position', {
position: self.options.position
});
}
function togglePlayIcon() {
2011-05-14 19:32:49 +00:00
self.$playIcon.attr({
2011-08-09 17:00:39 +00:00
src: Ox.UI.getImageURL(
2011-05-14 19:32:49 +00:00
'symbol' + (self.options.paused ? 'Play' : 'Pause'
2012-12-28 16:58:01 +00:00
), 'video')
2011-05-14 19:32:49 +00:00
});
}
function toggleScale(from) {
self.options.scaleToFill = !self.options.scaleToFill;
self.videoCSS = getVideoCSS();
self.$video.animate(self.videoCSS, 250);
self.$poster && self.$poster.animate(self.videoCSS, 250);
if (self.$scaleButton && from != 'button') {
2011-12-22 07:24:20 +00:00
self.$scaleButton.toggle();
2011-05-15 16:18:58 +00:00
}
if (self.$posterMarker) {
self.posterMarkerCSS = getPosterMarkerCSS();
Ox.forEach(self.$posterMarker, function(marker, position) {
marker.animate(self.posterMarkerCSS[position], 250);
});
}
2011-08-17 19:34:34 +00:00
that.triggerEvent('scale', {
scale: self.options.scaleToFill ? 'fill' : 'fit'
});
}
function toggleSize() {
self.options.sizeIsLarge = !self.options.sizeIsLarge;
that.triggerEvent('size', {
size: self.options.sizeIsLarge ? 'large' : 'small'
});
}
function toggleSubtitles() {
self.options.enableSubtitles = !self.options.enableSubtitles;
setSubtitle();
self.$timeline && self.$timeline.options({
subtitles: self.options.enableSubtitles ? self.options.subtitles : []
});
that.triggerEvent('subtitles', {
subtitles: self.options.enableSubtitles
});
}
2011-05-17 07:43:20 +00:00
function toggleVolume() {
self.$volume.toggle();
}
2012-05-21 10:38:18 +00:00
/*@
changeVolume <f> change volume
(num) -> <o> change volume
@*/
that.changeVolume = function(num) {
changeVolume(num);
return that;
};
2011-09-14 14:34:33 +00:00
/*@
playInToOut <f> play in to out
() -> <o> play in to out
@*/
that.playInToOut = function() {
2011-05-14 19:32:49 +00:00
playInToOut();
return that;
};
2011-09-14 14:34:33 +00:00
/*@
togglePaused <f> toggle paused state
() -> <o> toggle paused state
@*/
2011-05-18 16:00:29 +00:00
that.togglePaused = function() {
togglePaused();
return that;
}
2011-09-14 14:34:33 +00:00
/*@
toggleMuted <f> toggle muted state
() -> <o> toggle muted state
@*/
2011-05-18 16:00:29 +00:00
that.toggleMuted = function() {
toggleMuted();
return that;
}
return that;
2011-05-16 10:49:48 +00:00
};