var disableTouchZooming = function() {
'use strict';
var head = document.head || document.querySelector( 'head' );
var firstChild = head.firstChild;
var meta = document.createElement( 'meta' );
meta.setAttribute( 'name', 'viewport' );
meta.setAttribute( 'content', 'initial-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width' );
if ( firstChild ) {
head.insertBefore( meta, firstChild );
}
else {
head.appendChild( meta );
}
};
Figures = Figures.extend({
process_media: function () {
// we're not currently using this (jwplayer is not being included)
$("[data-mmtype='mp3']").each(function (index, element) {
var jq = $(element);
var id = jq.attr("data-figure-id");
var mmsrc = jq.attr("data-mmsrc");
// http://www.longtailvideo.com/jw/upload/bunny.mp3
// http://www.youtube.com/embed/CsGYh8AacgY
var src = jq.attr("src");
var attr = jq.attr("data-attr");
if (attr == null) attr = "";
attr = attr.split(/\s*,\s*/);
var params = new Object();
params.width = jq.width();
params.height = jq.height() + 24; // 24 is for the controler at the bottom
params.file = mmsrc;
params.image = src;
params.controlbar = "bottom";
params.screencolor = "ffffff";
params["viral.allowmenu"] = "false";
params["viral.onpause"] = "false";
params["viral.oncomplete"] = "false";
// determine url of flashplayer based on whether we're published or not
if (UI_Elements.in_preview_mode()) {
params.flashplayer = "/js/preview/player.swf";
} else {
params.flashplayer = "js/player.swf";
}
safe_log(params.flashplayer);
for (var i = 0; i < attr.length; ++i) {
var a = attr[i].split(/\s*=\s*/);
params[a[0]] = a[1];
}
jwplayer(id).setup(params);
});
//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 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);
};
}
});
var Player_devtk = Player_manuscript_type.extend({
add_question: function(index, element) {
var a = player.activity; // this fn gets called within the scope of a jquery each, so we can't refer to "this"
var jq = $(element);
// see if we're in a question_pool or question_sequence block
var qs_parent = jq.parents("[data-block_type=question_sequence], [data-block_type=question_sequence_one_at_a_time]");
var q = a.questions[a.questions.length] = new Question({
"index": a.questions.length
, "number": jQuery.trim($("[data-type='number']", jq).html())
, "title": jQuery.trim($("[data-type='title']", jq).html())
, "jq": jq
, "points_possible": 0
});
// store the question index in the DOM too
jq.attr("data-question_index", q.index);
// get question queries
a.question_being_initialized = q;
$("[data-type='query']", jq).each(a.add_query);
// if the question has queries, add bling to the bottom
if (q.queries.length > 0) {
var html = "
";
var submit_handler;
// add a submit button if we're supposed to have one
// (image map and matching questions, which should contain one and only one query, don't have submit buttons)
if (q.queries[0].hasSubmitButton === true) {
// "answer_one" pool mode (yet to be fully implemented...)
if (q.pool_mode == 'answer_one') {
html += "";
submit_handler = player.activity.Show_Submit.bind( this, q.index );
} else {
html += a.question_submit_button(q);
submit_handler = player.activity.submit_question.bind( this, q.index);
}
}
// add a "give up" button if we're supposed to have one
// (image map questions, which should contain one and only one query, should have this button)
if (q.queries[0].hasGiveUpButton === true) {
html += "";
submit_handler = player.activity.give_up_question;
}
html += "
";
jq.append(html);
var nAgt = navigator.userAgent
var Mobile = nAgt.match( /(iPhone|iPod|iPad|Android|BlackBerry)/ );
var PC = !Mobile;
var mousedown = ( Mobile ) ? "touchstart" : "mousedown";
document.querySelector( "#question_submit_button_" + q.index ).addEventListener( mousedown, submit_handler );
// bind the submit_handler function to the button, passing in the question_index
//$("#question_submit_button_" + q.index).click({question_index:q.index}, );
// float instructor controls to right of action button
jq.prepend(a.instructor_question_controls(q));
// also, determine question points and weight at this time
for (var i = 0; i < q.queries.length; ++i) {
q.points_possible += q.queries[i].getPointsPossible();
}
// round to two decimal places, in case there are decimals
q.points_possible = Math.round(q.points_possible * 100) / 100;
}
// now that the question has been created, deal with sequences and pools
if (qs_parent.length > 0) {
// get sequence index and item
var qs_index = qs_parent.attr("question_sequence_index") * 1;
var qs = a.question_sequences[qs_index];
// place in sequence
var sequence_num = qs.questions.length;
qs.questions[sequence_num] = q;
// place reference to sequence in question
q.question_sequence = qs;
q.question_sequence_index = sequence_num;
// if this isn't #1, hide the question
if (sequence_num > 0) {
jq.hide();
}
// update the sequence navigator if it's there
$("#question_sequence_max_index_" + qs.index).html(sequence_num+1);
}
},
submit_question: function (question_index) {
this._super(question_index);
},
start_activity: function() {
var src = $( "[data-block_type=activity_iframe] iframe" ).attr( "src" );
var window_width = screen.width;
var window_height = screen.height;
player.activity_window = window.open( src, "activity_window", "width=" + window_width + ",height=" + window_height + ", left=0, top=0, toolbar=no, location=no, directories=no, status=no, scrollbars=no, resizable=no, copyhistory=no" );
},
create_start_activity_button: function() {
var button = $( "[data-block_type=start_activity_button]" );
if( button.length )
{
var button_html = "
" + button.text() + "
";
button.after( button_html );
}
},
check_activity_availability: function () {
//check URL. If on websterfw.com, then show content (do nothing), if not, then determine if content should show or if coming soon message should show
safe_log("checking availability");
if (document.URL.indexOf('digfir-published') == -1) {
var isViewable = $("[key=activity_is_viewable]").html();
if (isViewable != null) {
isViewable = $.trim(isViewable);
isViewable = isViewable.toLowerCase();
if (document.URL.indexOf('show_activity') == -1) {
if (isViewable == "false") {
this.show_coming_soon_message();
}
}
}
}
},
show_coming_soon_message: function () {
var message = "This activity will be available soon.";
var html = "
" + message + "
";
$("#manuscript").before(html);
},
show_completion_message: function () {
// player.activity.grade_activity will always have been called before this fn
// so we'll have access to the properly-calculated activity properties below
var html = "Congratulations! You have completed this activity."
+ "
You have received a provisional score for your essay answers, which have been submitted to your instructor."
+ "
"
+ "
Your grade has been submitted to your instructor.
"
;
// section should have a block_type=activity_report paragraph to receive this info
$("[data-block_type=activity_report]").html(html).show();
// show the grade submitted message if user_has_received_completion_alert is true
if (player.user_has_received_completion_alert == true) {
$("#grade_submitted_message").show();
}
},
addVideoPlayer: function (containerID) {
safe_log("add player");
var playerHTML = "
";
playerHTML += '
';
$("#" + containerID).append(playerHTML);
},
show_section: function (section_to_show) {
this._super(section_to_show);
player.get_current_section_jq().find("[data-mmtype='mov']").each(function (index, element) {
safe_log("found a video");
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");
var vidHeight = jq.attr("height");
var vidWidth = jq.attr("width");
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";
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();
});
player.load_multi_video_boxes();
},
load_multi_video_boxes: function () {
player.get_current_section_jq().find("[data-block_type=multi_video_box]").each(function (index, element) {
//set the styles
var align = $(element).children().find("[data-type=metadata]").find("[key=position]").html();
$(element).attr("data-layout-border", "true").attr("data-layout-width", "medium").attr("data-layout-align", align).attr("data-type", "figure");
//insert the player
var boxID = $(element).attr("id");
var playerID = boxID + "_video_player";
player.videoIsReady[playerID] = false;
player.addVideoPlayer(boxID);
brightcove.createExperiences();
var firstVideoID = "";
var buttonsDiv = "
";
$(element).find("[data-block_type=video]").each(function (index, videoElement) {
var title = $(videoElement).find("h3").html();
var videoID = $(videoElement).find("[key=videoID]").html();
if (firstVideoID == "") {
firstVideoID = videoID;
}
var buttonHtml = "";
buttonsDiv += buttonHtml;
});
buttonsDiv += "
";
$(element).append(buttonsDiv);
player.set_video(boxID + "_video_player", firstVideoID, true);
$(element).attr("data-block_type", "multi_video_box_rendered");
$(element).find(".select_video_button").button();
});
},
set_video: function (playerID, videoID, pauseAfterLoad) {
//highlight the button
$(".select_video_button").removeClass("ui-state-focus");
$("#" + playerID + "_" + videoID).addClass("ui-state-focus");
if (!player.videoIsReady[playerID]) {
safe_log("video not ready.. going to settimeout");
setTimeout(function () { player.set_video(playerID, videoID, pauseAfterLoad) }, 100);
return false;
}
safe_log("inside load video");
var vidplayer = brightcove.api.getExperience(playerID);
var playerModule = vidplayer.getModule(brightcove.api.modules.APIModules.VIDEO_PLAYER);
safe_log("got player module");
if (pauseAfterLoad) {
playerModule.cueVideoByID(videoID);
} else {
playerModule.loadVideoByID(videoID);
}
},
videoIsReady: {},
show_section_animate: function (section_to_show, direction) {
//log with Google Analytics
this.log_section_view(section_to_show);
// make sure modal window is closed
$("#step_button").blur();
$("#toc_dialog").dialog("close");
// slide in using parent function
//this._super(section_to_show, direction);
// hide currently showing section
if (this.section_currently_showing != null) {
this.get_current_section_jq().hide();
}
this.section_currently_showing = section_to_show;
this.get_current_section_jq().fadeIn(300);
// update slide_number and title
safe_log("show_section_anim");
$("#slide_title").html(this.get_current_section().title);
$("#slide_number").html((section_to_show + 1) + " of " + this.sections.length + " ");
// if this is the first/last section, dim the previous/next button
if (this.section_currently_showing == 0) {
$(".prev_button").addClass("disabled_prev_button");
} else {
$(".prev_button").removeClass("disabled_prev_button");
}
if (this.section_currently_showing == (this.sections.length - 1)) {
$(".next_button").addClass("disabled_next_button");
} else {
$(".next_button").removeClass("disabled_next_button");
}
//apply click handler to termref items in the section - the global call done on init doesn't get the content in queries
player.glossary.set_click_event_for_terms_in_section(this.get_current_section_jq());
// scroll to top
window.scrollTo(0, 0);
},
show_navigation: function () {
var html = "
";
if (this.activity_thumbnail_src != null) {
html += "";
}
html += "
" + this.md.activity_type_title + "
"
+ "
" + this.activity_title + "
"
+ "
" //titles
+ "
"
+ "
TABLE OF CONTENTS
"
+ "
" //top_nav
+ "
" // top_banner
;
$("[data-type=chapter]").before(html);
html = "";
if (this.sections.length > 1 && this.md.hide_toolbar != "true") {
html += "
" // toolbar
;
}
$("[data-type=chapter]").prepend(html);
/* Hiding the next button
// button at the bottom of the manuscript to go on to the next step
$("[data-type=chapter]").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();
},
initialize: function () {
var fontHTML = '';
$("body").append(fontHTML);
this._super();
this.check_activity_availability();
player.glossary.set_click_event_for_terms_in_section = function (sectionjq) {
safe_log("doing click event for terms");
$(sectionjq).find("[data-type='termref']").each(function (index, element) {
// opening with a click event, as in the following line, doesn't work for queries;
// in any case I think a "real" link is probably better anyway.
// $(element).click(t.open_link).css("cursor", "pointer");
var jq = $(element);
jq.unbind("click");
safe_log("found term " + jq.html());
jq.click(function () { player.glossary.show_definition(this); });
});
}
disableTouchZooming();
this.create_start_activity_button();
},
initialize2: function () {
this._super();
//set up Google Analytics
//get the url without the querystring parts
var url = location.pathname;
//now get user info only if ARGA is initialized
var userID = "anonymous";
if (player.ARGA_running) {
userID = Get_ARGA_Data("learner_id")
}
ga('create', 'UA-52432131-1', { 'userId': userID });
ga('set', 'page', url);
ga("send", "pageview");
},
log_section_view: function (sectionNum) {
ga("send", "event", "Navigation", "LoadSection", sectionNum);
}
});
player = new Player_devtk();
//to not show the letters for MC choices
MC_Query = MC_Query.extend({
// mode should be "delivery" or "review"; "delivery" is assumed
getHTML: function (mode) {
// initialize imagemap elements
if (this.imagemap_initialized === false) {
var question_jq = this.jq.parent();
this.im_init(question_jq);
this.imagemap_initialized = true;
}
// start with the query text, if there
var html = this.query_text_html();
// wrap answers in a p tag
html += "
";
// Build answer selection
var is_correct = false;
for (var z = 0; z < this.choices.length; z++) {
var index = this.choice_order[z];
// if this is review mode...
var checked = "";
var disabled = "";
var radio_style = "query_mc_other_choice";
if (mode == 'review' || mode == 'review_correct_incorrect' || mode == 'preview') {
// if it's the correct choice, it should be marked in green
if (index == this.correct_answer_index) {
// but only if we're *not* in review_correct_incorrect mode or this is the user's choice
if (mode != 'review_correct_incorrect' || index == this.user_answer_index) {
radio_style = "query_mc_correct_choice";
}
// if this is what the user chose, he got it correct
if (index == this.user_answer_index) {
is_correct = true;
}
// else if it's the user's choice (and this.md.no_correct_answer is not true), it should be marked in red
} else if (index == this.user_answer_index && this.md.no_correct_answer != "true") {
radio_style = "query_mc_incorrect_user_choice";
}
// and the input should be disabled, unless we're in review_correct_incorrect mode
if (mode != "review_correct_incorrect") {
disabled = "disabled";
}
}
// if this is the choice the user clicked, it's checked (regardless of mode)
if (index == this.user_answer_index) {
checked = "checked";
}
// Create radio button input plus label
html += "
"
+ "
"
+ "
"
//+ "
" + this.choice_ids[z] + ".
"
+ "
"
+ "
";
}
// get a possible feedback string; this fn will take account of mode
html += this.correct_incorrect_feedback(mode, is_correct);
html += "";
return html;
}
});
//Overriding default essay query feedback text
Essay_Query = Essay_Query.extend({
getHTML: function (mode) {
// start with the query text, if there
var html = this.query_text_html();
var val, disabled;
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;
// convert breaks to newlines
val = val.replace(/ /g, "\n");
// also disable the input if we're not in review_correct_incorrect mode
if (mode != "review_correct_incorrect") {
disabled = "disabled";
}
}
html += "";
// if answer was just entered and grade is 100, also show the "provisional" message
// (unless for this question it isn't provisional)
if (this.answer_was_just_entered && this.grade == 100 && this.md.points_are_provisional == "true") {
html += "
Your answer has been provisionally accepted. You will receive full credit at this time, but your instructor may update your grade later after evaluating your answer.
";
}
return html;
}
});
function onTemplateLoaded(theID) {
safe_log("template loaded " + theID);
player.videoIsReady[theID] = true;
var vidplayer = brightcove.api.getExperience(theID);
safe_log("got player");
var playerModule = vidplayer.getModule(brightcove.api.modules.APIModules.VIDEO_PLAYER);
safe_log("god module");
playerModule.addEventListener(brightcove.api.events.MediaEvent.COMPLETE, player.onVideoComplete);
}
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');