var CourseManager = function() {
	this.course = {
		pages: { },
		opts: { },
		user: {
			score: 0,
			login: '',
			lesson_location: 0,
			courseStatus: 'nc'
		},
		objs: { },
		to: [ ],
		obj_types: {
			'simple': [
						99, //text
						9, // image
						10, // image drawed
						1, // link point
						11, // link fancybox iframe
						6, // popup point
						4, // point gallery
						17, // point download
						2, // point sound
						3, // point recorded sound
						16, // library image

						60, // iframe

						31, // shape
						],
			'drawed_area': [
						5, // drawed area popup
						43, // drawed area gallery
						41, // drawed area link
						42, // drawed area link iframe
						44 // drawed area download
						],
			'hide_background': [15],
			'scroller': [19],
			'quiz_multiple': [22],
			'quiz_qtext': [23],
			'quiz_dnd': [24],
			'quiz_crossword': [26],
			'quiz_wordsearch': [28],
			'quiz_connect_the_lines': [25],
			'quiz_results': [30],
			'quiz_memory': [27],
			'quiz_boardgame': [29],
			'swf': [12],
			'video': [18],
			'counter': [32],
			'plugins': [0],
			'forms': [
						50, // input
						51, // select
						52, // textarea
						53, // checkbox
						54, // radio
						55 // submit
					]
		}
	};

	this.componentSoundsContainer = $('<div></div>', {
		id: 'component-sounds',
		style: 'display:none'
	});
	this.componentSoundsContainer.appendTo($('body'));

	this.countersData = { };

	this.tempopts = {
		dndtimeouts: [ ]
	};

	this.qclInstance = { };

	this.wcag_active = false;
	this.objectToFocus = false;

	this.isIE = {
		ie7: (Utils.isIE() == 7),
		ie8: (Utils.isIE() == 8),
		ie9: (Utils.isIE() == 9),
		ie10: (Utils.isIE() == 10),
		ie9orOlder: ( (Utils.isIE() == 7) || (Utils.isIE() == 8) || (Utils.isIE() == 9) )
	};

	this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

	this.browser = {
		firefox: !(window.mozInnerScreenX == null)
	};

};

/* -------------- INIT / REFRESH  ------------------- */

CourseManager.prototype.init = function(pageID) {
	var _that = this;

    _that.initLayout();

    _that.videoObjects = [ ];

    if (_that.course.opts.singleFile) {
    	_that.initOfflineMethods();
    }

    $(document).find('div[actionkey][action="9"] img').each(function() {
    	$(this).attr('src_temp', $(this).attr('src'));
    	$(this).attr('src', 'about:blank');
    });

	// set max score value
	_that.course.opts.score.max = _that.getMaxScoreValue();

    // set max number of pages in course
    _that.course.opts.numberOfPages = Utils.ObjectLength(_that.course.pages);

	// init scorm
	_that.scorm_init();

	// $('a, input, select, checkbox, radio, textarea, form').attr('tabindex', '-1');

    _that.trigger_initCustomEvents();

	// set first page id as active page
    _that.course.opts.active.pageID = _that.getPageByOrder(0).opts.id;

    // set page order
    _that.course.opts.active.pageOrder = 0;

	// set first line of first page as active line
    _that.course.opts.active.line = 0;

	// set first line of first page as active line
    _that.course.opts.active.obj = 0;//_that.getPageByOrder(0).lines[0].objects[0];

    // exported_view or exported folder name
    if (view_true == 'true') {
        _that.course.opts.exportedFolderName = 'exported_view';
    } else {
        _that.course.opts.exportedFolderName = 'exported';
    }

    if (_that.course.opts.tocenabled == "0") {
		_that.L.tocBtn.hide();
    }
    



    _that.drawPages();

	_that.L.mainScreen.css('width', CM.course.opts.dimentions_x);
	_that.L.mainScreen.css('height', CM.course.opts.dimentions_y);
	if( $('#pause').css('left') === '-745px') {
	    $('#skin').css({
	        'width': CM.course.opts.dimentions_x,
	        'height': CM.course.opts.dimentions_y
	    });
	};

	if ( _that.isIE.ie9orOlder ) {
		_that.L.modal = $('<div id="modal"><div class="ie8loader"></div></div>');
	} else {
		_that.L.modal = $('<div id="modal"><div id="circularG"><div id="circularG_1" class="circularG"></div><div id="circularG_2" class="circularG"></div><div id="circularG_3" class="circularG"></div><div id="circularG_4" class="circularG"></div><div id="circularG_5" class="circularG"></div><div id="circularG_6" class="circularG"></div><div id="circularG_7" class="circularG"></div><div id="circularG_8" class="circularG"></div></div></div>');
	}


    _that.L.mainScreen.append(_that.L.modal);
    _that.L.modal.show();
    _that.L.modal.css('height', CM.course.opts.dimentions_y + 'px');

    if (_that.course.opts.singleFile) {
	    _that.L.iframe = $('<div></div>');
    } else {
	    _that.L.iframe = $('<iframe id="insideFrame" style="background:none;visibility:hidden;display:none" onload="this.style.visibility = \'visible\';" width="' + CM.course.opts.dimentions_x + '" height="' + CM.course.opts.dimentions_y + '" frameBorder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen ></iframe>');
		_that.L.mainScreen.append(_that.L.iframe);
    }


    _that.L.soundPage = $('<audio id="page-sound"></audio>');
	_that.L.mainScreen.append(_that.L.soundPage);

    _that.L.soundPoint = $('<audio id="point-sound"></audio>');
	_that.L.mainScreen.append(_that.L.soundPoint);

	// // init project variables setters
	// _that.initProjectVarSetters();


	// check if its an ipad and prepare screen
	var isiPad = navigator.userAgent.match(/iPad/i) != null;
	if(isiPad){
		_that.L.mainScreen.css('overflow-y', 'auto');
	}


    // init titles and logo
    _that.initLogoAndTitles();


	switch (_that.course.opts.resumptionType) {
		// show resumption popup
		case 'popup':
			// debug.log('Show popup!');
			_that.courseResumptionPopup(_that.course.user.lesson_location);

			if (_that.isMobile) {
				_that.showStartButton('start');
			} else {
				_that.initPage('start');
			}

			break;

		// auto load last visited page
		case 'auto':
			// debug.log('Auto load!');
        	var data = {
        		pageID: _that.getPageByOrder(_that.course.user.lesson_location).opts.id
        	}
			if (_that.isMobile) {
				_that.showStartButton( 'loadPageByID', data );
			} else {
        		_that.initPage( 'loadPageByID', data );
			}
			break;

		// simply load first page
		case 'none':
		default:
			// debug.log('Default val!');

			if (_that.isMobile) {
				_that.showStartButton('start');
			} else {
				_that.initPage('start');
			}
		 	break;
	}

    _that.initMenuButtons();
    _that.fullscreenEvents();


    window.onbeforeunload = function() {
    	// zapis do scorm przed wylaczeniem szkolenia
    	_that.checkAndSetCourseStatus();
    	_that.course.user.lesson_location = _that.getPageByID(_that.course.opts.active.pageID).opts.order;
    	_that.page_handleTimer('stop', _that.getPageByID(_that.course.opts.active.pageID));
    	_that.scorm_save();
    	_that.scorm_quit();
    }

    window.onresize = function () {
    	var skin = $('#skin');

    	var skinHeight = skin.height();
    	var windowHeight = $(window).height();
    	var topCalculated = ((windowHeight/2) - (skinHeight/2));

    	var windowWidth = $(window).width();
    	var skinWidth = skin.width();
    	var leftCalculated = ((windowWidth/2) - (skinWidth/2));

    	if (topCalculated < 0) {
    		topCalculated = 0;
    	}
    	if (leftCalculated < 0) {
    		leftCalculated = 0;
    	}
    	skin.css({
    		top: topCalculated + "px",
    		left: leftCalculated + "px"
    	});
    }
    window.onresize();
    $('#skin').css({
    		'margin-top': '0px'
    	});
    $('#skin').fadeIn();

    
};

CourseManager.prototype.renderAllTextElementsToCanvas = function(pageID) {
	var _that = this;

	_that.L.mainScreen.show();

	var elementsTempContainer = $('<div></div>').css({
														position: 'absolute',
														width: '860px',//$('#skin').css('width'), 
														height: '500px',//$('#skin').css('height'),
														top: '0px',
														left: '0px',
														// overflow: 'hidden',
														'z-index': '-1'
													});
	elementsTempContainer.appendTo($('#skin'));

	var pageObjects = _that.getPageObjects(pageID);

	var actionkeyArr = [ ];
	for (var o = pageObjects.length - 1; o >= 0; o--) {
		actionkeyArr.push(pageObjects[o].id);
	}

	debug.log(actionkeyArr);

	var i = actionkeyArr.length;

	var nextStep = function() {
		i--;
		if(i < 0) {
			elementsTempContainer.remove();
			return;
		};


		var ob = _that.course.objs[actionkeyArr[i]];

		debug.log("AKCJA: " + ob.action);

		if (ob.action != 99 || ob.renderedToCanvas === true) { return nextStep(); }



		var screenOb = _that.getScreenObjectByActionkeyFromProject(ob.id);
		var copiedOb = screenOb.find('.simpletext-txt').clone();

		var copiedObjectWrapper = $('<div>').css({
			height: screenOb.css('height'),
			width: screenOb.css('width')
		});

		copiedOb.appendTo(copiedObjectWrapper);
		copiedObjectWrapper.appendTo(elementsTempContainer);
		copiedOb.show();
		copiedObjectWrapper.show();

		debug.log('Przerabiam na canvas: ' + ob.id);
		debug.log(copiedOb[0]);

		html2canvas(
			copiedOb[0],
			{
				onrendered: function(canvas) {
					screenOb.html(canvas);
					copiedObjectWrapper.remove();
					nextStep();
					ob.renderedToCanvas = true;
				}
			}
		);
	}

	nextStep();
};

CourseManager.prototype.showStartButton = function(initType, data) {
	var _that = this;

	var overlay = $('<div>', {
		class: 'mobilestart-overlay'
	});

	var startBtn = $('<div>', {
		class: 'mobilestart-btn'
	});

	startBtn.text(lang[language]['MOBILE_STARTBTN']);

	overlay.append(startBtn);

	_that.L.mainScreen.append(overlay);

	startBtn.click(function() {
		overlay.remove();
		_that.initPage(initType, data);
	});
};

CourseManager.prototype.drawPages = function() {
	var _that = this;

	if (isUndefined(_that.course.opts.score.originalMax)) {
		_that.course.opts.score.originalMax = _that.course.opts.score.max;
	}

	if (_that.course.opts.drawedFromScorm !== true) {

		var drawData = _that.course.opts.drawPagesData.draws;

		for (var draw in drawData) {
			var singleDrawData = drawData[draw];

			var pickedItems = Utils.getRandomArrayElements(singleDrawData.pagesToDraw, singleDrawData.opts.amountToDraw);

			for (var i = singleDrawData.pagesToDraw.length - 1; i >= 0; i--) {
				var pageID = singleDrawData.pagesToDraw[i];
				if (pickedItems.indexOf(pageID) === -1) {
					var pageData = _that.getPageByID(pageID);
					if ( isObject(pageData) ) {
						pageData.opts.notDrawed = true;

						var pageObjects = _that.getPageObjects(pageID);

						for (var pageOb = pageObjects.length - 1; pageOb >= 0; pageOb--) {
							var pageObject = pageObjects[pageOb];
							pageObject.notDrawed = true;
							if (pageObject.status === 1 && pageObject.score > 0) {
								_that.course.opts.score.max -= pageObject.score;
							}
						};

						_that.course.opts.numberOfPages--;
					}
				}
			};
		}


		var numberOfPages = Utils.ObjectLength(_that.course.pages);

		var properOrder = 0;

		for (var p = 0; p < numberOfPages; p++) {
			var pageData = _that.getPageByOrder(p);
			if (pageData.opts.notDrawed !== true) {
				pageData.opts.order = properOrder;
				properOrder++;
			} else {
				pageData.opts.order = -1;
			}
		}
	}
};

CourseManager.prototype.initSoundManager = function() {
	var _that = this;

	// debug.log("INITNITNTIN");
	// debug.log(window.soundManager);
    // init sound manager
    if (_that.course.opts.initSoundManager !== true) {

	    if (_that.course.opts.singleFile) {
			_that.soundManager = window.soundManager;
		} else {
			_that.soundManager = window.frames[0].window.soundManager;
		}

		_that.soundManager.audioFormats.mp3.required = false;
		_that.soundManager.consoleOnly = true;
		_that.soundManager.useHTML5Audio = true;
		_that.soundManager.preferFlash = false;
		_that.soundManager.debugFlash = false;
		_that.soundManager.ignoreFlash = true;
	    if (_that.course.opts.singleFile) {
			_that.soundManager.setup({ html5: {usingFlash: false}, html5Only: true, preferFlash: false, debugMode: true });
		} else {
			_that.soundManager.setup({ url: '../../../../content_template/swf/', html5Only: true, preferFlash: false, debugMode: true, debugFlash: true });
		}

		_that.soundManager.html5.usingFlash = false;

		_that.course.opts.initSoundManager = true;
    }
};

CourseManager.prototype.simulateKeyPress = function(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}

CourseManager.prototype.initKeyBindings = function(key) {
	var _that = this;

	var selectedElement;
	if (_that.course.opts.singleFile) {
		selectedElement = _that.L.mainScreen.parent().find(':focus');
	} else {
		selectedElement = _that.L.scr.find(':focus');
	}

	switch (key.which) {
		// right arrow
		// case 39:
		// 	if (!(_that.L.nextBtn.hasClass('locked'))) {
		// 		_that.initPage('next');
		// 	}
		// 	break;

		// // left arrow
		// case 37:
		// 	if (!(_that.L.prevBtn.hasClass('locked'))) {
		// 		_that.initPage('previous');
		// 	}
		// 	break;

		// enter
		case 13:
			var tabindexed = $('div[tabindex="' + document.activeElement.tabIndex + '"]');
			if ( typeof tabindexed === "object" ) {
				tabindexed.trigger('click');
			}
			break;

		// space bar()
		case 32:
			debug.log(typeof selectedElement[0]);
			if (typeof selectedElement[0] === "object") {
				if (selectedElement.hasClass('feedback-button')) {
					// selectedElement.trigger('mouseup');
					selectedElement.trigger('mouseup');
				} else if (selectedElement.hasClass('question-submit-btn') || selectedElement.hasClass('qtext-submit')) {
					// selectedElement.trigger('click');
					selectedElement[0].click();
				} else {
					selectedElement[0].click();
					

					// if (selectedElement.hasClass('divsound')) {
					// 	selectedElement.parent().focus();
						// selectedElement.find('a')[0].click();
					// 	// selectedElement.focus();
					// } else if (selectedElement.hasClass('sm2_button')) {
					// 	alert('to jest link');
					// } else {
						// selectedElement[0].click();
					// }
				}
			}


			break;

		// n
		case 78:
			var ob = _that.getObjectByID(_that.L.scr.find('.quiz[dnd]').first().attr('actionkey'));
			
			if (selectedElement.data('draggable')) {
				_that.draggingElement = selectedElement;
				try {
					if (_that.course.opts.euroforum === true) {
						_that.dndSounds.elemPickedSound[0].play();
					}
				} catch(msg) {
					debug.log(msg);
				}
			}

			break;

		// m
		case 77:
			if (selectedElement.data('droppable') && typeof _that.draggingElement === "object" && !_that.draggingElement.draggable('option', 'disabled')) {
				var ob = _that.getObjectByID(_that.L.scr.find('.quiz[dnd]').first().attr('actionkey'));
				var thisObject = _that.getScreenObjectByActionkey(selectedElement.attr('actionkey'));
				var screenOb = _that.L.scr.find('.quiz[dnd]').first();

				var draggedObject = _that.getObjectByID(_that.draggingElement.attr('actionkey'));

				// if (!draggedObject.droppedwithkeyboard) {
					draggedObject.droppedwithkeyboard = true;
					_that.quiz_dndHandleAction('start', ob, screenOb, {draggedObject:_that.draggingElement});
					_that.quiz_dndHandleAction('drop', ob, screenOb, {droppableObject:_that.draggingElement,thisObject:thisObject,keyboard:true});	

				// }
			}

			break;

		// tab
		case 9:
			if (selectedElement !== false) {
				_that.activeTabIndexObject = selectedElement;
			}
			
			break;
	}

	// debug.log(document.activeElement.tabIndex);

	return true;
};

CourseManager.prototype.initProjectVarDefautBindings = function() {
	var _that = this;

	for (var varID in _that.course.opts.trigger) {

		var elems = _that.findElementsDirectlyContainingText(_that.L.scr[0], '{%'+ _that.course.opts.trigger[varID].pvarname +'%}');

		$(elems)
				.html(function() {
					var oldText = this.textContent;
					searchFor = "{%"+ _that.course.opts.trigger[varID].pvarname + "%}";
					var reg = new RegExp(searchFor, "g");
					var newText = oldText.replace(reg, '<span pvarbind="'+ _that.course.opts.trigger[varID].varhash +'">' + _that.course.opts.trigger[varID].pvarvalue + '</span>');
					return newText;
				});

				
	}
};

CourseManager.prototype.refreshAllProjectVariablesOnScreen = function() {
	var _that = this;

	for (var varID in _that.course.opts.trigger) {

		debug.log(_that.course.opts.trigger[varID]);

		_that.L.scr
			.find('*[pvarbind="'+ _that.course.opts.trigger[varID].varhash +'"]')
			.text(_that.course.opts.trigger[varID].pvarvalue);
				
	}
};

CourseManager.prototype.initMenuButtons = function() {
	var _that = this;

	if (!_that.course.opts.singleFile) {
		$(document).keyup(function(e) { _that.initKeyBindings(e); });
	}
	
	// _that.L.iframe.contents().keyup(function(e) { _that.initKeyBindings(e); });
	// _that.L.iframe.contents().on('keyup', 'document', function() { _that.initKeyBindings(); });

	// next screen button
	_that.L.nextBtn.click(function() {
		if (!(_that.L.nextBtn.hasClass('locked'))) {
			_that.initPage('next');
		}
	});	

	// previous screen button
	_that.L.prevBtn.click(function() { 
		if (!(_that.L.prevBtn.hasClass('locked'))) {
			_that.initPage('previous'); 
		}
	});

	// toc button
	_that.L.tocBtn.click(function() { _that.openTocWindow(); });

	// init toc as jquery dialog
	if (_that.L.tocBtn.css('display') != 'none') {
		_that.L.tocScreen.dialog({
			title: lang[language]['TOC_TITLE'],
			autoOpen: false,
			resizable: false,
			draggable: false,
			modal: true,
			// position: { my: "center", at: "center", of: skin },
			// show: {
			// 	effect: "fade",
			// 	duration: 400
			// },
			// hide: {
			// 	effect: "fade",
			// 	duration: 400
			// },
			width: 600,
			height: 340
		});
	} else {
		_that.L.tocScreen.css('display', 'none');
	}



	// TODO: zmieniÄ‡ ten help file w create.php na czesc obiektu zeby wyszko bylo spojne
    if (help_file != '') {
        _that.L.helpScreen.text('').append('<img class="help-img" src="help/' + help_file + '" />');
        help_size_h = parseInt((help_size_h * 700) / help_size_w);
        help_size_w = 720;

        var status_screen_h = help_size_h;
        if ((help_size_h + 38) < 450)
            status_screen_h += 38;
            
		// init help screen as jquery dialog
		_that.L.helpScreen.dialog({
			title: _that.course.opts.helpTitle,
			autoOpen: false,
			resizable: false,
			draggable: false,
			modal: true,
			position: { my: "center", at: "center", of: skin },
			show: {
				effect: "fade",
				duration: 400
			},
			hide: {
				effect: "fade",
				duration: 400
			},
			width: 'auto',
			height: 'auto'
		});
    	// $('.help-img').css('width', help_size_w + 'px').css('height', help_size_h + 'px');


    	
	    // help screen button
		_that.L.helpBtn.click(function() { _that.L.helpScreen.dialog('open'); });
    } else {
        _that.L.helpBtn.css('opacity', '0.5').css('cursor', 'pointer');
    }


    // MUTE
    _that.L.muteBtn.click(function() { _that.setSoundOption('mute_unmute'); });
    
    // Sound controls
    _that.L.soundPlay.click(function() {
    	_that.setSoundOption('play');
    });
    _that.L.soundPause.click(function() {
    	_that.setSoundOption('pause');
    });
    _that.L.soundStop.click(function() {
    	_that.setSoundOption('stop');
    });

    var onSliderChange = function(event, data) {
		if (data.value !== 1) {
			if (_that.course.opts.singleFile) {
    			_that.L.scr.css({
    				zoom: data.value,
    				'-moz-transform': 'scale('+data.value+')',
    				'-moz-transform-origin': '0px 0px'
    			});
    			_that.L.mainScreen.css('overflow', 'auto');
    			_that.L.scr.css({
    				overflow: 'auto'
    			});
			} else {
    			_that.L.scr.css({
    				zoom: data.value,
    				'-moz-transform': 'scale('+data.value+')',
    				'-moz-transform-origin': '0px 0px'
    			});
    			_that.L.scr.parent().css({
    				overflow: 'visible'
    			});
    			_that.L.scr.parent().parent().css({
    				overflow: 'visible'
    			});
    		}
		} else {
			if (_that.course.opts.singleFile) {
    			_that.L.scr.css({
    				zoom: 1,
    				'-moz-transform': 'scale(1)'
    			});
    			_that.L.scr.css({
    				'overflow-x': 'hidden'
    			});
			} else {
    			_that.L.scr.css({
    				zoom: 1,
    				'-moz-transform': 'scale(1)'
    			});
    			_that.L.scr.parent().css({
    				'overflow-x': 'hidden'
    			});
    			_that.L.scr.parent().parent().css({
    				'overflow-x': 'hidden'
    			});
    		}
		}

		scaleFactor = data.value;

        if (document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement) {
        	var fss = _that.fullscreenScale();

        	scaleFactor = data.value * fss;
        }
    }

    // zoom slider
    _that.L.zoomSlider.slider({
    	min: 1,
    	step: 0.1,
    	max: 2,
    	value: 1,
    	slide: function(event, data) {
    		onSliderChange(event, data);
    	},
    	change: function(event, data) {
    		onSliderChange(event, data);
    	}
    }).on('slide', function() {
  		$(this).slider('option', 'slide').apply(this, arguments);
	});
	_that.L.zoomSlider.find('a').attr('tabindex', '-1');

    // sound slider
    _that.L.soundSlider.slider({
    	min: 0,
    	step: 1,
    	max: 100,
    	value: _that.course.opts.sound.volume*100,
    	slide: function(event, data) {
    		_that.setSoundOption('setVolume', {volume: data.value});
    	}
    });
    _that.L.soundSlider.find('a').attr('tabindex', '-1');


    // toc buttons
    $(document).on('click', '.toc-gotoscreen', function(){
    	_that.L.tocScreen.dialog( "close" );
    	
    	var data = {
    		pageID: parseInt($(this).attr("id"))
    	};
    	_that.initPage('loadPageByID', data); 
    });

    $(document).on('click', '#fullscreen', function() {

        if (typeof document.fullscreen !== "undefined") { (document.fullscreen) ? _that.exitFullscreen() : _that.launchFullscreen(document.documentElement); }
        if (typeof document.mozFullScreen !== "undefined") { (document.mozFullScreen) ? _that.exitFullscreen() : _that.launchFullscreen(document.documentElement); }
        if (typeof document.webkitIsFullScreen !== "undefined") { (document.webkitIsFullScreen) ? _that.exitFullscreen() : _that.launchFullscreen(document.documentElement); }
        if (typeof document.msFullscreenElement !== "undefined") { (document.msFullscreenElement) ? _that.exitFullscreen() : _that.launchFullscreen(document.documentElement); }

    	// _that.fullscreenScale();
    });
};

CourseManager.prototype.fullscreenEvents = function() {
	var _that = this;

    document.addEventListener("fullscreenchange", function () {
        setTimeout(function() {
            var frame = $('#skin');
            (document.fullscreen) ? _that.setScale(frame, _that.fullscreenScale()) : _that.setScale(frame, 1);
        }, 500);
    }, false);
     
    document.addEventListener("mozfullscreenchange", function () {
        setTimeout(function() {
            var frame = $('#skin');
            (document.mozFullScreen) ? _that.setScale(frame, _that.fullscreenScale()) : _that.setScale(frame, 1);
        }, 500);
    }, false);
     
    document.addEventListener("webkitfullscreenchange", function () {
        setTimeout(function() {
            var frame = $('#skin');
            (document.webkitIsFullScreen) ? _that.setScale(frame, _that.fullscreenScale()) : _that.setScale(frame, 1);
        }, 500);
        
    }, false);
     
    document.addEventListener("MSFullscreenChange", function () {
        setTimeout(function() {
            var frame = $('#skin');
            (document.msFullscreenElement) ? _that.setScale(frame, _that.fullscreenScale()) : _that.setScale(frame, 1);
        });
    }, false);
};

CourseManager.prototype.setScale = function(obj, val)
{
    var scaleValue = 'scale(' + val + ')';
    
    obj .css("-webkit-transform", scaleValue)
        .css("-moz-transform", scaleValue)
        .css("-ms-transform", scaleValue)
        .css("-o-transform", scaleValue)
        .css("transform", scaleValue);
             
	scaleFactor = val;
	debug.log('scaleFactor: ' + scaleFactor);
}

CourseManager.prototype.launchFullscreen = function(element) {
	$('#fullscreen').addClass('fullscreen-exit');
    if(element.requestFullscreen) {
        element.requestFullscreen();
    } else if(element.mozRequestFullScreen) {
        element.mozRequestFullScreen();
    } else if(element.webkitRequestFullscreen) {
        element.webkitRequestFullscreen();
    } else if(element.msRequestFullscreen) {
        element.msRequestFullscreen();
    }
}

CourseManager.prototype.exitFullscreen = function() {
	var _that = this;

	$('#fullscreen').removeClass('fullscreen-exit');
    if(document.exitFullscreen) {
        document.exitFullscreen();
    } else if(document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
    } else if(document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    } else if(document.msExitFullscreen) {
        document.msExitFullscreen();
    }

    _that.L.zoomSlider.slider({value: 1});

    // _that.L.zoomSlider.trigger('change');
}

CourseManager.prototype.fullscreenScale = function() {
    var ifcontent =  $('#skin');

    var ww = $(window).width() - 50;
    var wh = $(window).height() - 50;
    var iw = ifcontent.width();
    var ih = ifcontent.height();
    var w = ww / iw;
    var h = wh / ih;

    if (w > h) {
        w = h;
    }
    return w;
};

CourseManager.prototype.initLayout = function() {
	this.L = {
		// main containers
		scr: null,
		mainScreen: $('#screen'),
		iframe: null,

		// modal
		modal: $('#modal'),

		// feedback
		feedbackWrapper: null,
		feedbackBtn: null,

		// NEXT & PREV
		nextBtn: $('#next'),
		prevBtn: $('#previous'),

		// page counter
		pageCounter: $('#counter'),

		// TOC
		tocBtn: $('#toc'),
		tocScreen: $('#toc-screen'),

		// HELP
		helpBtn: $("#status"),
		helpScreen: $("#status-screen"),

		zoomSlider: $('#zoom-slider'),

		soundSlider: $('#sound-slider'),

		// progressbar
		progressbar: $('#progressbar'),

		// MUTE
		muteBtn: $('#zoom'),

		// SOUND controls
		soundPlay: $('#play'),
		soundPause: $('#pause'),
		soundStop: $('#stop'),

		// logo
		logo: $('#logo'),

		// page titles
		pageTitle: $('#pagename')
	};
};

CourseManager.prototype.initOfflineMethods = function() {
	var _that = this;

	_that.initOfflineLayout();
	_that.initSoundManager();

	if (_that.course.opts.euroforum === true) {
		_that.initDndSounds();
	}

	$(window).keyup(function(e) {
	// $(window).keypress(function(e) {
		_that.initKeyBindings(e); 
	});

	// $('*').attr('role', 'region');
};

CourseManager.prototype.initDndSounds = function() {
	var _that = this;

	_that.dndSounds = {
		elemDroppedSound: $('<audio id="dndsounds-elemdropped"></audio>'),
		elemPickedSound: $('<audio id="dndsounds-elempicked"></audio>'),
		elemBadAnswer: $('<audio id="dndsounds-droppedbad"></audio>')
	};

	_that.dndSounds.elemDroppedSound.append($('<source/>', {
		type: 'audio/mpeg',
		src: './sounds/dropped.mp3'
	}));

	_that.dndSounds.elemPickedSound.append($('<source/>', {
		type: 'audio/mpeg',
		src: './sounds/picked.mp3'
	}));

	_that.dndSounds.elemBadAnswer.append($('<source/>', {
		type: 'audio/mpeg',
		src: './sounds/droppedbad.mp3'
	}));

	// _that.dndSounds.elemDroppedSound.append('<source type="audio/mpeg" src="./sounds/dropped.mp3">');
	// _that.dndSounds.elemPickedSound.append('<source type="audio/mpeg" src="./sounds/picked.mp3">');


	_that.L.mainScreen.append(_that.dndSounds.elemDroppedSound);
	_that.L.mainScreen.append(_that.dndSounds.elemPickedSound);
	_that.L.mainScreen.append(_that.dndSounds.elemBadAnswer);

};

CourseManager.prototype.initOfflineLayout = function() {
	var _that = this;

	_that.L.feedbackBtn = $('.feedback-button');
	_that.L.feedbackWrapper = $('.feedback-overlay');


	_that.L.feedbackWrapper.appendTo(_that.L.mainScreen);

	_that.L.feedbackBtn.on('mouseup', function() { 
		// _that.L.feedbackWrapper.hide(); 
		_that.L.feedbackWrapper.css({
			// visibility: 'hidden',
			position: 'relative',
			diplay: 'none'
			// 'z-index': '-1'
		});
    	_that.L.feedbackBtn.removeAttr('tabindex');
		// _that.L.feedbackWrapper.remove();
	});
};

CourseManager.prototype.initProjectSound = function() {
	var _that = this;

	// TODO: sound presentation
    if (_that.course.opts.sound.filename !== 'none') {
        var loop = '';
        if (_that.course.opts.sound.loop)
            loop = ' loop';
        
        $('body').append('<audio id="sound-presentation" src="sound/' + _that.course.opts.sound.filename + '" autoplay' + loop + '></audio>');
        try {
        	$('#sound-presentation').get(0).volume = _that.course.opts.sound.volume;
        } catch(msg) {
    		debug.log(msg);
        }
        
    }
};

CourseManager.prototype.initLogoAndTitles = function() {
	var _that = this;

	// logo
    if (_that.L.logo.push() && _that.course.opts.logo.filename != '') {
        var logo_w = _that.L.logo.width();
        var logo_h = _that.L.logo.height();
        
        if (logo_h < logo_w) {
            _that.course.opts.logo.logoWidth = parseInt((logo_h * logo_w) / _that.course.opts.logo.logoHeight);
            _that.course.opts.logo.logoHeight = logo_h;
        }
        
        var logo_top = 0;
        if (_that.course.opts.logo.logoHeight < logo_h) {
            logo_top = parseInt((logo_h - _that.course.opts.logo.logoHeight) / 2);
        }
        
        _that.L.logo.append('<img src="logo/' + _that.course.opts.logo.filename + '" style="margin-top:' + logo_top + 'px;" />');
    } else {
        _that.L.logo.css('opacity', '0');
    }


    // titles
	if (_that.course.opts.showTitles == 0)
	    _that.L.pageTitle.hide();
};

CourseManager.prototype.openTocWindow = function() {
	var _that = this;

	var content = $('#toc-end');
	
    content.text('');

    var numberOfPages = Utils.ObjectLength(_that.course.pages);

    for (var p = 0; p < numberOfPages; p++) {

    	var pageData = _that.getPageByOrder(p);

    	if (isObject(pageData) && pageData.opts.notDrawed !== true) {
	    	if (pageData.opts.compl) {
	    		content.append('<div class="toc-gotoscreen" id="' + _that.getPageByOrder(p).opts.id + '" type="button"><span style="position:absolute;font-size:23px;color:green;right:0px;top:0px;font-family:\'Comic Sans MS\'">&#10004;</span><span class="toc-page-counter">'+ (p+1) +'</span><div class="toc-pagename">' + _that.getPageByOrder(p).opts.name + '</div></div>');
	    	} else {
	    		content.append('<div class="toc-gotoscreen" id="' + _that.getPageByOrder(p).opts.id + '" type="button"><span class="toc-page-counter">'+ (p+1) +'</span><div class="toc-pagename">' + _that.getPageByOrder(p).opts.name + '</div></div>');
	    	}    	
    	}
    };

    _that.L.tocScreen.dialog('open');
};

CourseManager.prototype.closeAllDialogs = function() {
	var _that = this;

	$(".ui-dialog-content").dialog("close");
};

