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