/static/javascript/jPlayer/circle.player.js
JavaScript | 243 lines | 180 code | 23 blank | 40 comment | 25 complexity | 39561066f856ce364b40355989dde226 MD5 | raw file
- /*
- * CirclePlayer for the jPlayer Plugin (jQuery)
- * http://www.jplayer.org
- *
- * Copyright (c) 2009 - 2011 Happyworm Ltd
- * Dual licensed under the MIT and GPL licenses.
- * - http://www.opensource.org/licenses/mit-license.php
- * - http://www.gnu.org/copyleft/gpl.html
- *
- * Version: 1.0.1 (jPlayer 2.0.9)
- * Date: 30th May 2011
- *
- * Author: Mark J Panaghiston @thepag
- *
- * CirclePlayer prototype developed by:
- * Mark Boas @maboa
- * Silvia Benvenuti @aulentina
- * Jussi Kalliokoski @quinirill
- *
- * Inspired by :
- * Neway @imneway http://imneway.net/ http://forrst.com/posts/Untitled-CPt
- * and
- * Liam McKay @liammckay http://dribbble.com/shots/50882-Purple-Play-Pause
- *
- * Standing on the shoulders of :
- * John Resig @jresig
- * Mark Panaghiston @thepag
- * Louis-Rémi Babé @Louis_Remi
- */
- var CirclePlayer = function(jPlayerSelector, media, options) {
- var self = this,
- defaults = {
- // solution: "flash, html", // For testing Flash with CSS3
- supplied: "m4a, oga",
- // Android 2.3 corrupts media element if preload:"none" is used.
- // preload: "none", // No point preloading metadata since no times are displayed. It helps keep the buffer state correct too.
- cssSelectorAncestor: "#cp_container_1",
- cssSelector: {
- play: ".cp-play",
- pause: ".cp-pause"
- }
- },
- cssSelector = {
- bufferHolder: ".cp-buffer-holder",
- buffer1: ".cp-buffer-1",
- buffer2: ".cp-buffer-2",
- progressHolder: ".cp-progress-holder",
- progress1: ".cp-progress-1",
- progress2: ".cp-progress-2",
- circleControl: ".cp-circle-control"
- };
- this.cssClass = {
- gt50: "cp-gt50",
- fallback: "cp-fallback"
- };
- this.spritePitch = 104;
- this.spriteRatio = 0.24; // Number of steps / 100
- this.player = $(jPlayerSelector);
- this.media = $.extend({}, media);
- this.options = $.extend(true, {}, defaults, options); // Deep copy
- this.cssTransforms = Modernizr.csstransforms;
- this.audio = {};
- this.dragging = false; // Indicates if the progressbar is being 'dragged'.
- this.eventNamespace = ".CirclePlayer"; // So the events can easily be removed in destroy.
- this.jq = {};
- $.each(cssSelector, function(entity, cssSel) {
- self.jq[entity] = $(self.options.cssSelectorAncestor + " " + cssSel);
- });
- this._initSolution();
- this._initPlayer();
- };
- CirclePlayer.prototype = {
- _createHtml: function() {
- },
- _initPlayer: function() {
- var self = this;
- this.player.jPlayer(this.options);
- this.player.bind($.jPlayer.event.ready + this.eventNamespace, function(event) {
- if(event.jPlayer.html.used && event.jPlayer.html.audio.available) {
- self.audio = $(this).data("jPlayer").htmlElement.audio;
- }
- $(this).jPlayer("setMedia", self.media);
- self._initCircleControl();
- });
- this.player.bind($.jPlayer.event.play + this.eventNamespace, function(event) {
- $(this).jPlayer("pauseOthers");
- });
- // This event fired as play time increments
- this.player.bind($.jPlayer.event.timeupdate + this.eventNamespace, function(event) {
- if (!self.dragging) {
- self._timeupdate(event.jPlayer.status.currentPercentAbsolute);
- }
- });
- // This event fired as buffered time increments
- this.player.bind($.jPlayer.event.progress + this.eventNamespace, function(event) {
- var percent = 0;
- if((typeof self.audio.buffered === "object") && (self.audio.buffered.length > 0)) {
- if(self.audio.duration > 0) {
- var bufferTime = 0;
- for(var i = 0; i < self.audio.buffered.length; i++) {
- bufferTime += self.audio.buffered.end(i) - self.audio.buffered.start(i);
- // console.log(i + " | start = " + self.audio.buffered.start(i) + " | end = " + self.audio.buffered.end(i) + " | bufferTime = " + bufferTime + " | duration = " + self.audio.duration);
- }
- percent = 100 * bufferTime / self.audio.duration;
- } // else the Metadata has not been read yet.
- // console.log("percent = " + percent);
- } else { // Fallback if buffered not supported
- // percent = event.jPlayer.status.seekPercent;
- percent = 0; // Cleans up the inital conditions on all browsers, since seekPercent defaults to 100 when object is undefined.
- }
- self._progress(percent); // Problem here at initial condition. Due to the Opera clause above of buffered.length > 0 above... Removing it means Opera's white buffer ring never shows like with polyfill.
- // Firefox 4 does not always give the final progress event when buffered = 100%
- });
- this.player.bind($.jPlayer.event.ended + this.eventNamespace, function(event) {
- self._resetSolution();
- });
- },
- _initSolution: function() {
- if (this.cssTransforms) {
- this.jq.progressHolder.show();
- this.jq.bufferHolder.show();
- }
- else {
- this.jq.progressHolder.addClass(this.cssClass.gt50).show();
- this.jq.progress1.addClass(this.cssClass.fallback);
- this.jq.progress2.hide();
- this.jq.bufferHolder.hide();
- }
- this._resetSolution();
- },
- _resetSolution: function() {
- if (this.cssTransforms) {
- this.jq.progressHolder.removeClass(this.cssClass.gt50);
- this.jq.progress1.css({'transform': 'rotate(0deg)'});
- this.jq.progress2.css({'transform': 'rotate(0deg)'}).hide();
- }
- else {
- this.jq.progress1.css('background-position', '0 ' + this.spritePitch + 'px');
- }
- },
- _initCircleControl: function() {
- var self = this;
- this.jq.circleControl.grab({
- onstart: function(){
- self.dragging = true;
- }, onmove: function(event){
- var pc = self._getArcPercent(event.position.x, event.position.y);
- self.player.jPlayer("playHead", pc).jPlayer("play");
- self._timeupdate(pc);
- }, onfinish: function(event){
- self.dragging = false;
- var pc = self._getArcPercent(event.position.x, event.position.y);
- self.player.jPlayer("playHead", pc).jPlayer("play");
- }
- });
- },
- _timeupdate: function(percent) {
- var degs = percent * 3.6+"deg";
- var spriteOffset = (Math.floor((Math.round(percent))*this.spriteRatio)-1)*-this.spritePitch;
- if (percent <= 50) {
- if (this.cssTransforms) {
- this.jq.progressHolder.removeClass(this.cssClass.gt50);
- this.jq.progress1.css({'transform': 'rotate(' + degs + ')'});
- this.jq.progress2.hide();
- } else { // fall back
- this.jq.progress1.css('background-position', '0 '+spriteOffset+'px');
- }
- } else if (percent <= 100) {
- if (this.cssTransforms) {
- this.jq.progressHolder.addClass(this.cssClass.gt50);
- this.jq.progress1.css({'transform': 'rotate(180deg)'});
- this.jq.progress2.css({'transform': 'rotate(' + degs + ')'});
- this.jq.progress2.show();
- } else { // fall back
- this.jq.progress1.css('background-position', '0 '+spriteOffset+'px');
- }
- }
- },
- _progress: function(percent) {
- var degs = percent * 3.6+"deg";
- if (this.cssTransforms) {
- if (percent <= 50) {
- this.jq.bufferHolder.removeClass(this.cssClass.gt50);
- this.jq.buffer1.css({'transform': 'rotate(' + degs + ')'});
- this.jq.buffer2.hide();
- } else if (percent <= 100) {
- this.jq.bufferHolder.addClass(this.cssClass.gt50);
- this.jq.buffer1.css({'transform': 'rotate(180deg)'});
- this.jq.buffer2.show();
- this.jq.buffer2.css({'transform': 'rotate(' + degs + ')'});
- }
- }
- },
- _getArcPercent: function(pageX, pageY) {
- var offset = this.jq.circleControl.offset(),
- x = pageX - offset.left - this.jq.circleControl.width()/2,
- y = pageY - offset.top - this.jq.circleControl.height()/2,
- theta = Math.atan2(y,x);
- if (theta > -1 * Math.PI && theta < -0.5 * Math.PI) {
- theta = 2 * Math.PI + theta;
- }
- // theta is now value between -0.5PI and 1.5PI
- // ready to be normalized and applied
- return (theta + Math.PI / 2) / 2 * Math.PI * 10;
- },
- setMedia: function(media) {
- this.media = $.extend({}, media);
- this.player.jPlayer("setMedia", this.media);
- },
- play: function(time) {
- this.player.jPlayer("play", time);
- },
- pause: function(time) {
- this.player.jPlayer("pause", time);
- },
- destroy: function() {
- this.player.unbind(this.eventNamespace);
- this.player.jPlayer("destroy");
- }
- };