diff options
| -rw-r--r-- | js/player.js | 365 | ||||
| -rw-r--r-- | js/utils.js | 557 | ||||
| -rw-r--r-- | player.html | 186 | 
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> | 
