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