diff --git a/common/lib/xmodule/xmodule/js/src/video/01_initialize.js b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js index 7f8057c025..d9f0addabf 100644 --- a/common/lib/xmodule/xmodule/js/src/video/01_initialize.js +++ b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js @@ -271,6 +271,7 @@ function (VideoPlayer) { // The parent element of the video, and the ID. this.el = $(element).find('.video'); + this.elVideoWrapper = this.el.find('.video-wrapper'); this.id = this.el.attr('id').replace(/video_/, ''); console.log( diff --git a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js index 71198335e6..a722eadc87 100644 --- a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js @@ -34,46 +34,63 @@ function () { // function _makeFunctionsPublic(state) // - // Functions which will be accessible via 'state' object. When called, these functions will - // get the 'state' object as a context. + // Functions which will be accessible via 'state' object. When called, + // these functions will get the 'state' object as a context. function _makeFunctionsPublic(state) { - state.videoCaption.autoShowCaptions = _.bind(autoShowCaptions, state); - state.videoCaption.autoHideCaptions = _.bind(autoHideCaptions, state); - state.videoCaption.resize = _.bind(resize, state); - state.videoCaption.toggle = _.bind(toggle, state); - state.videoCaption.onMouseEnter = _.bind(onMouseEnter, state); - state.videoCaption.onMouseLeave = _.bind(onMouseLeave, state); - state.videoCaption.onMovement = _.bind(onMovement, state); - state.videoCaption.renderCaption = _.bind(renderCaption, state); - state.videoCaption.captionHeight = _.bind(captionHeight, state); - state.videoCaption.topSpacingHeight = _.bind(topSpacingHeight, state); - state.videoCaption.bottomSpacingHeight = _.bind(bottomSpacingHeight, state); - state.videoCaption.scrollCaption = _.bind(scrollCaption, state); - state.videoCaption.search = _.bind(search, state); - state.videoCaption.play = _.bind(play, state); - state.videoCaption.pause = _.bind(pause, state); - state.videoCaption.seekPlayer = _.bind(seekPlayer, state); - state.videoCaption.hideCaptions = _.bind(hideCaptions, state); - state.videoCaption.calculateOffset = _.bind(calculateOffset, state); - state.videoCaption.updatePlayTime = _.bind(updatePlayTime, state); - state.videoCaption.setSubtitlesHeight = _.bind(setSubtitlesHeight, state); + state.videoCaption.autoShowCaptions = _.bind( + autoShowCaptions, state + ); + state.videoCaption.autoHideCaptions = _.bind( + autoHideCaptions, state + ); + state.videoCaption.resize = _.bind(resize, state); + state.videoCaption.toggle = _.bind(toggle, state); + state.videoCaption.onMouseEnter = _.bind(onMouseEnter, state); + state.videoCaption.onMouseLeave = _.bind(onMouseLeave, state); + state.videoCaption.onMovement = _.bind(onMovement, state); + state.videoCaption.renderCaption = _.bind(renderCaption, state); + state.videoCaption.captionHeight = _.bind(captionHeight, state); + state.videoCaption.topSpacingHeight = _.bind( + topSpacingHeight, state + ); + state.videoCaption.bottomSpacingHeight = _.bind( + bottomSpacingHeight, state + ); + state.videoCaption.scrollCaption = _.bind(scrollCaption, state); + state.videoCaption.search = _.bind(search, state); + state.videoCaption.play = _.bind(play, state); + state.videoCaption.pause = _.bind(pause, state); + state.videoCaption.seekPlayer = _.bind(seekPlayer, state); + state.videoCaption.hideCaptions = _.bind(hideCaptions, state); + state.videoCaption.calculateOffset = _.bind( + calculateOffset, state + ); + state.videoCaption.updatePlayTime = _.bind(updatePlayTime, state); + state.videoCaption.setSubtitlesHeight = _.bind( + setSubtitlesHeight, state + ); - state.videoCaption.renderElements = _.bind(renderElements, state); - state.videoCaption.bindHandlers = _.bind(bindHandlers, state); - state.videoCaption.fetchCaption = _.bind(fetchCaption, state); - state.videoCaption.captionURL = _.bind(captionURL, state); - state.videoCaption.captionMouseOverOut = _.bind(captionMouseOverOut, state); - state.videoCaption.captionMouseDown = _.bind(captionMouseDown, state); - state.videoCaption.captionClick = _.bind(captionClick, state); - state.videoCaption.captionFocus = _.bind(captionFocus, state); - state.videoCaption.captionBlur = _.bind(captionBlur, state); - state.videoCaption.captionKeyDown = _.bind(captionKeyDown, state); + state.videoCaption.renderElements = _.bind(renderElements, state); + state.videoCaption.bindHandlers = _.bind(bindHandlers, state); + state.videoCaption.fetchCaption = _.bind(fetchCaption, state); + state.videoCaption.captionURL = _.bind(captionURL, state); + state.videoCaption.captionMouseOverOut = _.bind( + captionMouseOverOut, state + ); + state.videoCaption.captionMouseDown = _.bind( + captionMouseDown, state + ); + state.videoCaption.captionClick = _.bind(captionClick, state); + state.videoCaption.captionFocus = _.bind(captionFocus, state); + state.videoCaption.captionBlur = _.bind(captionBlur, state); + state.videoCaption.captionKeyDown = _.bind(captionKeyDown, state); } // *************************************************************** // Public functions start here. - // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object. - // The magic private function that makes them available and sets up their context is makeFunctionsPublic(). + // These are available via the 'state' object. Their context ('this' + // keyword) is the 'state' object. The magic private function that makes + // them available and sets up their context is makeFunctionsPublic(). // *************************************************************** /** @@ -109,10 +126,13 @@ function () { // function bindHandlers() // - // Bind any necessary function callbacks to DOM events (click, mousemove, etc.). + // Bind any necessary function callbacks to DOM events (click, + // mousemove, etc.). function bindHandlers() { $(window).bind('resize', this.videoCaption.resize); - this.videoCaption.hideSubtitlesEl.on('click', this.videoCaption.toggle); + this.videoCaption.hideSubtitlesEl.on( + 'click', this.videoCaption.toggle + ); this.videoCaption.subtitlesEl .on( @@ -138,8 +158,12 @@ function () { // Moving slider on subtitles is not a mouse move, // but captions and controls should be showed. - this.videoCaption.subtitlesEl.on('scroll', this.videoCaption.autoShowCaptions); - this.videoCaption.subtitlesEl.on('scroll', this.videoControl.showControls); + this.videoCaption.subtitlesEl.on( + 'scroll', this.videoCaption.autoShowCaptions + ); + this.videoCaption.subtitlesEl.on( + 'scroll', this.videoControl.showControls + ); } } @@ -209,7 +233,8 @@ function () { } function captionURL() { - return '' + this.config.caption_asset_path + this.youtubeId('1.0') + '.srt.sjson'; + return '' + this.config.caption_asset_path + + this.youtubeId('1.0') + '.srt.sjson'; } function autoShowCaptions(event) { @@ -224,13 +249,17 @@ function () { this.videoCaption.subtitlesEl.show(); this.captionState = 'visible'; } else if (this.captionState === 'hiding') { - this.videoCaption.subtitlesEl.stop(true, false).css('opacity', 1).show(); + this.videoCaption.subtitlesEl + .stop(true, false).css('opacity', 1).show(); this.captionState = 'visible'; } else if (this.captionState === 'visible') { clearTimeout(this.captionHideTimeout); } - this.captionHideTimeout = setTimeout(this.videoCaption.autoHideCaptions, this.videoCaption.fadeOutTimeout); + this.captionHideTimeout = setTimeout( + this.videoCaption.autoHideCaptions, + this.videoCaption.fadeOutTimeout + ); this.captionsShowLock = false; } @@ -249,15 +278,20 @@ function () { _this = this; - this.videoCaption.subtitlesEl.fadeOut(this.videoCaption.fadeOutTimeout, function () { + this.videoCaption.subtitlesEl.fadeOut( + this.videoCaption.fadeOutTimeout, + function () { + _this.captionState = 'invisible'; }); } function resize() { this.videoCaption.subtitlesEl - .find('.spacing:first').height(this.videoCaption.topSpacingHeight()) - .find('.spacing:last').height(this.videoCaption.bottomSpacingHeight()); + .find('.spacing:first') + .height(this.videoCaption.topSpacingHeight()) + .find('.spacing:last') + .height(this.videoCaption.bottomSpacingHeight()); this.videoCaption.scrollCaption(); @@ -269,7 +303,10 @@ function () { clearTimeout(this.videoCaption.frozen); } - this.videoCaption.frozen = setTimeout(this.videoCaption.onMouseLeave, 10000); + this.videoCaption.frozen = setTimeout( + this.videoCaption.onMouseLeave, + 10000 + ); } function onMouseLeave() { @@ -292,8 +329,9 @@ function () { var container = $('
    '), _this = this; - this.el.find('.video-wrapper').after(this.videoCaption.subtitlesEl); - this.el.find('.video-controls .secondary-controls').append(this.videoCaption.hideSubtitlesEl); + this.elVideoWrapper.after(this.videoCaption.subtitlesEl); + this.el.find('.video-controls .secondary-controls') + .append(this.videoCaption.hideSubtitlesEl); this.videoCaption.setSubtitlesHeight(); @@ -301,7 +339,10 @@ function () { this.videoCaption.fadeOutTimeout = this.config.fadeOutTimeout; this.videoCaption.subtitlesEl.addClass('html5'); - this.captionHideTimeout = setTimeout(this.videoCaption.autoHideCaptions, this.videoCaption.fadeOutTimeout); + this.captionHideTimeout = setTimeout( + this.videoCaption.autoHideCaptions, + this.videoCaption.fadeOutTimeout + ); } this.videoCaption.hideCaptions(this.hide_captions); @@ -344,16 +385,23 @@ function () { this.videoCaption.autoScrolling = true; // Keeps track of where the focus is situated in the array of captions. // Used to implement the automatic scrolling behavior and decide if the - // outline around a caption has to be hidden or shown on a mouseenter or - // mouseleave. Initially, no caption has the focus, set the index to -1. + // outline around a caption has to be hidden or shown on a mouseenter + // or mouseleave. Initially, no caption has the focus, set the + // index to -1. this.videoCaption.currentCaptionIndex = -1; // Used to track if the focus is coming from a click or tabbing. This // has to be known to decide if, when a caption gets the focus, an // outline has to be drawn (tabbing) or not (mouse click). this.videoCaption.isMouseFocus = false; - this.videoCaption.subtitlesEl.prepend($('
  1. ').height(this.videoCaption.topSpacingHeight())); - this.videoCaption.subtitlesEl.append($('
  2. ').height(this.videoCaption.bottomSpacingHeight())); + this.videoCaption.subtitlesEl.prepend( + $('
  3. ') + .height(this.videoCaption.topSpacingHeight()) + ); + this.videoCaption.subtitlesEl.append( + $('
  4. ') + .height(this.videoCaption.bottomSpacingHeight()) + ); this.videoCaption.rendered = true; } @@ -403,7 +451,14 @@ function () { caption.addClass('focused'); // The second and second to last elements turn automatic scrolling // off again as it may have been enabled in captionBlur. +<<<<<<< HEAD if (captionIndex <= 1 || captionIndex >= this.videoCaption.captions.length-2) { +======= + if ( + captionIndex <= 1 || + captionIndex >= this.videoCaption.captions.length-2 + ) { +>>>>>>> Work in progress. this.videoCaption.autoScrolling = false; } } @@ -413,11 +468,19 @@ function () { var caption = $(event.target), captionIndex = parseInt(caption.attr('data-index'), 10); caption.removeClass('focused'); +<<<<<<< HEAD // If we are on first or last index, we have to turn automatic scroll on // again when losing focus. There is no way to know in what direction we // are tabbing. So we could be on the first element and tabbing back out // of the captions or on the last element and tabbing forward out of the // captions. +======= + // If we are on first or last index, we have to turn automatic scroll + // on again when losing focus. There is no way to know in what + // direction we are tabbing. So we could be on the first element and + // tabbing back out of the captions or on the last element and tabbing + // forward out of the captions. +>>>>>>> Work in progress. if (captionIndex === 0 || captionIndex === this.videoCaption.captions.length-1) { this.videoCaption.autoScrolling = true; @@ -434,9 +497,19 @@ function () { function scrollCaption() { var el = this.videoCaption.subtitlesEl.find('.current:first'); +<<<<<<< HEAD // Automatic scrolling gets disabled if one of the captions has received // focus through tabbing. if (!this.videoCaption.frozen && el.length && this.videoCaption.autoScrolling) { +======= + // Automatic scrolling gets disabled if one of the captions has + // received focus through tabbing. + if ( + !this.videoCaption.frozen && + el.length && + this.videoCaption.autoScrolling + ) { +>>>>>>> Work in progress. this.videoCaption.subtitlesEl.scrollTo( el, { @@ -565,11 +638,15 @@ function () { } function topSpacingHeight() { - return this.videoCaption.calculateOffset(this.videoCaption.subtitlesEl.find('li:not(.spacing):first')); + return this.videoCaption.calculateOffset( + this.videoCaption.subtitlesEl.find('li:not(.spacing):first') + ); } function bottomSpacingHeight() { - return this.videoCaption.calculateOffset(this.videoCaption.subtitlesEl.find('li:not(.spacing):last')); + return this.videoCaption.calculateOffset( + this.videoCaption.subtitlesEl.find('li:not(.spacing):last') + ); } function toggle(event) { @@ -592,14 +669,20 @@ function () { if (hide_captions) { type = 'hide_transcript'; this.captionsHidden = true; - this.videoCaption.hideSubtitlesEl.attr('title', gettext('Turn on captions')); - this.videoCaption.hideSubtitlesEl.text(gettext('Turn on captions')); + this.videoCaption.hideSubtitlesEl.attr( + 'title', gettext('Turn on captions') + ); + this.videoCaption.hideSubtitlesEl + .text(gettext('Turn on captions')); this.el.addClass('closed'); } else { type = 'show_transcript'; this.captionsHidden = false; - this.videoCaption.hideSubtitlesEl.attr('title', gettext('Turn off captions')); - this.videoCaption.hideSubtitlesEl.text(gettext('Turn off captions')); + this.videoCaption.hideSubtitlesEl.attr( + 'title', gettext('Turn off captions') + ); + this.videoCaption.hideSubtitlesEl + .text(gettext('Turn off captions')); this.el.removeClass('closed'); this.videoCaption.scrollCaption(); } @@ -621,12 +704,19 @@ function () { } function captionHeight() { + var paddingTop; + if (this.isFullScreen) { - return $(window).height() - this.el.find('.video-controls').height() - - 0.5 * this.videoControl.sliderEl.height() - - 2 * parseInt(this.videoCaption.subtitlesEl.css('padding-top'), 10); + paddingTop = parseInt( + this.videoCaption.subtitlesEl.css('padding-top'), 10 + ); + + return $(window).height() - + this.videoControl.el.height() - + 0.5 * this.videoControl.sliderEl.height() - + 2 * paddingTop; } else { - return this.el.find('.video-wrapper').height(); + return this.elVideoWrapper.height(); } } @@ -635,13 +725,19 @@ function () { if (this.videoType === 'html5'){ // on page load captionHidden = undefined if ( - (this.captionsHidden === undefined && this.hide_captions === true ) || - (this.captionsHidden === true) ) { - // In case of html5 autoshowing subtitles, - // we ajdust height of subs, by height of scrollbar - height = this.videoControl.el.height() + 0.5 * this.videoControl.sliderEl.height(); - // height of videoControl does not contain height of slider. - // (css is set to absolute, to avoid yanking when slider autochanges its height) + ( + this.captionsHidden === undefined && + this.hide_captions === true + ) || + (this.captionsHidden === true) + ) { + // In case of html5 autoshowing subtitles, we adjust height of + // subs, by height of scrollbar. + height = this.videoControl.el.height() + + 0.5 * this.videoControl.sliderEl.height(); + // Height of videoControl does not contain height of slider. + // css is set to absolute, to avoid yanking when slider + // autochanges its height. } } this.videoCaption.subtitlesEl.css({