From 9d2eec07b9b901b2da5d6ff6dacd53bd05dab2ff Mon Sep 17 00:00:00 2001 From: Valera Rozuvan Date: Wed, 13 Mar 2013 17:21:27 +0200 Subject: [PATCH] Refactoring of events system. Minor fix. Minor fix. Now state of captions is properly set from cookies. Fix for hiding-showing subs based on cookie when subs are not found. Partial feature - hide show controls on mouse. Removed debugging messages. Changed trigger() method - now it has a better interface. Better function rewrite. Now .trigger() is more readable and understandable. In between. --- .../xmodule/css/videoalpha/display.scss | 11 +- .../js/src/videoalpha/display/initialize.js | 128 ++++++++++-------- .../src/videoalpha/display/video_caption.js | 20 +-- .../src/videoalpha/display/video_control.js | 110 +++++++++++---- .../js/src/videoalpha/display/video_player.js | 58 ++------ .../display/video_progress_slider.js | 30 ++-- .../display/video_quality_control.js | 13 +- .../videoalpha/display/video_speed_control.js | 23 +--- .../display/video_volume_control.js | 35 +++-- .../lib/xmodule/xmodule/videoalpha_module.py | 2 +- lms/templates/videoalpha.html | 5 +- 11 files changed, 215 insertions(+), 220 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/videoalpha/display.scss b/common/lib/xmodule/xmodule/css/videoalpha/display.scss index 879aee3f72..ee5b83d274 100644 --- a/common/lib/xmodule/xmodule/css/videoalpha/display.scss +++ b/common/lib/xmodule/xmodule/css/videoalpha/display.scss @@ -2,7 +2,7 @@ margin-bottom: 30px; } -div.video { +div.videoalpha { @include clearfix(); background: #f3f3f3; display: block; @@ -31,6 +31,15 @@ div.video { } } + section.video-roof { + background-color: green; + z-index: 10000; + width: 540px; + height: 100px; + position: absolute; + top: 387px; + } + section.video-controls { @include clearfix(); background: #333; diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js index 93e163461c..cd625672ff 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js @@ -27,6 +27,7 @@ function (bind, VideoPlayer) { state.setSpeed = bind(setSpeed, state); state.youtubeId = bind(youtubeId, state); state.getDuration = bind(getDuration, state); + state.trigger = bind(trigger, state); } // function renderElements(state) @@ -36,7 +37,7 @@ function (bind, VideoPlayer) { // way - you don't have to do repeated jQuery element selects. function renderElements(state, element) { // The parent element of the video, and the ID. - state.el = $(element).find('.video'); + state.el = $(element).find('.videoalpha'); state.id = state.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 @@ -113,8 +114,8 @@ function (bind, VideoPlayer) { state.hide_captions = true; $.cookie('hide_captions', state.hide_captions, { - expires: 3650, - path: '/' + 'expires': 3650, + 'path': '/' }); state.el.addClass('closed'); @@ -128,8 +129,8 @@ function (bind, VideoPlayer) { (function (currentPlayerMode) { if ((currentPlayerMode !== 'html5') && (currentPlayerMode !== 'flash')) { $.cookie('current_player_mode', 'html5', { - expires: 3650, - path: '/' + 'expires': 3650, + 'path': '/' }); state.currentPlayerMode = 'html5'; } else { @@ -137,39 +138,9 @@ function (bind, VideoPlayer) { } }($.cookie('current_player_mode'))); - // Will be used by various components to register callbacks that can be then called by video core, - // or other components. - state.callbacks = { - 'videoPlayer': { - 'onPlay': [], - 'onPause': [], - 'onEnded': [], - 'onPlaybackQualityChange': [], - 'updatePlayTime': [], - 'onSpeedSetChange': [] - }, - 'videoControl': { - 'togglePlaybackPlay': [], - 'togglePlaybackPause': [], - 'toggleFullScreen': [] - }, - 'videoQualityControl': { - 'toggleQuality': [] - }, - 'videoProgressSlider': { - 'onSlide': [], - 'onStop': [] - }, - 'videoVolumeControl': { - 'onChange': [] - }, - 'videoSpeedControl': { - 'changeVideoSpeed': [] - }, - 'videoCaption': { - 'seekPlayer': [] - } - }; + // Possible value are: 'visible', 'hiding', and 'invisible'. + state.controlState = 'visible'; + state.controlHideTimeout = null; // Launch embedding of actual video content, or set it up so that it will be done as soon as the // appropriate video player (YouTube or stand alone HTML5) is loaded, and can handle embedding. @@ -291,8 +262,8 @@ function (bind, VideoPlayer) { if (updateCookie !== false) { $.cookie('video_speed', this.speed, { - expires: 3650, - path: '/' + 'expires': 3650, + 'path': '/' }); } } @@ -305,7 +276,20 @@ function (bind, VideoPlayer) { return this.metadata[this.youtubeId()].duration; } - /* + /* he function .trigger() expects the parameter @callType one of + * + * 'event' + * 'method' + * + * Based on this parameter, this function can be used in two ways. + * + * + * + * First use: A safe way to trigger jQuery events. + * ----------------------------------------------- + * + * @callType === 'event' + * * Because jQuery events can be triggered on some jQuery object, we must make sure that * we don't trigger an event on an undefined object. For this we will have an in-between * method that will check for the existance of an object before triggering an event on it. @@ -321,34 +305,60 @@ function (bind, VideoPlayer) { * * object, and, if found to be present, will trigger the specified event on this object. * - * @eventName - the name of the event to trigger on the specified object. + * @eventName is a string the name of the event to trigger on the specified object. + * + * @extraParameters is an object or an array that should be passed to the triggered method. + * + * + * Second use: A safe way to call methods. + * --------------------------------------- + * + * @callType === 'method' + * + * Parameter @eventName is NOT necessary. + * + * The trigger() function will assume that the @objChain is a complete chain with a method + * (function) at the end. It will call this function. So for example, when trigger() is + * called like so: + * + * state.trigger(['videoPlayer', 'pause'], {'param1': 10}, 'method'); + * + * Then trigger() will execute: + * + * state.videoPlayer.pause({'param1': 10}); */ - function trigger(objChain, eventName, extraParameters) { - var tmpObj; + function trigger(objChain, extraParameters, callType, eventName) { + var i, tmpObj; // Remember that 'this' is the 'state' object. tmpObj = this; - getFinalObj(0); + // At the end of the loop the variable 'tmpObj' will either be the correct + // object/function to trigger/invoke. If the 'objChain' chain of object is + // incorrect (one of the link is non-existent), then the loop will immediately + // exit. + while (objChain.length > 0) { + i = objChain.shift(); - if (tmpObj === null) { + if (tmpObj.hasOwnProperty(i) === true) { + tmpObj = tmpObj[i]; + } else { + // An incorrect object chain was specified. + + return false; + } + } + + // Based on the type, either trigger, or invoke. + if (callType === 'event') { + tmpObj.trigger(eventName, extraParameters); + } else if (callType === 'method') { + tmpObj(extraParameters); + } else { return false; } - tmpObj.trigger(eventName, extraParameters); - return true; - - function getFinalObj(i) { - if (objChain.length !== i) { - if (tmpObj.hasOwnProperty(objChain[i]) === true) { - tmpObj = tmpObj[objChain[i]]; - getFinalObj(i + 1); - } else { - tmpObj = null; - } - } - } } }); diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_caption.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_caption.js index af69a81043..995d663c3f 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_caption.js @@ -13,7 +13,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -88,15 +87,9 @@ function (bind) { ); } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoPlayer.updatePlayTime.push(state.videoCaption.updatePlayTime); - state.callbacks.videoControl.toggleFullScreen.push(state.videoCaption.resize); - } - function fetchCaption(state) { + state.videoCaption.hideCaptions(state.hide_captions); + $.getWithPrefix(captionURL(state), function(captions) { state.videoCaption.captions = captions.text; state.videoCaption.start = captions.start; @@ -113,6 +106,10 @@ function (bind) { } function captionURL(state) { + console.log('We are inside captionURL() function.'); + console.log('state.config.caption_asset_path = "' + state.config.caption_asset_path + '".'); + console.log('state.youtubeId("1.0") = "' + state.youtubeId('1.0') + '".'); + return '' + state.config.caption_asset_path + state.youtubeId('1.0') + '.srt.sjson'; } @@ -257,10 +254,7 @@ function (bind) { event.preventDefault(); time = Math.round(Time.convert($(event.target).data('start'), '1.0', this.speed) / 1000); - $.each(this.callbacks.videoCaption.seekPlayer, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(time); - }); + this.trigger(['videoPlayer', 'onSeek'], time, 'method'); } function calculateOffset(element) { diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js index 2a1cfc8d7b..841e65b8d0 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js @@ -13,7 +13,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -25,6 +24,8 @@ function (bind) { // Functions which will be accessible via 'state' object. When called, these functions will // get the 'state' object as a context. function makeFunctionsPublic(state) { + state.videoControl.showControls = bind(showControls, state); + state.videoControl.hideControls = bind(hideControls, state); state.videoControl.play = bind(play, state); state.videoControl.pause = bind(pause, state); state.videoControl.togglePlayback = bind(togglePlayback, state); @@ -80,6 +81,9 @@ function (bind) { } else { state.videoControl.play(); } + + state.controlHideTimeout = setTimeout(state.videoControl.hideControls, 3000); + state.el.find('.video-roof').on('mousemove', state.videoControl.showControls); } // function bindHandlers(state) @@ -91,22 +95,82 @@ function (bind) { $(document).on('keyup', state.videoControl.exitFullScreen); } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoPlayer.onPlay.push(state.videoControl.play); - state.callbacks.videoPlayer.onPause.push(state.videoControl.pause); - state.callbacks.videoPlayer.onEnded.push(state.videoControl.pause); - state.callbacks.videoPlayer.updatePlayTime.push(state. videoControl.updateVcrVidTime); - } - // *************************************************************** // 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(). // *************************************************************** + function showControls(event) { + var elPosition, elWidth, elHeight; + + normalize(event); + + elPosition = this.el.position(); + elWidth = this.el.width(); + elHeight = this.el.height(); + + if ( + (event.pageX < elPosition.left) || + (event.pageX > elPosition.left + elWidth) || + (event.pageY < elPosition.top) || + (event.pageY > elPosition.top + elHeight) + ) { + return; + } + + if (this.controlState === 'invisible') { + this.videoControl.el.show(); + this.controlState = 'visible'; + this.controlHideTimeout = setTimeout(this.videoControl.hideControls, 3000); + }/* else if (this.controlState === 'hiding') { + this.videoControl.el.stop(true, false); + this.videoControl.el.show(); + this.controlState = 'visible'; + this.controlHideTimeout = setTimeout(this.videoControl.hideControls, 3000); + }*/ else if (this.controlState === 'visible') { + clearTimeout(this.controlHideTimeout); + this.controlHideTimeout = setTimeout(this.videoControl.hideControls, 3000); + } + + this.controlShowLock = false; + + if (this.videoPlayer && this.videoPlayer.player) { + (function (event, _this) { + var c1; + c1 = 0; + _this.el.find('#' + _this.id).children().each(function (index, value) { + $(value).trigger(event); + c1 += 1; + }); + }(event, this)); + } + + return; + + function normalize(event) { + if(!event.offsetX) { + event.offsetX = (event.pageX - $(event.target).offset().left); + event.offsetY = (event.pageY - $(event.target).offset().top); + } + + return event; + } + } + + function hideControls() { + var _this; + + this.controlHideTimeout = null; + this.controlState = 'hiding'; + + _this = this; + + this.videoControl.el.fadeOut(1000, function () { + _this.controlState = 'invisible'; + }); + } + function play() { this.videoControl.playPauseEl.removeClass('play').addClass('pause').attr('title', 'Pause'); this.videoControl.playPauseState = 'playing'; @@ -121,15 +185,9 @@ function (bind) { event.preventDefault(); if (this.videoControl.playPauseState === 'playing') { - $.each(this.callbacks.videoControl.togglePlaybackPause, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoPlayer', 'pause'], null, 'method'); } else { // if (this.videoControl.playPauseState === 'paused') { - $.each(this.callbacks.videoControl.togglePlaybackPlay, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoPlayer', 'play'], null, 'method'); } } @@ -146,11 +204,7 @@ function (bind) { this.videoControl.fullScreenEl.attr('title', 'Exit fill browser'); } - - $.each(this.callbacks.videoControl.toggleFullScreen, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoCaption', 'resize'], null, 'method'); } function exitFullScreen(event) { @@ -159,12 +213,8 @@ function (bind) { } } - function updateVcrVidTime(time, duration) { - var progress; - - progress = Time.format(time) + ' / ' + Time.format(duration); - - this.videoControl.vidTimeEl.html(progress); + function updateVcrVidTime(params) { + this.videoControl.vidTimeEl.html(Time.format(params.time) + ' / ' + Time.format(params.duration)); } }); diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js index bd34a00d98..0db33497d0 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js @@ -16,7 +16,6 @@ function (HTML5Video, bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(); - registerCallbacks(state); }; // *************************************************************** @@ -120,24 +119,6 @@ function (HTML5Video, bind) { } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoControl.togglePlaybackPlay.push(state.videoPlayer.play); - state.callbacks.videoControl.togglePlaybackPause.push(state.videoPlayer.pause); - - state.callbacks.videoQualityControl.toggleQuality.push(state.videoPlayer.handlePlaybackQualityChange); - state.callbacks.videoProgressSlider.onSlide.push(state.videoPlayer.onSeek); - state.callbacks.videoProgressSlider.onStop.push(state.videoPlayer.onSeek); - - state.callbacks.videoVolumeControl.onChange.push(state.videoPlayer.onVolumeChange); - - state.callbacks.videoSpeedControl.changeVideoSpeed.push(state.videoPlayer.onSpeedChange); - - state.callbacks.videoCaption.seekPlayer.push(state.videoPlayer.onSeek); - } - // function reinitAsFlash(state) // // When we are about to play a YouTube video in HTML5 mode and discover that we only @@ -149,8 +130,8 @@ function (HTML5Video, bind) { // Remember for future page loads that we should use Flash mode. $.cookie('current_player_mode', 'flash', { - expires: 3650, - path: '/' + 'expires': 3650, + 'path': '/' }); state.currentPlayerMode = 'flash'; @@ -214,8 +195,7 @@ function (HTML5Video, bind) { } else { this.videoPlayer.player.cueVideoById(this.youtubeId(), this.videoPlayer.currentTime); } - } - if (this.currentPlayerMode === 'flash') { + this.videoPlayer.updatePlayTime(this.videoPlayer.currentTime); } } @@ -234,10 +214,7 @@ function (HTML5Video, bind) { } function onEnded() { - $.each(this.callbacks.videoPlayer.onEnded, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoControl','pause'], null, 'method'); } function onPause() { @@ -246,10 +223,7 @@ function (HTML5Video, bind) { clearInterval(this.videoPlayer.updateInterval); delete this.videoPlayer.updateInterval; - $.each(this.callbacks.videoPlayer.onPause, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoControl','pause'], null, 'method'); } function onPlay() { @@ -259,10 +233,7 @@ function (HTML5Video, bind) { this.videoPlayer.updateInterval = setInterval(this.videoPlayer.update, 200); } - $.each(this.callbacks.videoPlayer.onPlay, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(); - }); + this.trigger(['videoControl','play'], null, 'method'); } function onUnstarted() { } @@ -276,10 +247,7 @@ function (HTML5Video, bind) { quality = this.videoPlayer.player.getPlaybackQuality(); - $.each(this.callbacks.videoPlayer.onPlaybackQualityChange, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(quality); - }); + this.trigger(['videoQualityControl', 'onQualityChange'], quality, 'method'); } function onReady() { @@ -306,10 +274,7 @@ function (HTML5Video, bind) { _this.speeds.push(value.toFixed(2).replace(/\.00$/, '.0')); }); - $.each(this.callbacks.videoPlayer.onSpeedSetChange, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(_this.speeds, _this.speed); - }); + this.trigger(['videoSpeedControl', 'reRender'], {'newSpeeds': this.speeds, 'currentSpeed': this.speed}, 'method'); this.setSpeed($.cookie('video_speed')); } @@ -346,10 +311,9 @@ function (HTML5Video, bind) { duration = this.videoPlayer.duration(); - $.each(this.callbacks.videoPlayer.updatePlayTime, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(time, duration); - }); + this.trigger(['videoProgressSlider', 'updatePlayTime'], {'time': time, 'duration': duration}, 'method'); + this.trigger(['videoControl', 'updateVcrVidTime'], {'time': time, 'duration': duration}, 'method'); + this.trigger(['videoCaption', 'updatePlayTime'], time, 'method'); } function isPlaying() { diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_progress_slider.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_progress_slider.js index ae1525781a..fe38d14382 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_progress_slider.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_progress_slider.js @@ -20,7 +20,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -60,19 +59,12 @@ function (bind) { } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoPlayer.updatePlayTime.push(state.videoProgressSlider.updatePlayTime); - } - function buildSlider(state) { state.videoProgressSlider.slider = state.videoProgressSlider.el.slider({ - 'range': 'min', + 'range': 'min', 'change': state.videoProgressSlider.onChange, - 'slide': state.videoProgressSlider.onSlide, - 'stop': state.videoProgressSlider.onStop + 'slide': state.videoProgressSlider.onSlide, + 'stop': state.videoProgressSlider.onStop }); } @@ -106,10 +98,7 @@ function (bind) { this.videoProgressSlider.frozen = true; this.videoProgressSlider.updateTooltip(ui.value); - $.each(this.callbacks.videoProgressSlider.onSlide, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(ui.value); - }); + this.trigger(['videoPlayer', 'onSeek'], ui.value, 'method'); } function onChange(event, ui) { @@ -123,10 +112,7 @@ function (bind) { this.videoProgressSlider.frozen = true; - $.each(this.callbacks.videoProgressSlider.onStop, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(ui.value); - }); + this.trigger(['videoPlayer', 'onSeek'], ui.value, 'method'); setTimeout(function() { _this.videoProgressSlider.frozen = false; @@ -137,10 +123,10 @@ function (bind) { this.videoProgressSlider.handle.qtip('option', 'content.text', '' + Time.format(value)); } - function updatePlayTime(currentTime, duration) { + function updatePlayTime(params) { if ((this.videoProgressSlider.slider) && (!this.videoProgressSlider.frozen)) { - this.videoProgressSlider.slider.slider('option', 'max', duration); - this.videoProgressSlider.slider.slider('value', currentTime); + this.videoProgressSlider.slider.slider('option', 'max', params.duration); + this.videoProgressSlider.slider.slider('value', params.time); } } diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_quality_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_quality_control.js index 97d04a496c..cc82ea9698 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_quality_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_quality_control.js @@ -18,7 +18,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -64,13 +63,6 @@ function (bind) { state.videoQualityControl.el.on('click', state.videoQualityControl.toggleQuality); } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoPlayer.onPlaybackQualityChange.push(state.videoQualityControl.onQualityChange); - } - // *************************************************************** // Public functions start here. // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object. @@ -100,10 +92,7 @@ function (bind) { newQuality = 'hd720'; } - $.each(this.callbacks.videoQualityControl.toggleQuality, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(newQuality); - }); + this.trigger(['videoPlayer', 'handlePlaybackQualityChange'], newQuality, 'method'); } }); diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_speed_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_speed_control.js index 2d2c7affba..ff0917540f 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_speed_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_speed_control.js @@ -13,7 +13,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -92,13 +91,6 @@ function (bind) { } } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - state.callbacks.videoPlayer.onSpeedSetChange.push(state.videoSpeedControl.reRender); - } - // *************************************************************** // Public functions start here. // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object. @@ -112,8 +104,6 @@ function (bind) { } function changeVideoSpeed(event) { - var _this; - event.preventDefault(); if (!$(event.target).parent().hasClass('active')) { @@ -123,21 +113,16 @@ function (bind) { parseFloat(this.videoSpeedControl.currentSpeed).toFixed(2).replace(/\.00$/, '.0') ); - _this = this; - - $.each(this.callbacks.videoSpeedControl.changeVideoSpeed, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(_this.videoSpeedControl.currentSpeed); - }); + this.trigger(['videoPlayer', 'onSpeedChange'], this.videoSpeedControl.currentSpeed, 'method'); } } - function reRender(newSpeeds, currentSpeed) { + function reRender(params /*newSpeeds, currentSpeed*/) { var _this; this.videoSpeedControl.videoSpeedsEl.empty(); this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active'); - this.videoSpeedControl.speeds = newSpeeds; + this.videoSpeedControl.speeds = params.newSpeeds; _this = this; $.each(this.videoSpeedControl.speeds, function(index, speed) { @@ -149,7 +134,7 @@ function (bind) { listItem = $('
  • ').attr('data-speed', speed).html(link); - if (speed === currentSpeed) { + if (speed === params.currentSpeed) { listItem.addClass('active'); } diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_volume_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_volume_control.js index 853db4ae06..3957734b6c 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_volume_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_volume_control.js @@ -13,7 +13,6 @@ function (bind) { makeFunctionsPublic(state); renderElements(state); bindHandlers(state); - registerCallbacks(state); }; // *************************************************************** @@ -35,8 +34,6 @@ function (bind) { // make the created DOM elements available via the 'state' object. Much easier to work this // way - you don't have to do repeated jQuery element selects. function renderElements(state) { - state.videoVolumeControl.currentVolume = 100; - state.videoVolumeControl.el = $( '
    ' + '' + @@ -51,15 +48,30 @@ function (bind) { state.videoControl.secondaryControlsEl.prepend(state.videoVolumeControl.el); + // Figure out what the current volume is. Set it up so that muting/unmuting works correctly. + // If no information about volume level could be retrieved, then we will use the default + // 100 level (full volume). + state.videoVolumeControl.currentVolume = parseInt($.cookie('video_player_volume_level'), 10); + state.videoVolumeControl.previousVolume = 100; + if ( + (isFinite(state.videoVolumeControl.currentVolume) === false) || + (state.videoVolumeControl.currentVolume < 0) || + (state.videoVolumeControl.currentVolume > 100) + ) { + state.videoVolumeControl.currentVolume = 100; + } + state.videoVolumeControl.slider = state.videoVolumeControl.volumeSliderEl.slider({ 'orientation': 'vertical', 'range': 'min', 'min': 0, 'max': 100, - 'value': 100, + 'value': state.videoVolumeControl.currentVolume, 'change': state.videoVolumeControl.onChange, 'slide': state.videoVolumeControl.onChange }); + + state.videoVolumeControl.el.toggleClass('muted', state.videoVolumeControl.currentVolume === 0); } // function bindHandlers(state) @@ -77,13 +89,6 @@ function (bind) { }); } - // function registerCallbacks(state) - // - // Register function callbacks to be called by other modules. - function registerCallbacks(state) { - - } - // *************************************************************** // Public functions start here. // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object. @@ -94,10 +99,12 @@ function (bind) { this.videoVolumeControl.currentVolume = ui.value; this.videoVolumeControl.el.toggleClass('muted', this.videoVolumeControl.currentVolume === 0); - $.each(this.callbacks.videoVolumeControl.onChange, function (index, value) { - // Each value is a registered callback (JavaScript function object). - value(ui.value); + $.cookie('video_player_volume_level', ui.value, { + 'expires': 3650, + 'path': '/' }); + + this.trigger(['videoPlayer', 'onVolumeChange'], ui.value, 'method'); } function toggleMute(event) { diff --git a/common/lib/xmodule/xmodule/videoalpha_module.py b/common/lib/xmodule/xmodule/videoalpha_module.py index 31f6a3943e..1b7d0dc1b2 100644 --- a/common/lib/xmodule/xmodule/videoalpha_module.py +++ b/common/lib/xmodule/xmodule/videoalpha_module.py @@ -96,7 +96,7 @@ class VideoAlphaModule(VideoAlphaFields, XModule): self.autoplay = xmltree.get('autoplay') or '' if self.autoplay.lower() not in ['true', 'false']: - self.autoplay = '' + self.autoplay = 'true' self.position = 0 self.show_captions = xmltree.get('show_captions', 'true') diff --git a/lms/templates/videoalpha.html b/lms/templates/videoalpha.html index 2443dbaf51..9d840630d5 100644 --- a/lms/templates/videoalpha.html +++ b/lms/templates/videoalpha.html @@ -6,14 +6,14 @@
    +