      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   // Only do this if they allow resize for this display.
     55   if (this.onResize) {
     56
     57     // Set the resize timeout and this pointer.
     58     var resizeTimeout = 0;
     59
     60     // Add a handler to trigger a resize event.
     61     jQuery(window).resize((function(display) {
     62       return function() {
     63         clearTimeout(resizeTimeout);
     64         resizeTimeout = setTimeout(function() {
     65           display.onResize();
     66         }, 200);
     67       };
     68     })(this));
     69   }
     70 };
     71
     72 /**
     73  * Called when the window resizes.
     74  */
     75 minplayer.display.prototype.onResize = false;
     76
     77 /**
     78  * Wrapper around hide that will always not show.
     79  *
     80  * @param {object} element The element you wish to hide.
     81  */
     82 minplayer.display.prototype.hide = function(element) {
     83   element = element || this.display;
     84   if (element) {
     85     element.forceHide = true;
     86     element.unbind().hide();
     87   }
     88 };
     89
     90 /**
     91  * Gets the full screen element.
     92  *
     93  * @return {object} The display to be used for full screen support.
     94  */
     95 minplayer.display.prototype.fullScreenElement = function() {
     96   return this.display;
     97 };
     98
     99 /**
    100  * Fix for the click function in jQuery to be cross platform.
    101  *
    102  * @param {object} element The element that will be clicked.
    103  * @param {function} fn Called when the element is clicked.
    104  * @return {object} The element that is to be clicked.
    105  */
    106 minplayer.click = function(element, fn) {
    107   var flag = false;
    108   element = jQuery(element);
    109   element.bind('touchstart click', function(event) {
    110     if (!flag) {
    111       flag = true;
    112       setTimeout(function() {
    113         flag = false;
    114       }, 100);
    115       fn.call(this, event);
    116     }
    117   });
    118   return element;
    119 };
    120
    121 /**
    122  * Determines if the player is in focus or not.
    123  *
    124  * @param {boolean} focus If the player is in focus.
    125  */
    126 minplayer.display.prototype.onFocus = function(focus) {
    127   this.hasFocus = this.focus = focus;
    128 };
    129
    130 /** Keep track of all the show hide elements. */
    131 minplayer.showHideElements = [];
    132
    133 /**
    134  * Show all the show hide elements.
    135  */
    136 minplayer.showAll = function() {
    137   var i = minplayer.showHideElements.length;
    138   var obj = null;
    139   while (i--) {
    140     obj = minplayer.showHideElements[i];
    141     minplayer.showThenHide(obj.element, obj.timeout, obj.callback);
    142   }
    143 };
    144
    145 /**
    146  * Stops the whole show then hide from happening.
    147  *
    148  * @param {object} element The element you want the showThenHide to stop.
    149  */
    150 minplayer.stopShowThenHide = function(element) {
    151   element = jQuery(element);
    152   if (element.showTimer) {
    153     clearTimeout(element.showTimer);
    154   }
    155   element.stopShowThenHide = true;
    156   element.shown = true;
    157   element.show();
    158 };
    159
    160 /**
    161  * Called if you would like for your display item to show then hide.
    162  *
    163  * @param {object} element The element you would like to hide or show.
    164  * @param {number} timeout The timeout to hide and show.
    165  * @param {function} callback Called when something happens.
    166  */
    167 minplayer.showThenHide = function(element, timeout, callback) {
    168
    169   // If no element exists, then just return.
    170   if (!element) {
    171     return;
    172   }
    173
    174   // Ensure we have a timeout.
    175   timeout = timeout || 5000;
    176
    177   // If this has not yet been configured.
    178   if (!element.showTimer) {
    179     element.shown = true;
    180     element.stopShowThenHide = false;
    181
    182     // Add this to our showHideElements.
    183     minplayer.showHideElements.push({
    184       element: element,
    185       timeout: timeout,
    186       callback: callback
    187     });
    188
    189     // Bind to a click event.
    190     minplayer.click(document, function() {
    191       if (!element.stopShowThenHide) {
    192         minplayer.showThenHide(element, timeout, callback);
    193       }
    194     });
    195
    196     // Bind to the mousemove event.
    197     jQuery(document).bind('mousemove', function() {
    198       if (!element.stopShowThenHide) {
    199         minplayer.showThenHide(element, timeout, callback);
    200       }
    201     });
    202   }
    203
    204   // Clear the timeout, and then setup the show then hide functionality.
    205   clearTimeout(element.showTimer);
    206
    207   // Show the display.
    208   if (!element.shown && !element.forceHide) {
    209     element.shown = true;
    210     element.show();
    211     if (callback) {
    212       callback(true);
    213     }
    214   }
    215
    216   // Set a timer to hide it after the timeout.
    217   element.showTimer = setTimeout(function() {
    218     element.hide('slow', function() {
    219       element.shown = false;
    220       if (callback) {
    221         callback(false);
    222       }
    223     });
    224   }, timeout);
    225 };
    226
    227 /**
    228  * Make this display element go fullscreen.
    229  *
    230  * @param {boolean} full Tell the player to go into fullscreen or not.
    231  */
    232 minplayer.display.prototype.fullscreen = function(full) {
    233   var isFull = this.isFullScreen();
    234   var element = this.fullScreenElement();
    235   if (isFull && !full) {
    236     element.removeClass('fullscreen');
    237     if (screenfull) {
    238       screenfull.exit();
    239     }
    240     this.trigger('fullscreen', false);
    241   }
    242   else if (!isFull && full) {
    243     element.addClass('fullscreen');
    244     if (screenfull) {
    245       screenfull.request(element[0]);
    246       screenfull.onchange = (function(display) {
    247         return function(e) {
    248           if (!screenfull.isFullscreen) {
    249             display.fullscreen(false);
    250           }
    251         };
    252       })(this);
    253     }
    254     this.trigger('fullscreen', true);
    255   }
    256 };
    257
    258 /**
    259  * Toggle fullscreen.
    260  */
    261 minplayer.display.prototype.toggleFullScreen = function() {
    262   this.fullscreen(!this.isFullScreen());
    263 };
    264
    265 /**
    266  * Checks to see if we are in fullscreen mode.
    267  *
    268  * @return {boolean} TRUE - fullscreen, FALSE - otherwise.
    269  */
    270 minplayer.display.prototype.isFullScreen = function() {
    271   return this.fullScreenElement().hasClass('fullscreen');
    272 };
    273
    274 /**
    275  * Returns a scaled rectangle provided a ratio and the container rect.
    276  *
    277  * @param {number} ratio The width/height ratio of what is being scaled.
    278  * @param {object} rect The bounding rectangle for scaling.
    279  * @return {object} The Rectangle object of the scaled rectangle.
    280  */
    281 minplayer.display.prototype.getScaledRect = function(ratio, rect) {
    282   var scaledRect = {};
    283   scaledRect.x = rect.x ? rect.x : 0;
    284   scaledRect.y = rect.y ? rect.y : 0;
    285   scaledRect.width = rect.width ? rect.width : 0;
    286   scaledRect.height = rect.height ? rect.height : 0;
    287   if (ratio) {
    288     if ((rect.width / rect.height) > ratio) {
    289       scaledRect.height = rect.height;
    290       scaledRect.width = Math.floor(rect.height * ratio);
    291     }
    292     else {
    293       scaledRect.height = Math.floor(rect.width / ratio);
    294       scaledRect.width = rect.width;
    295     }
    296     scaledRect.x = Math.floor((rect.width - scaledRect.width) / 2);
    297     scaledRect.y = Math.floor((rect.height - scaledRect.height) / 2);
    298   }
    299   return scaledRect;
    300 };
    301
    302 /**
    303  * Returns all the jQuery elements that this component uses.
    304  *
    305  * @return {object} An object which defines all the jQuery elements that
    306  * this component uses.
    307  */
    308 minplayer.display.prototype.getElements = function() {
    309   return {};
    310 };
    311
    312 /**
    313  * From https://github.com/sindresorhus/screenfull.js
    314  */
    315 /*global Element:true*/
    316 (function(window, document) {
    317   'use strict';
    318   var methods = (function() {
    319     var methodMap = [
    320       [
    321         'requestFullscreen',
    322         'exitFullscreen',
    323         'fullscreenchange',
    324         'fullscreen',
    325         'fullscreenElement'
    326       ],
    327       [
    328         'webkitRequestFullScreen',
    329         'webkitCancelFullScreen',
    330         'webkitfullscreenchange',
    331         'webkitIsFullScreen',
    332         'webkitCurrentFullScreenElement'
    333       ],
    334       [
    335         'mozRequestFullScreen',
    336         'mozCancelFullScreen',
    337         'mozfullscreenchange',
    338         'mozFullScreen',
    339         'mozFullScreenElement'
    340       ]
    341     ];
    342     for (var i = 0, l = methodMap.length; i < l; i++) {
    343       if (methodMap.hasOwnProperty(i)) {
    344         var val = methodMap[i];
    345         if (val[1] in document) {
    346           return val;
    347         }
    348       }
    349     }
    350   })();
    351
    352   if (!methods) {
    353     return window.screenfull = false;
    354   }
    355
    356   var keyboardAllowed = 'ALLOW_KEYBOARD_INPUT' in Element;
    357
    358   var screenfull = {
    359     init: function() {
    360       document.addEventListener(methods[2], function(e) {
    361         screenfull.isFullscreen = document[methods[3]];
    362         screenfull.element = document[methods[4]];
    363         screenfull.onchange(e);
    364       });
    365       return this;
    366     },
    367     isFullscreen: document[methods[3]],
    368     element: document[methods[4]],
    369     request: function(elem) {
    370       elem = elem || document.documentElement;
    371       elem[methods[0]](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
    372       // Work around Safari 5.1 bug: reports support for keyboard in fullscreen
    373       // even though it doesn't.
    374       if (!document.isFullscreen) {
    375         elem[methods[0]]();
    376       }
    377     },
    378     exit: function() {
    379       document[methods[1]]();
    380     },
    381     toggle: function(elem) {
    382       if (this.isFullscreen) {
    383         this.exit();
    384       } else {
    385         this.request(elem);
    386       }
    387     },
    388     onchange: function() {}
    389   };
    390
    391   window.screenfull = screenfull.init();
    392 })(window, document);
    393