CourseManager.prototype.initPage = function(cmd, data) {
	var _that = this;

	if (_that.course.opts.pageIsLoading)
		return false;


	var newPageOrder = _that.course.opts.active.pageOrder;

	_that.course.opts.pageIsLoading = true;


	_that.page_handleTimer('stop', _that.getPageByID(_that.course.opts.active.pageID));

	switch (cmd) {

		case 'next':
	        newPageOrder = _that.course.opts.active.pageOrder + 1;

			// 
			break;

		case 'previous':
	        newPageOrder = _that.course.opts.active.pageOrder - 1;
			break;

		case 'loadPageByID':
			if( typeof _that.getPageByID(data.pageID) === "object" ) {
				newPageOrder = _that.getPageByID(data.pageID).opts.order;
			}			
			break;

		case 'start':
	        var par = Utils.getURLParam();
	        for (var paramName in par) {
	            if (paramName == 'pageid') {
	                var page = _that.getPageByID(par[paramName]);
	                if ( isObject(page) && page.opts.notDrawed !== true) {
	                	newPageOrder = page.opts.order;
	                }
	            }
	        }
			break;

	}


	// if its first or last page then do nothing
	if ( newPageOrder < 0 || newPageOrder > (_that.course.opts.numberOfPages-1) ) {
		return;
	}



	// close all opened dialogs
	if (_that.course.opts.singleFile) {
		_that.closeAllDialogs();
	}

	// if its a normal page then populate main page order and go along
	_that.course.opts.active.pageOrder = newPageOrder;


	// clear active line and object to start from begining
    _that.course.opts.active.line = 0;
    _that.course.opts.active.obj = 0;


	// clear all timers for objects and lines
	_that.clearAllTimers();

	var previousPageID = _that.course.opts.active.pageID;

	// set new page id
 	_that.course.opts.active.pageID = _that.getPageByOrder(_that.course.opts.active.pageOrder).opts.id;

	_that.preparePageComponentsSounds(_that.course.opts.active.pageID);

 	// set elements clicked option to 0
 	var pageElems = _that.getPageObjects(_that.course.opts.active.pageID);
 	for (var elem in pageElems) {
 		pageElems[elem].clicked = 0;
 	}

	// debug.log("Initing page, id: " + _that.course.opts.active.pageID + ", command: " + cmd);
	
    


	if (!_that.course.opts.singleFile) {

		// show modal and hide iframe
		_that.L.modal.fadeIn();
		_that.L.iframe.fadeOut(500);

	    // timeout for smooth page loading
	    setTimeout(function() {
			// load new content to iframe
			_that.L.iframe
				.attr("src", _that.course.opts.exportedFolderName + "/"+_that.course.opts.active.pageID+"/page.html")
				.one("load", function() {
				// .load("exported" + view_true_dir + "/"+_that.course.opts.active.pageID+"/page.html", function() {

					// refresh main container with objects
				    _that.L.scr = _that.L.iframe.contents().find('#divimg');

				 	// refresh all triggers
				 	_that.trigger_refreshObjectsOnLoadedPage(_that.course.opts.active.pageID);

				    // init project variable bindings
				    _that.initProjectVarDefautBindings();
				    

				    // refresh feedback wrapper
				    _that.L.feedbackWrapper = _that.L.iframe.contents().find('.feedback-overlay');
					// feedback button
					_that.L.feedbackBtn = _that.L.feedbackWrapper.find('.feedback-button');
					_that.L.feedbackBtn.on('mouseup', function() { _that.L.feedbackWrapper.fadeOut(); });
				    
					_that.L.iframe.contents().keyup(function(e) { _that.initKeyBindings(e); });

					// refresh page title
					_that.L.pageTitle.text(_that.course.pages[_that.course.opts.active.pageID].opts.name);

				    // hide all objects
				    _that.L.scr.find('div[actionkey]').css({
				    	display: 'none'
				    });

				    // refresh page counter
				    _that.refreshPageCounter();

				    // refresh progressbar
				    _that.refreshProgressbar();

				    _that.course.to = [ ];

				    // set new lesson location
				    _that.course.user.lesson_location = newPageOrder;

				    // enable navigation, then check all things and disable it if nessessary
				    _that.navigationButtonsHandler('enableAll');

				    _that.setPageOptions('init', _that.getPageByOrder(_that.course.opts.active.pageOrder));

				    // if its first page then disable prev btn
				    if (_that.course.opts.active.pageOrder === 0) {
				    	_that.navigationButtonsHandler('disablePrev');
				    }

				    // if its last page then disable next btn
				    if ( _that.course.opts.active.pageOrder === (_that.course.opts.numberOfPages-1) ) {
				    	_that.navigationButtonsHandler('disableNext');
				    }
				    
				    _that.L.zoomSlider.slider('value', 1);

					_that.initSoundManager();


			    	// add page trigger
			    	_that.trigger_addEvent("page", _that.course.pages[_that.course.opts.active.pageID].opts);


				    setTimeout (function() {

				    	try {
							_that.L.modal.fadeOut();
							_that.L.iframe.fadeIn();
							_that.L.soundPoint[0].pause();
							_that.soundManager.stopAll();
							_that.refreshAllProjectVariablesOnScreen();
							// _that.renderAllTextElementsToCanvas(_that.course.opts.active.pageID);
			    		} catch(msg) { 
			    			debug.log(msg);
			    		}
				    	
					    // launch timeline!
					    _that.launchTimeline(
					    	_that.course.opts.active.pageID,
					    	_that.getLineByOrder(_that.course.opts.active.pageID, 0),
					    	0
					    	);


					    // load presentation sound
					    if (!_that.course.opts.projectSoundLoaded){
					    	_that.initProjectSound();
					    	_that.course.opts.projectSoundLoaded = true;
					    }

					    if (!_that.isMobile) {
							// init page sounds, pause everything else
							_that.initPageSound(_that.course.opts.active.pageID);		
					    }

						
					    _that.course.opts.pageIsLoading = false;

				    }, 500);
					
			});

		}, 500);
	
		if (_that.isMobile) {
			// init page sounds, pause everything else
			_that.initPageSound(_that.course.opts.active.pageID);


		}


	} else {

		_that.L.mainScreen.find('.activepage').fadeOut(300);
		_that.L.feedbackWrapper.fadeOut(300);

		var modalShowTimeout = setTimeout(function() {
			_that.L.modal.fadeIn();
		}, 1000);


		// timeout for smooth page loading
	    setTimeout(function() {

	    	// delete all video objects
			for (var videoOb = _that.videoObjects.length - 1; videoOb >= 0; videoOb--) {
				_that.videoObjects[videoOb].html('');
			};
			_that.videoObjects = [ ];

		    _that.setPageOptions('clearAllEvents', _that.getPageByID(previousPageID));

			// load new content
			_that.L.scr = _that.L.mainScreen.find('div[pageid="'+_that.course.opts.active.pageID+'"]');
			
		 	// refresh all triggers
		 	_that.trigger_refreshObjectsOnLoadedPage(_that.course.opts.active.pageID);

			$('.activepage').removeClass('activepage');

			_that.L.scr.addClass('activepage');

		    _that.L.scr.find('div[actionkey][action="9"] img').each(function() {
		    	$(this).attr('src', $(this).attr('src_temp'));
		    });


		    // init project variable bindings
		    _that.initProjectVarDefautBindings();

			// refresh page title
			_that.L.pageTitle.text(_that.course.pages[_that.course.opts.active.pageID].opts.name);

		    // hide all objects
		    _that.L.scr.find('div[actionkey]').css({
		    	display: 'none'
		    });

		    // refresh page counter
		    _that.refreshPageCounter();

		    // refresh progressbar
		    _that.refreshProgressbar();

		    _that.course.to = [ ];

		    // set new lesson location
		    _that.course.user.lesson_location = newPageOrder;

		    // enable navigation, then check all things and disable it if nessessary
		    _that.navigationButtonsHandler('enableAll');


		    _that.setPageOptions('init', _that.getPageByOrder(_that.course.opts.active.pageOrder));

		    // if its first page then disable prev btn
		    if (_that.course.opts.active.pageOrder === 0) {
		    	_that.navigationButtonsHandler('disablePrev');
		    }

		    // if its last page then disable next btn
		    if ( _that.course.opts.active.pageOrder === (_that.course.opts.numberOfPages-1) ) {
		    	_that.navigationButtonsHandler('disableNext');
		    }

		    _that.L.zoomSlider.slider('value', 1);

	    	// add page trigger
	    	_that.trigger_addEvent("page", _that.course.pages[_that.course.opts.active.pageID].opts);

	    	var bgUrl = _that.L.scr.find('#divimg').css('background-image').replace('url(','').replace(')','');

			var backgroundImage = new Image();

			if (bgUrl != "none") {
		    	backgroundImage.onload = function() {
		    		launchPage();
			    };
		    	backgroundImage.onerror = function() {
		    		launchPage();
			    };
			    backgroundImage.src = bgUrl;
			} else {
				setTimeout (function() {
		    		launchPage();
				}, 300);
			}


			var launchPage = function() {

				try {
					// show screen with page content
					_that.L.scr.fadeIn();
					// hide modal
					_that.L.modal.fadeOut();
					clearTimeout(modalShowTimeout);
					_that.L.soundPoint[0].pause();
					_that.soundManager.stopAll();
					_that.refreshAllProjectVariablesOnScreen();
					// _that.renderAllTextElementsToCanvas(_that.course.opts.active.pageID);

					// scroll page to top if it was scrolled down
					_that.L.scr.scrollTop(0);
				} catch(msg) {
					debug.log(msg);
				}

				_that.objectToFocus = _that.getFirstTabindexOnPage(_that.course.opts.active.pageID);

			    // launch timeline!
			    _that.launchTimeline(
			    	_that.course.opts.active.pageID,
			    	_that.getLineByOrder(_that.course.opts.active.pageID, 0),
			    	0
			    	);


			    // load presentation sound
			    if (!_that.course.opts.projectSoundLoaded){
			    	_that.initProjectSound();
			    	_that.course.opts.projectSoundLoaded = true;
			    }

			    if (!_that.isMobile) {
					// init page sounds, pause everything else
					_that.initPageSound(_that.course.opts.active.pageID);
				}

			    _that.course.opts.pageIsLoading = false;
			};


		}, 300);

	
		if (_that.isMobile) {
			// init page sounds, pause everything else
			_that.initPageSound(_that.course.opts.active.pageID);
		}
	}
};

CourseManager.prototype.buildTimeline = function(cmd, opts) {
	var _that = this;

	// check if command is a string
	if (typeof cmd === "string") {

		// check if command is a string
		switch (cmd) {

			case "setCourseOptions":
			    // set main Course Options
			    _that.course.opts = opts;
				break;

			case "addPage":
			    // add new page to course structure
			    _that.course.pages[opts.id] = { };
			    _that.course.pages[opts.id].lines = {};
			    _that.course.pages[opts.id].opts = opts;
				break;

			case "addLine":
				// add new line on selected page to course structure

			    _that.course.pages[opts.opts.pageID].lines[opts.opts.id] = { };
			    _that.course.pages[opts.opts.pageID].lines[opts.opts.id].objects = [];

			    for (var i = 0; i < opts.objs.length; i++) {
			    	// debug.log("Getting from line: " + opts.opts.id + ", obiekt: " + i);
			    	_that.course.pages[opts.opts.pageID].lines[opts.opts.id].objects.push(_that.getObjectByID(opts.objs[i]));
			    }

			    _that.course.pages[opts.opts.pageID].lines[opts.opts.id].opts = opts.opts;

				break;

			case "addObject":
				// add object to main course objects container 
				_that.course.objs[opts.id] = opts;
				break;
		}
	}
};



CourseManager.prototype.preparePageComponentsSounds = function(pageID) {
	var _that = this;

	this.componentSoundsContainer.html('');

	var pageObjects = this.getPageObjects(pageID);

	for (var i in pageObjects) {
		var component = pageObjects[i];
		var soundPath = _that.course.opts.exportedFolderName + '/' + pageID + '/sounds/' + component.id + '/' + component.sound.filename;

		var componentSound = $('<audio></audio>',{
			controls: 'false',
			class: 'component-sound',
			soundpath: soundPath
		});

		var sourceMP3, sourceOgg;
		// find and replace file source of point sound container
		sourceMP3 = $('<source/>', {
			type: 'audio/mpeg',
			src: soundPath
		});

		var soundPathOGG = soundPath.substring(0, soundPath.length - 3) + "ogg";
		sourceOGG = $('<source/>', {
			type: 'audio/ogg',
			src: soundPathOGG
		});
		
		sourceMP3.appendTo(componentSound);
		sourceOGG.appendTo(componentSound);

		_that.componentSoundsContainer.append(componentSound);

    	try {
        	componentSound[0].load();
        	componentSound[0].pause();
		} catch(msg) {
			_log('ERROR playing sound', msg);
		}

	}
};

CourseManager.prototype.refreshPageCounter = function() {
	var _that = this;

	_that.L.pageCounter.text(
		(_that.course.opts.active.pageOrder+1) + "/" + _that.course.opts.numberOfPages
	)
};

CourseManager.prototype.navigationButtonsHandler = function(cmd) {
	var _that = this;
	
	if (typeof cmd === "string") {
		switch (cmd) {

			case 'disableAll':
				_that.L.nextBtn.addClass('locked').css({opacity: '.3'});
				_that.L.prevBtn.addClass('locked').css({opacity: '.3'});
				break;

			case 'enableAll':
				if ( _that.course.opts.active.pageOrder !== (_that.course.opts.numberOfPages-1) ) {
					_that.L.nextBtn.removeClass('locked').css({opacity: '1'});
				}
				if ( _that.course.opts.active.pageOrder !== 0 ) {
					_that.L.prevBtn.removeClass('locked').css({opacity: '1'});
				}
				break;
				
			case 'disableNext':
				_that.L.nextBtn.addClass('locked').css({opacity: '.3'});
				break;
				
			case 'enableNext':
				_that.L.nextBtn.removeClass('locked').css({opacity: '1'});
				break;
				
			case 'disablePrev':
				_that.L.prevBtn.addClass('locked').css({opacity: '.3'});
				break;
				
			case 'enablePrev':
				_that.L.prevBtn.removeClass('locked').css({opacity: '1'});
				break;

		}
	}
};

CourseManager.prototype.refreshProgressbar = function() {
    var _that = this;

    if (!_that.L.progressbar.push())
        return;

    if (_that.L.progressbar.push() === 1 && _that.L.progressbar.css('display') !== "none") {
        var perc = ((_that.course.opts.active.pageOrder+1) / _that.course.opts.numberOfPages) * 100;
        _that.L.progressbar.find('#progressbar-inside').css('width', perc + "%");
    }
};

CourseManager.prototype.checkAndSetCourseStatus = function() {
	var _that = this;

	if ( _that.course.opts.req.p || _that.course.opts.req.s || _that.course.opts.req.e ) {

		// get page, score and elements status
		var status = _that.getCompletion();

		// temp var 
		var allCompleted = true;

		var setToFailed = false;

		// check if pages are completed
		if (_that.course.opts.req.p) {
			if (!status.pages) {
				allCompleted = false;
			}
		}

		// check all elements for passing
		if (_that.course.opts.req.e) {
			if (!status.elems) {
				allCompleted = false;
			}
		}

		// check if user score is passed
		if (_that.course.opts.req.s) {

			if (allCompleted && status.elems) {
				setToFailed = true;
			}

			if (!status.score) {
				allCompleted = false;
			}
		}


		// if all required elements are completed - set course status to 'completed'
		if (allCompleted) {
			_that.setCourseOption("completed");

		// if one of required elements are not passed - set course status to failed
		} else {

			if (setToFailed) {
				_that.setCourseOption("failed");
			} else {
				_that.setCourseOption("notCompleted");
			}
		}
	} else {
		_that.setCourseOption("completed");
	}
};

CourseManager.prototype.courseResumptionPopup = function(last_location) {
	var _that = this;

	if (last_location !== 0) {
		setTimeout(function() {
		        $('<div />').html( lang[language]['PUB_LASTPAGE'] + (last_location+1) +')' ).dialog({
		                resizable: false,
		                title: lang[language]['PUB_LASTPAGE_CONTINUE'],
		                height:200,
		                modal: false,
		                position: { my: "center", at: "center", of: _that.L.mainScreen },
		                buttons: [
		                        {
		                        	text: "Ok",
		                        	click: function() {
						            	var data = { 
						            		pageID: _that.getPageByOrder(last_location).opts.id
						            	}
						            	_that.initPage( 'loadPageByID', data );
						            	$('.mobilestart-overlay').hide();
			                           	$( this ).dialog("close");
		                        	}

		                        },
		                        {
		                        	text: lang[language]['PUB_CANCEL'],
		                        	click: function() {
		                        		$( this ).dialog("close");
		                        	}

		                        }
		                    ]
		                
		        }).parent().addClass('dialog-lastpage');
		}, 500);
	}
	
};

CourseManager.prototype.bindAnimationInfoToObjects = function(pageID) {
	var _that = this;

	var pageObjects = _that.getPageObjects(pageID);

	for (var ob = pageObjects.length - 1; ob >= 0; ob--) {
		(function(loopObj) {
			// animation start
			_that.getScreenObjectByActionkey(loopObj.id)
									.bind(
										"animationstart webkitAnimationStart oAnimationStart MSAnimationStart", 
										function(){
											loopObj.animations.animationReady = false;
										});

			// animation end
			_that.getScreenObjectByActionkey(loopObj.id)
									.bind(
										"animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", 
										function(){
											loopObj.animations.animationReady = true;
										});
		})(pageObjects[ob]);
	};
};

CourseManager.prototype.playHtmlSound = function(soundPath) {
	var _that = this;


	// check if point has a sound file
	if (soundPath.length > 0) {

		$('#point-sound').remove();

	    _that.L.soundPoint = $('<audio id="point-sound"></audio>');
		_that.L.mainScreen.append(_that.L.soundPoint);
		
		_that.L.soundPoint.html('');

		var sourceMP3, sourceOgg;
		// find and replace file source of point sound container
		sourceMP3 = $('<source/>', {
			type: 'audio/mpeg',
			src: soundPath
		});

		var soundPathOGG = soundPath.substring(0, soundPath.length - 3) + "ogg";
		sourceOGG = $('<source/>', {
			type: 'audio/ogg',
			src: soundPathOGG
		});
		
		sourceMP3.appendTo(_that.L.soundPoint);
		sourceOGG.appendTo(_that.L.soundPoint);
		
    	try {
        	_that.L.soundPoint[0].play();
	    	_that.L.soundPoint[0].volume = _that.course.opts.sound.volume;

	    	if (_that.course.opts.sound.muted) {
	    		_that.L.soundPoint[0].volume = 0;
	    	}
		} catch(msg) {
			debug.log(msg);
		}

	}
};

/* -------------- GET / SET  ------------------- */

CourseManager.prototype.getObjectByID = function(objectName) {
	// return reference to object in main course object container
	return this.course.objs[objectName];
};

CourseManager.prototype.getPageByID = function(id) {
	return this.course.pages[id];
};

CourseManager.prototype.getPageByOrder = function(order) {
	var _that = this;

	for (var page in _that.course.pages) {
		if (_that.course.pages[page].opts.order === order) {
			return _that.course.pages[page];
		}
	}
	return false;
};

CourseManager.prototype.getScreenObjectByActionkey = function(actionkey) {
	if (isObject(this.L.scr)) {
		return this.L.scr.find('div[actionkey="' + actionkey + '"]');
	} else {
		return false;
	}
};

CourseManager.prototype.getScreenObjectByActionkeyFromProject = function(actionkey) {
	return this.L.mainScreen.find('div[actionkey="' + actionkey + '"]');
};

CourseManager.prototype.getLineObjectsNumber = function(pageID, lineID) {
	return this.course
				.pages[pageID]
				.lines[lineID]
				.objects.length;
};

CourseManager.prototype.getLineObjects = function(lineID) {

	if (typeof this.course.pages[this.course.opts.active.pageID].lines[lineID] === "object") {
			return this.course
				.pages[this.course.opts.active.pageID]
				.lines[lineID]
				.objects;
	} else {
		return {};
	}
};

CourseManager.prototype.getPageObjects = function(pageID) {
	var _that = this;

	var pageObjects = [ ];

	for ( var line in _that.course.pages[pageID].lines ) {
		for (var ob = _that.course.pages[pageID].lines[line].objects.length - 1; ob >= 0; ob--) {
			if (typeof _that.course.pages[pageID].lines[line].objects[ob] === "object") {
				pageObjects.push(_that.course.pages[pageID].lines[line].objects[ob]);
			} 
		};
	};

	return pageObjects;
};

CourseManager.prototype.getObjectType = function(ob) {
	var _that = this;


	var object_type = "undefined";

	var object_action_code = parseInt(ob.action);

	if ( !isNaN(object_action_code) ) {
		for (var type in _that.course.obj_types) {
			for (var i = 0; i < _that.course.obj_types[type].length; i++) {
				if (_that.course.obj_types[type].indexOf(object_action_code) !== -1) {
					object_type = type;
				}
			}
		}
	}

	return object_type;
};

CourseManager.prototype.getLineByOrder = function(pageID, order) {
	var _that = this;

    for (var line in _that.course.pages[pageID].lines) {
        if (_that.course.pages[pageID].lines[line].opts.order == order)
        	return _that.course.pages[pageID].lines[line];
    }

    return false;
};

CourseManager.prototype.setPageOptions = function(cmd, page) {
	var _that = this;

	switch (cmd) {
		case 'init':
			if (page.opts.locknavi) {
				_that.navigationButtonsHandler('disableAll');
			} else {
				_that.navigationButtonsHandler('enableAll');
			}

			if (page.opts.lockscroll) {
				if (_that.course.opts.singleFile) {
					$('.activepage').css('overflow', 'hidden');
				} else {
					_that.L.iframe.contents().find("html").css('overflow', 'hidden');
				}
			} else {
				if (_that.course.opts.singleFile) {
				    $('.activepage').css({
				        'overflow-y': 'auto',
				        'overflow-x': 'hidden'
				    });
				} else {
				    _that.L.iframe.contents().find("html").css({
				        'overflow-y': 'auto',
				        'overflow-x': 'hidden'
				    });
				}
			}

			// if page sound is muted then mute it on start
			if (_that.L.scr.find('#sound').push() > 0) {

				try {
					if (_that.course.opts.sound.muted) {
						_that.L.scr.find('#sound').get(0).volume = 0;
					} else {
						_that.L.scr.find('#sound').get(0).volume = _that.course.opts.sound.volume;
					}
					_that.L.scr.find('#sound').get(0).play();
				} catch(msg) {
					debug.log(msg);
				}
				
			}

			// if there is no sound on page - light out sound controls
			if (_that.L.scr.find('#sound > source').push() === 0) {
				_that.L.soundPlay.css('opacity', '0.4').css('cursor', 'default');
				_that.L.soundPause.css('opacity', '0.4').css('cursor', 'default');
				_that.L.soundStop.css('opacity', '0.4').css('cursor', 'default');
			} else {
				_that.L.soundPlay.css('opacity', '1').css('cursor', 'pointer');
				_that.L.soundPause.css('opacity', '1').css('cursor', 'pointer');
				_that.L.soundStop.css('opacity', '1').css('cursor', 'pointer');
			}

			_that.page_handleTimer('start', page);

			var selectedElement;
			if (_that.course.opts.singleFile) {
				selectedElement = _that.L.mainScreen.parent().find(':focus');
				selectedElement.blur();
				debug.log(selectedElement);
			}

			break;

		case 'setComplete': 
			var pageObjs = _that.getPageObjects(page.opts.id);
			var allCompleted = true;

			for (var o in pageObjs) {
				if (pageObjs[o].status === 1 && pageObjs[o].compl === 0 && pageObjs[o].score != 0) {
					allCompleted = false;
				}
			}

			if (allCompleted) {
				page.opts.compl = 1;
				_that.checkAndSetCourseStatus();	
			}
			
			break;

		case 'lockNavigation': 
			_that.navigationButtonsHandler('disableAll');
			break;

		case 'unlockNavigation': 
			if (page.opts.locknavitrigger === false) {
				_that.navigationButtonsHandler('enableAll');
			}
			
			break;

		case 'unlockNavigationTrigger': 
			_that.navigationButtonsHandler('enableAll');
			break;

		case 'lockScroll': 
				if (_that.course.opts.singleFile) {
					$('.activepage').css('overflow', 'hidden');
				} else {
					_that.L.scr.find("html").css('overflow', 'hidden');
				}
			break;

		case 'unlockScroll': 
				if (_that.course.opts.singleFile) {
					$('.activepage').css({
								        'overflow-y': 'auto',
								        'overflow-x': 'hidden'
								    });
				} else {
					_that.L.iframe.contents().find("html").css({
										        'overflow-y': 'auto',
										        'overflow-x': 'hidden'
										    });
				}
			break;

		case 'clearAllEvents':
			debug.log('Clearing all events on page:');
			debug.log(page.opts.id);
			if (typeof page === "object" && _that.L.scr != null) {
				var pageObjects = _that.getPageObjects(page.opts.id);

				var pageHTML = _that.getScreenPageByID(page.opts.id);
				pageHTML.unbind();

				for (var o in pageObjects) {
					
					var screenPageOb = _that.getScreenObjectByActionkey(pageObjects[o].id);
					
					// delete all previousely used animations
					screenPageOb.removeClass(pageObjects[o].animations.animIn);
					screenPageOb.removeClass(pageObjects[o].animations.animInTrigger.animationName);
					screenPageOb.removeClass(pageObjects[o].animations.animOut);
					screenPageOb.removeClass(pageObjects[o].animations.animOutTrigger.animationName);

					// debug.log("Removing classes: ");
					// debug.log(pageObjects[o].animations.animIn);
					// debug.log(pageObjects[o].animations.animInTrigger.animationName);
					// debug.log(pageObjects[o].animations.animOut);
					// debug.log(pageObjects[o].animations.animOutTrigger.animationName);

					if( !isUndefined( pageObjects[o].timeOut ) ){
						pageObjects[o].timeOut.pause();
					} 

					// screenPageOb.unbind();
					// screenPageOb.off('click');

					// if (screenPageOb.data('ui-droppable')) {
					// 	screenPageOb.droppable("destroy");
					// }
					// if (screenPageOb.data('ui-draggable')) {
					// 	screenPageOb.draggable("destroy");
					// }

					// if (pageObjects[o].action == 99) {
					// 	var copiedOb = screenPageOb[0].cloneNode(true);

					// 	var oldCanvas = screenPageOb.find('canvas')[0];

					// 	if (isObject(oldCanvas)) {
					// 		var newCanvas = document.createElement('canvas');
					// 		newCanvas.width  = oldCanvas.width;
					// 		newCanvas.height = oldCanvas.height;

					// 		var destCtx = newCanvas.getContext('2d');
					// 		destCtx.drawImage(oldCanvas, 0, 0);

					// 		$(copiedOb).html(newCanvas);
					// 	}
					// 	screenPageOb[0].parentNode.replaceChild(copiedOb, screenPageOb[0]);
						
					// } 
					// else {

					debug.log(pageObjects[o]);

					if (pageObjects[o]) {
						if ( !isUndefined(pageObjects[o].originalPosition) ) {
							screenPageOb.css({
								top: pageObjects[o].originalPosition.posY + "px",
								left: pageObjects[o].originalPosition.posX + "px"
							})	
						}
						var copiedOb = screenPageOb[0].cloneNode(true);
						screenPageOb[0].parentNode.replaceChild(copiedOb, screenPageOb[0]);
					}
					// }
				}

				_that.L.mainScreen.find('div[pageid="'+page.opts.id+'"] #divimg > .memory-item').remove();
			}
			break;

	}
};

CourseManager.prototype.initPageSound = function(pageID) {
	var _that = this;

	$('#page-sound').remove();

    _that.L.soundPage = $('<audio id="page-sound"></audio>');
	_that.L.mainScreen.append(_that.L.soundPage);

	// _that.L.soundPage[0].pause();
	// _that.L.soundPage.html('');

	var pageObj = _that.getPageByID(pageID);

	if (pageObj.opts.sound.filename.length > 0) {
		// var sourceMP3 = $('<source type="audio/mpeg" src="'+ _that.course.opts.exportedFolderName +'/' + pageID +'/audio/page/'+ pageObj.opts.sound.filename +'"></source>');

		var sourceMP3 = $('<source/>', {
			type: 'audio/mpeg',
			src: _that.course.opts.exportedFolderName +'/' + pageID +'/audio/page/'+ pageObj.opts.sound.filename
		});

		var sourceOGG = $('<source/>', {
			type: 'audio/ogg',
			src: _that.course.opts.exportedFolderName +'/' + pageID +'/audio/page/'+ pageObj.opts.sound.filenameogg
		});

		sourceMP3.appendTo(_that.L.soundPage);
		sourceOGG.appendTo(_that.L.soundPage);
		try {
			if (CM.course.opts.sound.muted) {
				_that.L.soundPage[0].volume = 0;
			}
			// _that.L.soundPage.load();
			// _that.L.soundPage[0].load();
			_that.L.soundPage[0].play();
		} catch(msg) {
			debug.log(msg);
		}
		
		
	}
};

CourseManager.prototype.setSoundOption = function(cmd, data) {
	var _that = this;

	// var sm;
	// if (_that.course.opts.singleFile) {
	// 	sm = window.soundManager;
	// } else {
	// 	sm = window.frames[0].window.soundManager;
	// }
    
    var soundPage = _that.L.soundPage;
    var pointSound = _that.L.soundPoint;//scr.find('#point-sound');
    var soundpresentation = $('#sound-presentation');


    switch (cmd) {

    	case 'mute_unmute':

		    // jesli strona nie jest wyciszona wycisz ja
		    if (!_that.course.opts.sound.muted) {
		        try {
			        // mute main sound for page
			        if (soundPage.push() != 0)
			            soundPage.get(0).volume = 0;
			        
			        if (pointSound.push() != 0)
			            pointSound.get(0).volume = 0;
			        
			        if (soundpresentation.push() != 0)
			            soundpresentation.get(0).volume = 0;
			        
			        // mute all sounds on page
			        _that.soundManager.muteAll();
			        
			        // change main var 
			        _that.course.opts.sound.muted = true;
			        
			        
			        // mute all swf objects on scene
			        _that.L.scr.find('.div-point-swf').each(function(){
			            $(this).flash(
			                    function() {
			                            this.SetVariable('/:swfsound', mutepage);
			                    }
			            );
			        });
			    } catch (msg) {
			    	debug.log(msg);
			    }
		        
		        _that.L.muteBtn.css('background-position', '-5px -95px');
		    }
		    
		    // jesli strona jest juz wyciszona to uruchom dzwieki
		    else {
		        try {
			        // unmute main sound for page
			        if (soundPage.push() != 0)
			            soundPage.get(0).volume = 1;
			        
			        if (pointSound.push() != 0)
			            pointSound.get(0).volume = 1;
			        
			        if (soundpresentation.push() != 0)
			            soundpresentation.get(0).volume = _that.course.opts.sound.volume / 100;
			        
			        // unmute all sounds on page
			        _that.soundManager.unmuteAll();
			        
			        // change main var 
			        _that.course.opts.sound.muted = false;
			        
			        // unmute all swf objects on scene
			        _that.L.scr.find('.div-point-swf').each(function(){
			            $(this).flash(
			                    function() {
			                            this.SetVariable('/:swfsound', mutepage);
			                    }
			            );
			        });
		        } catch (msg) {
		        	debug.log(msg);
		        }
		        _that.L.muteBtn.css('background-position', '-5px -65px');
		    }
    		break;


		case 'mute':
			try {
				// mute main sound for page
		        if (soundPage.push() != 0)
		            soundPage.get(0).volume = 0;
		        
		        if (pointSound.push() != 0)
		            pointSound.get(0).volume = 0;
		        
		        if (soundpresentation.push() != 0)
		            soundpresentation.get(0).volume =0;
		        
		        // mute all sounds on page
		        _that.soundManager.muteAll();
		        
		        // change main var 
		        _that.course.opts.sound.muted = true;
		        
		        
		        // mute all swf objects on scene
		        _that.L.scr.find('.div-point-swf').each(function(){
		            $(this).flash(
		                    function() {
		                            this.SetVariable('/:swfsound', mutepage);
		                    }
		            );
		        });
			} catch (msg) {
				debug.log(msg);
			}

			break;



		case 'play':
	        if (soundPage.push() != 0) {
				try {
					soundPage.get(0).play();
	        		soundPage.get(0).volume = _that.course.opts.sound.volume;
				} catch(msg) {
					debug.log(msg);
				}
	        }
			break;

		case 'pause':
	        if (soundPage.push() != 0) {
	        	try {
					soundPage.get(0).pause();
				} catch(msg) {
					debug.log(msg);
				}
	        }
			break;

		case 'stop':
	        if (soundPage.push() != 0) {
	        	try {
	            	soundPage.get(0).pause();
	            	soundPage.get(0).currentTime=0;
				} catch(msg) {
					debug.log(msg);
				}
	        }
			break;

		case 'setVolume':
			try {
				var html5Volume = (data.volume/100);

				if (soundPage.push() != 0)
		            soundPage.get(0).volume = html5Volume;
		        
		        if (pointSound.push() != 0)
		            pointSound.get(0).volume = html5Volume;
		        
		        if (soundpresentation.push() != 0)
		            soundpresentation.get(0).volume = html5Volume;
		        
		        if (html5Volume !== 0){
		        	_that.soundManager.setVolumeAll(data.volume);
		        	_that.soundManager.unmuteAll();
		        } else {
		        	_that.soundManager.muteAll();
		        }
			} catch (msg) {
				debug.log(msg);
			}

	        _that.course.opts.sound.volume = html5Volume;
			break;

    }
};

CourseManager.prototype.setCourseOption = function(cmd, data) {
	var _that = this;

	switch (cmd) {
		case 'completed':
			if (_that.course.user.courseStatus !== 'c') {
				_that.course.user.courseStatus = 'c';
				_that.scorm_save();
			}

			break;

		case 'failed':
			if (_that.course.user.courseStatus !== 'f') {
				_that.course.user.courseStatus = 'f';
				_that.scorm_save();
			}

			break;

		case 'notCompleted':
			// _that.course.user.courseStatus = 'nc';
			break;

		case 'forceNotCompleted':
			_that.course.user.courseStatus = 'nc';
			break;

	}
};

CourseManager.prototype.getScreenPageByID = function(pageID) {
	var _that = this;
	return _that.L.mainScreen.find('div[pageid="'+pageID+'"]');
};

CourseManager.prototype.getCompletion = function() {
	var _that = this;

	var status = { };

	// check all pages for completion
	// if (_that.course.opts.req.p) {
		var completedPages = 0;
		for (var page in _that.course.pages) {
			if (_that.course.pages[page].opts.notDrawed !== true) {
				if ( !_that.course.pages[page].opts.compl ) {
					break;
				} else {
					completedPages++;
				}
			}
		}
		if (completedPages === _that.course.opts.numberOfPages) {
			status.pages = true;
		} else {
			status.pages = false;
		}
	// }

	// compare user score and required
	// if (_that.course.opts.req.s) {
		if (_that.course.user.score >= _that.course.opts.score.required) {
			status.score = true;
		} else {
			status.score = false;
		}
	// }

	// check all elements
	// if (_that.course.opts.req.e) {
		var completedElements = 0;
		for (var elem in _that.course.objs) {
			var element = _that.course.objs[elem];
			if (element.notDrawed !== true) {
				if (element.status === 1 && element.score !== 0) {
					if (element.compl === 0 ) {
						break;
					} else {
						completedElements++;
					}
				}	
			}
		}

		var numberOfRequiredElements = 0;
		for (var o in _that.course.objs) {
			if (_that.course.objs[o].notDrawed !== true) {
				if (_that.course.objs[o].status === 1 && _that.course.objs[o].score !== 0) {
					numberOfRequiredElements++;
				}
			}
		}

		if (completedElements === numberOfRequiredElements) {
			status.elems = true;
		} else {
			status.elems = false;
		}

		debug.log("completed elems: " + completedElements);
		debug.log("numberOfRequiredElements: " + numberOfRequiredElements);
	// }


	return status;
};

CourseManager.prototype.getMaxScoreValue = function() {
	var _that = this;

	if (_that.course.opts.euroforum && !isUndefined(_that.course.opts.project_max_points_custom)) {
		return _that.course.opts.project_max_points_custom;
	}

	var maxScore = 0;

	for ( var ob in _that.course.objs ) {
		if ( _that.course.objs[ob].status === 1 ) {
			maxScore += parseInt(_that.course.objs[ob].score) || 0;
		}
	}

	return maxScore;
};

CourseManager.prototype.getObjectLine = function(ob) {
	var _that = this;

	for (var p in _that.course.pages) {
		for (var l in _that.course.pages[p].lines) {
			for (var o in _that.course.pages[p].lines[l].objects) {
				if (_that.course.pages[p].lines[l].objects[o].id === ob.id) {
					return _that.course.pages[p].lines[l];
				}
			}
		}
	}

	return false;
};

CourseManager.prototype.isLastObject = function(pageID, line, obID) {
	var _that = this;

	var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);

	if (obID === (numberOfObjects-1)) {
		return true;
	}

	return false;
};

CourseManager.prototype.setProjectVariableValue = function(varID, value) {
	var _that = this;

	var variable;

	if (varID.length === 32) {

		variable = _that.trigger_getVariableByHash(varID);

		if (typeof variable === "object") {
			variable.pvarvalue = value;
			if (_that.course.opts.euroforum) {
				if (variable.pvarname === 'suma'){
					_that.course.user.score = value;
				}
			}
		}

	} else {

		variable = _that.course.opts.trigger[varID];

		if (typeof variable === "object") {
			variable.pvarvalue = value;


			
		}

	}


	if(isObject(variable)){
		_that.L.scr
				.find('*[pvarbind="'+ variable.varhash +'"]')
				.text(variable.pvarvalue);
	}

		// _that.L.iframe.contents().find('*>:contains()').text(_that.course.opts.trigger[varID].pvarvalue);
		// debug.log(_that.course.opts.trigger[varID].pvarname);



		// debug.log("zmieniam (o "+ value +") varID: " + varID + " | now value is: " + _that.course.opts.trigger[varID].pvarvalue);
		// debug.log(_that.course.opts.trigger[varID]);
};

