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 animate: true, 105 range: 'min', 106 orientation: 'vertical' 107 }); 108 } 109 110 // Get the player plugin. 111 this.get('player', function(player) { 112 113 // If they have a fullscreen button. 114 if (this.elements.fullscreen) { 115 116 // Bind to the click event. 117 minplayer.click(this.elements.fullscreen.unbind(), function() { 118 player.toggleFullScreen(); 119 }).css({'pointer' : 'hand'}); 120 } 121 }); 122 123 // Get the media plugin. 124 this.get('media', function(media) { 125 126 // Only bind if this player does not have its own play loader. 127 if (!media.hasController()) { 128 129 // If they have a pause button 130 if (this.elements.pause) { 131 132 // Bind to the click on this button. 133 minplayer.click(this.elements.pause.unbind(), (function(controller) { 134 return function(event) { 135 event.preventDefault(); 136 controller.playPause(false, media); 137 }; 138 })(this)); 139 140 // Bind to the pause event of the media. 141 media.ubind(this.uuid + ':pause', (function(controller) { 142 return function(event) { 143 controller.setPlayPause(true); 144 }; 145 })(this)); 146 } 147 148 // If they have a play button 149 if (this.elements.play) { 150 151 // Bind to the click on this button. 152 minplayer.click(this.elements.play.unbind(), (function(controller) { 153 return function(event) { 154 event.preventDefault(); 155 controller.playPause(true, media); 156 }; 157 })(this)); 158 159 // Bind to the play event of the media. 160 media.ubind(this.uuid + ':playing', (function(controller) { 161 return function(event) { 162 controller.setPlayPause(false); 163 }; 164 })(this)); 165 } 166 167 // If they have a duration, then trigger on duration change. 168 if (this.elements.duration) { 169 170 // Bind to the duration change event. 171 media.ubind(this.uuid + ':durationchange', (function(controller) { 172 return function(event, data) { 173 controller.setTimeString('duration', data.duration); 174 }; 175 })(this)); 176 177 // Set the timestring to the duration. 178 media.getDuration((function(controller) { 179 return function(duration) { 180 controller.setTimeString('duration', duration); 181 }; 182 })(this)); 183 } 184 185 // If they have a progress element. 186 if (this.elements.progress) { 187 188 // Bind to the progress event. 189 media.ubind(this.uuid + ':progress', (function(controller) { 190 return function(event, data) { 191 var percent = data.total ? (data.loaded / data.total) * 100 : 0; 192 controller.elements.progress.width(percent + '%'); 193 }; 194 })(this)); 195 } 196 197 // If they have a seek bar or timer, bind to the timeupdate. 198 if (this.seekBar || this.elements.timer) { 199 200 // Bind to the time update event. 201 media.ubind(this.uuid + ':timeupdate', (function(controller) { 202 return function(event, data) { 203 if (!controller.dragging) { 204 var value = 0; 205 if (data.duration) { 206 value = (data.currentTime / data.duration) * 100; 207 } 208 209 // Update the seek bar if it exists. 210 if (controller.seekBar) { 211 controller.seekBar.slider('value', value); 212 } 213 214 controller.setTimeString('timer', data.currentTime); 215 } 216 }; 217 })(this)); 218 } 219 220 // If they have a seekBar element. 221 if (this.seekBar) { 222 223 // Register the events for the control bar to control the media. 224 this.seekBar.slider({ 225 start: (function(controller) { 226 return function(event, ui) { 227 controller.dragging = true; 228 }; 229 })(this), 230 stop: (function(controller) { 231 return function(event, ui) { 232 controller.dragging = false; 233 media.getDuration(function(duration) { 234 media.seek((ui.value / 100) * duration); 235 }); 236 }; 237 })(this), 238 slide: (function(controller) { 239 return function(event, ui) { 240 media.getDuration(function(duration) { 241 var time = (ui.value / 100) * duration; 242 if (!controller.dragging) { 243 media.seek(time); 244 } 245 controller.setTimeString('timer', time); 246 }); 247 }; 248 })(this) 249 }); 250 } 251 252 // Setup the mute button. 253 if (this.elements.mute) { 254 minplayer.click(this.elements.mute, (function(controller) { 255 return function(event) { 256 event.preventDefault(); 257 var value = controller.volumeBar.slider('option', 'value'); 258 if (value > 0) { 259 controller.vol = value; 260 controller.volumeBar.slider('value', 0); 261 media.setVolume(0); 262 } 263 else { 264 controller.volumeBar.slider('value', controller.vol); 265 media.setVolume(controller.vol / 100); 266 } 267 }; 268 })(this)); 269 } 270 271 // Setup the volume bar. 272 if (this.volumeBar) { 273 274 // Create the slider. 275 this.volumeBar.slider({ 276 slide: function(event, ui) { 277 media.setVolume(ui.value / 100); 278 } 279 }); 280 281 media.ubind(this.uuid + ':volumeupdate', (function(controller) { 282 return function(event, vol) { 283 controller.volumeBar.slider('value', (vol * 100)); 284 }; 285 })(this)); 286 287 // Set the volume to match that of the player. 288 media.getVolume((function(controller) { 289 return function(vol) { 290 controller.volumeBar.slider('value', (vol * 100)); 291 }; 292 })(this)); 293 } 294 } 295 else { 296 297 // Hide this controller. 298 this.hide(); 299 } 300 }); 301 302 // We are now ready. 303 this.ready(); 304 }; 305 306 /** 307 * Sets the play and pause state of the control bar. 308 * 309 * @param {boolean} state TRUE - Show Play, FALSE - Show Pause. 310 */ 311 minplayer.controller.prototype.setPlayPause = function(state) { 312 var css = ''; 313 if (this.elements.play) { 314 css = state ? 'inherit' : 'none'; 315 this.elements.play.css('display', css); 316 } 317 if (this.elements.pause) { 318 css = state ? 'none' : 'inherit'; 319 this.elements.pause.css('display', css); 320 } 321 }; 322 323 /** 324 * Plays or pauses the media. 325 * 326 * @param {bool} state true => play, false => pause. 327 * @param {object} media The media player object. 328 */ 329 minplayer.controller.prototype.playPause = function(state, media) { 330 var type = state ? 'play' : 'pause'; 331 this.display.trigger(type); 332 this.setPlayPause(!state); 333 if (media) { 334 media[type](); 335 } 336 }; 337 338 /** 339 * Sets the time string on the control bar. 340 * 341 * @param {string} element The name of the element to set. 342 * @param {number} time The total time amount to set. 343 */ 344 minplayer.controller.prototype.setTimeString = function(element, time) { 345 if (this.elements[element]) { 346 this.elements[element].text(minplayer.formatTime(time).time); 347 } 348 }; 349