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