CourseManager.prototype.findElementsDirectlyContainingText = function(ancestor, text) {
    var elements= [];
    walk(ancestor);
    return elements;

    function walk(element) {
        var n= element.childNodes.length;
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===3 && child.data.indexOf(text)!==-1) {
                elements.push(element);
                break;
            }
        }
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===1)
                walk(child);
        }
    }
};

/* -------------- OBJECT HANDLERS ------------------- */

CourseManager.prototype.object_before_show = function(ob, screenOb, triggered) {
	var _that = this;

	// fix artifacts on ios while animating position
	screenOb.css('-webkit-transform', 'translate3d(0,0,0)');

	// WCAG
	if (typeof screenOb.attr('title') === "string" || screenOb.attr('wcag') == "1") {
		screenOb.attr({
			'aria-label': screenOb.attr('title'),
			'role': 'application'
		});
		screenOb.removeAttr('title');
	}

	// remove box shadow if its not set - eroors on firefox
	// if (screenOb.css('box-shadow') == "rgb(255, 255, 255) 0px 0px 0px 0px") {
	// 	screenOb.css('box-shadow', '');
	// }




	//Uwaga, sprawdzić wszystkie elementy
	screenOb.removeAttr('id');


	switch(_that.getObjectType(ob)) {
		case 'simple':
			_that.object_crossBrowserRotation(ob, screenOb);

			_that.object_loadDownloadObject(ob, screenOb);

			if (_that.browser.firefox && screenOb.find('a').attr('action') === '2') {
				var soundPath = screenOb.find('a').attr('href');
				debug.log(soundPath);
				var soundPathOgg = soundPath.substring(0, soundPath.length - 3) + "ogg";
				screenOb.find('a').attr('href', soundPathOgg);
			}

			screenOb.click(function(e) {
				if ($(this).find('a').attr('action') === '2') {
					e.preventDefault();
					$('#point-sound').remove();
				}
				_that.object_setCompleted(ob); 
				_that.object_endActionHandler(ob, screenOb);
				// triggerEvent(screenOb[0], 'custom_requirepassing');
			});
			break;

		case 'drawed_area':

			_that.object_loadDrawedArea(ob, screenOb);

			screenOb.click(function() {
				_that.object_setCompleted(ob); 
				_that.object_endActionHandler(ob, screenOb);
				// triggerEvent(screenOb[0], 'custom_requirepassing');
			});	
			break;

		case 'hide_background':
			_that.object_loadHideBackground(ob, screenOb);
			
			screenOb.click(function() {
				_that.object_setCompleted(ob); 
				// triggerEvent(screenOb[0], 'custom_requirepassing');
			});
			break;

		case 'scroller':
			_that.scrollPageToPositionWithScrollerObject(ob, screenOb);
			// triggerEvent(screenOb[0], 'custom_requirepassing');
			
			break;

		case 'quiz_multiple':
			_that.quiz_multiplePrepareQuestion(ob, screenOb);
			break;

		case 'quiz_qtext':
			_that.quiz_qtextPrepareQtextQuestion(ob, screenOb);
			break;

		case 'quiz_dnd':
			_that.quiz_dndPrepareDnDQuestion(ob, screenOb);
			break;

		case 'quiz_memory':
			_that.quiz_memoryPrepareObjects(ob, screenOb);
			break;

		case 'quiz_results':
			_that.populateQuizResultDivs();
			_that.object_setCompleted(ob); 

			screenOb.click(function() {
				_that.object_endActionHandler(ob, screenOb);
				// triggerEvent(screenOb[0], 'custom_requirepassing');
			});
			break;

		case 'swf':
			_that.object_loadSwf(ob, screenOb);
			_that.object_setCompleted(ob); 
				// triggerEvent(screenOb[0], 'custom_requirepassing');
			break;

		case 'video':
			_that.object_loadVideo(ob, screenOb);
			// triggerEvent(screenOb[0], 'custom_requirepassing');
			break;

		case 'plugins':
			
			break;

		case 'forms':
			_that.forms_prepareForm(ob, screenOb);
			break;

		case 'quiz_crossword':
			_that.quiz_prepareCrossword(ob, screenOb);
			break;

		case 'quiz_connect_the_lines':
			switch (ob.compl) {
				case 1:
					_that.quiz_qclMarkQuestionAsPassed(ob, screenOb);
					setTimeout(function() {
						triggerEvent(screenOb[0], 'custom_questionpassed');
					}, 50);
					break;

				case 2:
					_that.quiz_qclMarkQuestionAsFailed(ob, screenOb);
					setTimeout(function() {
						triggerEvent(screenOb[0], 'custom_questionfailed');
					}, 50);
					
					break;

				default:
					// _that.quiz_qclMarkQuestionAsPassed(ob, screenOb);
					_that.quiz_qclPrepareQuestion(ob, screenOb);
					break;
			}
			break;

		case 'quiz_wordsearch':
			_that.quiz_qwsPrepareQuestion(ob, screenOb);
			break;

		case 'counter':
			_that.counter_prepareObject(ob, screenOb);
			break;

		case 'quiz_boardgame':
			_that.quiz_boardgamePrepare(ob, screenOb);
			break;
	}

	// change class bassing on ob.compl variable
	if (ob.compl === 1) {
		screenOb.addClass('active-point').removeClass('inactive-point');
	}

	// handle object parallax
	_that.object_parallaxHandler(ob, screenOb);

	// debug.log("triggered? " + triggered);

	// load sound for object
	if (
		screenOb.attr('soundonstart') === "true" || 
		( screenOb.attr('soundonstart') === undefined && _that.course.opts.euroforum !== true ) || 
		triggered === true
		) 
	{
		_that.object_loadSound(ob, screenOb);
	}
	

	// add triggers
	_that.trigger_addEvent("object", {ob:ob, screenOb:screenOb});

	screenOb.click(function() { 
		screenOb.removeClass('inactive-point').addClass('active-point');
	});
};

CourseManager.prototype.forms_resetFormSubmitQuestion = function(ob, screenOb) {
	var _that = this;

	screenOb.css('opacity', '1');
	screenOb.off('click');

	screenOb.click(function() { _that.forms_submitCheckAnswers(ob, screenOb); });

	$.each(ob.form.options.formFields, function(index, value) {
		var screenElement = _that.getScreenObjectByActionkeyFromProject(value);
		screenElement.find('input, select, textarea').prop('disabled', false);
		screenElement.find('input, select, textarea').val('');
		screenElement.find('input, select, textarea').css({
			'box-shadow': 'none'
		});

		var obElement = _that.getObjectByID(value);
		obElement.form.answers.userSelection = [ ];
	});
};

CourseManager.prototype.forms_prepareForm = function(ob, screenOb) {
	var _that = this;

	switch (ob.action) {

		// INPUT
		case 50:
			if (ob.form.answers.userSelection.push() !== 0) {
				screenOb.find('.form-wrapper input').val(ob.form.answers.userSelection[ob.form.answers.userSelection.length - 1]);
			} else {
				screenOb.find('.form-wrapper input').val(ob.form.options.defaultVal);
			}

			screenOb.find('.form-wrapper input').attr('maxlength', ob.form.options.maxLengthInput);

			if (screenOb.attr('wcag') == "1") {
				screenOb.find('input').attr({
					"tabindex": screenOb.attr('tabindex'),
					"aria-label": screenOb.attr('aria-label'),
				});
				screenOb.removeAttr('aria-label');
				screenOb.removeAttr('tabindex');
			}
			
			screenOb.change(function() { _that.forms_inputChange(ob, screenOb); });
			break;

		// SELECT
		case 51:
			if (ob.form.answers.userSelection.push() !== 0) {
				screenOb.find('.form-wrapper select').val(ob.form.answers.userSelection[ob.form.answers.userSelection.length - 1]);
			} else {
				var selectedOption = screenOb.find('.form-wrapper select option[selected]').val();
				ob.form.answers.userSelection.push(selectedOption)
			}

			screenOb.change(function() { _that.forms_selectChange(ob, screenOb); });
			break;

		// TEXTAREA
		case 52:
			if (ob.form.answers.userSelection.push() !== 0) {
				screenOb.find('.form-wrapper textarea').val(ob.form.answers.userSelection[ob.form.answers.userSelection.length - 1]);
			} else {
				screenOb.find('.form-wrapper textarea').val(ob.form.options.defaultVal);
			}

			screenOb.find('.form-wrapper textarea').attr('maxlength', ob.form.options.maxLengthTextarea);

			screenOb.change(function() { _that.forms_textareaChange(ob, screenOb); });
			break;

		// CHECKBOX
		case 53:
			if (ob.form.answers.userSelection.push() !== 0) {
				ob.form.answers.userSelection[ob.form.answers.userSelection.length - 1] ? screenOb.find('.form-wrapper input').prop('checked', true) : screenOb.find('.form-wrapper input').prop('checked', false);
			} else {
				screenOb.find('.form-wrapper input').prop('checked', ob.form.options.requiredChecked);
				ob.form.answers.userSelection.push(ob.form.options.requiredChecked);
			}

			screenOb.change(function() { _that.forms_checkboxChange(ob, screenOb); });
			break;

		// RADIO
		case 54:
			if (ob.form.answers.userSelection.push() !== 0) {

				ob.form.answers.userSelection[ob.form.answers.userSelection.length - 1] ? screenOb.find('.form-wrapper input').prop('checked', true) : screenOb.find('.form-wrapper input').prop('checked', false);
			} else {
				screenOb.find('.form-wrapper input').prop('checked', false);
			}

			screenOb.change(function() { _that.forms_allRadioChange(ob, screenOb); });
			break;

		// SUBMIT
		case 55:

			if (isUndefined(ob.qattempts)) {
				ob.qattempts = parseInt(screenOb.attr('attempts'));
			}
			if (isUndefined(ob.startAttempts)) {
				ob.startAttempts = parseInt(screenOb.attr('attempts'));
			}
			if (!isUndefined(screenOb.attr('score-pass'))) {
				ob.score = parseInt(screenOb.attr('score-pass'));
			}
			if (!isUndefined(screenOb.attr('score-fail'))) {
				ob.scoreFail = parseInt(screenOb.attr('score-pass'));
			} else {
				ob.scoreFail = 0;
			}

			if (ob.compl === 1) {
				_that.forms_markElemsAsCompleted(ob, screenOb);
				setTimeout(function(){
					// if (!_that.course.opts.euroforum) {
						triggerEvent(screenOb[0], 'custom_questionpassed');
					// }
				}, 100);
			} else if(ob.compl == 2) {
				_that.forms_markElemsAsFailed(ob, screenOb);
				setTimeout(function(){
					// if (!_that.course.opts.euroforum) {
						triggerEvent(screenOb[0], 'custom_questionfailed');
					// }
				}, 100);
			} else {
				screenOb.off('click');
				screenOb.click(function() { _that.forms_submitCheckAnswers(ob, screenOb); });
			}
			break;
	}
};

CourseManager.prototype.forms_allRadioChange = function(ob, screenOb) {
	var _that = this;

	var group = screenOb.find('.form-wrapper input').attr('name');

	$('.form-wrapper input[name="' + group + '"]').each(function() {
		var actualScreenOb = $(this).parent().parent();
		var actionKey = actualScreenOb.attr('actionkey');
		var actualOb = _that.course.objs[actionKey];

		_that.forms_radioChange(actualOb, actualScreenOb);
	});
};

CourseManager.prototype.forms_radioChange = function(ob, screenOb) {
	var _that = this;

	var radioInput = screenOb.find('.form-wrapper input').is(':checked');

	ob.form.answers.userSelection.push(radioInput);
};

CourseManager.prototype.forms_checkboxChange = function(ob, screenOb) {
	var _that = this;

	var checkboxInput = screenOb.find('.form-wrapper input').is(':checked');

	ob.form.answers.userSelection.push(checkboxInput);
};

CourseManager.prototype.forms_textareaChange = function(ob, screenOb) {
	var _that = this;

	var textareaInput = screenOb.find('.form-wrapper textarea').val();

	ob.form.answers.userSelection.push(textareaInput);
};

CourseManager.prototype.forms_selectChange = function(ob, screenOb) {
	 var _that = this;

	 var selectInput = screenOb.find('.form-wrapper select').val();

	 ob.form.answers.userSelection.push(selectInput);
};

CourseManager.prototype.forms_inputChange = function(ob, screenOb) {
	var _that = this;

	var textInput = screenOb.find('.form-wrapper input').val();


	debug.log('ob.form.answers.userSelection');
	debug.log(ob.form.answers.userSelection);

	ob.form.answers.userSelection.push(textInput);
};

CourseManager.prototype.forms_markElemsAsCompleted = function(ob, screenOb) {
	var _that = this;

	// screenOb.prop('disabled', true);
	screenOb.css('opacity', '0.7');
	screenOb.off('click');

	$.each(ob.form.options.formFields, function(index, value) {
		var screenElement = _that.getScreenObjectByActionkey(value);
		screenElement.find('input, select, textarea').prop('disabled', true);
	});
};


CourseManager.prototype.forms_markElemsAsFailed = function(ob, screenOb) {
	var _that = this;

	screenOb.css('opacity', '0.7');
	screenOb.off('click');

	$.each(ob.form.options.formFields, function(index, value) {
		var screenElement = _that.getScreenObjectByActionkey(value);
		screenElement.find('input, select, textarea').prop('disabled', true);
	});
};

CourseManager.prototype.forms_submitCheckAnswers = function(ob, screenOb) {
	var _that = this;



	var answersStatus = {};
	var answersArray = [ ];

	if(isUndefined(ob.form.options.formFields)) {
		answersArray.push(false);
	}

	var markFormElement = function(isGoodAnswer, htmlObject, submitHtmlObject) {

		var color, outline, shadow;

		if (submitHtmlObject.attr('fsign') === 'true') {
			if (isGoodAnswer) {
				color = '#0DBF3C';
				outline = '2px solid #0DBF3C';
				shadow = '0px 0px 10px #0DBF3C';
			} else {
				color = '#B32121';
				outline = '2px solid #B32121';
				shadow = '0px 0px 10px #B32121';
			}

			htmlObject
				.find('input, select, textarea')
				.css({
					// color: color,
					'box-shadow': shadow
				});	
		}
	}

	$.each(ob.form.options.formFields, function(index, value) {

		var screenFormHtmlObject = _that.getScreenObjectByActionkey(value);

		if (isObject(_that.course.objs[value])) {

			switch (_that.course.objs[value].action) {

				case 50: // input
					var userAnswer = _that.course.objs[value].form.answers.userSelection;
					if(userAnswer.length > 0){

						var goodAnswer = _that.course.objs[value].form.options.caseSensitive ? _that.course.objs[value].form.options.requiredVal.split(';|') : _that.course.objs[value].form.options.requiredVal.toLowerCase().split(';|');
						var userLastAnswer = _that.course.objs[value].form.answers.userSelection[_that.course.objs[value].form.answers.userSelection.length - 1];

						var userAnswerToCheck = _that.course.objs[value].form.options.caseSensitive ? userLastAnswer : userLastAnswer.toLowerCase();

						debug.log(userAnswerToCheck);	

						if (userLastAnswer.length > 0 && goodAnswer.indexOf(userAnswerToCheck) === -1) {
							answersArray.push(false);
							markFormElement(false, screenFormHtmlObject, screenOb);
						} else {
							answersArray.push(true);
							markFormElement(true, screenFormHtmlObject, screenOb);
						}
					} else {
						answersArray.push(false);
						markFormElement(false, screenFormHtmlObject, screenOb);
					}
					// else {
					// 	_that.quiz_selectAtLeastOneAnswerInfo(lang[language]['ANSWER_QUESTIONS_DND_FIRST'], 'red');
					// 	answersArray.push(false);
					// }


					break;

				case 51: // select
					console.log('51');
					var lastVal = 0;
					var userAnswer = _that.course.objs[value].form.answers.userSelection;

					

					if (userAnswer.push() !== 0) 
						lastVal = parseInt(userAnswer[userAnswer.length - 1]);

					if (_that.course.objs[value].form.options.selectOptions[lastVal].require) {
						debug.log("select jest ok");
						answersArray.push(true);
						markFormElement(true, screenFormHtmlObject, screenOb);
					} else {
						debug.log("select jest zle");
						answersArray.push(false);
						markFormElement(false, screenFormHtmlObject, screenOb);
					}
					break;

				case 52: // textarea
					var userAnswer = _that.course.objs[value].form.answers.userSelection;
					if(userAnswer.length > 0){

						var goodAnswer = _that.course.objs[value].form.options.requiredVal.toLowerCase().split(';|');
						var userLastAnswer = _that.course.objs[value].form.answers.userSelection[_that.course.objs[value].form.answers.userSelection.length - 1];

						if (goodAnswer.indexOf(userLastAnswer.toLowerCase()) === -1) {
							answersArray.push(false);
							debug.log("textarea jest zle");
							markFormElement(false, screenFormHtmlObject, screenOb);
						} else {
							answersArray.push(true);
							debug.log("textarea jest ok");
							markFormElement(true, screenFormHtmlObject, screenOb);

						}
					} else {
						answersArray.push(false);
						markFormElement(false, screenFormHtmlObject, screenOb);
					}
					break;

				case 53: // checkbox
					console.log('53');
					var isRequired = _that.course.objs[value].form.options.requiredChecked;
					var lastVal = false;
					if (_that.course.objs[value].form.answers.userSelection.push() !== 0)
						lastVal = _that.course.objs[value].form.answers.userSelection[_that.course.objs[value].form.answers.userSelection.length - 1];

					if (_that.course.objs[value].form.options.correct === lastVal) {
						answersArray.push(true);
						markFormElement(true, screenFormHtmlObject, screenOb);
					} else {
						answersArray.push(false);
						markFormElement(false, screenFormHtmlObject, screenOb);
					}
					break;

				case 54: // radiobutton
					console.log('54');
					var lastVal = false;
					if (_that.course.objs[value].form.answers.userSelection.push() !== 0)
						lastVal = _that.course.objs[value].form.answers.userSelection[_that.course.objs[value].form.answers.userSelection.length - 1];

					if (_that.course.objs[value].form.options.correct === lastVal) {
						markFormElement(true, screenFormHtmlObject, screenOb);
						answersArray.push(true);
					} else {
						markFormElement(false, screenFormHtmlObject, screenOb);
						answersArray.push(false);
					}
					break;
			}
		}
	});


	if (answersArray.indexOf(false) !== -1) {
		answersStatus.questionIsPassed = false;
	} else {

		answersStatus.questionIsPassed = true;
		_that.forms_markElemsAsCompleted(ob, screenOb);
	}

	_that.quiz_ShowFeedback(ob, screenOb, answersStatus);

};

CourseManager.prototype.object_showing = function(ob, screenOb, triggered) {
	var _that = this;

	switch(_that.getObjectType(ob)) {
		case 'simple':
		case 'drawed_area':
		case 'quiz_multiple':
		case 'quiz_qtext':
		case 'quiz_dnd':
		case 'quiz_crossword':
		case 'quiz_wordsearch':
		case 'quiz_connect_the_lines':
		case 'quiz_results':
		case 'swf':
		case 'video':
		case 'plugins':
		case 'forms':
		case 'counter':
		case 'quiz_boardgame':

			var animationTime = parseFloat(ob.animations.animInExecTime);

			if ( !isUndefined(ob.animations.animInTrigger) && ob.animations.animInTrigger != "none") {
				animationTime = parseFloat(ob.animations.animInTrigger.animationTime);
			}
			if ( !isNumber(animationTime) ) {
				animationTime = 1.3;
			}

			var animationIn = ob.animations.animIn;
			if ( !isUndefined(ob.animations.animInTrigger) && ob.animations.animInTrigger != "none") {
				animationIn = ob.animations.animInTrigger.animationName;
			}

			var animationOut = ob.animations.animOut;
			if ( !isUndefined(ob.animations.animOutTrigger) && ob.animations.animOutTrigger != "none") {
				animationOut = ob.animations.animOutTrigger.animationName;
			}

			// handle animations for ie 9 and older
			if ( _that.isIE.ie9orOlder ) {
				// js animation for ie 9 and older
				_that.object_handleIEanimations(ob, screenOb, "animIn");
			} else {

				// if object is hiding now - delete animation and hide it manually
				if (animationOut !== "none" && screenOb.hasClass(animationOut)) {
					screenOb.removeClass(animationOut);
					screenOb.css("display", "none");
				}

				// change animation time property
				screenOb.css("animation-duration", animationTime + "s");
				screenOb.css("-webkit-animation-duration", animationTime + "s");

				var splittedForJS = animationIn.split('-');

				// add enter animation for object!
				if (splittedForJS[0] === 'js') {
					var animationData = {
						animationName: animationIn,
						animationTime: animationTime,
						animationType: 'in'
					};
					_that.object_handleJavascriptAnimation(ob, screenOb, animationData);
				} else {
					screenOb.addClass("animated");
					screenOb.addClass(animationIn);
					screenOb.css("display", "block");	
				}
			}


			if (animationIn !== "none") {
				// delete animation-in class when object finish showing itself
				clearTimeout(ob.animations.to);
				ob.animations.to = setTimeout(function() {
					screenOb.removeClass(animationIn);
					_that.object_after_show(ob, screenOb, triggered);
				}, animationTime * 1000);
			} else {
				screenOb.removeClass(animationIn);
				_that.object_after_show(ob, screenOb, triggered);
			}


			break;

		case 'hide_background':
		case 'scroller':

			// do something?

			break;
	}
};

CourseManager.prototype.object_handleJavascriptAnimation = function(ob, screenOb, animationData) {
	var _that = this;

	var animationName = animationData.animationName;
	var animationTime = animationData.animationTime;
	var animationType = animationData.animationType;

	var splitted = animationName.split('-');


	var animationName = splitted[1];


	if (animationName === 'premadeslide') {

		// reset element position
		if (animationType === 'in') {
			screenOb.css({
				left: ob.originalPosition.posX,
				top: ob.originalPosition.posY
			});

			screenOb.show();
		}

		// go to edge or over edge
		var toOrOver = splitted[2];

		// left, right, up or down
		var direction = splitted[3];

		// get element position and size
		var element = {
			posX: parseInt(screenOb.css('left')),
			posY: parseInt(screenOb.css('top')),
			elWidth: parseInt(screenOb.width()),
			elHeight: parseInt(screenOb.height())
		};

		var targetPosition = {
			top: {
				to: 0,
				over: -element.elHeight - 100
			},
			bottom: {
				to: _that.L.scr.find('#divimg').height() - element.elHeight,
				over: _that.L.scr.find('#divimg').height() + 100
			},
			left: {
				to: 0,
				over: -element.elWidth - 100
			},
			right: {
				to: _that.course.opts.dimentions_x - element.elWidth,
				over: _that.course.opts.dimentions_x + 100
			}
		};

		// if (toOrOver === 'to') {
		// 	targetPosition.posX -= element.elWidth;
		// 	targetPosition.posY -= element.elHeight;
		// }

		switch (direction) {
			case 'top':
				screenOb.animate({top: targetPosition[direction][toOrOver]}, animationTime*1000);
				break;
			case 'bottom':
				screenOb.animate({top: targetPosition[direction][toOrOver]}, animationTime*1000);
				break;
			case 'right':
				screenOb.animate({left: targetPosition[direction][toOrOver]}, animationTime*1000);
				break;
			case 'left':
				screenOb.animate({left: targetPosition[direction][toOrOver]}, animationTime*1000);
				break;
		}
	}

};

CourseManager.prototype.object_handleIEanimations = function(ob, screenOb, cmd) {
	var _that = this;

	var data = {
		animationString: '',
		direction: null,
		animType: null
	};

	var animationTime = parseFloat(ob.animations.animInExecTime);
	if ( !isNumber(animationTime) ) {
		animationTime = 1.3;
	}

	switch (cmd) {
		case "animIn":
			data.animationString = ob.animations.animIn;
			break;
		case "animOut":
			if (ob.animations.animOut === "none"){
				return;
			}
			
			data.animationString = ob.animations.animOut;
			break;
	}

	
	if (data.animationString.search(/right/i) !== -1)
		data.direction = "right";

	if (data.animationString.search(/left/i) !== -1)
		data.direction = "left";

	if (data.animationString.search(/top/i) !== -1)
		data.direction = "top";

	if (data.animationString.search(/bottom/i) !== -1)
		data.direction = "bottom";



	if (data.animationString.search(/fade/i) !== -1)
		data.animType = "drop";
	
	if (data.animationString.search(/bounce/i) !== -1)
		data.animType = "drop";
	
	if (data.animationString.search(/door/i) !== -1)
		data.animType = "drop";
	
	if (data.animationString.search(/rotate/i) !== -1)
		data.animType = "fade";
	

	if (data.animationString.search(/slide/i) !== -1)
		data.animType = "slide";

	if (data.animType === null && data.animationString !== "none")
		data.animType = "fade";




	if (data.direction === null)
		data.direction = "none";
	
	if (data.animType === null)
		data.animType = "none";



	switch (cmd) {
		case "animIn":
			screenOb.show(data.animType, { direction: data.direction },  animationTime * 1000);
			break;
		case "animOut":
			screenOb.hide(data.animType, { direction: data.direction },  animationTime * 1000);
			break;
	}
};

CourseManager.prototype.getFirstTabindexOnPage = function() {
	var _that = this;

	var foundObject = false;

	for (var i = 0; i < 100; i++) {
		if (CM.L.scr.find('*[tabindex="'+i+'"]').push() > 0) {
			foundObject = CM.L.scr.find('*[tabindex="'+i+'"]');
			return foundObject;
		}
	}

	return foundObject;
};

CourseManager.prototype.object_after_show = function(ob, screenOb, triggered) {
	var _that = this;

	if (typeof triggered === "undefined") {
		triggered = false;
	}

	

	if (_that.objectToFocus !== false && (ob.id == _that.objectToFocus.attr('actionkey') || ob.action === 50) ) {
		setTimeout(function() {
			if (screenOb.hasClass('divsound')) {
				screenOb.find('a').focus();
			} 
			else if(ob.action === 50) {
				if (_that.objectToFocus.closest('div[actionkey]') == ob.id) {
					screenOb.find('input').focus();	
				}
			}
			else {
				screenOb.focus();
			}
		}, 500);
		
	}

	switch(_that.getObjectType(ob)) {
		case 'simple':

			if (ob.action === 4) {
				_that.object_loadGallery(ob, screenOb);
			}

			if (ob.action === 6) {
				_that.object_loadDialog(ob, screenOb);
			}



			break;

		case 'drawed_area':


			if (ob.action === 43) {
				_that.object_loadGallery(ob, screenOb);
			}

			if (ob.action === 5) {
				_that.object_loadDialog(ob, screenOb);
			}

			break;

		case 'hide_background':

			break;

		case 'scroller':

			break;

		case 'quiz_multiple':

			break;

		case 'quiz_qtext':

			break;

		case 'quiz_dnd':
			
			break;

		case 'quiz_results':

			break;

		case 'swf':

			break;

		case 'video':

			break;

		case 'plugins':
			
			break;

		case 'forms':

			break;

		case 'quiz_crossword':

			break;
	}

	if (!triggered) {
		if (ob.animations.lineType === 'after_time') {
			// handle animations for ie 9 and older
			if ( _that.isIE.ie9orOlder ) {
				// js animation for ie 9 and older
				_that.object_handleIEanimations(ob, screenOb, "animOut");
			} else {
				if (ob.animations.animOut !== "none") {

					var animationTime = parseFloat(ob.animations.animOutExecTime);

					if ( !isUndefined(ob.animations.animOutTrigger) && ob.animations.animOutTrigger != "none") {
						animationTime = parseFloat(ob.animations.animOutTrigger.animationTime);
					}
					if ( !isNumber(animationTime) ) {
						animationTime = 1.3;
					}

					debug.log('Animation out time: ' + animationTime);

					var splittedForJS = ob.animations.animOut.split('-');

					debug.log(splittedForJS);

					// add enter animation for object!
					if (splittedForJS[0] === 'js') {
						var animationData = {
							animationName: ob.animations.animOut,
							animationTime: animationTime,
							animationType: 'out'
						};
						_that.object_handleJavascriptAnimation(ob, screenOb, animationData);
					} else {

						var timeout = parseFloat(ob.animations.obTime);
						setTimeout(function() {
							// change animation time property
							screenOb.css("animation-duration", animationTime + "s");
							screenOb.css("-webkit-animation-duration", animationTime + "s");
							screenOb.addClass(ob.animations.animOut);

							clearTimeout(ob.animations.to);
							ob.animations.to = setTimeout(function() {
								screenOb.css("display", "none");
								screenOb.removeClass(ob.animations.animOut);
							}, animationTime * 1000);
						}, timeout * 1000);
					}

				}
			}
		}
	}



	// add endless animation
    if (typeof ob.animations.endless === 'string') {
            if (!screenOb.hasClass(ob.animations.endless)){
                screenOb.addClass(ob.animations.endless);
            }
    }

    // add hover animation
    if (typeof ob.animations.hover === 'string') {
        screenOb.mouseenter(function() {
        	var _ob = $(this);

            if (!screenOb.hasClass(ob.animations.hover)){
                screenOb.addClass(ob.animations.hover);

           //      setTimeout(function() {
		        	// screenOb.removeClass(ob.animations.hover);
           //      }, 1000);

                // screenOb.bind('animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd', function(e){
                //         _ob.removeClass(ob.animations.hover);
                //         screenOb.unbind('animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd');
                //         debug.log("USUN animacje hover: " + ob.animations.hover);
                // }); 
            }
        });

        screenOb.mouseleave(function() {
        	var _ob = $(this);

            if (!screenOb.hasClass(ob.animations.hover)){
	        	screenOb.removeClass(ob.animations.hover);
            }
        });
    }
};

CourseManager.prototype.object_before_hide = function(ob, screenOb) {
	var _that = this;
	// remove events and handlers
};

CourseManager.prototype.object_hiding = function(ob, screenOb) {
	var _that = this;

	// handle animations for ie 9 and older
	if ( _that.isIE.ie9orOlder ) {
		// js animation for ie 9 and older
		_that.object_handleIEanimations(ob, screenOb, "animOut")
	} else {
		if (ob.animations.animOut !== "none") {
			var timeout = parseFloat(ob.animations.obTime);
			
			setTimeout(function() {
				screenOb.addClass(ob.animations.animOut);

				clearTimeout(ob.animations.to);
				ob.animations.to = setTimeout(function() {
					screenOb.css("display", "none");
					screenOb.removeClass(ob.animations.animOut);
				}, 1500);
			}, timeout * 1000);
		}
	}
};

CourseManager.prototype.object_after_hide = function(ob, screenOb) {
	var _that = this;

	switch(_that.getObjectType(ob)) {
		case 'simple':

			break;

		case 'drawed_area':

			break;

		case 'hide_background':
			_that.object_endActionHandler(ob, screenOb);
			break;

		case 'scroller':

			break;

		case 'quiz_multiple':

			break;

		case 'quiz_qtext':

			break;

		case 'quiz_dnd':

			break;

		case 'quiz_results':

			break;

		case 'swf':

			break;

		case 'video':

			break;

		case 'plugins':
			
			break;

		case 'forms':

			break;

		case 'quiz_crossword':
			
			break;

		case 'counter':
			
			break;

		case 'quiz_boardgame':
			
			break;
	}
};

CourseManager.prototype.object_loadSound = function(ob, screenOb) {
	var _that = this;

	if (ob.sound.filename.length > 0) {
		var soundpath = _that.course.opts.exportedFolderName + '/' + _that.course.opts.active.pageID + '/sounds/' + ob.id + '/' + ob.sound.filename;

		var componentAudioObject = this.componentSoundsContainer.find('audio[soundpath="'+soundpath+'"]')[0];

		if (componentAudioObject) {
	    	try {
	        	// this.componentSound[0].load();
	        	componentAudioObject.play();
		    	componentAudioObject.volume = _that.course.opts.sound.volume;

		    	if (_that.course.opts.sound.muted) {
		    		componentAudioObject.volume = 0;
		    	}
			} catch(msg) {
				debug.log('ERROR playing sound' + msg);
			}
		}
	}

	// check if point has a sound file


		// var audioObject = $('#component-sounds audio[soundpath="'+soundpath+'"]');

  //   	try {
  //       	audioObject[0].play();
	 //    	audioObject[0].volume = _that.course.opts.sound.volume;

	 //    	if (_that.course.opts.sound.muted) {
	 //    		audioObject[0].volume = 0;
	 //    	}
		// } catch(msg) {
		// 	debug.log(msg);
		// }

		// debug.log('play object sound...');

		// $('#point-sound').remove();

	 //    _that.L.soundPoint = $('<audio id="point-sound"></audio>');
		// _that.L.mainScreen.append(_that.L.soundPoint);
		
		// _that.L.soundPoint.html('');

		// var sourceMP3, sourceOgg;
		// // find and replace file source of point sound container
		// sourceMP3 = $('<source/>', {
		// 	type: 'audio/mpeg',
		// 	src: _that.course.opts.exportedFolderName + '/' + _that.course.opts.active.pageID + '/sounds/' + ob.id + '/' + ob.sound.filename
		// });

		// sourceOGG = $('<source/>', {
		// 	type: 'audio/ogg',
		// 	src: _that.course.opts.exportedFolderName + '/' + _that.course.opts.active.pageID + '/sounds/' + ob.id + '/' + ob.sound.filenameogg
		// });
		// debug.log(sourceMP3.attr('src'));
		
		// sourceMP3.appendTo(_that.L.soundPoint);
		// sourceOGG.appendTo(_that.L.soundPoint);
		
  //   	try {
  //       	_that.L.soundPoint[0].play();
	 //    	_that.L.soundPoint[0].volume = _that.course.opts.sound.volume;

	 //    	if (_that.course.opts.sound.muted) {
	 //    		_that.L.soundPoint[0].volume = 0;
	 //    	}
	 //    	_that.soundManager.pauseAll();
		// } catch(msg) {
		// 	debug.log(msg);
		// }

	// }
};

CourseManager.prototype.object_loadGallery = function(ob, screenOb) {
	var _that = this;

	var galleryObjects = [ ];

	if (typeof ob.gallery === "object") {

		// for (var gOb in ob.gallery) {
		for (var galleryFile = ob.gallery.length - 1; galleryFile >= 0; galleryFile--) {

			var gOb = { href: _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/gallery/' + ob.id + '/' + ob.gallery[galleryFile]};
			galleryObjects.push(gOb);
		};

		debug.log(galleryObjects);

	   	screenOb.click(function() {

       		$.fancybox.open(
		       	galleryObjects, 
		       	{
		       	autoHeight: false,
		       	autoSize: false,
		       	minHeight: 50,
		       	maxHeight: 1200
	       });
	   });
	}
};

CourseManager.prototype.showWarningPopup = function(msg) {
	var _that = this;

	var dialogOb = $('<div id="dialog-warning"  title="'+lang[language]['WARNING']+' ('+ lang[language]['CROSSWORD'] +')"> <p style="text-align:center">'+msg+'</p> </div>');

	dialogOb.dialog({
		width: 400,
		height: 'auto',
		buttons: {
			OK: function() {
				$( this ).dialog( "close" );
			}
		}
	});
};

CourseManager.prototype.openDialogWindow = function(dialogID) {
	var _that = this;
	var dialogOb = $('#' + dialogID);
	if (dialogOb.push() > 0 && dialogOb.text().length > 0) {


		_that.closeAllDialogs();

		var labelledby = dialogOb.closest('.ui-dialog').attr('aria-labelledby');
		// var content = dialogOb.closest('.ui-dialog').find('.ui-dialog-content').text();

		dialogOb.closest('.ui-dialog').attr('aria-labelledby', labelledby + " " + dialogID);

		if (dialogOb.attr('appenddone') != 'yes') {
			dialogOb.parent().appendTo($("#screen"));
			dialogOb.attr('appenddone', 'yes');
		}
		
		dialogOb.dialog("open");
	}
};

CourseManager.prototype.object_loadDialog = function(ob, screenOb) {
	var _that = this;
	screenOb.click(function() { 
		var dialogID = 'dialog-' + ob.id;
		_that.openDialogWindow(dialogID);
	});
};

CourseManager.prototype.object_setCompleted = function(ob) {
	var _that = this;

	var screenOb = _that.getScreenObjectByActionkey(ob.id);

	switch(_that.getObjectType(ob)) {
		case 'simple':
		case 'quiz_results':
		case 'video':
		case 'hide_background':
		case 'scroller':
		case 'swf':
		case 'forms':
		case 'quiz_wordsearch':
		case 'quiz_crossword':

			if (!ob.compl && ob.status === 1) {
				_that.course.user.score += ob.score;
				_that.populateQuizResultDivs();

				screenOb.removeClass('inactive-point').addClass('active-point');
				ob.compl = 1;
				ob.clicked = 1;
				_that.setPageOptions('setComplete', _that.getPageByID(_that.course.opts.active.pageID));
				_that.checkAndSetCourseStatus();
			}

			break;
		case 'drawed_area':
			if (!ob.compl && ob.status === 1) {
				_that.course.user.score += ob.score;
				_that.populateQuizResultDivs();

				screenOb.removeClass('inactive-point').addClass('active-point');
				ob.compl = 1;
				ob.clicked = 1;
				_that.setPageOptions('setComplete', _that.getPageByID(_that.course.opts.active.pageID));
				_that.checkAndSetCourseStatus();
			}
			screenOb.css('border-color', screenOb.attr('bordercolor-active'));
			break;
	}


};

CourseManager.prototype.object_setClicked = function(ob) {
	var _that = this;

	var screenOb = _that.getScreenObjectByActionkey(ob.id);
	

	switch(_that.getObjectType(ob)) {
		case 'simple':
		case 'quiz_results':
		case 'video':
		case 'hide_background':
		case 'scroller':
		case 'swf':
			if (!ob.clicked) {
				// ob.compl = 1;
				ob.clicked = 1;
				screenOb.removeClass('inactive-point').addClass('active-point');
			}
			break;
		case 'drawed_area':
			if (!ob.clicked) {
				// ob.compl = 1;
				ob.clicked = 1;
				screenOb.removeClass('inactive-point').addClass('active-point');
				screenOb.css('border-color', screenOb.attr('bordercolor-active'));
			}
			break;
	}
};

CourseManager.prototype.object_addRequireClickEvent = function(pageID, line, obID, triggered) {
	var _that = this;

	var ob = _that.course
			.pages[pageID]
			.lines[line.opts.id]
			.objects[obID];

	var prevOb = _that.course
			.pages[pageID]
			.lines[line.opts.id]
			.objects[obID-1];

	var lineOrder = _that.course.pages[pageID].lines[line.opts.id].opts.order;

	// get object on screen
	var screenOb = _that.getScreenObjectByActionkey(ob.id);

	// is one by one?
	var isOneByOne = parseInt(ob.animations.async);

	// add pointer cursor to object
	screenOb.css({cursor: 'pointer'});

	if (!ob.clicked) {
		// add click event
		screenOb.click(function() {

			_that.object_setClicked(ob);

			var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);


			if (_that.checkClickLineCompletion(pageID, line.opts.id)) {
				var timeout = 0;
				if ( isOneByOne && _that.isLastObject(pageID, line, obID) ) {
					timeout = parseFloat(ob.animations.obTime);
				}

				setTimeout(function() {
					if (!triggered) {
						_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
					}
				}, timeout * 1000);

				_that.hideWholeLine(pageID, line);
				
			}

			if ( isOneByOne ) {
				// get object lifetime
				var timeout = parseFloat(ob.animations.obTime);

				// push new timeout into array
				_that.course.to.push(
					_that.timer(
						function() { 
							_that.loadObject(pageID, line, obID+1, triggered);
						},
						timeout * 1000
					)
				);
			}

			$(this).off('click');
		});
	}



	if ( !isOneByOne ) {
		_that.loadObject(pageID, line, obID+1, triggered);

		if (_that.checkClickLineCompletion(pageID, line.opts.id)) {
			if (!triggered) {
				_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
			}
		}
	} else {
		if (ob.clicked) {

			var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);

			// get object lifetime
			var timeout = parseFloat(ob.animations.obTime) + parseFloat(ob.animations.animTime);

			// push new timeout into array
			_that.course.to.push(
				_that.timer(
					function() {
						_that.loadObject(pageID, line, obID+1, triggered);
					},
					timeout * 1000
				)
			);
			if (obID === (numberOfObjects-1)) {
				if (_that.checkClickLineCompletion(pageID, line.opts.id)) {
					_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
				}
			}
		}
	}
};

CourseManager.prototype.object_addRequirePassingEvent = function(pageID, line, obID, triggered) {
	var _that = this;

	var ob = _that.course
			.pages[pageID]
			.lines[line.opts.id]
			.objects[obID];

	var prevOb = _that.course
			.pages[pageID]
			.lines[line.opts.id]
			.objects[obID-1];

	var lineOrder = _that.course.pages[pageID].lines[line.opts.id].opts.order;

	// get object on screen
	var screenOb = _that.getScreenObjectByActionkey(ob.id);

	// is one by one?
	var isOneByOne = parseInt(ob.animations.async);

	// add pointer cursor to object
	if (ob.status === 1) {
		screenOb.css({cursor: 'pointer'});
	}
	

	if (ob.status === 1/* && ob.compl === 0*/) {

		// add click event
		screenOb.mouseup(function() {
		// screenOb[0].addEventListener('custom_requirepassing', function(){
			var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);

			_that.object_setCompleted(ob);

			setTimeout(function() {
				if (_that.checkPassingLineCompletion(pageID, line.opts.id)) {
					var timeout = 0;
					if ( isOneByOne && _that.isLastObject(pageID, line, obID) ) {
						timeout = parseFloat(ob.animations.obTime);
					}

					setTimeout(function() {
						if (!triggered) {
							_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
						}
					}, timeout * 1000);

					_that.hideWholeLine(pageID, line);
					
				}

				if ( ob.compl !== 0 ) {
					if ( isOneByOne ) {
						_that.loadObject(pageID, line, obID+1, triggered);
					}
				}
				screenOb.off('mouseup');
				// screenOb[0].removeEventListener('custom_requirepassing');
			}, 50);
		});
	}


	if ( !isOneByOne ) {
		_that.loadObject(pageID, line, obID+1, triggered);

		var numberOfRequiredElements = 0;
		for (var o in _that.course.pages[pageID].lines[line.opts.id].objects) {
			if (_that.course.pages[pageID].lines[line.opts.id].objects[o].status) {
				numberOfRequiredElements++;
			}
		}

		// if (_that.checkPassingLineCompletion(pageID, line.opts.id)) {
		if (numberOfRequiredElements === 0) {
			if (!triggered) {
				_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
			}
		}
	} else {
		// debug.log("object completion: " + ob.compl);
		if (ob.compl !== 0 || ob.status === 0) {
		

			var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);

			// get object lifetime
			var timeout = parseFloat(ob.animations.obTime) + parseFloat(ob.animations.animTime);

			// push new timeout into array
			_that.course.to.push(
				_that.timer(
					function() {
						_that.loadObject(pageID, line, obID+1, triggered);
					},
					timeout * 1000
				)
			);
			if (obID === (numberOfObjects-1)) {
				if (_that.checkPassingLineCompletion(pageID, line.opts.id)) {
					if (!triggered) {
						_that.loadLine(pageID, _that.getLineByOrder(pageID, parseInt(line.opts.order) + 1), 0);
					}
				}
			}
		}
	}
};

CourseManager.prototype.scrollPageToPositionWithScrollerObject = function(ob, screenOb) {
    var _that = this;

    var scrollTime = 0;
    if (_that.getObjectType(ob) === "scroller") {
    	scrollTime = parseFloat(ob.animations.obTime);

    	setTimeout(function() {
    		debug.log('*************************** end of time ***************************');
    		_that.object_endActionHandler(ob, screenOb);
    	}, scrollTime*1000);
    } else {
    	scrollTime = screenOb.attr('actionend-scrolltime');
    }

    var scrBodyAndHTML, scrHTML;
    if (_that.course.opts.singleFile) {
		scrBodyAndHTML = _that.L.scr;
		scrHTML = _that.L.scr;
    } else {
    	scrBodyAndHTML = _that.L.iframe.contents().find("body, html");
    	scrHTML = _that.L.iframe.contents().find("html");
    }
    scrBodyAndHTML
    		.animate({ scrollTop: parseInt(screenOb.attr("topval")) }, { duration: scrollTime*1000, easing: 'swing' });


    if(screenOb.attr('adv') == 'off') {
        scrHTML.css('overflow-y', 'hidden');
    } else if(screenOb.attr('adv') == 'on') {
        scrHTML.css('overflow-y', 'auto');
    }

	_that.object_setCompleted(ob);
};

CourseManager.prototype.object_endActionHandler = function(ob, screenOb) {
	var _that = this;

	// TODO: end action jest wywoĹ‚ywane po klikniÄ™ciu w obiekt, trzeba zrobiÄ‡ ĹĽe w 
	//       Ä‡wiczeniach jest wywoĹ‚ywany dopiero po zaliczeniu / niezaliczeniu itd.
	
    var option = 'none';
    if (screenOb.attr('animation-actionend') != undefined && screenOb.attr('animation-actionend') != 'none')
        option = screenOb.attr('animation-actionend');
    else
        option = 'none';
    
    
    var wait_time = 1000;
    
    if(screenOb.attr('animation-out') == 'none')
        wait_time = 1;
    
    setTimeout(function() {
        switch (option) {
            case 'none' :
                break;

            case 'nextpage' :
            	_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
                _that.initPage('next');
                break;

            case 'prevpage' :
            	_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
                _that.initPage('previous');
                break;

            case 'gotoline':
                _that.scrollPageToPositionWithScrollerObject(ob, screenOb);
                break;

            case 'repeatTest':
            	debug.log("repeat test...");

        		// reset all questions
            	for (var o in _that.course.objs) {
            		if (typeof _that.course.objs[o].question === "object") {
            			_that.course.objs[o].compl = 0;
            			_that.course.objs[o].question.attempts = _that.course.objs[o].question.startAttempts;
            			_that.course.objs[o].qattempts = _that.course.objs[o].question.startAttempts;
            		}
            	}

            	// reset user score
            	_that.course.user.score = 0;

            	// set course status to not completed
            	_that.setCourseOption("forceNotCompleted");


            	var data = { 
            		pageID: _that.getPageByOrder(1).opts.id
            	}
            	_that.initPage( 'loadPageByID', data );

                break;

            case 'checkquestion':
            	var activeLine = _that.getObjectLine(ob) || { };

        		for (var o in activeLine.objects) {
        			if (activeLine.objects[o].action === 22) {
        				var q = activeLine.objects[o];
        				_that.quiz_multipleCheckAnswers(q, _that.getScreenObjectByActionkey(q.id));
        			}
        			if (activeLine.objects[o].action === 23) {
        				var q = activeLine.objects[o];
        				_that.quiz_qtextCheckAnswers(q, _that.getScreenObjectByActionkey(q.id));
        			}
        		}

        		if (_that.checkPassingLineCompletion(_that.course.opts.active.pageID, activeLine.opts.id)) {
        			_that.loadLine(_that.course.opts.active.pageID, _that.getLineByOrder(_that.course.opts.active.pageID, parseInt(activeLine.opts.order) + 1), 0);
        		}

        		_that.scorm_save();
            	break;

            default:
            	_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
            	var data = {
            		pageID: parseInt(screenOb.attr('animation-actionend'))
            	}
            	_that.initPage('loadPageByID', data);

                break;
        }
    }, wait_time);
};

CourseManager.prototype.object_crossBrowserRotation = function(ob, screenOb) {
	var _that = this;

    if (screenOb.find('.img-container').push() !== 0) {
    	var rot = screenOb.find('.img-container').attr('rot');
	    if ( typeof rot === "string" ) {
	        var style = screenOb.find('.img-container').attr('style');
	        screenOb.find('.img-container').attr('style', style + ';' + rot);
	    }
    }
};

CourseManager.prototype.object_parallaxHandler = function(ob, screenOb) {
	var _that = this;

    var parallax = {  };
    var iframe = _that.L.scr;
    
    var parallax_obj = eval( "(" + screenOb.attr('parallax') + ")");

    if (typeof parallax_obj === "object") {

        if (parallax_obj.cursor.on === true || parallax_obj.scroll.on === true) {
                var ak = screenOb.attr('actionkey');

                parallax[ak] = {
                    width: screenOb.width(),
                    height: screenOb.height(),
                    top: parseInt(screenOb.css('top')) - iframe.scrollTop(),
                    left: parseInt(screenOb.css('left')),
                    last_y: 0,
                    last_x: 0
                };

        }
    }
        
    

    
    iframe.bind('scroll mousemove', function(e){
        var cont = $(this);
        
        for (var i in parallax) {
            var parallax_obj = eval( "(" + screenOb.attr('parallax') + ")");
            
            
            var cursor_new_left = null;
            var cursor_new_top = null;
            
            if (parallax_obj.scroll.on === true) {
                if (parseInt(parallax_obj.scroll.sens) === 0) {
                    parallax_obj.scroll.sens = 10;
                }
                
                var scroll_sens = parseInt(parallax_obj.scroll.sens) * 0.1;
                
                cursor_new_top = (parallax[i].top + (cont.scrollTop() * scroll_sens));
            } else {
                cursor_new_top = parallax[i].top;
            }

            if (parallax_obj.cursor.on === true) {
                var cursor_sens = (101 - parseInt(parallax_obj.cursor.sens));


                var x = ((e.pageX - parallax[i].left - (screenOb.width() / 2) ) / (cursor_sens));
                var y = ((e.pageY - cursor_new_top - (screenOb.height() / 2) ) / (cursor_sens));
                
                if (isNaN(x) || isNaN(y)) {
                    y = parallax[i].last_y;
                    x = parallax[i].last_x;
                }
                if (parallax_obj.cursor.dir === false) {
                    cursor_new_left = parallax[i].left - x;
                    cursor_new_top = cursor_new_top - y;
                } else {
                    cursor_new_left = parallax[i].left + x;
                    cursor_new_top = cursor_new_top + y;
                }
                
                parallax[i].last_y = y;
                parallax[i].last_x = x;
                
            }

            // wyswietlanie 
            if (parallax_obj.cursor.on === true) {
                if (cursor_new_left !== null) {
                    screenOb.css({
                        left: cursor_new_left + "px"
                    });
                }

            }
            screenOb.css({
                top: cursor_new_top + "px"
            });
            
            
        }
    });
};

CourseManager.prototype.object_loadVideo = function(ob, screenOb) {
	var _that = this;


	if (ob.action == 18) {
        var src_video = '';
        var video_prop = '';
        var screenOb_key = ob.id;
        var src_videoposter = '';

        _that.videoObjects.push(screenOb);
        
        var random = new Date().getTime();
        
        switch (screenOb.attr('video-type')) {
            case '1':
                // wideo z pliku
                var videoJS;
                if (_that.course.opts.singleFile) {
                	videoJS = _V_;
                } else {
                	videoJS = document.getElementById('insideFrame').contentWindow._V_;
                }
            	if (_that.course.opts.singleFile) {
            		src_video = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/video/' + screenOb.attr('actionkey') + '/' + screenOb.attr('videofile') + '?r=' + random;
            	} else {
            		src_video = 'video/' + screenOb.attr('actionkey') + '/' + screenOb.attr('videofile') + '?r=' + random;
            	}
                
                screenOb.html('');

                if (screenOb.attr('video-autoplay') == 1)
                    video_prop = 'autoplay ';

                if (screenOb.attr('video-controls') == 1)
                    video_prop += 'controls ';

                if (screenOb.attr('video-loop') == 1)
                    video_prop += 'loop ';

                if ($(this).attr('videoposter') != undefined && $(this).attr('videoposter') != '') {
                    src_videoposter = 'poster="video/' + screenOb.attr('actionkey') + '/poster/' + $(this).attr('videoposter') + '"';
                }

                screenOb.append('<video id="'+ screenOb.attr('actionkey') + '" class="video-js vjs-default-skin" ' + video_prop + ' preload="auto" ' + src_videoposter + ' width="100%" height="100%"> </video>');
                videoJS(screenOb.attr('actionkey'), {"techOrder": ["html5", "flash", "links"], "src": src_video}, function() {
                    this.src(src_video);
                    _that.object_setCompleted(ob);
                });
                break;
            
            case '2':
                // wideo z youtube
                src_video = screenOb.attr('videofile');
                var videoJS;
                if (_that.course.opts.singleFile) {
                	videoJS = _V_;
                } else {
                	videoJS = document.getElementById('insideFrame').contentWindow._V_;
                }
                setTimeout(function(){
                    videoJS(screenOb_key).dispose();
                    screenOb.html('');

                    if (screenOb.attr('video-autoplay') == 1)
                        video_prop = 'autoplay ';

                    if (screenOb.attr('video-controls') == 1)
                        video_prop += 'controls ';

                    if (screenOb.attr('video-loop') == 1)
                        video_prop += 'loop ';

                    if ($(this).attr('videoposter') != undefined && $(this).attr('videoposter') != '') {
                        src_videoposter = 'poster="video/' + screenOb.attr('actionkey') + '/poster/' + $(this).attr('videoposter') + '"';
                    }
                    screenOb.append('<video id="'+ screenOb.attr('actionkey') + '" class="video-js vjs-default-skin" ' + video_prop + ' preload="auto" ' + src_videoposter + ' width="100%" height="100%"> </video>');
                    setTimeout(function(){
                        videoJS(screenOb_key, {"techOrder": ["youtube"], "src": src_video, "ytcontrols": false}).ready(function() {
                            if (screenOb.attr('video-autoplay') == 0)
                                this.pause();

                            _that.object_setCompleted(ob);
                        });
                    }, 1);
                }, 100);
                break;
                
            case '3':
                // wideo z vimeo
               	src_video = screenOb.attr('videofile');
                var videoJS;
                if (_that.course.opts.singleFile) {
                	videoJS = _V_;
                } else {
                	videoJS = document.getElementById('insideFrame').contentWindow._V_;
                }
                videoJS(screenOb_key).dispose();
                screenOb.html('');

                if (screenOb.attr('video-autoplay') == 1)
                    video_prop = 'autoplay ';

                if (screenOb.attr('video-controls') == 1)
                    video_prop += 'controls ';

                if (screenOb.attr('video-loop') == 1)
                    video_prop += 'loop ';

                if ($(this).attr('videoposter') != undefined && $(this).attr('videoposter') != '') {
                    src_videoposter = 'poster="video/' + screenOb.attr('actionkey') + '/poster/' + $(this).attr('videoposter') + '"';
                }

                screenOb.append('<video id="'+ screenOb.attr('actionkey') + '" class="video-js vjs-default-skin" ' + video_prop + ' preload="auto" ' + src_videoposter + ' width="100%" height="100%"> </video>');
                videoJS(screenOb_key, {techOrder: ["vimeo"], src: src_video}, function() {
                	_that.object_setCompleted(ob);
                });
                break;
        }

    }
};

CourseManager.prototype.object_loadDrawedArea = function(ob, screenOb) {
	var _that = this;

	switch (ob.action) {
		case 43: // gallery
			if (ob.gallery.length > 0) {
				screenOb.css("cursor", "pointer");
			}
			break;
		case 44: // download
			_that.object_loadDownloadObject(ob, screenOb);
			break;
	}
    
    screenOb.css({
    	'border-color': screenOb.attr('bordercolor')
    });
};

CourseManager.prototype.object_loadSwf = function(ob, screenOb) {
	var _that = this;

    var random = new Date().getTime();

	if (_that.course.opts.singleFile) {
		swf_src = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/swf/' + ob.id + '/' + screenOb.attr('swffile') + '?r=' + random;
	} else {
		swf_src = 'swf/' + screenOb.attr('actionkey') + '/' + screenOb.attr('swffile') + '?r=' + random;
	}

	screenOb.find('object').attr('data', swf_src);
    screenOb.find('object param[name="movie"]').attr('value', swf_src);
};

CourseManager.prototype.object_loadDownloadObject = function(ob, screenOb) {
	var _that = this;

	if (ob.action === 17 || ob.action === 44) {
		var linkString = "window.open( '" + _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + "/files/" + ob.id + "/" + screenOb.attr('filename') + "')";
		screenOb.attr("onclick", linkString);
	}
};

CourseManager.prototype.object_loadHideBackground = function(ob, screenOb) {
	var _that = this;
    
    screenOb.css({
    	display: 'block'
    });
};

/* -------------- TRIGGER  ------------------- */

CourseManager.prototype.trigger_initCustomEvents = function() {
	var _that = this;

	try {
		_that.customEvents = {
			custom_questionpassed: document.createEvent('HTMLEvents'),
			custom_questionfailed: document.createEvent('HTMLEvents'),
			custom_questionbadanswer: document.createEvent('HTMLEvents')
			// custom_requirepassing: new Event('custom_requirepassing')
			
		};

		_that.customEvents.custom_questionpassed.initEvent('custom_questionpassed', true, true);
		_that.customEvents.custom_questionfailed.initEvent('custom_questionfailed', true, true);
		_that.customEvents.custom_questionbadanswer.initEvent('custom_questionbadanswer', true, true);
	} catch(msg) {
		debug.log(msg);
	}


	// _that.customEvents = {
	// 	custom_questionpassed: new Event('custom_questionpassed'),
	// 	custom_questionfailed: new Event('custom_questionfailed'),
	// 	custom_questionbadanswer: new Event('custom_questionbadanswer')
	// 	// custom_requirepassing: new Event('custom_requirepassing')
		
	// };
};

CourseManager.prototype.trigger_addEvent = function(type, data) {
	var _that = this;

	if (typeof type === "string") {

		switch(type) {

			case "object":
				var ob = data.ob;
				var screenOb = data.screenOb;

				if ( ob.trigger.triggers && ob.trigger.enabled ) {
					// debug.log('===========================================================');

					for (var t = 0; t < ob.trigger.triggers.length; t++) {

						var whendoit = ob.trigger.triggers[t].whendoit;
						var whattodo = ob.trigger.triggers[t].whattodo;
						var objs = ob.trigger.triggers[t].objs;
						var opts = ob.trigger.triggers[t].opts;
						var conditions = ob.trigger.triggers[t].conditions;
						var elseActions = ob.trigger.triggers[t].elseactions;

						var mainObjectTrigger = ob.trigger.triggers[t];

						var actionDelay = 0;
						if (typeof ob.trigger.triggers[t].opts === "object") {
							if (typeof ob.trigger.triggers[t].opts.delay !== "undefined") {
								ob.trigger.triggers[t].opts.delay.replace(",", ".");
								actionDelay = parseFloat(ob.trigger.triggers[t].opts.delay);
							}
						}


						// debug.log("Adding TRIGGER, init is: "+ ob.trigger.triggers[t].init);

						if ( ob.trigger.triggers[t].init !== true) {

							if (whendoit != "none") {

								// debug.log('!! Adding trigger !! whendoit: ' + whendoit + ' whattodo: ' + whattodo + ', objs: ' + objs );

								// add cursor pointer to screen object
								screenOb.css({cursor: 'pointer'});


								debug.log((actionDelay * 1000));

								(function(screenOb, whattodo, objs, conditions, elseActions, actionDelay, mainObjectTrigger, opts, whendoit) {
										addEvent( 
											screenOb[0],
											whendoit,
											function () {
												if ((actionDelay * 1000) === 0) {
													_that.trigger_eventHandler(screenOb, whattodo, objs, conditions, elseActions, "object", mainObjectTrigger, true, opts);
												} else {
													setTimeout(function() {
														_that.trigger_eventHandler(screenOb, whattodo, objs, conditions, elseActions, "object", mainObjectTrigger, true, opts);
													}, actionDelay * 1000);
												}
											},
											false
										);
								})(screenOb, whattodo, objs, conditions, elseActions, actionDelay, mainObjectTrigger, opts, whendoit);
							}

							if (typeof ob.trigger.triggers[t].subtriggers === "object") {
								for (var subt = 0; subt < ob.trigger.triggers[t].subtriggers.length; subt++) {

									var whendoitST = ob.trigger.triggers[t].subtriggers[subt].whendoit;
									var whattodoST = ob.trigger.triggers[t].subtriggers[subt].whattodo;
									var objsST = ob.trigger.triggers[t].subtriggers[subt].objs;
									var optsST = ob.trigger.triggers[t].subtriggers[subt].opts;

									// debug.log('!! Adding SUBTRIGGER !! whendoit: ' + whendoitST + ' whattodo: ' + whattodoST + ', objs: ' + objsST );

									(function(screenOb, whattodoST, objsST, conditions, elseActions, actionDelay, mainObjectTrigger, optsST) {
										
											addEvent( screenOb[0],
												whendoitST,
												function () {

													if ((actionDelay * 1000) === 0) {
														_that.trigger_eventHandler(screenOb, whattodoST, objsST, conditions, elseActions, "object", mainObjectTrigger, false, optsST);
													} else {
														setTimeout(function() {
															_that.trigger_eventHandler(screenOb, whattodoST, objsST, conditions, elseActions, "object", mainObjectTrigger, false, optsST);
														}, actionDelay * 1000);
													}
												},
												false
											);
									})(screenOb, whattodoST, objsST, conditions, elseActions, actionDelay, mainObjectTrigger, optsST);

								}
							}
						}


						// mark trigger as aleady applied
						ob.trigger.triggers[t].init = true;
					};



					// debug.log('===========================================================');
				}
				break;

			case "page":
				if ( data.trigger.triggers && data.trigger.enabled ) {
					// debug.log('===========================================================');

					for (var t = 0; t < data.trigger.triggers.length; t++) {

						var whendoit = data.trigger.triggers[t].whendoit;
						var whattodo = data.trigger.triggers[t].whattodo;
						var objs = data.trigger.triggers[t].objs;
						var opts = data.trigger.triggers[t].opts;
						var conditions = data.trigger.triggers[t].conditions;
						var elseActions = data.trigger.triggers[t].elseactions;
						var mainObjectTrigger = data.trigger.triggers[t];

						var actionDelay = 0;
						if (typeof data.trigger.triggers[t].opts === "object") {
							if (typeof data.trigger.triggers[t].opts.delay !== "undefined") {
								data.trigger.triggers[t].opts.delay.replace(",", ".");
								actionDelay = parseFloat(data.trigger.triggers[t].opts.delay);
							}
						}

						if ( whendoit != "none" ) {

							// debug.log('!! Adding trigger to PAGE !! whendoit: ' + whendoit + ' whattodo: ' + whattodo + ', objs: ' + objs );

							(function(data, whattodo, objs, conditions, elseActions, mainObjectTrigger, actionDelay, opts) {

								if ((actionDelay * 1000) === 0) {
									_that.trigger_eventHandler(data, whattodo, objs, conditions, elseActions, "page", mainObjectTrigger, true, opts);
								} else {
									setTimeout(function() {
										_that.trigger_eventHandler(data, whattodo, objs, conditions, elseActions, "page", mainObjectTrigger, true, opts);
									}, actionDelay * 1000);
								}

							})(data, whattodo, objs, conditions, elseActions, mainObjectTrigger, actionDelay, opts);



						}

						if (typeof data.trigger.triggers[t].subtriggers === "object") {
							for (var subt = 0; subt < data.trigger.triggers[t].subtriggers.length; subt++) {

								var whendoitST = data.trigger.triggers[t].subtriggers[subt].whendoit;
								var whattodoST = data.trigger.triggers[t].subtriggers[subt].whattodo;
								var objsST = data.trigger.triggers[t].subtriggers[subt].objs;
								var optsST = data.trigger.triggers[t].subtriggers[subt].objs;

								// debug.log('!! Adding SUBTRIGGER to PAGE !! whendoit: ' + whendoitST + ' whattodo: ' + whattodoST + ', objs: ' + objsST );



								(function(data, whattodoST, objsST, conditions, elseActions, mainObjectTrigger, actionDelay, optsST) {

									if ((actionDelay * 1000) === 0) {
										_that.trigger_eventHandler(data, whattodoST, objsST, conditions, elseActions, "page", mainObjectTrigger, false, optsST);
									} else {
										setTimeout(function() {
											_that.trigger_eventHandler(data, whattodoST, objsST, conditions, elseActions, "page", mainObjectTrigger, false, optsST);
										}, actionDelay * 1000);
									}

								})(data, whattodoST, objsST, conditions, elseActions, mainObjectTrigger, actionDelay, optsST);

							}
						}


						// mark trigger as aleady applied
						// data.trigger.triggers[t].init = true;
					};
				}
				break;

		}


	}
};

CourseManager.prototype.trigger_refreshObjectsOnLoadedPage = function(pageID) {
	var _that = this;

	var lines = _that.course.pages[pageID].lines;

	for ( var line in lines ) {
		for (var ob = lines[line].objects.length - 1; ob >= 0; ob--) {
			// refresh hiddenWithTrigger value

			if (!lines[line].objects[ob]) {
				continue;
			}


			lines[line].objects[ob].hiddenWithTrigger = false;

			// refresh trigger animations

			var screenOb = _that.getScreenObjectByActionkey(lines[line].objects[ob].id);
			if (isObject(screenOb)) {
				screenOb.removeClass(lines[line].objects[ob].animations.animInTrigge);
				screenOb.removeClass(lines[line].objects[ob].animations.animOutTrigger);	
			}

			lines[line].objects[ob].animations.animInTrigger = "none";
			lines[line].objects[ob].animations.animOutTrigger = "none";
			


			if ( isObject(lines[line].objects[ob].trigger.triggers) ) {
				for (var t = lines[line].objects[ob].trigger.triggers.length - 1; t >= 0; t--) {
					// refresh trigger init value
					lines[line].objects[ob].trigger.triggers[t].init = false;
				}	
			}
		};
	};
};

CourseManager.prototype.trigger_eventHandler = function(screenOb, whattodo, data, conditions, elseActions, type, triggerObject, isMainTrigger, opts) {
	var _that = this;

	debug.log('triggering: ', type);

	var ob;

	if (type === "object") {
		ob = _that.getObjectByID(screenOb.attr('actionkey'));
	} else if(type === "page") {
		ob = screenOb;
	} else {
		return;
	}


	if (isMainTrigger) {
		if (_that.trigger_checkConditions(conditions)) {
			triggerObject.passed = true;
		} else {
			triggerObject.passed = false;
		}
	}


	// debug.log('whattodo: ' + whattodo);
	// debug.log('triggerObject.passed: ' + triggerObject.passed);
	// debug.log(conditions);

	if (typeof whattodo === "string") {
		if (triggerObject.passed) {
			_that.trigger_actionHandler(screenOb, whattodo, data, type, opts);
		} else {
			for (elseAction in elseActions) {
				_that.trigger_actionHandler(screenOb, elseActions[elseAction].whattodo, elseActions[elseAction].objs, type, opts);
			}
		}
	}
};

