Skip to content

Commit

Permalink
Fixed an issue with Youtube on IE/FF
Browse files Browse the repository at this point in the history
  • Loading branch information
moay committed Sep 14, 2015
1 parent 7cc7dd4 commit da824d7
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 29 deletions.
20 changes: 10 additions & 10 deletions dist/afterglow.min.js

Large diffs are not rendered by default.

Binary file modified dist/afterglow.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "afterglow",
"description": "An easy to integrate HTML5 video player with lightbox support.",
"version": "0.1.1",
"version": "0.1.2",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions src/afterglow.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ afterglow = {

// Fix youtube poster
if(afterglow.isYoutubePlayer(videoel) && !options.poster && this.tech.poster != ""){
this.addClass('vjs-youtube-ready');
this.poster(this.tech.poster);
}

Expand Down
46 changes: 35 additions & 11 deletions src/lib/afterglow-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,42 @@ function loadYoutubeThumbnailUrl(id){
/**
* Sets a variable 'ie' holding the IE version (if IE)
*/
var ie = (function(){
var ie = (function () {
"use strict";

var undef,
v = 6,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
var ret, isTheBrowser,
actualVersion,
jscriptMap, jscriptVersion;

while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
isTheBrowser = false;
jscriptMap = {
"5.5": "5.5",
"5.6": "6",
"5.7": "7",
"5.8": "8",
"9": "9",
"10": "10"
};
jscriptVersion = new Function("/*@cc_on return @_jscript_version; @*/")();

return v > 7 ? v : undef;
if (jscriptVersion !== undefined) {
isTheBrowser = true;
actualVersion = jscriptMap[jscriptVersion];
}

ret = {
isTheBrowser: isTheBrowser,
actualVersion: actualVersion
};

if(!isTheBrowser){
if(window.navigator.userAgent.indexOf("Trident/7.0") > 0 && !/x64|x32/ig.test(window.navigator.userAgent)){
ret = {
isTheBrowser: true,
actualVersion: "11"
};
}
}

}());
return ret;
}()).actualVersion;
321 changes: 321 additions & 0 deletions src/videojs/components/ResolutionSwitchingButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
'use strict';

const VjsButtonResBBase = videojs.getComponent('Button');

/**
* Button to switch resolutions based on the data-quality attribute.
*
* @extends Button
* @class LightboxCloseButton
*/
class ResolutionSwitchingButton extends VjsButtonResBBase {

constructor(player, options) {
super(player, options);
this.init();
}

buildCSSClass(){
return 'vjs-ag-res-button vjs-control vjs-button';
}

/**
* Initiates the button and its functionality
* @return {void}
*/
init(){
this.prepareSources();

this.setCurrentResFromPlayer();
this.setResolutionsNeededFromPlayer();

this.updateButton();
this.on('click',this.switchResolution);
this.on('tap',this.switchResolution);
}

/**
* Prepares the sources that are needed for the button functionality
* @return {void}
*/
prepareSources(){
this.sources = this.player_.options_['sources'];
this.sourcesByType = videojs.reduce(this.sources, function(init, val, i){
(init[val.type] = init[val.type] || []).push(val);
return init;
}, {}, this.player_);
this.typeAndTech = this.selectTypeAndTech(this.sources);
}

/**
* Sets the currentRes based on the currently played source
*/
setCurrentResFromPlayer(){
var currentSrc = this.player_.src();
var allSources = this.sources;
for (var i = allSources.length - 1; i >= 0; i--) {
if(allSources[i]['src'] == currentSrc){
if(allSources[i]['data-quality'] !== 'hd'){
this.currentRes = 'sd';
}
else{
this.currentRes = 'hd';
}
}
};
}

/**
* Checks if the plugin is needed for that player
*/
setResolutionsNeededFromPlayer(){
// Fallback
this.resolutionsNeeded = false;

// Real determination
if(typeof this.typeAndTech == 'object'){
var type = this.typeAndTech.type;
if(this.sourcesByType[type] !== undefined
&& this.sourcesByType[type].length > 1){
for (var i = this.sourcesByType[type].length - 1; i >= 0; i--) {
if(this.sourcesByType[type][i]['data-quality'] !== undefined
|| this.sourcesByType[type][i]['data-quality'] != this.currentRes){
this.resolutionsNeeded = true;
return;
}
};
}
}
}

/**
* Removes all sources without actually disposing the player
* @return {void}
*/
removeSources(){
var videoEl = this.player_.el_.getElementsByTagName("video")[0];

if (this.player_.techName !== "Html5" || !videoEl) return;

var srcs = videoEl.getElementsByTagName("source");
for(var i=0;i<srcs.length;i++){
videoEl.removeChild(srcs[i]);
}
}

/**
* Gets the source that should be launched on the next resolution change
* @return {object} The source object which should be played
*/
getSourceForResolutionChange(){
var type = this.typeAndTech.type;
var availableSources = this.sourcesByType[type];
for (var i = availableSources.length - 1; i >= 0; i--) {
if(this.currentRes == 'hd'){
if(availableSources[i]['data-quality'] == undefined
|| availableSources[i]['data-quality'] !== 'hd')
return availableSources[i];
}
else{
if(availableSources[i]['data-quality'] == 'hd')
return availableSources[i];
}
};
// Fallback if all other options failed...
return availableSources[0];
}

/**
* Changes the currently played source to another solution if possible
* @return {[type]} [description]
*/
switchResolution(){
var sourceToPlay = this.getSourceForResolutionChange();
this.switchSource(sourceToPlay);
}

/**
* Stops the currently playing stream without disposing the player
* @return {[type]} [description]
*/
stopStream(){
switch(this.player_.techName){
case "Flash":
this.player_.tech.el_.vjs_stop();
break;
}
}

/**
* Selectes sources by type
*/
selectSource(sources){
this.removeSources();

var sourcesByType = this.sourcesByType;
var typeAndTech = this.selectTypeAndTech(sources);

if (!typeAndTech) return false;

// even though we choose the best resolution for the user here, we
// should remember the resolutions so that we can potentially
// change resolution later
this.options_['sourceResolutions'] = sourcesByType[typeAndTech.type];

return this.selectResolution(this.options_['sourceResolutions']);
}

/**
* Returns the media type and tech to use
* @return {object}
*/
selectTypeAndTech(sources) {
var techName;
var tech;

for (var i=0,j=this.player_.options_['techOrder'];i<j.length;i++) {
techName = this.player_.techName;
tech = window['videojs'].getComponent(techName);

// Check if the browser supports this technology
if (tech.isSupported()) {
// Loop through each source object
for (var a=0,b=sources;a<b.length;a++) {
var source = b[a];
// Check if source can be played with this technology
if (tech['canPlaySource'](source)) {
return { type: source.type, tech: techName };
}
}
}
}
}

/**
* Selects a source for a given resolution
*/
selectResolution(typeSources) {
var defaultRes = 0;
var supportsLocalStorage = !!window.localStorage;

// if the user has previously selected a preference, check if
// that preference is available. if not, use the source marked
// default
var preferredRes = defaultRes;

// trying to follow the videojs code conventions of if statements
if (supportsLocalStorage){
var storedRes = parseInt(window.localStorage.getItem('videojs_preferred_res'), 10);

if (!isNaN(storedRes))
preferredRes = storedRes;
}

var maxRes = (typeSources.length - 1);
var actualRes = preferredRes > maxRes ? maxRes : preferredRes;

return typeSources[actualRes];
}

/** takes a source and switches the player's stream to it on the fly
* @param {Object} singular source:
* {
* "data-default": "true",
* "data-res": "SD",
* "type": "video/mp4",
* "src": "http://some_video_url_sd"
* }
*/
switchSource(new_source){
// has the exact same source been chosen?
if (this.player_.cache_.src === new_source.src){
this.player_.trigger('resolutionchange');
return this.player_; // basically a no-op
}

// remember our position and playback state
var curTime = this.player_.currentTime();
var remainPaused = this.player_.paused();

// pause playback
this.player_.pause();

// attempts to stop the download of the existing video
this.stopStream();

// HTML5 tends to not recover from reloading the tech but it can
// generally handle changing src. Flash generally cannot handle
// changing src but can reload its tech.
if (this.player_.techName === "Html5"){
this.player_.src(new_source.src);
} else {
this.player_.loadTech(this.player_.techName, {src: new_source.src});
}

var _this = this;

// when the technology is re-started, kick off the new stream
this.player_.ready(function() {
this.player_.one('loadeddata', videojs.bind(this.player_, function() {
this.player_.currentTime(curTime);
}));

this.player_.trigger('resolutionchange');

if (!remainPaused) {
this.player_.load();
this.player_.play();
}

// remember this selection
localStorage.setItem('videojs_preferred_res', parseInt(new_source.index, 10));

_this.setCurrentResFromPlayer();
_this.updateButton();
});
}

/**
* Updates the button display the currently active quality.
*/
updateButton(){
var buttonEl = this.el_;
if(!this.resolutionsNeeded){
buttonEl.addClass("vjs-hidden");
}
else{
buttonEl.removeClass("vjs-hidden");
}

if(this.currentRes == 'hd'){
buttonEl.addClass("vjs-ag-res-hd");
}
else{
buttonEl.removeClass("vjs-ag-res-hd");
}

// Get rid of the focus when having clicked the button
this.el_.blur();
}
}

/**
* 'reduce' utility method
* @param {Array} array to iterate over
* @param {Function} iterator function for collector
* @param {Array|Object|Number|String} initial collector
* @return collector
*/
videojs.reduce = function(arr, fn, init, n) {
if (!arr || arr.length === 0) { return; }
for (var i=0,j=arr.length; i<j; i++) {
init = fn.call(arr, init, arr[i], i);
}
return init;
};

(function(){

videojs.registerComponent('ResolutionSwitchingButton', ResolutionSwitchingButton);

})();
Loading

0 comments on commit da824d7

Please sign in to comment.