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