CourseManager.prototype.trigger_actionHandler = function(screenOb, whattodo, data, type, opts) {
	var _that = this;

	debug.log('TRIGGER OPTS: ', opts);
	debug.log(opts);
	if (typeof opts !== "object" ) {
		opts = { };
	}

	switch (whattodo) {
		case 'showLine': 
			var pageID = _that.course.opts.active.pageID;

			for (var l = data.length - 1; l >= 0; l--) {
				var line = _that.course.pages[pageID].lines[data[l]];

				_that.trigger_loadLine(
							pageID, 
							line, 
							0,
							type,
							opts.animationType
						);
			}
			break;

		case 'hideLine': 
			_that.trigger_hideLine(data, type, opts.animationType);
			break;



		case 'showObject':
			for (var o in data) {
				// get object
				var ob = _that.getObjectByID(data[o]);

				// load triggered object
				_that.trigger_loadObject(ob, type, opts.animationType);
			}

			break;

		case 'showObjectAndFocus':
			var iterator = 0;
			for (var o in data) {
				// get object
				var ob = _that.getObjectByID(data[o]);

				// load triggered object
				_that.trigger_loadObject(ob, type, opts.animationType);

				if (iterator === 0) {
					var firstObject = _that.getScreenObjectByActionkey(data[o]);
					firstObject.focus();
				}

				iterator++;
			}

			

			break;

		case 'hideObject':
			for (var o in data) {
				// get object
				var ob = _that.getObjectByID(data[o]);

				// load triggered object
				_that.trigger_hideObject(ob, type, opts.animationType);
			}

			break;

		case 'gotopage':
			_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
			var pageData = {
				pageID: parseInt(data)
			}

			debug.log('LOADING PAGE BY ID')
			debug.log(data)

			_that.initPage('loadPageByID', pageData);
			break;

		case 'gotonextpage':
			_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
			_that.initPage('next');
			break;

		case 'gotoprevpage':
			_that.setPageOptions("setComplete", _that.getPageByID(_that.course.opts.active.pageID));
			_that.initPage('previous');
			break;



		case 'playobjectsound':
			var ob = _that.getObjectByID(screenOb.attr('actionkey'));
			_that.object_loadSound(ob, screenOb);
			break;

		case 'unlockpagenavigation':
			_that.setPageOptions('unlockNavigationTrigger', _that.getPageByID(_that.course.opts.active.pageID));
			break;

		case 'resetquestions':
			for (var o in data) {
				// get object
				var ob = _that.getObjectByID(data[o]);
				var screenObject = _that.getScreenObjectByActionkey(data[o]);

				if (ob.question) {
					ob.question.attempts = ob.question.startAttempts;
				}
				
				ob.compl = 0;

				if (ob.action == 55) {
					ob.qattempts = ob.startAttempts;
					_that.forms_resetFormSubmitQuestion(ob, screenObject);
				}

				if (ob.action == 23) {
					_that.quiz_qtextPrepareQuestionToEdit(ob, screenObject);
				}
			}
			break;

		case 'resetallquestions':
			for (var o in _that.course.objs) {
				// get object
				var ob = _that.course.objs[o];
				var screenObject = _that.getScreenObjectByActionkeyFromProject(o);

				if (ob.question) {
					ob.question.attempts = ob.question.startAttempts;
				}
				

				if (ob.action == 55) {
					ob.qattempts = ob.startAttempts;
					_that.forms_resetFormSubmitQuestion(ob, screenObject);
				}

				if (ob.action == 25) {
					ob.qattempts = ob.startAttempts;
					_that.quiz_qclPrepareQuestion(ob, screenObject);
				}

				if (ob.action == 23) {
					_that.quiz_qtextPrepareQuestionToEdit(ob, screenObject);
				}

				ob.compl = 0;
			}
			break;

		case 'resetalltimers':
			var screenObjects = [ ];
			// delete all timers data
			for (var o in _that.course.objs) {
				var ob = _that.course.objs[o];
				if (_that.getObjectType(ob) == "counter") {
					if (!isUndefined(ob.timeOut)) {
						ob.timeOut.stop();
					}
					delete ob.timeOut;
					var screenOb = _that.getScreenObjectByActionkey(ob.id);
					if (screenOb.length) {
						screenObjects.push({ob: ob, screenOb: screenOb});
					}
				}
			}
			_that.countersData = { };

			// restart all timers on screen
			
			for (var i = screenObjects.length - 1; i >= 0; i--) {
				_that.counter_prepareObject(screenObjects[i].ob, screenObjects[i].screenOb);
			};
			break;

		case 'starttimer':
			for (var o in data) {
				var ob = _that.getObjectByID(data[o]);
				if (_that.getObjectType(ob) === 'counter') {
					_that.counter_startCounting(ob, _that.getScreenObjectByActionkey(ob.id));
				}
			}
			break;

		case 'resetallpagedraws':

			// _that.course.opts.score.max = _that.course.opts.score.originalMax;

			// for (var p in _that.course.pages) {
			// 	var pageData = _that.course.pages[p];
			// 	if (pageData.notDrawed) {
					
			// 	}
			// }

			break;

		case 'changevarvalue':
			if ( isObject(data[0]) ) {
				// if variable value is a number - parse it to properly add and subtract
				var variable = _that.trigger_getVariableByHash(data[0].varName);
				if (!isNaN(variable.pvarvalue)) {
					variable.pvarvalue = parseFloat(variable.pvarvalue);
				}


				var rightSideValue = data[0].varValue;

				switch(true) {

					// normal number
					case !isNaN(rightSideValue):
						rightSideValue = parseFloat(rightSideValue);
						break;

					// variable hash
					case (!isNumber(rightSideValue) && rightSideValue.length == 32):
						var variableValue = _that.trigger_getVariableByHash(rightSideValue);
						rightSideValue = parseFloat(variableValue.pvarvalue);
						break;

					// scope to get random number
					case (!isNumber(rightSideValue) && rightSideValue.split("-").length == 2):
						var scopeMin = parseInt(rightSideValue.split("-")[0]);
						var scopeMax = parseInt(rightSideValue.split("-")[1]);

						rightSideValue = parseInt(Math.random() * (scopeMax - scopeMin) + scopeMin);
						break;

				}

				// save actual variable value to "pvarvaluePrevious" just in case
				// _that.course.opts.trigger[data[0].varName]['pvarvaluePrevious'] = _that.course.opts.trigger[data[0].varName]['pvarvalue'];


				switch (data[0].varAction) {

					// EVERY TIME
					case 'add':
					case 'add-variable':
						_that.setProjectVariableValue(
								data[0].varName,
								variable.pvarvalue + rightSideValue
							); 
						break;

					case 'subtract':
					case 'subtract-variable':
						_that.setProjectVariableValue(
								data[0].varName,
								variable.pvarvalue - rightSideValue
							);
						break;

					case 'changevalue':
					case 'changevalue-variable':
						_that.setProjectVariableValue(
								data[0].varName,
								rightSideValue
							);
						break;

					// ONCE
					case 'addonce':
					case 'addonce-variable':
						if (data[0].done !== true) {
							_that.setProjectVariableValue(
								data[0].varName,
								variable.pvarvalue + rightSideValue
							);
							data[0].done = true;
						}
						
						break;

					case 'subtractonce':
					case 'subtractonce-variable':
						if (data[0].done !== true) {
							_that.setProjectVariableValue(
								data[0].varName,
								variable.pvarvalue - rightSideValue
							);
							data[0].done = true;
						}
						break;

					case 'changevalueonce':
					case 'changevalueonce-variable':
						if (data[0].done !== true) {
							_that.setProjectVariableValue(
								data[0].varName,
								rightSideValue
							);
							data[0].done = true;
						}
						break;

					case 'changevalue-random':
						// if (data[0].done !== true) {

							var interval = setInterval(function() {
								_that.setProjectVariableValue(
									data[0].varName,
									parseInt(Math.random() * (rightSideValue + 10) + (rightSideValue - 10))
								);
							}, 60);

							setTimeout(function() {
								clearInterval(interval);

								_that.setProjectVariableValue(
									data[0].varName,
									rightSideValue
								);
								data[0].done = true;
							}, 2000);

						// }
						break;
				}

			}
			
			
			// debug.log("changing ("+ data[0].varAction +": "+ data[0].varValue +") varID: " + data[0].varName + " | now value is: " + _that.course.opts.trigger[data[0].varName]['pvarvalue']);
			
			break;

	}
};

CourseManager.prototype.trigger_getVariableByHash = function(hash) {
	var _that = this;

	for (var v in _that.course.opts.trigger) {
		if (hash.length == 32) {
			if (_that.course.opts.trigger[v].varhash === hash) {
				return _that.course.opts.trigger[v];
			}	
		} else {
			return _that.course.opts.trigger[hash];
		}
		
	}

	return false;
};

CourseManager.prototype.trigger_checkConditions = function(conditions) {
	var _that = this;

	// if we have no conditions - just return true
	if (conditions.length === 0) { return true; }

	var resultArray = [ ];

	// for (var c in conditions) {
	for (var c = 0; c < conditions.length; c++) {
		
	

		var conditionPassed = true;




		// get right side compare value basing on input or variable
		var valueToCompare;
		if (conditions[c].actionType === "variable") {
			valueToCompare = _that.trigger_getVariableByHash(conditions[c].compareValue).pvarvalue;
		} else {
			valueToCompare = conditions[c].compareValue;
		}

		// if left side variable is not set - continue to next condition
		if (typeof _that.trigger_getVariableByHash(conditions[c].variable) === "object") {
			var variableLeftSide = _that.trigger_getVariableByHash(conditions[c].variable).pvarvalue;
		} else {
			continue;
		}

		// get compare action
		var compareAction = conditions[c].action.split('-');

		// debug.log("compareAction: " + compareAction[1]);
		switch (compareAction[1]) {
			case 'equals':
				// debug.log(variableLeftSide + " == " + valueToCompare);
				if (! (variableLeftSide == valueToCompare) ) {
					conditionPassed = false;
				}
				break;
			case 'lessthan':
				// debug.log(variableLeftSide + " < " + valueToCompare);
				if (! (variableLeftSide < valueToCompare) ) {
					conditionPassed = false;
				}
				break;
			case 'greaterthan':
				// debug.log(variableLeftSide + " > " + valueToCompare);
				if (! (variableLeftSide > valueToCompare) ) {
					conditionPassed = false;
				}
			case 'greaterthanorequal':
				// debug.log(variableLeftSide + " >= " + valueToCompare);
				if (! (variableLeftSide >= valueToCompare) ) {
					conditionPassed = false;
				}
				break;
			case 'lessthanorequal':
				// debug.log(variableLeftSide + " <= " + valueToCompare);
				if (! (variableLeftSide <= valueToCompare) ) {
					conditionPassed = false;
				}
				break;
			case 'modulo':
				if (! (variableLeftSide%2 == valueToCompare) ) {
					conditionPassed = false;
				}
				break;
		}

		var andArray = [ ];

		if ( c !== 0 ){
			if (conditions[c-1].andor === "and") {
				andArray = resultArray[resultArray.length-1];
			}
		}

		andArray.push(conditionPassed);

		if (c === 0) {
			resultArray.push(andArray);
		} else {
			if (conditions[c-1].andor === "and") {
				resultArray[resultArray.length-1] = andArray;
			} else {
				resultArray.push(andArray);
			}
		}
	}

	var allOrConditions = [ ];

	for (var r in resultArray) {
		var orValue = true;
		for (var andR in resultArray[r]) {
			if (resultArray[r][andR] === false) {
				orValue = false;
			}
		}
		allOrConditions.push(orValue);
	}

	if (allOrConditions.indexOf(true) !== -1) {
		return true;
	} else {
		return false;
	}
};

CourseManager.prototype.trigger_loadLine = function(pageID, line, objectID, type, animationType) {
	var _that = this;
	// debug.log('Triggering line! (pageID: '+ pageID +', line: ' + line.opts.id + ')');

	// check if line exists in this page
 	if( typeof line === "object") {

		var lineObjects = _that.getLineObjects(line.opts.id);

		// set trigger animation to objects
		for (var o in lineObjects) {
			if (typeof animationType !== "undefined") {
				lineObjects[o].animations.animInTrigger = animationType;
			}
		} 

		
		var lineOrder = _that.course.pages[pageID].lines[line.opts.id].opts.order;

		var ob = _that.course
					.pages[pageID]
					.lines[line.opts.id]
					.objects[objectID];

		if (type === "page") {
			ob.hiddenWithTrigger = false;
		}

		_that.course.opts.active.line = line.opts.id;

		var line_delaytime = parseFloat(ob.animations.delaytime);

		if (line_delaytime > 0 && !_that.isMobile) {
			_that.course.to.push(
				_that.timer(
					function() { _that.loadObject(pageID, line, objectID, true); },
					line_delaytime * 1000
				)
			);	
		} else {
			_that.loadObject(pageID, line, objectID, true);
		}
	}
};

CourseManager.prototype.trigger_hideLine = function(lineID, type, animationType) {
	var _that = this;

	for (var i = lineID.length - 1; i >= 0; i--) {
		
		var lineObjects = _that.getLineObjects(lineID[i]);

		for (var o in lineObjects) {
			if (type === "page") {
				lineObjects[o].hiddenWithTrigger = true;
			}

			// set trigger animation to objects
			if (type === "object") {
				if (typeof animationType !== "undefined") {
					lineObjects[o].animations.animOutTrigger = animationType;
				}
			}
			_that.trigger_hideObject(lineObjects[o]);
		}
	};
};

CourseManager.prototype.trigger_loadObject = function(ob, type, animationType) {
	var _that = this;
		
	if (typeof ob === "object") {
		// get object on screen
		var screenOb = _that.getScreenObjectByActionkey(ob.id);

		// check for trigger animation
		if (typeof animationType !== "undefined") {
			ob.animations.animInTrigger = animationType;
		}

		if (type === "page") {
			ob.hiddenWithTrigger = false;
		}

		if (screenOb.css('display') === 'none' || screenOb.hasClass(ob.animations.animOutTrigger.animationName)) {
			// showing object
			_that.object_before_show(ob, screenOb, true);
			_that.object_showing(ob, screenOb, true);
		}

		if (ob.action == 25) {
			$('._jsPlumb_endpoint, ._jsPlumb_connector').fadeIn();
		}
		// hiding
		// _that.object_before_hide(ob, screenOb);
		// _that.object_hiding(ob, screenOb);
		// _that.object_after_hide(ob, screenOb);
	}
};

CourseManager.prototype.trigger_hideObject = function(ob, type, animationType) {
	var _that = this;

	if (typeof ob === "object") {

		debug.log("HIDING:");
		// debug.log(ob);
		
		// get object on screen
		var screenOb = _that.getScreenObjectByActionkey(ob.id);

		// check for trigger animation
		if (typeof animationType !== "undefined") {
			ob.animations.animOutTrigger = animationType;
		}

		if (type === "page") {
			ob.hiddenWithTrigger = true;
		}

		var animationTime = 1.3;

		if ( !isUndefined(ob.animations.animOutTrigger) && ob.animations.animOutTrigger != "none") {
			animationTime = parseFloat(ob.animations.animOutTrigger.animationTime);
		}
		if ( !isNumber(animationTime) ) {
			animationTime = 1.3;
		}

		
		// change animation time property
		screenOb.css("animation-duration", animationTime + "s");
		screenOb.css("-webkit-animation-duration", animationTime + "s");

		// Check for animation triggers
		var animationIn = ob.animations.animIn;
		if (typeof ob.animations.animInTrigger != "undefined" && ob.animations.animInTrigger != "none") {
			animationIn = ob.animations.animInTrigger.animationName;
		}

		var animationOut = ob.animations.animOut;
		if (typeof ob.animations.animOutTrigger != "undefined" && ob.animations.animOutTrigger != "none") {
			animationOut = ob.animations.animOutTrigger.animationName;
		}

		if (animationIn !== "none" && screenOb.hasClass(animationIn)) {
			screenOb.removeClass(animationIn);
			screenOb.css('display', 'block');
		}

		var animationEndless = ob.animations.endless;
		if (animationEndless !== "none" && screenOb.hasClass(animationEndless)) {
			screenOb.removeClass(animationEndless);
		}
		

		if (animationOut !== "none") {
			screenOb.addClass(animationOut);

			clearTimeout(ob.animations.to);
			ob.animations.to = setTimeout(function() {
				screenOb.removeClass(animationOut);
				screenOb.css('display', 'none');
			}, 2500);
		} else {
			screenOb.css('display', 'none');
		}
		if (ob.action == 25) {
			setTimeout(function() {
				$('._jsPlumb_endpoint, ._jsPlumb_connector').fadeOut();
			}, 10);
		}
	}


	// screenOb.css('display', 'none');
};

/* -------------- PAGE  ------------------- */

CourseManager.prototype.page_endActionHandler = function(page) {
	var _that = this;
	    
    switch (page.opts.endAction) {
        case 'none' :
            break;
        case 'nextpage' :
            _that.initPage('next');
            break;
        case 'prevpage' :
            _that.initPage('previous');
            break;
        default:
        	var data = {
        		pageID: parseInt(page.opts.endAction)
        	}
        	_that.initPage('loadPageByID', data);

            break;
    }
};

CourseManager.prototype.page_handleTimer = function(cmd, page) {
	var _that = this;

	switch (cmd) {
		case 'start':
            var date = new Date();
            page.opts.time = date.getTime();
			break;


		case 'stop':
			if (typeof _that.course.user.page_time === 'object' && page.opts.time != undefined) {
	            var date = new Date();
	            //page.opts.time = date.getTime() - page.opts.time;
	            _that.course.user.page_time[page.opts.id] += (date.getTime() - page.opts.time);
	        }
			break;
	}
};

CourseManager.prototype.hideWholeLine = function(pageID, line) {
	var _that = this;

	// debug.log(line);

	for (var ob in line.objects) {
		_that.object_hiding(line.objects[ob], _that.getScreenObjectByActionkey(line.objects[ob].id));
	}
};

/* -------------- LINE  ------------------- */

CourseManager.prototype.checkClickLineCompletion = function(pageID, lineID) {
	var _that = this;

	var completed = true;

	for (var i = 0; i < _that.course.pages[pageID].lines[lineID].objects.length; i++ ) {
		if ( parseInt(_that.course.pages[pageID].lines[lineID].objects[i].clicked) === 0 ) {
			completed = false;
		}
	}

	debug.log("Everything on line is clicked? " + completed);
	return completed;
};

CourseManager.prototype.checkPassingLineCompletion = function(pageID, lineID) {
	var _that = this;

	var completed = true;

	for (var i = 0; i < _that.course.pages[pageID].lines[lineID].objects.length; i++ ) {
		if ( _that.course.pages[pageID].lines[lineID].objects[i].status === 1 && parseInt(_that.course.pages[pageID].lines[lineID].objects[i].compl) === 0 ) {
				completed = false;
		}
	}

	debug.log("Is line passed? " + completed);
	return completed;
};

/* -------------- TIMERS  ------------------- */

CourseManager.prototype.timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        remaining -= new Date() - start;
    };

    this.resume = function() {
        start = new Date();
        timerId = window.setTimeout(callback, remaining);
    };

    this.stop = function() {
    	window.clearTimeout(timerId);
    }

    this.resume();

    return timerId;
};

CourseManager.prototype.timer2 = function(seconds, onTick, onComplete) {

	var _that = this;

	_that.timerId = undefined;

    _that.timerTime = seconds != undefined ? seconds : 0;

    _that.timerStarted = false;

    _that.startTimer = function() {
    	if (!_that.timerStarted) {
    		_that.onTick( _that.timerTime );
    		_that.timerStarted = true;
    	}
    };

    _that.loop = function() {
    	
    	if(_that.timerTime > 0){

    		_that.timerId = window.setTimeout( function(){ _that.onTick( _that.timerTime ) }, 1000 );
    		
    	}else{
    		_that.onComplete();
    	}

    	_that.timerTime --;
    };

    _that.stop = function() {
    	window.clearTimeout(_that.timerId);
    	_that.timerStarted = false;
    }

    _that.pause = function() {
    	_that.timerStarted = false;
    	window.clearTimeout(_that.timerId);
    }

    _that.onTick = function( timerTime ) {

    	if (timerTime >= 0) {

	    	var t = _that.convertToTime( timerTime );

	    	// debug.log(onTick);

	    	if(onTick != undefined){

	    		// debug.log("onTick " + t);

	    		onTick( t, timerTime );
	    	}

	    	_that.loop();
    	}
    }

    _that.onComplete = function() {
    	debug.log("onComplete");

    	_that.stop();

    	if(onComplete != undefined){
    		onComplete();
    	}
    }

    _that.convertToTime = function( timeInSeconds ){

		var date = new Date(null);
		date.setSeconds(timeInSeconds);
		var time = _that.retValue( date.getUTCHours() ) + ':' + _that.retValue( date.getUTCMinutes() ) + ':' + _that.retValue( date.getUTCSeconds() );

		return time;
	}

	_that.retValue = function( value ){

		var ret  = value < 10 ? '0' + value : value;
		return ret;
	}

	return _that;
};

CourseManager.prototype.clearAllTimers = function() {
	var _that = this;

	for (var i = 0; i < _that.course.to.length; i++) {
		window.clearTimeout(_that.course.to[i]);
	}

	_that.course.to = [ ];
};

/* -------------- TIMELINE  ------------------- */

CourseManager.prototype.launchTimeline = function(pageID, line, objectID) {
	var _that = this;

	// animate first line
	_that.loadLine(pageID, line, objectID);

	_that.setPageOptions('setComplete', _that.getPageByID(pageID));
};

CourseManager.prototype.loadLine = function(pageID, line, objectID) {
	var _that = this;
	// debug.log('Loading next line! (pageID: '+ pageID +', line: ' + line.opts.id + ')');

	var numberOfLines = Utils.ObjectLength(_that.course.pages[pageID].lines);

	if (typeof line === "object" && line.opts.hide == "1") {
		_that.loadLine(pageID, _that.getLineByOrder(pageID, (parseInt(line.opts.order) + 1)), 0);
		return;
	}

	// check if line exists in this page
 	if( typeof line === "object") {
		
		var lineOrder = _that.course.pages[pageID].lines[line.opts.id].opts.order;

		var ob = _that.course
					.pages[pageID]
					.lines[line.opts.id]
					.objects[objectID];

		_that.course.opts.active.line = line.opts.id;

		var line_delaytime = parseFloat(ob.animations.delaytime);

		_that.course.to.push(
			_that.timer(
				function() { _that.loadObject(pageID, line, objectID, false); },
				line_delaytime * 1000
			)
		);
	// it's last line in this page!
	} else {

		var activePage = _that.getPageByOrder(_that.course.opts.active.pageOrder);

		_that.setPageOptions('unlockNavigation', activePage);
		_that.setPageOptions('setComplete', activePage);
		_that.page_endActionHandler(activePage);

		debug.log(' +++ End of lines! +++');
	}
};

CourseManager.prototype.loadObject = function(pageID, line, objectID, triggered) {
	var _that = this;

	var numberOfObjects = _that.getLineObjectsNumber(pageID, line.opts.id);

	// debug.log("objectID  < numberOfObjects");
	// debug.log(objectID + " < " + numberOfObjects);

	// check if object exists in this line
	if (objectID < numberOfObjects) {

		var ob = _that.course
				.pages[pageID]
				.lines[line.opts.id]
				.objects[objectID];

		if (!ob) {
			return;
		}

		// if object is hidden - dont load it
		if (((typeof ob.hidden === "boolean" && ob.hidden === true) || (typeof ob.hiddenWithTrigger === "boolean" && ob.hiddenWithTrigger === true)) && !triggered) {
			// debug.log(" { Pomijanie obiektu: ");
			// debug.log(ob);
			_that.loadObject(pageID, line, objectID+1, triggered);
		} else {
			_that.animateObject(pageID, line, objectID, triggered); 
			_that.handleLineTypes(pageID, line, objectID, triggered);
		}
	} else {
		// debug.log('TRIGGERED? ' + triggered);
		if (!triggered) {
			var prevOb = _that.course
				.pages[pageID]
				.lines[line.opts.id]
				.objects[objectID-1];

			switch( prevOb.animations.lineType ) {
				case 'after_time': 
					if (line.opts.wflc) {
						_that.loadLine(pageID, _that.getLineByOrder(pageID, (parseInt(line.opts.order) + 1)), 0);
					}
					break;
			}
		}
	}
};

CourseManager.prototype.animateObject = function(pageID, line, obID, triggered) {
	var _that = this;


	// try {
	 	// get actual object to animate
		var ob = _that.course
						.pages[pageID]
						.lines[line.opts.id]
						.objects[obID];
		
		// get object on screen
		var screenOb = _that.getScreenObjectByActionkey(ob.id);

		// showing object
		_that.object_before_show(ob, screenOb, triggered);
		_that.object_showing(ob, screenOb, triggered, triggered);

		// hiding
		_that.object_before_hide(ob, screenOb);
		// _that.object_hiding(ob, screenOb);
		_that.object_after_hide(ob, screenOb);

		

	// } catch(msg) {
	// 	debug.log(msg);
	// }
};

CourseManager.prototype.handleLineTypes = function(pageID, line, objectID, triggered) {
	var _that = this;

	var ob = _that.course
					.pages[pageID]
					.lines[line.opts.id]
					.objects[objectID];

	switch( ob.animations.lineType ) {


		case 'after_time': 
			// if its a normal line then play next line
			if (objectID === 0 && !line.opts.wflc && !triggered) {
				_that.loadLine(pageID, _that.getLineByOrder(pageID, (parseInt(line.opts.order) + 1)), 0);
			}

			// get object lifetime
			var timeout = parseFloat(ob.animations.obTime);

			// check if line is one by one or all together
			if ( !parseInt(ob.animations.async) && !_that.isLastObject(pageID, line, objectID) ) {
				timeout = 0;
			}

			// push new timeout into array
			if (timeout > 0 && !_that.isMobile) {
				_that.course.to.push(
					_that.timer(
						function() { 
							_that.loadObject(pageID, line, objectID+1, triggered);
						},
						timeout * 1000
					)
				);
			} else {
				_that.loadObject(pageID, line, objectID+1, triggered);
			}
			
			break;

		case 'all_clicked':
			_that.object_addRequireClickEvent(pageID, line, objectID, triggered);

			break;

		case 'all_passed':
			_that.object_addRequirePassingEvent(pageID, line, objectID, triggered);

			break;

	}
};

/* -------------- QUIZZING ------------------- */

CourseManager.prototype.quiz_selectAtLeastOneAnswerInfo = function(msg, style) {
	var _that = this;

	debug.log('SHOWING INFO............');
	
    var first_answer_div = _that.L.scr.find('.answer-questions-first');


    if (first_answer_div.push() === 0) {
    	debug.log('dodaje diva');
        first_answer_div = $('<div class="answer-questions-first"><span>'+msg+'</span></div>');
        _that.L.scr.append(first_answer_div);
    }

    if (_that.course.opts.singleFile) {
    	first_answer_div.css({
    		top: '10px',
    		left: '0px',
    		position: 'absolute'
    	});
    }

    switch(style) {
    	case 'red':
	    	first_answer_div.find('span').css({
	    		color: '#fff',
	    		background: '#EF5656'
	    	});
    		break;
    	case 'yellow':
	    	first_answer_div.find('span').css({
	    		color: '#000',
	    		background: '#F7F57A'
	    	});
    		break;
    	default:
	    	first_answer_div.find('span').css({
	    		color: '#000',
	    		background: '#F7F57A'
	    	});
    		break;
    }

     first_answer_div.show('drop', {direction: 'up', distance: 15}, 400);

     setTimeout(function(){
        first_answer_div.hide('drop', {direction: 'up', distance: 15}, 400);
     }, 2000);
};

CourseManager.prototype.populateQuizResultDivs = function() {
	var _that = this;

	_that.L.scr.find('.quiz-results-wrapper').each(function(){

		var screenOb = $(this);

		screenOb.find('.result-info-wrapper p').each(function(){
	        if ( $(this).css('opacity') != 1 )
	            $(this).hide();
	    });
	    
	    var passed_failed_text,
	        percentage_score;
	    
	    screenOb.find('.result-max-score span.result-value').text(_that.course.opts.score.max);
	    screenOb.find('.result-required-score span.result-value').text(_that.course.opts.score.required);
	    screenOb.find('.result-your-score span.result-value').text(_that.course.user.score);
	    
	    if (_that.course.opts.score.max === 0) {
	        percentage_score = 100;
	    } else {
	        percentage_score = parseInt((_that.course.user.score / _that.course.opts.score.max) * 100);
	    }
	    
	    if(percentage_score > 100)
	        percentage_score = 100;
	    
	    if(percentage_score <= 0)
	        percentage_score = 0;


	    screenOb.find('.result-percentage-score span.result-value').text(percentage_score + '%');

	    if( _that.course.user.score < _that.course.opts.score.required ) {
	    	passed_failed_text = screenOb.attr('info-bad');
	    } else {
	    	passed_failed_text = screenOb.attr('info-good');
	    }

	    screenOb.find('.result-info strong').text(passed_failed_text);

	});
};

CourseManager.prototype.quiz_ShowFeedback = function(ob, screenOb, answersStatus) {
	var _that = this;


	var userAttempts = 0;

	switch(_that.getObjectType(ob)) {
		case 'forms':
			userAttempts = isNumber(ob.qattempts) ? ob.qattempts : 999;
			break;

		default:
			userAttempts = isNumber(ob.question.attempts) ? ob.question.attempts : ob.qattempts;
			break;
	}

    if( answersStatus.questionIsPassed ) {

        var goodFeedback = screenOb.attr('feedback-good');
        
        if(goodFeedback == ''){
            goodFeedback = lang[language]['POINTS_FEEDBACK_GOOD'];
        }
        
        _that.L.feedbackWrapper.find('.feedback-button').attr('actionkey', screenOb.attr('actionkey'));
        _that.L.feedbackWrapper.find('.feedback-back').removeClass('feedback-back-bad').addClass('feedback-back-good');
        _that.L.feedbackWrapper.find('.feedback-text').html(goodFeedback);
        _that.L.feedbackWrapper.find('.feedback-avatar').removeClass('feedback-avatar-bad').addClass('feedback-avatar-good');
        
        // odpal event dla cwiczenia zaliczonego
        triggerEvent(screenOb[0], 'custom_questionpassed');
		// triggerEvent(screenOb[0], 'custom_requirepassing');

        // dodaj punkty za zaliczenie
        _that.course.user.score += ob.score;

        // ustaw zaliczenie na 1 - czyli passed
		ob.compl = 1;
        
        if (ob.score !== 0) {
            _that.L.feedbackWrapper.find('.feedback-text').append('<p class="question-score-info">'+ lang[language]['POINTS_FEEDBACK_1'] + ' ' + ob.score + ' '+ lang[language]['POINTS_FEEDBACK_2'] +' ' + _that.course.user.score + ' ' + lang[language]['POINTS_FEEDBACK_3'] + '</p>');
        }

        // odswiez quiz results diva
        _that.populateQuizResultDivs();


    	switch (ob.action) {
    		case 22: 
    			_that.quiz_multipleMarkQuestionAsPassed(ob, screenOb);
    			break;

    		case 23: 
    			_that.quiz_qtextMarkQuestionAsPassed(ob, screenOb);
    			break;

    		case 24: 
    			_that.quiz_dndMarkQuestionAsPassed(ob, screenOb);
    			break;

    		case 25: 
    			_that.quiz_qclMarkQuestionAsPassed(ob, screenOb);
    			break;

    		case 55: 
    			_that.forms_markElemsAsCompleted(ob, screenOb);
    			break;
    	}

    } else {
        
        var badFeedback = screenOb.attr('feedback-bad');
        
        if(badFeedback == ''){
            badFeedback = lang[language]['POINTS_FEEDBACK_BAD'];
        }
        
        _that.L.feedbackWrapper.find('.feedback-back').removeClass('feedback-back-good').addClass('feedback-back-bad');
        _that.L.feedbackWrapper.find('.feedback-text').html(badFeedback);
        _that.L.feedbackWrapper.find('.feedback-avatar').removeClass('feedback-avatar-good').addClass('feedback-avatar-bad');

        if (ob.action === 55) {
        	ob.question = {
        		attempts: 0
        	}
        }

        debug.log(userAttempts);

        // user has more attempts
        if ( (userAttempts - 1) !== 0 ) {
            ob.question.attempts--;
            ob.qattempts--;
            ob.touched = 1;

            // debug.log(ob.question.attempts)
            // debug.log(ob.qattempts)

            // odpal event dla zlej odpowiedzi
            triggerEvent(screenOb[0], 'custom_questionbadanswer');

        // user has NO MORE attempts
        } else {
        	userAttempts = "n";
            ob.question.attempts = "n";
            ob.qattempts = "n";

            // dodaj punkty do offlineScora
            _that.course.user.score += ob.scoreFail;

            // ustaw zaliczenie na 2 - czyli failed
            ob.compl = 2;

            // odpal event dla cwiczenia niezaliczonego
            triggerEvent(screenOb[0], 'custom_questionfailed');
            // triggerEvent(screenOb[0], 'custom_requirepassing');
            
            // odswiez quiz results diva
            _that.populateQuizResultDivs();

            // pokaz odpowiednia ilosc punktow w feedbacku
            if (ob.scoreFail !== 0) {
                _that.L.feedbackWrapper.find('.feedback-text').append('<p class="question-score-info">'+ lang[language]['POINTS_FEEDBACK_1'] + ' ' + ob.scoreFail + ' '+ lang[language]['POINTS_FEEDBACK_2'] +' ' + _that.course.user.score + ' ' + lang[language]['POINTS_FEEDBACK_3'] + '</p>');
        	}

        	switch (ob.action) {
        		case 22: 
        			_that.quiz_multipleMarkQuestionAsFailed(ob, screenOb);
        			break;

        		case 23: 
        			_that.quiz_qtextMarkQuestionAsFailed(ob, screenOb);
        			break;

        		case 24: 
        			_that.quiz_dndMarkQuestionAsFailed(ob, screenOb);
        			break;

	    		case 25: 
	    			_that.quiz_qclMarkQuestionAsFailed(ob, screenOb);
	    			break;

	    		case 55: 
	    			_that.forms_markElemsAsFailed(ob, screenOb);
	    			break;
        	}

        	// _that.object_endActionHandler(ob, screenOb);
        	
        }
    }

	
    if (typeof screenOb.attr('feedbacks') === 'string' && screenOb.attr('feedbacks') === 'true' ){
        _that.L.feedbackWrapper.css({
        	display: 'block', 
        	visibility: 'visible',
        	position: 'absolute'
        });
        _that.L.feedbackBtn.attr('tabindex', '98');
        _that.L.feedbackBtn.focus();
        _that.L.feedbackBtn.click(function() {
	    	if (ob.compl !== 0) {
	    		_that.object_endActionHandler(ob, screenOb);
	    	}
	    	_that.L.feedbackBtn.removeAttr('tabindex');
	    	// $(this).off('click');
        });
    } else {
    	if (ob.compl !== 0) {
    		_that.object_endActionHandler(ob, screenOb);
    	}
    }

    _that.setPageOptions('setComplete', _that.getPageByID(_that.course.opts.active.pageID));
    _that.checkAndSetCourseStatus();
};

// quiz multiple methods
CourseManager.prototype.quiz_multipleMarkQuestionAsFailed = function(ob, screenOb) {
	var _that = this;

    // show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

	screenOb.find('input, a').addClass('disabled-btn').prop('disabled', true);

	if ( showSigns ) {
        screenOb.find('.question-header').append('<div class="question-failed"><div class="failed-marker"></div></div>');
    }

	screenOb.find('input').each(function(){
        $(this).prop('disabled', true);
        $(this).next().prop('disabled', true);
        $(this).prop('checked', false);
    });


	// mark all answers that user last time selected - its his selection when 
    for (var answerID in ob.question.answers) {
    	// if answer is correct then mark it on screen

    	var userSelection = ob.question.answers[answerID].userSelection;

    	if (userSelection.length > 0 && userSelection[userSelection.length-1]) {
    		screenOb.find('#' + answerID + ' input').prop('checked', true);
    	}
    	
    }

    screenOb.off('click');
};

CourseManager.prototype.quiz_multipleMarkQuestionAsPassed = function(ob, screenOb) {
	var _that = this;

    screenOb.find('input, a').addClass('disabled-btn').prop('disabled', true);
	
    // show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

    if ( showSigns ) {
        screenOb.find('.question-header').append('<div class="question-completed"><div class="passed-marker"></div></div>');
    }

	screenOb.find('input').each(function(){
        $(this).prop('disabled', true);
        $(this).next().prop('disabled', true);
        $(this).prop('checked', false);
    });

	// mark all good answers bcos question is completed
    for (var answerID in ob.question.answers) {
    	// if answer is correct then mark it on screen
    	if (ob.question.answers[answerID].correct) {
    		screenOb.find('#' + answerID + ' input').prop('checked', true);
    	}
    	
    }

    screenOb.off('click');
};

CourseManager.prototype.quiz_multiplePrepareQuestion = function(ob, screenOb) {
	var _that = this;

	// question is not yet completed
	if (ob.compl === 0) {
		screenOb.find('input').each(function(){
	        $(this).prop('disabled', false);
	        $(this).next().prop('disabled', false);
	        $(this).prop('checked', false);
	    });

	// question is passed
	} else if(ob.compl === 1) {
		_that.quiz_multipleMarkQuestionAsPassed(ob, screenOb);
		setTimeout(function() {
			triggerEvent(screenOb[0], 'custom_questionpassed');
			// triggerEvent(screenOb[0], 'custom_requirepassing');
		},10);

	// question is failed
	} else if (ob.compl === 2) {
		_that.quiz_multipleMarkQuestionAsFailed(ob, screenOb);
		setTimeout(function() {
			triggerEvent(screenOb[0], 'custom_questionfailed');
			// triggerEvent(screenOb[0], 'custom_requirepassing');
		},10);
	}
    
    // multiple choice question Submit btn handle
    screenOb.find('.question-submit-btn').on('click', function(){
    	
        if (!($(this).hasClass('disabled-btn'))) {
            _that.quiz_multipleCheckAnswers(ob, screenOb);
        }

        // setTimeout(function() {
        	// _that.L.iframe.contents().find('.feedback-front .feedback-button').trigger('focus');
        // }, 1000);

        //$('.feedback-front .feedback-button').select();
        
    });
};

