263 lines
6.6 KiB
JavaScript
263 lines
6.6 KiB
JavaScript
function arrayMap(array, iter) {
|
|
if (array.map)
|
|
return array.map(iter);
|
|
else {
|
|
var result = [], i;
|
|
for(i = 0; i < array.length; i++)
|
|
result.push(iter(array[i]));
|
|
return result;
|
|
}
|
|
}
|
|
|
|
function arraySome(array, iter) {
|
|
if (array.some)
|
|
return array.some(iter);
|
|
else {
|
|
var i;
|
|
for(i = 0; i < array.length; i++)
|
|
if (iter(array[i]))
|
|
return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function arrayForEach(array, iter) {
|
|
if (array.forEach)
|
|
array.forEach(iter);
|
|
else {
|
|
var i;
|
|
for(i = 0; i < array.length; i++)
|
|
iter(array[i]);
|
|
}
|
|
}
|
|
|
|
function addButton(container, res, chapters) {
|
|
var button = $('<a class="play" title="Abspielen"><span class="postercaption">▶ Play</span></a>');
|
|
if (res.poster) {
|
|
var img = $('<img class="poster"/>');
|
|
img.attr('src', res.poster);
|
|
if (res.preview) {
|
|
button.mouseover(function() {
|
|
img.attr('src', res.preview);
|
|
});
|
|
button.mouseout(function() {
|
|
img.attr('src', res.poster);
|
|
});
|
|
}
|
|
button.append(img);
|
|
} else {
|
|
/* No poster */
|
|
button.text('▶ Play');
|
|
button.addClass('no-poster');
|
|
}
|
|
|
|
button.click(function() {
|
|
button.remove();
|
|
|
|
addPlayer(container, res, chapters);
|
|
|
|
var section = container.parents().
|
|
filter(function() {
|
|
return $(this).hasClass('video-resource');
|
|
})[0];
|
|
if (section)
|
|
$(section).addClass("playing");
|
|
});
|
|
container.append(button);
|
|
}
|
|
|
|
function parseTime(time) {
|
|
var parts = time.split(":"), part;
|
|
var r = 0;
|
|
while((part = parts.shift())) {
|
|
r = r * 60 + parseInt(part, 10);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
function addPlayer(container, res, chapters) {
|
|
var types = arrayMap(res, function(res) {
|
|
return res.type;
|
|
});
|
|
/* Can we have <audio> or <video> please?
|
|
*
|
|
* Video must be prefered over audio because <audio> can play
|
|
* videos too.
|
|
*/
|
|
var html5player;
|
|
if (arraySome(types, canPlayVideo)) {
|
|
html5player = $('<video controls="controls" autoplay="autoplay"></video>');
|
|
} else if (arraySome(types, canPlayAudio)) {
|
|
html5player = $('<audio controls="controls" autoplay="autoplay"></audio>');
|
|
}
|
|
/* ...install sources */
|
|
if (html5player) {
|
|
arrayForEach(res, function(r) {
|
|
var src = $('<source/>');
|
|
src.attr('src', r.href);
|
|
src.attr('type', r.type);
|
|
html5player.append(src);
|
|
});
|
|
}
|
|
|
|
/* Anything else than HTML5? */
|
|
var fallback;
|
|
arrayForEach(res, function(r) {
|
|
if (fallback) /* Got one already */
|
|
return;
|
|
|
|
if (r.type === 'audio/mpeg') {
|
|
var movie = '/script/dewplayer-mini.swf?showtime=1&autostart=1&mp3=' + r.href;
|
|
fallback = $('<object type="application/x-shockwave-flash" width="150" height="20">' +
|
|
'<param name="wmode" value="transparent"/>' +
|
|
'<param name="allowScriptAccess" value="always"/>' +
|
|
'<param name="movie"/>' +
|
|
'</object>');
|
|
fallback.attr('data', movie);
|
|
fallback.find('param[name="movie"]').attr('value', movie);
|
|
} else if (r.type === 'video/x-flv') {
|
|
/* Create unique id for multiple containers on one page */
|
|
var containerId = 'flowplayer' + Math.round(Math.random() * 9999);
|
|
fallback = $('<div>Moment bitte</div>');
|
|
fallback.attr('id', containerId);
|
|
/* Defer loading because fallback needs to be appended first, and we want that .js on demand anyway */
|
|
window.setTimeout(function() {
|
|
loadFlowplayer(function() {
|
|
fallback.text('');
|
|
flowplayer(containerId, { src: '/script/flowplayer-3.2.5.swf' },
|
|
{ clip: r.href });
|
|
});
|
|
}, 1);
|
|
}
|
|
});
|
|
|
|
/* Add stuff to page */
|
|
if (html5player) {
|
|
if (fallback)
|
|
html5player.append(fallback);
|
|
container.append(html5player);
|
|
if (chapters[0]) {
|
|
var dl = $('<dl class="chapters"></dl>');
|
|
var prevStart;
|
|
chapters.find('chapter').each(function() {
|
|
var title = this.getAttribute('title');
|
|
var start = this.getAttribute('start');
|
|
var href = this.getAttribute('href');
|
|
if (start && start != prevStart) {
|
|
var dt = $('<dt><a href="#"></a></dt>');
|
|
var dt_a = dt.find('a');
|
|
dt_a.text(start);
|
|
dt_a.click(function(ev) {
|
|
ev.preventDefault();
|
|
html5player[0].currentTime = parseTime(start);
|
|
});
|
|
dl.append(dt);
|
|
}
|
|
prevStart = start;
|
|
var dd = $('<dd></dd>');
|
|
if (href) {
|
|
var dd_a = $('<a></a>');
|
|
dd_a.attr('href', href);
|
|
dd_a.text(title);
|
|
dd.append(dd_a);
|
|
} else {
|
|
dd.text(title);
|
|
}
|
|
dl.append(dd);
|
|
});
|
|
container.append(dl);
|
|
}
|
|
} else if (fallback) {
|
|
container.append(fallback);
|
|
} else {
|
|
container.append('<p>Upps, das musst du wohl erstmal herunterladen</p>');
|
|
}
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
try {
|
|
/* Iterate over all resources in HTML output */
|
|
$('.resource').each(function() {
|
|
var resource = { href: $(this).find('a').attr('href'),
|
|
type: $(this).find('a').attr('type') };
|
|
var poster = $(this).dataset('poster');
|
|
var preview = $(this).dataset('preview');
|
|
|
|
/* Get all associated alternatives */
|
|
var alternativeEls = $(this).nextUntil('.resource');
|
|
var alternatives = alternativeEls.find('a').
|
|
map(function() {
|
|
return { href: $(this).attr('href'),
|
|
type: $(this).attr('type') };
|
|
}).
|
|
toArray();
|
|
|
|
var res = [resource].concat(alternatives);
|
|
if (poster)
|
|
res.poster = poster;
|
|
if (preview)
|
|
res.preview = preview;
|
|
|
|
/* Check playability */
|
|
if (arraySome(arrayMap(res, function(r) {
|
|
return r.type;
|
|
}), canPlay)) {
|
|
var liEl = $('<li class="play-resource"></li>');
|
|
$(this).before(liEl);
|
|
var player = addButton(liEl, res, $(this).find('chapters'));
|
|
}
|
|
});
|
|
} catch (x) {
|
|
if (console && console.error)
|
|
console.error(x);
|
|
}
|
|
});
|
|
|
|
function canPlay(type) {
|
|
return canPlayAudio(type) ||
|
|
canPlayVideo(type) ||
|
|
canFallback(type);
|
|
}
|
|
|
|
/**
|
|
* From http://diveintohtml5.org/everything.html
|
|
*/
|
|
function canPlayAudio(type) {
|
|
var a = document.createElement('audio');
|
|
return !!(a.canPlayType &&
|
|
a.canPlayType(type).replace(/no/, ''));
|
|
}
|
|
|
|
/**
|
|
* Partially from http://diveintohtml5.org/everything.html
|
|
*
|
|
* But we don't want audio/* as <video>
|
|
*/
|
|
function canPlayVideo(type) {
|
|
var v = document.createElement('video');
|
|
return !!(v.canPlayType &&
|
|
v.canPlayType(type).replace(/no/, '') &&
|
|
!(/^audio\//.test(type)));
|
|
}
|
|
|
|
function canFallback(type) {
|
|
return type === 'audio/mpeg' ||
|
|
type === 'video/x-flv';
|
|
}
|
|
|
|
function loadFlowplayer(cb) {
|
|
if (window.flowplayer)
|
|
cb();
|
|
else {
|
|
var playerScript = $('<script type="text/javascript" src="/script/flowplayer-3.2.4.min.js"></script>');
|
|
$(document).append(playerScript);
|
|
/* Cannot use load event because it won't work if when cached */
|
|
var interval = window.setInterval(function() {
|
|
if (window.flowplayer) {
|
|
window.clearInterval(interval);
|
|
cb();
|
|
}
|
|
}, 100);
|
|
}
|
|
}
|