      1 /** The minplayer namespace. */
      2 var minplayer = minplayer || {};
      3
      4 /**
      5  * @constructor
      6  * @extends minplayer.display
      7  * @class This is the base minplayer controller.  Other controllers can derive
      8  * from the base and either build on top of it or simply define the elements
      9  * that this base controller uses.
     10  *
     11  * @param {object} context The jQuery context.
     12  * @param {object} options This components options.
     13  */
     14 minplayer.controller = function(context, options) {
     15
     16   // Derive from display
     17   minplayer.display.call(this, 'controller', context, options);
     18 };
     19
     20 /** Derive from minplayer.display. */
     21 minplayer.controller.prototype = new minplayer.display();
     22
     23 /** Reset the constructor. */
     24 minplayer.controller.prototype.constructor = minplayer.controller;
     25
     26 /**
     27  * A static function that will format a time value into a string time format.
     28  *
     29  * @param {integer} time An integer value of time.
     30  * @return {string} A string representation of the time.
     31  */
     32 minplayer.formatTime = function(time) {
     33   time = time || 0;
     34   var seconds = 0, minutes = 0, hour = 0, timeString = '';
     35
     36   hour = Math.floor(time / 3600);
     37   time -= (hour * 3600);
     38   minutes = Math.floor(time / 60);
     39   time -= (minutes * 60);
     40   seconds = Math.floor(time % 60);
     41
     42   if (hour) {
     43     timeString += String(hour);
     44     timeString += ':';
     45   }
     46
     47   timeString += (minutes >= 10) ? String(minutes) : ('0' + String(minutes));
     48   timeString += ':';
     49   timeString += (seconds >= 10) ? String(seconds) : ('0' + String(seconds));
     50   return {time: timeString, units: ''};
     51 };
     52
     53 /**
     54  * @see minplayer.display#getElements
     55  * @return {object} The elements defined by this display.
     56  */
     57 minplayer.controller.prototype.getElements = function() {
     58   var elements = minplayer.display.prototype.getElements.call(this);
     59   return jQuery.extend(elements, {
     60     play: null,
     61     pause: null,
     62     fullscreen: null,
     63     seek: null,
     64     progress: null,
     65     volume: null,
     66     timer: null
     67   });
     68 };
     69
     70 /**
     71  * @see minplayer.plugin#construct
     72  */
     73 minplayer.controller.prototype.construct = function() {
     74
     75   // Call the minplayer plugin constructor.
     76   minplayer.display.prototype.construct.call(this);
     77
     78   // Set the plugin name within the options.
     79   this.options.pluginName = 'controller';
     80
     81   // Keep track of if we are dragging...
     82   this.dragging = false;
     83
     84   // Keep track of the current volume.
     85   this.vol = 0;
     86
     87   // If they have a seek bar.
     88   if (this.elements.seek) {
     89
     90     // Create the seek bar slider control.
     91     this.seekBar = this.elements.seek.slider({
     92       range: 'min',
     93       create: function(event, ui) {
     94         jQuery('.ui-slider-range', event.target).addClass('ui-state-active');
     95       }
     96     });
     97   }
     98
     99   // If they have a volume bar.
    100   if (this.elements.volume) {
    101
    102     // Create the volume bar slider control.
    103     this.volumeBar = this.elements.volume.slider({
    104       range: 'min',
    105       orientation: 'vertical'
    106     });
    107   }
    108
    109   // Get the player plugin.
    110   this.get('player', function(player) {
    111
    112     // If they have a fullscreen button.
    113     if (this.elements.fullscreen) {
    114
    115       // Bind to the click event.
    116       minplayer.click(this.elements.fullscreen.unbind(), function() {
    117         player.toggleFullScreen();
    118       }).css({'pointer' : 'hand'});
    119     }
    120   });
    121
    122   // Get the media plugin.
    123   this.get('media', function(media) {
    124
    125     // Only bind if this player does not have its own play loader.
    126     if (!media.hasController()) {
    127
    128       // If they have a pause button
    129       if (this.elements.pause) {
    130
    131         // Bind to the click on this button.
    132         minplayer.click(this.elements.pause.unbind(), (function(controller) {
    133           return function(event) {
    134             event.preventDefault();
    135             controller.playPause(false, media);
    136           };
    137         })(this));
    138
    139         // Bind to the pause event of the media.
    140         media.bind('pause', (function(controller) {
    141           return function(event) {
    142             controller.setPlayPause(true);
    143           };
    144         })(this));
    145       }
    146
    147       // If they have a play button
    148       if (this.elements.play) {
    149
    150         // Bind to the click on this button.
    151         minplayer.click(this.elements.play.unbind(), (function(controller) {
    152           return function(event) {
    153             event.preventDefault();
    154             controller.playPause(true, media);
    155           };
    156         })(this));
    157
    158         // Bind to the play event of the media.
    159         media.bind('playing', (function(controller) {
    160           return function(event) {
    161             controller.setPlayPause(false);
    162           };
    163         })(this));
    164       }
    165
    166       // If they have a duration, then trigger on duration change.
    167       if (this.elements.duration) {
    168
    169         // Bind to the duration change event.
    170         media.bind('durationchange', (function(controller) {
    171           return function(event, data) {
    172             controller.setTimeString('duration', data.duration);
    173           };
    174         })(this));
    175
    176         // Set the timestring to the duration.
    177         media.getDuration((function(controller) {
    178           return function(duration) {
    179             controller.setTimeString('duration', duration);
    180           };
    181         })(this));
    182       }
    183
    184       // If they have a progress element.
    185       if (this.elements.progress) {
    186
    187         // Bind to the progress event.
    188         media.bind('progress', (function(controller) {
    189           return function(event, data) {
    190             var percent = data.total ? (data.loaded / data.total) * 100 : 0;
    191             controller.elements.progress.width(percent + '%');
    192           };
    193         })(this));
    194       }
    195
    196       // If they have a seek bar or timer, bind to the timeupdate.
    197       if (this.seekBar || this.elements.timer) {
    198
    199         // Bind to the time update event.
    200         media.bind('timeupdate', (function(controller) {
    201           return function(event, data) {
    202             if (!controller.dragging) {
    203               var value = 0;
    204               if (data.duration) {
    205                 value = (data.currentTime / data.duration) * 100;
    206               }
    207
    208               // Update the seek bar if it exists.
    209               if (controller.seekBar) {
    210                 controller.seekBar.slider('option', 'value', value);
    211               }
    212
    213               controller.setTimeString('timer', data.currentTime);
    214             }
    215           };
    216         })(this));
    217       }
    218
    219       // If they have a seekBar element.
    220       if (this.seekBar) {
    221
    222         // Register the events for the control bar to control the media.
    223         this.seekBar.slider({
    224           start: (function(controller) {
    225             return function(event, ui) {
    226               controller.dragging = true;
    227             };
    228           })(this),
    229           stop: (function(controller) {
    230             return function(event, ui) {
    231               controller.dragging = false;
    232               media.getDuration(function(duration) {
    233                 media.seek((ui.value / 100) * duration);
    234               });
    235             };
    236           })(this),
    237           slide: (function(controller) {
    238             return function(event, ui) {
    239               media.getDuration(function(duration) {
    240                 var time = (ui.value / 100) * duration;
    241                 if (!controller.dragging) {
    242                   media.seek(time);
    243                 }
    244                 controller.setTimeString('timer', time);
    245               });
    246             };
    247           })(this)
    248         });
    249       }
    250
    251       // Setup the mute button.
    252       if (this.elements.mute) {
    253         minplayer.click(this.elements.mute, (function(controller) {
    254           return function(event) {
    255             event.preventDefault();
    256             var value = controller.volumeBar.slider('option', 'value');
    257             if (value > 0) {
    258               controller.vol = value;
    259               controller.volumeBar.slider('option', 'value', 0);
    260               media.setVolume(0);
    261             }
    262             else {
    263               controller.volumeBar.slider('option', 'value', controller.vol);
    264               media.setVolume(controller.vol / 100);
    265             }
    266           };
    267         })(this));
    268       }
    269
    270       // Setup the volume bar.
    271       if (this.volumeBar) {
    272
    273         // Create the slider.
    274         this.volumeBar.slider({
    275           slide: function(event, ui) {
    276             media.setVolume(ui.value / 100);
    277           }
    278         });
    279
    280         media.bind('volumeupdate', (function(controller) {
    281           return function(event, vol) {
    282             controller.volumeBar.slider('option', 'value', (vol * 100));
    283           };
    284         })(this));
    285
    286         // Set the volume to match that of the player.
    287         media.getVolume((function(controller) {
    288           return function(vol) {
    289             controller.volumeBar.slider('option', 'value', (vol * 100));
    290           };
    291         })(this));
    292       }
    293     }
    294     else {
    295
    296       // Hide this controller.
    297       this.hide();
    298     }
    299   });
    300
    301   // We are now ready.
    302   this.ready();
    303 };
    304
    305 /**
    306  * Sets the play and pause state of the control bar.
    307  *
    308  * @param {boolean} state TRUE - Show Play, FALSE - Show Pause.
    309  */
    310 minplayer.controller.prototype.setPlayPause = function(state) {
    311   var css = '';
    312   if (this.elements.play) {
    313     css = state ? 'inherit' : 'none';
    314     this.elements.play.css('display', css);
    315   }
    316   if (this.elements.pause) {
    317     css = state ? 'none' : 'inherit';
    318     this.elements.pause.css('display', css);
    319   }
    320 };
    321
    322 /**
    323  * Plays or pauses the media.
    324  *
    325  * @param {bool} state true => play, false => pause.
    326  * @param {object} media The media player object.
    327  */
    328 minplayer.controller.prototype.playPause = function(state, media) {
    329   var type = state ? 'play' : 'pause';
    330   this.display.trigger(type);
    331   this.setPlayPause(!state);
    332   if (media) {
    333     media[type]();
    334   }
    335 };
    336
    337 /**
    338  * Sets the time string on the control bar.
    339  *
    340  * @param {string} element The name of the element to set.
    341  * @param {number} time The total time amount to set.
    342  */
    343 minplayer.controller.prototype.setTimeString = function(element, time) {
    344   if (this.elements[element]) {
    345     this.elements[element].text(minplayer.formatTime(time).time);
    346   }
    347 };
    348