CourseManager.prototype.quiz_multipleCheckAnswers = function(ob, screenOb) {
	var _that = this;

	var userAttempts = !isUndefined(ob.question.attempts) ? ob.question.attempts : ob.qattempts;

    // if there are no attempts - return
    if (userAttempts == 'n' || ob.compl !== 0){
        return false;
    } 


	// get screen answers wrappers
    var screenObAnswers = screenOb.find('.multiple-answer');
    

    // if neither answer is selected - show info to select at least one answer
    if (screenObAnswers.find('input:checked').push() === 0) {
        _that.quiz_selectAtLeastOneAnswerInfo(lang[language]['ANSWER_QUESTIONS_FIRST'], 'red');
        return;
    }

    var answers_status = {
    	questionIsPassed: true
    };

    screenObAnswers.each(function(){

    	var answerID = $(this).attr('id');
    	answers_status[answerID] = false;

        if ($(this).find('input').is(':checked')) {
        	if (ob.question.answers[answerID].correct) {
        		answers_status[answerID] = true;
        	} else {
        		answers_status[answerID] = false;
        	}
        	ob.question.answers[answerID].userSelection.push(true);
        } else {
        	if (ob.question.answers[answerID].correct) {
        		answers_status[answerID] = false;
        	} else {
        		answers_status[answerID] = true;
        	}
        	ob.question.answers[answerID].userSelection.push(false);
        }
    });


    for (var ans in answers_status) {
    	if (answers_status[ans] !== true) {
			answers_status.questionIsPassed = false;
    	}
    }

    _that.quiz_ShowFeedback(ob, screenOb, answers_status);
};

// quiz Qtext methods
CourseManager.prototype.quiz_qtextPrepareQtextQuestion = function(ob, screenOb) {
	var _that = this;

	// question is not yet completed
	if (ob.compl === 0) {
		// ZADANIADOMEP =============================================
		// for (var ans in ob.question.answers) {
		// 	var answer = ob.question.answers[ans];
		// 	for (var subans in answer) {
		// 		if (typeof answer[subans].userSelection !== 'undefined' && answer[subans].userSelection.length > 0) {
		// 			_that.quiz_qtextMarkQuestionAsPassed(ob, screenOb);
		// 		}
		// 	}
		// }
		// ZADANIADOMEP END=============================================

	// question is passed
	} else if(ob.compl === 1) {
		_that.quiz_qtextMarkQuestionAsPassed(ob, screenOb);
		setTimeout(function() {
			triggerEvent(screenOb[0], 'custom_questionpassed');
			// triggerEvent(screenOb[0], 'custom_requirepassing');
		},10);

	// question is failed
	} else if (ob.compl === 2) {
		_that.quiz_qtextMarkQuestionAsFailed(ob, screenOb);
		setTimeout(function() {
			triggerEvent(screenOb[0], 'custom_questionfailed');
			// triggerEvent(screenOb[0], 'custom_requirepassing');
		},10);
	}


	if (screenOb.attr('adddefaultvalue') === "true") {
		screenOb.find('select').each(function() {
			$(this).find('option').first().attr('value', 'defaultselectvalue');
		});
	}
    
    // multiple choice question Submit btn handle
    screenOb.find('.qtext-submit').on('click', function(){
        if (!($(this).hasClass('disabled-btn'))) {
            _that.quiz_qtextCheckAnswers(ob, screenOb);
        }
        
    });
};

CourseManager.prototype.quiz_qtextMarkQuestionAsFailed = function(ob, screenOb) {
	var _that = this;

    // show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

    screenOb.find('input, .qtext-submit, select, textarea').addClass('disabled-btn').prop('disabled', true);

	if ( showSigns ) {
        screenOb.find('.qtext-header').append('<div class="question-failed"><div class="failed-marker"></div></div>');
    }

	// screenOb.find('input').each(function(){
 //        $(this).prop('disabled', true);
 //        $(this).next().prop('disabled', true);
 //        $(this).prop('checked', false);
 //    });


	// mark all good answers bcos question is completed
    for (var lineID in ob.question.answers) {
    	for (var inputID in ob.question.answers[lineID]) {

    		var userSelection = ob.question.answers[lineID][inputID].userSelection;
			if (userSelection.length > 0) {
				var span = screenOb
							.find('li[ansid=' + lineID + ']')
							.find('.qtext-txt[subanswer=' + inputID + ']');

				
				switch (span.attr('atype')) {
					case 'input':
						span.find('input').val(userSelection[userSelection.length-1].trim());
						break;
						
					case 'textarea':
						span.find('textarea').val(userSelection[userSelection.length-1].trim());
						break;

					case 'select':
						span.find('select').val(userSelection[userSelection.length-1].trim());
						break;
				}

			}
    	}
    }
    screenOb.off('click');
};

CourseManager.prototype.quiz_qtextMarkQuestionAsPassed = function(ob, screenOb) {
	var _that = this;

    screenOb.find('input, .qtext-submit, select, textarea').addClass('disabled-btn').prop('disabled', true);
	
    // show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

    if ( showSigns ) {
        // screenOb.find('.qtext-header').append('<div class="question-completed"><div class="passed-marker"></div></div>');
    }

	// screenOb.find('input').each(function(){
 //        $(this).prop('disabled', true);
 //        $(this).next().prop('disabled', true);
 //        $(this).prop('checked', false);
 //    });

	// mark all good answers bcos question is completed
    for (var lineID in ob.question.answers) {
    	for (var inputID in ob.question.answers[lineID]) {

    		var userSelection = ob.question.answers[lineID][inputID].userSelection;
			if (userSelection.length > 0) {
				var span = screenOb
							.find('li[ansid=' + lineID + ']')
							.find('.qtext-txt[subanswer=' + inputID + ']');

				
				switch (span.attr('atype')) {
					case 'input':
						span.find('input').val(userSelection[userSelection.length-1].trim());
						break;

					case 'textarea':
						span.find('textarea').val(userSelection[userSelection.length-1].trim());
						break;

					case 'select':
						span.find('select').val(userSelection[userSelection.length-1].trim());
						break;
				}

			}
    	}
    }
    screenOb.off('click');
};

CourseManager.prototype.quiz_qtextPrepareQuestionToEdit = function(ob, screenOb) {
	var _that = this;

    screenOb.find('input, .qtext-submit, select, textarea').removeClass('disabled-btn').prop('disabled', false);


	

	// populate all inputs with last user answers
    for (var lineID in ob.question.answers) {
    	for (var inputID in ob.question.answers[lineID]) {

    		var userSelection = ob.question.answers[lineID][inputID].userSelection;
			if (userSelection.length > 0) {
				var span = screenOb
							.find('li[ansid=' + lineID + ']')
							.find('.qtext-txt[subanswer=' + inputID + ']');

				
				switch (span.attr('atype')) {
					case 'input':
						span.find('input').val(userSelection[userSelection.length-1].trim());
						break;

					case 'textarea':
						span.find('textarea').val(userSelection[userSelection.length-1].trim());
						break;

					case 'select':
						span.find('select').val(userSelection[userSelection.length-1].trim());
						break;
				}

			}
    	}
    }
    // multiple choice question Submit btn handle
    screenOb.find('.qtext-submit').on('click', function(){
        if (!($(this).hasClass('disabled-btn'))) {
            _that.quiz_qtextCheckAnswers(ob, screenOb);
        }
    });
};

CourseManager.prototype.quiz_qtextMarkInputAsPassed = function(ob, screenOb, input) {
	var _that = this;

	// show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

    if (showSigns){
	    input.css({
                    outline: '1px solid #0F9C00',
                    background: '#0F9C00',
                    color: '#fff'
                });
    }
};

CourseManager.prototype.quiz_qtextMarkInputAsFailed = function(ob, screenOb, input) {
	var _that = this;

	// show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );

    if (showSigns){
        input.css({
                    outline: '1px solid #FF7878',
                    background: '#FF7878',
                    color: '#fff'
                });
    }
};

CourseManager.prototype.quiz_qtextMarkLineAsPassed = function(ob, screenOb, line) {
	var _that = this;

	// show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );


    if (showSigns){
        line.removeClass('bad-line-answer').addClass('good-line-answer');
    }
};

CourseManager.prototype.quiz_qtextMarkLineAsFailed = function(ob, screenOb, line) {
	var _that = this;

	// show signs on answers when passed failed?
    var showSigns = (typeof screenOb.attr('fsign') === 'string' && screenOb.attr('fsign') === 'true' );


    if (showSigns){
        line.removeClass('good-line-answer').addClass('bad-line-answer');
    }
};

CourseManager.prototype.quiz_qtextCheckFilledTextAnswers = function(ob, screenOb) {
	var _that = this;

	var allFilled = true;

	// get screen answers wrappers
    var screenObAnswers = screenOb.find('.qtext-answers-list li.qtext-answer');

	screenObAnswers.each(function(){

		var lineID = parseInt($(this).attr('ansid'));

		$(this).find('span.qtext-txt[atype="input"], span.qtext-txt[atype="select"], span.qtext-txt[atype="textarea"]').each(function() {
			var user_input = null;
			var inputType = $(this).attr('atype');

			var inputID = parseInt($(this).attr('subanswer'));

            if (inputType === "input") {
                // get user input value
                user_input = $(this).find('input[type="text"]').val().trim();
                if (user_input.length == 0) {
                	allFilled = false;
                }
            }
            if (inputType === "textarea") {
                // get user input value
	            user_input = $(this).find('textarea').val().trim();
                if (user_input.length == 0) {
                	allFilled = false;
                }
            }
            if (inputType === "select") {
                // if user has selected at least one answer in select
                user_input = $(this).find('select option:selected').attr('value');

                if (user_input === 'defaultselectvalue') {
                	allFilled = false;
                }
            }
		});

	});

	if (allFilled) {
		return true;
	} else {
		return false;
	}
};

CourseManager.prototype.quiz_qtextCheckAnswers = function(ob, screenOb) {
	var _that = this;

    // if there are no attempts - return
    if (ob.question.attempts == 'n' || ob.compl !== 0){
        return false;
    } 

    if (!_that.quiz_qtextCheckFilledTextAnswers(ob, screenOb)) {
    	_that.quiz_selectAtLeastOneAnswerInfo(lang[language]['ANSWER_ALL_QUESTIONS_FIRST'], 'red');
    	return false;
    }


	// get screen answers wrappers
    var screenObAnswers = screenOb.find('.qtext-answers-list li.qtext-answer');

    var answers_status = {
    	questionIsPassed: true
    };
    
    var lines_number = screenObAnswers.push();
    var line_passed_number = 0;

    var checked_ans = [];
    
    // iterate through every question line
    screenObAnswers.each(function(){
        var line = $(this);
        
        var lineID = parseInt($(this).attr('ansid'));

        var line_answer_number = $(this).find('span.qtext-txt[atype="input"], span.qtext-txt[atype="select"], span.qtext-txt[atype="textarea"]').push();
        var good_answer_counter = 0;

        
        // iterate throught every select or input in actual line
        $(this).find('span.qtext-txt[atype="input"], span.qtext-txt[atype="select"], span.qtext-txt[atype="textarea"]').each(function() {
            var that = $(this);
            
            var inputID = parseInt(that.attr('subanswer'));
            var inputType = that.attr('atype');
            
            // debug.log(ob.question);
            // debug.log(lineID);
            // debug.log(inputID);

            // get list of all good answers for input
            var good_answers = ob.question.answers[lineID][inputID].pa;

            var user_input = null;
            if (inputType === "input") {
                var cs = (that.attr('cs') === 'true');

                // get user input value
                user_input = $(this).find('input[type="text"]').val().trim();
                var checked_input = $(this).find('input[type="text"]');

                oob = {
                    ans: user_input,
                    line: parseInt($(this).parent().attr('ansid'))
                }

                checked_ans.push(oob);

                if (typeof good_answers !== "object")
                	good_answers = JSON.parse(good_answers);

                $.each(good_answers, function(key, val) {
            	// for (var good_answer_value in good_answers) {
                    // jesli pytanie jest case sensitive to zwracaj uwage na wielkosc liter
                    var answer_check = key;
                    var user_input_to_check = user_input;
                    if (!cs) {
                        answer_check = key.toLowerCase();
                        user_input_to_check = user_input_to_check.toLowerCase();
                    }

                    if ( user_input_to_check.trim() === answer_check.trim() ) {
                        // oznacz odpowiedz jako prawidlowa
                        _that.quiz_qtextMarkInputAsPassed(ob, screenOb, checked_input);
                        good_answer_counter++;
                        return false;
                    } else {
                        // oznacz odpowiedz jako zla
                        _that.quiz_qtextMarkInputAsFailed(ob, screenOb, checked_input);

                    } 
                });
            }
            else if (inputType === "textarea") {
	            var cs = (that.attr('cs') === 'true');

	            // get user input value
	            user_input = $(this).find('textarea').val().trim();
	            var checked_input = $(this).find('textarea');

                oob = {
                    ans: user_input,
                    line: parseInt($(this).parent().attr('ansid'))
                }

                checked_ans.push(oob);

                if (typeof good_answers !== "object")
                	good_answers = JSON.parse(good_answers);

                $.each(good_answers, function(key, val) {
            	// for (var good_answer_value in good_answers) {
                    // jesli pytanie jest case sensitive to zwracaj uwage na wielkosc liter
                    var answer_check = key;
                    var user_input_to_check = user_input;
                    if (!cs) {
                        answer_check = key.toLowerCase();
                        user_input_to_check = user_input_to_check.toLowerCase();
                    }

                    if ( user_input_to_check.trim() === answer_check.trim() ) {
                        // oznacz odpowiedz jako prawidlowa
                        _that.quiz_qtextMarkInputAsPassed(ob, screenOb, checked_input);
                        good_answer_counter++;
                        return false;
                    } else {
                        // oznacz odpowiedz jako zla
                        _that.quiz_qtextMarkInputAsFailed(ob, screenOb, checked_input);

                    } 
                });
            }
            else if (inputType === "select") {

                var select_box = $(this).find('select');
                user_input = $(this).find('select option:selected').text();
                
                oob = {
                    ans: user_input,
                    line: parseInt($(this).parent().attr('ansid'))
                }

                checked_ans.push(oob);

                $.each(good_answers, function(key, val) {
                    if (user_input.trim() === key.trim()) {
                        if (val === 1) {
                            // oznacz jesli odpowiedz jest prawidlowa
                            good_answer_counter++;
                            _that.quiz_qtextMarkInputAsPassed(ob, screenOb, select_box);
                            return false;
                        } else {
                            // oznacz jesli odpowiedz jest zla
                            _that.quiz_qtextMarkInputAsFailed(ob, screenOb, select_box);
                        }
                    }
                    
                });
                
            }



            ob.question.answers[lineID][inputID].userSelection.push(user_input);
        });
        
        if (line_answer_number === good_answer_counter) {
            _that.quiz_qtextMarkLineAsPassed(ob, screenOb, line);
            line_passed_number++;
        } else {
            _that.quiz_qtextMarkLineAsFailed(ob, screenOb, line);
        }
        
        
    });

	var answersStatus = { };

	if (lines_number === line_passed_number) {
		answersStatus.questionIsPassed = true;
	} else {
		answersStatus.questionIsPassed = false;
	}

	_that.quiz_ShowFeedback(ob, screenOb, answersStatus);
};

//quiz DnD methods
CourseManager.prototype.quiz_dndPrepareDnDQuestion = function(ob, screenOb) {
	var _that = this;

	debug.log('quiz_dndPrepareDnDQuestion');

	screenOb.click(function() { _that.quiz_dndCheckAnswers(ob, screenOb) });
	screenOb.css({
		opacity: 1
	});

	for (var o = ob.question.draggableObjs.length - 1; o >= 0; o--) {

		var draggableOb = _that.getObjectByID(ob.question.draggableObjs[o]);
		var draggableScreenOb = _that.getScreenObjectByActionkey(ob.question.draggableObjs[o]);

		draggableScreenOb.attr('name', ob.id);

		if (typeof draggableScreenOb.attr('tabindexorg') !== "undefined") {
			draggableScreenOb.attr('tabindex', draggableScreenOb.attr('tabindexorg'));
		}

		if (typeof draggableOb.startPos === "object") {
			draggableScreenOb.css({
				left: draggableOb.startPos.leftStartPos,
				top: draggableOb.startPos.topStartPos,
				opacity: 1,
				cursor: 'pointer'
			});
		}

		draggableOb.startPos = {
			leftStartPos: parseInt(draggableScreenOb.css('left')),
			topStartPos: parseInt(draggableScreenOb.css('top'))
		};

		draggableScreenOb.removeClass('bounceOut');

		draggableOb.droppedwithkeyboard = false;

		var draggableIframeObjects = _that.course.opts.singleFile ? _that.L.scr.find('div[actionkey="'+ ob.question.draggableObjs[o] +'"]') : _that.L.iframe[0].contentWindow.$('div[actionkey="'+ ob.question.draggableObjs[o] +'"]');

		draggableIframeObjects.css({cursor: 'pointer'});


		var pointerX;
		var pointerY;
		draggableIframeObjects.draggable({

			scope: ob.id,
			disabled: false,

			revert: function(droppableObj) {
				_that.quiz_dndHandleAction('revert', ob, screenOb, {droppableObj:droppableObj,draggedObject:$(this)});
			},

			drag: function(evt, ui) {

				// zoom fix
				if (scaleFactor != 1) { 
					var contain = _that.L.scr.find('#divimg');
					var canvasTop = contain.offset().top;
				    var canvasLeft = contain.offset().left;
				    var canvasHeight = contain.height();
				    var canvasWidth = contain.width();

				    // Fix for zoom
				    ui.position.top = Math.round((evt.pageY - canvasTop) / scaleFactor - pointerY); 
				    ui.position.left = Math.round((evt.pageX - canvasLeft) / scaleFactor - pointerX); 

				    // Check if element is outside canvas
				    if (ui.position.left < 0) ui.position.left = 0;
				    if (ui.position.left + $(this).width() > canvasWidth) ui.position.left = canvasWidth - $(this).width();  
				    if (ui.position.top < 0) ui.position.top = 0;
				    if (ui.position.top + $(this).height() > canvasHeight) ui.position.top = canvasHeight - $(this).height();  

				    // Finally, make sure offset aligns with position
				    ui.offset.top = Math.round(ui.position.top + canvasTop);
				    ui.offset.left = Math.round(ui.position.left + canvasLeft);
				}
				_that.quiz_dndHandleAction('drag', ob, screenOb, {evt:evt,ui:ui,draggedObject:$(this)});
			},

			start: function(evt, ui) {
				// zoom fix
				pointerY = (evt.pageY - _that.L.scr.find('#divimg').offset().top) / scaleFactor - parseInt($(evt.target).css('top'));
    			pointerX = (evt.pageX - _that.L.scr.find('#divimg').offset().left) / scaleFactor - parseInt($(evt.target).css('left'));

				_that.quiz_dndHandleAction('start', ob, screenOb, {draggedObject:$(this)});
			},

			stop: function() {
				_that.quiz_dndHandleAction('stop', ob, screenOb, {draggedObject:$(this)});
			}
		});
	}

	for ( var dropObj in ob.question.answers ) {

		ob.question.answers[dropObj].userSelection = [];

		var droppableIframeObjects = _that.course.opts.singleFile ? _that.L.scr.find('div[actionkey="'+ dropObj +'"]') : _that.L.iframe[0].contentWindow.$('div[actionkey="'+ dropObj +'"]');

		droppableIframeObjects.css({
			opacity: 1
		});

		if (typeof droppableIframeObjects.attr('aria-label-org') === "string") {
			droppableIframeObjects.attr('aria-label', droppableIframeObjects.attr('aria-label-org'));
		}

		droppableIframeObjects.droppable({

			tolerance: "pointer",
			scope: ob.id,

			// hoverClass: "div-point",

			drop: function(evt, droppableObject) {
				_that.quiz_dndHandleAction('drop', ob, screenOb, {evt:evt, droppableObject:droppableObject,thisObject:$(this)});
			}

		});
	}
};

CourseManager.prototype.quiz_dndHandleAction = function(action, ob, screenOb, data) {
	var _that = this;

	switch(action) {

		case 'revert':
			if (data.droppableObj === false && ob.question.opts.revertObjects === true) {
				var droppedOb = _that.getObjectByID(data.draggedObject.attr('actionkey'));
				data.draggedObject.animate({
					left: droppedOb.startPos.leftStartPos + "px",
					top: droppedOb.startPos.topStartPos + "px"
				}, 500);
			}
			break;
		
		case 'drag':
			// debug.log('drag');
   //          if (scaleFactor !== 1) {
   //              var canvasTop = _that.L.scr.offset().top;
   //              var canvasLeft = _that.L.scr.offset().left;
   //              var canvasHeight = _that.L.scr.height();
   //              var canvasWidth = _that.L.scr.width();
   //              data.ui.position.top = Math.round((data.evt.pageY - canvasTop) / scaleFactor - _that.course.opts.pointerY); 
   //              data.ui.position.left = Math.round((data.evt.pageX - canvasLeft) / scaleFactor - _that.course.opts.pointerX);

   //              data.ui.offset.top = Math.round(data.ui.position.top + canvasTop);
   //              data.ui.offset.left = Math.round(data.ui.position.left + canvasLeft);
   //          }
			break;
		
		case 'start':


			data.draggedObject.css('z-index', screenOb.css('z-index'));

			data.draggedObject.attr('aria-grabbed', 'true');

			// if (typeof data.evt === "object") {
			// 	_that.course.opts.pointerY = (data.evt.pageY - _that.L.scr.offset().top) / scaleFactor - parseInt($(data.evt.target).css('top'));
   //          	_that.course.opts.pointerX = (data.evt.pageX - _that.L.scr.offset().left) / scaleFactor - parseInt($(data.evt.target).css('left'));
			// }

			var draggedObjectID = data.draggedObject.attr('actionkey');

			for (var ans in ob.question.answers) {
				var indexOfObject = ob.question.answers[ans].userSelection.indexOf(draggedObjectID);
				var containerObject = _that.getScreenObjectByActionkey(ans);
				if (indexOfObject !== -1) {
					ob.question.answers[ans].userSelection.splice(indexOfObject, 1);
					_that.quiz_dndRefreshContainers(ob, containerObject);
				}
			}

			break;
		
		case 'stop':
			data.draggedObject.attr('aria-grabbed', 'false');
			break;
		
		case 'drop':
			var droppedObject;
			if (typeof data.droppableObject.draggable === "object") {
				droppedObject = $(data.droppableObject.draggable[0]);
				// debug.log("Normalne upuszczenie " + typeof data.droppableObject.draggable);
				// debug.log(data.droppableObject.draggable);
			} else {
				// debug.log("Keyboard upuszczenie");
				droppedObject = $(data.droppableObject);
			}

			// debug.log(droppedObject);
			
			var success = false;
			var reverted = false;

			// draggable and droppable ID
			var droppedID = droppedObject.attr('actionkey');
			var droppedObjectOb = _that.getObjectByID(droppedID);
			var droppableID = data.thisObject.attr('actionkey');

			// [onlygoodanswers] - if it's not a good answer - revert object
			if (ob.question.answers[droppableID].opts.onlygoodanswers === true) {
				if (!(_that.quiz_dndIsGoodAnswer(ob, droppableID, droppedID))) {
					droppedObject.animate({
						left: droppedObjectOb.startPos.leftStartPos + "px",
						top: droppedObjectOb.startPos.topStartPos + "px"
					}, 500);
					success = false;
					reverted = true;
				}
			}

			if (!reverted) {
				// check for max answers
				var maxAnswers = ob.question.answers[droppableID].opts.maxAnswers;
				if (typeof maxAnswers === "number") {
					if (maxAnswers > ob.question.answers[droppableID].userSelection.length || maxAnswers <= 0) {
						ob.question.answers[droppableID].userSelection.push(droppedID);
						success = true;
					} else {
						droppedObject.animate({
							left: droppedObjectOb.startPos.leftStartPos + "px",
							top: droppedObjectOb.startPos.topStartPos + "px"
						}, 500);	
						success = false;
					}
				} else {
					// push object id to user selection when dropped
					ob.question.answers[droppableID].userSelection.push(droppedID);
					success = true;
				}
			}



			if (success && ob.question.opts.disableOnGoodDrop && ob.question.answers[droppableID].opts.onlygoodanswers) {
				droppedObject.draggable("disable");
				var containerLabel = data.thisObject.attr('aria-label');
				var objectLabel = droppedObject.attr('aria-label');
				data.thisObject.attr('aria-label-org', containerLabel);
				data.thisObject.attr('aria-label', "Upuszczono prawidłowo, " + containerLabel + ", " + objectLabel);
				data.thisObject.focus();

				if (typeof droppedObject.attr('tabindex') !== "undefined") {
					droppedObject.attr('tabindexorg', droppedObject.attr('tabindex'));
					droppedObject.removeAttr('tabindex');
				}
			}

			if (data.keyboard === true && _that.course.opts.euroforum === true) {
				if (success) {
					try {
						_that.dndSounds.elemDroppedSound[0].play();
					} catch(msg) {
						debug.log(msg);
					}
				} else {
					try {
						_that.dndSounds.elemBadAnswer[0].play();
					} catch(msg) {
						debug.log(msg);
					}
				}
			}

			_that.quiz_dndRefreshContainers(ob, data.thisObject);

			break;

	}
};

CourseManager.prototype.quiz_dndRefreshContainers = function(dndObject, containerScreenObject) {
	var _that = this;

	var screenOb = _that.getScreenObjectByActionkey(dndObject.id);

	var position = {
		leftPos : parseInt(containerScreenObject.css('left')),
		topPos  : parseInt(containerScreenObject.css('top'))
	}

	var containerID = containerScreenObject.attr('actionkey');

	var previousElem;

	var highestElemValue = 0;

	for (var i = 0; i < dndObject.question.answers[containerID].userSelection.length; i++) {
		var answerID = dndObject.question.answers[containerID].userSelection[i];

		var answerObject = _that.getScreenObjectByActionkey(answerID);

		if (dndObject.question.answers[containerID].opts.dropandhide === true) {

			if (!answerObject.hasClass('bounceOut')) {
				answerObject.addClass('animated');
				answerObject.addClass('bounceOut');

				answerObject.attr( 'tabindex-b', answerObject.attr('tabindex') );
				answerObject.removeAttr( 'tabindex');


				var answerObjectTimeout = setTimeout(function() {
										answerObject.removeClass('bounceOut');
										answerObject.removeClass('animated');
										answerObject.hide();
									}, 1300);

				(function(answerObject) {
					setTimeout(function() {
						answerObject.attr( 'tabindex', answerObject.attr('tabindex-b') );
					}, 1300);
				})(answerObject);

				_that.tempopts.dndtimeouts.push(answerObjectTimeout);
			}

		} else {
			answerObject.css('z-index', screenOb.css('z-index') );
			if (dndObject.question.answers[containerID].opts.autoArrangeAnswers || typeof dndObject.question.answers[containerID].opts.autoArrangeAnswers === 'undefined') {
				if (typeof previousElem !== "undefined") {
					if (highestElemValue < previousElem.height()) {
						highestElemValue = previousElem.height();
					}


					if ( (position.leftPos + previousElem.width() + answerObject.width() ) > (parseInt(containerScreenObject.css('left')) + containerScreenObject.width() ) ) {
						position.leftPos = parseInt(containerScreenObject.css('left'));
						position.topPos += highestElemValue;
					} else {
						position.leftPos += previousElem.width();
					}
				}

				if (position.topPos >= (containerScreenObject.height() + parseInt(containerScreenObject.css('top'))) ){
					position.topPos = parseInt(containerScreenObject.css('top'));
				}
				answerObject.animate({
					left: position.leftPos + "px",
					top: position.topPos + "px"
				}, 500);
			}
		}

		previousElem = answerObject;

	};

	debug.log('refreshing containers...');
	debug.log(dndObject.question);
};

CourseManager.prototype.quiz_dndIsGoodAnswer = function(ob, containerID, droppedID) {
	debug.log(ob);
	debug.log('checking: ' + containerID + ", ob: " + droppedID);
	if (ob.question.answers[containerID].pa.indexOf(droppedID) !== -1) {
		debug.log("GOOD");
		return true;
	}
	debug.log("BAD...");
	return false;
};

CourseManager.prototype.quiz_dndCheckAnswers = function(ob, screenOb) {
	var _that = this;

	var containersStatus = { };

	var allUserAnswers = { };

	var badAnswers = { };

	var atLeastOneAnswerHasBennDrawed = false;

	for (var container in ob.question.answers) {

		containersStatus[container] = true;

		var userAnswers = ob.question.answers[container].userSelection;
		var goodAnswers = ob.question.answers[container].pa;

		allUserAnswers[container] = [ ];
		for (var ua = userAnswers.length - 1; ua >= 0; ua--) {
			allUserAnswers[container].push(userAnswers[ua]);
		};

		badAnswers[container] = [ ];

		// if (userAnswers.length === goodAnswers.length) {
			for (var a = userAnswers.length - 1; a >= 0; a--) {
				if ( goodAnswers.indexOf(userAnswers[a]) === -1 ) {
					containersStatus[container] = false;
					badAnswers[container].push(userAnswers[a]);
				} else {

					if (ob.question.answers[container].opts.forceGoodSequence) {
						debug.log('Sprawdzam kolejność!');
						if (a !== goodAnswers.indexOf(userAnswers[a])) {
							debug.log('Nie na swoim miejscu!');
							containersStatus[container] = false;
							badAnswers[container].push(userAnswers[a]);
						}
					}

				}
				atLeastOneAnswerHasBennDrawed = true;
			};
		// } else {
		// 	containersStatus[container] = false;
		// }
		// jesli nie zgadza sie ilosc dobrych odpowiedzi z usera odpowiedziami
		if (userAnswers.length !== goodAnswers.length) {
			containersStatus[container] = false;
		}

		// if (ob.question.answers[container].opts.forceGoodSequence) {
		// 	alert('forcing good sequence');
		// }

		// jesli ilosc sie nie zgadza, ale jest ustawione enoughAnswers 
		if (parseInt(ob.question.answers[container].opts.enoughAnswers) !== 0) {
			if ((allUserAnswers[container].length - badAnswers[container].length) >= ob.question.answers[container].opts.enoughAnswers) {
				containersStatus[container] = true;
			}
		}

	}

	var answersStatus = {
		questionIsPassed: true
	};

	for (var stat in containersStatus) {
		if (!containersStatus[stat]) {
			answersStatus.questionIsPassed = false;
		}
	}



	if (answersStatus.questionIsPassed) {
		// _that.quiz_dndMarkQuestionAsPassed(ob, screenOb);
	} else {

		for (var container in ob.question.answers) {
			// if revertType is not none...
			// debug.log(ob.question.answers[container]);
			if (ob.question.answers[container].opts.revertType.revertNone === false) {

				// Revert only bad answers
				if (ob.question.answers[container].opts.revertType.revertOnlyBad === true) {
					for (var ba = badAnswers[container].length - 1; ba >= 0; ba--) {

							var badAnswerID = badAnswers[container][ba];
							var indexOfBadAnswer = ob.question.answers[container].userSelection.indexOf(badAnswerID);

							ob.question.answers[container].userSelection.splice(indexOfBadAnswer, 1);

							var screenObject = _that.getScreenObjectByActionkey(badAnswerID);
							var courseObject = _that.getObjectByID(badAnswerID);

							debug.log("_that.tempopts.dndtimeouts.length: " + _that.tempopts.dndtimeouts.length);

							for (var i = _that.tempopts.dndtimeouts.length - 1; i >= 0; i--) {
								clearTimeout(_that.tempopts.dndtimeouts[i]);
							};

							screenObject.removeClass('bounceOut');
							screenObject.removeClass('animated');

							if (typeof screenObject.attr('tabindex-b') !== "undefined") {
								screenObject.attr( 'tabindex', screenObject.attr('tabindex-b') );
							}

							screenObject.show();

							screenObject.animate({
									left: courseObject.startPos.leftStartPos + "px",
									top: courseObject.startPos.topStartPos + "px"
							}, 500);

					};
				}

				// Revert all user answers from container
				if (ob.question.answers[container].opts.revertType.revertAll === true) {
					for (var aua = allUserAnswers[container].length - 1; aua >= 0; aua--) {
						var screenObject = _that.getScreenObjectByActionkey(allUserAnswers[container][aua]);
						var courseObject = _that.getObjectByID(allUserAnswers[container][aua]);

						debug.log("_that.tempopts.dndtimeouts.length: " + _that.tempopts.dndtimeouts.length);

						for (var i = _that.tempopts.dndtimeouts.length - 1; i >= 0; i--) {
							clearTimeout(_that.tempopts.dndtimeouts[i]);
						};

						screenObject.removeClass('bounceOut');
						screenObject.removeClass('animated');

						if (typeof screenObject.attr('tabindex-b') !== "undefined") {
							screenObject.attr( 'tabindex', screenObject.attr('tabindex-b') );
						}

						screenObject.show();

						screenObject.animate({
							left: courseObject.startPos.leftStartPos + "px",
							top: courseObject.startPos.topStartPos + "px"
						}, 500);

						screenObject.draggable("enable");
					};


					ob.question.answers[container].userSelection = [ ];
				}
			}
		}
	}
	

	if (atLeastOneAnswerHasBennDrawed) {
		_that.quiz_ShowFeedback(ob, screenOb, answersStatus);
	} else {
		_that.quiz_selectAtLeastOneAnswerInfo(lang[language]['ANSWER_QUESTIONS_DND_FIRST'], 'red');
	}
    
};

CourseManager.prototype.quiz_dndMarkQuestionAsPassed = function(ob, screenOb) {
	var _that = this;

	screenOb.css({opacity: '.4'});
	screenOb.off("click");

	for (var i = ob.question.draggableObjs.length - 1; i >= 0; i--) {

		if (_that.course.opts.singleFile) {
			_that.L.scr
				.find('div[actionkey="'+ ob.question.draggableObjs[i] +'"]')
				.draggable({ disabled: true })
				.css({opacity: '.7'});
		} else {
			_that.L.iframe[0].contentWindow
				.$('div[actionkey="'+ ob.question.draggableObjs[i] +'"]')
				.draggable({ disabled: true })
				.css({opacity: '.7'});
		}
	};
};

CourseManager.prototype.quiz_dndMarkQuestionAsFailed = function(ob, screenOb) {
	var _that = this;

	screenOb.css({opacity: '.4'});
	screenOb.off("click");

	for (var i = ob.question.draggableObjs.length - 1; i >= 0; i--) {

		if (_that.course.opts.singleFile) {
			_that.L.scr
				.find('div[actionkey="'+ ob.question.draggableObjs[i] +'"]')
				.draggable({ disabled: true })
				.css({opacity: '.7'});
		} else {
			_that.L.iframe[0].contentWindow
				.$('div[actionkey="'+ ob.question.draggableObjs[i] +'"]')
				.draggable({ disabled: true })
				.css({opacity: '.7'});
		}
	};
};

