Video player: adding Dragabilly to closed captions

* tests for dragging
* icon location reference updates
* pattern library usage
This commit is contained in:
Chris Rodriguez
2016-02-05 09:30:34 -05:00
parent db9037bc86
commit df5520bdf9
23 changed files with 195 additions and 335 deletions

View File

@@ -543,6 +543,7 @@ from openedx.core.lib.rooted_paths import rooted_glob
PIPELINE_CSS = {
'style-vendor': {
'source_filenames': [
'js/vendor/afontgarde/afontgarde.css',
'css/vendor/normalize.css',
'css/vendor/font-awesome.css',
'css/vendor/html5-input-polyfills/number-polyfill.css',

View File

@@ -63,10 +63,13 @@
"xblock": "coffee/src/xblock",
"utility": "js/src/utility",
"accessibility": "js/src/accessibility_tools",
"draggabilly": "js/vendor/draggabilly.pkgd",
"URI": "js/vendor/URI.min",
"ieshim": "js/src/ie_shim",
"tooltip_manager": "js/src/tooltip_manager",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "js/vendor/draggabilly",
// Files needed for Annotations feature
"annotator": "js/vendor/ova/annotator-full",
@@ -241,7 +244,6 @@
exports: "XBlock",
deps: ["xblock/core"]
},
"coffee/src/main": {
deps: ["coffee/src/ajax_prefix"]
},
@@ -249,6 +251,12 @@
exports: "Logger",
deps: ["coffee/src/ajax_prefix"]
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
},
// the following are all needed for annotation tools
"video.dev": {

View File

@@ -46,10 +46,13 @@ requirejs.config({
"jasmine-imagediff": "xmodule_js/common_static/js/vendor/jasmine-imagediff",
"jasmine-stealth": "xmodule_js/common_static/js/vendor/jasmine-stealth",
"jasmine.async": "xmodule_js/common_static/js/vendor/jasmine.async",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly.pkgd",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly",
"domReady": "xmodule_js/common_static/js/vendor/domReady",
"URI": "xmodule_js/common_static/js/vendor/URI.min",
"mock-ajax": "xmodule_js/common_static/js/vendor/mock-ajax",
"modernizr": "xmodule_js/common_static/edx-pattern-library/js/modernizr-custom",
"afontgarde": "xmodule_js/common_static/edx-pattern-library/js/afontgarde",
"edxicons": "xmodule_js/common_static/edx-pattern-library/js/edx-icons",
"mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured",
"youtube": "//www.youtube.com/player_api?noext",
@@ -206,6 +209,12 @@ requirejs.config({
},
"coffee/src/ajax_prefix": {
deps: ["jquery"]
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
}
});

View File

@@ -38,7 +38,10 @@ requirejs.config({
"squire": "xmodule_js/common_static/js/vendor/Squire",
"jasmine-stealth": "xmodule_js/common_static/js/vendor/jasmine-stealth",
"jasmine.async": "xmodule_js/common_static/js/vendor/jasmine.async",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly.pkgd",
"modernizr": "xmodule_js/common_static/edx-pattern-library/js/modernizr-custom",
"afontgarde": "xmodule_js/common_static/edx-pattern-library/js/afontgarde",
"edxicons": "xmodule_js/common_static/edx-pattern-library/js/edx-icons",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly",
"domReady": "xmodule_js/common_static/js/vendor/domReady",
"URI": "xmodule_js/common_static/js/vendor/URI.min",
@@ -176,6 +179,12 @@ requirejs.config({
},
"coffee/src/ajax_prefix": {
deps: ["jquery"]
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
}
});

View File

@@ -56,7 +56,7 @@ lib_paths:
- xmodule_js/common_static/js/vendor/jQuery-File-Upload/js
- xmodule_js/src/xmodule.js
- xmodule_js/common_static/js/test/i18n.js
- xmodule_js/common_static/js/vendor/draggabilly.pkgd.js
- xmodule_js/common_static/js/vendor/draggabilly.js
- xmodule_js/common_static/js/vendor/date.js
- xmodule_js/common_static/js/vendor/domReady.js
- xmodule_js/common_static/js/vendor/URI.min.js
@@ -70,6 +70,9 @@ lib_paths:
- xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate.js
- xmodule_js/common_static/js/vendor/mock-ajax.js
- xmodule_js/common_static/js/vendor/requirejs/text.js
- xmodule_js/common_static/edx-pattern-library/js/modernizr-custom.js
- xmodule_js/common_static/edx-pattern-library/js/afontgarde.js
- xmodule_js/common_static/edx-pattern-library/js/edx-icons.js
# Paths to source JavaScript files
src_paths:

View File

@@ -10,54 +10,54 @@
// --------
// the html target is necessary for xblocks and xmodules, but works across the board
html:not('.afontgarde') .icon-fallback-img {
.icon-fallback-img {
.fa-play {
background: url('#{$static-path}/images/fontawesome/play.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/play.svg') center center no-repeat;
}
.fa-pause {
background: url('#{$static-path}/images/fontawesome/pause.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/pause.svg') center center no-repeat;
}
.fa-step-forward {
background: url('#{$static-path}/images/fontawesome/step-forward.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/fast-forward.svg') center center no-repeat;
}
.fa-arrows-alt {
background: url('#{$static-path}/images/fontawesome/arrows-alt.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/fullscreen.svg') center center no-repeat;
}
.fa-caret-right {
background: url('#{$static-path}/images/fontawesome/caret-right.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/caret-right.svg') center center no-repeat;
}
.fa-caret-left {
background: url('#{$static-path}/images/fontawesome/caret-left.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/caret-left.svg') center center no-repeat;
}
.fa-caret-up {
background: url('#{$static-path}/images/fontawesome/caret-up.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/caret-up.svg') center center no-repeat;
}
.fa-compress {
background: url('#{$static-path}/images/fontawesome/compress.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/exit-fullscreen.svg') center center no-repeat;
}
.fa-quote-left {
background: url('#{$static-path}/images/fontawesome/quote-left.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/quote-left.svg') center center no-repeat;
}
.fa-volume-up {
background: url('#{$static-path}/images/fontawesome/volume-up.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/volume-up.svg') center center no-repeat;
}
.fa-volume-down {
background: url('#{$static-path}/images/fontawesome/volume-down.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/volume-down.svg') center center no-repeat;
}
.fa-volume-off {
background: url('#{$static-path}/images/fontawesome/volume-off.svg') center center no-repeat;
background: url('#{$static-path}/edx-pattern-library/fonts/edx-icons/fallback-img/volume-off.svg') center center no-repeat;
}
}
@@ -261,6 +261,28 @@ html:not('.afontgarde') .icon-fallback-img {
padding: 8px ($baseline / 2) 8px ($baseline * 1.5);
background: rgba(0, 0, 0, .75);
color: $yellow;
&:before {
position: absolute;
display: inline-block;
top: 50%;
@include left($baseline);
margin-top: -.6em;
font-family: 'FontAwesome';
content: "\f142";
color: $white;
opacity: 0.5;
}
&:hover,
&.is-dragging {
background: rgba(0, 0, 0, 1.0);
cursor: move;
&:before {
opacity: 1.0;
}
}
}
.video-player {
@@ -289,7 +311,7 @@ html:not('.afontgarde') .icon-fallback-img {
width: 100%;
}
h3 {
h4 {
text-align: center;
color: white;

View File

@@ -98,7 +98,7 @@ class HtmlModuleMixin(HtmlBlock, XModule):
'js': [
resource_string(__name__, 'js/src/collapsible.js'),
resource_string(__name__, 'js/src/html/imageModal.js'),
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.pkgd.js'),
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.js'),
]
}
js_module_name = "HTMLModule"

View File

@@ -59,6 +59,10 @@ lib_paths:
- public/js/split_test_staff.js
- common_static/js/src/accessibility_tools.js
- common_static/js/vendor/moment.min.js
- common_static/js/vendor/draggabilly.js
- common_static/edx-pattern-library/js/modernizr-custom.js
- common_static/edx-pattern-library/js/afontgarde.js
- common_static/edx-pattern-library/js/edx-icons.js
- spec/main_requirejs.js
# Paths to spec (test) JavaScript files

View File

@@ -1,10 +1,20 @@
(function(requirejs) {
requirejs.config({
paths: {
"moment": "xmodule/include/common_static/js/vendor/moment.min"
"moment": "xmodule/include/common_static/js/vendor/moment.min",
"modernizr": "xmodule/include/common_static/edx-pattern-library/js/modernizr-custom",
"afontgarde": "xmodule/include/common_static/edx-pattern-library/js/afontgarde",
"edxicons": "xmodule/include/common_static/edx-pattern-library/js/edx-icons",
"draggabilly": "xmodule/include/common_static/js/vendor/draggabilly"
},
"moment": {
exports: "moment"
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
});

View File

@@ -2,11 +2,14 @@
// VideoCaption module.
'use strict';
define('video/09_video_caption.js', [
define('video/09_video_caption.js',[
'video/00_sjson.js',
'video/00_async_process.js'
],
function (Sjson, AsyncProcess) {
'video/00_async_process.js',
'draggabilly',
'modernizr',
'afontgarde',
'edxicons'
], function (Sjson, AsyncProcess, Draggabilly) {
/**
* @desc VideoCaption module exports a function.
@@ -33,12 +36,14 @@
'handleKeypress', 'handleKeypressLink', 'openLanguageMenu', 'closeLanguageMenu',
'previousLanguageMenuItem', 'nextLanguageMenuItem', 'handleCaptionToggle',
'showClosedCaptions', 'hideClosedCaptions', 'toggleClosedCaptions',
'updateCaptioningCookie', 'handleCaptioningCookie', 'handleTranscriptToggle'
'updateCaptioningCookie', 'handleCaptioningCookie', 'handleTranscriptToggle',
'listenForDragDrop'
);
this.state = state;
this.state.videoCaption = this;
this.renderElements();
this.handleCaptioningCookie();
this.listenForDragDrop();
return $.Deferred().resolve().promise();
};
@@ -531,7 +536,7 @@
if (state.isTouch) {
self.subtitlesEl.find('.subtitles-menu')
.text(gettext('Transcript will be displayed when you start playing the video.')) // jshint ignore: line
.wrapInner('<li></li>');
.wrapInner('<li></li>');
} else {
self.renderCaption(start, captions);
}
@@ -1147,6 +1152,17 @@
}
},
listenForDragDrop: function() {
var captions = document.querySelector('.closed-captions'),
draggable;
if (typeof Draggabilly === "function") {
draggable = new Draggabilly(captions, { containment: true });
} else {
console.log('Closed captioning available but not draggable');
}
},
/**
* @desc Shows/Hides captions and updates the cookie.
*

View File

@@ -32,7 +32,11 @@
'jasmine-imagediff': 'js/vendor/jasmine-imagediff',
'jasmine-stealth': 'js/vendor/jasmine-stealth',
'jasmine.async': 'js/vendor/jasmine.async',
'URI': 'js/vendor/URI.min'
'URI': 'js/vendor/URI.min',
'modernizr': 'edx-pattern-library/js/modernizr-custom',
'afontgarde': 'edx-pattern-library/js/afontgarde',
'edxicons': 'edx-pattern-library/js/edx-icons',
'draggabilly': 'js/vendor/draggabilly',
},
shim: {
'gettext': {
@@ -149,6 +153,12 @@
},
"sinon": {
exports: "sinon"
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
}
});

View File

@@ -57,4 +57,4 @@ html:not('.afontgarde') .icon-fallback-img .icon:before {
/* The img fallback version is not as reliable since it does not check to make sure the fontloaded font has loaded. If we did add the .fontloaded class, it would unnecessarily request the fallback image. */
.fontawesome .icon-fallback-img .icon {
background-image: none;
}
}

View File

@@ -1,287 +0,0 @@
/*! afontgarde - v0.1.6 - 2015-03-13
* https://github.com/filamentgroup/a-font-garde
* Copyright (c) 2015 Filament Group c/o Zach Leatherman
* MIT License */
/*! fontfaceonload - v0.1.6 - 2015-03-13
* https://github.com/zachleat/fontfaceonload
* Copyright (c) 2015 Zach Leatherman (@zachleat)
* MIT License */
;(function( win, doc ) {
"use strict";
var TEST_STRING = 'AxmTYklsjo190QW',
SANS_SERIF_FONTS = 'sans-serif',
SERIF_FONTS = 'serif',
// lighter and bolder not supported
weightLookup = {
normal: '400',
bold: '700'
},
defaultOptions = {
tolerance: 2, // px
delay: 100,
glyphs: '',
success: function() {},
error: function() {},
timeout: 5000,
weight: '400', // normal
style: 'normal'
},
// See https://github.com/typekit/webfontloader/blob/master/src/core/fontruler.js#L41
style = [
'display:block',
'position:absolute',
'top:-999px',
'left:-999px',
'font-size:48px',
'width:auto',
'height:auto',
'line-height:normal',
'margin:0',
'padding:0',
'font-variant:normal',
'white-space:nowrap'
],
html = '<div style="%s">' + TEST_STRING + '</div>';
var FontFaceOnloadInstance = function() {
this.fontFamily = '';
this.appended = false;
this.serif = undefined;
this.sansSerif = undefined;
this.parent = undefined;
this.options = {};
};
FontFaceOnloadInstance.prototype.getMeasurements = function () {
return {
sansSerif: {
width: this.sansSerif.offsetWidth,
height: this.sansSerif.offsetHeight
},
serif: {
width: this.serif.offsetWidth,
height: this.serif.offsetHeight
}
};
};
FontFaceOnloadInstance.prototype.load = function () {
var startTime = new Date(),
that = this,
serif = that.serif,
sansSerif = that.sansSerif,
parent = that.parent,
appended = that.appended,
dimensions,
options = this.options,
ref = options.reference;
function getStyle( family ) {
return style
.concat( [ 'font-weight:' + options.weight, 'font-style:' + options.style ] )
.concat( "font-family:" + family )
.join( ";" );
}
var sansSerifHtml = html.replace( /\%s/, getStyle( SANS_SERIF_FONTS ) ),
serifHtml = html.replace( /\%s/, getStyle( SERIF_FONTS ) );
if( !parent ) {
parent = that.parent = doc.createElement( "div" );
}
parent.innerHTML = sansSerifHtml + serifHtml;
sansSerif = that.sansSerif = parent.firstChild;
serif = that.serif = sansSerif.nextSibling;
if( options.glyphs ) {
sansSerif.innerHTML += options.glyphs;
serif.innerHTML += options.glyphs;
}
function hasNewDimensions( dims, el, tolerance ) {
return Math.abs( dims.width - el.offsetWidth ) > tolerance ||
Math.abs( dims.height - el.offsetHeight ) > tolerance;
}
function isTimeout() {
return ( new Date() ).getTime() - startTime.getTime() > options.timeout;
}
(function checkDimensions() {
if( !ref ) {
ref = doc.body;
}
if( !appended && ref ) {
ref.appendChild( parent );
appended = that.appended = true;
dimensions = that.getMeasurements();
// Make sure we set the new font-family after we take our initial dimensions:
// handles the case where FontFaceOnload is called after the font has already
// loaded.
sansSerif.style.fontFamily = that.fontFamily + ', ' + SANS_SERIF_FONTS;
serif.style.fontFamily = that.fontFamily + ', ' + SERIF_FONTS;
}
if( appended && dimensions &&
( hasNewDimensions( dimensions.sansSerif, sansSerif, options.tolerance ) ||
hasNewDimensions( dimensions.serif, serif, options.tolerance ) ) ) {
options.success();
} else if( isTimeout() ) {
options.error();
} else {
if( !appended && "requestAnimationFrame" in window ) {
win.requestAnimationFrame( checkDimensions );
} else {
win.setTimeout( checkDimensions, options.delay );
}
}
})();
}; // end load()
FontFaceOnloadInstance.prototype.checkFontFaces = function( timeout ) {
var _t = this;
doc.fonts.forEach(function( font ) {
if( font.family.toLowerCase() === _t.fontFamily.toLowerCase() &&
( weightLookup[ font.weight ] || font.weight ) === ''+_t.options.weight &&
font.style === _t.options.style ) {
font.load().then(function() {
_t.options.success();
win.clearTimeout( timeout );
});
}
});
};
FontFaceOnloadInstance.prototype.init = function( fontFamily, options ) {
var timeout;
for( var j in defaultOptions ) {
if( !options.hasOwnProperty( j ) ) {
options[ j ] = defaultOptions[ j ];
}
}
this.options = options;
this.fontFamily = fontFamily;
// For some reason this was failing on afontgarde + icon fonts.
if( !options.glyphs && "fonts" in doc ) {
if( options.timeout ) {
timeout = win.setTimeout(function() {
options.error();
}, options.timeout );
}
this.checkFontFaces( timeout );
} else {
this.load();
}
};
var FontFaceOnload = function( fontFamily, options ) {
var instance = new FontFaceOnloadInstance();
instance.init(fontFamily, options);
return instance;
};
// intentional global
win.FontFaceOnload = FontFaceOnload;
})( this, this.document );
/*
* A Font Garde
*/
;(function( w ) {
var doc = w.document,
ref,
css = ['.FONT_NAME.supports-generatedcontent .icon-fallback-text .icon { display: inline-block; }',
'.FONT_NAME.supports-generatedcontent .icon-fallback-text .text { clip: rect(0 0 0 0); overflow: hidden; position: absolute; height: 1px; width: 1px; }',
'.FONT_NAME .icon-fallback-glyph .icon:before { font-size: 1em; font-size: inherit; line-height: 1; line-height: inherit; }'];
function addEvent( type, callback ) {
if( 'addEventListener' in w ) {
return w.addEventListener( type, callback, false );
} else if( 'attachEvent' in w ) {
return w.attachEvent( 'on' + type, callback );
}
}
// options can be a string of glyphs or an options object to pass into FontFaceOnload
AFontGarde = function( fontFamily, options ) {
var fontFamilyClassName = fontFamily.toLowerCase().replace( /\s/g, '' ),
executed = false;
function init() {
if( executed ) {
return;
}
executed = true;
if( typeof FontFaceOnload === 'undefined' ) {
throw 'FontFaceOnload is a prerequisite.';
}
if( !ref ) {
ref = doc.getElementsByTagName( 'script' )[ 0 ];
}
var style = doc.createElement( 'style' ),
cssContent = css.join( '\n' ).replace( /FONT_NAME/gi, fontFamilyClassName );
style.setAttribute( 'type', 'text/css' );
if( style.styleSheet ) {
style.styleSheet.cssText = cssContent;
} else {
style.appendChild( doc.createTextNode( cssContent ) );
}
ref.parentNode.insertBefore( style, ref );
var opts = {
timeout: 5000,
success: function() {
// If youre using more than one icon font, change this classname (and in a-font-garde.css)
doc.documentElement.className += ' ' + fontFamilyClassName;
if( options && options.success ) {
options.success();
}
}
};
// These characters are a few of the glyphs from the font above */
if( typeof options === "string" ) {
opts.glyphs = options;
} else {
for( var j in options ) {
if( options.hasOwnProperty( j ) && j !== "success" ) {
opts[ j ] = options[ j ];
}
}
}
FontFaceOnload( fontFamily, opts );
}
// MIT credit: filamentgroup/shoestring
addEvent( "DOMContentLoaded", init );
addEvent( "readystatechange", init );
addEvent( "load", init );
if( doc.readyState === "complete" ){
init();
}
};
})( this );

View File

@@ -1,7 +0,0 @@
(function() {
'use strict';
window.AFontGarde('FontAwesome', {
glyphs: '&#61515;'
});
});

View File

@@ -1,4 +0,0 @@
/* Modernizr 2.7.1 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-fontface-generatedcontent-cssclasses-teststyles-cssclassprefix:supports!
*/
;window.Modernizr=function(a,b,c){function w(a){j.cssText=a}function x(a,b){return w(prefixes.join(a+";")+(b||""))}function y(a,b){return typeof a===b}function z(a,b){return!!~(""+a).indexOf(b)}function A(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:y(f,"function")?f.bind(d||b):f}return!1}var d="2.7.1",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l=":)",m={}.toString,n={},o={},p={},q=[],r=q.slice,s,t=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},u={}.hasOwnProperty,v;!y(u,"undefined")&&!y(u.call,"undefined")?v=function(a,b){return u.call(a,b)}:v=function(a,b){return b in a&&y(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=r.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(r.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(r.call(arguments)))};return e}),n.fontface=function(){var a;return t('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},n.generatedcontent=function(){var a;return t(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a};for(var B in n)v(n,B)&&(s=B.toLowerCase(),e[s]=n[B](),q.push((e[s]?"":"no-")+s));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)v(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" supports-"+(b?"":"no-")+a),e[a]=b}return e},w(""),i=k=null,e._version=d,e.testStyles=t,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" supports-js supports-"+q.join(" supports-"):""),e}(this,this.document);

View File

@@ -38,10 +38,14 @@ lib_paths:
- js/vendor/backbone-min.js
- js/vendor/jquery.timeago.js
- js/vendor/URI.min.js
- js/vendor/draggabilly.js
- coffee/src/ajax_prefix.js
- js/test/add_ajax_prefix.js
- js/test/i18n.js
- coffee/src/jquery.immediateDescendents.js
- edx-pattern-library/js/modernizr-custom.js
- edx-pattern-library/js/afontgarde.js
- edx-pattern-library/js/edx-icons.js
# Paths to source JavaScript files
src_paths:

View File

@@ -8,6 +8,8 @@ import os
from mock import patch
from nose.plugins.attrib import attr
from unittest import skipIf, skip
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from ..helpers import UniqueCourseTest, is_youtube_available, YouTubeStubConfig
from ...pages.lms.video.video import VideoPage
from ...pages.lms.tab_nav import TabNavPage
@@ -1189,6 +1191,42 @@ class YouTubeQualityTest(VideoBaseTest):
self.video.wait_for(lambda: self.video.is_quality_button_active, 'waiting for quality button activation')
@attr('shard_4')
class DragAndDropTest(VideoBaseTest):
"""
Tests draggability of closed captions within videos.
"""
def setUp(self):
super(DragAndDropTest, self).setUp()
def test_if_captions_are_draggable(self):
"""
Loads transcripts so that closed-captioning is available.
Ensures they are draggable by checking start and dropped location.
"""
self.assets.append('subs_3_yD_cEKoCk.srt.sjson')
data = {'sub': '3_yD_cEKoCk'}
self.metadata = self.metadata_for_mode('html5', additional_data=data)
self.navigate_to_video()
self.assertTrue(self.video.is_video_rendered('html5'))
self.video.show_closed_captions()
self.video.wait_for_closed_captions()
self.assertTrue(self.video.is_closed_captions_visible)
action = ActionChains(self.browser)
captions = self.browser.find_element(By.CLASS_NAME, 'closed-captions')
captions_start = captions.location
action.drag_and_drop_by_offset(captions, 0, -15).perform()
captions_end = captions.location
self.assertEqual(
captions_end.get('y') + 15,
captions_start.get('y'),
'Closed captions did not get dragged.'
)
@attr('a11y')
class LMSVideoModuleA11yTest(VideoBaseTest):
"""

View File

@@ -1261,7 +1261,8 @@ base_vendor_js = [
'js/vendor/requirejs/require.js',
'js/RequireJS-namespace-undefine.js',
'js/vendor/URI.min.js',
'js/vendor/backbone-min.js'
'js/vendor/backbone-min.js',
'edx-pattern-library/js/modernizr-custom.js',
]
main_vendor_js = base_vendor_js + [
@@ -1269,9 +1270,6 @@ main_vendor_js = base_vendor_js + [
'js/vendor/jquery-ui.min.js',
'js/vendor/jquery.qtip.min.js',
'js/vendor/jquery.ba-bbq.min.js',
'js/vendor/afontgarde/modernizr.fontface-generatedcontent.js',
'js/vendor/afontgarde/afontgarde.js',
'js/vendor/afontgarde/edx-icons.js'
]
# Common files used by both RequireJS code and non-RequireJS code
@@ -1670,7 +1668,10 @@ REQUIRE_JS_PATH_OVERRIDES = {
'js/student_account/logistration_factory': 'js/student_account/logistration_factory.js',
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory.js',
'js/bookmarks/bookmarks_factory': 'js/bookmarks/bookmarks_factory.js',
'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory.js'
'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory.js',
'afontgarde': 'edx-pattern-library/js/afontgarde.js',
'edxicons': 'edx-pattern-library/js/edx-icons.js',
'draggabilly': 'js/vendor/draggabilly.js'
}
################################# CELERY ######################################

View File

@@ -47,7 +47,6 @@
'jasmine-imagediff': 'xmodule_js/common_static/js/vendor/jasmine-imagediff',
'jasmine-stealth': 'xmodule_js/common_static/js/vendor/jasmine-stealth',
'jasmine.async': 'xmodule_js/common_static/js/vendor/jasmine.async',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly.pkgd',
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line
'youtube': '//www.youtube.com/player_api?noext',
@@ -67,6 +66,10 @@
'mathjax_delay_renderer': 'coffee/src/mathjax_delay_renderer',
'MathJaxProcessor': 'coffee/src/customwmd',
'picturefill': 'common/js/vendor/picturefill.min',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
'modernizr': 'xmodule_js/common_static/edx-pattern-library/js/modernizr-custom',
'afontgarde': 'xmodule_js/common_static/edx-pattern-library/js/afontgarde',
'edxicons': 'xmodule_js/common_static/edx-pattern-library/js/edx-icons',
// Manually specify LMS files that are not converted to RequireJS
'history': 'js/vendor/history',
@@ -625,8 +628,13 @@
'xmodule_js/common_static/coffee/src/discussion/utils'
],
exports: 'DiscussionSpecHelper'
},
'modernizr': {
exports: 'Modernizr'
},
'afontgarde': {
exports: 'AFontGarde'
}
}
});

View File

@@ -72,6 +72,7 @@
'utility': 'empty:',
'URI': 'empty:',
'DiscussionModuleView': 'empty:',
'modernizr': 'empty',
// Don't bundle UI Toolkit helpers as they are loaded into the "edx" namespace
'edx-ui-toolkit/js/utils/html-utils': 'empty:',

View File

@@ -39,6 +39,7 @@
defineDependency("Logger", "logger");
defineDependency("URI", "URI");
defineDependency("Backbone", "backbone");
defineDependency("Modernizr", "modernizr");
// Add the UI Toolkit helper classes that have been installed in the "edx" namespace
defineDependency("edx.HtmlUtils", "edx-ui-toolkit/js/utils/html-utils");
@@ -73,6 +74,10 @@
"URI": "js/vendor/URI.min",
"string_utils": "js/src/string_utils",
"utility": "js/src/utility",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "js/vendor/draggabilly",
// Files needed by OVA
"annotator": "js/vendor/ova/annotator-full",
@@ -200,6 +205,15 @@
},
"moment-with-locales": {
exports: "moment"
},
"afontgarde": {
exports: "AFontGarde"
},
// Because Draggabilly is being used by video code, the namespaced version of
// require is not being recognized. Therefore the library is being added to the
// global namespace instead of being registered in require.
"draggabilly": {
exports: "Draggabilly"
}
}
});

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"dependencies": {
"coffee-script": "1.6.1",
"edx-pattern-library": "~0.12.1",
"edx-pattern-library": "~0.12.4",
"edx-ui-toolkit": "~0.9.1",
"requirejs": "~2.1.22",
"uglify-js": "2.4.24",