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