CourseManager.prototype.quiz_memoryPrepareObjects = function(ob, screenOb) {
	var _that = this;

	debug.log('quiz_memoryPrepareObjects');

	ob.question.userSelection = [ ];

	ob.question.ga = 0;

	var singleObjectWidth = ob.question.opts.elementsWidth + 'px';
	var singleObjectHeight = ob.question.opts.elementsHeight + 'px';

	_that.L.scr.find('#divimg > .memory-overlay-object').remove();

	ob.question.overlayObject = $('<div class="memory-overlay-object"></div>');
	ob.question.overlayObject.css({
		visibility: 'hidden',
		position: 'absolute',
		width: screenOb.css('width'),
		height: screenOb.css('height'),
		left: screenOb.css('left'),
		top: screenOb.css('top'),
		'z-index': '99999'
	});

	_that.L.scr.find('#divimg').append(ob.question.overlayObject);

	// hide memory element on screen
	screenOb[0].style.setProperty('display', 'none', 'important');

	var elementsArray = [ ];
	var tempElementsArray = [ ];

	var overlayPath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/gallery/' + ob.id + '/' + ob.question.overlay;

	if (Utils.ObjectLength(ob.question.files) === 0) {
		alert(lang[language]['MEMORY_ERROR_NOELEMENTS']);
		return;
	}
	if (ob.question.overlay.length === 0) {
		alert(lang[language]['MEMORY_ERROR_NOOVERLAY']);
		return;
	}

	var itemIsPaired = function(itemname) {
	    var _that = this;
	    if ( isObject(ob.question.pairs) ) {
	        for (var p = ob.question.pairs.length - 1; p >= 0; p--) {
	            var pair = ob.question.pairs[p];

	            if (pair.indexOf(itemname) !== -1) {
	                return true;
	            }
	        }
	    }
	    return false;
	};


	var getPairID = function(itemname) {
	    var _that = this;
	    if ( isObject(ob.question.pairs) ) {
	        for (var p = ob.question.pairs.length - 1; p >= 0; p--) {
	            var pair = ob.question.pairs[p];

	            if (pair.indexOf(itemname) !== -1) {
	            	if (pair.indexOf(itemname) === 0) {
	            		return p+"p";
	            	}
	            	if (pair.indexOf(itemname) === 1) {
	            		return p+"pb";
	            	}
	            }
	        }
	    }
	    return -1;
	};


	var iterator = 0;
	// prepare all memory graphic items
	for (var file in ob.question.files) {


		
		debug.log(file + " != " + ob.question.overlay)
		if (file != ob.question.overlay) {
			var filename = file;
			var filePath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/gallery/' + ob.id + '/' + filename;

			var soundPath = "none";
			if (ob.question.files[file].sound.length > 0) {
				soundPath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/gallery/' + ob.id + '/sounds/' + ob.question.files[file].sound;
			}
			var badSoundPath = "none";
			if (ob.question.files[file].sound.length > 0) {
				badSoundPath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/gallery/' + ob.id + '/sounds/' + ob.question.files[ob.question.overlay].sound;
			}
			

			
			var memoryItemContainer = $('<div>', {
				class: 'memory-item animated flipInY',
				itemid: (iterator < 10) ? '0'+iterator : iterator
			}).css({
				width: singleObjectWidth,
				height: singleObjectHeight,
				position: 'absolute',
				'z-index': screenOb.css('z-index')
			});

			var memoryItemInside = $('<div>', {
				class: 'memory-item-inside',
				realimage: filePath,
				overlayimage: overlayPath,
				soundfile: soundPath,
				badSoundPath: badSoundPath
			}).css({
				width: '100%',
				height: '100%',
				'background-image': 'url('+overlayPath+')',
				'background-size': 'contain',
				'background-repeat': 'no-repeat',
				'background-position': '50% 50%'
			});

			memoryItemContainer.append(memoryItemInside);

			elementsArray.push(memoryItemContainer);

			tempElementsArray.push(memoryItemContainer);

			

			if (itemIsPaired(file)) {
				var pairID = getPairID(file);
				memoryItemContainer.attr({
					'itemid': (parseInt(pairID) < 10) ? '0'+pairID : pairID
				});

				if (isString(pairID) && pairID.slice(-2) == "pb") {
					iterator++;
				}
				continue;
			}

			iterator++;

			var clonedELement = memoryItemContainer.clone();
			clonedELement.attr('itemid', clonedELement.attr('itemid') + "a");
			elementsArray.push(clonedELement);
			tempElementsArray.push(clonedELement);

		}
	};

	ob.question.allAnswersNumber = iterator;


	var stopAndDisableMemory = function(memoryItems) {


		for (var i = memoryItems.length - 1; i >= 0; i--) {
			var memoryItem = memoryItems[i];

			memoryItem.find('.memory-item-inside').css({
				opacity: '.4'
			});

			var memoryScreenItem = _that.L.scr.find('div[itemid="'+memoryItem.attr('itemid') + '"]');
				memoryScreenItem.off("click");
		};
		triggerEvent(screenOb[0], 'custom_questionfailed');
	}

	if (typeof ob.question.opts.gameLivetime !== "undefined" && ob.question.opts.gameLivetime !== 0 ) {
		ob.question.looseTO = setTimeout(function() {
			debug.log("stop!!!!!!!!!!!!!1");
			stopAndDisableMemory(tempElementsArray);
		}, parseFloat(ob.question.opts.gameLivetime) * 1000);
	}

	_that.quiz_memoryDistributeElementsOnScreen(ob, screenOb, elementsArray);
};

CourseManager.prototype.quiz_memoryDistributeElementsOnScreen = function(ob, mainScreenOb, elements) {
	var _that = this;

	debug.log('quiz_memoryDistributeElementsOnScreen');

	try {

		var mainElementPositionAndSize = {
			_width: parseInt(mainScreenOb.css('width')),
			_height: parseInt(mainScreenOb.css('height')),

			_top: parseInt(mainScreenOb.css('top')),
			_left: parseInt(mainScreenOb.css('left'))
		};

		var singleElementSize = {
			_width: elements[0].width(),
			_height: elements[0].height()
		};

		// debug.log("main");
		// debug.log(mainElementPositionAndSize);

		// debug.log("singleElementSize");
		// debug.log(singleElementSize);


		var numberOfAllElements = elements.length;

		var numberOfElementsInSingleRow = parseInt(mainElementPositionAndSize._width / singleElementSize._width );

		if (numberOfElementsInSingleRow === 0) {
			numberOfElementsInSingleRow = 1;
		}

		var numberOfRows = Math.ceil(numberOfAllElements / numberOfElementsInSingleRow);

		var spaceLeftInMainContainerX = mainElementPositionAndSize._width - (numberOfElementsInSingleRow*singleElementSize._width);
		var spaceLeftInMainContainerY = mainElementPositionAndSize._height - (numberOfRows*singleElementSize._height);

		var blankSpaceForDistributionX = spaceLeftInMainContainerX/numberOfElementsInSingleRow;
		var blankSpaceForDistributionY = spaceLeftInMainContainerY/numberOfRows;


		var listOfX = [ ];

		// prepare list of X positions
		for (var i = 0; i < numberOfElementsInSingleRow; i++) {
			var positionX = mainElementPositionAndSize._left + ((i*singleElementSize._width) + (i*blankSpaceForDistributionX));
			listOfX.push(positionX);
		};

		// distribute elements on screen
		for (var i = 0; i < numberOfRows; i++) {

			var _elementY = mainElementPositionAndSize._top + (i*singleElementSize._height)  + (i*blankSpaceForDistributionY);

			for (var j = 0; j < numberOfElementsInSingleRow; j++) {
				var element = elements[Math.floor(Math.random()*elements.length)];

				if (typeof element === "object") {
					element.css({
						left: listOfX[j],
						top: _elementY
					});

					_that.L.scr.find('> #divimg').append(element);
					_that.quiz_memoryPrepareSingleObject(ob, mainScreenOb, element);
					elements.splice(elements.indexOf(element), 1);
				}
			};
		}	

	} catch(msg) {
		debug.log(msg);
	}
};

CourseManager.prototype.quiz_memoryPrepareSingleObject = function(ob, screenOb, element) {
	var _that = this;

	debug.log('quiz_memoryPrepareSingleObject');

	element.click(function() {
		_that.quiz_memorySingleObjectOnClick(ob, screenOb, $(this));
	});
};

CourseManager.prototype.quiz_memorySingleObjectOnClick = function(ob, screenOb, clickedElement) {
	var _that = this;

	var clickedElementID = clickedElement.attr('itemid');

	if (ob.question.userSelection.length <= 1) {
		if (ob.question.userSelection.indexOf(clickedElementID) === -1) {
			ob.question.userSelection.push(clickedElementID);
			clickedElement.find('.memory-item-inside').css('background-image', 'url('+ clickedElement.find('.memory-item-inside').attr('realimage') + ')');		
		}
	}

	if (ob.question.userSelection.length === 2) {
		ob.question.overlayObject.css('visibility', 'visible');
		if (_that.quiz_memoryIsGoodAnswer(ob.question.userSelection)) {
			// good answer!
			debug.log('Good answer!');

			// play sound!
			if (clickedElement.find('.memory-item-inside').attr('soundfile') != "none") {
				_that.playHtmlSound(clickedElement.find('.memory-item-inside').attr('soundfile'));
			}

			for (var i = ob.question.userSelection.length - 1; i >= 0; i--) {
				var selectedElement = _that.L.scr.find('div[itemid="'+ob.question.userSelection[i] + '"]');
				selectedElement.off("click");

				if (ob.question.opts.hideGoodAnswers === true) {
					(function(selectedElement) {
						setTimeout(function() {
							selectedElement.addClass('flipOutY');
						}, 1000);
					})(selectedElement);

				}
			};	
			ob.question.overlayObject.css('visibility', 'hidden');
			ob.question.userSelection = [ ];


			
			ob.question.ga++;

			// WIN!
			if (ob.question.ga === ob.question.allAnswersNumber) {
				clearTimeout(ob.question.looseTO);
				triggerEvent(screenOb[0], 'custom_questionpassed');
			} 
		} else {
			var elementsLiveTime = parseFloat(ob.question.opts.elementsLivetime) * 1000;
			debug.log(ob.question.opts.elementsLivetime);
			debug.log(ob);
			// bad answer!

			// play sound!
			if (clickedElement.find('.memory-item-inside').attr('soundfile') != "none") {
				_that.playHtmlSound(clickedElement.find('.memory-item-inside').attr('badSoundPath'));
			}

			setTimeout(function() {
				if (ob.question.userSelection.length === 2) {
					for (var i = ob.question.userSelection.length - 1; i >= 0; i--) {
						var selectedElement = _that.L.scr.find('div[itemid="'+ob.question.userSelection[i] + '"]');
						selectedElement.css('display', 'none');
						selectedElement.find('.memory-item-inside').css('background-image', 'url('+selectedElement.find('.memory-item-inside').attr('overlayimage') +')');
						(function(_selectedElement){ 
							setTimeout(function(){
								_selectedElement.css('display', 'block');
							},1);
						})(selectedElement);
						
					};
					ob.question.overlayObject.css('visibility', 'hidden');
					ob.question.userSelection = [ ];
				}
			}, elementsLiveTime);
		}
	}
};

/* CROSSWORD */
CourseManager.prototype.quiz_prepareCrossword = function(ob, screenOb) {
	var _that = this;

	debug.log('przygotowuje crossword');

	screenOb.find('.crossword-hidden-button').remove();

	var hiddenButton = $('<div class="crossword-cm-hidden-button"></div>');

	screenOb.append(hiddenButton);

	screenOb.find('.crossword-cm-hidden-button').hide();

	// wzdłóż której lonii focus ma się poruszać, 
	//null wyszukuje oba położenia, 0 dla x, 1 dla y, 2 przestaje wyszukiwać, 
	//po klinieciu w celkę along ustawia się ponownie na null
	var along = null;

	screenOb.find('.crossword-cell-background').css({
		'float': 'left'
	});

	var allCells = screenOb.find('.crossword-cell[celltype=answer]').val("");

	
	//screenOb.find('.crossword-cell-background>textarea').prop('disabled', true);

	allQuestionCells = screenOb.find('.crossword-cell[celltype="question"]').each(function(){
		$(this).attr('title', $(this).val());

		// if (!_that.isMobile) {
			$(this).tooltip({
				tooltipClass: 'crossword-tooltip',
				items: "img, [data-geo], [title]",
				position:{within: '#skin',collision: "flipfit" },
				content: function() {
					var cellid = $(this).attr('cellid');
					var questionType = isObject(ob.question.ob[cellid]) ? ob.question.ob[cellid].type : 'text';

					switch(questionType) {
						case 'text':
							var content = $('<div>', {style: 'text-align:left' });
							return content.html($(this).val().replace(/\n/g,"<br/>"));
							break;

						case 'image':
							var filePath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/images/' + ob.id + '/' + ob.question.ob[cellId].file;
							setTimeout(function() {
							}, 1000);
							
							return "<img class='crossword-tooltip-image' src='"+ filePath +"'>";
							break;

						case 'audio':
							return lang[language]['CROSSWORD_PLAY_AUDIO'];
							break;
					}
				},
	            close: function (event, ui) {
	                    ui.tooltip.hover(

	                    function () {
	                            $(this).stop(true).fadeTo(400, 1);
	                    },

	                    function () {
	                            $(this).fadeOut("400", function () {
	                                    $(this).remove();
	                            })
	                    });
	            }				
			});
		// }

		

		var cellId = $(this).attr('cellid');

		if(isObject(ob.question.ob)){

			if(isObject(ob.question.ob[cellId])){

				var filePath = _that.course.opts.exportedFolderName + "/" + _that.course.opts.active.pageID + '/images/' + ob.id + '/' + ob.question.ob[cellId].file;
				switch(ob.question.ob[cellId].type){
					case 'text':

					break;

					case 'image':
						
						$(this).css('background-image', 'none' );
						$(this).css('background-image', 'url(' + filePath + ')' );
					// alert(backgroundImage);
					break;

					case 'audio':
						$(this).click(function(){
							_that.playHtmlSound( filePath );
						});
					break;
				}
				
			}

		}
		
	});

	allQuestionCells.attr('readonly', 'true');



	var prepareAnswers = function( ){

		var divisionCrossword = {
			answers: {},
			questions: {},
			answersStatus : {}
		};
		var allCells = screenOb.find('.crossword-cell');
		var questionsCells = screenOb.find('.crossword-cell[celltype="question"]');

		allCells.css('float', 'left');

		

		for (var j = 0; j <= questionsCells.length; j++) {
			var questionCell = $(questionsCells[j]);

			debug.log("questionGender");
			debug.log(questionCell);

			var questionCellId = questionCell.attr('cellid');
			var questionCellX = parseInt( questionCell.attr('cellx') );
			var questionCellY = parseInt( questionCell.attr('celly') );
			var questionGender = questionCell.attr('arrow-id');

			var answersCell =  screenOb.find('.crossword-cell[celltype=answer]');

			switch(questionGender){
				case '1':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						var cellId = cell.attr('cellid');
						var cellX = parseInt( cell.attr('cellx') );
						var cellY = parseInt( cell.attr('celly') );
						var genderCell = cell.attr('celltype');
						var cellValue = ob.question.objs[cell.attr('cellid')] || "";;

						if(cellX != questionCellX || cellY <= questionCellY){
							continue;
						}

						if(genderCell == "question" || cellValue == ""){
							break;
						}

						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;	
				break;

				case '2':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						
						var cellX = parseInt( cell.attr('cellx') )  + 1;
						var cellY = parseInt( cell.attr('celly') );
						
						

						debug.log("questionCellY " + questionCellY);
						debug.log("cellY " + cellY);

						if(cellX != questionCellX + 1 || cellY < questionCellY){

							debug.log("continue ");
							continue;
						}

						var finedCell =  screenOb.find('.crossword-cell[cellx="' + cellX + '"][celly="' + cellY + '"]');
						var cellId = finedCell.attr('cellid');
						var genderCell = finedCell.attr('celltype');
						var cellValue = ob.question.objs[finedCell.attr('cellid')] || "";;

						debug.log("genderCell " + genderCell);
						debug.log("cellValue " + cellValue);

						if(genderCell == "question" || cellValue == ""){

							break;
						}

						debug.log("cellX " + cellX);
						debug.log("cellY " + cellY);


						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;	
				break;

				case '3':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						
						var cellX = parseInt( cell.attr('cellx') )  - 1;
						var cellY = parseInt( cell.attr('celly') );
						
						

						debug.log("questionCellY " + questionCellY);
						debug.log("cellY " + cellY);

						if(cellX != questionCellX - 1 || cellY < questionCellY){

							debug.log("continue ");
							continue;
						}

						var finedCell =  screenOb.find('.crossword-cell[cellx="' + cellX + '"][celly="' + cellY + '"]');
						var cellId = finedCell.attr('cellid');
						var genderCell = finedCell.attr('celltype');
						var cellValue = ob.question.objs[finedCell.attr('cellid')] || "";;

						debug.log("genderCell " + genderCell);
						debug.log("cellValue " + cellValue);

						if(genderCell == "question" || cellValue == ""){

							break;
						}

						debug.log("cellX " + cellX);
						debug.log("cellY " + cellY);


						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;	
				break;

				case '4':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						var cellId = cell.attr('cellid');
						var cellX = parseInt( cell.attr('cellx') );
						var cellY = parseInt( cell.attr('celly') );
						var genderCell = cell.attr('celltype');
						var cellValue = ob.question.objs[cell.attr('cellid')] || "";;

						if(cellY != questionCellY || cellX <= questionCellX){
							continue;
						}

						if(genderCell == "question" || cellValue == ""){
							
							break;
						}

						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;
				break;

				case '5':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						
						var cellX = parseInt( cell.attr('cellx') );
						var cellY = parseInt( cell.attr('celly') ) + 1;
						

						if(cellY != questionCellY + 1 || cellX < questionCellX){
							continue;
						}

						var finedCell =  screenOb.find('.crossword-cell[cellx="' + cellX + '"][celly="' + cellY + '"]');
						var cellId = finedCell.attr('cellid');
						var genderCell = finedCell.attr('celltype');
						var cellValue = ob.question.objs[finedCell.attr('cellid')] || "";;

						if(genderCell == "question" || cellValue == ""){
							
							break;
						}

						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;
				break;

				case '6':
					for (var i = 0; i < allCells.length; i++) {
						var cell = $(allCells[i]);

						
						var cellX = parseInt( cell.attr('cellx') );
						var cellY = parseInt( cell.attr('celly') ) - 1;
						

						if(cellY != questionCellY - 1 || cellX < questionCellX){
							continue;
						}

						var finedCell =  screenOb.find('.crossword-cell[cellx="' + cellX + '"][celly="' + cellY + '"]');
						var cellId = finedCell.attr('cellid');
						var genderCell = finedCell.attr('celltype');
						var cellValue = ob.question.objs[finedCell.attr('cellid')] || "";;

						if(genderCell == "question" || cellValue == ""){
							
							break;
						}

						if(isUndefined( divisionCrossword.answers[questionCellId] )){
							divisionCrossword.answers[questionCellId] = [];
						}

						divisionCrossword.answers[questionCellId].push( cellId );
					};

					divisionCrossword.answersStatus[questionCellId] = false;
				break;

			}

		};


		
		return divisionCrossword;
	}

	ob.divisionCrosswordAnswers = prepareAnswers();
	debug.log(ob.divisionCrosswordAnswers.answers);
	if ( Utils.ObjectLength(ob.divisionCrosswordAnswers.answers) === 0 ) {
		_that.showWarningPopup(lang[language]['CROSSWORD_ERROR']);
	}


	var hideEmptyAnswerCell = function( ){

		var answersCells = screenOb.find('.crossword-cell[celltype=answer]');

		for (var i = 0; i < answersCells.length; i++) {
			var cell = $(answersCells[i]);
			var answerValue = ob.question.objs[cell.attr('cellid')];
			if( answerValue == "" || answerValue == null){
				
				cell.parent().css("visibility", "hidden");
				cell.attr("enabled", "false");
			} else {
				cell.attr("enabled", "true");
			}
		};
	}

	hideEmptyAnswerCell();


	var onCellKeyUp = function( cell ){

		var value = cell.val();
		var cellId = cell.attr('cellid');

		if(ob.question.opts == undefined) ob.question.opts = {};
		ob.question.opts[cellId] = value; 

		//colorizeGoodAnswer( cell );
		
		//checkOneWord();


		
		var next = findNextCell(cell, along);

		if(next != null){

			var nextCell = next.nextCell;

			if(nextCell != null){
				along = next.along;

				if (isObject(nextCell)) {
					nextCell.focus();
					nextCell[0].select();	
				}
			}
		}
		

		chechCrossworAnswers();

		return checkOneWord();

	}

	var focusCellByGender = function( cell ){

		findClosersCell( cell );
	}

	var focusCellByAnswer = function( cell ){

		var closerCells = findClosersCell( cell );


		for (var cellPosition in closerCells) {

			if (closerCells[cellPosition] !== null) {
				switch (cellPosition) {
					case 'bottom':
						if (closerCells[cellPosition].parent().attr('gender') == '6') {
							along = 0;
						}
						break;
					case 'right':
						if (closerCells[cellPosition].parent().attr('gender') == '3') {
							along = 1;
						}
						break;
					case 'top':
						if (closerCells[cellPosition].parent().attr('gender') == '1') {
							along = 1;
						}
						if (closerCells[cellPosition].parent().attr('gender') == '5') {
							along = 0;
						}
						break;
					case 'left':
						if (closerCells[cellPosition].parent().attr('gender') == '4') {
							along = 0;
						}
						if (closerCells[cellPosition].parent().attr('gender') == '2') {
							along = 1;
						}
						break;
				}	
			}
		}

		cell.focus();
	}


	var findClosersCell = function( cell ){

		

		var gender = cell.parent().attr('gender');
		gender = parseInt(gender);


		var cellx = parseInt(cell.attr('cellx'));
		var celly = parseInt(cell.attr('celly'));

		closerCellRight =  screenOb.find('.crossword-cell[cellid='+ celly +'-' + (cellx + 1) +']').first();
		closerCellBottom = screenOb.find('.crossword-cell[cellid='+ (celly + 1) +'-' + cellx +']').first();

		closerCellLeft = screenOb.find('.crossword-cell[cellid='+ celly +'-' + (cellx - 1) +']').first();
		closerCellTop = screenOb.find('.crossword-cell[cellid='+ (celly - 1) +'-' + cellx +']').first();

		closerCellRight = closerCellRight.push() > 0 ? closerCellRight : null;
		closerCellBottom = closerCellBottom.push() > 0 ? closerCellBottom : null;
		closerCellLeft = closerCellLeft.push() > 0 ? closerCellLeft : null;
		closerCellTop = closerCellTop.push() > 0 ? closerCellTop : null;


		var closerCells =  [closerCellBottom, closerCellRight, closerCellTop, closerCellLeft];


		debug.log( closerCells );

		var selectedCell;
		var selectedAlong;

		for (var i = 0; i < closerCells.length; i++) {
			var closerCell = closerCells[i];

			if(closerCell != null){

				if( closerCell.attr('celltype') == 'question' || closerCell.attr('celltype') == undefined){
					continue;
				}

				switch(gender){
					case 1:
						selectedCell = closerCellBottom;
						selectedAlong = 1;
					break;

					case 2:
						selectedCell = closerCellRight;
						selectedAlong = 1;
					break;

					case 3:
						selectedCell = closerCellLeft;
						selectedAlong = 1;
					break;

					case 4:
						selectedCell = closerCellRight;
						selectedAlong = 0;
					break;

					case 5:
						selectedCell = closerCellBottom;
						selectedAlong = 0;
					break;

					case 6:
						selectedCell = closerCellTop;
						selectedAlong = 0;
					break;
				}

			}


		};

		if(typeof selectedCell !== 'undefined'){
			along = selectedAlong;
			selectedCell.focus();
			selectedCell.select();
		}


		return {
			botttom: closerCellBottom,
			right: closerCellRight,
			top: closerCellTop,
			left: closerCellLeft
		}

	}


	var findNextCell = function( cell, alongCross ){

		var cellx = parseInt(cell.attr('cellx'));
		var celly = parseInt(cell.attr('celly'));

		var nextCelly = null;
		var nextCellx = null;

		if(alongCross == null){
			nextCelly = screenOb.find('.crossword-cell[cellid='+ (celly + 1) +'-' + cellx +']').first();
			nextCellx = screenOb.find('.crossword-cell[cellid='+ celly +'-' + (cellx + 1) +']').first();
		}else{

			if(alongCross === 0){
				nextCellx = screenOb.find('.crossword-cell[cellid='+ celly +'-' + (cellx + 1) +']').first();
			} else if( alongCross === 1 ){
				nextCelly = screenOb.find('.crossword-cell[cellid='+ (celly + 1) +'-' + cellx +']').first();
			}
		}

		//nextCelly = nextCelly.push() > 0 ? nextCelly : null;
		//nextCellx = nextCellx.push() > 0 ? nextCellx : null;

		var nextCells =  [nextCellx, nextCelly];

		for (var i = 0; i < nextCells.length; i++) {
			var nextCell = nextCells[i];

			//alert(nextCell);

			if(nextCell != null){

				if( nextCell.attr('celltype') == 'question' || nextCell.attr('celltype') == undefined){
					continue;
				}

				return { nextCell: nextCell, along:i };
			}

		};

		along = 2;

		return null;
	}

	var colorizeGoodAnswer = function( cell ){

		if(cell.val() == ""){
			$(cell).attr('isWrited', 'false');
		}else{
			$(cell).attr('isWrited', 'true');
		}
		
		debug.log(cell);
		if(cell.val().toLowerCase() == ob.question.objs[cell.attr('cellid')].toLowerCase()){

			$(cell).attr('good', 'true');
			if(ob.question.colorizeGoodAnswer == true){
				$(cell).addClass('crossword-answer-select');
			}
		}
		else {
			$(cell).attr('good', 'false');
			$(cell).removeClass('crossword-answer-select');
		}
	}

	var findCellById = function( cellId ){ 
		var cell = screenOb.find('.crossword-cell[cellid="' + cellId + '"]');
		return cell;
	}

	var checkOneWord = function( exerciseIsFinished ){ 

		allCells.removeClass('crossword-answer-select');
		allCells.removeClass('qcrossword-word-is-good');

		var divisionAnswers = ob.divisionCrosswordAnswers.answers;

		for (var item in divisionAnswers) {
			var oneWordArrayIds = divisionAnswers[item];

			ob.divisionCrosswordAnswers.answersStatus[item] = false;

			
			var wordIsCorrect = true;

			for (var i = 0; i < oneWordArrayIds.length; i++) {
				var cellId =  oneWordArrayIds[i];
				var oneCell = findCellById( cellId );

				colorizeGoodAnswer( oneCell );

				if(oneCell.attr('good') == "false"){
					wordIsCorrect = false;
					break;
				}
			};

			if(wordIsCorrect == true){
				
				ob.divisionCrosswordAnswers.answersStatus[item] = true;


				for (var j = 0; j < oneWordArrayIds.length; j++) {
					var cellId =  oneWordArrayIds[j];
					var oneCell = findCellById( cellId );

					if(ob.question.colorizeGoodWord == true){
						oneCell.removeClass('crossword-answer-select');
						oneCell.addClass('qcrossword-word-is-good');
					}

				};
			}else{
				for (var k = 0; k < oneWordArrayIds.length; k++) {
					var cellId =  oneWordArrayIds[k];
					var oneCell = findCellById( cellId );

					colorizeGoodAnswer( oneCell );
				};
			}
		};

		if(ob.question.colorizeCrosswordAfterWriteLastWord == true ){

			var lastWordIsWrited = true;

			var wordIsCorrect = true;

			for (var item in divisionAnswers) {
				var oneWordArrayIds = divisionAnswers[item];
				

				for (var o = 0; o < oneWordArrayIds.length; o++) {
					var cellId =  oneWordArrayIds[o];
					var oneCell = findCellById( cellId );
					
					if(oneCell.attr('isWrited') != "true"){
						lastWordIsWrited = false;
					}

					if(oneCell.attr('good') == "false"){
						wordIsCorrect = false;
						break;
					}
				};
			}


			if(lastWordIsWrited == true || exerciseIsFinished == true){

				for (var item in divisionAnswers) {
					var oneWordArrayIds = divisionAnswers[item];

					var wordIsCorrect = true;

					for (var p = 0; p < oneWordArrayIds.length; p++) {
						var cellId =  oneWordArrayIds[p];
						var oneCell = findCellById( cellId );

						if(oneCell.attr('good') == "false"){
							wordIsCorrect = false;
							break;
						}
					};

					if(wordIsCorrect == true){
						for (var r = 0; r < oneWordArrayIds.length; r++) {
							var cellId =  oneWordArrayIds[r];
							var oneCell = findCellById( cellId );

							oneCell.addClass('qcrossword-word-is-good');
						};
					}	
				}
			}
		}

		var isCorrect = true;
		var goodAnswersNumber = 0;

		for (var item in ob.divisionCrosswordAnswers.answersStatus) {
			var status = ob.divisionCrosswordAnswers.answersStatus[item];

			if(status == true){
				goodAnswersNumber++;
			}else {
				isCorrect = false;
			}
		};


		//var isCorrect = checkResult.isCorrect;  
		//var goodAnswersNumber = checkResult.goodAnswersNumber;  


		var minAnswrsNumber = ob.question.minAnswrsNumber;
		var requireAnswersToAllQuestions = ob.question.requireAnswersToAllQuestions;


		// change variable value if option is selected
		_that.setProjectVariableValue(
			ob.question.varToChange,
			goodAnswersNumber
		);


		if( requireAnswersToAllQuestions == false){
			if(goodAnswersNumber >= minAnswrsNumber){
				isCorrect = true;	
			}
		}


		return { goodAnswersNumber:goodAnswersNumber, isCorrect:isCorrect };
	}

	var chechCrossworAnswers = function( ){

		var answersCells = screenOb.find('.crossword-cell[celltype="answer"][enabled="true"]');

		var crosswordCorrect = true;

		for (var i = 0; i < answersCells.length; i++) {
			var cell = $(answersCells[i]);
			debug.log(cell);
			if(cell.val().toLowerCase() != ob.question.objs[cell.attr('cellid')].toLowerCase()){
				crosswordCorrect = false;
				break;
			}
		};

		// if(crosswordCorrect == true){

		// 	triggerEvent(screenOb[0], 'custom_questionpassed');
		// }


		return crosswordCorrect;
	}

	

	
	//finishCrosswordExercise
	var finishCrosswordExercise = function( isCorrect ){

		//debug.log(ob.timeOut);;

		var screenOb = _that.getScreenObjectByActionkey(ob.id);

		screenOb.off('keyup paste');
		screenOb.off('click');
		screenOb.find('.crossword-cm-hidden-button').show();

		if(!isUndefined(ob.timeOut)){
			ob.timeOut.stop();
		}


		setTimeout(function(){
			switch (isCorrect) {
				case true:
					_that.object_setCompleted(ob, screenOb);
					triggerEvent(screenOb[0], 'custom_questionpassed');
					break;

				case false: 
					ob.compl = 2;
					triggerEvent(screenOb[0], 'custom_questionfailed');
					break;
			}
			
		}, 50);

	}

	var removeSelectionForAllCells = function( ){

		for (var i = 0; i < allCells.length; i++) {
			var oneCell = $(allCells[i]);

			//oneCell.css('background-color', 'rgba(0, 0, 0, 0); ');

			oneCell.removeClass('crossword-answer-select');
		};
	}

	var selectAnswers = function( ){


		removeSelectionForAllCells();

		if(ob.question.opts != undefined){
			var opts = ob.question.opts;

			for (var i in opts) {
				var oneAnswer = opts[i];

				var cell = screenOb.find('.crossword-cell[cellid="'+ i +'"]');

				cell.val( oneAnswer );

				//colorizeGoodAnswer( cell );

				
			};

			checkOneWord( true );
		}
	}

	if(ob.compl == 0){ //nie jest zaliczone

		screenOb.on('keyup paste', '.crossword-cell[celltype=answer]', function(e){
			
			if (e.which == 17 || e.which == 18) {
				return;
			}

			var checkResult = onCellKeyUp($(this));

			var isCorrect = checkResult.isCorrect; 
			var goodAnswersNumber = checkResult.goodAnswersNumber;  


			var minAnswrsNumber = ob.question.minAnswrsNumber;
			var requireAnswersToAllQuestions = ob.question.requireAnswersToAllQuestions;


			if( requireAnswersToAllQuestions == false){
				if(goodAnswersNumber >= minAnswrsNumber){
					isCorrect = true;
				}
			}

			if(isCorrect){
				finishCrosswordExercise( isCorrect );
			}

		});

		screenOb.on('click', '.crossword-cell[celltype=answer]', function(){
			this.select();
			along = null;
			focusCellByAnswer($(this));
		});

		screenOb.on('click', '.crossword-cell[celltype=question]', function(){
			if (!_that.isMobile) {
				focusCellByGender($(this) );
			}
		});

		screenOb.on('mousedown', '.crossword-cell[celltype=question]', function(e){
			if (!_that.isMobile) {
				e.preventDefault();
			}
			
			$(this).scrollTop(0);
		});

		screenOb[0].ontouchmove = function(e) {
			e.preventDefault();
		}

	}

	if(ob.compl == 1){ // jest zaliczone

		screenOb.find('.crossword-cm-hidden-button').show();

		selectAnswers();

		finishCrosswordExercise();

		setTimeout(function(){
			debug.log('crossword setcomplete');
			triggerEvent(screenOb[0], 'custom_questionpassed');
		}, 50);

	}

	if(ob.compl == 2){ // nie jest zaliczone

		screenOb.find('.crossword-cm-hidden-button').hide();

		finishCrosswordExercise();
	}

	selectAnswers();


	var crosswordTimeOut =  parseFloat( ob.question.crosswordTimeOut );
	var timeLimitOption =   ob.question.timeLimitOption ;


	if(isNumber(crosswordTimeOut)) {


		debug.log("ob.timeOut");
		debug.log(ob.timeOut);

		if(crosswordTimeOut > 0 && timeLimitOption == true){
			if(isUndefined( ob.timeOut )){

				var timerView =  $('<div class="crossword-timer-view">\
										<span class="crossword-timer-span">00:00:00</span>\
									</div>');

				screenOb.parent().append(timerView);

				var crosswordTimerSpan = timerView.find('.crossword-timer-span');

				var timerCallBack = function( time, seconds ){

					debug.log('tick');

					crosswordTimerSpan.text( time );
				}

				ob.timeOut = new _that.timer2(crosswordTimeOut, timerCallBack, function(){

					var answers_status = {
						questionIsPassed:false
					}

					var checkResult = checkOneWord();

					var isCorrect = checkResult.isCorrect;  

					finishCrosswordExercise( isCorrect );

				}, crosswordTimeOut * 1000);

				ob.timeOut.startTimer();
			}else{

				ob.timeOut.startTimer();
			}
		}
	}
};

CourseManager.prototype.quiz_memoryIsGoodAnswer = function(userSelection) {
	var _that = this;

	var success = false;

	if (userSelection.length === 2) {

		var firstItemID = userSelection[0];
		var secondItemID = userSelection[1];

		if ((firstItemID.length + secondItemID.length) >= 5) {
			if (firstItemID.replace("a", "") === secondItemID.replace("a", "")) {
				success = true;
			} else if (
				(firstItemID.length + secondItemID.length) == 7 &&
				(firstItemID.replace("p", "") === secondItemID.replace("pb", "") ||
				firstItemID.replace("pb", "") === secondItemID.replace("p", ""))
				) 
				{
					success = true;
				}
		}

		// if ((firstItemID.length === 3 && secondItemID.length === 2) || (firstItemID.length === 2 && secondItemID.length === 3)) {
		// 	if (firstItemID.length === 2) {
		// 		if ((firstItemID + "a") === secondItemID) {
		// 			success = true;
		// 		}
		// 	}
		// 	if (secondItemID.length === 2) {
		// 		if ((secondItemID + "a") === firstItemID) {
		// 			success = true;
		// 		}
		// 	}
		// }
	}

	return success;
};

