(function(){ var INSTRUCTIONS = [ "Roll over each card to see the other side. After all the cards are turned over, select the \"Decision task\" button to continue.", "Select only the card(s) necessary to test the statement. Then, select the \"Results\" button to continue.", "Roll over each card to see the other side." ]; var CARD_OPTIONS = [ { needRotation: true, needSelection: false }, { needRotation: false, needSelection: true }, { needRotation: true, needSelection: false } ]; var BUTTONS = [ "Decision task", "Results", "Reset" ]; var SLIDE_CALLBACK = [ null, function(){ var node = document.querySelector( ".cards-practice .order" ); var results = []; var i; for( i = 0; i < this.cards.length; i++ ){ if( this.cards[i].selected ){ results.push( this.cards[i].title ); } } node.innerHTML = results.join(", "); }, null ]; function Practice(section){ this.section = section; this.sectionNode = section.jq[0]; section.jq.addClass("cards-practice"); this.section.points_possible = 1; this.section.points_earned = 0; this.section.section_completed = false; this.completed = false; // initialize (function(){ var slidesNodes = this.sectionNode.querySelectorAll( ".slide" ); this.navBtn = this.sectionNode.querySelector( ".navigation-controls button" ); this.navBtn.addEventListener( "click", this.showNextSlide.bind(this) ); this.slides = []; for( var i = 0; i < slidesNodes.length; i++ ){ this.slides.push( new Slide( slidesNodes[i], i ) ); } this.reset(); }).call(this); } Practice.prototype.reset = function(){ // hide all slides this.slides.forEach(function( slide ){ slide.hide(); slide.reset(); }); // set current slide this.slide = this.slides[0]; this.slide.show(); // update nav button this.navBtn.innerHTML = BUTTONS[0]; // update instructions this.setInstruction( INSTRUCTIONS[0] ); // set focus on the slide this.sectionNode.focus(); }; Practice.prototype.showNextSlide = function(){ // get his index in array "slides" var position = this.slides.indexOf( this.slide ) + 1; // if has slide with this position - set his if( this.slides[position] ){ // hide current slide this.slide.hide(); // set new slide and show it this.slide = this.slides[position]; this.slide.show(); // update nav button this.navBtn.innerHTML = BUTTONS[position]; // update instructions this.setInstruction( INSTRUCTIONS[position] ); // set focus on the slide this.sectionNode.focus(); // if last slide and practice isn't complete - finish it if( !this.completed && !this.slides[position + 1] ){ this.finishPractice(); } return; } this.reset(); }; Practice.prototype.setInstruction = function( instruction ){ if( !instruction ) return; // define footer container var node = document.querySelector( ".footer" ); // declare variables var p, ariaText; // create container for instruction p = document.createElement( "p" ); p.innerText = instruction; // clear and append new instruction node.innerHTML = ""; node.appendChild( p ); // make text for aria-label attribute ariaText = this.section.title + ". " + instruction; // set aria label this.section.jq[0].setAttribute( "aria-label", ariaText ); }; Practice.prototype.finishPractice = function(){ this.section.points_earned = this.section.points_possible; this.section.section_completed = true; this.completed = true; player.activity.grade_activity(); player.update_section_status(); document.querySelector(".navigation_button.next_button").focus(); }; /*-------------------------------------------------------------------*/ /*-------------------------------Slide-------------------------------*/ /*-------------------------------------------------------------------*/ function Slide( container, position ) { this.node = container; this.position = position; this.callback = SLIDE_CALLBACK[position] || function(){}; this.cards = []; // initialize (function(){ var cardsNodes = this.node.querySelectorAll( ".card" ); var titles = ["Card 1", "Card 2", "Card 3", "Card 4"]; var options = CARD_OPTIONS[position]; for( var i = 0; i < cardsNodes.length; i++ ){ this.cards.push( new Card( cardsNodes[i], titles[i], options ) ); } }).call(this) } Slide.prototype.show = function(){ show( this.node ); }; Slide.prototype.hide = function(){ hide( this.node ); this.callback.call(this); }; Slide.prototype.reset = function(){ this.cards.forEach(function( card ){ card.reset(); card.selected = false; }); }; /*-------------------------------------------------------------------*/ /*-------------------------------Card--------------------------------*/ /*-------------------------------------------------------------------*/ function Card( container, title, options ){ this.node = container; this.title = title; this.options = options; this.front = container.querySelector( ".front" ); this.back = container.querySelector( ".back" ); this.isPlaying = false; this.selected = false; // initialize (function(){ var reset = this.reset.bind(this); var select = this.select.bind(this); var rotate = this.animateRotation.bind(this); var turn = this.turn.bind(this); // define events if( options.needRotation ){ // if browser support css-rotation if( "transform" in document.body.style ){ this.node.addEventListener( "focus", rotate ); this.node.addEventListener( "mouseenter", rotate ); } else { this.node.addEventListener( "focus", turn ); this.node.addEventListener( "mouseenter", turn ); } this.node.addEventListener( "blur", reset ); this.node.addEventListener( "mouseleave", reset ); } if( options.needSelection ){ this.node.addEventListener( "click", select ); this.node.addEventListener( "keydown", select ); this.node.addEventListener( "blur", reset ); this.node.addEventListener( "mouseleave", reset ); } this.reset(); }).call(this); } Card.prototype.animateRotation = function(){ if( this.isPlaying ) return; // reset current state this.reset(); this.isPlaying = true; var self = this; var value = 1; var step = 0.05; this.intervalId = setInterval(function(){ value = Math.round( ( value - step ) * 100 )/ 100; if( !value ){ step *= -1; self.turn(); } if( value >= 1 ){ clearInterval( self.intervalId ); } self.scale( value ) }, 10 ); }; Card.prototype.turn = function(){ if( hasClass( this.front, "hidden" ) ){ this.currentSide = this.front; hide( this.back ); show( this.front ); } else { this.currentSide = this.back; show( this.back ); hide( this.front ); } }; Card.prototype.reset = function(){ clearInterval( this.intervalId ); this.isPlaying = false; // hide back and show front side hide( this.back ); show( this.front ); // set front side as default this.currentSide = this.front; this.scale( 1 ); }; Card.prototype.scale = function( v ){ this.currentSide.style.transform = "scaleX(" + v + ")"; }; Card.prototype.select = function(){ if( !this.selected ){ this.selected = true; } this.animateRotation(); }; /*-------------------------------------------------------------------*/ /*-------------------------------Common------------------------------*/ /*-------------------------------------------------------------------*/ function hide(el){ addClass( el, "hidden" ); } function show(el){ removeClass( el, "hidden" ); } /** * remove class[es] from element * @param {Element} el * @param {String} cls - it may be one class, or some classes separated with space */ function removeClass( el, cls ){ var removable = cls.replace(/\s{2,}/gi, "").split(" "); var classes = el.className.split(" "); var i, j; for( i = 0; i < classes.length; i++ ){ for( j = 0; j < removable.length; j++ ){ if( classes[i] === removable[j] ){ classes.splice( i, 1 ); // decrease i, for duplicate classes i--; // out of cycle continue; } } } el.className = classes.join(" "); } /** * add class[es] from element * @param {Element} el * @param {String} cls - it may be one class, or some classes separated with space */ function addClass( el, cls ){ var added = cls.replace(/\s{2,}/gi, "").split(" "); var classes = el.className.split(" "); var i, j; // if element has no classes if( !el.className ){ el.className = added.join(" "); return; } for( i = 0; i < classes.length; i++ ){ for( j = 0; j < added.length; j++ ){ if( classes[i] === added[j] ){ added.splice( j, 1 ); } } } el.className = classes.concat( added ).join(" "); } /** * check class availability * @param {Element} el * @param {String} cls */ function hasClass( el, cls ){ var classes = el.className.split(" "); var i; for( i = 0; i < classes.length; i++ ){ if( classes[i] === cls ){ return true; } } return false; } window.mheContpract = window.mheContpract || {}; window.mheContpract["cards"] = { initialize: function(section){ section.slide = new Practice(section); }, show: function(section){ section.slide.reset(); }, hide: function(section){} }; }()); (function(){ 'use strict'; 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($('
' + 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() { }; window.mheContpract = window.mheContpract || {}; window.mheContpract['custom_dnd_test'] = { initialize: function(section) { section.slide = new DnDSlide(section); }, show: function(section) { section.slide.showSlide(); } }; }());