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, 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   // Set the name of this plugin.
 82   this.options.name = 'controller';
 83 
 84   // Call the minplayer plugin constructor.
 85   minplayer.display.prototype.construct.call(this);
 86 
 87   // Play or pause the player.
 88   this.playPause = function(state) {
 89     var type = state ? 'play' : 'pause';
 90     this.display.trigger(type);
 91     this.setPlayPause(state);
 92     if (this.player) {
 93       this.player[type]();
 94     }
 95   };
 96 
 97   // Trigger the controller events.
 98   if (this.elements.play) {
 99     this.elements.play.bind('click', {obj: this}, function(event) {
100       event.preventDefault();
101       event.data.obj.playPause(true);
102     });
103   }
104 
105   if (this.elements.pause) {
106     this.elements.pause.bind('click', {obj: this}, function(event) {
107       event.preventDefault();
108       event.data.obj.playPause(false);
109     });
110   }
111 
112   // Fullscreen button.
113   var _this = this, sliderOptions = {};
114   if (this.elements.fullscreen) {
115     this.elements.fullscreen.click(function() {
116       var isFull = _this.elements.player.hasClass('fullscreen');
117       if (isFull) {
118         _this.elements.player.removeClass('fullscreen');
119       }
120       else {
121         _this.elements.player.addClass('fullscreen');
122       }
123       _this.trigger('fullscreen', !isFull);
124     }).css({'pointer' : 'hand'});
125   }
126 
127   // Create the slider.
128   this.dragging = false;
129 
130   // Add a seekBar and volumeBar using jQuery UI Slider.
131   if (this.elements.seek) {
132     this.seekBar = this.elements.seek.slider({range: 'min'});
133   }
134   if (this.elements.volume) {
135     sliderOptions = {range: 'min', orientation: 'vertical'};
136     this.volumeBar = this.elements.volume.slider(sliderOptions);
137   }
138 };
139 
140 /**
141  * Sets the play and pause state of the control bar.
142  *
143  * @param {boolean} state TRUE - Show Play, FALSE - Show Pause.
144  */
145 minplayer.controllers.base.prototype.setPlayPause = function(state) {
146   var css = '';
147   if (this.elements.play) {
148     css = state ? 'inherit' : 'none';
149     this.elements.play.css('display', css);
150   }
151   if (this.elements.pause) {
152     css = state ? 'none' : 'inherit';
153     this.elements.pause.css('display', css);
154   }
155 };
156 
157 /**
158  * Sets the time string on the control bar.
159  *
160  * @param {string} element The name of the element to set.
161  * @param {number} time The total time amount to set.
162  */
163 minplayer.controllers.base.prototype.setTimeString = function(element, time) {
164   if (this.elements[element]) {
165     this.elements[element].text(minplayer.formatTime(time).time);
166   }
167 };
168 
169 /**
170  * @see minplayer.plugin#setPlayer
171  */
172 minplayer.controllers.base.prototype.setPlayer = function(player) {
173   minplayer.display.prototype.setPlayer.call(this, player);
174 
175   var _this = this;
176 
177   // If they have a pause button, then bind to the pause event.
178   if (this.elements.pause) {
179     player.bind('pause', {obj: this}, function(event) {
180       event.data.obj.setPlayPause(true);
181     });
182   }
183 
184   // If they have a play button, then bind to playing.
185   if (this.elements.play) {
186     player.bind('playing', {obj: this}, function(event) {
187       event.data.obj.setPlayPause(false);
188     });
189   }
190 
191   // If they have a duration, then trigger on duration change.
192   if (this.elements.duration) {
193 
194     // Bind to the duration change event.
195     player.bind('durationchange', {obj: this}, function(event, data) {
196       event.data.obj.setTimeString('duration', data.duration);
197     });
198 
199     // Set the timestring to the duration.
200     player.getDuration(function(duration) {
201       _this.setTimeString('duration', duration);
202     });
203   }
204 
205   // If they have a progress, then bind to the progress.
206   if (this.elements.progress) {
207     player.bind('progress', {obj: this}, function(event, data) {
208       var percent = data.total ? (data.loaded / data.total) * 100 : 0;
209       _this.elements.progress.width(percent + '%');
210     });
211   }
212 
213   // If they have a seek bar or timer, bind to the timeupdate.
214   if (this.seekBar || this.elements.timer) {
215     player.bind('timeupdate', {obj: this}, function(event, data) {
216       if (!event.data.obj.dragging) {
217         var value = 0;
218         if (data.duration) {
219           value = (data.currentTime / data.duration) * 100;
220         }
221 
222         // Update the seek bar if it exists.
223         if (event.data.obj.seekBar) {
224           event.data.obj.seekBar.slider('option', 'value', value);
225         }
226 
227         event.data.obj.setTimeString('timer', data.currentTime);
228       }
229     });
230   }
231 
232   // Register the events for the control bar to control the media.
233   if (this.seekBar) {
234     this.seekBar.slider({
235       start: function(event, ui) {
236         _this.dragging = true;
237       },
238       stop: function(event, ui) {
239         _this.dragging = false;
240         player.getDuration(function(duration) {
241           player.seek((ui.value / 100) * duration);
242         });
243       },
244       slide: function(event, ui) {
245         player.getDuration(function(duration) {
246           var time = (ui.value / 100) * duration;
247           if (!_this.dragging) {
248             player.seek(time);
249           }
250           _this.setTimeString('timer', time);
251         });
252       }
253     });
254   }
255 
256   // Setup the volume bar.
257   if (this.volumeBar) {
258 
259     // Create the slider.
260     this.volumeBar.slider({
261       slide: function(event, ui) {
262         player.setVolume(ui.value / 100);
263       }
264     });
265 
266     // Set the volume to match that of the player.
267     player.getVolume(function(vol) {
268       _this.volumeBar.slider('option', 'value', (vol * 100));
269     });
270   }
271 };
272