Sanj
12 years ago
commit
8c7d55f67b
3 changed files with 212 additions and 0 deletions
@ -0,0 +1,11 @@ |
|||
<!doctype html> |
|||
<html> |
|||
<head> |
|||
<script type="text/javascript" src="jquery.js"></script> |
|||
<script type="text/javascript" src="padmavideo.js"></script> |
|||
</head> |
|||
<body> |
|||
<div class="padmaVideo" data-padma-id="AJW"></div> |
|||
</body> |
|||
|
|||
</html> |
File diff suppressed because one or more lines are too long
@ -0,0 +1,197 @@ |
|||
'use strict'; |
|||
|
|||
(function($) { |
|||
$.fn.padmavideo = function(id, options) { |
|||
var opts = $.extend({ |
|||
'layers': ['transcripts'], |
|||
'url': "http://pad.ma/api/", |
|||
'time_in': 0, |
|||
'time_out': 0, |
|||
'padma_base': 'http://pad.ma/', |
|||
'resolution': '480p', |
|||
'width': '640', |
|||
'interval': 400, |
|||
'action': 'get' //action POST param to send to url
|
|||
}, options); |
|||
var $this = this; |
|||
|
|||
var keys = ['layers']; //FIXME: add more apt keys
|
|||
var $loading = $('<div />').addClass("padmaLoading").text("Loading video...").appendTo($this); |
|||
var sendData = JSON.stringify({'id': id, 'keys': keys}); |
|||
//alert("hi");
|
|||
var deferred = $.post(opts.url, {'action': opts.action, 'data': sendData}, function(response) { |
|||
$loading.hide().remove(); |
|||
var padma = new PadmaVideo(id, response.data, $this, opts); |
|||
padma.render(); |
|||
}, "json"); |
|||
|
|||
deferred.error(function(data) { |
|||
alert("failed to load video data"); |
|||
}); |
|||
}; |
|||
|
|||
var PadmaVideo = function(id, data, $el, opts) { |
|||
this.id = id; |
|||
this.data = data; |
|||
this.$el = $el; |
|||
this.o = opts; |
|||
this.videoURL = opts.padma_base + id + "/" + opts.resolution + ".webm"; |
|||
this.render = function() { |
|||
var that = this; |
|||
this.$el.empty(); |
|||
this.$el.append(that.getWidget()); |
|||
}; |
|||
|
|||
|
|||
this.getWidget = function() { |
|||
var that = this; |
|||
var $container = this.$container = $('<div />').addClass("padmaContainer"); |
|||
var $video = this.$video = $('<video />') |
|||
.appendTo($container) |
|||
.attr("src", that.videoURL) |
|||
.attr("controls", "controls") |
|||
.addClass("padmaVideo") |
|||
.animate({'width': that.o.width}) |
|||
.load() |
|||
.bind("play", function() { |
|||
that.interval = setInterval(function() { |
|||
that.updatePlayer(); |
|||
}, that.o.interval); |
|||
}) |
|||
.bind("pause", function() { |
|||
clearInterval(that.interval); |
|||
}) |
|||
.bind("ended", function() { |
|||
clearInterval(that.interval); |
|||
}) |
|||
.bind("seeked", function() { |
|||
that.updatePlayer(); |
|||
}); |
|||
var $annotations = this.$annotations = $('<div />') |
|||
.addClass("padmaAnnotations") |
|||
.appendTo($container); |
|||
return $container; |
|||
}; |
|||
|
|||
this.updatePlayer = function() { |
|||
var that = this; |
|||
var currentTime = this.$video[0].currentTime; |
|||
|
|||
//first, handle if video has crossed end-point
|
|||
if (that.o.time_out != 0) { |
|||
if (currentTime > that.o.time_out) { |
|||
that.$video[0].currentTime = that.o.time_out; |
|||
that.$video[0].pause(); |
|||
} |
|||
if (currentTime < that.o.time_in) { |
|||
that.$video[0].currentTime = that.o.time_in; |
|||
that.$video[0].pause(); |
|||
} |
|||
} |
|||
|
|||
//now get all matching layers at current time code
|
|||
var layerNames = this.o.layers, |
|||
matchedLayers = {}; |
|||
$.each(layerNames, function(i, layerName) { |
|||
matchedLayers[layerName] = that.getLayersAtTimecode(layerName, currentTime) |
|||
}); |
|||
|
|||
//if layers are the same as last update, return
|
|||
if (isSameLayers(matchedLayers, that.currentLayers)) return false; |
|||
|
|||
//else, construct DOM elements for currently matched layers, etc.
|
|||
that.currentLayers = matchedLayers; |
|||
that.$annotations.empty(); |
|||
for (var layer in matchedLayers) { |
|||
if (matchedLayers.hasOwnProperty(layer)) { |
|||
var theseLayers = matchedLayers[layer]; |
|||
if (theseLayers.length > 0) { |
|||
var $annotsForLayer = getElemForLayer(layer, theseLayers); |
|||
$annotsForLayer.appendTo(that.$annotations); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
this.getLayersAtTimecode = function(layerName, currentTime) { |
|||
var ret = []; |
|||
var theseLayers = this.data.layers[layerName]; |
|||
$.each(theseLayers, function(i,layer) { |
|||
if (layer['in'] < currentTime && layer.out > currentTime) { |
|||
ret.push(layer); |
|||
} |
|||
}); |
|||
return ret; |
|||
}; |
|||
|
|||
}; |
|||
|
|||
function getElemForLayer(layerName, layers) { |
|||
var $elem = $('<div />').addClass("padmaLayer"); |
|||
var title = layerName.substr(0,1).toUpperCase() + layerName.substr(1, layerName.length); |
|||
var $title = $('<div />').addClass("padmaLayerTitle").text(title).appendTo($elem); |
|||
$.each(layers, function(i,v) { |
|||
var $annot = $('<div />').addClass("padmaAnnot"); |
|||
//TODO: add time-code div
|
|||
var $annotText = $('<div />') |
|||
.addClass("padmaAnnotText") |
|||
.html(v.value) |
|||
.appendTo($annot); |
|||
$annot.appendTo($elem); |
|||
}); |
|||
return $elem; |
|||
} |
|||
|
|||
function isSameLayers(layers1, layers2) { |
|||
var idString1 = '', |
|||
idString2 = ''; |
|||
for (var l in layers1) { |
|||
if (layers1.hasOwnProperty(l)) { |
|||
$.each(layers1[l], function(i,v) { |
|||
idString1 += v.id; |
|||
}); |
|||
} |
|||
} |
|||
for (var l in layers2) { |
|||
if (layers2.hasOwnProperty(l)) { |
|||
$.each(layers2[l], function(i,v) { |
|||
idString2 += v.id; |
|||
}); |
|||
} |
|||
} |
|||
return idString1 == idString2 |
|||
} |
|||
|
|||
//return true or false based on whether the browser can play padma video
|
|||
function canPlayVideo() { |
|||
return true; |
|||
} |
|||
|
|||
|
|||
//loop through all elements with class padmaVideo and automagically instantiate them using optional data- attributes for options
|
|||
$(document).ready(function() { |
|||
$('.padmaVideo').each(function() { |
|||
var padmaId = $(this).attr("data-padma-id"), |
|||
options = {}, |
|||
$this = $(this); |
|||
|
|||
if ($this.hasAttr("data-padma-layers")) options.layers = $this.attr("data-padma-layers"); |
|||
if ($this.hasAttr("data-padma-url")) options.url = $this.attr("data-padma-url"); |
|||
if ($this.hasAttr("data-padma-in")) options.time_in = $this.attr("data-padma-in"); |
|||
if ($this.hasAttr("data-padma-out")) options.time_out = $this.attr("data-padma-out"); |
|||
if ($this.hasAttr("data-padma-base")) options.padma_base = $this.attr("data-padma-base"); |
|||
if ($this.hasAttr("data-padma-resolution")) options.resolution = $this.attr("data-padma-resolution"); |
|||
if ($this.hasAttr("data-padma-width")) options.width = $this.attr("data-padma-width"); |
|||
if ($this.hasAttr("data-padma-interval")) options.interval = $this.attr("data-padma-interval"); |
|||
// if ($this.hasAttr("data-padma-height")) options.height = $this.attr("data-padma-height");
|
|||
|
|||
$this.padmavideo(padmaId, options); |
|||
|
|||
}); |
|||
}); |
|||
|
|||
$.fn.hasAttr = function(attr) { |
|||
return this.attr(attr) != undefined; |
|||
}; |
|||
|
|||
})(jQuery); |
Loading…
Reference in new issue