var complete = false, firstTime = true;
/* brb: New code for HTML5 brightcove video player. Processing of videos
in DF takes place in the Figures.process_media method. So we need to
rewrite it to use the new player markup and methods. */
Figures = Figures.extend({
bcVideo: {}, // holds all of the video players (by ID)
bcPlayerData: { 'accountId': '1500315202001', 'playerId': 'B1AhVYg4l' },
process_media: function() {
var context = this;
// Process each video
$("[data-mmtype='mov']").each(function() {
var $this = $(this);
var $parent = $this.parent("[data-type='figure']");
var video_mmsrc = $this.attr("data-mmsrc");
//var video_id = "vidPlayerID";
var video_id = $parent.attr("data-figure-id");
var caption = "";
var $caption = $parent.find("[data-type='caption']");
if ($caption.length == 1) {
caption = "
" + $caption.html() + "
";
}
// Replace the current figure HTML with the new HTML5 video HTML
playerHTML = '
' + caption + '
';
$parent.before(playerHTML);
$parent.remove();
// instantiate the player
bc(document.getElementById(video_id));
// create player instance and set up cuepoints
safe_log("creating video player");
videojs(video_id).ready(function() {
context.bcVideo[video_id] = this;
// reset the video to the beginning after it ends
context.bcVideo[video_id].on("ended", function() {
context.bcVideo[video_id].currentTime(0);
context.bcVideo[video_id].pause();
//$("#" + video_id).removeClass("vjs-has-started");
complete = true;
var $curr_sec = $("#digfir_section_" + player.section_currently_showing);
var $video = $curr_sec.find("[data-class='video']");
$video.addClass("restored");
var nextBtn = document.getElementById("next_button");
var prevBtn = document.getElementById("previous_button");
var slideBtn = document.getElementById("slide_number");
UI_Elements.toggle_button("step_button", true);
$(nextBtn).removeClass('button_dimmed');
nextBtn.disabled = false;
$(slideBtn).removeClass('button_dimmed');
slideBtn.disabled = false;
if( player.section_currently_showing > 0 ){
$( prevBtn ).removeClass('button_dimmed');
prevBtn.disabled = false;
}
var s = player.get_current_section();
s.video_is_ended = true;
player.update_section_status();
player.update_navigation();
});
context.bcVideo[video_id].on("play", function() {
//$("#" + video_id).addClass("vjs-has-started");
});
}); //end ready
});
}
});
function initVideo(fig_id) {
safe_log("initVideo");
var section = player.sections[ player.section_currently_showing ];
var figureId = section.jq.find( '[data-class="video"]' ).data( 'figure-id' );
if (fig_id !== undefined) {
figureId = fig_id;
}
safe_log("initVideo: figureID = " + figureId);
// brb: if a fig_id was passed in we just need to do a few things
if (fig_id !== undefined) {
$("[data-figure-id='" + figureId + "']").addClass("restored").css('display', 'block');
return;
}
/*
var videoPlayer = brightcove.api.getExperience( figureId );
if( !videoPlayer ){ return }
var playerModule = videoPlayer.getModule( brightcove.api.modules.APIModules.VIDEO_PLAYER );
playerModule.seek( 0 );
playerModule.addEventListener( brightcove.api.events.MediaEvent.COMPLETE, function() {
complete = true;
safe_log("video complete");
var $curr_sec = $("#digfir_section_" + player.section_currently_showing);
var $video = $curr_sec.find("[data-class='video']");
$video.addClass("restored");
var nextBtn = document.getElementById("next_button");
var prevBtn = document.getElementById("previous_button");
var slideBtn = document.getElementById("slide_number");
UI_Elements.toggle_button("step_button", true);
$(nextBtn).removeClass('button_dimmed');
nextBtn.disabled = false;
$(slideBtn).removeClass('button_dimmed');
slideBtn.disabled = false;
if( player.section_currently_showing > 0 ){
$( prevBtn ).removeClass('button_dimmed');
prevBtn.disabled = false;
}
var s = player.get_current_section();
s.video_is_ended = true;
player.update_section_status();
player.update_navigation();
});
*/
var nextBtn = document.getElementById("next_button");
var prevBtn = document.getElementById("previous_button");
var slideBtn = document.getElementById("slide_number");
// brb: have all questions on page been answered correctly
var all_answers_correct = true;
var $curr_sec = $("#digfir_section_" + player.section_currently_showing);
$curr_sec.find("[data-type='question']").each(function() {
var $this = $(this);
var q_idx = $this.attr("data-question_index");
var question = player.activity.questions[q_idx];
for (var j = 0; j < question.queries.length; ++j) {
var query = question.queries[j];
safe_log(query);
if (query.isCorrect() == false) {
all_answers_correct = false;
}
}
});
safe_log("all_answers_correct = " + all_answers_correct);
if (all_answers_correct) {
$("[data-figure-id='" + figureId + "']").addClass("restored");
}
$(nextBtn ).removeClass('button_dimmed');
$( slideBtn ).removeClass('button_dimmed');
nextBtn.disabled = false;
slideBtn.disabled = false;
if( player.section_currently_showing > 0 ){
$( prevBtn ).removeClass('button_dimmed');
prevBtn.disabled = false;
}
var s = player.get_current_section();
s.video_is_ended = true;
player.update_section_status();
player.update_navigation();
}
Activity_manuscript_type = Activity_manuscript_type.extend({
// This function goes through all questions (from all sections)
// and restores answers from previous sessions that are retrieved via ARGA.
// The function needs to be kept "in synch" with submit_question, so that everything
// done in submit_question gets done here.
restore_saved_answers: function() {
// skip page queries (questions[0])
for (var i = 1; i < this.questions.length; ++i) {
var question = this.questions[i];
// prepare for question_report_text questions
var query_responses;
if (question.md_set("question_report_text")) {
query_responses = "" + Get_ARGA_QuestionData(this.get_question_number(question))
query_responses = query_responses.split(this.query_responses_separator);
}
var restored_all_answers = true;
var all_answers_correct = true;
for (var j = 0; j < question.queries.length; ++j) {
var query = question.queries[j];
var saved_answer, saved_grade;
// get saved answer and grade out of the questionData for question_report_text questions
if (question.md_set("question_report_text")) {
if (query_responses[j] != null) {
var arr = query_responses[j].split(this.query_responses_grade_separator);
saved_answer = arr[0];
saved_grade = arr[1];
} else {
saved_grade = saved_answer = "";
}
// or out of learnerResponse / questionData for single-query questions
} else {
var ARGA_question_number = this.get_query_number(question, j);
saved_answer = Get_ARGA_LearnerResponse(ARGA_question_number);
// we stored the original grade in questionData
saved_grade = Get_ARGA_QuestionData(ARGA_question_number)
}
// if we found a grade...
if (saved_grade !== "" && saved_grade >= 0) {
// restore the answer
query.restoreAnswerFromARGA(saved_answer);
query.setGrade(saved_grade);
// then re-render the query in review mode
query.jq.html(query.getHTML("review"));
if (query.isCorrect() == false) {
all_answers_correct = false;
}
} else {
restored_all_answers = false;
}
}
if (restored_all_answers) {
// update the submit div for the question
this.update_question_action_div(i);
// Show appropriate feedback. If the question responses were submitted,
// the student must have finished the question, so we don't have to worry
// about hints.
this.show_question_feedback(question, all_answers_correct, false);
// if the item is in a sequence, show the next question
this.show_next_question(question);
// NEED TO CHECK TO MAKE SURE THIS IS WORKING PROPERLY
// If the question is in a sequence and the sequence is complete, call show_closing_material
var qs = question.question_sequence;
if (qs != null && qs.sequence_complete == "partial") {
this.show_closing_material(qs.index);
}
// update section status
player.update_section_status();
// if there is a video with this question then show it
var video = question.jq.next( '[data-class="video"]' );
if (video.length > 0) {
safe_log("found video for completed question " + question.index);
question.jq.after(video);
video.show();
//safe_log("adding restored class to " + video.attr('data-figure-id'));
video.addClass("restored");
}
//question.jq.addClass("answered");
}
} // end for each question
},
init: function(){
var title = document.querySelector('h1.section-title');
var childs = title.childNodes;
for ( var i = 0; i < childs.length - 1; ++i ){
var node = childs[ i ];
if ( node.nodeType === 3 && jQuery.trim( node.textContent ) === '.') {
title.removeChild( node );
}
}
},
/* brb: need to override this method so we can remove the grade percentage
from the completed message pop-up */
ARGA_initialization_alert: function() {
// This overrides the standard ARGA initialization message, which doesn't
// tell the user he/she can resubmit (or tell him his grade)
// brb: get the correct arga grade (also, see first "if" below)
//var grade = Get_ARGA_Grade();
var grade = Get_Correct_ARGA_Grade();
var due_date_passed = (Get_ARGA_Data("due_date_has_passed") == "1");
var msg = "";
var buttons;
due_date_passed = false;
safe_log("ARGA_initialization_alert: grade = " + grade);
safe_log(ARGA_API);
// brb: first comparison must use strict equality otherwise "" is converted
// to 0 which will return false if grade is actually 0
if (grade !== "" && grade != null && grade >= 0) {
// if resubmissions are allowed...
if (player.md.allow_resubmission == "true") {
// if due date has not passed, give the student the option of resubmitting or reviewing
if (!due_date_passed) {
msg = "
You have completed this activity, and your grade (" + grade + "%) has been submitted. Would you like to:
"
+ "
Keep your current grade and review your previous answers
"
+ "
Or reset your submission and try the activity again?
You have completed this activity, and your grade (" + grade + "%) has been submitted. Since the due date for the activity has now passed, you cannot re-submit answers to the activity questions.
"
buttons = [ {text:"OK", click: player.activity.ARGA_initialization_final} ];
}
// resubmissions are not allowed
} else {
// brb: Don't show grade percentage in this message since the
// instructor may have manually changed the grade in the grade
// book and we currently have no way of knowing what it is.
msg = "
You have completed this activity.
"
;
buttons = [ {text:"OK", click: player.activity.ARGA_initialization_final} ];
}
// grade has not been submitted
} else {
// if due date has passed, tell the user "tough luck". Otherwise show nothing.
if (due_date_passed) {
msg = "
The due date for this activity has passed. You can still review the activity, but no answers will be submitted and no grade will be recorded.
"
;
buttons = [ {text:"OK", click: player.activity.ARGA_initialization_final} ];
}
}
// if we need a message, show it in a jquery UI dialog
if (msg != "") {
msg = "
" + msg + "
";
$("body").append(msg);
$("#arga_init_dialog").dialog({title:"Please Note", width:450, modal:true, buttons: buttons});
} else {
player.activity.ARGA_initialization_final();
}
},
submit_question: function(question_index) {
// the arg may be a number or an event object; in the latter case...
if (typeof question_index == "object") {
// extract the question_index from the object
question_index = question_index.data.question_index;
}
var question = player.activity.questions[question_index];
//force all queries to be answered before doing anything
for (var i=0; i < player.activity.questions[question_index].queries.length; i++) {
var query = player.activity.questions[question_index].queries[i];
var answered = query.user_has_answered();
if (!answered) {
//question.display_alert_mesg();
Standard_Dialog.alert("You must answer the question before submitting.");
//alert("You must answer the question before submitting.");
return false;
}
}
this._super(question_index);
UI_Elements.toggle_button("step_button", false);
complete = false;
firstTime = true;
var video = $('[data-section-index=' + player.section_currently_showing + ']').find('[data-class="video"]');
video.show();
var nextBtn = document.getElementById("next_button");
var prevBtn = document.getElementById("previous_button");
var slideBtn = document.getElementById("slide_number");
if ( !complete ) {
$(nextBtn ).addClass('button_dimmed');
$( slideBtn ).addClass('button_dimmed');
nextBtn.disabled = true;
slideBtn.disabled = true;
if( player.section_currently_showing > 0 ){
$( prevBtn ).addClass('button_dimmed');
prevBtn.disabled = true;
}
}
var s = player.get_current_section();
if ( firstTime ) {
firstTime = false;
setTimeout( initVideo, 3000);
}
}
});
MC_Query = MC_Query.extend({
user_has_answered: function () {
if ($('input:radio[name=query_answer_' + this.query_index + ']:checked').val() !== undefined) {
return true;
}
else {
return false;
}
},
correct_incorrect_feedback: function(mode, is_correct) {
var html = "";
// get correct answer as presented to user
for (var i = 0; i < this.choices.length; ++i) {
if (this.choice_order[i] == this.correct_answer_index) {
break;
}
}
// if the question explicitly defines feedback for the user's answer, use it as the feedback
if (this.user_answer_index != null && this.choices_fb[this.user_answer_index] != null) {
html += this.choices_fb[this.user_answer_index];
}
// the correct answer will be highlighted in green, so there's no reason to say anything more.
// now, if we got any feedback, enclose it in a div
if (html != "") {
html = "
Feedback
" + html + "
";
}
return html;
}
});
var FB_Query = Query.extend({
// ========================================
// define and set defaults for variables specific to this question type
user_answer: "",
user_has_answered: function () {
var answer = $("input#query_answer_" + this.query_index).val();
if (answer === undefined || answer === null || answer.length == 0 || !/\S/.test(answer)) {
return false;
}
else {
return true;
}
},
// fn to be used for comparing answers
answer_transform: function(s) {
s = "" + s;
// lower case
s = s.toLowerCase();
// remove leading and trailing spaces
s = jQuery.trim(s);
// remove dashes and spaces not at the start of the string
s = s.replace(/(.+)[\s-]/g, "$1");
// return s
return s;
},
// ========================================
// initialization
parseSource: function() {
// lines might start with "FB:"; if so, strip it out
var s = this.query_source.replace(/^FB:\s*/, "");
// if line ends with "~~\d+", that's points
if (s.search(/(.*)~~([\.\d]+)$/) > -1) {
s = RegExp.$1;
this.points_possible = RegExp.$2;
}
// split and go through the lines
var lines = s.split(this.line_separator);
this.query_text = "";
for (var i = 0; i < lines.length; ++i) {
// get line and trim
var l = jQuery.trim(lines[i]);
// points_possible
if (l.search(/^_points:\s*(\d+)/i) > -1) {
this.points_possible = RegExp.$1;
// answer
} else if (l.search(/^\*\s*(.*)/i) > -1) {
var ans = RegExp.$1;
// if answer starts with "!!", it's case sensitive
if (ans.substr(0, 2) == "!!") {
this.md.case_sensitive = "true";
// strip the !! out of answer
ans = ans.substr(2);
}
// if answer ends with "??", any answer is correct
// (there should still be a "sample" answer specified)
if (ans.substr(-2, 2) == "??") {
this.md.no_correct_answer = "true";
// strip the ?? out of answer
ans = ans.replace(/\?\?$/, "");
}
// if answer ends with "##\d+", that's the blank size
if (ans.search(/\#\#(\d+)$/) > -1) {
this.md.blank_size = RegExp.$1;
ans = ans.replace(/\#\#\d+$/, "");
}
// take out anything in parens and replace common entities
//ans = ans.replace(/\s*\(.*?\)/g, "");
ans = ans.replace(/ *\– */g, "-");
ans = ans.replace(/ *\ */g, " ");
// split multiple answers, which can be specified with "_"'s
// first deal with escaped _'s
ans = ans.replace(/\\_/g, "_");
this.answers = ans.split(/_/);
// clean up answers
for (var j = 0; j < this.answers.length; ++j) {
// Replace _s with literal "_"s in correct answers so they match user input
this.answers[j] = jQuery.trim(this.answers[j].replace(/\_/g, "_"));
}
// the "official" correct answer is the first answer
this.correct_answer = this.answers[0];
// see if the answer is numeric or string
if (isNaN(this.correct_answer * 1)) {
this.answerType = "string";
} else {
this.answerType = "numeric";
}
// If the immediately-following line contains *only* a number,
// its points_possible
if (lines[i+1] != null && lines[i+1].search(/^\d+$/) > -1) {
this.points_possible = lines[i+1]*1;
i += 1;
}
// metadata -- starts with "_[a-zA-Z]"
} else if (l.search(/^\_[a-zA-Z]/) > -1) {
this.extractMetadata(l);
// by default add it to the query text
} else {
this.query_text += l + "\n";
}
}
// now we should be done with the query text. Strip spaces
this.query_text = jQuery.trim(this.query_text);
},
// ========================================
// extend query functions
setQueryData: function(qd) {
this._super(qd);
// for fb questions, if we get question_data, that's the user's answer
this.user_answer = qd;
},
restoreAnswerFromARGA: function(answer) {
// for fb questions, the user's answer is stored directly
this.user_answer = answer;
},
getQueryTypeForARGA: function() {
return 'fill-in-the-blank';
},
getCorrectAnswerForARGA: function() {
return this.correct_answer;
},
getUserAnswerForARGA: function() {
if (this.user_answer == null || this.user_answer == "") {
return "Not answered";
} else {
return this.user_answer;
}
},
// mode should be "delivery" or "review" or "review_correct_incorrect"; "delivery" is assumed
getHTML: function(mode) {
var html = "";
// start with the query text, if there is any
html += this.query_text_html();
// determine how big the response blank should be, unless one was specified
//var blank_size = this.md.blank_size;
//if (blank_size == "" || blank_size == null || isNaN(blank_size * 1)) {
// var s = "" + this.correct_answer;
// blank_size = (s.length + 2);
//}
var blank_size = 10;
// if student hasn't answered or we're in preview mode, use an empty string for the input value
var val, disabled;
var fb_string = "";
if (!this.userHasAnswered() || mode == 'preview') {
val = "";
disabled = "";
// otherwise we have an answer, so fill it in
} else {
// make sure we convert double quotes to " for placement in 'value="xxx"' attributes
val = this.user_answer.replace(/\"/g, """);
// also disable the input in this case, if we're not in review_correct_incorrect mode
// or if the user got it right
if (mode != "review_correct_incorrect" || this.isCorrect()) {
disabled = "disabled";
}
}
blank_size = 10;
html += ''
+ ''
;
html += this.finish_inline_query(this.correct_answer, mode);
html += '';
return html;
},
evaluateAnswer: function() {
this.user_answer = jQuery.trim($("#query_answer_" + this.query_index).val());
var is_correct = false;
// if there's no one correct answer, any answer is correct!
if (this.md.no_correct_answer == "true" || this.answers == null) {
is_correct = true;
// MT: 2013-08-22 fix as perPpepper's suggestion for DF-26
// NEXT ELSE IF IS NEW CODE
// assume that an empty string is never correct
} else if (this.user_answer === "") {
is_correct = false;
} else {
for (var i = 0; i < this.answers.length; ++i) {
var ca_comp = this.answers[i];
var sa_comp = this.user_answer;
// if this is *not* case sensitive...
if (this.md.case_sensitive != "true") {
// convert to lower case
ca_comp = ca_comp.toLowerCase();
sa_comp = sa_comp.toLowerCase();
// if ca_comp is a number and case_sensitive is false...
if (!isNaN(ca_comp * 1)) {
// MOVE THIS TO ANOTHER FUNCTION SO WE CAN USE IT ELSEWHERE
// see how many decimal places ca_comp has
var dec = ca_comp.replace(/.*\.(.*)/, "$1");
var factor = Math.pow(10, dec.length);
// convert ca_comp to a number
ca_comp = ca_comp * 1;
// convert sa_comp to a number and round to the given number of places
sa_comp = Math.round(factor * sa_comp) / factor;
}
}
// now evaluate against this answer
if (sa_comp == ca_comp) {
is_correct = true;
break;
}
}
}
// set grade accordingly
if (is_correct) {
this.setGrade(100);
} else {
this.setGrade(0);
}
return true;
}
});
/*
var FIO_Figures = Figures.extend({
process_media: function() {
//AF: this is less than ideal, but i had to make this a global variable so it can be accessed by the video players when they fire the templateloaded event.
// we should look into changing it.
videos.templateReady = function (figureObjectID) {
var vidplayer = brightcove.api.getExperience(figureObjectID);
var experienceModule = vidplayer.getModule(brightcove.api.modules.APIModules.EXPERIENCE);
var playerModule = vidplayer.getModule(brightcove.api.modules.APIModules.VIDEO_PLAYER);
var el = document.querySelector("[data-figure-id="+ figureObjectID +"]");
el.style.position = "relative";
var playBtn = document.createElement("div"),
iconBtn = document.createElement("div"),
textBtn = document.createElement("p");
playBtn.className = "playBtn-sub";
iconBtn.className = "icon-play_button";
textBtn.innerHTML = "PLAY";
playBtn.appendChild( iconBtn );
playBtn.appendChild( textBtn );
var substrate = document.createElement("div");
substrate.className = "play-substrate";
var playNode = document.createElement("div");
playNode.className = "play";
playNode.appendChild( playBtn );
playBtn.addEventListener( "click", function(){
playerModule.play();
setTimeout( function(){
substrate.style.display = "none";
}, 200);
});
substrate.appendChild( playNode );
el.appendChild( substrate );
var questionSequence = $("#" + figureObjectID).closest('[data-type="figure"]').nextAll('[data-block_type="question_sequence"], [data-block_type="question_sequence_one_at_a_time"]');
questionSequence.each(function (index, element) {
if ($(element).attr("data-block_type") == "figure") {
if ($(element).find(".BrightcoveExperience").size() > 0) { //we have found another video following the current one, so stop
return false;
}
}
var questionSequenceIndex = $(element).attr("question_sequence_index");
var questionSequenceMetaData = $(element).find('[data-type="box_inner"]').children('[data-type="metadata"]').find('[key="cuepoint"]').html();
$(element).hide();
if (questionSequenceMetaData != null) {
var cuePointsModule = vidplayer.getModule(brightcove.api.modules.APIModules.CUE_POINTS);
var CuePointType = brightcove.api.modules.CuePointsModule.CuePointType;
var cuePoints = [{ name: figureObjectID, metadata: questionSequenceIndex, time: questionSequenceMetaData, type: CuePointType.CODE }];
cuePointsModule.addCuePoints(videos[figureObjectID], cuePoints);
videos.question_sequence_to_video_map[questionSequenceIndex] = figureObjectID;
}
});
playerModule.addEventListener(brightcove.api.events.CuePointEvent.CUE, videos.cuePointEvent);
};
videos.cuePointEvent = function (e) {
//get the player - the name property of the cuePoint is set to the ID of the Brightcove experience
//so we can find the player here.
var vidplayer = brightcove.api.getExperience(e.cuePoint.name);
globalPlayer = brightcove.api.getExperience(e.cuePoint.name);
safe_log("got vid player");
var playerModule = vidplayer.getModule(brightcove.api.modules.APIModules.VIDEO_PLAYER);
safe_log("got module");
playerModule.pause(true);
safe_log("paused");
player.show_question_sequence(e.cuePoint.metadata, false);
};
$("[data-mmtype='mov']").each(function(index, element) {
var jq = $(element);
var id = jq.attr("data-figure-id");
var mmsrc = jq.attr("data-mmsrc");
var src = jq.attr("src");
var attr = jq.attr("data-attr");
if (attr == null) attr = "";
attr = attr.split(/\s*,\s/);
var params = new Object();
for (var i = 0; i < attr.length; ++i) {
var a = attr[i].split(/\s*=\s/);
params[a[0]] = a[1];
safe_log("added param " + a[0] + ": " + a[1]);
}
params.autoStart = jq.attr("data-autoplay");
var videoPlayerID = "";
var videoPlayerKey = "";
//if(params.showVideoControls == 'true'){
//AF: This is the video player with playback controls. We are only using this one for right now.
videoPlayerID = "1513003547001";
if(jq.attr("data-playerid")){
videoPlayerID = jq.attr("data-playerid");
}
videoPlayerKey = "AQ~~,AAABXVHBMdE~,bnY9CM55Z1MLPZuidy4KYEC_16wi-U8Q";
//}else{
// videoPlayerID = "1504927982001";
// videoPlayerKey = "AQ~~,AAABXVHBMdE~,bnY9CM55Z1PiqOYprq-NHmUPG2yKZ4U-";
//}
videos[id] = mmsrc;
var BCL = {};
BCL.markup = function (html, data) {
var m;
var i = 0;
var match = html.match(data instanceof Array ? /{{\d+}}/g : /{{\w+}}/g) || [];
while (m = match[i++]) {
html = html.replace(m, data[m.substr(2, m.length-4)]);
}
return html;
};
videos.templateLoad = function(e){
//AF: For now, we are not using captions.
var vidplayer = brightcove.api.getExperience(e);
var CuePointType = brightcove.api.modules.CuePointsModule.CuePointType;
var modExp = vidplayer.getModule(brightcove.api.modules.APIModules.EXPERIENCE);
modExp.addEventListener(brightcove.api.events.ExperienceEvent.TEMPLATE_READY, function (evt) { videos.templateReady(e); });
//captionsModule.loadDFXP(player.md.video_caption_url + videos[e] + ".xml", videos[e]);
//if needed, we can use these events to trigger code upon the success or error of loading captions.
//if there is an error, it fails silently and just doesn't show captions.
//captionsModule.addEventListener(brightcove.api.events.CaptionsEvent.DFXP_LOAD_SUCCESS, onDFXPLoadSuccess);
//captionsModule.addEventListener(brightcove.api.events.CaptionsEvent.DFXP_LOAD_ERROR, onDFXPLoadError);
};
BCL.playerData = { "playerID" : videoPlayerID,
"playerKey" : videoPlayerKey,
"width" : jq.width(),
"height" : jq.height(),
"videoID" : mmsrc,
"autoStart" : params.autoStart};
BCL.playerTemplate = "";
var playerHTML = "";
playerHTML = BCL.markup(BCL.playerTemplate, BCL.playerData); //replaces placeholders with values
jq.replaceWith(playerHTML);
brightcove.createExperiences();
});
}
});
*/
var player_ = Player_manuscript_type.extend({
ACTIVITY_COMPLETED: false,
DUE_DATE_HAS_PASSED: false,
initialize2: function () {
this._super();
// brb: Need to set allowfullscreen to true on parent iframe so videos
// can go to full screen
$('#document-body-iframe', window.parent.document).attr('allowfullscreen', 'true').attr('mozallowfullscreen', 'true').attr('webkitallowfullscreen', 'true');
// brb: set ACTIVITY_COMPLETED
if (player.ARGA_running) {
try {
var dejs_arr = ARGA_API.dejs_data;
for (var i=0; iPlease note: The due date for this assignment has now passed. You may review the materials in the activity but you will not be able to submit answers for a grade.");
}
});
// disable all questions
$('[data-type="question"]').each(function() {
var $this = $(this);
//xBookUtils.debug("Disabling question " + $this.attr('id'));
//$this.children('.question_action_div').remove();
$this.find('input[type="radio"]').attr("disabled",true);
$this.find('textarea').attr("disabled",true);
$this.find('input').attr("disabled",true);
//$this.find('.query_matching_item').unbind('click').removeClass('active');
});
$('[data-block_type="reveal_video"]').addClass("watched");
alert("The due date for this assignment has now passed. You may review the materials in the activity but you will not be able to submit answers for a grade.");
// display all videos
$("[data-class='video']").each(function() {
var fig_id = $(this).attr('data-figure-id');
initVideo(fig_id);
});
}
},
initialize: function() {
// hide section numbers and titles
$("h2").hide();
// also get rid of chapter numbers in question numbers
$("[data-type=question]").find("h3").each(function(index, element) {
var html = $(this).html();
html = html.replace(/^Question/, "");
html = html.replace(/\d+\.(\d+)/, "");
$(this).html(html);
});
// activity title is data-type="title" inside h1
this.activity_title = $("h1").find("[data-type=title]").html();
$('[data-type=table_text]').hide();
// extract thumbnail
var jq = $('[data-block_type="thumbnail"]');
this.activity_thumbnail_src = jq.find("img").attr("src");
jq.hide();
// assign classes to chapter
$("[data-type='chapter']").addClass("ui-widget-content").addClass("ui-corner-all");
this._super();
//this.figures = new FIO_Figures();
this.figures = new Figures();
// after we call this.super, re-initialize the activity to the custom
// activity type for this manuscript
this.activity = new Activity_manuscript_type();
},
update_section_status: function() {
if (this.section_currently_showing != null && this.last_available_section <= this.section_currently_showing) {
var s = this.get_current_section();
s.all_questions_answered = true;
// if the current section has any questions, see if they've all been answered
var qs_to_check = [];
s.jq.find("[data-type=question]").each(function(index, element) {
var q_index = $(element).attr("data-question_index");
var question = player.activity.questions[q_index];
s.all_questions_answered = s.all_questions_answered && question.is_complete();
if (question.question_sequence != null) {
for (var i = 0; i < qs_to_check.length; ++i) {
if (qs_to_check[i] == question.question_sequence) break;
}
if (i == qs_to_check.length) {
qs_to_check.push(question.question_sequence);
}
}
});
// now check question sequences to make sure they're done too
s.all_question_sequences_completed = true;
for (var i = 0; i < qs_to_check.length; ++i) {
s.all_question_sequences_completed = s.all_question_sequences_completed && (qs_to_check[i].sequence_complete == "complete");
}
if (s.all_questions_answered && s.all_question_sequences_completed && s.video_is_ended) {
this.last_available_section = this.section_currently_showing + 1;
}
}
this.fill_in_previous_query_responses();
// if ARGA is initialized and we need to restore the user to his last position when he returns,
if (this.ARGA_running && player.md.restore_last_viewed_section == "true") {
// if we're viewing a page other than the one currently saved as LVS (last-viewed section)
var lvs = Get_ARGA_Data("LVSX");
if (this.section_currently_showing != null && this.section_currently_showing != lvs) {
// store LVS/LAS to register the last-viewed/last-available page,
// and save ARGA so it gets registered
Set_ARGA_Data("LVSX", this.section_currently_showing);
Set_ARGA_Data("LASX", this.last_available_section);
/* brb: If the activity has not been completed then save LVSX, but if
it has been completed then do not save LVSX because that will also
send the grade to the PX grade book again, overwriting any manual
grade changes the instructor may have made. */
/* brb: also don't want to do this if the due date has passed */
if (!this.ACTIVITY_COMPLETED && !this.DUE_DATE_HAS_PASSED) {
this.activity.ARGA_submit_data(false);
}
}
}
},
show_section: function(section_to_show) {
safe_log("show_section: " + section_to_show);
if (player.ARGA_running) {
var las = Get_ARGA_Data("LASX");
if (las === undefined || las === null || las === "") {
las = 0;
}
safe_log("LASX = " + las);
}
$('video').each(function() {
this.pause();
});
this._super(section_to_show);
var curr_sec = player.section_currently_showing;
safe_log("show_section: section_currently_showing = " + curr_sec);
if (curr_sec <= las && percentQuestionsAnsweredInSection(curr_sec) == 1) {
safe_log("show_section: all questions on this page have been answered");
var $video = $("#digfir_section_" + curr_sec).find("[data-class='video']");
$video.show();
if ($video.length > 0) {
setTimeout( initVideo, 1000);
}
}
resize_iframe();
},
show_toc: function() {
$("#toc_dialog").remove();
var html = "";
for (var i = 0; i < this.sections.length; ++i) {
var s = this.sections[i];
var extra_style = "";
// brb: need to take into account the period between answering the
// question and watching the video (if necessary)
var prev_unwatched_video = false;
if (i > 0) {
var p_sec = i-1;
var $prev_sec = $("#digfir_section_" + p_sec);
var $video = $prev_sec.find("[data-class='video']");
if ($video.length) {
if (!$video.hasClass("restored")) {
prev_unwatched_video = true;
}
}
}
// brb: also check if this is an instructor or the due
// date has passed
if (this.md.sequenced_sections == "true" && i > this.last_available_section && !player.activity.is_instructor() && !this.DUE_DATE_HAS_PASSED) {
extra_style = "toc_section_not_available";
html += "
"
+ (i+1) + ". "
+ s.title
+ "
"
;
}
// when we click the submit button the last_available_section automatically
// increases by 1 but we may not have watched the video yet, so we need a
// special check for this case
else if (this.md.sequenced_sections == "true" && i == this.last_available_section && !player.activity.is_instructor() && !this.DUE_DATE_HAS_PASSED && prev_unwatched_video) {
extra_style = "toc_section_not_available";
html += "
"
+ (i+1) + ". "
+ s.title
+ "
"
;
}
else {
html += "
"
+ (i+1) + ". "
+ s.title
+ "
"
;
}
}
html = "
Click on a slide to view it. Note: Grey slides are not accessible until preceding slides have been viewed or completed.
"
+ html
html = "
" + html + "
";
$("body").append(html);
$("#toc_dialog").dialog({title:"Table of Contents", width:450, modal:true, buttons: [ {text:"OK", click: function() {$("#toc_dialog").dialog("close");}}]});
},
update_navigation: function() {
var s = this.get_current_section();
var nextBtn = document.getElementById("next_button");
safe_log("update_navigation");
// brb: This is a hack.
// brb: determine if due date has passed for assignment
// Note: If you don't want all the due date fixes for this activity then
// just comment out this if statement.
if (player.ARGA_running) {
if (Get_ARGA_Data("due_date_has_passed") == 1) {
this.DUE_DATE_HAS_PASSED = true;
}
safe_log("DUE_DATE_HAS_PASSED = " + this.DUE_DATE_HAS_PASSED);
}
// for for any 'submitted' videos (question has been answered but
// video has not been watched
var $sub_video = $("#digfir_section_" + this.section_currently_showing).find("[data-class='video']:not('.restored')");
safe_log($sub_video);
// show/hide the "next" button as appropriate
//if (this.last_available_section > this.section_currently_showing && this.showing_last_section() == false && s.video_is_ended) {
if (this.last_available_section > this.section_currently_showing && this.showing_last_section() == false && $sub_video.length === 0) {
UI_Elements.toggle_button("step_button", true);
$(nextBtn ).removeClass('button_dimmed');
nextBtn.disabled = false;
} else {
safe_log("disabling next button (1)");
UI_Elements.toggle_button("step_button", false);
$(nextBtn ).addClass('button_dimmed');
nextBtn.disabled = true;
}
// brb: always show next buttons if due date has passed
if (this.DUE_DATE_HAS_PASSED && this.showing_last_section() == false) {
UI_Elements.toggle_button("step_button", true);
$(nextBtn ).removeClass('button_dimmed');
nextBtn.disabled = false;
}
if (this.showing_last_section() && player.activity.answered_all_queries) {
player.show_completion_message();
}
resize_iframe();
},
show_navigation: function() {
var html = "
";
if (this.activity_thumbnail_src != null) {
html += "";
}
html += "
" + this.md.activity_type_title + "
"
+ "
" + this.activity_title + "
"
+ "
" // top_banner
;
if (this.sections.length > 1 && this.md.hide_toolbar != "true") {
html += "
" // toolbar
;
}
var $chapter = $("[data-type=chapter]");
$chapter.prepend(html);
// button at the bottom of the manuscript to go on to the next step
var $footer = $('
').appendTo($chapter).addClass('activity_footer');
$footer.append(UI_Elements.get_button_html({
id: "step_button",
label: "Next",
fn: 'player.show_section("next")'
}));
// icons for toolbar and next buttons...
$('#previous_button').button({
icons: {
primary: "ui-icon-circle-triangle-w"
}
});
$('#next_button').button({
icons: {
secondary: "ui-icon-circle-triangle-e"
}
});
$('#slide_number').button({
icons: {
secondary: "ui-icon-circle-triangle-s"
}
});
$('#step_button').button({
icons: {
secondary: "ui-icon-circle-triangle-e"
}
});
// activate all other buttons
UI_Elements.activate_buttons();
}
});
window.player = new player_();
//player.figures = new FIO_Figures();
// brb: This returns 1 if all questions are answered in the section (or if there are
// no questions in the section), otherwise it returns the percentage of questions
// answered in the section.
function percentQuestionsAnsweredInSection(section_index) {
safe_log("percentQuestionsAnsweredInSection: section_index = " + section_index);
var num_questions = 0;
var questions_answered = 0;
var $sec = $('[data-section-index="' + section_index + '"]');
$sec.find('[data-type="question"]').each(function() {
num_questions++;
var q_index = $(this).attr('data-question_index');
if (player.activity.questions[q_index].is_complete()) {
questions_answered++;
}
});
if (num_questions == 0 || (num_questions == questions_answered)) {
safe_log("percentQuestionsAnsweredInSection: returning " + 1 + " for sec index " + section_index);
return 1;
}
safe_log("percentQuestionsAnsweredInSection: returning " + (questions_answered/num_questions) + " for sec index " + section_index);
return (questions_answered/num_questions);
}
// brb: There is a bug in Get_ARGA_Grade (it returns -1 when the grade is 0 due to
// use of lenient equality instead of strict equality.
function Get_Correct_ARGA_Grade() {
if (!ARGA_API || ARGA_API.grade === null || ARGA_API.grade === "") {
return -1
}
else {
return ARGA_API.grade
}
}
function resize_iframe() {
safe_log("executing resize_iframe");
var iFrame = $('#document-body-iframe', parent.document.body);
var body_height = $(document.body).height();
iFrame.height(body_height + 30);
$('body').click();
}