(function() {
function shuffle(a) {
var j, x, i, result = [];
for (i = a.length - 1; i >= 0; i--) {
result[i] = a[i];
}
for (i = a.length; i; i--) {
j = Math.floor(Math.random() * i);
x = result[i - 1];
result[i - 1] = result[j];
result[j] = x;
}
return result;
}
/**
* Модель графика
* @constructor
*/
var Model = function(scores) {
this.scores = scores;
this.offset = -1;
this.offsetVisible = false;
this.isSorted = false;
this.isInited = false;
this.animateSteps = false;
this.visible = {
mode: false,
median: false,
mean: false,
all: false
};
};
Model.prototype.getMode = function() {
var counts = {};
var cnt = this.scores.length;
var i, key;
var mode = 0;
var mode_size = 0;
for (i = 0; i < cnt; i++) {
key = this.scores[i];
if ( !counts[key] ) {
counts[key] = {
value: key,
start: i,
end: i,
cnt: 1
};
}
else {
counts[key].cnt++;
counts[key].end = i;
}
if ( mode_size < counts[key].cnt ) {
mode = key;
mode_size = counts[key].cnt;
}
}
//multi-mode distribution
var maxCount = 0;
for (i = 0; i < cnt; i++) {
key = this.scores[i];
if ( counts[key].cnt > maxCount ) {
maxCount = counts[key].cnt;
}
}
var modes = [];
for (var key in counts) {
if ( counts[key].cnt == maxCount ) {
modes.push(counts[key]);
}
}
return modes;
};
Model.prototype.getMedian = function() {
if ( this.scores.length > 0 ) {
var i = Math.min(Math.round(this.scores.length / 2), this.scores.length) - 1;
return {
index: i,
value: this.scores[i]
}
}
return {
index: -1,
value: null
};
};
Model.prototype.getMean = function() {
var result = {
sum: 0,
count: this.scores.length,
value: 0
};
var i;
for (i = 0; i < result.count; i++) {
result.sum += this.scores[i];
}
result.value = Math.round(result.sum / result.count * 100) / 100;
return result;
};
Model.prototype.move = function(selectedScore, newScore) {
var newScoreCount = 0;
var selectedScoreIndex = -1;
var si, si_cnt = this.scores.length;
for (si = 0; si < si_cnt; si++) {
if ( this.scores[si] == selectedScore ) {
selectedScoreIndex = si;
}
if ( this.scores[si] == newScore ) {
newScoreCount++;
}
}
if ( selectedScoreIndex >= 0 && newScoreCount < 5 ) {
this.scores.splice(selectedScoreIndex, 1, newScore);
this.scores = this.scores.sort();
return {
success: true,
index: newScore - 1,
count: newScoreCount
};
}
return {
success: false
};
};
var _ID = 0;
/**
* Слайд
* @param section
* @param model
* @constructor
*/
var ReviewSlide = function(section, model, practice, editable) {
// http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
// detect IE <= 11
this.isIE = /*@cc_on!@*/false || !!document.documentMode;
this.section = section;
this.section.points_possible = 1;
this.section.points_earned = 0;
this.section.section_completed = false;
this.practice = practice;
this.editable = editable || false;
this.model = model;
this.section = section;
this.playTimeout = null;
this.scoreTitle = section.jq.find('.svg-score-title');
this.scoreItems = section.jq.find('.svg-score-item');
this.offsetArrow = section.jq.find('.svg-arrow-1');
this.charts = [
section.jq.find('.svg-chart-1'),
section.jq.find('.svg-chart-2'),
section.jq.find('.svg-chart-3'),
section.jq.find('.svg-chart-4'),
section.jq.find('.svg-chart-5')
];
this.chartBackground = section.jq.find('.svg-chart-background');
this.chartsDummyContainer = section.jq.find('.charts-dummy-container');
this.chartsDummy = [];
this.chartMedian = section.jq.find('.svg-chart-median');
this.chartMedianValue = section.jq.find('.svg-chart-median-value');
this.chartMean = section.jq.find('.svg-chart-mean');
this.chartMeanValue = section.jq.find('.svg-chart-mean-value');
this.chartMode = section.jq.find('.svg-chart-mode');
this.chartModeValue = section.jq.find('.svg-chart-mode-value');
this.scoreMode = section.jq.find('.svg-score-mode');
this.scoreModeLine = section.jq.find('.svg-score-mode-line');
this.scoreMedian = section.jq.find('.svg-score-median');
this.scoreMean = section.jq.find('.svg-score-mean');
this.scoreMeanSum = section.jq.find('.svg-score-mean-sum');
this.scoreMeanNumber = section.jq.find('.svg-score-mean-number');
this.scoreMeanResult = section.jq.find('.svg-score-mean-result');
var self = this;
this.allVisited = [0, 0, 0, 0];
section.jq.find('button.mode').click(function() {
self.showMode();
});
section.jq.find('button.median').click(function() {
self.showMedian();
});
section.jq.find('button.mean').click(function() {
self.showMean();
});
section.jq.find('button.show-all').click(function() {
self.showAll();
});
this.playButton = section.jq.find('button.play');
this.playButton.click(function() {
self.play();
});
section.jq.find('button.reset').click(function() {
self.model.scores = [1, 2, 2, 3, 3, 4, 4, 4, 5];
self.render();
});
this.svg = section.jq.find('.svg-practice');
var selectedElement = null;
var selectedScore = 0;
var currentX = 0;
var currentY = 0;
var initX = 0;
var initY = 0;
var newX = 0;
var newY = 0;
var scale = 1;
var drag = function(chart, score, count) {
$(chart).mousedown(function(e) {
scale = (self.svg[0].getBoundingClientRect().width / 400);
// save the original values when the user clicks on the element
currentX = e.clientX;
currentY = e.clientY;
selectedScore = score;
selectedElement = e.target;
initX = parseFloat(selectedElement.getAttribute("x")) * scale;
initY = parseFloat(selectedElement.getAttribute("y")) * scale;
});
};
$(document).mousemove(function(e) {
// if there is an active element, move it around by updating its coordinates
if ( selectedElement ) {
newX = (initX + e.clientX - currentX) / scale;
newY = (initY + e.clientY - currentY) / scale;
selectedElement.setAttribute("x", newX);
selectedElement.setAttribute("y", newY);
}
}).mouseup(function(e) {
// deactivate element when the mouse is up
if ( selectedElement ) {
selectedElement.setAttribute("x", initX / scale);
selectedElement.setAttribute("y", initY / scale);
if ( newX > 195.7 && newY > 42.4 && newX < 351.7 && newY < 185.6 ) {
var newScore = Math.max(1, Math.min(5, Math.round((newX - 185) / 32)));
if ( self.model.move(selectedScore, newScore).success ) {
self.render();
finishSlide.call(self);
}
}
selectedElement = null;
selectedScore = 0;
}
});
if ( this.editable ) {
var i, j, jcnt, icnt = this.charts.length;
var block;
for (i = 0; i < icnt; i++) {
jcnt = self.charts[i].length;
self.chartsDummy.push([]);
for (j = 0; j < jcnt; j++) {
(function(chart, i, j) {
drag(chart, i + 1, j);
block = $('
' + (i + 1) + ':' + (j + 1) + '
');
block.focusin(function(e) {
$(chart).css({
'stroke-dasharray': '2.5px',
'stroke': '#000'
});
});
block.focusout(function(e) {
$(chart).css({
'stroke': '#487654',
'stroke-dasharray': 0
});
});
block.keypress(function(e) {
e = e || window.event;
var keyCode = e.keyCode || e.which;
var newScore = keyCode - 48;
if ( newScore > 0 && newScore <= 5 && newScore != (i + 1) ) {
var result = self.model.move(i + 1, newScore);
if ( result.success ) {
self.render();
self.chartsDummy[result.index][result.count].focus();
finishSlide.call(self);
}
}
});
self.chartsDummyContainer.append(block);
self.chartsDummy[i].push(block);
})(self.charts[i][j], i, j);
}
}
}
//mc-test
if ( this.practice == 3 ) {
_ID++;
this.incorrect_feedback = this.section.jq.find('.incorrect_feedback').text() ||
'Sorry. You did not answer the question correctly. Perhaps you should go back to review the activity.';
this.correct_feedback = this.section.jq.find('.correct_feedback').text() ||
'Press the Next button and move forward.';
this.choiceItems = [];
this.checkedItem = null;
this.section.jq.find('.mc_question_text').attr('id', 'qu_' + _ID);
this.section.jq.find('.mc_choice_item').each(function() {
var $item = $(this).remove();
var item = {
correct: $item.data('correct'),
feedback: $item.data('feedback'),
text: $item.text()
};
self.choiceItems.push(item);
});
createHtml.call(this);
addButtons.call(this);
disableButtons.call(this);
addAriaElement.call(this);
disableButtons.call(this);
}
initLiveRegion.call(this);
};
var initLiveRegion = function() {
this.liveRegion = $('');
this.section.jq.append(this.liveRegion);
};
/* mc-test */
var createHtml = function() {
var $container = this.section.jq.find('.mc_choice_items');
$container.attr({
'role': 'radiogroup',
'aria-labelledby': 'qu_' + _ID
});
for (var i = 0; i < this.choiceItems.length; i++) {
var item = this.choiceItems[i];
var id = 'item_' + _ID + '_' + i;
var text = item.text;
var $input = $('');
var $label = $('');
$container.append($input, $label);
item.jq = $input;
$input.bind('change', selectItem.bind(this, item))
}
};
var disableItems = function() {
for (var i = 0; i < this.choiceItems.length; i++) {
this.choiceItems[i].jq.attr('disabled', 'disabled');
}
};
var addAriaElement = function() {
var ariaLabel = this.section.title + '. ' + this.section.instructions;
this.ariaReader = $('');
this.section.jq.prepend(this.ariaReader);
};
var addButtons = function() {
this.btnCheck = $('');
this.btnCheck.bind('click', checkAnswer.bind(this));
this.section.jq.find('.mc_slide').append(this.btnCheck);
//Jaws 17 don't enter application (form) mode automatically
this.section.jq.find('.mc_slide').attr('role', 'application');
};
var disableButtons = function() {
this.btnCheck.attr('disabled', 'disabled');
};
var checkAnswer = function() {
var self = this;
var feedback;
// Disabled button submit
disableButtons.call(this);
var className = this.checkedItem.correct ? 'correct' : 'incorrect';
this.checkedItem.jq.addClass(className);
if ( this.checkedItem.correct ) {
feedback = this.checkedItem.feedback || this.correct_feedback;
disableItems.call(this);
finishSlide.call(this);
document.querySelector('.navigation_button.next_button').focus();
Standard_Dialog.open(feedback, {
title: 'Correct!'
}, 'correct');
}
else {
feedback = this.checkedItem.feedback || this.incorrect_feedback;
Standard_Dialog.open(feedback, {
title: 'Incorrect',
buttons: [
{
text: "OK",
click: function() {
Standard_Dialog.close();
reset.call(self);
self.attempt++;
self.section.jq.find('.mc_choice_items').focus();
}
}
]
}, 'incorrect');
}
};
var reset = function() {
this.checkedItem.jq.removeClass('incorrect');
this.checkedItem.jq.attr('checked', '');
this.checkedItem = null;
};
var selectItem = function(item) {
this.checkedItem = item;
this.btnCheck.attr('disabled', '');
};
/* mc-test-end */
function initDrag() {
}
ReviewSlide.prototype.getScale = function() {
var t = $('.ui-corner-all').css('transform');
var values = t.split('(')[1];
values = values.split(')')[0];
values = values.split(',');
var a = values[0];
var b = values[1];
return Math.sqrt(a * a + b * b);
};
ReviewSlide.prototype.render = function() {
var liveText = '';
if ( this.chartBackground.length ) {
this.chartBackground.css('opacity', this.editable ? 1 : 0);
}
var i, cnt, j, cntj;
// Скрытие всех столбиков
cnt = this.charts.length;
for (i = 0; i < cnt; i++) {
this.charts[i].css('display', 'none');
if ( this.chartsDummy[i] ) {
cntj = this.chartsDummy[i].length;
for (j = 0; j < cntj; j++) {
$(this.chartsDummy[i][j]).css('display', 'none');
}
}
}
// Очистка ячеек score
cnt = this.scoreItems.length;
for (i = 0; i < cnt; i++) {
this.scoreItems[i].textContent = '';
}
// Перемешать
if ( this.practice == 1 ) {
//var scoreItems = this.model.isSorted ? this.scoreItems : shuffle(this.scoreItems);
var scoreItems = this.model.isSorted ? this.scoreItems : this.shuffled;
var y = 43.6;
var x = 66.4113;
if ( !this.model.isSorted ) {
this.scoreTitle[0].textContent = 'Original Scores';
}
else {
this.scoreTitle[0].textContent = 'Sorted Scores';
}
for (i = 0; i < cnt; i++) {
$(scoreItems[i]).css({
transform: 'translate(' + x + 'px,' + y + 'px)',
transition: this.model.isSorted ? 'transform 0.6s' : 'none'
});
if ( this.isIE ) {
scoreItems[i].setAttribute('transform', 'translate(' + x + ',' + y + ')');
}
y += 14.05;
}
}
// Рисование графика и заполнение таблицы score
cnt = this.model.scores.length;
var indexes = new Array(cnt);
var index;
liveText += 'Scores: ';
for (i = 0; i < cnt; i++) {
this.scoreItems[i].textContent = this.model.scores[i];
if ( !this.model.animateSteps || i <= this.model.offset ) {
index = this.model.scores[i] - 1;
if ( typeof indexes[index] === 'undefined' ) {
indexes[index] = 0;
}
$(this.charts[index][indexes[index]]).css('display', 'block');
if ( this.chartsDummy[index] ) {
$(this.chartsDummy[index][indexes[index]]).css('display', 'block');
}
indexes[index]++;
}
liveText += this.model.scores[i] + ', ';
}
// Строчка над текущей позицией Score
this.offsetArrow.css({
opacity: this.model.offsetVisible && this.model.offset >= 0 ? 1 : 0,
transform: 'translateY(' + this.model.offset * 14.05 + 'px)'
});
//IE 10 and below does not support CSS transforms on SVG elements (though SVG transform attributes do work)
//в IE11 тоже не срабатывает
if ( this.isIE ) {
this.offsetArrow[0].setAttribute('transform', 'translate(0,' + this.model.offset * 14.05 + ')');
}
var value;
if ( this.practice > 1 ) {
var median = this.model.getMedian();
this.chartMedian.css({
opacity: this.model.visible.median || this.model.visible.all ? 1 : 0,
transform: 'translateX(' + (median.value * 32 - (median.value > 0 ? 64 : 69)) + 'px)'
});
if ( this.isIE ) {
value = median.value * 32 - (median.value > 0 ? 64 : 69);
this.chartMedian[0].setAttribute('transform',
'translate(' + value + ')');
}
this.chartMedianValue[0].textContent = 'Median = ' + median.value + '';
liveText += 'Median = ' + median.value + '. ';
var mean = this.model.getMean();
this.chartMean.css({
opacity: this.model.visible.mean || this.model.visible.all ? 1 : 0,
transform: 'translateX(' + (mean.value * 32 - (mean.value > 0 ? 76 : 81)) + 'px)'
});
if ( this.isIE ) {
value = mean.value * 32 - (mean.value > 0 ? 76 : 81);
this.chartMean[0].setAttribute('transform',
'translate(' + value + ')');
}
this.chartMeanValue[0].textContent = 'Mean = ' + mean.value;
liveText += 'Mean = ' + mean.value + '. ';
if ( this.editable ) {
var modes = this.model.getMode();
for (i = 0; i < modes.length; i++) {
$(this.chartMode[i]).css({
opacity: this.model.visible.mode || this.model.visible.all ? 1 : 0,
transform: 'translateX(' + (modes[i].value * 32 - (modes[i].value > 0 ? 47 : 52)) + 'px)'
});
if ( this.isIE ) {
value = modes[i].value * 32 - (modes[i].value > 0 ? 47 : 52);
this.chartMode[i].setAttribute('transform',
'translate(' + value + ')');
}
(this.chartModeValue[i]).textContent = 'Mode = ' + modes[i].value;
var startY = modes[i].start * 14.05;
var height = 70.5 + modes[i].cnt * 14.05;
// this.scoreModeLine[i].setAttribute('points', '91,70.5 96,70.5 96,' + height + ' 91,' + height);
liveText += 'Mode = ' + modes[i].value + '. ';
}
for (i = modes.length; i < 5; i++) {
$(this.chartMode[i]).css({ opacity: 0});
}
}
else {
var mode = this.model.getMode()[0];
this.chartMode.css({
opacity: this.model.visible.mode || this.model.visible.all ? 1 : 0,
transform: 'translateX(' + (mode.value * 32 - (mode.value > 0 ? 47 : 52)) + 'px)'
});
if ( this.isIE ) {
value = mode.value * 32 - (mode.value > 0 ? 47 : 52);
this.chartMode[0].setAttribute('transform',
'translate(' + value + ')');
}
this.chartModeValue[0].textContent = 'Mode = ' + mode.value;
var startY = mode.start * 14.05;
var height = 70.5 + mode.cnt * 14.05;
this.scoreModeLine[0].setAttribute('points', '91,70.5 96,70.5 96,' + height + ' 91,' + height);
}
this.scoreMode.css({
opacity: this.model.visible.mode ? 1 : 0,
transform: 'translateY(' + startY + 'px)'
});
if ( this.isIE ) {
this.scoreMode[0].setAttribute('transform',
'translate(0,' + startY + ')');
}
this.scoreMean.css({
opacity: this.model.visible.mean ? 1 : 0,
transform: 'translateX(-16px)'
});
if ( this.isIE ) {
this.scoreMean[0].setAttribute('transform',
'translate(-16)');
}
this.scoreMedian.css({
opacity: this.model.visible.median ? 1 : 0,
transform: 'translateY(-42px)'
});
if ( this.isIE ) {
this.scoreMedian[0].setAttribute('transform',
'translate(0,-42)');
}
this.scoreMeanSum[0].textContent = mean.sum;
this.scoreMeanNumber[0].textContent = mean.count;
this.scoreMeanResult[0].textContent = mean.sum + ' / ' + mean.count + ' = ' + mean.value;
}
if (this.editable){
this.liveRegion.text(liveText);
}
};
var prerenderAnim = function() {
this.model.offsetVisible = false;
this.model.scores = [1, 2, 2, 3, 3, 4, 4, 4, 5];
this.model.offset = -1;
this.model.isSorted = false;
this.model.animateSteps = true;
this.shuffled = shuffle(this.scoreItems);
this.render();
}
ReviewSlide.prototype.play = function() {
this.playButton.text('PLAY').attr('aria-label', 'play');
if ( this.playTimeout ) {
clearTimeout(this.playTimeout)
}
var self = this;
if (this.model.isSorted) {prerenderAnim.call(this);}
var animation = function() {
self.render();
if ( self.model.isSorted ) {
self.model.offset++;
}
self.model.isSorted = true;
self.model.offsetVisible = true;
if ( self.playTimeout ) {
clearTimeout(self.playTimeout);
}
if ( self.model.offset <= self.model.scores.length ) {
self.playTimeout = setTimeout(animation, 1000);
}
else {
self.model.offsetVisible = false;
self.render();
self.playButton.text('REPLAY').attr('aria-label', 'replay');
finishSlide.call(self);
}
};
animation();
};
ReviewSlide.prototype.showMode = function() {
this.model.visible = {
mode: true,
median: false,
mean: false,
all: false
};
this.render();
this.allVisited[0] = 1;
checkVisited.call(this);
};
ReviewSlide.prototype.showMedian = function() {
this.model.visible = {
mode: false,
median: true,
mean: false,
all: false
};
this.render();
this.allVisited[1] = 1;
checkVisited.call(this);
};
ReviewSlide.prototype.showMean = function() {
this.model.visible = {
mode: false,
median: false,
mean: true,
all: false
};
this.render();
this.allVisited[2] = 1;
checkVisited.call(this);
};
ReviewSlide.prototype.showAll = function() {
this.model.visible = {
mode: false,
median: false,
mean: false,
all: true
};
this.render();
this.allVisited[3] = 1;
checkVisited.call(this);
};
var checkVisited = function() {
if ( this.allVisited.reduce(function(pv, cv) { return pv + cv; }, 0) == 4 ) {
finishSlide.call(this);
}
}
ReviewSlide.prototype.showSlide = function() {
if ( this.practice == 1 ) {
prerenderAnim.call(this);
}
else {
this.render();
}
if ( this.editable ) {
this.liveRegion.text('choose scores by pressing TAB button. then press any number from 1 to 5 to change selected score');
}
};
ReviewSlide.prototype.hideSlide = function() {
if ( this.playTimeout ) {
clearTimeout(this.playTimeout)
}
document.querySelector('.navigation' + '_button.next_button').focus();
};
var finishSlide = function() {
this.section.points_earned = this.section.points_possible;
this.section.section_completed = true;
player.activity.grade_activity();
player.update_section_status();
};
window.mheContpract = window.mheContpract || {};
window.mheContpract['mean_median'] = {
initialize: function(section) {
section.slide = new ReviewSlide(section, new Model([]), 1, false);
},
show: function(section) {
section.slide.showSlide();
},
hide: function(section) {
section.slide.hideSlide();
}
};
window.mheContpract['mean_median-2'] = {
initialize: function(section) {
section.slide = new ReviewSlide(section, new Model([1, 2, 2, 3, 3, 4, 4, 4, 5]), 2, false);
},
show: function(section) {
section.slide.showSlide();
},
hide: function(section) {
section.slide.hideSlide();
}
};
window.mheContpract['mean_median-3'] = {
initialize: function(section) {
section.slide = new ReviewSlide(section, new Model([1, 2, 2, 3, 3, 4, 4, 4, 5]), 2, true);
section.slide.model.visible = {
mode: false,
median: false,
mean: false,
all: true
}
},
show: function(section) {
section.slide.showSlide();
},
hide: function(section) {
section.slide.hideSlide();
}
};
window.mheContpract['mean_median-4'] = {
initialize: function(section) {
section.slide = new ReviewSlide(section, new Model([1, 2, 2, 3, 3, 4, 4, 4, 5]), 3, true);
section.slide.model.visible = {
mode: false,
median: false,
mean: false,
all: true
}
},
show: function(section) {
section.slide.showSlide();
},
hide: function(section) {
section.slide.hideSlide();
}
};
})();