1 /** The minplayer namespace. */ 2 minplayer = minplayer || {}; 3 4 /** 5 * @constructor 6 * @extends minplayer.plugin 7 * @class Base class used to provide the display and options for any component 8 * deriving from this class. Components who derive are expected to provide 9 * the elements that they define by implementing the getElements method. 10 * 11 * @param {string} name The name of this plugin. 12 * @param {object} context The jQuery context this component resides. 13 * @param {object} options The options for this component. 14 * @param {object} queue The event queue to pass events around. 15 */ 16 minplayer.display = function(name, context, options, queue) { 17 18 // Derive from plugin 19 minplayer.plugin.call(this, name, context, options, queue); 20 }; 21 22 /** Derive from minplayer.plugin. */ 23 minplayer.display.prototype = new minplayer.plugin(); 24 25 /** Reset the constructor. */ 26 minplayer.display.prototype.constructor = minplayer.display; 27 28 /** 29 * Returns the display for this component. 30 * 31 * @return {object} The jQuery context for this display. 32 */ 33 minplayer.display.prototype.getDisplay = function() { 34 return this.context; 35 }; 36 37 /** 38 * @see minplayer.plugin.construct 39 */ 40 minplayer.display.prototype.construct = function() { 41 42 // Set the display. 43 this.display = this.getDisplay(this.context, this.options); 44 45 // Call the plugin constructor. 46 minplayer.plugin.prototype.construct.call(this); 47 48 // Set the plugin name within the options. 49 this.options.pluginName = 'display'; 50 51 // Get the display elements. 52 this.elements = this.getElements(); 53 54 // Set if this display is in autohide. 55 this.autoHide = false; 56 57 // Only do this if they allow resize for this display. 58 if (this.onResize) { 59 60 // Set the resize timeout and this pointer. 61 var resizeTimeout = 0; 62 63 // Add a handler to trigger a resize event. 64 jQuery(window).resize((function(display) { 65 return function() { 66 clearTimeout(resizeTimeout); 67 resizeTimeout = setTimeout(function() { 68 display.onResize(); 69 }, 200); 70 }; 71 })(this)); 72 } 73 }; 74 75 /** 76 * Called when the window resizes. 77 */ 78 minplayer.display.prototype.onResize = false; 79 80 /** 81 * Wrapper around hide that will always not show. 82 * 83 * @param {object} element The element you wish to hide. 84 */ 85 minplayer.display.prototype.hide = function(element) { 86 element = element || this.display; 87 if (element) { 88 element.forceHide = true; 89 element.unbind().hide(); 90 } 91 }; 92 93 /** 94 * Gets the full screen element. 95 * 96 * @return {object} The display to be used for full screen support. 97 */ 98 minplayer.display.prototype.fullScreenElement = function() { 99 return this.display; 100 }; 101 102 /** 103 * Fix for the click function in jQuery to be cross platform. 104 * 105 * @param {object} element The element that will be clicked. 106 * @param {function} fn Called when the element is clicked. 107 * @return {object} The element that is to be clicked. 108 */ 109 minplayer.click = function(element, fn) { 110 var flag = false; 111 element = jQuery(element); 112 element.bind('touchstart click', function(event) { 113 if (!flag) { 114 flag = true; 115 setTimeout(function() { 116 flag = false; 117 }, 100); 118 fn.call(this, event); 119 } 120 }); 121 return element; 122 }; 123 124 /** 125 * Determines if the player is in focus or not. 126 * 127 * @param {boolean} focus If the player is in focus. 128 */ 129 minplayer.display.prototype.onFocus = function(focus) { 130 this.hasFocus = this.focus = focus; 131 132 // If they have autoHide enabled, then show then hide this element. 133 if (this.autoHide) { 134 this.showThenHide( 135 this.autoHide.element, 136 this.autoHide.timeout, 137 this.autoHide.cb 138 ); 139 } 140 }; 141 142 /** 143 * Called if you would like for your plugin to show then hide. 144 * 145 * @param {object} element The element you would like to hide or show. 146 * @param {number} timeout The timeout to hide and show. 147 * @param {function} cb Called when something happens. 148 */ 149 minplayer.display.prototype.showThenHide = function(element, timeout, cb) { 150 151 // Get the element type. 152 var elementType = (typeof element); 153 154 // Set some interface defaults. 155 if (elementType === 'undefined') { 156 cb = null; 157 element = this.display; 158 } 159 else if (elementType === 'number') { 160 cb = timeout; 161 timeout = element; 162 element = this.display; 163 } 164 else if (elementType === 'function') { 165 cb = element; 166 element = this.display; 167 } 168 169 // Make sure we have a timeout. 170 timeout = timeout || 5000; 171 172 // Set the autohide variable. 173 this.autoHide = { 174 element: element, 175 timeout: timeout, 176 cb: cb 177 }; 178 179 // Show the element. 180 if (!element.forceHide) { 181 if (typeof element.showMe !== 'undefined') { 182 if (element.showMe) { 183 element.showMe(cb); 184 } 185 } 186 else { 187 element.show(); 188 if (cb) { 189 cb(true); 190 } 191 } 192 } 193 194 // Define the hover state for this element. 195 if (!element.hoverState) { 196 jQuery(element).bind('mouseenter', function() { 197 element.hoverState = true; 198 }); 199 jQuery(element).bind('mouseleave', function() { 200 element.hoverState = false; 201 }); 202 } 203 204 // Clear the timeout and start it over again. 205 clearTimeout(this.showTimer); 206 this.showTimer = setTimeout((function(self) { 207 return function tryAgain() { 208 209 // Check the hover state. 210 if (!element.hoverState) { 211 if (typeof element.hideMe !== 'undefined') { 212 if (element.hideMe) { 213 element.hideMe(cb); 214 } 215 } 216 else { 217 // Hide the element. 218 element.hide('slow', function() { 219 if (cb) { 220 cb(false); 221 } 222 }); 223 } 224 } 225 else { 226 227 // Try again in the timeout time. 228 self.showTimer = setTimeout(tryAgain, timeout); 229 } 230 }; 231 })(this), timeout); 232 }; 233 234 /** 235 * Make this display element go fullscreen. 236 * 237 * @param {boolean} full Tell the player to go into fullscreen or not. 238 */ 239 minplayer.display.prototype.fullscreen = function(full) { 240 var isFull = this.isFullScreen(); 241 var element = this.fullScreenElement(); 242 if (isFull && !full) { 243 element.removeClass('fullscreen'); 244 if (screenfull) { 245 screenfull.exit(); 246 } 247 this.trigger('fullscreen', false); 248 } 249 else if (!isFull && full) { 250 element.addClass('fullscreen'); 251 if (screenfull) { 252 screenfull.request(element[0]); 253 screenfull.onchange = (function(display) { 254 return function(e) { 255 if (!screenfull.isFullscreen) { 256 display.fullscreen(false); 257 } 258 }; 259 })(this); 260 } 261 this.trigger('fullscreen', true); 262 } 263 }; 264 265 /** 266 * Toggle fullscreen. 267 */ 268 minplayer.display.prototype.toggleFullScreen = function() { 269 this.fullscreen(!this.isFullScreen()); 270 }; 271 272 /** 273 * Checks to see if we are in fullscreen mode. 274 * 275 * @return {boolean} TRUE - fullscreen, FALSE - otherwise. 276 */ 277 minplayer.display.prototype.isFullScreen = function() { 278 return this.fullScreenElement().hasClass('fullscreen'); 279 }; 280 281 /** 282 * Returns a scaled rectangle provided a ratio and the container rect. 283 * 284 * @param {number} ratio The width/height ratio of what is being scaled. 285 * @param {object} rect The bounding rectangle for scaling. 286 * @return {object} The Rectangle object of the scaled rectangle. 287 */ 288 minplayer.display.prototype.getScaledRect = function(ratio, rect) { 289 var scaledRect = {}; 290 scaledRect.x = rect.x ? rect.x : 0; 291 scaledRect.y = rect.y ? rect.y : 0; 292 scaledRect.width = rect.width ? rect.width : 0; 293 scaledRect.height = rect.height ? rect.height : 0; 294 if (ratio) { 295 if ((rect.width / rect.height) > ratio) { 296 scaledRect.height = rect.height; 297 scaledRect.width = Math.floor(rect.height * ratio); 298 } 299 else { 300 scaledRect.height = Math.floor(rect.width / ratio); 301 scaledRect.width = rect.width; 302 } 303 scaledRect.x = Math.floor((rect.width - scaledRect.width) / 2); 304 scaledRect.y = Math.floor((rect.height - scaledRect.height) / 2); 305 } 306 return scaledRect; 307 }; 308 309 /** 310 * Returns all the jQuery elements that this component uses. 311 * 312 * @return {object} An object which defines all the jQuery elements that 313 * this component uses. 314 */ 315 minplayer.display.prototype.getElements = function() { 316 return {}; 317 }; 318 319 /** 320 * From https://github.com/sindresorhus/screenfull.js 321 */ 322 /*global Element:true*/ 323 (function(window, document) { 324 'use strict'; 325 var methods = (function() { 326 var methodMap = [ 327 [ 328 'requestFullscreen', 329 'exitFullscreen', 330 'fullscreenchange', 331 'fullscreen', 332 'fullscreenElement' 333 ], 334 [ 335 'webkitRequestFullScreen', 336 'webkitCancelFullScreen', 337 'webkitfullscreenchange', 338 'webkitIsFullScreen', 339 'webkitCurrentFullScreenElement' 340 ], 341 [ 342 'mozRequestFullScreen', 343 'mozCancelFullScreen', 344 'mozfullscreenchange', 345 'mozFullScreen', 346 'mozFullScreenElement' 347 ] 348 ]; 349 for (var i = 0, l = methodMap.length; i < l; i++) { 350 if (methodMap.hasOwnProperty(i)) { 351 var val = methodMap[i]; 352 if (val[1] in document) { 353 return val; 354 } 355 } 356 } 357 })(); 358 359 if (!methods) { 360 return window.screenfull = false; 361 } 362 363 var keyboardAllowed = 'ALLOW_KEYBOARD_INPUT' in Element; 364 365 var screenfull = { 366 init: function() { 367 document.addEventListener(methods[2], function(e) { 368 screenfull.isFullscreen = document[methods[3]]; 369 screenfull.element = document[methods[4]]; 370 screenfull.onchange(e); 371 }); 372 return this; 373 }, 374 isFullscreen: document[methods[3]], 375 element: document[methods[4]], 376 request: function(elem) { 377 elem = elem || document.documentElement; 378 elem[methods[0]](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT); 379 // Work around Safari 5.1 bug: reports support for keyboard in fullscreen 380 // even though it doesn't. 381 if (!document.isFullscreen) { 382 elem[methods[0]](); 383 } 384 }, 385 exit: function() { 386 document[methods[1]](); 387 }, 388 toggle: function(elem) { 389 if (this.isFullscreen) { 390 this.exit(); 391 } else { 392 this.request(elem); 393 } 394 }, 395 onchange: function() {} 396 }; 397 398 window.screenfull = screenfull.init(); 399 })(window, document); 400