// mediaelement-player
$(function() {
function deserialize(string) {
var result = {};
if (string) {
var parts = string.split(/&|\?/);
for (var i = 0; i < parts.length; i++) {
var part = parts[i].split("=");
if (part.length === 2)
result[decodeURIComponent(part[0])] = decodeURIComponent(part[1]);
}
}
return result;
}
(function(strings) {
strings['en-US'] = {
'Download File': 'Open Stream in Desktop-Player'
}
})(mejs.i18n.locale.strings);
var feat = ['playpause', 'volume', 'fullscreen'];
if($('.video-wrap').hasClass('has-subtitles'))
feat.push('subtitles');
$('body.room video.mejs, body.embed video.mejs').mediaelementplayer({
features: feat,
enableAutosize: true
});
$('body.room audio.mejs, body.embed audio.mejs').mediaelementplayer({
features: ['playpause', 'volume', 'current']
});
var $relivePlayer = $('body.relive-player .video-wrap');
if($relivePlayer.length > 0) {
var player = new Clappr.Player({
baseUrl: 'assets/clapprio/',
plugins: {
core: [ClapprThumbnailsPlugin]
},
source: $relivePlayer.data('m3u8'),
height: $relivePlayer.data('height'),
width: $relivePlayer.data('width'),
autoPlay: true,
scrubThumbnails: {
backdropHeight: 64,
spotlightHeight: 84,
thumbs: ClapprThumbnailsPlugin.buildSpriteConfig(
$relivePlayer.data("sprites"),
$relivePlayer.data("sprites-n"),
160, 90,
$relivePlayer.data("sprites-cols"),
$relivePlayer.data("sprites-interval")
),
},
events: {
onReady: function() {
var playback = player.core.getCurrentContainer().playback;
var params = deserialize(location.href)
playback.once(Clappr.Events.PLAYBACK_PLAY, function() {
var seek = parseFloat(params.t);
if (!isNaN(seek)) {
player.seek(seek);
} else if (playback.getPlaybackType() == 'vod') {
// skip forward to scheduled beginning of the talk at ~ 0:14:30 (30 sec offset, if speaker starts on time)
player.seek(14 * 60 + 30);
}
});
}
}
});
player.attachTo($relivePlayer.get(0));
}
$(window).on('load', function() {
$(window).trigger('resize');
});
});
// tabs
$(function() {
// activate tab via hash and default to video
function setTabToHash() {
var activeTab = $('.nav-tabs a[href=' + window.location.hash + ']').tab('show');
}
// change hash on tab change
$('.nav-tabs').on('shown.bs.tab', 'a', function (e) {
window.location.hash = e.target.hash;
});
// adjust tabs when hash changes
$(window).on('hashchange', setTabToHash).trigger('hashchange');
});
// schedule-timeline
$(function() {
var
$schedule = $('body .schedule'),
$now = $schedule.find('.now'),
scrollLock = false,
rewindTimeout,
/* 10 seconds after manual navigation */
rewindTime = 10000,
/* 1/2s animation on the scolling element */
scrollDuration = 500,
/* update now-pointer placement every 1/2s */
updateTimer = 500,
/* offset to the browsers realtime (for simulation) */
offset = $('.js-schedule-settings').data('scheduleoffset');
$schedule.on('mouseenter mouseleave touchstart touchend', function(e) {
if(e.type == 'mouseleave' || e.type == 'touchend') {
rewindTimeout = setTimeout(function() {
scrollLock = false;
}, 5000);
} else {
clearTimeout(rewindTimeout);
scrollLock = true;
}
});
// schedule now-marker & scrolling
function updateProgramView(initial) {
var
// corrected "now" timestamp in unix-counting (seconds, not microseconds)
now = (Date.now() / 1000) + offset;
// only check the first room (shouldn't matter anyway)
// find the newest block that starts in the past
// that's the one that is most probably currently still running
var $block = $schedule
.find('.room')
.first()
.find('.block')
.filter(function(i, el) {
return $(this).data('start') < now;
}).last();
if($block.length == 0)
return $now.css('width', 0);
var
// start & end-timestamp
start = $block.data('start'),
end = $block.data('end'),
// place of the now-marker between 0 and 1 within this block
normalized = Math.max(0, Math.min(1, (now - start) / (end - start))),
// projected to pixels with respect to the schedules left end
px = $block.position().left + ($block.outerWidth() * normalized),
// visible width of the schedule display
displayw = $schedule.width(),
// current scroll position
scrollx = $schedule.scrollLeft(),
// distance of the now-marker to the left border of the schedule display
px_in_display = px - scrollx;
//console.log($block.get(0), new Date(start*1000), new Date(now*1000), new Date(end*1000), normalized, px);
$now.css('width', px);
// scrolling is locked by manual interaction
if(scrollLock)
return;
if(
// now marker is > 2/3 of the schedule-display-width
px_in_display > (displayw * 2/3) ||
// now marker is <1/7 of the schedule-display-width
px_in_display < (displayw/7)
) {
// scroll schedule so that now-marker is as 1/5 of the screen
$schedule.stop().scrollTo(px - displayw/6, {
axis: 'x',
duration: initial ? 0 : scrollDuration,
});
}
}
// when on schedules tab
var updateInterval;
function on() {
// initial trigger
updateProgramView(true);
// timed triggers
updateInterval = setInterval(updateProgramView, updateTimer);
}
function off() {
clearInterval(updateInterval);
}
if(window.location.hash == '#schedule' || window.location.href.indexOf('/schedule') != -1)
on();
// trigger when a tab was changed
$('.nav-tabs').on('shown.bs.tab', 'a', function(e) {
if(e.target.hash == '#schedule')
on();
else
off();
});
});
// feedback form
$(function() {
$('.feedback-form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
$('.feedback-form').hide();
$.ajax({
url: $form.prop('action'),
method: $form.prop('method'),
data: $form.serialize(),
success: function() {
$('.feedback-thankyou').show();
},
error: function() {
$('.feedback-error').show();
}
});
});
});
// update teaser images
$(function() {
setInterval(function() {
$('.rooms .lecture .teaser').each(function() {
var
$teaser = $(this),
$preload = $(''),
src = $teaser.data('src');
if(!src) {
src = $teaser.prop('src');
$teaser.data('src', src);
}
$preload.on('load', function() {
$teaser.prop('src', $preload.prop('src'));
}).prop('src', src + '?'+(new Date()).getTime());
});
}, 1000*60);
});
// multiviewer
$(function() {
var audioMeter = !!window.chrome;
$('body.multiview')
.find('audio, video')
.each(function(idx, player) {
var
$player = $(player),
$meter = $player.closest('.cell').find('.meter'),
$timer = $player.closest('.cell').find('.timer');
$player.on("timeupdate", function(e)
{
var
s = Math.floor(this.currentTime % 60),
m = Math.floor(this.currentTime / 60) % 60,
h = Math.floor(this.currentTime / 60 / 60) % 24,
d = Math.floor(this.currentTime / 60 / 60 / 24),
f = Math.floor((this.currentTime - Math.floor(this.currentTime)) * 1000),
txt = '';
txt += d+'d ';
if(h < 10) txt += '0';
txt += h+'h ';
if(m < 10) txt += '0';
txt += m+'m ';
if(s < 10) txt += '0';
txt += s+'s ';
if(f < 10) txt += '00';
else if(f < 100) txt += '0';
txt += f+'ms';
$timer.text(txt);
});
if(!audioMeter)
{
$player.prop('muted', true);
$meter.hide();
return;
}
var
ctx = new AudioContext(),
audioSrc = ctx.createMediaElementSource(player),
analyser = ctx.createAnalyser();
// we have to connect the MediaElementSource with the analyser
audioSrc.connect(analyser);
// we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
analyser.fftSize = 64;
var w = 100 / analyser.frequencyBinCount;
for (var i = 0; i < analyser.frequencyBinCount; i++) {
var c = Math.floor( i * 255 / analyser.frequencyBinCount );
$('