summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/player.js365
-rw-r--r--js/utils.js557
-rw-r--r--player.html186
3 files changed, 1108 insertions, 0 deletions
diff --git a/js/player.js b/js/player.js
new file mode 100644
index 0000000..bcdb72b
--- /dev/null
+++ b/js/player.js
@@ -0,0 +1,365 @@
+
+/*
+* Right now I can only assume that we are going with Open Player, or OmniPlayer
+* for this bad boy. OP seems like a good idea. OP.Player(iframe);
+*/
+
+var OP = {};
+
+OP.DEBUG = false;
+OP.POST_MESSAGE = !!window.postMessage;
+
+/*
+* Utils.
+*/
+OP.origin = function(url){
+ // Grab the origin of a URL
+ if (url.substr(0, 2) === '//'){
+ url = window.location.protocol + url;
+ }
+
+ return url.split('/').slice(0,3).join('/');
+};
+
+OP.addEvent = function(elem, type, eventHandle) {
+ if (!elem) { return; }
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ } else {
+ elem["on"+type]=eventHandle;
+ }
+};
+
+// usage: log('inside coolFunc',this,arguments);
+// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
+OP.log = function(){
+ OP.log.history = OP.log.history || []; // store logs to an array for reference
+ OP.log.history.push(arguments);
+ if(window.console && OP.DEBUG){
+ window.console.log( Array.prototype.slice.call(arguments) );
+ }
+};
+
+OP.Listeners = function(){
+ this.init();
+};
+
+OP.Listeners.prototype.init = function(){
+ this.data = {};
+};
+
+OP.Listeners.prototype.getUUID = function(){
+ // Create a random id. #http://stackoverflow.com/a/2117523/564191
+ return 'listener-xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
+ return v.toString(16);
+ });
+};
+
+OP.Listeners.prototype.has = function(id){
+ return this.data.hasOwnProperty(id);
+};
+
+OP.Listeners.prototype.add = function(id, event, cb, ctx, one){
+ var d = {
+ event: event,
+ cb: cb,
+ ctx: ctx,
+ one: one
+ };
+
+ if (this.has(id)){
+ this.data[id].push(d);
+ } else {
+ this.data[id] = [d];
+ }
+};
+
+OP.Listeners.prototype.execute = function(id, data){
+ if (!this.has(id)){
+ return false;
+ }
+
+ var keep = [];
+ for (var i=0; i< this.data[id].length; i++){
+ var d = this.data[id][i];
+
+ d.cb.call(d.ctx? d.ctx: window, data);
+
+ if (d.one === false){
+ keep.push(d);
+ }
+ }
+
+ if (keep.length === 0){
+ delete this.data[id];
+ } else {
+ this.data[id] = keep;
+ }
+};
+
+OP.Listeners.prototype.on = function(id, event, cb, ctx){
+ this.add(id, event, cb, ctx, false);
+};
+
+OP.Listeners.prototype.one = function(id, event, cb, ctx){
+ this.add(id, event, cb, ctx, true);
+};
+
+OP.Listeners.prototype.off = function(event, cb){
+ // We should probably restructure so this is a bit less of a pain.
+ var keys = [];
+ for(var k in this.data){
+ keys.push(k);
+ }
+
+ var listeners = [];
+
+ for (var i in keys){
+
+ var values = this.data[keys[i]];
+ var keep = [];
+
+ for (var j in values){
+ var data = values[j];
+ if (data.event === event && data.cb === cb){
+ listeners.push(keys[i]);
+ } else {
+ keep.push(data);
+ }
+ }
+
+ if (keep.length === 0){
+ delete this.data[keys[i]];
+ } else {
+ this.data[keys[i]] = keep;
+ }
+ }
+ return listeners;
+};
+
+OP.Player = function(elem){
+ this.init(elem);
+};
+
+
+OP.Player.EVENTS = {
+ // Stop Events.
+ PLAY: 'play',
+ PAUSE: 'pause',
+ FINISH: 'finish',
+ SEEK: 'seek',
+
+ // Progress Events
+ PLAY_PROGRESS: 'playProgress',
+ LOAD_PROGRESS: 'load-progress'
+};
+
+OP.Player.prototype.init = function(elem){
+ this.elem = elem;
+
+ // Figure out the origin of where we are sending messages.
+ this.origin = OP.origin(elem.src);
+
+ // Event handling.
+ this.listeners = new OP.Listeners();
+
+ // Queuing before ready.
+ this.isReady = false;
+ this.queue = [];
+
+ if (OP.POST_MESSAGE){
+ // Set up the reciever.
+ var self = this;
+ OP.addEvent(window, 'message', function(e){
+ self.receive(e);
+ });
+ } else {
+ OP.log('Post Message is not Available.');
+ }
+};
+
+OP.Player.prototype.send = function(data, callback, ctx){
+ // We are expecting a response.
+ if (callback) {
+ // Create a UUID
+ var id = this.listeners.getUUID();
+
+ // Set the listener.
+ data.listener = id;
+
+ // Only hang on to this listener once.
+ this.listeners.one(id, null, callback, ctx);
+ }
+
+ if (!this.isReady){
+ this.queue.push(data);
+ return false;
+ }
+
+ OP.log('Player.send', data, this.origin);
+ this.elem.contentWindow.postMessage(JSON.stringify(data), this.origin);
+ return true;
+};
+
+OP.Player.prototype.receive = function(e){
+ OP.log('Player.receive', e);
+ if (e.origin !== this.origin){
+ return false;
+ }
+
+ var data;
+ try {
+ data = JSON.parse(e.data);
+ } catch (err){
+ // Not a valid response.
+ return false;
+ }
+
+ // We need to determine if we are ready.
+ if (data.method === 'ready'){
+ this.ready();
+ }
+
+ if (this.listeners.has(data.listener)){
+ this.listeners.execute(data.listener, data.value);
+ }
+};
+
+
+OP.Player.prototype.ready = function(){
+
+ if (this.isReady === true){
+ return false;
+ }
+
+ // set ready.
+ this.isReady = true;
+
+ // Clear the queue
+ for (var i=0; i<this.queue.length; i++){
+ OP.log('Player.dequeue', this.queue[i]);
+ this.send(this.queue[i]);
+ }
+ this.queue = [];
+};
+
+OP.Player.prototype.connect = function(callback, ctx){
+ var id = this.listeners.getUUID();
+ this.listeners.one(id, 'ready', callback, ctx);
+
+ if (this.isReady){
+ this.listeners.execute(id);
+ } else {
+ // We need to give the option to connect after we play.
+ this.elem.contentWindow.postMessage(JSON.stringify({
+ method:'ready',
+ listener: id
+ }), this.origin);
+ }
+};
+
+OP.Player.prototype.on = function(event, callback, ctx){
+ var id = this.listeners.getUUID();
+
+ this.listeners.on(id, event, callback, ctx);
+
+ this.send({
+ method: 'addEventListener',
+ event: event,
+ listener: id
+ });
+
+ return true;
+};
+
+OP.Player.prototype.off = function(event, callback){
+
+ var listeners = this.listeners.off(event, callback);
+
+ if (listeners.length > 0) {
+ for (var i in listeners){
+ this.send({
+ method: 'removeEventListener',
+ event: event,
+ listener: listeners[i]
+ });
+ return true;
+ }
+ }
+
+ return false;
+};
+
+OP.Player.prototype.play = function(){
+ this.send({
+ method: 'play'
+ });
+};
+
+OP.Player.prototype.pause = function(){
+ this.send({
+ method: 'pause'
+ });
+};
+
+OP.Player.prototype.paused = function(callback, ctx){
+ this.send({
+ method: 'paused'
+ }, callback, ctx);
+};
+
+OP.Player.prototype.mute = function(){
+ this.send({
+ method: 'mute'
+ });
+};
+
+OP.Player.prototype.unmute = function(){
+ this.send({
+ method: 'unmute'
+ });
+};
+
+OP.Player.prototype.isMuted = function(callback, ctx){
+ this.send({
+ method: 'isMuted'
+ }, callback, ctx);
+};
+
+OP.Player.prototype.getVolume = function(callback, ctx){
+ this.send({
+ method: 'getVolume'
+ }, callback, ctx);
+};
+
+OP.Player.prototype.setVolume = function(value){
+ this.send({
+ method: 'setVolume',
+ value: value
+ });
+};
+
+OP.Player.prototype.getDuration = function(callback, ctx){
+ this.send({
+ method: 'getDuration'
+ }, callback, ctx);
+};
+
+OP.Player.prototype.seekTo = function(value){
+ this.send({
+ method: 'seekTo',
+ value: value
+ });
+};
+
+OP.Player.prototype.currentTime = function(callback, ctx){
+ this.send({
+ method: 'currentTime'
+ }, callback, ctx);
+};
+
+// Set the global.
+window.OP = OP;
diff --git a/js/utils.js b/js/utils.js
new file mode 100644
index 0000000..6fee040
--- /dev/null
+++ b/js/utils.js
@@ -0,0 +1,557 @@
+
+var _ = {};
+
+// Random Conts
+var breaker = {};
+
+var ArrayProto = Array.prototype,
+ ObjProto = Object.prototype,
+ FuncProto = Function.prototype;
+
+var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ concat = ArrayProto.concat,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+_.each = function(obj, iterator, context) {
+ if (obj == null) { return; }
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) { return; }
+ }
+ } else {
+ for (var key in obj) {
+ if (hasOwnProperty.call(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) { return; }
+ }
+ }
+ }
+};
+
+_.map = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) {
+ return results;
+ }
+ if (Array.prototype.map && obj.map === Array.prototype.map){
+ return obj.map(iterator, context);
+ }
+ _.each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ return results;
+};
+
+// From: http://bit.ly/T9SjVv
+_.zip = function(arrays) {
+ return _.map(arrays[0], function(_,i){
+ return _.map(arrays, function(array){return array[i];});
+ });
+};
+
+_.extend = function(obj) {
+ _.each(Array.prototype.slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ if (source[prop] !== void 0){ obj[prop] = source[prop]; }
+ }
+ });
+ return obj;
+};
+
+
+var ctor = function(){};
+
+_.bind = function(func, context) {
+ var args, bound;
+ if (nativeBind && func.bind === nativeBind) {
+ return nativeBind.apply(func, slice.call(arguments, 1));
+ }
+ if (!_.isFunction(func)) {
+ throw new TypeError;
+ }
+ args = slice.call(arguments, 2);
+ return bound = function() {
+ if (!(this instanceof bound)) {
+ return func.apply(context, args.concat(slice.call(arguments)));
+ }
+ ctor.prototype = func.prototype;
+ var self = new ctor;
+ ctor.prototype = null;
+ var result = func.apply(self, args.concat(slice.call(arguments)));
+ if (Object(result) === result) { return result; }
+ return self;
+ };
+};
+
+_.trim = function(str){
+ return str.replace(/^\s+|\s+$/g, '');
+};
+
+
+/* is Functions*/
+
+// from a comment on http://dbj.org/dbj/?p=286
+// fails on only one very rare and deliberate custom object:
+// var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
+_.isFunction = function (f) {
+ try {
+ return (/^\s*\bfunction\b/).test(f);
+ } catch (x) {
+ return false;
+ }
+};
+
+_.isNone = function(obj){
+ return (obj === null || obj === undefined);
+};
+_.isString = function(obj){
+ return toString.call(obj) === "[object String]";
+};
+_.isNumber = function(obj){
+ return toString.call(obj) === "[object Number]";
+};
+_.isDate = function(obj){
+ return toString.call(obj) === "[object Date]";
+};
+_.isObject = function(obj){
+ return toString.call(obj) === "[object Object]";
+};
+_.isArray = function(obj){
+ return toString.call(obj) === "[object Array]";
+};
+_.isElement = function(obj){
+ return (!_.isNone(obj) && !_.isNone(obj.nodeType) && obj.nodeType === 1);
+};
+
+_.isEmptyObject = function(obj) {
+ if (_.isObject(obj)) {
+ for (var key in obj) {
+ if (hasOwnProperty.call(obj, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+};
+
+/* Simple JavaScript Inheritance
+ * By John Resig http://ejohn.org/
+ * MIT Licensed.
+ */
+// Inspired by base2 and Prototype
+(function(_){
+ var initializing = false, fnTest = (/xyz/).test(function(){xyz;}) ? /\b_super\b/ : /.*/;
+
+ // The base Class implementation (does nothing)
+ _.Class = function(){};
+
+ // Create a new Class that inherits from this class
+ _.Class.extend = function(prop) {
+ var _super = this.prototype;
+
+ // Instantiate a base class (but only create the instance,
+ // don't run the init constructor)
+ initializing = true;
+ var prototype = new this();
+ initializing = false;
+
+ // Copy the properties over onto the new prototype
+ for (var name in prop) {
+ // Check if we're overwriting an existing function
+ prototype[name] = typeof prop[name] === "function" &&
+ typeof _super[name] === "function" && fnTest.test(prop[name]) ?
+ (function(name, fn){
+ return function() {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]) :
+ prop[name];
+ }
+
+ // The dummy class constructor
+ function Class() {
+ // All construction is actually done in the init method
+ if ( !initializing && this.init ){
+ this.init.apply(this, arguments);
+ }
+ }
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ Class.prototype.constructor = Class;
+
+ // And make this class extendable
+ Class.extend = arguments.callee;
+
+ return Class;
+ };
+})(_);
+
+
+/* UUID */
+_.getUUID = function(){
+ return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
+ return v.toString(16);
+ });
+};
+
+
+/* SELECTORS */
+_.getElementsByClassName = function(cls, tag){
+ var elements = [];
+ if (_.isFunction(document.getElementsByClassName)){
+ _.each(document.getElementsByClassName(cls), function(e){
+ elements.push(e);
+ });
+ return elements;
+ }
+
+ if (_.isNone(tag)){
+ tag = '*';
+ }
+
+ var tags = document.getElementsByTagName(tag);
+
+ _.each(tags, function(elem){
+ if ((' ' + elem.className + ' ').indexOf(' '+cls+' ') > -1) {
+ elements.push(elem);
+ }
+ });
+ return elements;
+};
+
+_.getElementByClassName = function(cls, tag){
+ var elements = _.getElementsByClassName(cls, tag);
+ if (elements.length === 0){
+ return null;
+ }
+ return elements[0];
+};
+
+/* DOM */
+_.createElement = function(tag, attrs){
+ // create the iframe.
+ var elem = document.createElement(tag);
+
+ _.each(attrs, function(v, k){
+ elem.setAttribute(k, v);
+ });
+
+ return elem;
+};
+
+_.getChildren = function(elem, nodeName){
+ var e = [];
+
+ if (_.isString(nodeName)){
+ nodeName = nodeName.toUpperCase();
+ }
+
+ _.each(elem.childNodes, function(node){
+ if (_.isElement(node)){
+ if (!_.isNone(nodeName) && nodeName !== node.nodeName){
+ return false;
+ }
+ e.push(node);
+ }
+ });
+ return e;
+};
+
+_.getChild = function(elem, tagName){
+ /* gets the first child of the tag name.*/
+ var e = _.getChildren(elem, tagName);
+
+ if (e.length !== 0){
+ return e[0];
+ }
+ return null;
+};
+
+_.getTextContent = function(node){
+ return node.innerText || node.textContent;
+};
+
+_.setTextContent = function(node, text){
+ var prop = node.textContent === undefined ? 'innerText' : 'textContent';
+ node[prop] = text;
+};
+
+_.hasClass = function(elem, cls){
+ var kls = elem.getAttribute('class');
+
+ if (_.isNone(kls)){
+ return false;
+ }
+
+ if ((' '+kls+' ').indexOf(' '+cls+' ') > -1){
+ return true;
+ }
+ return false;
+};
+
+_.addClass = function(elem, cls){
+ var kls = elem.getAttribute('class');
+
+ if (_.isNone(kls)){
+ elem.setAttribute('class', cls);
+ return true;
+ }
+
+ var parts = kls.split(' '),
+ results = [];
+
+ _.map(parts, function(part){
+ var p = _.trim(part);
+
+ if (p !== ''){
+ results.push(p);
+ }
+ });
+
+ results.push(cls);
+
+ elem.setAttribute('class', results.join(' '));
+};
+
+_.removeClass = function(elem, cls){
+ var kls = elem.getAttribute('class');
+
+ if (_.isNone(kls)){
+ return true;
+ }
+
+ var parts = kls.split(' '),
+ results = [];
+
+ _.map(parts, function(part){
+ var p = _.trim(part);
+
+ if (p !== '' && p !== cls){
+ results.push(p);
+ }
+ });
+
+ elem.setAttribute('class', results.join(' '));
+};
+
+_.getData = function(e, attr){
+ if (!_.isNone(e.dataset)){
+ var parts = attr.split('-');
+
+ if (parts.length > 1){
+ attr = parts[0];
+ attr += _.map(parts.slice(1), function(p){return p[0].toUpperCase() + p.substr(1);}).join('');
+ }
+
+
+ // Just so it's null instead of undefined
+ return _.isNone(e.dataset[attr])? null: e.dataset[attr];
+ }
+ return e.getAttribute('data-'+attr);
+};
+
+
+_.parseStyle = function(style){
+ var data = {};
+
+ if (_.isNone(style)) { return data;}
+
+ _.each(style.split(';'), function(s){
+ var p = s.split(':');
+ data[_.trim(p[0])] = _.trim(p[1]);
+ });
+
+ return data;
+};
+
+_.createStyle = function(data){
+ var parts = [];
+ _.each(data, function(v,k){
+ parts.push(k+':'+v);
+ });
+ return parts.join(';');
+};
+
+
+/* EVENTS */
+
+_.addEvent = function(elem, type, eventHandle) {
+ if (_.isNone(elem)) { return; }
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ } else {
+ elem["on"+type]=eventHandle;
+ }
+};
+
+_.detachEvent = function(elem, type, eventHandle) {
+ if (_.isNone(elem)) { return; }
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, eventHandle, false );
+ } else if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, eventHandle );
+ } else {
+ elem["on"+type]=null;
+ }
+};
+
+/* URL */
+_.parseQuery = function(query){
+ var data = {};
+
+ if (query.substr(0,1) === '#' || query.substr(0,1) === '?'){
+ query = query.substr(1);
+ }
+
+ var parts = query.split('&');
+
+ _.each(parts, function(part){
+ var p = part.split('=');
+ data[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
+ });
+ return data;
+};
+
+_.createQuery = function(data){
+ var parts = [],
+ query = '';
+
+ _.each(data, function(v, k){
+ parts.push(k+'='+encodeURIComponent(v));
+ });
+
+ return parts.join('&');
+};
+
+_.appendQuery = function(src, query){
+ var parts = src.split('?');
+
+ if (parts.length === 2){
+ var data = _.parseQuery(parts[1]);
+ data = _.extend(data, query);
+
+ return parts[0] +'?'+ _.createQuery(data);
+
+ } else {
+ return src +'?'+ _.createQuery(query);
+ }
+};
+
+_.getOrigin = function(url){
+ return url.split('/').slice(0,3).join('/');
+};
+
+_.parseHost = function(url){
+ if (_.isNone(url)){
+ return null;
+ }
+ try {
+ return url.split('//')[1].split('/')[0];
+ } catch (err){
+ return null;
+ }
+};
+
+
+/* IMGAGES */
+//IMAGES
+
+/**
+ * I want a consistent way to pick an i#{n).embed.ly server to use, so the
+ * browser can effeciently cache images. So we use abs(hash(url)) % 10
+ *
+ * this hashing function discussion at:
+ * http://werxltd.com/wp/2010/05/13/
+ * javascript-implementation-of-javas-string-hashcode-method/
+ */
+_.hashCode = function(str){
+ var hash = 0, i, ch;
+ if (str.length === 0) {
+ return hash;
+ }
+ for (i = 0; i < str.length; i++) {
+ ch = str.charCodeAt(i);
+ hash = ((hash<<5)-hash)+ch;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
+};
+
+_.isGif = function(url){
+ if (_.isNone(url)){
+ return false;
+ }
+ return (/.gif/i).test(url);
+};
+
+
+_.generateImage = function(url, width, height, options){
+ var method,
+ data = {
+ key: 'fd92ebbc52fc43fb98f69e50e7893c13',
+ url: url,
+ errorurl: 'http://4.bp.blogspot.com/-_Gx8wi1NZf0/TW_S5s4MibI/' +
+ 'AAAAAAAAAT4/HQj19wUqfLA/s320/missin.gif'
+ //t: Math.ceil(Math.random() * 10000)
+ };
+
+ // Add our options.
+ data = _.extend(data, _.isNone(options)? {}: options);
+
+ if (width || height) {
+ method = 'crop';
+ } else {
+ method = 'resize';
+ }
+
+ if (width){
+ data.width = width;
+ }
+ if (height){
+ data.height = height;
+ }
+
+ var iServerNum = Math.abs(_.hashCode(url)) % 10;
+ return 'http://i-cdn.embed.ly/1/image/'+method+'?'+_.createQuery(data);
+};
+
+
+if (window.EMB_DEBUG === true){
+ window._ = _;
+}
diff --git a/player.html b/player.html
new file mode 100644
index 0000000..0ee8ead
--- /dev/null
+++ b/player.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Player</title>
+ <style>
+ html * {
+ box-sizing:border-box;
+ }
+
+ .left {
+ width:600px;
+ float: left;
+ }
+ .middle {
+ width:500px;
+ float: left;
+ }
+ .right {
+ width:500px;
+ float: left;
+ }
+
+ .responsive-object {
+ position: relative;
+ padding-bottom: 67.5%;
+ height: 0;
+ margin: 10px 0;
+ overflow: hidden;
+ }
+ .responsive-object iframe,
+ .responsive-object object,
+ .responsive-object embed {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+
+ #progress {
+ width: 100%;
+ height: 20px;
+ clear: both;
+ border: 1px solid #ddd;
+ margin: 10px 0;
+ }
+ #progress span{
+ width:0%;
+ height:18px;
+ background:red;
+ display: inline-block;
+ }
+
+ #volume {
+ width:40%;
+ height: 20px;
+ float:left;
+ border: 1px solid #ddd;
+ margin: 5px 0 10px 0;
+ }
+ #volume span{
+ width:0%;
+ height:18px;
+ background:blue;
+ display: inline-block;
+ }
+ .right {
+ width:60%;
+ float:left;
+ }
+ </style>
+ <script src='/js/utils.js'></script>
+ <script src='/js/player.js'></script>
+ </head>
+ <body>
+ <div class="controls">
+ <div class="right">
+ <a id="play">Play</a>
+ <a id="pause">Pause</a>
+ <a id="mute">Mute</a>
+ <a id="unmute">Unmute</a>
+ <span id="seconds">0</span>
+ <span id="duration"></span>
+ </div>
+ <div id="volume">
+ <span id="volumeBar"></span>
+ </div>
+
+ <div id="progress">
+ <span id="progressBar"></span>
+ </div>
+
+ </div>
+ <div class="responsive-object">
+
+ <iframe src="http://cdn.embedly.com/widgets/media.html?schema=vimeo&type=text%2Fhtml&html=http://player.vimeo.com/video/18150336" width="500" height="281" scrolling="no" frameborder="0" allowfullscreen></iframe>
+
+ </div>
+
+ <script>
+ OP.DEBUG = true;
+
+ var iframe = document.getElementsByTagName('iframe')[0];
+ var ratio = ((iframe.height/iframe.width)*100).toPrecision(4) + '%';
+ iframe.parentNode.style.paddingBottom =ratio;
+
+
+ var player = new OP.Player(document.getElementsByTagName('iframe')[0]);
+
+ _.addEvent(document.getElementById('play'), 'click', function(){
+ player.play();
+ });
+
+ _.addEvent(document.getElementById('pause'), 'click', function(){
+ player.pause();
+ });
+
+ _.addEvent(document.getElementById('mute'), 'click', function(){
+ player.mute();
+ updateVolume();
+ });
+
+ _.addEvent(document.getElementById('unmute'), 'click', function(){
+ player.unmute();
+ updateVolume();
+ });
+
+ var title = document.getElementsByTagName('title')[0];
+ player.on('play', function(){
+ _.setTextContent(title, '\u25b6 '+_.getTextContent(title));
+ console.log('play');
+ });
+
+ player.on('pause', function(){
+ _.setTextContent(title, _.getTextContent(title).substr(2));
+
+ console.log('pause');
+ });
+
+ var duration = null;
+ player.getDuration(function(value){
+ duration = value;
+ _.setTextContent(document.getElementById('duration'), value);
+ });
+
+ var progressBar = document.getElementById('progressBar');
+
+ var playProgress = function(value){
+ console.log('playProgress', value);
+ progressBar.style.width = ((value.seconds / value.duration)*100) + '%';
+ _.setTextContent(document.getElementById('seconds'), value.seconds);
+ };
+
+ player.on('playProgress', playProgress);
+
+ var progress = document.getElementById('progress');
+ _.addEvent(progress, 'click', function(e){
+ var seek = ((e.pageX-progress.offsetLeft)/progress.offsetWidth)*duration;
+ player.seekTo(seek);
+ });
+
+
+ player.on('finish', function(){
+ console.log('finish');
+ });
+
+ var volumeBar = document.getElementById('volumeBar');
+ var updateVolume = function(){
+ player.getVolume(function(value){
+ volumeBar.style.width = ((value / 100)*100) + '%';
+ });
+ }
+ var volume = document.getElementById('volume');
+ _.addEvent(volume, 'click', function(e){
+ console.log('hi')
+ console.log((e.pageX-volume.offsetLeft)/volume.offsetWidth)
+ var v = ((e.pageX-volume.offsetLeft)/volume.offsetWidth)*100;
+ player.setVolume(v);
+ updateVolume();
+ });
+ updateVolume();
+
+ </script>
+
+ </body>
+</html>