Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
441eb369
Commit
441eb369
authored
Sep 06, 2013
by
Valera Rozuvan
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #869 from edx/valera/video_js_console_log_useful_debug_info
Adding debugging messages for Video player.
parents
bd4b4c16
73a9c43e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
314 additions
and
155 deletions
+314
-155
common/lib/xmodule/xmodule/js/src/video/01_initialize.js
+150
-64
common/lib/xmodule/xmodule/js/src/video/03_video_player.js
+139
-71
common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js
+25
-20
No files found.
common/lib/xmodule/xmodule/js/src/video/01_initialize.js
View file @
441eb369
/**
/**
* @file Initialize module works with the JSON config, and sets up various settings, parameters,
* @file Initialize module works with the JSON config, and sets up various
* variables. After all setup actions are performed, it invokes the video player to play the
* settings, parameters, variables. After all setup actions are performed, it
* specified video. This module must be invoked first. It provides several functions which do not
* invokes the video player to play the specified video. This module must be
* fit in with other modules.
* invoked first. It provides several functions which do not fit in with other
* modules.
*
*
* @external VideoPlayer
* @external VideoPlayer
*
*
...
@@ -16,8 +17,17 @@ define(
...
@@ -16,8 +17,17 @@ define(
[
'video/03_video_player.js'
],
[
'video/03_video_player.js'
],
function
(
VideoPlayer
)
{
function
(
VideoPlayer
)
{
if
(
typeof
(
window
.
gettext
)
==
"undefined"
)
{
// window.console.log() is expected to be available. We do not support
window
.
gettext
=
function
(
s
){
return
s
;};
// browsers which lack this functionality.
// The function gettext() is defined by a vendor library. If, however, it
// is undefined, it is a simple wrapper. It is used to return a different
// version of the string passed (translated string, etc.). In the basic
// case, the original string is returned.
if
(
typeof
(
window
.
gettext
)
==
'undefined'
)
{
window
.
gettext
=
function
(
s
)
{
return
s
;
};
}
}
/**
/**
...
@@ -50,43 +60,54 @@ function (VideoPlayer) {
...
@@ -50,43 +60,54 @@ function (VideoPlayer) {
* methods, modules) of the Video player.
* methods, modules) of the Video player.
*/
*/
function
_makeFunctionsPublic
(
state
)
{
function
_makeFunctionsPublic
(
state
)
{
state
.
setSpeed
=
_
.
bind
(
setSpeed
,
state
);
state
.
setSpeed
=
_
.
bind
(
setSpeed
,
state
);
state
.
youtubeId
=
_
.
bind
(
youtubeId
,
state
);
state
.
youtubeId
=
_
.
bind
(
youtubeId
,
state
);
state
.
getDuration
=
_
.
bind
(
getDuration
,
state
);
state
.
getDuration
=
_
.
bind
(
getDuration
,
state
);
state
.
trigger
=
_
.
bind
(
trigger
,
state
);
state
.
trigger
=
_
.
bind
(
trigger
,
state
);
state
.
stopBuffering
=
_
.
bind
(
stopBuffering
,
state
);
state
.
stopBuffering
=
_
.
bind
(
stopBuffering
,
state
);
// Old private functions. Now also public so that can be
// Old private functions. Now also public so that can be
// tested by Jasmine.
// tested by Jasmine.
state
.
initialize
=
_
.
bind
(
initialize
,
state
);
state
.
initialize
=
_
.
bind
(
initialize
,
state
);
state
.
parseSpeed
=
_
.
bind
(
parseSpeed
,
state
);
state
.
parseSpeed
=
_
.
bind
(
parseSpeed
,
state
);
state
.
fetchMetadata
=
_
.
bind
(
fetchMetadata
,
state
);
state
.
fetchMetadata
=
_
.
bind
(
fetchMetadata
,
state
);
state
.
parseYoutubeStreams
=
_
.
bind
(
parseYoutubeStreams
,
state
);
state
.
parseYoutubeStreams
=
_
.
bind
(
parseYoutubeStreams
,
state
);
state
.
parseVideoSources
=
_
.
bind
(
parseVideoSources
,
state
);
state
.
parseVideoSources
=
_
.
bind
(
parseVideoSources
,
state
);
state
.
getVideoMetadata
=
_
.
bind
(
getVideoMetadata
,
state
);
state
.
getVideoMetadata
=
_
.
bind
(
getVideoMetadata
,
state
);
}
}
// function _renderElements(state)
// function _renderElements(state)
//
//
// Create any necessary DOM elements, attach them, and set their initial configuration. Also
// Create any necessary DOM elements, attach them, and set their
// make the created DOM elements available via the 'state' object. Much easier to work this
// initial configuration. Also make the created DOM elements available
// way - you don't have to do repeated jQuery element selects.
// via the 'state' object. Much easier to work this way - you don't
// have to do repeated jQuery element selects.
function
_renderElements
(
state
)
{
function
_renderElements
(
state
)
{
// Launch embedding of actual video content, or set it up so that it will be done as soon as the
// Launch embedding of actual video content, or set it up so that it
// appropriate video player (YouTube or stand alone HTML5) is loaded, and can handle embedding.
// will be done as soon as the appropriate video player (YouTube or
// stand-alone HTML5) is loaded, and can handle embedding.
//
//
// Note that the loading of stand alone HTML5 player API is handled by Require JS. At the time
// Note that the loading of stand alone HTML5 player API is handled by
// when we reach this code, the stand alone HTML5 player is already loaded, so no further testing
// Require JS. At the time when we reach this code, the stand alone
// in that case is required.
// HTML5 player is already loaded, so no further testing in that case
// is required.
var
onPlayerReadyFunc
;
var
onPlayerReadyFunc
;
if
(
if
(
((
state
.
videoType
===
'youtube'
)
&&
(
window
.
YT
)
&&
(
window
.
YT
.
Player
))
||
(
(
state
.
videoType
===
'youtube'
)
&&
(
window
.
YT
)
&&
(
window
.
YT
.
Player
)
)
||
(
state
.
videoType
===
'html5'
)
(
state
.
videoType
===
'html5'
)
)
{
)
{
VideoPlayer
(
state
);
VideoPlayer
(
state
);
}
else
{
}
else
{
onPlayerReadyFunc
=
(
state
.
videoType
===
'youtube'
)
?
'onYouTubePlayerAPIReady'
:
'onHTML5PlayerAPIReady'
;
if
(
state
.
videoType
===
'youtube'
)
{
onPlayerReadyFunc
=
'onYouTubePlayerAPIReady'
;
}
else
{
onPlayerReadyFunc
=
'onHTML5PlayerAPIReady'
;
}
window
[
onPlayerReadyFunc
]
=
_
.
bind
(
VideoPlayer
,
window
,
state
);
window
[
onPlayerReadyFunc
]
=
_
.
bind
(
VideoPlayer
,
window
,
state
);
}
}
}
}
...
@@ -102,7 +123,8 @@ function (VideoPlayer) {
...
@@ -102,7 +123,8 @@ function (VideoPlayer) {
// Option
// Option
// this.hide_captions = true | false
// this.hide_captions = true | false
//
//
// represents the user's choice of having the subtitles shown or hidden. This choice is stored in cookies.
// represents the user's choice of having the subtitles shown or
// hidden. This choice is stored in cookies.
function
_configureCaptions
(
state
)
{
function
_configureCaptions
(
state
)
{
if
(
state
.
config
.
show_captions
)
{
if
(
state
.
config
.
show_captions
)
{
state
.
hide_captions
=
(
$
.
cookie
(
'hide_captions'
)
===
'true'
);
state
.
hide_captions
=
(
$
.
cookie
(
'hide_captions'
)
===
'true'
);
...
@@ -119,14 +141,19 @@ function (VideoPlayer) {
...
@@ -119,14 +141,19 @@ function (VideoPlayer) {
}
}
// function _setPlayerMode(state)
// function _setPlayerMode(state)
// By default we will be forcing HTML5 player mode. Only in the case when, after initializtion, we will
// By default we will be forcing HTML5 player mode. Only in the case
// get one available playback rate, we will change to Flash player mode. There is a need to store this
// when, after initializtion, we will get one available playback rate,
// setting in cookies because otherwise we will have to change from HTML5 to Flash on every page load
// we will change to Flash player mode. There is a need to store this
// in a browser that doesn't fully support HTML5. When we have this setting in cookies, we can select
// setting in cookies because otherwise we will have to change from
// HTML5 to Flash on every page load in a browser that doesn't fully
// support HTML5. When we have this setting in cookies, we can select
// the proper mode from the start (not having to change mode later on).
// the proper mode from the start (not having to change mode later on).
function
_setPlayerMode
(
state
)
{
function
_setPlayerMode
(
state
)
{
(
function
(
currentPlayerMode
)
{
(
function
(
currentPlayerMode
)
{
if
((
currentPlayerMode
===
'html5'
)
||
(
currentPlayerMode
===
'flash'
))
{
if
(
(
currentPlayerMode
===
'html5'
)
||
(
currentPlayerMode
===
'flash'
)
)
{
state
.
currentPlayerMode
=
currentPlayerMode
;
state
.
currentPlayerMode
=
currentPlayerMode
;
}
else
{
}
else
{
$
.
cookie
(
'current_player_mode'
,
'html5'
,
{
$
.
cookie
(
'current_player_mode'
,
'html5'
,
{
...
@@ -135,20 +162,32 @@ function (VideoPlayer) {
...
@@ -135,20 +162,32 @@ function (VideoPlayer) {
});
});
state
.
currentPlayerMode
=
'html5'
;
state
.
currentPlayerMode
=
'html5'
;
}
}
console
.
log
(
'[Video info]: YouTube player mode is "'
+
state
.
currentPlayerMode
+
'".'
);
}(
$
.
cookie
(
'current_player_mode'
)));
}(
$
.
cookie
(
'current_player_mode'
)));
}
}
// function _parseYouTubeIDs(state)
// function _parseYouTubeIDs(state)
// The function parse YouTube stream ID's.
// The function parse YouTube stream ID's.
// @return
// @return
// false: We don't have YouTube video IDs to work with; most likely we have HTML5 video sources.
// false: We don't have YouTube video IDs to work with; most likely
// true: Parsing of YouTube video IDs went OK, and we can proceed onwards to play YouTube videos.
// we have HTML5 video sources.
// true: Parsing of YouTube video IDs went OK, and we can proceed
// onwards to play YouTube videos.
function
_parseYouTubeIDs
(
state
)
{
function
_parseYouTubeIDs
(
state
)
{
if
(
state
.
parseYoutubeStreams
(
state
.
config
.
youtubeStreams
))
{
if
(
state
.
parseYoutubeStreams
(
state
.
config
.
youtubeStreams
))
{
state
.
videoType
=
'youtube'
;
state
.
videoType
=
'youtube'
;
return
true
;
return
true
;
}
}
console
.
log
(
'[Video info]: Youtube Video IDs are incorrect or absent.'
);
return
false
;
return
false
;
}
}
...
@@ -184,6 +223,10 @@ function (VideoPlayer) {
...
@@ -184,6 +223,10 @@ function (VideoPlayer) {
state
.
el
.
find
(
'.video-player div'
).
addClass
(
'hidden'
);
state
.
el
.
find
(
'.video-player div'
).
addClass
(
'hidden'
);
state
.
el
.
find
(
'.video-player h3'
).
removeClass
(
'hidden'
);
state
.
el
.
find
(
'.video-player h3'
).
removeClass
(
'hidden'
);
console
.
log
(
'[Video info]: Non-youtube video sources aren
\'
t available.'
);
return
false
;
return
false
;
}
}
...
@@ -212,8 +255,9 @@ function (VideoPlayer) {
...
@@ -212,8 +255,9 @@ function (VideoPlayer) {
// ***************************************************************
// ***************************************************************
// Public functions start here.
// Public functions start here.
// These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
// These are available via the 'state' object. Their context ('this'
// The magic private function that makes them available and sets up their context is makeFunctionsPublic().
// keyword) is the 'state' object. The magic private function that makes
// them available and sets up their context is makeFunctionsPublic().
// ***************************************************************
// ***************************************************************
// function initialize(element)
// function initialize(element)
...
@@ -221,15 +265,21 @@ function (VideoPlayer) {
...
@@ -221,15 +265,21 @@ function (VideoPlayer) {
function
initialize
(
element
)
{
function
initialize
(
element
)
{
var
_this
=
this
,
tempYtTestTimeout
;
var
_this
=
this
,
tempYtTestTimeout
;
// This is used in places where we instead would have to check if an element has a CSS class 'fullscreen'.
// This is used in places where we instead would have to check if an
// element has a CSS class 'fullscreen'.
this
.
isFullScreen
=
false
;
this
.
isFullScreen
=
false
;
// The parent element of the video, and the ID.
// The parent element of the video, and the ID.
this
.
el
=
$
(
element
).
find
(
'.video'
);
this
.
el
=
$
(
element
).
find
(
'.video'
);
this
.
id
=
this
.
el
.
attr
(
'id'
).
replace
(
/video_/
,
''
);
this
.
id
=
this
.
el
.
attr
(
'id'
).
replace
(
/video_/
,
''
);
// We store all settings passed to us by the server in one place. These are "read only", so don't
console
.
log
(
// modify them. All variable content lives in 'state' object.
'[Video info]: Initializing video with id "'
+
this
.
id
+
'".'
);
// We store all settings passed to us by the server in one place. These
// are "read only", so don't modify them. All variable content lives in
// 'state' object.
this
.
config
=
{
this
.
config
=
{
element
:
element
,
element
:
element
,
...
@@ -238,7 +288,10 @@ function (VideoPlayer) {
...
@@ -238,7 +288,10 @@ function (VideoPlayer) {
caption_data_dir
:
this
.
el
.
data
(
'caption-data-dir'
),
caption_data_dir
:
this
.
el
.
data
(
'caption-data-dir'
),
caption_asset_path
:
this
.
el
.
data
(
'caption-asset-path'
),
caption_asset_path
:
this
.
el
.
data
(
'caption-asset-path'
),
show_captions
:
(
this
.
el
.
data
(
'show-captions'
).
toString
().
toLowerCase
()
===
'true'
),
show_captions
:
(
this
.
el
.
data
(
'show-captions'
)
.
toString
().
toLowerCase
()
===
'true'
),
youtubeStreams
:
this
.
el
.
data
(
'streams'
),
youtubeStreams
:
this
.
el
.
data
(
'streams'
),
sub
:
this
.
el
.
data
(
'sub'
),
sub
:
this
.
el
.
data
(
'sub'
),
...
@@ -262,12 +315,16 @@ function (VideoPlayer) {
...
@@ -262,12 +315,16 @@ function (VideoPlayer) {
this
.
config
.
ytTestTimeout
=
tempYtTestTimeout
;
this
.
config
.
ytTestTimeout
=
tempYtTestTimeout
;
if
(
!
(
_parseYouTubeIDs
(
this
)))
{
if
(
!
(
_parseYouTubeIDs
(
this
)))
{
// If we do not have YouTube ID's, try parsing HTML5 video sources.
// If we do not have YouTube ID's, try parsing HTML5 video sources.
if
(
!
_prepareHTML5Video
(
this
,
true
))
{
if
(
!
_prepareHTML5Video
(
this
,
true
))
{
// Non-YouTube sources were not found either.
// Non-YouTube sources were not found either.
return
;
return
;
}
}
console
.
log
(
'[Video info]: Start player in HTML5 mode.'
);
_setConfigurations
(
this
);
_setConfigurations
(
this
);
_renderElements
(
this
);
_renderElements
(
this
);
}
else
{
}
else
{
...
@@ -276,29 +333,52 @@ function (VideoPlayer) {
...
@@ -276,29 +333,52 @@ function (VideoPlayer) {
}
}
this
.
youtubeXhr
this
.
youtubeXhr
.
always
(
function
(
json
,
status
)
{
.
always
(
function
(
json
,
status
)
{
var
err
=
$
.
isPlainObject
(
json
.
error
)
||
var
err
=
$
.
isPlainObject
(
json
.
error
)
||
(
status
!==
'success'
&&
status
!==
'notmodified'
);
(
status
!==
'success'
&&
status
!==
'notmodified'
);
if
(
err
)
{
if
(
err
)
{
console
.
log
(
'[Video info]: YouTube returned an error for '
+
'video with id "'
+
_this
.
id
+
'".'
);
// When the youtube link doesn't work for any reason
// When the youtube link doesn't work for any reason
// (for example, the great firewall in china) any
// (for example, the great firewall in china) any
// alternate sources should automatically play.
// alternate sources should automatically play.
if
(
!
_prepareHTML5Video
(
_this
))
{
if
(
!
_prepareHTML5Video
(
_this
))
{
console
.
log
(
'[Video info]: Continue loading '
+
'YouTube video.'
);
// Non-YouTube sources were not found either.
// Non-YouTube sources were not found either.
_this
.
el
.
find
(
'.video-player div'
).
removeClass
(
'hidden'
);
_this
.
el
.
find
(
'.video-player div'
)
_this
.
el
.
find
(
'.video-player h3'
).
addClass
(
'hidden'
);
.
removeClass
(
'hidden'
);
_this
.
el
.
find
(
'.video-player h3'
)
.
addClass
(
'hidden'
);
// If in reality the timeout was to short, try to
// If in reality the timeout was to short, try to
// continue loading the YouTube video anyways.
// continue loading the YouTube video anyways.
_this
.
fetchMetadata
();
_this
.
fetchMetadata
();
_this
.
parseSpeed
();
_this
.
parseSpeed
();
}
else
{
}
else
{
console
.
log
(
'[Video info]: Change player mode to HTML5.'
);
// In-browser HTML5 player does not support quality
// In-browser HTML5 player does not support quality
// control.
// control.
_this
.
el
.
find
(
'a.quality_control'
).
hide
();
_this
.
el
.
find
(
'a.quality_control'
).
hide
();
}
}
}
else
{
}
else
{
console
.
log
(
'[Video info]: Start player in YouTube mode.'
);
_this
.
fetchMetadata
();
_this
.
fetchMetadata
();
_this
.
parseSpeed
();
_this
.
parseSpeed
();
}
}
...
@@ -313,23 +393,28 @@ function (VideoPlayer) {
...
@@ -313,23 +393,28 @@ function (VideoPlayer) {
//
//
// Take a string in the form:
// Take a string in the form:
// "iCawTYPtehk:0.75,KgpclqP-LBA:1.0,9-2670d5nvU:1.5"
// "iCawTYPtehk:0.75,KgpclqP-LBA:1.0,9-2670d5nvU:1.5"
// parse it, and make it available via the 'state' object. If we are
not given a string, or
// parse it, and make it available via the 'state' object. If we are
// it's length is zero, then we return false.
//
not given a string, or
it's length is zero, then we return false.
//
//
// @return
// @return
// false: We don't have YouTube video IDs to work with; most likely we have HTML5 video sources.
// false: We don't have YouTube video IDs to work with; most likely
// true: Parsing of YouTube video IDs went OK, and we can proceed onwards to play YouTube videos.
// we have HTML5 video sources.
// true: Parsing of YouTube video IDs went OK, and we can proceed
// onwards to play YouTube videos.
function
parseYoutubeStreams
(
youtubeStreams
)
{
function
parseYoutubeStreams
(
youtubeStreams
)
{
var
_this
;
var
_this
;
if
(
typeof
youtubeStreams
===
'undefined'
||
youtubeStreams
.
length
===
0
)
{
if
(
typeof
youtubeStreams
===
'undefined'
||
youtubeStreams
.
length
===
0
)
{
return
false
;
return
false
;
}
}
_this
=
this
;
_this
=
this
;
this
.
videos
=
{};
this
.
videos
=
{};
$
.
each
(
youtubeStreams
.
split
(
/,/
),
function
(
index
,
video
)
{
$
.
each
(
youtubeStreams
.
split
(
/,/
),
function
(
index
,
video
)
{
var
speed
;
var
speed
;
video
=
video
.
split
(
/:/
);
video
=
video
.
split
(
/:/
);
...
@@ -343,8 +428,8 @@ function (VideoPlayer) {
...
@@ -343,8 +428,8 @@ function (VideoPlayer) {
// function parseVideoSources(, mp4Source, webmSource, oggSource)
// function parseVideoSources(, mp4Source, webmSource, oggSource)
//
//
// Take the HTML5 sources (URLs of videos), and make them available
explictly for each type
// Take the HTML5 sources (URLs of videos), and make them available
// of video format (mp4, webm, ogg).
//
explictly for each type
of video format (mp4, webm, ogg).
function
parseVideoSources
(
sources
)
{
function
parseVideoSources
(
sources
)
{
var
_this
=
this
,
var
_this
=
this
,
v
=
document
.
createElement
(
'video'
),
v
=
document
.
createElement
(
'video'
),
...
@@ -376,16 +461,17 @@ function (VideoPlayer) {
...
@@ -376,16 +461,17 @@ function (VideoPlayer) {
// function fetchMetadata()
// function fetchMetadata()
//
//
// When dealing with YouTube videos, we must fetch meta data that has certain key facts
// When dealing with YouTube videos, we must fetch meta data that has
// not available while the video is loading. For example the length of the video can be
// certain key facts not available while the video is loading. For
// determined from the meta data.
// example the length of the video can be determined from the meta
// data.
function
fetchMetadata
()
{
function
fetchMetadata
()
{
var
_this
=
this
;
var
_this
=
this
;
this
.
metadata
=
{};
this
.
metadata
=
{};
$
.
each
(
this
.
videos
,
function
(
speed
,
url
)
{
$
.
each
(
this
.
videos
,
function
(
speed
,
url
)
{
_this
.
getVideoMetadata
(
url
,
function
(
data
)
{
_this
.
getVideoMetadata
(
url
,
function
(
data
)
{
if
(
data
.
data
)
{
if
(
data
.
data
)
{
_this
.
metadata
[
data
.
data
.
id
]
=
data
.
data
;
_this
.
metadata
[
data
.
data
.
id
]
=
data
.
data
;
}
}
...
@@ -397,7 +483,7 @@ function (VideoPlayer) {
...
@@ -397,7 +483,7 @@ function (VideoPlayer) {
//
//
// Create a separate array of available speeds.
// Create a separate array of available speeds.
function
parseSpeed
()
{
function
parseSpeed
()
{
this
.
speeds
=
(
$
.
map
(
this
.
videos
,
function
(
url
,
speed
)
{
this
.
speeds
=
(
$
.
map
(
this
.
videos
,
function
(
url
,
speed
)
{
return
speed
;
return
speed
;
})).
sort
();
})).
sort
();
...
@@ -439,7 +525,7 @@ function (VideoPlayer) {
...
@@ -439,7 +525,7 @@ function (VideoPlayer) {
function
stopBuffering
()
{
function
stopBuffering
()
{
var
video
;
var
video
;
if
(
this
.
videoType
===
'html5'
){
if
(
this
.
videoType
===
'html5'
)
{
// HTML5 player haven't default way to abort bufferization.
// HTML5 player haven't default way to abort bufferization.
// In this case we simply resetting source and call load().
// In this case we simply resetting source and call load().
video
=
this
.
videoPlayer
.
player
.
video
;
video
=
this
.
videoPlayer
.
player
.
video
;
...
@@ -457,9 +543,9 @@ function (VideoPlayer) {
...
@@ -457,9 +543,9 @@ function (VideoPlayer) {
}
}
/*
/*
* The trigger() function will assume that the @objChain is a complete
chain with a method
* The trigger() function will assume that the @objChain is a complete
*
(function) at the end. It will call this function. So for example, when trigger() is
*
chain with a method (function) at the end. It will call this function.
* called like so:
*
So for example, when trigger() is
called like so:
*
*
* state.trigger('videoPlayer.pause', {'param1': 10});
* state.trigger('videoPlayer.pause', {'param1': 10});
*
*
...
@@ -474,10 +560,10 @@ function (VideoPlayer) {
...
@@ -474,10 +560,10 @@ function (VideoPlayer) {
tmpObj
=
this
;
tmpObj
=
this
;
chain
=
objChain
.
split
(
'.'
);
chain
=
objChain
.
split
(
'.'
);
// At the end of the loop the variable 'tmpObj' will either be the
correct
// At the end of the loop the variable 'tmpObj' will either be the
//
object/function to trigger/invoke. If the 'chain' chain of object is
//
correct object/function to trigger/invoke. If the 'chain' chain of
//
incorrect (one of the link is non-existent), then the loop will immediately
//
object is incorrect (one of the link is non-existent), then the loop
// exit.
//
will immediately
exit.
while
(
chain
.
length
)
{
while
(
chain
.
length
)
{
i
=
chain
.
shift
();
i
=
chain
.
shift
();
...
...
common/lib/xmodule/xmodule/js/src/video/03_video_player.js
View file @
441eb369
...
@@ -21,35 +21,46 @@ function (HTML5Video) {
...
@@ -21,35 +21,46 @@ function (HTML5Video) {
// function _makeFunctionsPublic(state)
// function _makeFunctionsPublic(state)
//
//
// Functions which will be accessible via 'state' object. When called,
these functions will
// Functions which will be accessible via 'state' object. When called,
// get the 'state' object as a context.
//
these functions will
get the 'state' object as a context.
function
_makeFunctionsPublic
(
state
)
{
function
_makeFunctionsPublic
(
state
)
{
state
.
videoPlayer
.
pause
=
_
.
bind
(
pause
,
state
);
state
.
videoPlayer
.
pause
=
_
.
bind
(
pause
,
state
);
state
.
videoPlayer
.
play
=
_
.
bind
(
play
,
state
);
state
.
videoPlayer
.
play
=
_
.
bind
(
play
,
state
);
state
.
videoPlayer
.
update
=
_
.
bind
(
update
,
state
);
state
.
videoPlayer
.
update
=
_
.
bind
(
update
,
state
);
state
.
videoPlayer
.
onSpeedChange
=
_
.
bind
(
onSpeedChange
,
state
);
state
.
videoPlayer
.
onSpeedChange
=
_
.
bind
(
onSpeedChange
,
state
);
state
.
videoPlayer
.
onCaptionSeek
=
_
.
bind
(
onSeek
,
state
);
state
.
videoPlayer
.
onCaptionSeek
=
_
.
bind
(
onSeek
,
state
);
state
.
videoPlayer
.
onSlideSeek
=
_
.
bind
(
onSeek
,
state
);
state
.
videoPlayer
.
onSlideSeek
=
_
.
bind
(
onSeek
,
state
);
state
.
videoPlayer
.
onEnded
=
_
.
bind
(
onEnded
,
state
);
state
.
videoPlayer
.
onEnded
=
_
.
bind
(
onEnded
,
state
);
state
.
videoPlayer
.
onPause
=
_
.
bind
(
onPause
,
state
);
state
.
videoPlayer
.
onPause
=
_
.
bind
(
onPause
,
state
);
state
.
videoPlayer
.
onPlay
=
_
.
bind
(
onPlay
,
state
);
state
.
videoPlayer
.
onPlay
=
_
.
bind
(
onPlay
,
state
);
state
.
videoPlayer
.
onUnstarted
=
_
.
bind
(
onUnstarted
,
state
);
state
.
videoPlayer
.
handlePlaybackQualityChange
=
_
.
bind
(
handlePlaybackQualityChange
,
state
);
state
.
videoPlayer
.
onUnstarted
=
_
.
bind
(
state
.
videoPlayer
.
onPlaybackQualityChange
=
_
.
bind
(
onPlaybackQualityChange
,
state
);
onUnstarted
,
state
state
.
videoPlayer
.
onStateChange
=
_
.
bind
(
onStateChange
,
state
);
);
state
.
videoPlayer
.
onReady
=
_
.
bind
(
onReady
,
state
);
state
.
videoPlayer
.
updatePlayTime
=
_
.
bind
(
updatePlayTime
,
state
);
state
.
videoPlayer
.
handlePlaybackQualityChange
=
_
.
bind
(
state
.
videoPlayer
.
isPlaying
=
_
.
bind
(
isPlaying
,
state
);
handlePlaybackQualityChange
,
state
state
.
videoPlayer
.
log
=
_
.
bind
(
log
,
state
);
);
state
.
videoPlayer
.
duration
=
_
.
bind
(
duration
,
state
);
state
.
videoPlayer
.
onVolumeChange
=
_
.
bind
(
onVolumeChange
,
state
);
state
.
videoPlayer
.
onPlaybackQualityChange
=
_
.
bind
(
onPlaybackQualityChange
,
state
);
state
.
videoPlayer
.
onStateChange
=
_
.
bind
(
onStateChange
,
state
);
state
.
videoPlayer
.
onReady
=
_
.
bind
(
onReady
,
state
);
state
.
videoPlayer
.
updatePlayTime
=
_
.
bind
(
updatePlayTime
,
state
);
state
.
videoPlayer
.
isPlaying
=
_
.
bind
(
isPlaying
,
state
);
state
.
videoPlayer
.
log
=
_
.
bind
(
log
,
state
);
state
.
videoPlayer
.
duration
=
_
.
bind
(
duration
,
state
);
state
.
videoPlayer
.
onVolumeChange
=
_
.
bind
(
onVolumeChange
,
state
);
}
}
// function _initialize(state)
// function _initialize(state)
//
//
// Create any necessary DOM elements, attach them, and set their initial configuration. Also
// Create any necessary DOM elements, attach them, and set their
// make the created DOM elements available via the 'state' object. Much easier to work this
// initial configuration. Also make the created DOM elements available
// way - you don't have to do repeated jQuery element selects.
// via the 'state' object. Much easier to work this way - you don't
// have to do repeated jQuery element selects.
function
_initialize
(
state
)
{
function
_initialize
(
state
)
{
var
youTubeId
;
var
youTubeId
;
...
@@ -92,9 +103,10 @@ function (HTML5Video) {
...
@@ -92,9 +103,10 @@ function (HTML5Video) {
//
//
// TODO: Check the status of
// TODO: Check the status of
// http://code.google.com/p/gdata-issues/issues/detail?id=4654
// http://code.google.com/p/gdata-issues/issues/detail?id=4654
// When the YouTube team fixes the API bug, we can remove this temporary
// When the YouTube team fixes the API bug, we can remove this
// bug fix.
// temporary bug fix.
state
.
browserIsFirefox
=
navigator
.
userAgent
.
toLowerCase
().
indexOf
(
'firefox'
)
>
-
1
;
state
.
browserIsFirefox
=
navigator
.
userAgent
.
toLowerCase
().
indexOf
(
'firefox'
)
>
-
1
;
if
(
state
.
videoType
===
'html5'
)
{
if
(
state
.
videoType
===
'html5'
)
{
state
.
videoPlayer
.
player
=
new
HTML5Video
.
Player
(
state
.
el
,
{
state
.
videoPlayer
.
player
=
new
HTML5Video
.
Player
(
state
.
el
,
{
...
@@ -117,7 +129,8 @@ function (HTML5Video) {
...
@@ -117,7 +129,8 @@ function (HTML5Video) {
events
:
{
events
:
{
onReady
:
state
.
videoPlayer
.
onReady
,
onReady
:
state
.
videoPlayer
.
onReady
,
onStateChange
:
state
.
videoPlayer
.
onStateChange
,
onStateChange
:
state
.
videoPlayer
.
onStateChange
,
onPlaybackQualityChange
:
state
.
videoPlayer
.
onPlaybackQualityChange
onPlaybackQualityChange
:
state
.
videoPlayer
.
onPlaybackQualityChange
}
}
});
});
}
}
...
@@ -125,9 +138,10 @@ function (HTML5Video) {
...
@@ -125,9 +138,10 @@ function (HTML5Video) {
// function _restartUsingFlash(state)
// function _restartUsingFlash(state)
//
//
// When we are about to play a YouTube video in HTML5 mode and discover that we only
// When we are about to play a YouTube video in HTML5 mode and discover
// have one available playback rate, we will switch to Flash mode. In Flash speed
// that we only have one available playback rate, we will switch to
// switching is done by reloading videos recorded at different frame rates.
// Flash mode. In Flash speed switching is done by reloading videos
// recorded at different frame rates.
function
_restartUsingFlash
(
state
)
{
function
_restartUsingFlash
(
state
)
{
// Remove from the page current iFrame with HTML5 video.
// Remove from the page current iFrame with HTML5 video.
state
.
videoPlayer
.
player
.
destroy
();
state
.
videoPlayer
.
player
.
destroy
();
...
@@ -139,25 +153,29 @@ function (HTML5Video) {
...
@@ -139,25 +153,29 @@ function (HTML5Video) {
});
});
state
.
currentPlayerMode
=
'flash'
;
state
.
currentPlayerMode
=
'flash'
;
console
.
log
(
'[Video info]: Changing YouTube player mode to "flash".'
);
// Removed configuration option that requests the HTML5 mode.
// Removed configuration option that requests the HTML5 mode.
delete
state
.
videoPlayer
.
playerVars
.
html5
;
delete
state
.
videoPlayer
.
playerVars
.
html5
;
// Request for the creation of a new Flash player
// Request for the creation of a new Flash player
state
.
videoPlayer
.
player
=
new
YT
.
Player
(
state
.
id
,
{
state
.
videoPlayer
.
player
=
new
YT
.
Player
(
state
.
id
,
{
'playerVars'
:
state
.
videoPlayer
.
playerVars
,
playerVars
:
state
.
videoPlayer
.
playerVars
,
'videoId'
:
state
.
youtubeId
(),
videoId
:
state
.
youtubeId
(),
'events'
:
{
events
:
{
'onReady'
:
state
.
videoPlayer
.
onReady
,
onReady
:
state
.
videoPlayer
.
onReady
,
'onStateChange'
:
state
.
videoPlayer
.
onStateChange
,
onStateChange
:
state
.
videoPlayer
.
onStateChange
,
'onPlaybackQualityChange'
:
state
.
videoPlayer
.
onPlaybackQualityChange
onPlaybackQualityChange
:
state
.
videoPlayer
.
onPlaybackQualityChange
}
}
});
});
}
}
// ***************************************************************
// ***************************************************************
// Public functions start here.
// Public functions start here.
// These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
// These are available via the 'state' object. Their context ('this'
// The magic private function that makes them available and sets up their context is makeFunctionsPublic().
// keyword) is the 'state' object. The magic private function that makes
// them available and sets up their context is makeFunctionsPublic().
// ***************************************************************
// ***************************************************************
function
pause
()
{
function
pause
()
{
...
@@ -174,9 +192,11 @@ function (HTML5Video) {
...
@@ -174,9 +192,11 @@ function (HTML5Video) {
// This function gets the video's current play position in time
// This function gets the video's current play position in time
// (currentTime) and its duration.
// (currentTime) and its duration.
// It is called at a regular interval when the video is playing (see below).
// It is called at a regular interval when the video is playing (see
// below).
function
update
()
{
function
update
()
{
this
.
videoPlayer
.
currentTime
=
this
.
videoPlayer
.
player
.
getCurrentTime
();
this
.
videoPlayer
.
currentTime
=
this
.
videoPlayer
.
player
.
getCurrentTime
();
if
(
isFinite
(
this
.
videoPlayer
.
currentTime
))
{
if
(
isFinite
(
this
.
videoPlayer
.
currentTime
))
{
this
.
videoPlayer
.
updatePlayTime
(
this
.
videoPlayer
.
currentTime
);
this
.
videoPlayer
.
updatePlayTime
(
this
.
videoPlayer
.
currentTime
);
...
@@ -206,19 +226,27 @@ function (HTML5Video) {
...
@@ -206,19 +226,27 @@ function (HTML5Video) {
if
(
if
(
this
.
currentPlayerMode
===
'html5'
&&
this
.
currentPlayerMode
===
'html5'
&&
!
(
this
.
browserIsFirefox
&&
newSpeed
===
'1.0'
&&
this
.
videoType
===
'youtube'
)
!
(
this
.
browserIsFirefox
&&
newSpeed
===
'1.0'
&&
this
.
videoType
===
'youtube'
)
)
{
)
{
this
.
videoPlayer
.
player
.
setPlaybackRate
(
newSpeed
);
this
.
videoPlayer
.
player
.
setPlaybackRate
(
newSpeed
);
}
else
{
}
else
{
// We request the reloading of the video in the case when YouTube
is in
// We request the reloading of the video in the case when YouTube
//
Flash player mode, or when we are in Firefox, and the new speed is 1.0.
//
is in Flash player mode, or when we are in Firefox, and the new
//
The second case is necessary to avoid the bug where in Firefox speed
//
speed is 1.0. The second case is necessary to avoid the bug
//
switching to 1.0 in HTML5 player mode is handled incorrectly by YouTube
//
where in Firefox speed switching to 1.0 in HTML5 player mode is
// API.
//
handled incorrectly by YouTube
API.
if
(
this
.
videoPlayer
.
isPlaying
())
{
if
(
this
.
videoPlayer
.
isPlaying
())
{
this
.
videoPlayer
.
player
.
loadVideoById
(
this
.
youtubeId
(),
this
.
videoPlayer
.
currentTime
);
this
.
videoPlayer
.
player
.
loadVideoById
(
this
.
youtubeId
(),
this
.
videoPlayer
.
currentTime
);
}
else
{
}
else
{
this
.
videoPlayer
.
player
.
cueVideoById
(
this
.
youtubeId
(),
this
.
videoPlayer
.
currentTime
);
this
.
videoPlayer
.
player
.
cueVideoById
(
this
.
youtubeId
(),
this
.
videoPlayer
.
currentTime
);
}
}
this
.
videoPlayer
.
updatePlayTime
(
this
.
videoPlayer
.
currentTime
);
this
.
videoPlayer
.
updatePlayTime
(
this
.
videoPlayer
.
currentTime
);
...
@@ -243,7 +271,9 @@ function (HTML5Video) {
...
@@ -243,7 +271,9 @@ function (HTML5Video) {
if
(
this
.
videoPlayer
.
isPlaying
())
{
if
(
this
.
videoPlayer
.
isPlaying
())
{
clearInterval
(
this
.
videoPlayer
.
updateInterval
);
clearInterval
(
this
.
videoPlayer
.
updateInterval
);
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
}
else
{
}
else
{
this
.
videoPlayer
.
currentTime
=
params
.
time
;
this
.
videoPlayer
.
currentTime
=
params
.
time
;
}
}
...
@@ -286,7 +316,9 @@ function (HTML5Video) {
...
@@ -286,7 +316,9 @@ function (HTML5Video) {
);
);
if
(
!
this
.
videoPlayer
.
updateInterval
)
{
if
(
!
this
.
videoPlayer
.
updateInterval
)
{
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
this
.
videoPlayer
.
updateInterval
=
setInterval
(
this
.
videoPlayer
.
update
,
200
);
}
}
this
.
trigger
(
'videoControl.play'
,
null
);
this
.
trigger
(
'videoControl.play'
,
null
);
...
@@ -325,19 +357,26 @@ function (HTML5Video) {
...
@@ -325,19 +357,26 @@ function (HTML5Video) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=840745
// https://bugzilla.mozilla.org/show_bug.cgi?id=840745
// https://developer.mozilla.org/en-US/docs/DOM/HTMLMediaElement
// https://developer.mozilla.org/en-US/docs/DOM/HTMLMediaElement
availablePlaybackRates
=
_
.
filter
(
availablePlaybackRates
,
function
(
item
){
availablePlaybackRates
=
_
.
filter
(
var
speed
=
Number
(
item
);
availablePlaybackRates
,
return
speed
>
0.25
&&
speed
<=
5
;
function
(
item
)
{
});
var
speed
=
Number
(
item
);
return
speed
>
0.25
&&
speed
<=
5
;
}
);
if
((
this
.
currentPlayerMode
===
'html5'
)
&&
(
this
.
videoType
===
'youtube'
))
{
if
(
this
.
currentPlayerMode
===
'html5'
&&
this
.
videoType
===
'youtube'
)
{
if
(
availablePlaybackRates
.
length
===
1
)
{
if
(
availablePlaybackRates
.
length
===
1
)
{
// This condition is needed in cases when Firefox version is less than 20. In those versions
// This condition is needed in cases when Firefox version is
// HTML5 playback could only happen at 1 speed (no speed changing). Therefore, in this case,
// less than 20. In those versions HTML5 playback could only
// we need to switch back to Flash.
// happen at 1 speed (no speed changing). Therefore, in this
// case, we need to switch back to Flash.
//
//
// This might also happen in other browsers, therefore when we
have 1 speed available, we fall
// This might also happen in other browsers, therefore when we
// back to Flash.
//
have 1 speed available, we fall
back to Flash.
_restartUsingFlash
(
this
);
_restartUsingFlash
(
this
);
...
@@ -352,18 +391,26 @@ function (HTML5Video) {
...
@@ -352,18 +391,26 @@ function (HTML5Video) {
// and their associated subs.
// and their associated subs.
// First clear the dictionary.
// First clear the dictionary.
$
.
each
(
this
.
videos
,
function
(
index
,
value
)
{
$
.
each
(
this
.
videos
,
function
(
index
,
value
)
{
delete
_this
.
videos
[
index
];
delete
_this
.
videos
[
index
];
});
});
this
.
speeds
=
[];
this
.
speeds
=
[];
// Recreate it with the supplied frame rates.
// Recreate it with the supplied frame rates.
$
.
each
(
availablePlaybackRates
,
function
(
index
,
value
)
{
$
.
each
(
availablePlaybackRates
,
function
(
index
,
value
)
{
_this
.
videos
[
value
.
toFixed
(
2
).
replace
(
/
\.
00$/
,
'.0'
)]
=
baseSpeedSubs
;
var
key
=
value
.
toFixed
(
2
).
replace
(
/
\.
00$/
,
'.0'
);
_this
.
videos
[
key
]
=
baseSpeedSubs
;
_this
.
speeds
.
push
(
value
.
toFixed
(
2
).
replace
(
/
\.
00$/
,
'.0'
)
);
_this
.
speeds
.
push
(
key
);
});
});
this
.
trigger
(
'videoSpeedControl.reRender'
,
{
'newSpeeds'
:
this
.
speeds
,
'currentSpeed'
:
this
.
speed
});
this
.
trigger
(
'videoSpeedControl.reRender'
,
{
newSpeeds
:
this
.
speeds
,
currentSpeed
:
this
.
speed
}
);
this
.
setSpeed
(
$
.
cookie
(
'video_speed'
));
this
.
setSpeed
(
$
.
cookie
(
'video_speed'
));
}
}
...
@@ -373,7 +420,10 @@ function (HTML5Video) {
...
@@ -373,7 +420,10 @@ function (HTML5Video) {
this
.
videoPlayer
.
player
.
setPlaybackRate
(
this
.
speed
);
this
.
videoPlayer
.
player
.
setPlaybackRate
(
this
.
speed
);
}
}
if
(
!
onTouchBasedDevice
()
&&
$
(
'.video:first'
).
data
(
'autoplay'
)
===
'True'
)
{
if
(
!
onTouchBasedDevice
()
&&
$
(
'.video:first'
).
data
(
'autoplay'
)
===
'True'
)
{
this
.
videoPlayer
.
play
();
this
.
videoPlayer
.
play
();
}
}
}
}
...
@@ -400,19 +450,37 @@ function (HTML5Video) {
...
@@ -400,19 +450,37 @@ function (HTML5Video) {
duration
=
this
.
videoPlayer
.
duration
();
duration
=
this
.
videoPlayer
.
duration
();
this
.
trigger
(
'videoProgressSlider.updatePlayTime'
,
{
'time'
:
time
,
'duration'
:
duration
});
this
.
trigger
(
this
.
trigger
(
'videoControl.updateVcrVidTime'
,
{
'time'
:
time
,
'duration'
:
duration
});
'videoProgressSlider.updatePlayTime'
,
{
time
:
time
,
duration
:
duration
}
);
this
.
trigger
(
'videoControl.updateVcrVidTime'
,
{
time
:
time
,
duration
:
duration
}
);
this
.
trigger
(
'videoCaption.updatePlayTime'
,
time
);
this
.
trigger
(
'videoCaption.updatePlayTime'
,
time
);
}
}
function
isPlaying
()
{
function
isPlaying
()
{
return
this
.
videoPlayer
.
player
.
getPlayerState
()
===
this
.
videoPlayer
.
PlayerState
.
PLAYING
;
var
playerState
=
this
.
videoPlayer
.
player
.
getPlayerState
(),
PLAYING
=
this
.
videoPlayer
.
PlayerState
.
PLAYING
;
return
playerState
===
PLAYING
;
}
}
function
duration
()
{
function
duration
()
{
var
dur
;
var
dur
;
dur
=
this
.
videoPlayer
.
player
.
getDuration
();
dur
=
this
.
videoPlayer
.
player
.
getDuration
();
if
(
!
isFinite
(
dur
))
{
if
(
!
isFinite
(
dur
))
{
dur
=
this
.
getDuration
();
dur
=
this
.
getDuration
();
}
}
...
@@ -431,7 +499,7 @@ function (HTML5Video) {
...
@@ -431,7 +499,7 @@ function (HTML5Video) {
// If extra parameters were passed to the log.
// If extra parameters were passed to the log.
if
(
data
)
{
if
(
data
)
{
$
.
each
(
data
,
function
(
paramName
,
value
)
{
$
.
each
(
data
,
function
(
paramName
,
value
)
{
logInfo
[
paramName
]
=
value
;
logInfo
[
paramName
]
=
value
;
});
});
}
}
...
...
common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js
View file @
441eb369
...
@@ -19,6 +19,10 @@ function () {
...
@@ -19,6 +19,10 @@ function () {
}
}
if
(
state
.
videoType
===
'html5'
&&
!
(
_checkPlaybackRates
()))
{
if
(
state
.
videoType
===
'html5'
&&
!
(
_checkPlaybackRates
()))
{
console
.
log
(
'[Video info]: HTML5 mode - playbackRate is not supported.'
);
_hideSpeedControl
(
state
);
_hideSpeedControl
(
state
);
return
;
return
;
...
@@ -65,7 +69,7 @@ function () {
...
@@ -65,7 +69,7 @@ function () {
state
.
videoSpeedControl
.
el
state
.
videoSpeedControl
.
el
);
);
$
.
each
(
state
.
videoSpeedControl
.
speeds
,
function
(
index
,
speed
)
{
$
.
each
(
state
.
videoSpeedControl
.
speeds
,
function
(
index
,
speed
)
{
var
link
=
'<a class="speed_link" href="#">'
+
speed
+
'x</a>'
;
var
link
=
'<a class="speed_link" href="#">'
+
speed
+
'x</a>'
;
state
.
videoSpeedControl
.
videoSpeedsEl
state
.
videoSpeedControl
.
videoSpeedsEl
...
@@ -78,26 +82,27 @@ function () {
...
@@ -78,26 +82,27 @@ function () {
}
}
/**
/**
* @desc Check if playbackRate supports by browser.
* @desc Check if playbackRate supports by browser.
*
*
* @type {function}
* @type {function}
* @access private
* @access private
*
*
* @param {object} state The object containg the state of the video player.
* @param {object} state The object containg the state of the video player.
* All other modules, their parameters, public variables, etc. are
* All other modules, their parameters, public variables, etc. are
* available via this object.
* available via this object.
*
*
* @this {object} The global window object.
* @this {object} The global window object.
*
*
* @returns {Boolean}
* @returns {Boolean}
* true: Browser support playbackRate functionality.
* true: Browser support playbackRate functionality.
* false: Browser doesn't support playbackRate functionality.
* false: Browser doesn't support playbackRate functionality.
*/
*/
function
_checkPlaybackRates
()
{
function
_checkPlaybackRates
()
{
var
video
=
document
.
createElement
(
'video'
);
var
video
=
document
.
createElement
(
'video'
);
// If browser supports, 1.0 should be returned by playbackRate property.
// If browser supports, 1.0 should be returned by playbackRate
// In this case, function return True. Otherwise, False will be returned.
// property. In this case, function return True. Otherwise, False will
// be returned.
return
Boolean
(
video
.
playbackRate
);
return
Boolean
(
video
.
playbackRate
);
}
}
...
@@ -128,7 +133,7 @@ function () {
...
@@ -128,7 +133,7 @@ function () {
.
on
(
'click'
,
state
.
videoSpeedControl
.
changeVideoSpeed
);
.
on
(
'click'
,
state
.
videoSpeedControl
.
changeVideoSpeed
);
if
(
onTouchBasedDevice
())
{
if
(
onTouchBasedDevice
())
{
state
.
videoSpeedControl
.
el
.
on
(
'click'
,
function
(
event
)
{
state
.
videoSpeedControl
.
el
.
on
(
'click'
,
function
(
event
)
{
// So that you can't highlight this control via a drag
// So that you can't highlight this control via a drag
// operation, we disable the default browser actions on a
// operation, we disable the default browser actions on a
// click event.
// click event.
...
@@ -287,7 +292,7 @@ function () {
...
@@ -287,7 +292,7 @@ function () {
this
.
videoSpeedControl
.
videoSpeedsEl
.
find
(
'li'
).
removeClass
(
'active'
);
this
.
videoSpeedControl
.
videoSpeedsEl
.
find
(
'li'
).
removeClass
(
'active'
);
this
.
videoSpeedControl
.
speeds
=
params
.
newSpeeds
;
this
.
videoSpeedControl
.
speeds
=
params
.
newSpeeds
;
$
.
each
(
this
.
videoSpeedControl
.
speeds
,
function
(
index
,
speed
)
{
$
.
each
(
this
.
videoSpeedControl
.
speeds
,
function
(
index
,
speed
)
{
var
link
,
listItem
;
var
link
,
listItem
;
link
=
'<a class="speed_link" href="#">'
+
speed
+
'x</a>'
;
link
=
'<a class="speed_link" href="#">'
+
speed
+
'x</a>'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment