')
ariaReader.addClass('hidden_element')
ariaReader.attr('aria-label', ariaLabel)
ariaReader.attr('tabindex', '-1')
section.jq.prepend(ariaReader)
}
function slideShowHandler(section) {
var $questions = section.jq.find('.question_container')
var $navPanel = section.jq.find('.navigation_buttons_container')
var currQuestNum = 0
var $nextBtn = $navPanel
.find('.button_next')
.attr('disabled', true)
.unbind('click')
.bind('click', function () {
if (currQuestNum < $questions.length - 1) currQuestNum++
$nextBtn.attr('disabled', true)
showStep(currQuestNum)
})
var $backBtn = $navPanel
.find('.button_back')
.attr('disabled', true)
.unbind('click')
.bind('click', function () {
if (currQuestNum > 0) currQuestNum--
if (currQuestNum == 0) $backBtn.attr('disabled', true)
showStep(currQuestNum)
})
var $curQuest
$questions.hide()
showStep(currQuestNum)
function showStep(currQuestNum) {
section.jq.focus()
$backBtn.attr('disabled', currQuestNum == 0)
$nextBtn.attr('disabled', true)
$curQuest = $questions.hide().eq(currQuestNum).show()
//=====================================================
switch ($curQuest.data('type')) {
//subtask with choices ------------------------------------------
case 'choice':
var instruction = 'Answer the question. Correct answers turn green; incorrect answers turn red. Then, select the “New subtest” button.';
var sectionAria = section.title + ". " + instruction;
section.jq.attr('aria-label', sectionAria);
$('.footer p').text(instruction);
$curQuest.show()
.find('.quest-variant')
.attr('disabled', false)
.removeClass('correct incorrect')
.unbind('keyup')
.bind('keyup', function (event) {
if (event.keyCode == 13) {
$(this).click();
}
})
.unbind('click')
.bind('click', function () {
var feedback = '';
if ($(this).data('correct')) {
$(this).addClass('correct');
feedback = 'correct';
}
else {
$(this).addClass('incorrect');
feedback = 'incorrect. Correct answer is ' + $curQuest.find('[data-correct="true"]').text();
}
$('#live-region').text("Feedback: your answer is " + feedback);
$curQuest.find('.quest-variant').attr('disabled', true)
$nextBtn.attr('disabled', false)
})
break
//subtask with random numbers -----------------------------------
case 'numbers':
var instruction = 'Follow the instructions at the top of the screen. When the subtest is finished, select the NEXT button and move to Practice 2.';
var sectionAria = section.title + ". " + instruction;
section.jq.attr('aria-label', sectionAria);
$('.footer p').text(instruction);
var $beginBtn = $curQuest.find('.begin_button').show()
var $finishBtn = $curQuest.find('.finished_button').hide()
var $continueBtn = $curQuest.find('.continue_button').hide()
var $numsInput = $curQuest.find('.input_container').hide()
var $numsInputField = $numsInput.find('.you_number')
var $numsField = $curQuest.find('.number').hide()
var $fbCont = $curQuest.find('.feedback_container').hide()
var $finishCont = $curQuest.find('.finish_container').hide()
var $fbUserNum = $curQuest.find('.you_number_result')
var $fbAnswer = $curQuest.find('.correct_text')
var $fbRecalledNum = $curQuest.find('.red_text__recalled')
var $fbRecalledPerc = $curQuest.find('.red_text__percent')
var $fbRecalledDigits = $curQuest.find('.red_text__count')
var dt = 1000
var maxDigits = 7
var minDigits = 5
$beginBtn
.unbind('click')
.bind('click', function () {
$beginBtn.hide()
var nums = []
for (var i = 0; i < 10; i++) {
nums.push(i)
}
$numsField.empty()
subStep()
function subStep() {
nums = nums.reduce(function (sum, val, i, arr) {
var idx = Math.floor(Math.random() * (i + 1));
var tmp = sum[idx]
sum[idx] = sum[i]
sum[i] = tmp
return sum
}, nums)
$numsField.empty().show()
var counter = 0
var timer = setTimeout(function tick() {
//shows random number every second-------------------
$numsField.html('
')
if (counter < minDigits) {
counter++
timer = setTimeout(tick, dt)
}
else {
clearTimeout(timer)
$numsField.hide()
$numsInput.show()
$numsInputField
.val('')
.focus()
.unbind('keyup')
.bind('keyup', function (event) {
if (event.keyCode == 13) {
$finishBtn.click();
}
});
$finishBtn
.show()
.unbind('click')
.bind('click', function () {
$numsInput.hide()
$finishBtn.hide()
$fbUserNum.val($numsInputField.val())
$fbAnswer.html(nums.slice(0, minDigits).join(''))
$fbRecalledNum.html(
$numsInputField
.val()
.split('')
.slice(0, minDigits)
.filter(function (n, i) {
return n == nums[i]
})
.length
)
$fbRecalledPerc.html(Math.round(
($numsInputField
.val()
.split('')
.slice(0, minDigits)
.filter(function (n, i) {
return n == nums[i]
})
.length * 100 / minDigits)))
$fbRecalledDigits.html(minDigits)
var feedbackAriaText = 'You recalled ' + $fbRecalledNum.html() +
' numbers in the correct positions. That is ' + $fbRecalledPerc.html() +
' percent correct with ' + minDigits + '.';
$fbCont.attr('aria-label',feedbackAriaText);
if (maxDigits > minDigits) {
$continueBtn
.show()
.unbind('click')
.bind('click', function () {
$fbCont.hide()
$continueBtn.hide()
minDigits++
subStep()
})
} else {
$finishCont.show()
finishTask(section)
}
setTimeout( function() {
$fbCont.show().focus()
}, 100);
})
}
}, dt)
}
})
break
default:
console.log('No such step type')
}
}
}
function finishTask(section) {
section.points_earned = 1;
section.section_completed = true;
player.activity.grade_activity();
player.update_section_status();
}
function slideHideHandler(section) {
// console.log('slideHideHandler', section)
}
window.mheContpract = window.mheContpract || {};
window.mheContpract['practice1'] = {
initialize: slideInitHandler,
show: slideShowHandler,
hide: slideHideHandler
};
})();
//############################################################
//Practice 2
;(function () {
'use strict';
var _timer = null
function slideInitHandler(section) {
section.points_possible = 1;
section.points_earned = 0;
section.section_completed = false;
section.jq
.addClass('practice2')
.addClass('practice-steps')
//add Accessibility elements
var ariaLabel = section.title + '. ' //+ section.instructions
var ariaReader = $('
')
ariaReader.addClass('hidden_element')
ariaReader.attr('aria-label', ariaLabel)
ariaReader.attr('tabindex', '-1')
section.jq.prepend(ariaReader)
var $nextBtn = section.jq
.find('.navigation_buttons_container')
.find('.button_next')
section.quests = []
var $dndQuestions = section.jq
.find('.question_container')
.each(function(i, item){
var sectionMock = {
jq: $(this),
$nextBtn: $nextBtn
}
switch ($(this).data('type')){
case 'dragdrop':
section.quests[i] = new DnDSlide(sectionMock)
break
default:
section.quests[i] = null
}
})
}
function slideShowHandler(section) {
var $questions = section.jq.find('.question_container')
var $navPanel = section.jq.find('.navigation_buttons_container')
var currQuestNum = 0
var $nextBtn = $navPanel
.find('.button_next')
.attr('disabled', true)
.unbind('click')
.bind('click', function () {
if (currQuestNum < $questions.length - 1) currQuestNum++
$nextBtn.attr('disabled', true)
showStep(currQuestNum)
})
var $backBtn = $navPanel
.find('.button_back')
.attr('disabled', true)
.unbind('click')
.bind('click', function () {
if (currQuestNum > 0) currQuestNum--
if (currQuestNum == 0) $backBtn.attr('disabled', true)
showStep(currQuestNum)
})
var $curQuest
$questions.hide()
showStep(currQuestNum)
function showStep(currQuestNum) {
clearInterval(_timer)
section.jq.focus()
$backBtn.attr('disabled', currQuestNum == 0)
$nextBtn.attr('disabled', true)
$curQuest = $questions.hide().eq(currQuestNum).show()
//=====================================================
switch ($curQuest.data('type')) {
//subtask with input ------------------------------------------
case 'input':
var $finishBtn = $curQuest.find('.finished_button')
var $inputField = $curQuest
.find('.quest__answer-field .you_answer')
var $correctAns = $curQuest
.find('.quest__answer-field .correct_answer')
.hide()
$curQuest.show()
$finishBtn
.attr('disabled', true)
.unbind('click')
.bind('click', function () {
$('#live-region').text($correctAns.text());
$correctAns.show()
$inputField.attr('disabled', true)
$finishBtn.attr('disabled', true)
$nextBtn.attr('disabled', false)
if (!window.mheContpract.libs.browser.platform.PC) {
$correctAns.attr('tabIndex', '0').focus();
}
else {
$nextBtn.focus();
}
})
$inputField
.attr('disabled', false)
.unbind('keyup')
.bind('keyup', function (event) {
if (event.keyCode == 13) {
$(this).attr('disabled', true)
$finishBtn.click();
}
})
.unbind('input')
.bind('input', function () {
if (!$(this).val()) {
$finishBtn.attr('disabled', true)
} else {
$finishBtn.attr('disabled', false)
}
})
.val('')
break
//subtask with drag&drop ---------------------------------------
case 'dragdrop':
section.quests[currQuestNum].updateButtons()
break
//subtask with digits ---------------------------------------
case 'digits':
var instruction = 'Follow the instructions at the top of the screen. When the subtest is finished, select the NEXT button and move to Quiz 1.';
var sectionAria = section.title + ". " + instruction;
section.jq.attr('aria-label', sectionAria);
$('.footer p').text(instruction);
var $timer = $curQuest
.find('.quest-digist__timer-value')
.html(0)
var $symbols = $curQuest
.find('.quest-digist__code_symbols')
.hide()
var $correctNumbers = $curQuest
.find('.quest-digist__correct_answer')
.hide()
var $displaySymbols = $curQuest
.find('.display_button')
.unbind('click')
.bind('click', function(){
$(this).hide()
$correctNumbers.hide()
$symbols.show()
$testNumbers.val('').attr('disabled', false)
$('.quest-digits__answer-table input').first().focus();
var counter=0
_timer = setInterval(function(){
counter++
$timer.html(counter)
}, 1000)
})
.show()
var $finishBtn = $curQuest
.find('.finished_button')
.hide()
.unbind('click')
.bind('click', function(){
clearInterval(_timer)
$(this).hide()
$correctNumbers.show()
$displaySymbols.show()
$testNumbers.attr('disabled', true)
finishTask(section)
})
var $testNumbers =
$curQuest.find('.quest-digits__test_number')
.unbind('input')
.bind('input', function(){
$(this).val(this.value.replace(/[^0-9]+/g,''))
if (!$testNumbers
.toArray()
.filter(function(n){return $(n).val()==''})
.length){
$finishBtn.show()
}else{
$finishBtn.hide()
}
})
.val('')
.attr('disabled', true)
break
default:
console.log('No such step type')
}
}
}
function finishTask(section) {
section.points_earned = 1;
section.section_completed = true;
player.activity.grade_activity();
player.update_section_status();
//#########################
document.querySelector('.navigation_button.next_button').focus();
}
function slideHideHandler(section) {
clearInterval(_timer)
}
window.mheContpract = window.mheContpract || {};
window.mheContpract['practice2'] = {
initialize: slideInitHandler,
show: slideShowHandler,
hide: slideHideHandler
};
//DnD hard code copy ================================================
var FEEDBACK = {
INCORRECT: 'Sorry. Perhaps you should go back to review the activity.',
CORRECT: 'Press the Next button and move forward.'
};
var ARIATEXTS = {
INTRO_END: "You can change the location of the label only while this label is selected.",
DONE_DRAG: "You have completed the Table with all answers. Press Reset button to start a new try or press Check answer button to check this try.",
COMPLETE: "You have set all the labels correctly. Good job! "
};
var KEYCODES = {
SHIFT: 16
};
var DnDSlide = function (section) {
var self = this;
this.attempt = 0;
this.section = section;
this.section.jq.addClass('dnd_test');
this.section.jq.attr('role', 'application');
this.section.points_possible = 1;
this.section.points_earned = 0;
this.section.section_completed = false;
var correct_fb = this.section.jq.find('.correct_feedback').text();
var incorrect_fb = this.section.jq.find('.incorrect_feedback').text();
this.incorrect_feedback = incorrect_fb || FEEDBACK.INCORRECT;
this.correct_feedback = correct_fb || FEEDBACK.CORRECT;
this.dragItems = [];
this.dropItems = [];
this.ariaDragItems = [];
this.numPlacedItems = 0;
this.numCorrectItems = 0;
this.dragItemsNodes = this.section.jq.find('.drag-item');
this.dropAreas = this.section.jq.find('.drop-area');
var mainAria;
this.dropAreas.each(function (i) {
i = i + 1;
$(this).append($('
' + i + '
'));
self.dropItems.push($(this));
});
this.dragItemsNodes.each(function (i) {
var $item = $(this).data('drag-item', i);
var ariaLabel = $item.text();
$item.attr({
'tabindex': '0',
'aria-label': ariaLabel
});
$item.keydown(onKeyHandler.bind(self, i));
$item.keyup(onKeyHandlerUp.bind(self, i));
$item.focus(onFocus.bind(self, i));
$item.blur(onBlur.bind(self, i));
self.dragItems.push({
targets: $item.data('targets').split(','),
correct: false,
userTarget: null,
dropped: false
});
});
addButtons.call(this);
initDraggableItems.call(this);
initDropAreas.call(this);
initLiveRegion.call(this);
this.updateButtons();
};
var initLiveRegion = function () {
this.liveRegion = $('
');
this.section.jq.append(this.liveRegion);
};
var getAriaText = function ($item, ind) {
var text = $item.data('text') || $item.text();
var ariaText = 'You chose ' + text + '. ' +
' Label ' + ( ind + 1 ) + ' of ' + this.dragItemsNodes.length + '.' +
' Enter one of the following numbers to select the corresponding answer: ';
this.dropAreas.each(function (i) {
var isDisabled = $(this).droppable("option", "disabled");
if (!isDisabled) {
ariaText += ( i + 1 ) + '. ' + $(this).data('definition') + '. '
}
});
return ariaText;
};
var onFocus = function (i) {
var item = this.dragItemsNodes[i];
var $item = $(item);
var aria = getAriaText.call(this, $item, i);
$item.attr('aria-label', aria);
this.section.jq.addClass('grabbed');
};
var onBlur = function () {
this.section.jq.removeClass('grabbed');
};
var key;
var onKeyHandlerUp = function (i, e) {
e = e || window.event;
var keyCode = e.keyCode || e.which;
// when the user releases the button
if (keyCode === KEYCODES.SHIFT) {
key = parseInt(key, 10);
key -= 1;
setDropItem.call(this, i);
}
};
var onKeyHandler = function (i, e) {
e = e || window.event;
var keyCode = e.keyCode || e.which;
// If the shift button is pressed, we need to remember what kind of
if (e.shiftKey && keyCode !== KEYCODES.SHIFT) {
key = key || "";
key += String.fromCharCode(keyCode);
} else {
key = String.fromCharCode(e.keyCode);
key = parseInt(key, 10);
key -= 1;
setDropItem.call(this, i);
}
};
var setDropItem = function (i) {
if (!isNaN(key) && key >= 0 && key < this.dragItems.length) { // key 0 -- this.dragItems.length - 1
var $dropArea = $(this.dropAreas[key]);
var $item = $(this.dragItemsNodes[i]);
var item = this.dragItems[i];
if (item.correct) return;
if (!item.originalPosition) {
item.originalPosition = findPosition($item);
}
var isDisabled = $dropArea.droppable('option', 'disabled');
if (!isDisabled) {
this.dragItemsNodes[i].setAttribute('tabindex', "-1");
dropItem.call(this, item, $item, $dropArea);
}
}
key = "";
};
var initDropAreas = function () {
var self = this;
this.dropAreas.droppable({
drop: function (event, ui) {
var $dropArea = $(this);
var $dragItem = $(ui.draggable[0]);
var dragItem = self.dragItems[$dragItem.data('drag-item')];
dropItem.call(self, dragItem, $dragItem, $dropArea);
},
tolerance: 'intersect',
accept: '.drag-item'
});
};
var dropItem = function (dragItem, $dragItem, $dropArea) {
var self = this;
if (!self.checkSingleLabel.call(self, dragItem, $dropArea.data('drop-area'))) {
return console.log('incorrect!')
}
var position = $dropArea.position();
position = {
top: position.top / player._scaleFactor,
left: position.left / player._scaleFactor
};
if (dragItem.userTarget) {
dragItem.userTarget.droppable('enable');
}
else {
this.numPlacedItems++;
this.updateButtons.call(this);
}
dragItem.userTarget = $dropArea;
dragItem.dropped = true;
$dragItem.css(position);
$dropArea.droppable('disable');
};
var initDraggableItems = function () {
var self = this;
this.dragItemsNodes.draggable({
start: function () {
var $item = $(this);
var item = self.dragItems[$item.data('drag-item')];
item.dropped = false;
resetItem.call(self, item);
if (!item.originalPosition) {
item.originalPosition = findPosition($item);
}
},
drag: function (event, ui) {
ui.position = {
top: Math.round(ui.position.top / player._scaleFactor),
left: Math.round(ui.position.left / player._scaleFactor)
};
},
stop: function (event, ui) {
var $item = $(this);
var item = self.dragItems[$item.data('drag-item')];
// Revert item with animation
if (!item.dropped) {
revertItem.call(self, item, $item);
}
},
scroll: false
});
};
var findPosition = function ($item) {
var position = $item.position();
return {
top: Math.round(position.top / player._scaleFactor),
left: Math.round(position.left / player._scaleFactor)
};
};
DnDSlide.prototype.updateButtons = function () {
var disable = ( this.numPlacedItems === this.dropItems.length ) ? '' : 'disabled';
this.section.$nextBtn.attr('disabled', disable)
// this.btnCheck.attr( 'disabled', disable );
// this.btnReset.attr( 'disabled', disable );
if (this.numPlacedItems === this.dropItems.length) {
this.liveRegion.text(ARIATEXTS.DONE_DRAG);
onBlur.call(this);
}
};
DnDSlide.prototype.checkSingleLabel = function (item, id) {
var result = false;
item.targets.forEach(function (target) {
if (target === id) {
result = true;
}
});
return result;
};
var addButtons = function () {
// this.btnReset = $('
');
// this.btnCheck = $('
');
var instruction = $('
Enter one of the following numbers to select the corresponding answer
');
// this.btnCheck.bind('click', checkAnswer.bind(this));
// this.btnReset.bind('click', resetAllItems.bind(this));
var btnContainer = $('
');
// btnContainer.append(instruction, this.btnReset, this.btnCheck);
btnContainer.append(instruction);
this.section.jq.append(btnContainer);
};
var disableButtons = function () {
// this.btnCheck.attr('disabled', 'disabled');
// this.btnReset.attr('disabled', 'disabled');
};
var resetAllItems = function () {
var self = this;
if (self.numCorrectItems === self.dropItems.length) {
self.numCorrectItems = 0;
self.section.jq.focus();
this.dragItemsNodes.each(function () {
var $item = $(this);
var item = self.dragItems[$item.data('drag-item')];
resetItem.call(self, item, $item);
if (item.originalPosition) {
$item.css(item.originalPosition);
}
$item.attr('tabindex', '0');
$item.draggable('enable');
$item.removeClass('incorrect');
$item.removeClass('correct');
});
return;
}
this.dragItemsNodes.each(function () {
var $item = $(this);
var item = self.dragItems[$item.data('drag-item')];
if (!item.correct) {
resetItem.call(self, item);
if (item.originalPosition) {
$item.css(item.originalPosition);
}
$item.attr('tabindex', '0');
$item.draggable('enable');
$item.removeClass('incorrect');
$item.removeClass('correct');
}
});
this.updateButtons.call(this);
};
var resetItem = function (item, $item) {
if (item.userTarget) {
item.userTarget.droppable('enable');
item.userTarget = null;
item.correct = false;
item.dropped = false;
this.numPlacedItems--;
}
};
var revertItem = function (item, $item) {
resetItem.call(this, item);
this.updateButtons.call(this);
$item.addClass('revert');
$item.animate(item.originalPosition, 400, function () {
$item.removeClass('revert');
});
};
var checkAnswer = function () {
var self = this;
disableButtons.call(this);
this.numCorrectItems = 0;
var fb;
var correctAnswers = 0;
this.dragItemsNodes.each(function (i) {
var $item = $(this);
var item = self.dragItems[$item.data('drag-item')];
if (item.userTarget) {
item.correct = self.checkSingleLabel.call(self, item, item.userTarget.data('drop-area'));
if (item.correct) {
$item.attr('tabindex', '-1');
correctAnswers++;
}
fb = 'You have set ' + correctAnswers + ' of ' + self.dragItemsNodes.length + ' labels correctly. ';
var className = item.correct ? 'correct' : 'incorrect';
$item.addClass(className);
$item.draggable('disable');
self.numCorrectItems += item.correct;
}
});
var html;
if (this.numCorrectItems === this.dropItems.length) {
finishSlide.call(this);
html = '
' + this.correct_feedback + '
';
Standard_Dialog.open(html, {
title: 'Correct!',
buttons: [{
text: 'OK',
click: function () {
Standard_Dialog.close();
self.btnReset.attr('disabled', '');
}
}]
}, 'correct');
this.btnReset.attr('disabled', '');
this.liveRegion.text(ARIATEXTS.COMPLETE);
}
else {
html = '
' + this.incorrect_feedback + '
';
Standard_Dialog.open(html, {
title: 'Incorrect',
buttons: [{
text: 'OK',
click: function () {
Standard_Dialog.close();
self.section.jq.focus();
}
}]
}, 'incorrect');
self.attempt++;
resetAllItems.call(this);
Standard_Dialog.activeElement = this.section.jq[0];
this.liveRegion.text(fb);
}
};
var finishSlide = function () {
this.section.points_earned = this.section.points_possible;
this.section.section_completed = true;
player.activity.grade_activity();
player.update_section_status();
document.querySelector('.navigation_button.next_button').focus();
};
DnDSlide.prototype.showSlide = function () {
};
})();