new timeline implementation

This commit is contained in:
rolux 2011-05-15 18:18:58 +02:00
parent 0642c10951
commit fd1fc212f2
8 changed files with 690 additions and 54 deletions

View file

@ -2,8 +2,31 @@ Ox.load('UI', {
debug: true,
theme: 'modern'
}, function() {
var $foo, $bar;
var id = '0393109',
poster = 'png/poster.png',
results = [
{'in': 190.335, out: 192.353},
{'in': 1185.215, out: 1188.115},
{'in': 1784.525, out: 1785.915},
{'in': 1786.015, out: 1787.835},
{'in': 3087.365, out: 3090.275},
{'in': 3704.915, out: 3706.795},
{'in': 3706.895, out: 3709.615},
{'in': 4061.655, out: 4063.95},
{'in': 4531.775, out: 4533.415},
{'in': 4946.095, out: 4948.875},
{'in': 5292.885, out: 5294.665},
{'in': 5381.965, out: 5383.338},
{'in': 5385.415, out: 5389.58},
{'in': 5434.93, out: 5436.93},
{'in': 5437.405, out: 5439.405},
{'in': 5749.535, out: 5751.915},
{'in': 5780.235, out: 5782.435},
{'in': 5881.365, out: 5886.635}
],
timeline = 'http://next.0xdb.org/' + id + '/timeline.16.png',
url = 'http://next.0xdb.org/' + id + '/96p.webm',
videoSize = getVideoSize(),
@ -13,9 +36,11 @@ Ox.load('UI', {
enableKeyboard: true,
focus: 'mouseenter',
height: 192,
'in': 3128.725,
logoLink: 'http://next.0xdb.org/' + id,
logoTitle: 'Watch on 0xdb',
logo: 'png/logo.png',
out: 3130.725,
paused: true,
poster: poster,
showIconOnLoad: true,
@ -51,6 +76,7 @@ Ox.load('UI', {
Ox.VideoPlayer({
controls: ['play', 'playInToOut', 'mute', 'size', 'space', 'position'],
externalControls: true,
find: 'brick',
height: 192,
'in': 3128.725,
out: 3130.725,
@ -66,8 +92,10 @@ Ox.load('UI', {
top: '16px'
})
.bindEvent({
size: function() {
position: function(data) {
$blockTimeline.options({
position: data.position
});
}
})
];
@ -90,7 +118,7 @@ Ox.load('UI', {
resize: [100, 400]
},
{
element: Ox.Element()
element: $foo = Ox.Element()
}
],
orientation: 'vertical'
@ -127,7 +155,7 @@ Ox.load('UI', {
resize: [100, 400]
},
{
element: Ox.Element()
element: $bar = Ox.Element()
}
],
orientation: 'vertical'
@ -135,6 +163,7 @@ Ox.load('UI', {
.bindEvent({
resize: function(foo, size) {
$videos[2].options({width: size - 32});
$blockTimeline.options({width: size - 40});
}
}),
size: 392,
@ -160,4 +189,49 @@ Ox.load('UI', {
});
}
Ox.get('srt/0393109.srt', function(srt) {
var subtitles = Ox.parseSRT(srt);
$foo.append(
Ox.SmallVideoTimelineImages({
duration: 6336.08,
getTimelineURL: function(i) {
return 'png/timeline.16.' + i + '.png';
},
'in': 1800,
out: 1900,
results: [
{'in': 3600, out: 3700}
],
subtitles: subtitles,
type: 'editor',
width: 392
})
);
$bar.append(
$blockTimeline = Ox.BlockVideoTimeline({
duration: 6336.08,
find: 'brick',
getTimelineURL: function(i) {
return 'png/timeline.16.' + i + '.png';
},
'in': 3128.725,
out: 3130.725,
results: results,
subtitles: subtitles,
width: 353
})
.css({
position: 'absolute',
left: '16px',
top: '16px'
})
.bindEvent('position', function(data) {
$videos[2].options({
position: data.position
});
})
);
})
});

View file

@ -331,7 +331,7 @@ Ox.Element = function() {
Ox.forEach(Ox.makeObject(arguments), function(data, event) {
if ([
'mousedown', 'mouserepeat', 'anyclick', 'singleclick', 'doubleclick',
'dragstart', 'drag', 'dragpause', 'dragend', 'playing', 'progress'
'dragstart', 'drag', 'dragpause', 'dragend', 'playing', 'position', 'progress'
].indexOf(event) == -1) {
Ox.print(that.id, self.options.id, 'trigger', event, data);
}

View file

@ -516,7 +516,7 @@ Ox.Input = function(options, self) {
Ox.UI.$document.unbind('keydown', keypress);
Ox.UI.$document.unbind('keypress', keypress);
}
that.triggerEvent('blur', {});
that.triggerEvent('blur');
}
function cancel() {
@ -602,6 +602,7 @@ Ox.Input = function(options, self) {
Ox.UI.$document.keypress(keypress);
self.options.autocompleteSelect && setTimeout(autocomplete, 0); // fixme: why is the timeout needed?
}
that.triggerEvent('focus');
}
function getInputWidth() {

View file

@ -4,7 +4,6 @@ Ox.BlockTimeline = function(options, self) {
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
cuts: [],
duration: 0,
find: '',
matches: [],
@ -113,7 +112,7 @@ Ox.BlockTimeline = function(options, self) {
.appendTo(self.$lines[i].$element);
}
if (self.options.points[0] != self.options.points[1]) {
addSelection[i];
addSelection(i);
}
}

View file

@ -0,0 +1,246 @@
Ox.BlockVideoTimeline = function(options, self) {
self = self || {};
var that = new Ox.Element({}, self)
.defaults({
duration: 0,
find: '',
getTimelineURL: null,
'in': 0,
out: 0,
position: 0,
results: [],
subtitles: [],
width: 0
})
.options(options || {})
.css({
position: 'absolute',
})
.bind({
mousedown: mousedown,
mouseleave: mouseleave,
mousemove: mousemove
})
.bindEvent({
drag: function(event, e) {
mousedown(e);
}
});
self.$images = [];
self.$interfaces = [];
self.$lines = [];
self.$tooltip = new Ox.Tooltip({
animate: false
}).css({
textAlign: 'center'
});
self.height = 16;
self.lines = getLines();
self.margin = 8;
setCSS();
Ox.loop(self.lines, function(i) {
addLine(i);
});
self.$positionMarker = $('<img>')
.attr({
src: Ox.UI.PATH + 'png/videoMarkerPlay.png'
})
.css({
position: 'absolute',
width: '9px',
height: '5px',
zIndex: 10
})
.appendTo(that.$element);
setPositionMarker();
self.$pointMarker = {};
['in', 'out'].forEach(function(point) {
var titleCase = Ox.toTitleCase(point);
self.$pointMarker[point] = $('<img>')
.addClass('OxPointMarker' + titleCase)
.attr({
src: Ox.UI.PATH + 'png/videoMarker' + titleCase + '.png'
})
.css({
position: 'absolute',
width: '6px',
height: '6px',
marginLeft: (point == 'in' ? -1 : 4) + 'px',
zIndex: 10
})
.appendTo(that.$element);
setPointMarker(point);
});
function addLine(i) {
self.$lines[i] = $('<div>')
.css({
position: 'absolute',
left: (self.margin / 2) + 'px',
top: i * (self.height + self.margin) + 'px',
width: self.options.width + 'px',
height: '24px',
overflow: 'hidden'
})
.appendTo(that.$element);
self.$images[i] = Ox.SmallVideoTimelineImages({
duration: self.options.duration,
editing: self.options.editing,
getTimelineURL: self.options.getTimelineURL,
'in': self.options['in'],
out: self.options.out,
results: self.options.results,
subtitles: self.options.subtitles,
width: Math.ceil(self.options.duration),
type: self.options.type
})
.css({
position: 'absolute',
marginLeft: (-i * self.options.width) + 'px'
})
.appendTo(self.$lines[i]);
self.$interfaces[i] = $('<div>').addClass('OxInterface')
.css({
position: 'absolute',
top: '2px',
width: Math.ceil(self.options.duration) + 'px',
height: '20px',
marginLeft: (-i * self.options.width) + 'px',
zIndex: 11
})
.appendTo(self.$lines[i]);
}
function getLines() {
return Math.ceil(self.options.duration / self.options.width);
}
function getPosition(e) {
//FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
return (e.offsetX ? e.offsetX : e.clientX - $(e.target).offset().left);
}
function getSubtitle(position) {
var subtitle = '';
Ox.forEach(self.options.subtitles, function(v) {
if (v['in'] <= position && v.out > position) {
subtitle = v;
return false;
}
});
return subtitle;
}
function mousedown(e) {
if ($(e.target).is('.OxInterface')) {
self.options.position = getPosition(e);
setPositionMarker();
// fixme: check if this pattern is better
// than the one used for list selection
if (!self.triggered) {
Ox.print('$$$$$$$$$$$$$$$')
that.triggerEvent('position', {
position: self.options.position
});
self.triggered = true;
setTimeout(function() {
self.triggered = false;
}, 250);
}
}
}
function mouseleave() {
self.$tooltip.hide();
}
function mousemove(e) {
var position, subtitle;
if ($(e.target).is('.OxInterface')) {
position = getPosition(e);
subtitle = getSubtitle(position);
self.$tooltip.options({
title: subtitle ?
'<span class=\'OxBright\'>' +
Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '<br/>') +
'</span><br/>' +
Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
Ox.formatDuration(position, 3)
})
.show(e.clientX, e.clientY);
} else {
self.$tooltip.hide();
}
}
function setCSS() {
that.css({
width: (self.options.width + self.margin) + 'px',
height: ((self.height + self.margin) * self.lines) + 'px'
});
}
function setPointMarker(point) {
var position = Math.round(self.options[point]);
Ox.print('$$ position', position)
self.$pointMarker[point].css({
left: (position % self.options.width) + 'px',
top: (parseInt(position / self.options.width) *
(self.height + self.margin) + 16) + 'px'
});
}
function setPositionMarker() {
self.$positionMarker.css({
left: (self.options.position % self.options.width) + 'px',
top: (parseInt(self.options.position / self.options.width) *
(self.height + self.margin) + 2) + 'px'
});
}
function setWidth() {
self.lines = getLines();
setCSS();
Ox.loop(self.lines, function(i) {
if (self.$lines[i]) {
self.$lines[i].css({
width: self.options.width + 'px'
});
self.$images[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
self.$interfaces[i].css({
marginLeft: (-i * self.options.width) + 'px'
});
} else {
addLine(i);
}
});
while (self.$lines.length > self.lines) {
self.$lines[self.$lines.length - 1].remove();
self.$lines.pop();
self.$images.pop();
}
setPositionMarker();
setPointMarker('in');
setPointMarker('out');
}
self.setOption = function(key, value) {
if (key == 'position') {
setPositionMarker();
} else if (key == 'width') {
setWidth();
}
}
return that;
};

View file

@ -0,0 +1,54 @@
Ox.SmallVideoTimeline = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
duration: 0,
editing: false,
getTimelineURL: null,
'in': 0,
out: 0,
width: 256,
type: 'player'
})
.options(options || {})
.addClass('OxSmallVideoTimeline')
.css({
width: self.options.width + 'px'
});
self.height = self.options.type == 'player' ? 16 : 24;
self.imageHeight = self.options.type == 'player' ? 16 : 18;
self.imageTop = self.options.type == 'player' ? 0 : 3;
that.css({
height: self.height + 'px'
});
self.tooltip = Ox.Tooltip({
animate: false
}).css({
textAlign: 'center'
});
getImageURL('timeline', function(timelineURL) {
$('<img>')
.attr({
src: timelineURL
})
.css({
width: self.options.width + 'px',
height: self.imageHeight + 'px',
top: self.imageTop + 'px'
})
.appendTo(that.$element);
});
return that;
};

View file

@ -0,0 +1,187 @@
Ox.SmallVideoTimelineImages = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
duration: 0,
editing: false,
getTimelineURL: null,
'in': 0,
out: 0,
results: [],
subtitles: [],
width: 256,
type: 'player'
})
.options(options || {})
.addClass('OxSmallVideoTimeline')
.css({
position: 'absolute',
width: self.options.width + 'px'
});
self.height = self.options.type == 'player' ? 16 : 24;
self.imageHeight = self.options.type == 'player' ? 16 : 18;
self.imageTop = self.options.type == 'player' ? 0 : 3;
that.css({
height: self.height + 'px'
});
self.$timeline = $('<img>')
.attr({
src: Ox.UI.PATH + 'png/transparent.png'
})
.css({
position: 'absolute',
width: self.options.width + 'px',
height: self.imageHeight + 'px',
top: self.imageTop + 'px'
})
.appendTo(that.$element);
getImageURL('timeline', function(imageURL) {
self.$timeline.attr({
src: imageURL
});
});
self.$subtitles = $('<img>')
.attr({
src: getImageURL('subtitles')
})
.css({
position: 'absolute',
width: self.options.width + 'px',
height: self.imageHeight + 'px',
top: self.imageTop + 'px'
})
.appendTo(that.$element);
self.$results = $('<img>')
.attr({
src: getImageURL('results')
})
.css({
position: 'absolute',
width: self.options.width + 'px',
height: self.imageHeight + 'px',
top: self.imageTop + 'px'
})
.appendTo(that.$element);
self.$selection = $('<img>')
.attr({
src: getImageURL('selection')
})
.css({
position: 'absolute',
width: self.options.width + 'px',
height: self.imageHeight + 'px',
top: self.imageTop + 'px'
})
.appendTo(that.$element);
function getImageURL(image, callback) {
var width = Math.ceil(self.options.duration),
height = self.imageHeight,
canvas = $('<canvas>')
.attr({
width: width,
height: height
})[0],
context = canvas.getContext('2d'),
imageData = context.createImageData(width, height),
data = imageData.data;
if (image == 'results') {
var top = 0,
bottom = height;
self.options.results.forEach(function(result) {
var left = Math.round(result['in']),
right = Math.round(result.out) + 1;
Ox.loop(left, right, function(x) {
Ox.loop(top, bottom, function(y) {
var color = (y == top || y == bottom - 1) ? [255, 255, 0, 255] : [255, 255, 0, 64],
index = x * 4 + y * 4 * width;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = color[3];
});
});
});
} else if (image == 'selection') {
var left = Math.round(self.options['in']),
right = Math.round(self.options.out) + 1,
top = 0,
bottom = height,
rgb = self.options.editing ? [128, 255, 255] : [255, 255, 255];
Ox.loop(left, right, function(x) {
Ox.loop(top, bottom, function(y) {
var color = [rgb[0], rgb[1], rgb[2], (y == top || y == bottom - 1) ? 255 : 64],
index = x * 4 + y * 4 * width;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = color[3];
});
});
} else if (image == 'subtitles') {
var bottom = self.options.type == 'player' ? 14 : 15;
self.options.subtitles.forEach(function(subtitle) {
var left = Math.round(subtitle['in']),
right = Math.round(subtitle.out) + 1,
top = bottom - subtitle.text.split('\n').length - 2;
Ox.loop(left, right, function(x) {
Ox.loop(top, bottom, function(y) {
var color = (y == top || y == bottom - 1) ? [0, 0, 0] : [255, 255, 255],
index = x * 4 + y * 4 * width;
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = 128;
});
});
});
} else if (image == 'timeline') {
var counter = 0,
images = Math.ceil(self.options.duration / 3600),
top = self.options.type == 'player' ? 0 : 1;
Ox.loop(images, function(i) {
var $image = $('<img>')
.attr({
src: self.options.getTimelineURL(i)
})
.load(function() {
context.drawImage($image[0], i * 3600, top);
if (++counter == images) {
callback(canvas.toDataURL());
}
});
})
}
if (image != 'timeline') {
context.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
}
self.setOption = function(key, value) {
if (key == 'in' || key == 'out') {
self.$selection.attr({
src: getImageURL('selection')
});
} else if (key == 'results') {
self.$results.attr({
src: getImageURL('results')
});
} else if (key == 'subtitles') {
self.$subtitles.attr({
src: getImageURL('subtitles')
});
}
}
return that;
}

View file

@ -16,6 +16,7 @@ Ox.VideoPlayer <f> Generic Video Player
duration <n|-1> Duration (sec)
enableKeyboard <b|false> If true, enable keyboard controls
externalControls <b|false> If true, controls are outside the video
find <s|''> Query string
focus <s|'click'> focus on 'click', 'load' or 'mouseover'
fps <n|25> Frames per second
fullscreen <b|false> If true, video is in fullscreen
@ -68,6 +69,7 @@ Ox.VideoPlayer = function(options, self) {
duration: 86399,
enableKeyboard: false,
externalControls: false,
find: '',
focus: 'click',
fps: 25,
fullscreen: false,
@ -143,7 +145,7 @@ Ox.VideoPlayer = function(options, self) {
setPosition(self.options.position + self.secondsPerFrame, true);
},
key_shift_f: function() {
toggleFullscreen();
toggleFullscreen(true);
},
key_space: function() {
togglePaused(true);
@ -154,8 +156,14 @@ Ox.VideoPlayer = function(options, self) {
if (self.options.enableKeyboard) {
if (self.options.focus == 'mouseenter') {
that.bind({
mouseenter: that.gainFocus,
mouseleave: that.loseFocus
mouseenter: function() {
if (!self.inputHasFocus) {
that.gainFocus();
}
},
mouseleave: function() {
that.loseFocus();
}
});
} else {
that.bind({
@ -164,10 +172,21 @@ Ox.VideoPlayer = function(options, self) {
}
}
if ((!self.options.externalControls && self.options.controls.length) || self.options.showIcon || self.options.title) {
if (
(!self.options.externalControls && self.options.controls.length) ||
self.options.showIcon || self.options.title
) {
that.bind({
mouseenter: showInterface,
mouseleave: hideInterface
mouseenter: function() {
showInterface();
self.mouseHasLeft = false;
Ox.print('MOUSE HAS ENTERED')
},
mouseleave: function() {
hideInterface();
self.mouseHasLeft = true;
Ox.print('MOUSE HAS LEFT')
}
});
}
@ -300,7 +319,7 @@ Ox.VideoPlayer = function(options, self) {
}
if (self.options.title) {
self.$titlebar = $('<div>')
self.$title = $('<div>')
.addClass('OxInterface')
.css({
position: 'absolute',
@ -388,7 +407,9 @@ Ox.VideoPlayer = function(options, self) {
type: 'image'
})
.css({float: 'left'})
.bindEvent('click', toggleMuted)
.bindEvent('click', function() {
toggleMuted();
})
.appendTo(self.$controls);
} else if (control == 'volume') {
@ -420,7 +441,9 @@ Ox.VideoPlayer = function(options, self) {
type: 'image'
})
.css({float: 'left'})
.bindEvent('click', toggleFullscreen)
.bindEvent('click', function() {
toggleFullscreen();
})
.appendTo(self.$controls);
} else if (control == 'size') {
@ -576,12 +599,6 @@ Ox.VideoPlayer = function(options, self) {
MozBoxShadow: '0 0 0',
WebkitBoxShadow: '0 0 0'
})
.bind({
blur: function() {
},
focus: function() {
}
})
.bindEvent({
focus: function() {
self.inputHasFocus = true;
@ -618,6 +635,11 @@ Ox.VideoPlayer = function(options, self) {
setSizes();
function clearInterfaceTimeout() {
clearTimeout(self.interfaceTimeout);
self.interfaceTimeout = 0;
}
function ended() {
if (!self.options.paused) {
togglePaused(true);
@ -643,7 +665,7 @@ Ox.VideoPlayer = function(options, self) {
function getCSS(element) {
var css;
if (element == 'controls' || element == 'titlebar') {
if (element == 'controls' || element == 'title') {
css = {
width: self.width + 'px'
};
@ -655,11 +677,11 @@ Ox.VideoPlayer = function(options, self) {
height: self.iconSize + 'px'
};
} else if (element == 'logo') {
var logoHeight = Math.round(self.height / 10);
self.logoMargin = Math.round(self.height / 20);
var logoHeight = Math.round(self.height / 10),
logoMargin = Math.round(self.height / 20);
css = {
left: self.logoMargin + 'px',
top: self.logoMargin + 'px',
left: logoMargin + 'px',
top: (logoMargin + !!self.titleIsVisible * 16) + 'px',
height: logoHeight + 'px',
};
} else if (element == 'player') {
@ -727,7 +749,7 @@ Ox.VideoPlayer = function(options, self) {
};
} else if (element == 'subtitle') {
css = {
bottom: parseInt(self.height / 16) + 'px',
bottom: (parseInt(self.height / 16) + !!self.controlsAreVisible * 16) + 'px',
width: self.width + 'px',
fontSize: parseInt(self.height / 20) + 'px',
WebkitTextStroke: (self.height / 1000) + 'px rgb(0, 0, 0)'
@ -811,7 +833,7 @@ Ox.VideoPlayer = function(options, self) {
v['in'] <= self.options.position &&
v.out > self.options.position
) {
subtitle = v.text;
subtitle = Ox.highlight(v.text, self.options.find, 'OxHighlight');
return false;
}
});
@ -819,13 +841,16 @@ Ox.VideoPlayer = function(options, self) {
}
function hideInterface() {
if (!self.inputHasFocus) {
self.controlsTimeout = setTimeout(function() {
Ox.print('hideInterface');
self.interfaceTimeout = setTimeout(function() {
if (!self.exitFullscreen && !self.inputHasFocus && !self.mouseIsInControls) {
self.titleIsVisible = false;
self.controlsAreVisible = false;
that.find('.OxInterface').animate({
opacity: 0
}, 250);
self.$logo && self.$logo.animate({
top: self.logoMargin + 'px',
top: getCSS('logo').top,
opacity: 0.25
}, 250, function() {
self.options.logoLink && self.$logo.unbind('click');
@ -833,10 +858,10 @@ Ox.VideoPlayer = function(options, self) {
self.$logo.unbind('mouseenter').unbind('mouseleave');
});
self.$subtitle && self.$subtitle.animate({
bottom: parseInt(self.options.height / 16) + 'px',
});
}, 1000);
}
bottom: getCSS('subtitle').bottom,
}, 250);
}
}, self.options.fullscreen ? 2500 : 1000);
}
function hideLoadingIcon() {
@ -932,6 +957,9 @@ Ox.VideoPlayer = function(options, self) {
} else {
setPosition(self.options.position);
}
that.triggerEvent('position', {
position: self.options.position
});
}
function playInToOut() {
@ -1020,7 +1048,7 @@ Ox.VideoPlayer = function(options, self) {
self.$loadingIcon.animate(getCSS('loadingIcon'), ms);
self.$playIcon && self.$playIcon.animate(getCSS('playIcon'), ms);
self.$subtitle && self.$subtitle.animate(getCSS('subtitle'), ms);
self.$titlebar && self.$titlebar.animate(getCSS('titlebar'), ms);
self.$title && self.$title.animate(getCSS('title'), ms);
self.$controls && self.$controls.animate(getCSS('controls'), ms);
if (self.$timeline) {
self.$timeline.animate(getCSS('timeline'), ms);
@ -1045,12 +1073,19 @@ Ox.VideoPlayer = function(options, self) {
}
function showInterface() {
clearTimeout(self.controlsTimeout);
Ox.print('showInterface');
clearTimeout(self.interfaceTimeout);
if (self.$title) {
self.titleIsVisible = true;
}
if (self.$controls) {
self.controlsAreVisible = true;
}
that.find('.OxInterface').animate({
opacity: 1
}, 250);
self.$logo && self.$logo.animate({
top: self.logoMargin + 16 + 'px',
top: getCSS('logo').top,
opacity: 0.5
}, 250, function() {
self.options.logoLink && self.$logo
@ -1067,9 +1102,9 @@ Ox.VideoPlayer = function(options, self) {
mouseleave: self.$logoTooltip.hide
});
});
self.$subtitle.animate({
bottom: self.barHeight + parseInt(self.options.height / 16) + 'px',
});
self.$subtitle && self.$subtitle.animate({
bottom: getCSS('subtitle').bottom,
}, 250);
}
function showLoadingIcon() {
@ -1088,12 +1123,17 @@ Ox.VideoPlayer = function(options, self) {
self.video.play();
self.wasPlaying = false;
}
if (self.focus == 'mouseenter' && !self.mouseHasLeft) {
that.gainFocus();
}
self.mouseHasLeft && hideInterface();
}
function toggleFullscreen() {
function toggleFullscreen(toggleButton) {
var parentOffset, wasPlaying;
self.options.fullscreen = !self.options.fullscreen;
if (!self.options.paused) {
// video won't keep playing accross detach/append
self.video.pause();
wasPlaying = true;
}
@ -1114,10 +1154,36 @@ Ox.VideoPlayer = function(options, self) {
.appendTo(Ox.UI.$body);
setSizes(function() {
wasPlaying && self.video.play();
that.bind({
mousemove: function() {
if (!self.mouseIsInControls) {
showInterface();
hideInterface();
}
}
});
self.$controls && self.$controls.bind({
mouseenter: function() {
self.mouseIsInControls = true;
},
mouseleave: function() {
self.mouseIsInControls = false;
}
});
showInterface();
hideInterface();
});
} else {
// flag makes the animation end on absolute position
self.exitFullscreen = true;
that.unbind('mousemove');
self.$controls && self.$controls
.trigger('mouseleave')
.unbind('mouseenter')
.unbind('mouseleave');
Ox.print('???', self.mouseIsInControls);
setSizes(function() {
self.exitFullscreen = false;
that.detach()
.css({
left: self.relativeOffset.left + 'px',
@ -1125,17 +1191,24 @@ Ox.VideoPlayer = function(options, self) {
})
.appendTo(self.$parent);
wasPlaying && self.video.play();
self.exitFullscreen = false;
self.options.enableKeyboard && that.gainFocus();
//showInterface();
});
}
if (toggleButton && self.$fullscreenButton) {
self.$fullscreenButton.toggleTitle();
}
}
function toggleMuted() {
function toggleMuted(toggleButton) {
self.options.muted = !self.options.muted;
self.video.muted = self.options.muted;
if (toggleButton && self.$muteButton) {
self.$muteButton.toggleTitle();
}
}
function togglePaused(togglePlayButton) {
function togglePaused(toggleButton) {
self.options.paused = !self.options.paused;
self.$timeline && self.$positionMarkerRing.css({
borderColor: 'rgba(255, 255, 255, ' + (self.options.paused ? 0.5 : 1) + ')'
@ -1161,7 +1234,7 @@ Ox.VideoPlayer = function(options, self) {
}, 250, togglePlayIcon);
}
}
if (togglePlayButton && self.$playButton) {
if (toggleButton && self.$playButton) {
self.$playButton.toggleTitle();
}
}
@ -1174,10 +1247,13 @@ Ox.VideoPlayer = function(options, self) {
});
}
function toggleScale() {
function toggleScale(toggleButton) {
self.options.scaleToFill = !self.options.scaleToFill;
self.$video.animate(getCSS('video'), 250);
self.$poster && self.$poster.animate(getCSS('poster'), 250);
if (toggleButton && self.$scaleButton) {
self.$scaleButton.toggleTitle();
}
}
function toggleSize() {
@ -1189,18 +1265,17 @@ Ox.VideoPlayer = function(options, self) {
self.setOption = function(key, value) {
if (key == 'fullscreen') {
toggleFullscreen();
toggleFullscreen(true);
} else if (key == 'height' || key == 'width') {
setSizes();
} else if (key == 'muted') {
toggleMuted();
self.$muteButton && self.$muteButton.toggleTitle();
toggleMuted(true);
} else if (key == 'paused') {
togglePaused(true);
} else if (key == 'position') {
setPosition(value);
setPosition(value, true);
} else if (key == 'scaleToFill') {
self.$video.css(getVideoCSS());
toggleScale(true);
}
};