Move loading of YouTube API to video module.

The availability of the YouTube API will be stored in student's settings.
The YouTube API is loaded asynchronously now, so no need to pass a
parameter to the front-end telling it if YouTube API should not be loaded
because of it's unavailability.

Removing loading of YouTube API from Studio RequireJS config. Now loading
of YouTube API is handled by Video module.

BLD-531.
This commit is contained in:
Valera Rozuvan
2014-03-19 15:32:39 +02:00
parent 0752b008bb
commit 2e8fe6a41c
7 changed files with 88 additions and 19 deletions

View File

@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
Blades: Fix problem with loading YouTube API is it is not available. BLD-531.
Blades: Fix download subs for non youtube videos and non-en language. BLD-897.
Blades: Fix issues related to videos that have separate YouTube IDs for the

View File

@@ -4,14 +4,13 @@
## These files assume that several libraries are available and bound to
## variables in the global context, so we load those libraries with requirejs
## and attach them to the global context manually.
define(["jquery", "underscore", "youtube", "mathjax", "codemirror", "tinymce",
define(["jquery", "underscore", "mathjax", "codemirror", "tinymce",
"jquery.tinymce", "jquery.qtip", "jquery.scrollTo", "jquery.flot",
"jquery.cookie",
"utility"],
function($, _, YT, MathJax, CodeMirror, tinymce) {
function($, _, MathJax, CodeMirror, tinymce) {
window.$ = $;
window._ = _;
window.YT = YT;
window.MathJax = MathJax;
window.CodeMirror = CodeMirror;
window.RequireJS = {

View File

@@ -1,6 +1,5 @@
(function ($, undefined) {
// Stub YouTube API.
window.YT = {
var stubbedYT = {
Player: function () {
var Player = jasmine.createSpyObj(
'YT.Player',
@@ -32,6 +31,9 @@
}
};
// Stub YouTube API.
window.YT = stubbedYT;
window.STATUS = window.YT.PlayerState;
window.onTouchBasedDevice = function () {
@@ -158,6 +160,14 @@
) {
// Do nothing.
} else if (settings.url == '/save_user_state') {
return {success: true};
} else if (settings.url === 'http://www.youtube.com/iframe_api') {
// Stub YouTube API.
window.YT = stubbedYT;
// Call the callback that must be called when YouTube API is loaded. By specification.
window.onYouTubeIframeAPIReady();
return {success: true};
} else {
throw 'External request attempted for ' +

View File

@@ -157,6 +157,26 @@
});
});
describe('YouTube API is not loaded', function () {
beforeEach(function () {
window.YT = undefined;
state = jasmine.initializePlayerYouTube('video.html');
});
it('callback, to be called after YouTube API loads, exists and is called', function () {
waitsFor(function () {
return state.youtubeApiAvailable === true;
}, 'YouTube API is loaded', 3000);
runs(function () {
// If YouTube API is not loaded, then the code will should create
// a global callback that will be called by API once it is loaded.
expect(window.onYouTubeIframeAPIReady).not.toBeUndefined();
});
});
});
describe('YouTube video in FireFox will cue first', function () {
var oldUserAgent;

View File

@@ -112,15 +112,31 @@ function (VideoPlayer, VideoStorage) {
// Require JS. At the time when we reach this code, the stand alone
// HTML5 player is already loaded, so no further testing in that case
// is required.
var video;
var video, onYTApiReady;
if (state.videoType === 'youtube') {
state.youtubeApiAvailable = false;
onYTApiReady = function () {
console.log('[Video info]: YouTube API is available and is loaded.');
if(state.videoType === 'youtube') {
YT.ready(function() {
video = VideoPlayer(state);
state.modules.push(video);
state.__dfd__.resolve();
});
state.youtubeApiAvailable = true;
};
if (window.YT) {
window.YT.ready(onYTApiReady);
} else {
window.onYouTubeIframeAPIReady = function () {
onYTApiReady();
};
_loadYoutubeApi(state);
}
} else {
video = VideoPlayer(state);
@@ -129,6 +145,28 @@ function (VideoPlayer, VideoStorage) {
}
}
function _loadYoutubeApi(state) {
console.log('[Video info]: YouTube API is not loaded. Will try to load...');
window.setTimeout(function () {
// If YouTube API will load OK, it will run `onYouTubeIframeAPIReady`
// callback, which will set `state.youtubeApiAvailable` to `true`.
// If something goes wrong at this stage, `state.youtubeApiAvailable` is
// `false`.
_reportToServer(state, state.youtubeApiAvailable);
}, state.config.ytTestTimeout);
$.getScript(document.location.protocol + '//www.youtube.com/iframe_api');
}
function _reportToServer(state, youtubeIsAvailable) {
if (!youtubeIsAvailable) {
console.log('[Video info]: YouTube API is not available.');
}
state.saveState(true, { youtube_is_available: youtubeIsAvailable });
}
// function _configureCaptions(state)
// Configure displaying of captions.
//

View File

@@ -173,6 +173,11 @@ class VideoFields(object):
scope=Scope.preferences,
default=1.0
)
youtube_is_available = Boolean(
help="The availaibility of YouTube API for the user",
scope=Scope.user_info,
default=True
)
class VideoModule(VideoFields, XModule):
@@ -221,12 +226,13 @@ class VideoModule(VideoFields, XModule):
def handle_ajax(self, dispatch, data):
accepted_keys = [
'speed', 'saved_video_position', 'transcript_language',
'transcript_download_format',
'transcript_download_format', 'youtube_is_available'
]
conversions = {
'speed': json.loads,
'saved_video_position': lambda v: RelativeTime.isotime_to_timedelta(v),
'youtube_is_available': json.loads,
}
if dispatch == 'save_user_state':
@@ -332,7 +338,7 @@ class VideoModule(VideoFields, XModule):
- KeyError if transcript file has incorrect format.
If language is 'en', self.sub should be correct subtitles name.
If language is 'en', but if self.sub is not defined, this means that we
If language is 'en', but if self.sub is not defined, this means that we
should search for video name in order to get proper transcript (old style courses).
If language is not 'en', give back transcript in proper language and format.
"""

View File

@@ -8,11 +8,11 @@
<%block name="bodyclass">courseware ${course.css_class or ''}</%block>
<%block name="title"><title>
% if section_title:
% if section_title:
${page_title_breadcrumbs(section_title, course_name())}
% else:
${page_title_breadcrumbs(course_name())}
%endif
%endif
</title></%block>
<%block name="headextra">
@@ -48,12 +48,6 @@ ${page_title_breadcrumbs(course_name())}
<%include file="xqa_interface.html"/>
% endif
<!-- TODO: http://docs.jquery.com/Plugins/Validation -->
<script type="text/javascript">
document.write('\x3Cscript type="text/javascript" src="' +
document.location.protocol + '//www.youtube.com/iframe_api">\x3C/script>');
</script>
<script type="text/javascript">
var $$course_id = "${course.id}";