/* CONNECT THE LINES */
CourseManager.prototype.quiz_qclPrepareQuestion = function(ob, screenOb) {
	var _that = this;

	screenOb.css({
		opacity: '1'
	});

	screenOb.off('click');
	screenOb.click(function(){
		_that.quiz_qclCheckAnswers(ob, screenOb);
	});

	_that.quiz_qclDrawDots(ob, screenOb);
};

CourseManager.prototype.quiz_qclDrawDots = function(ob, screenOb) {
	var _that = this;


	var getParameter = function( id ){
		return ob.question.objs[id];
	}

	// jsPlumb.ready(function() {


		var connections = [];
		var updateConnections = function(conn, remove) {
			

			if (!remove) connections.push(conn.connection);
			else {
				var idx = -1;
				for (var i = 0; i < connections.length; i++) {
					if (connections[i] == conn.connection) {
						idx = i; break;
					}
				}
				if (idx != -1) connections.splice(idx, 1);
			}
		

			//alert("updateConnections");
			var isNew = true;

			if (remove == false) {

				for (var i in ob.question.userSelection) {
					if ($(conn.connection.source).attr('actionkey') === ob.question.userSelection[i][0] &&
						$(conn.connection.target).attr('actionkey') === ob.question.userSelection[i][1] ||
						$(conn.connection.source).attr('actionkey') === ob.question.userSelection[i][1] &&
						$(conn.connection.target).attr('actionkey') === ob.question.userSelection[i][0]) {
						setTimeout(function() {
							jsPlumb.detach(conn);
						}, 50);
						// debug.log('jest juz taki, nie dodaje');
						isNew = false;
					}
				}
			}

			 if (isNew) {
				ob.question.userSelection = [];

				for (var i = 0; i < connections.length; i++) {
					var connection = connections[i];
					ob.question.userSelection.push( [ $(connection.source).attr('actionkey'), $(connection.target).attr('actionkey') ] );
				};
			 }
		};


		_that.qclInstance[ob.id] = jsPlumb.getInstance({
			
			// DragOptions : { cursor: 'pointer', zIndex:900 },
			Scope: ob.id,
			// PaintStyle : { strokeStyle:'#666' },
	        // EndpointHoverStyle: { fillStyle:"orange" },
	        // HoverPaintStyle: { strokeStyle:"orange" },
			// EndpointStyle : { width:20, height:16, strokeStyle:'#666' },
			// Endpoint : "Rectangle",
			// Anchors : ["TopCenter", "TopCenter"],
			Container:_that.L.scr.find('#divimg')
		});	

		_that.qclInstance[ob.id].setContainer(_that.L.scr.find('#divimg'));

		// var instance = _that.qclInstance[ob.id];

	   // bind to connection/connectionDetached events, and update the list of connections on screen.
		_that.qclInstance[ob.id].bind("connection", function(info, originalEvent) {
			updateConnections(info, false);

			if (!ob.question.opts.allowBadAnswers) {
				if (!_that.quiz_qclConnectionIsAGoodAnswer(ob, info.connection)) {
					setTimeout(function() {
						_that.qclInstance[ob.id].detach(info.connection);
					}, 10);
				}	
			}
			
		});
		_that.qclInstance[ob.id].bind("connectionDetached", function(info, originalEvent) {
			updateConnections(info, true);
		});
		
		_that.qclInstance[ob.id].bind("connectionMoved", function(info, originalEvent) {
			//  only remove here, because a 'connection' event is also fired.
			// in a future release of jsplumb this extra connection event will not
			// be fired.
			updateConnections(info, true);
		});

		_that.qclInstance[ob.id]._isDisabled = false;
		_that.qclInstance[ob.id]._obActionkey = ob.id;

	    _that.qclInstance[ob.id].bind("click", function(component, originalEvent) {


	    	if (!_that.qclInstance[ob.id]._isDisabled && ob.id === _that.qclInstance[ob.id]._obActionkey) {

	    		jsPlumb.detach(component); 
	        	updateConnections(component, true);
	    	}
	        
	    });

		for (var a in ob.question.objs) {
			var ans = ob.question.objs[a];

			var qclOb = _that.getObjectByID(a);
			var qclScreenOb = _that.getScreenObjectByActionkey(a);


			if ( isObject(qclOb) && !qclOb.qclinit) {
				var options = getParameter(a);

				var align = options.align;
				var color1 = options.color;
				var size1 = options.size;
				var lineWidth1 = options.lineWidth;
				var maxConnections1 = options.maxConnections;

				maxConnections1 = maxConnections1 == 0 ? maxConnections1 = -1 : maxConnections1;

				var objectIsSource = ob.question.opts.onlySourceTarget ? options.isSource : true;
				var objectIsTarget = ob.question.opts.onlySourceTarget ? options.isTarget : true;

				if (!objectIsSource && !objectIsTarget) {
					objectIsTarget = true;
				}

				var endpointOptions = {
					endpoint: ["Dot", { radius:size1 }],
					paintStyle: { fillStyle:color1 },
					connectorStyle: { strokeStyle:color1, lineWidth:lineWidth1 },
					connector : "Straight",
					dropOptions : { tolerance:"touch" },
					maxConnections: maxConnections1,
					isSource: objectIsSource,
					isTarget: objectIsTarget,

					beforeDrop:function(params) { 
						return true;
					},
				}


				var elFix = false;
				if (qclScreenOb.css('display') == "none") {
					elFix = true;
					qclScreenOb.css({
						visibility: 'hidden',
						display: 'block'
					});
				}

				_that.qclInstance[ob.id].addEndpoint( qclScreenOb, { anchor:align }, endpointOptions);

				if (elFix) {
					// (function(element){
						// setTimeout(function(){
							qclScreenOb.css({
								visibility: 'visible',
								display: 'none'
							});
						// }, 1);
					// })(qclScreenOb);
					
				}
				qclOb.qclinit = true;
			}
		}

		$('._jsPlumb_endpoint, ._jsPlumb_connector').css({
			'z-index': screenOb.css('z-index')
		}).fadeIn();

	// });
};

CourseManager.prototype.quiz_qclCheckAnswers = function(ob, screenOb) {
	var _that = this;


	var userSelection = ob.question.userSelection;

	if ( !isObject(userSelection) ) {
		_that.quiz_selectAtLeastOneAnswerInfo( lang[language]['ANSWER_ALL_QUESTIONS_FIRST_QCL'] , 'red')
		return;
	}
	
	// Get connection object by actionkeys in answer
	var getConnectionByActionkeys = function(actionkeys) {
		var allConnections = _that.qclInstance[ob.id].getAllConnections();

		for (var i = allConnections.length - 1; i >= 0; i--) {
			var connection = allConnections[i];

			var connectionActionkeys = [ 
				$(connection.source).attr('actionkey'),
				$(connection.target).attr('actionkey')
			];

			if (Utils.arrayAreEqual(actionkeys.sort(), connectionActionkeys.sort())) {
				return connection;
			}
		};

		return false;
	}



	var answers = ob.question.answers;

	var isCorrect = true;

	var allGoodAnswers = [];


	for (var i = 0; i < answers.length; i++) {
		var answer = answers[i];
		var from = answer.from;

		for (var j = 0; j < answer.to.length; j++) {
			var to = answer.to[j];
			var goodAnswer = [from, to];
			goodAnswer.sort();
			allGoodAnswers.push(goodAnswer);
		};
	};

	var userAnswersStatus = [ ];

	var allBadAnswers = [ ];

	if (typeof userSelection !== "undefined") {

		for (var us = 0; us < ob.question.userSelection.length; us++) {
			var userAnswer = ob.question.userSelection[us].sort();


			var answerStatus = false;


			for (var ga = 0; ga < allGoodAnswers.length; ga++) {
				var goodAnswer = allGoodAnswers[ga];

				if (Utils.arrayAreEqual(goodAnswer, userAnswer)) {
					answerStatus = true;
				}

			}


			if (!answerStatus) {
				allBadAnswers.push(userAnswer);
			}


			userAnswersStatus.push(answerStatus);
		};
	}

	// if length of user answers and good answers are not the same - its bad answer
	if (allGoodAnswers.length !== ob.question.userSelection.length) {
		userAnswersStatus = [false];
	}

	var answers_status = {
		questionIsPassed:false
	}
   
   	debug.log(allBadAnswers);

	if (userAnswersStatus.indexOf(false) === -1 && userAnswersStatus.length > 0) {
		answers_status.questionIsPassed = true;
	} else {
		answers_status.questionIsPassed = false;

		// after bad answer...
		switch (ob.question.opts.afterBadAnswer) {
			case 'donothing':
				// doing nothing...
				break;
				
			case 'removebad':

				for (var i = allBadAnswers.length - 1; i >= 0; i--) {
					var singleBadAnswer = allBadAnswers[i].sort();
					var connection = getConnectionByActionkeys(singleBadAnswer);

					if (connection) {
						_that.qclInstance[ob.id].detach(connection);
					}
				};
				break;
				
			case 'removeall':
				_that.qclInstance[ob.id].detachEveryConnection();
				break;
		}
	}

	_that.quiz_ShowFeedback(ob, screenOb, answers_status);
};

CourseManager.prototype.quiz_qclConnectionIsAGoodAnswer = function(ob, connection) {
	var _that = this;

	var allGoodAnswers = [];
	var answers = ob.question.answers;


	var connectionActionkeys = [ 
				$(connection.source).attr('actionkey'),
				$(connection.target).attr('actionkey')
			];

	for (var i = 0; i < answers.length; i++) {
		var answer = answers[i];
		var from = answer.from;

		for (var j = 0; j < answer.to.length; j++) {
			var to = answer.to[j];
			var goodAnswer = [from, to];
			goodAnswer.sort();
			allGoodAnswers.push(goodAnswer);
		};
	};

	for (var ga = 0; ga < allGoodAnswers.length; ga++) {
		var goodAnswer = allGoodAnswers[ga];

		if (Utils.arrayAreEqual(goodAnswer, connectionActionkeys.sort())) {
			return true;
		}
	}

	return false
};

CourseManager.prototype.quiz_qclMarkQuestionAsPassed = function(ob, screenOb) {
	var _that = this;

	screenOb.off('click');
	screenOb.css({
		opacity: '.4'
	});


	var activeInstance = _that.qclInstance[ob.id];

	if (!isUndefined(activeInstance)){

		activeInstance.unbind();

		// activeInstance.unbind("click");
		// activeInstance.unbind("connectionMoved");
		// activeInstance.unbind("connectionDetached");
		// activeInstance.unbind("connection");

		activeInstance._isDisabled = true;

		activeInstance.deleteEveryEndpoint();


	    var endpointFrom, 
	        endpointTo;

	    var answers = ob.question.answers;

	    for (var i = 0; i < answers.length; i++) {
	    	var answer = answers[i];

	        var options = ob.question.objs[answer.from];
	        var screenElement = _that.getScreenObjectByActionkey(answer.from);


	        var maxConnections1 = options.maxConnections;
	        maxConnections1 = maxConnections1 == 0 ? maxConnections1 = -1 : maxConnections1;

	        var point1 = {
	            endpoint:["Dot", { radius:options.size }],
	            paintStyle:{ fillStyle:options.color },
	            connectorStyle:{ strokeStyle:options.color, lineWidth:options.lineWidth },
	            connector : "Straight",
	            dropOptions : { tolerance:"touch" },
	            maxConnections:maxConnections1,
	            isSource:false,
	            isTarget:false
	        }

			var el1fix = false;
			if (screenElement.css('display') == "none") {
				el1fix = true;
				screenElement.css({
					visibility: 'hidden',
					display: 'block'
				});
			}

			endpointFrom = activeInstance.addEndpoint(screenElement, { anchor:options.align }, point1);

			if (el1fix === true) {
				(function(element){
					setTimeout(function(){
						element.css({
							visibility: 'visible',
							display: 'none'
						});
					}, 1);
				})(screenElement);
			}

	        for (var k = 0; k < answer.to.length; k++) {

	            var to = answer.to[k];

	            var screenElement = _that.getScreenObjectByActionkey(to);


	            var options = ob.question.objs[to];

	            var maxConnections1 = options.maxConnections;
	            maxConnections1 = maxConnections1 == 0 ? maxConnections1 = -1 : maxConnections1;

	            var point1 = {
	                endpoint:["Dot", { radius:options.size }],
	                paintStyle:{ fillStyle:options.color },
	                connectorStyle:{ strokeStyle:options.color, lineWidth:options.lineWidth },
	                connector : "Straight",
	                dropOptions : { tolerance:"touch" },
	                maxConnections:maxConnections1,
	                isSource:false,
	                isTarget:false
	            }

				var el2fix = false;
				if (screenElement.css('display') == "none") {
					el2fix = true;
					screenElement.css({
						visibility: 'hidden',
						display: 'block'
					});
				}

	            endpointTo =  activeInstance.addEndpoint(screenElement, { anchor:options.align }, point1);

				if (el2fix === true) {
					(function(element){
						setTimeout(function(){
							element.css({
								visibility: 'visible',
								display: 'none'
							});
						}, 1);
					})(screenElement);
				}

	            _that.qclInstance[ob.id].connect({ source: endpointFrom, target: endpointTo });
	    	};
	    }



		for (var a in ob.question.objs) {
			var ans = ob.question.objs[a];

			debug.log("Rysuje dla: " + a); 

			var qclOb = _that.getObjectByID(a);
			var qclScreenOb = _that.getScreenObjectByActionkey(a);

			var align = ans.align;
			var color1 = ans.color;
			var size1 = ans.size;
			var lineWidth1 = ans.lineWidth;
			var maxConnections1 = ans.maxConnections;

			maxConnections1 = maxConnections1 == 0 ? maxConnections1 = -1 : maxConnections1;

			var endpointOptions = {
				endpoint: ["Dot", { radius:size1 }],
				paintStyle: { fillStyle:color1 },
				connectorStyle: { strokeStyle:color1, lineWidth:lineWidth1 },
				connector : "Straight",
				dropOptions : { tolerance:"touch" },
				maxConnections: maxConnections1,
				isSource: false,
				isTarget: false
			}


			var elFix = false;
			if (qclScreenOb.css('display') == "none") {
				elFix = true;
				qclScreenOb.css({
					visibility: 'hidden',
					display: 'block'
				});
			}

			activeInstance.addEndpoint( qclScreenOb, { anchor:align }, endpointOptions);

			if (elFix === true) {
				(function(element){
					setTimeout(function(){
						element.css({
							visibility: 'visible',
							display: 'none'
						});
					}, 1);
				})(qclScreenOb);
				
			}
		}

    }
};

CourseManager.prototype.quiz_qclMarkQuestionAsFailed = function(ob, screenOb) {
	var _that = this;


	screenOb.off('click');
	screenOb.css({
		opacity: '.4'
	});

	var activeInstance = _that.qclInstance[ob.id];

	if (!isUndefined(activeInstance)){

		activeInstance.unbind();
		
		activeInstance._isDisabled = true;

		activeInstance.deleteEveryEndpoint();


	    var endpoints = [ ];

    	for (var ans in ob.question.objs) {
	    	var answer = ob.question.objs[ans];


	    	// var answer1 = answer[0];
	    	// var answer2 = answer[1];

	        var screenElement = _that.getScreenObjectByActionkey(ans);

	        var endpointOptions = {
	            endpoint:["Dot", { radius:answer.size }],
	            paintStyle:{ fillStyle:answer.color },
	            connectorStyle:{ strokeStyle:answer.color, lineWidth:answer.lineWidth },
	            connector : "Straight",
	            dropOptions : { tolerance:"touch" },
	            maxConnections:-1,
	            isSource:false,
	            isTarget:false
	        }

			var el1fix = false;
			if (screenElement.css('display') == "none") {
				el1fix = true;
				screenElement.css({
					visibility: 'hidden',
					display: 'block'
				});
			}

			endpoints[ans] = activeInstance.addEndpoint(screenElement, { anchor:answer.align }, endpointOptions);

			if (el1fix === true) {
				(function(element){
					setTimeout(function(){
						element.css({
							visibility: 'visible',
							display: 'none'
						});
					}, 1);
				})(screenElement);
			}
	    }

	    var userAnswers = ob.question.userSelection;

	    if (isObject(userAnswers)) {
		    for (var i = 0; i < userAnswers.length; i++) {
		    	activeInstance.connect({ source: endpoints[userAnswers[i][0]], target: endpoints[userAnswers[i][1]] });
		    }
	    }
    }
};


/* WORD SERACH */
CourseManager.prototype.quiz_qwsPrepareQuestion = function(ob, screenOb) {
	var _that = this;

	// screenOb.find('textarea').each(function() {
	// 	$(this).changeElementType('div');
	// })

	screenOb.find('.wordsearch-hidden-button').hide();

	// screenOb.find('*').css({
	// 	'-webkit-user-select': 'none',
	// 	'-ms-user-select': 'none',
	// 	'-moz-user-select': 'none',
	// 	'-o-user-select': 'none',
	// 	'user-select': 'none'
	// });


	var alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'W', 'Y', 'Z'];


	var allCells = screenOb.find('.wordsearch-cell');
	allCells.attr('readonly', 'true');

	screenOb.allCells = allCells;


	for (var i = 0; i < allCells.length; i++) {
	    var cell = $(allCells[i]);

	    if(cell.text() == "") {
	    	var letterId = Math.floor(Math.random() * (alphabet.length - 1));
	    	cell.text(alphabet[letterId]);
	    }
	    cell.parent().css({'float': 'left'});
	};



	var checkWordsearchAnswer = function ( minAnswrsNumber ) {

		var selectedCells = screenOb.find('.qwordsearch-select');

		allCells.removeClass('qwordsearch-select');

		var selectedAnswer = [];

		for (var i = 0; i < selectedCells.length; i++) {
			selectedAnswer.push( $(selectedCells[i]).attr('cellid') );
		};

		

		var answers = ob.question.answers;

		for (var i = 0; i < answers.length; i++) {
			var answer = answers[i];


			var objs = answer.objs;
			objs.sort();

			if(answer.opts.isCorrect != true){

				var findError = false;

				if(objs.length != selectedAnswer.length) findError = true;

				selectedAnswer.sort();

				for (var j = 0; j < objs.length; j++) {
					var oneAnswer = objs[j];

					if(oneAnswer != selectedAnswer[j]){
						debug.log(oneAnswer);
						debug.log(selectedAnswer[j]);
						findError = true;
					}
				};

				if(!findError){
					selectedCells.addClass('qwordsearch-selected-word'); 
					answer.opts.isCorrect = true;
				}
			}

		};	


		var isCorrect = true;

		var goodAnswersNumber = 0;

		for (var k = 0; k < answers.length; k++) {
			var answer = answers[k];
			var opts = answer.opts;		

			if(opts.isCorrect != true){
				isCorrect = false;
			}


			if (opts.isCorrect) {
				goodAnswersNumber++;
			}
		}	

		// change variable value if option is selected
		_that.setProjectVariableValue(
			ob.question.varToChange,
			goodAnswersNumber
		);


		if (minAnswrsNumber > 0) {
			if (goodAnswersNumber >= minAnswrsNumber) {
				isCorrect = true;
			}
		}

		return isCorrect;
	}

	var colorizeGoodAnswers = function (  ) {


		var answers = ob.question.answers;

		for (var i = 0; i < answers.length; i++) {
			var answer = answers[i];

			var objs = answer.objs;

			if(answer.opts.isCorrect == true){

				for (var j = 0; j < objs.length; j++) {

					var cellId = objs[j];

					var cell = screenOb.find('.wordsearch-cell[cellid="' + cellId + '"]');

					cell.addClass('qwordsearch-selected-word');
				}
			}

		};
	}

	var colorizeAllAnswers = function (  ) {


		var answers = ob.question.answers;

		for (var i = 0; i < answers.length; i++) {
			var answer = answers[i];

			var objs = answer.objs;


			for (var j = 0; j < objs.length; j++) {

				var cellId = objs[j];

				var cell = screenOb.find('.wordsearch-cell[cellid="' + cellId + '"]');

				cell.addClass('qwordsearch-selected-word');
			}
		};
	}

	var selectCells = function (selectedCell) {

		// Mouse controller
		screenOb.on('mousemove', '.wordsearch-cell', function(){
			var selectedCellX = parseInt(selectedCell.attr('cellx'));
			var selectedCellY = parseInt(selectedCell.attr('celly'));

			allCells.removeClass('qwordsearch-select');

			selectedCell.addClass('qwordsearch-select');
			onControllerMove($(this), selectedCell, selectedCellX, selectedCellY);
		});

		// Touch controller
		screenOb[0].ontouchmove = function(e) {

			e.preventDefault();

			var touchX = e.touches[0].pageX;
			var touchY = e.touches[0].pageY;

			var finedCell = document.elementFromPoint(touchX, touchY);

			if($(finedCell).hasClass('wordsearch-cell')) {
				var selectedCellX = parseInt(selectedCell.attr('cellx'));
				var selectedCellY = parseInt(selectedCell.attr('celly'));

				allCells.removeClass('qwordsearch-select');

				selectedCell.addClass('qwordsearch-select');
				onControllerMove($(finedCell), selectedCell, selectedCellX, selectedCellY);
			}
		}
	}

	var onControllerMove = function(finedCell, selectedCell, selectedCellX, selectedCellY) {
		debug.log('Touch move...');


		debug.log(finedCell);
		// debug.log(selectedCell);

		var finedCellX = parseInt(finedCell.attr('cellx'));
		var finedCellY = parseInt(finedCell.attr('celly'));

		allCells.removeClass('qwordsearch-select');
		// selectedCell.addClass('qwordsearch-select');

		if(finedCellX == selectedCellX){


			if(selectedCellY > finedCellY){
				
				for (var i = selectedCellY; i >= finedCellY; i--) {
					var cell = screenOb.find('.wordsearch-cell[cellx="' + finedCellX + '"][celly="' + i + '"]')

					cell.addClass('qwordsearch-select');
				};
			}else{
				for (var i = selectedCellY; i <= finedCellY; i++) {
					var cell = screenOb.find('.wordsearch-cell[cellx="' + finedCellX + '"][celly="' + i + '"]')

					cell.addClass('qwordsearch-select');
				};
			}

			
		}

		if(finedCellY == selectedCellY){

			for (var i = selectedCellX; i <= finedCellX; i++) {
				var cell = screenOb.find('.wordsearch-cell[cellx="' + i + '"][celly="' + finedCellY + '"]')

				cell.addClass('qwordsearch-select');
			};


			if(selectedCellX > finedCellX){
				
				for (var i = selectedCellX; i >= finedCellX; i--) {
				var cell = screenOb.find('.wordsearch-cell[cellx="' + i + '"][celly="' + finedCellY + '"]')

				cell.addClass('qwordsearch-select');
			};
			}else{
				for (var i = selectedCellX; i <= finedCellX; i++) {
					var cell = screenOb.find('.wordsearch-cell[cellx="' + i + '"][celly="' + finedCellY + '"]')

					cell.addClass('qwordsearch-select');
				};
			}
		}

		if(Math.abs(finedCellX - selectedCellX) == Math.abs(finedCellY - selectedCellY)){


			switch(true) {

				case finedCellX > selectedCellX && finedCellY > selectedCellY:

					var x = selectedCellX;
					var y = selectedCellY;

					for (var i = selectedCellX; i <= finedCellX; i++) {
						var cell = screenOb.find('.wordsearch-cell[cellx="' + x + '"][celly="' + y + '"]');

						y++;
						x++;

						cell.addClass('qwordsearch-select');
					};

					break;

				case finedCellX < selectedCellX && finedCellY < selectedCellY:

					var x = selectedCellX;
					var y = selectedCellY;

					for (var i = finedCellX; i <= selectedCellX; i++) {
						var cell = screenOb.find('.wordsearch-cell[cellx="' + x + '"][celly="' + y + '"]');

						y--;
						x--;

						cell.addClass('qwordsearch-select');
					};
					

					break;	

				case finedCellX > selectedCellX && finedCellY < selectedCellY:

					var x = selectedCellX;
					var y = selectedCellY;

					for (var i = selectedCellX; i <= finedCellX; i++) {
						var cell = screenOb.find('.wordsearch-cell[cellx="' + x + '"][celly="' + y + '"]');

						y--;
						x++;

						cell.addClass('qwordsearch-select');
					};

					break;	

				case finedCellX < selectedCellX && finedCellY > selectedCellY:

					var x = selectedCellX;
					var y = selectedCellY;

					for (var i = finedCellX; i <= selectedCellX; i++) {
						var cell = screenOb.find('.wordsearch-cell[cellx="' + x + '"][celly="' + y + '"]');

						y++;
						x--;

						cell.addClass('qwordsearch-select');
					};
				
					break;		
			}	
		}
	}


	var finishExercise = function( answers_status ){

		if(!isUndefined(ob.timeOut)){
			ob.timeOut.stop();
		}

		var screenOb = _that.getScreenObjectByActionkey(ob.id);

		var allCells = screenOb.find('.wordsearch-cell');

		screenOb.allCells = allCells;

		screenOb.off('mousemove');
		screenOb.allCells.off('mousedown');
		screenOb.off('mouseup');
		screenOb.off('mouseleave');

		//_that.quiz_ShowFeedback(ob, screenOb, answers_status);

		var minAnswrsNumber = ob.question.minAnswrsNumber;

		var isCorrect = checkWordsearchAnswer( minAnswrsNumber );

		var answers_status = {
			questionIsPassed:false
		}

		if (isCorrect) {
			answers_status.questionIsPassed = true;
		} else{
			answers_status.questionIsPassed = false;
		}

		setTimeout(function(){
			switch (answers_status.questionIsPassed) {
				case true:
					_that.object_setCompleted(ob, screenOb);
					triggerEvent(screenOb[0], 'custom_questionpassed');
					break;

				case false: 
					ob.compl = 2;
					triggerEvent(screenOb[0], 'custom_questionfailed');
					break;
			}
		}, 50);
	}

	if(ob.compl == 0){ 

		// Mouse controller
		screenOb.allCells.mousedown(function(){
			var selectedCell = $(this);
			selectCells( selectedCell );
		});
		// Touch controller
		screenOb.allCells.each(function() {
			this.ontouchstart = function() {
				var selectedCell = $(this);
				selectCells( selectedCell );
			}
		});


		// Mouse controller
		screenOb.mouseup(function(){
			screenOb.off('mousemove');
			var isCorrect = checkWordsearchAnswer(0);
			debug.log(isCorrect);
			var answers_status = {
				questionIsPassed:false
			}
			if (isCorrect) {
				answers_status.questionIsPassed = true;
				finishExercise(answers_status);
			} else {
				//answers_status.questionIsPassed = false;
			}
		});
		// Touch controller
		screenOb[0].ontouchend = function() {
			var isCorrect = checkWordsearchAnswer();
			debug.log('Touch end...');
			var answers_status = {
				questionIsPassed:false
			}
			if (isCorrect) {
				answers_status.questionIsPassed = true;
				finishExercise(answers_status);
			}
		}
		// screenOb.mouseleave(function(){
		// 	screenOb.off('mousemove');
		// });
	}

	if(ob.compl == 1){ 

		// screenOb.off('mousemove');
		// screenOb.off('mousedown');
		// screenOb.off('mouseup');
		// screenOb.off('mouseleave');

		allCells.removeClass('qwordsearch-select');

		debug.log("koloruj");

		colorizeAllAnswers();

		setTimeout(function(){
			triggerEvent(screenOb[0], 'custom_questionpassed');
		}, 50);

	}else{

		// screenOb.off('mousemove');
		// screenOb.off('mousedown');
		// screenOb.off('mouseup');
		// screenOb.off('mouseleave');

		allCells.removeClass('qwordsearch-select');

		debug.log("koloruj tylko dobre odpowiedzi");

		colorizeGoodAnswers();
	}


	var wordSearchTimeOut =  parseFloat( ob.question.wordSearchTimeOut );
	var timeLimitOption =   ob.question.timeLimitOption ;

	if(isNumber(wordSearchTimeOut)) {

		if(wordSearchTimeOut > 0 && timeLimitOption == true){
			debug.log("ob.timeOut");
			debug.log(ob.timeOut);

			if(isUndefined( ob.timeOut )){


				var timerView =  $('<div class="wordsearch-timer-view">\
										<span class="wordsearch-timer-span">00:00:00</span>\
									</div>');

				var wordsearchTimerSpan = timerView.find('.wordsearch-timer-span');

				var timerCallBack = function( time, seconds ){

					debug.log('tick');

					wordsearchTimerSpan.text( time );
				}

				screenOb.parent().append(timerView);


				ob.timeOut = new _that.timer2(wordSearchTimeOut, timerCallBack, function(){

					var answers_status = {
						questionIsPassed:false
					}

					finishExercise( answers_status );

				}, wordSearchTimeOut * 1000);

				ob.timeOut.startTimer();

			}else{
				if (ob.compl === 0) {
					ob.timeOut.startTimer();
				}
			}
		}
	}
	//0 nie ruszone 1 dobrze 2 żle
}


CourseManager.prototype.counter_prepareObject = function(ob, screenOb) {
	var _that = this;

	debug.log(ob);



	var hours = ob.counterdata.hours.enabled ? parseInt(ob.counterdata.hours.time)*3600 : 0,
		minutes = ob.counterdata.minutes.enabled ? parseInt(ob.counterdata.minutes.time)*60 : 0,
		seconds = ob.counterdata.seconds.enabled ? parseInt(ob.counterdata.seconds.time) : 0;


	var timeInSeconds = hours + minutes + seconds;

	var timerID = ob.counterdata.timerID;

	var timerCallBack = function( time, seconds ) {

		var timeToShow = _that.convertToTime(
						seconds, 
						ob.counterdata.hours.enabled,
						ob.counterdata.minutes.enabled,
						 ob.counterdata.seconds.enabled
					)

		_that.countersData[timerID].timerSeconds = seconds;

		_that.getScreenObjectByActionkey(ob.id).find('.simpletext-txt span').first().text( timeToShow );
	}

	

	var continueTimerTime = false;

	if (isObject(_that.countersData[timerID])) {
		continueTimerTime = true;
		timeInSeconds = _that.countersData[timerID].timerSeconds

	} else {
		_that.countersData[timerID] = {
			timerSeconds: timeInSeconds
		};	
	}



	if(isUndefined( ob.timeOut )) {

		ob.timeOut = new _that.timer2(timeInSeconds, timerCallBack, function(){
			triggerEvent(screenOb[0], 'custom_timerend');
		}, timeInSeconds * 1000);

		if (ob.counterdata.autostart) {


			
			// ob.timeOut.startTimer();
			_that.counter_startCounting(ob, screenOb);
		}

	} else {
		if (ob.compl === 0) {
			if (continueTimerTime) {
				ob.timeOut.timerTime = timeInSeconds;
			}

			if (ob.counterdata.autostart) {
				_that.counter_startCounting(ob, screenOb);
			}
		}

	}

	timerCallBack('', ob.timeOut.timerTime);
};


CourseManager.prototype.counter_startCounting = function(ob, screenOb) {
	var _that = this;


	ob.timeOut.startTimer();

	setTimeout(function() {
		triggerEvent(screenOb[0], 'custom_timerstart');
	}, 1);
};

CourseManager.prototype.convertToTime = function( timeInSeconds, showHours, showMinutes, showSeconds ) {
	var date = new Date(null);
	date.setSeconds(timeInSeconds);

	var hours = date.getUTCHours();
	var minutes = date.getUTCMinutes();
	var seconds = date.getUTCSeconds();

	var time = '';

	switch (true) {
		case showHours && showMinutes && showSeconds:
			time = Utils.zeroWiodace( hours ) + ":" + Utils.zeroWiodace( minutes ) + ":" + Utils.zeroWiodace( seconds );
			break;

		case !showHours && showMinutes && showSeconds:
			time = Utils.zeroWiodace( ((hours*60) + minutes) ) + ":" + Utils.zeroWiodace( seconds );
			break;

		case !showHours && !showMinutes && showSeconds:
			time = Utils.zeroWiodace( ((hours*3600) + minutes*60) + seconds );
			break;

		default:
			time = Utils.zeroWiodace( hours ) + ":" + Utils.zeroWiodace( minutes ) + ":" + Utils.zeroWiodace( seconds );
			break;
	}
	return time;
};


CourseManager.prototype.quiz_boardgamePrepare = function(ob, screenOb) {
	var _that = this;

	var variableToUseValue;

	for (var v in _that.course.opts.trigger) {
		if (ob.gamedata.opts.variableToUse.length == 32) {
			if (_that.course.opts.trigger[v].varhash === ob.gamedata.opts.variableToUse) {
				variableToUseValue = _that.course.opts.trigger[v];
			}	
		}
	}

	unwatch(variableToUseValue, "pvarvalue");

	var to;
	watch(variableToUseValue, "pvarvalue", function() {
		clearTimeout(to);
		to = setTimeout(function() {
			_that.quiz_boardgameRefreshActorPosition(ob, screenOb, variableToUseValue);
		},20);
		
	});

	_that.quiz_boardgameRefreshActorPosition(ob, screenOb, variableToUseValue);
};	


CourseManager.prototype.quiz_boardgameRefreshActorPosition = function(ob, screenOb, variableToUse) {
	var _that = this;

	screenOb.hide();

	var variableToUseValue = variableToUse.pvarvalue;




	var actor = _that.getScreenObjectByActionkey(ob.gamedata.gameActor);
	var actorOb = _that.getObjectByID(ob.gamedata.gameActor);

	debug.log(" ======================== actor ========================");
	debug.log(actor);

	actor.hide();

	var activeField;
	if (ob.gamedata.gameFields.length >= variableToUseValue) {
		
		activeField = _that.getScreenObjectByActionkey(ob.gamedata.gameFields[variableToUseValue]);
	} else {
		activeField = _that.getScreenObjectByActionkey(ob.gamedata.gameFields[ob.gamedata.gameFields.length-1]);
	}

	// activeField = _that.getScreenObjectByActionkey(ob.gamedata.gameFields[variableToUseValue]);

	debug.log('activeField');
	debug.log(activeField);

	var centerY = (parseInt(activeField.css('top')) + activeField.height()/2) - (actor.height()/2);
	var centerX = (parseInt(activeField.css('left')) + activeField.width()/2) - (actor.width()/2);

	actor.css({
		top: centerY + "px",
		left: centerX + "px"
	});

	_that.object_showing(actorOb, actor, true);



	if ((ob.gamedata.gameFields.length-1) <= variableToUseValue) {
		triggerEvent(screenOb[0], 'custom_questionpassed');
	}
};


function triggerEvent(el,eventName){
    var event;
    if(document.createEvent){
        event = document.createEvent('HTMLEvents');
        event.initEvent(eventName,true,true);
    }else if(document.createEventObject){// IE < 9

        event = document.createEventObject();
        event.eventType = eventName;
    }
    event.eventName = eventName;
    if(el.dispatchEvent){
        el.dispatchEvent(event);
    }else if(el.fireEvent && htmlEvents['on'+eventName]){// IE < 9
        el.fireEvent('on'+event.eventType,event);// can trigger only real event (e.g. 'click')
    }else if(el[eventName]){
        el[eventName]();
    }else if(el['on'+eventName]){
        el['on'+eventName]();
    }
}
function addEvent(el,type,handler){
    if(el.addEventListener){
        el.addEventListener(type,handler,false);
    }else if(el.attachEvent && htmlEvents['on'+type]){// IE < 9
        el.attachEvent('on'+type,handler);
    }else{
        el['on'+type]=handler;
    }
}
