2011-04-23 16:45:50 +00:00
|
|
|
// vim: et:ts=4:sw=4:sts=4:ft=js
|
2011-04-22 22:03:10 +00:00
|
|
|
Ox.VideoPanelPlayer = function(options, self) {
|
|
|
|
|
|
|
|
var self = self || {},
|
|
|
|
that = new Ox.Element('div', self)
|
|
|
|
.defaults({
|
|
|
|
annotationsSize: 256,
|
|
|
|
duration: 0,
|
|
|
|
height: 0,
|
|
|
|
loop: false,
|
|
|
|
muted: false,
|
|
|
|
paused: false,
|
|
|
|
playInToOut: false,
|
|
|
|
points: [0, 0],
|
|
|
|
position: 0,
|
|
|
|
poster: '',
|
|
|
|
showAnnotations: true,
|
|
|
|
showControls: true,
|
|
|
|
subtitles: [],
|
|
|
|
videoHeight: 0,
|
|
|
|
videoSize: 'fit',
|
|
|
|
videoWidth: 0,
|
|
|
|
videoURL: '',
|
|
|
|
width: 0
|
|
|
|
})
|
|
|
|
.options(options || {})
|
|
|
|
.css({
|
|
|
|
height: self.options.height + 'px',
|
|
|
|
width: self.options.width + 'px'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
resize: resizeElement,
|
|
|
|
key_shift_a: function() {
|
|
|
|
that.toggleAnnotations();
|
|
|
|
},
|
|
|
|
key_shift_c: function() {
|
|
|
|
that.toggleControls();
|
|
|
|
},
|
|
|
|
key_shift_s: function() {
|
|
|
|
that.toggleSize();
|
|
|
|
},
|
|
|
|
key_space: function() {
|
|
|
|
that.togglePlay();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$.extend(self, {
|
|
|
|
fullscreen: false,
|
|
|
|
videoCSS: getVideoCSS()
|
|
|
|
});
|
|
|
|
//alert(JSON.stringify([self.playerHeight, self.playerWidth, self.videoCSS]))
|
|
|
|
|
|
|
|
self.$player = new Ox.Element()
|
|
|
|
.css({
|
|
|
|
overflowX: 'hidden',
|
|
|
|
overflowY: 'hidden'
|
|
|
|
})
|
|
|
|
.bind({
|
|
|
|
mousedown: that.gainFocus
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
resize: resizeVideo
|
|
|
|
});
|
|
|
|
|
|
|
|
self.$video = new Ox.VideoElement({
|
|
|
|
height: self.videoCSS.height,
|
|
|
|
paused: true,
|
|
|
|
points: self.options.points,
|
|
|
|
position: self.options.position,
|
|
|
|
url: self.options.videoURL,
|
|
|
|
width: self.videoCSS.width
|
|
|
|
})
|
|
|
|
.css(self.videoCSS)
|
|
|
|
.bindEvent({
|
|
|
|
paused: paused,
|
|
|
|
playing: playing
|
|
|
|
})
|
|
|
|
.appendTo(self.$player);
|
|
|
|
|
|
|
|
self.$controls = new Ox.Element()
|
|
|
|
.bindEvent({
|
|
|
|
toggle: toggleControls
|
|
|
|
});
|
|
|
|
|
|
|
|
self.$buttons = new Ox.Element()
|
|
|
|
.css({
|
|
|
|
float: 'left',
|
|
|
|
width: '16px',
|
|
|
|
margin: '4px'
|
|
|
|
})
|
|
|
|
.appendTo(self.$controls);
|
|
|
|
|
|
|
|
self.$button = {
|
|
|
|
play: new Ox.Button({
|
|
|
|
id: 'play',
|
|
|
|
title: [
|
|
|
|
{id: 'play', title: 'play'},
|
|
|
|
{id: 'pause', title: 'pause'}
|
|
|
|
],
|
|
|
|
tooltip: ['Play', 'Pause'],
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
click: self.$video.togglePlay
|
|
|
|
}),
|
|
|
|
mute: new Ox.Button({
|
|
|
|
id: 'mute',
|
|
|
|
title: [
|
|
|
|
{id: 'mute', title: 'mute'},
|
|
|
|
{id: 'unmute', title: 'unmute'}
|
|
|
|
],
|
|
|
|
tooltip: ['Mute', 'Unmute'],
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
click: self.$video.toggleMute
|
|
|
|
}),
|
|
|
|
size: new Ox.Button({
|
|
|
|
id: 'size',
|
|
|
|
title: self.options.videoSize == 'fit' ? [
|
|
|
|
{id: 'fill', title: 'fill'},
|
|
|
|
{id: 'fit', title: 'fit'}
|
|
|
|
] : [
|
|
|
|
{id: 'fit', title: 'fit'},
|
|
|
|
{id: 'fill', title: 'fill'}
|
|
|
|
],
|
|
|
|
tooltip: self.options.videoSize == 'fit' ? [
|
|
|
|
'Fill Screen', 'Fit to Screen'
|
|
|
|
] : [
|
|
|
|
'Fit to Screen', 'Fill Screen'
|
|
|
|
],
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
click: toggleSize
|
|
|
|
}),
|
|
|
|
fullscreen: new Ox.Button({
|
|
|
|
id: 'size',
|
|
|
|
title: [
|
|
|
|
{id: 'grow', title: 'grow'},
|
|
|
|
{id: 'shrink', title: 'shrink'}
|
|
|
|
],
|
|
|
|
tooltip: [
|
|
|
|
'Enter Fullscreen', 'Exit Fullscreen'
|
|
|
|
],
|
|
|
|
type: 'image'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
click: toggleFullscreen
|
|
|
|
})
|
|
|
|
}
|
|
|
|
var i = 0;
|
|
|
|
Ox.forEach(self.$button, function($button) {
|
|
|
|
$button.css({
|
|
|
|
position: 'absolute',
|
|
|
|
left: '8px',
|
|
|
|
top: (8 + i++ * 24) + 'px'
|
|
|
|
})
|
|
|
|
.appendTo(self.$buttons);
|
|
|
|
});
|
|
|
|
|
|
|
|
self.$timelines = new Ox.Element()
|
|
|
|
.css({
|
|
|
|
float: 'left',
|
|
|
|
margin: '4px'
|
|
|
|
})
|
|
|
|
.appendTo(self.$controls);
|
|
|
|
|
|
|
|
self.$timeline = {
|
|
|
|
large: new Ox.LargeTimeline({
|
|
|
|
duration: self.options.duration,
|
|
|
|
position: self.options.position,
|
|
|
|
subtitles: self.options.subtitles,
|
|
|
|
videoId: self.options.videoId,
|
|
|
|
width: getTimelineWidth()
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
top: '4px'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
change: changeLargeTimeline
|
|
|
|
}),
|
|
|
|
small: new Ox.SmallTimeline({
|
|
|
|
duration: self.options.duration,
|
|
|
|
position: self.options.position,
|
|
|
|
subtitles: self.options.subtitles,
|
|
|
|
videoId: self.options.videoId,
|
|
|
|
width: getTimelineWidth()
|
|
|
|
})
|
|
|
|
.css({
|
|
|
|
top: '76px'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
change: changeSmallTimeline
|
|
|
|
})
|
|
|
|
};
|
|
|
|
Ox.forEach(self.$timeline, function($timeline) {
|
|
|
|
$timeline.appendTo(self.$timelines);
|
|
|
|
});
|
|
|
|
|
|
|
|
self.$panel = new Ox.SplitPanel({
|
|
|
|
elements: [
|
|
|
|
{
|
|
|
|
element: self.$player
|
|
|
|
},
|
|
|
|
{
|
|
|
|
collapsed: !self.options.showControls,
|
|
|
|
collapsible: true,
|
|
|
|
element: self.$controls,
|
|
|
|
size: 104
|
|
|
|
}
|
|
|
|
],
|
|
|
|
orientation: 'vertical'
|
|
|
|
})
|
|
|
|
.bindEvent({
|
|
|
|
resize: resizePanel
|
|
|
|
});
|
|
|
|
|
|
|
|
self.$annotations = new Ox.Element()
|
|
|
|
.bindEvent({
|
|
|
|
resize: resizeAnnotations,
|
|
|
|
resizeend: resizeendAnnotations,
|
|
|
|
toggle: toggleAnnotations
|
|
|
|
});
|
|
|
|
|
|
|
|
that.$element = new Ox.SplitPanel({
|
|
|
|
elements: [
|
|
|
|
{
|
|
|
|
element: self.$panel
|
|
|
|
},
|
|
|
|
{
|
|
|
|
collapsed: !self.options.showAnnotations,
|
|
|
|
collapsible: true,
|
|
|
|
element: self.$annotations,
|
|
|
|
resizable: true,
|
|
|
|
resize: [192, 256, 320, 384],
|
|
|
|
size: self.options.annotationsSize
|
|
|
|
}
|
|
|
|
],
|
|
|
|
orientation: 'horizontal'
|
|
|
|
});
|
|
|
|
|
|
|
|
function changeLargeTimeline(event, data) {
|
|
|
|
self.options.position = data.position;
|
|
|
|
self.$video.position(self.options.position);
|
|
|
|
self.$timeline.small.options({
|
|
|
|
position: self.options.position
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function changeSmallTimeline(event, data) {
|
|
|
|
self.options.position = data.position;
|
|
|
|
self.$video.position(self.options.position);
|
|
|
|
self.$timeline.large.options({
|
|
|
|
position: self.options.position
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getPlayerHeight() {
|
|
|
|
return self.options.height -
|
|
|
|
self.options.showControls * 104 - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getPlayerWidth() {
|
|
|
|
return self.options.width -
|
|
|
|
(self.options.showAnnotations && !self.fullscreen) *
|
|
|
|
self.options.annotationsSize - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTimelineWidth() {
|
|
|
|
return self.options.width -
|
|
|
|
(self.options.showAnnotations && !self.fullscreen) *
|
|
|
|
self.options.annotationsSize - 40
|
|
|
|
}
|
|
|
|
|
|
|
|
function getVideoCSS() {
|
|
|
|
var width = getPlayerWidth(),
|
|
|
|
height = getPlayerHeight(),
|
|
|
|
ratio = width / height,
|
|
|
|
videoRatio = self.options.videoWidth / self.options.videoHeight,
|
|
|
|
isWide = ratio < videoRatio;
|
|
|
|
return self.options.videoSize == 'fit' ? {
|
|
|
|
position: 'absolute',
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
top: 0,
|
|
|
|
bottom: 0,
|
|
|
|
width: (isWide ? width : Math.round(height * videoRatio)) + 'px',
|
|
|
|
height: (isWide ? Math.round(width / videoRatio) : height) + 'px',
|
|
|
|
margin: 'auto'
|
|
|
|
} : {
|
|
|
|
width: (isWide ? Math.round(height * videoRatio) : width) + 'px',
|
|
|
|
height: (isWide ? height : Math.round(width / videoRatio)) + 'px',
|
|
|
|
margin: [
|
|
|
|
isWide ? '0' : Math.floor((height - width / videoRatio) / 2) + 'px',
|
|
|
|
isWide ? Math.ceil((width - height * videoRatio) / 2) + 'px' : '0',
|
|
|
|
isWide ? '0' : Math.ceil((height - width / videoRatio) / 2) + 'px',
|
|
|
|
isWide ? Math.floor((width - height * videoRatio) / 2) + 'px' : '0'
|
|
|
|
].join(' ')
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function paused() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function playing(event, data) {
|
|
|
|
self.options.position = data.position;
|
|
|
|
self.$timeline.large.options({
|
|
|
|
position: self.options.position
|
|
|
|
});
|
|
|
|
self.$timeline.small.options({
|
|
|
|
position: self.options.position
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeAnnotations(event, data) {
|
|
|
|
self.options.annotationsSize = data;
|
|
|
|
resizeVideoAndControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeendAnnotations(event, data) {
|
|
|
|
self.options.annotationsSize = data;
|
|
|
|
that.triggerEvent('change', {
|
|
|
|
annotationsSize: self.options.annotationsSize
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeControls() {
|
|
|
|
self.$timeline.large.options({
|
|
|
|
width: getTimelineWidth()
|
|
|
|
});
|
|
|
|
self.$timeline.small.options({
|
|
|
|
width: getTimelineWidth()
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeElement(event, data) {
|
|
|
|
// called on browser toggle
|
|
|
|
self.options.height = data;
|
|
|
|
resizeVideo();
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizePanel(event, data) {
|
|
|
|
// called on annotations toggle
|
|
|
|
resizeVideoAndControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeVideoAndControls() {
|
|
|
|
resizeVideo();
|
|
|
|
resizeControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
function resizeVideo() {
|
|
|
|
self.videoCSS = getVideoCSS();
|
|
|
|
self.$video.css(self.videoCSS);
|
|
|
|
};
|
|
|
|
|
|
|
|
function toggleAnnotations(event, data) {
|
|
|
|
self.options.showAnnotations = !data.collapsed;
|
|
|
|
that.triggerEvent('change', {
|
|
|
|
showAnnotations: self.options.showAnnotations
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function toggleControls(event, data) {
|
|
|
|
self.options.showControls = !data.collapsed;
|
|
|
|
that.triggerEvent('change', {
|
|
|
|
showControls: self.options.showControls
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function toggleFullscreen() {
|
|
|
|
self.fullscreen = !self.fullscreen;
|
|
|
|
self.options.showAnnotations && that.$element.toggle(1);
|
|
|
|
self.fullscreen && self.options.showControls && self.$panel.toggle(1);
|
|
|
|
that.triggerEvent((self.fullscreen ? 'enter' : 'exit') + 'fullscreen', {});
|
|
|
|
}
|
|
|
|
|
|
|
|
function toggleSize() {
|
|
|
|
self.options.videoSize = self.options.videoSize == 'fit' ? 'fill' : 'fit';
|
|
|
|
resizeVideo();
|
|
|
|
that.triggerEvent('change', {
|
|
|
|
videoSize: self.options.videoSize
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
self.onChange = function(key, value) {
|
|
|
|
if (key == 'height') {
|
|
|
|
resizeVideo();
|
|
|
|
} else if (key == 'position') {
|
|
|
|
self.$video.position(value);
|
|
|
|
} else if (key == 'width') {
|
|
|
|
resizeVideoAndControls();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
that.toggleAnnotations = function() {
|
|
|
|
that.$element.toggle(1);
|
|
|
|
//that.toggleAnnotations(null, !self.options.showAnnotations);
|
|
|
|
};
|
|
|
|
|
|
|
|
that.toggleControls = function() {
|
|
|
|
self.$panel.toggle(1);
|
|
|
|
//that.toggleControls(null, !self.options.showControls);
|
|
|
|
};
|
|
|
|
|
|
|
|
that.toggleMute = function() {
|
|
|
|
self.$button.mute.trigger('click');
|
|
|
|
};
|
|
|
|
|
|
|
|
that.togglePlay = function() {
|
|
|
|
self.$button.play.trigger('click');
|
|
|
|
};
|
|
|
|
|
|
|
|
that.toggleSize = function() {
|
|
|
|
self.$button.size.trigger('click');
|
|
|
|
}
|
|
|
|
|
|
|
|
return that;
|
|
|
|
|
|
|
|
}
|