PageSourceSearch

https://www.ilo.pl/elearning/pics/js/etest/utilsETest.js

js ilo.pl collected 2026-09-29 19:35:52 UTC 198,057 bytes, 6,582 lines download raw bytes

1var ETestUtils = {};
2
3if (typeof window != 'undefined') {
4    window.ETestUtils = ETestUtils;
5}
6
7ETestUtils.etestTypeTest = 0;
8ETestUtils.etestTypePresentation = 1;
9ETestUtils.etestTypeHomework = 2;
10ETestUtils.etestTypeProject = 3;
11ETestUtils.etestTypeExam = 4;
12ETestUtils.colors = ["#3366cc","#dc3912","#ff9900","#109618","#990099","#0099c6","#dd4477","#66aa00","#b82e2e","#316395","#994499","#22aa99","#aaaa11","#6633cc","#e67300","#8b0707","#651067","#329262","#5574a6","#3b3eac","#b77322","#16d620","#b91383","#f4359e","#9c5935","#a9c413","#2a778d","#668d1c","#bea413","#0c5922","#743411"];
13
14ETestUtils.isNumeric = function(n) {	
15  return !isNaN(parseFloat(n)) && isFinite(n);
16}
17
18ETestUtils.getHomeworksPageMode = function() {
19	return 'all';
20}
21
22ETestUtils.getTemaOduceneHodiny = function(tema) {
23	var ret = [];
24	if (!tema.oduceneHodiny) return ret;
25	var ad = (new Date()).format('Y-m-d');
26	for (var i=0;i<tema.oduceneHodiny.length;i++) {
27		var r = tema.oduceneHodiny[i];
28		if (r.datum <= ad) ret.push(r);
29	}
30	return ret;
31}
32
33ETestUtils.getTemaBuduceHodiny = function(tema) {
34	var ret = [];
35	if (!tema.oduceneHodiny) return ret;
36	var ad = (new Date()).format('Y-m-d');
37	for (var i=0;i<tema.oduceneHodiny.length;i++) {
38		var r = tema.oduceneHodiny[i];
39		if (r.datum > ad) ret.push(r);
40	}
41	return ret;
42}
43
44ETestUtils.fixIOSSrc = function(src) {
45	if (!src) return '';
46	if ((MobileAppBridge.isActive()) && src.startsWith('/') && !src.startsWith('//') && EdubarUtils.getEdupage()) {
47		src = 'https://'+EdubarUtils.getEdupage()+'.edupage.org'+src;
48	} else if ((MobileAppBridge.isActive()) && src.startsWith('//')) {
49		src = 'https:'+src;
50	}
51	
52	return src;
53}
54ETestUtils.jePrebranaTema = function(tema) {
55	if (!tema) return false;
56	if (tema.prebrane_man) return true;
57	if (tema.prebrane_man === false) return false;
58
59	if (tema.done) return true;
60	
61	if (tema.prebrane) return true;
62
63	if (!tema.oduceneHodiny) return false;
64	if (tema.pocet_hodin > tema.oduceneHodiny.length) return false;
65
66	var pocetOduc = ETestUtils.getTemaOduceneHodiny(tema).length;
67	
68
69	return pocetOduc>0 && pocetOduc >= tema.pocet_hodin;
70}
71
72ETestUtils.getSortLink = function(name, id, sortOptions) {
73	var s = '';
74	s += '<a class="etest-sort-button" data-field="{id}" style="cursor:pointer;color:inherit">';
75		s += '{!name}';
76		
77		if (sortOptions["field"] == id) {
78			if (sortOptions["dir"] == 'desc') {
79				s += '<i class="fa fa-fw fa-caret-down"></i>';
80			} else {
81				s += '<i class="fa fa-fw fa-caret-up"></i>';
82			}
83		}
84	s += '</a>';
85	
86	return renderS(s, {
87			name: name,
88			id: id,
89			 
90		   });
91}
92
93ETestUtils.handleSortLink = function(elem, sortOptions) {	
94	var field = $j(elem).attr('data-field');
95	if (field == sortOptions["field"]) {
96		sortOptions["dir"] = sortOptions["dir"] == 'desc' ? 'asc' : 'desc';
97	} else {
98		sortOptions["field"] = field;
99		sortOptions["dir"] = 'asc';
100	}
101}
102
103ETestUtils.sortRows = function(rows, sortOptions) {
104	if (!$.isArray(rows)) {
105		var rows0 = [];
106		for (var x in rows) {
107			rows0.push(rows[x]);
108		}
109		rows = rows0;
110	}
111	var sortDirMultiplier = sortOptions.dir == 'desc' ? -1 : 1;
112	var field = sortOptions.field ? sortOptions.field : '';
113	var numeric = false;
114	if (field.substr(0,1) == '#') {
115		numeric = true;
116		field = field.substr(1);
117	}
118	rows.sort(function(a,b) {
119		var as = '';
120		var bs = '';			
121		if (field == 'student') {
122			as = EdubarUtils.getUserRowName(a.sr) + ';' + (a.cr ? a.cr.name : '');
123			bs = EdubarUtils.getUserRowName(b.sr) + ';' + (b.cr ? b.cr.name : '');
124			return as.localeCompare(bs)*sortDirMultiplier;
125		} else 
126		if (!field || field == 'class') {
127			as = (a.cr ? a.cr.name : '') + ';' + EdubarUtils.getUserRowName(a.sr);
128			bs = (b.cr ? b.cr.name : '') + ';' + EdubarUtils.getUserRowName(b.sr);
129			
130		} else {
131			as = a[field] || b[field] === 0 ? a[field] : '';
132			bs = b[field] || b[field] === 0 ? b[field] : '';
133			 				
134		}
135		
136		var ret = 0;
137		if (numeric && ETestUtils.isNumeric(as) && ETestUtils.isNumeric(bs)) {
138			ret = as*1 - bs*1; 					
139		} else {
140			ret = (as || "").toString().localeCompare((bs || "").toString());
141		}
142		return ret*sortDirMultiplier;				
143	});
144
145	return rows;
146}
147
148ETestUtils.initContentEditable = function(element, options) {
149	if (!options) options = {};
150	
151	element.toggleClass('etest-contenteditable',true);
152	element.off('focus.etestcontenteditable').off('click.etestcontenteditable').off('mousedown.etestcontenteditable');
153	
154	if (options.plainText) {
155		element.attr('contenteditable',true);
156		var that = element.get(0);
157		element.on('keydown', function(event) {			
158			var keycode = event.which;			
159			if (keycode == 38 && EdubarUtils.mozePreskocit(that,'hore',event)) {					
160				event.stopPropagation();	
161				
162				ETestUtils.contentEditableFocusPrev(that);
163				event.preventDefault();		
164			} else if ((keycode == 40 && EdubarUtils.mozePreskocit(that,'dole',event)) || keycode == 9) {						
165				event.stopPropagation();
166				
167				ETestUtils.contentEditableFocusNext(that);		
168				event.preventDefault();				
169			} else if (keycode == 13) {
170				if (options.onKeyEnter && !event.shiftKey && !event.ctrlKey) {
171					event.stopPropagation();
172					event.preventDefault();	
173					options.onKeyEnter.call(that);
174				}
175			} 	 
176		}).on('keyup', function(event) {
177			var keycode = event.which;		
178			if (keycode == 8) {				
179				if (options.onKeyBackspace) {						
180					options.onKeyBackspace.call(that, event);
181				}
182			}
183		}).on('focus',function() {
184			$(this).data('contentBeforeEdit', $(this).html());
185		}).on('blur keyup paste input', function(event) {
186			var $this = $(this);
187			var cnt = $this.html();
188			
189			if ($this.data('contentBeforeEdit') != cnt) {
190				
191          	  	$this.data('contentBeforeEdit', cnt);
192				$this.trigger('contentchange');
193			}
194		});		
195	} else {
196		element.toggleClass('etest-contenteditable',true);
197		var mouseDownEvent = null;
198		if (element.html() == '') {			
199			element.html('<div></div>');				
200		}
201		
202		if (true && (element.closest('.etestw').length>0 || element.hasClass('etest-cardnotes-editor'))) {	
203			element.data('ckeditorInitOptions',options);
204			ETestUtils.initEditor5mrDelayed(element.get(0), options);
205		} else {
206			element.attr('contenteditable',true);
207			element.on('focusin',function(event) {	
208					
209				if ($(this).data('ckeditorinited')) return;	
210				if ($(this).data('ckeditoriniting')) return;
211				
212				element.data('ckeditoriniting', true);
213				if (mouseDownEvent) {
214					options.triggerMouseDown = mouseDownEvent;
215					mouseDownEvent = null;	
216				}
217				
218				
219				ETestUtils.initEditor5(element.get(0), options);
220				element.data('ckeditoriniting', false);			
221				
222							
223				
224			}).on('mousedown.ckeditorinit',function(event) {
225				if (!$(this).data('ckeditorinited')) {
226					mouseDownEvent = event;
227				}	
228				$(this).off('mousedown.ckeditorinit');
229			});
230		}
231		
232		$j(element).parent().toggleClass('empty',$.trim($j(element).text()) == '');	
233	}	
234}
235
236
237ETestUtils.getGlobalMultirootEditor = function() {
238	return ETestUtils.multirooteditor5Obj;
239}
240
241ETestUtils.setGlobalMultirootEditor = function(val) {
242	if (!val && ETestUtils.multirooteditor5Obj) {
243		ETestUtils.multirooteditor5Obj.destroy();
244
245		ETestUtils._getGlobalMultirootEditorPromise = null;
246	}
247
248	ETestUtils.multirooteditor5Obj = val;
249}
250
251
252ETestUtils.initEditor5mrDelayed = function(elem, options, addToStart) {
253	if (!ETestUtils._editorsToInit) ETestUtils._editorsToInit = [];
254
255	if (addToStart) {
256		ETestUtils._editorsToInit.splice(0, 0, {elem: elem, options: options});
257	} else {
258		ETestUtils._editorsToInit.push({elem: elem, options: options});
259	}
260
261	if (ETestUtils._initEditor5mrDelayedTimeout) clearTimeout(ETestUtils._initEditor5mrDelayedTimeout);
262
263	/*if (ETestUtils.getGlobalMultirootEditor()) {
264		ETestUtils.initEditor5mrProcess0();
265		return;
266	} */
267
268
269	ETestUtils._initEditor5mrDelayedTimeout = setTimeout(function() {
270		ETestUtils.initEditor5mrProcess0();
271	}, 20);
272	
273}
274
275
276ETestUtils.initEditor5mrProcess0x = function(doneFunc) {
277	if (!ETestUtils._editorsToInit) return;
278	if (ETestUtils._editorsToInit.length == 0) return;
279	//if (ETestUtils._editorIniting) return;
280
281	//ETestUtils._editorIniting = true;
282	var item = ETestUtils._editorsToInit[0];
283	ETestUtils._editorsToInit = ETestUtils._editorsToInit.slice(1);
284	var multiElems = null;
285	/*if (ETestUtils._editorsToInit.length>0) {
286		multiElems = [item.elem];
287		for (var i =0;i<ETestUtils._editorsToInit.length;i++) {
288			multiElems.push(ETestUtils._editorsToInit[i].elem);
289		}
290	}*/
291
292	ETestUtils.initEditor5mr(item.elem, item.options, function() {
293		//ETestUtils._editorIniting = false;
294		setTimeout(function() {
295			ETestUtils.initEditor5mrProcess0x();
296		},20);
297	}, multiElems);
298	
299}
300
301
302
303ETestUtils.initEditor5mrProcess0 = function(ts) {
304	if (!ETestUtils._editorsToInit) return;
305	if (ETestUtils._editorsToInit.length == 0) return;
306	//if (ETestUtils._editorIniting) return;
307
308	//ETestUtils._editorIniting = true;
309	var item = ETestUtils._editorsToInit[0];
310	ETestUtils._editorsToInit = ETestUtils._editorsToInit.slice(1);
311	var multiElems = null;
312	/*if (ETestUtils._editorsToInit.length>0) {
313		multiElems = [item.elem];
314		for (var i =0;i<ETestUtils._editorsToInit.length;i++) {
315			multiElems.push(ETestUtils._editorsToInit[i].elem);
316		}
317	}*/
318
319	if (!ts) ts = Date.now();
320
321	ETestUtils.initEditor5mr(item.elem, item.options, function() {
322		//ETestUtils._editorIniting = false;
323		if (Date.now() - ts > 100) {
324			setTimeout(function() {
325				ETestUtils.initEditor5mrProcess0();
326			},20);
327		} else {		
328			ETestUtils.initEditor5mrProcess0(ts);
329		}
330	}, multiElems);
331	
332}
333
334
335ETestUtils.initGlobalMultiRootEditor = function(rootName, elem, options) {
336	return new Promise(function(resolve, reject) {
337		if (ETestUtils.getGlobalMultirootEditor()) {
338
339			var editor = ETestUtils.getGlobalMultirootEditor();
340			if (!$('#etestckeditortoolbar').data('ckeditorObj')) {
341				ETestUtils.reinitedMREditor = true;
342				$('#etestckeditortoolbar').data('ckeditorObj', editor);
343				$('#etestckeditortoolbar').append($(editor.ui.view.toolbar.element));//.closest('.ck-body'));	
344				
345				
346				editor.model.change(function(writer) {
347					writer.setSelection(null);
348				});
349			}
350			
351
352
353			resolve(editor);
354			return;
355		} 
356		if (ETestUtils._getGlobalMultirootEditorPromise) {
357			ETestUtils._getGlobalMultirootEditorPromise.then(function(res) {				
358				resolve(ETestUtils.getGlobalMultirootEditor());
359			})
360			return;
361		}
362		barJsLibraryLoad('/global/pics/js/ckeditor5/ckeditor.multiroot.es6.js', function() {
363			var toolbarItems = [];
364			if (MobileAppBridge.isActive()) {
365				toolbarItems = [							
366					
367					'bold',
368					'italic',
369					'underline',				
370					'strikethrough',
371					'|',
372					'alignment',
373					'fontcolor',
374					
375					'numberedList',
376					'bulletedList',
377					'|',
378					'outdent', 'indent',
379					'|',
380					'fontsize',												
381					'fontbackgroundcolor',
382					'link',
383					
384					'superscript',
385					'subscript',				
386					'|',
387					'code',
388					'blockquote',
389					'codeBlock',				
390					'ascInsertMath'
391				]
392			} else
393			if (false && MobileAppBridge.isActive()) {
394				//'heading',
395				toolbarItems = [	
396					'bold', 'italic','alignment', 
397					{
398						// This drop-down uses a default icon because none was specified.
399						label: '',					
400						items: ['underline','strikethrough','superscript','subscript']
401					},
402					'|',
403					{
404						// This drop-down uses a default icon because none was specified.
405						label: 'Fonts',
406						icon: '<svg viewBox="0 0 20 20"><path d="M9.816 11.5 7.038 4.785 4.261 11.5h5.555Zm.62 1.5H3.641l-1.666 4.028H.312l5.789-14h1.875l5.789 14h-1.663L10.436 13Z"></path><path d="m12.09 17-.534-1.292.848-1.971.545 1.319L12.113 17h-.023Zm1.142-5.187.545 1.319L15.5 9.13l1.858 4.316h-3.45l.398.965h3.467L18.887 17H20l-3.873-9h-1.254l-1.641 3.813Z"></path></svg>',
407						items: [ 'fontSize', 'fontcolor', 'fontbackgroundcolor','code' ]
408					},
409					{
410						// This drop-down uses a default icon because none was specified.
411						label: 'Align',
412						icon: '<svg viewBox="0 0 20 20"><path d="m2.315 14.705 2.224-2.24a.689.689 0 0 1 .963 0 .664.664 0 0 1 0 .949L2.865 16.07a.682.682 0 0 1-.112.089.647.647 0 0 1-.852-.051L.688 14.886a.635.635 0 0 1 0-.903.647.647 0 0 1 .91 0l.717.722zm5.185.045a.75.75 0 0 1 .75-.75h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75zM2.329 5.745l2.21-2.226a.689.689 0 0 1 .963 0 .664.664 0 0 1 0 .95L2.865 7.125a.685.685 0 0 1-.496.196.644.644 0 0 1-.468-.187L.688 5.912a.635.635 0 0 1 0-.903.647.647 0 0 1 .91 0l.73.736zM7.5 5.75A.75.75 0 0 1 8.25 5h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75z"></path></svg>',
413						items: [ 'numberedList','bulletedList', '|', 'outdent', 'indent', '|','link',
414									'blockquote',
415									'codeBlock',
416									'ascInsertMath']
417					},
418					
419				]
420				
421				//toolbarItems.push('ascInsertMath');
422			} else {
423				toolbarItems = [							
424					'heading',
425					'|',
426					'fontsize',				
427					'|',
428					'bold',
429					'italic',
430					'underline',				
431					'strikethrough',
432					'code',
433					'|',
434					'ascCustomizeTheme',
435					'fontcolor',
436					'fontbackgroundcolor',
437					'|',
438					'superscript',
439					'subscript',
440					'|',
441					'alignment',
442					'|',
443					'numberedList',
444					'bulletedList',
445					'|',
446					'outdent', 'indent',
447					'|',
448					'link',
449					'blockquote',
450					'codeBlock',
451					
452					/*'insertTable',
453					'ascInsertImage',*/
454				]
455				if (edubar && edubar.options && edubar.options.isAsc) {
456					toolbarItems.push('pre');
457					toolbarItems.push('ascInsertImage');
458				}
459				toolbarItems.push('ascInsertMath');
460			}
461
462			
463			var sourceElems = {};		
464			if ($.isPlainObject(rootName)) {
465				sourceElems = rootName;
466			} else {
467				sourceElems[rootName] = elem;
468			}
469			var MultirootEditor = InlineEditor.MultirootEditor;
470			ETestUtils._getGlobalMultirootEditorPromise = MultirootEditor.create(sourceElems, {
471				entities: false,
472				removePlugins: ['ImageCaption'],
473				image: {
474					resizeUnit: 'px'
475				},
476				language: EdubarUtils.getLang() ? EdubarUtils.getLang() : 'en',
477				toolbar: {
478					items: toolbarItems,
479					shouldNotGroupWhenFull: true				
480				},
481				heading: {			 
482					options: [
483						{ model: 'paragraph', title: ls(12034), class: 'ck-heading_paragraph' },
484						{ model: 'heading1', view: 'h1', title: ls(1044)+' 1', class: 'ck-heading_heading1' },
485						{ model: 'heading2', view: 'h2', title: ls(1044)+' 2', class: 'ck-heading_heading2' },
486						{ model: 'heading3', view: 'h3', title: ls(1044)+' 3', class: 'ck-heading_heading3' },
487						{ model: 'heading4', view: 'h4', title: ls(1044)+' 4', class: 'ck-heading_heading4' }			
488					] 		
489				},
490				table: {
491					contentToolbar: [
492						'tableColumn', 'tableRow', 'mergeTableCells',
493						'tableProperties', 'tableCellProperties'
494					]
495				}
496			}).then(function(editor) {
497				ETestUtils.setGlobalMultirootEditor(editor);
498				$('#etestckeditortoolbar').data('ckeditorObj',editor);
499				$('#etestckeditortoolbar').append($(editor.ui.view.toolbar.element));//.closest('.ck-body'));			
500			
501				$('#etestckeditortoolbar').on('remove', function() {	
502					if (!MobileAppBridge.isActive()) {			
503						ETestUtils.setGlobalMultirootEditor(null);
504					}
505				});
506
507				$('#etestckeditortoolbar').closest('.etest-return-div').on('viewclosed', function() {					
508					//ETestUtils.setGlobalMultirootEditor(null);
509				});
510
511				editor.editing.view.document.on( 'clipboardInput', function( evt, data ) {
512					if ( editor.isReadOnly ) {
513						return;
514					}
515					
516					var dataTransfer = data.dataTransfer;
517					if (!dataTransfer.getData( 'text/plain' )) {
518						evt.stop();
519					}			
520					var val = dataTransfer.getData( 'text/html' );
521					if (val) {
522
523						var elem = $('<div>'+val+'</div>');
524						
525						if (elem.find('li div, li p, li h1, li h2, li h3, li h4').length > 0) {
526
527							function removeBlocks0(e) {
528								
529								var blocks = e.find('div, p, h1, h2, h3, h4');
530								blocks.each(function() {
531									$(this).replaceWith($(this).text()+'<br>');
532								})						
533							}
534
535							elem.find('li').each(function() {
536								removeBlocks0($(this));
537							});					
538							val = elem.html();
539							evt.stop();					
540							editor.plugins.get( 'Clipboard' ).fire( 'inputTransformation', { content:editor.data.processor.toView( val ) } );
541						}	
542					}
543
544				}, {'priority':'high'});
545				
546				function handleVArrow(data, cancel) {
547					var elem0 = data.domTarget;
548					var smer = data.keystroke == 38 ? 'hore' : 'dole';
549					var tableElem = $(elem0).closest('.etest-table-inner');
550					var options = $(elem0).data('ckeditorOptions');
551					if (tableElem.length > 0) {
552						
553						if (EdubarUtils.mozePreskocit(elem0,smer,data.domEvent)) {
554							cancel();					
555							var td = $(elem0).closest('td');
556
557							var lastEditable = tableElem.find('td[data-j="'+td.attr('data-j')+'"]').filter(function() {
558								if (smer == 'hore' && $(this).attr('data-i')*1>=td.attr('data-i')) return false;
559								if (smer == 'dole' && $(this).attr('data-i')*1<=td.attr('data-i')) return false;
560								return true;
561							}).find('.etest-contenteditable');
562							lastEditable = smer == 'hore' ? lastEditable.last() : lastEditable.first();
563							if (lastEditable.length > 0) {
564								
565								ETestUtils.focusContentEditable(lastEditable.get(0), smer == 'hore' ? 'zaciatok' : 'koniec');
566							} else {
567								ETestUtils.contentEditableFocusSmer(smer, smer == 'hore' ? tableElem.find('.etest-contenteditable').first().get(0) : tableElem.find('.etest-contenteditable').last().get(0), smer == 'hore' ? 'zaciatok' : 'koniec');
568							}
569						}
570					} else {
571
572						if (EdubarUtils.mozePreskocit(elem0,smer,data.domEvent)) {
573							cancel();
574							var focusElem = ETestUtils.contentEditableFocusSmer(smer, elem0, smer == 'hore' ? 'koniec' : 'zaciatok');
575							if (!focusElem && options && options.focusSmerFunc) {
576								options.focusSmerFunc(smer);
577							}
578						}
579					}
580				}
581
582				function handleHArrow(data, cancel) {
583					var elem0 = data.domTarget;
584					var smer = data.keystroke == 37 ? 'hore' : 'dole';
585					var tableElem = $(elem0).closest('.etest-table-inner');
586					
587					if (tableElem.length > 0) {
588						if (EdubarUtils.mozePreskocit(elem0,smer,data.domEvent)) {
589							cancel();
590												
591							var td = $(elem0).closest('td');
592
593							var lastEditable = tableElem.find('td[data-i="'+td.attr('data-i')+'"]').filter(function() {							
594								if (smer == 'dole' && $(this).attr('data-j')*1 <= td.attr('data-j')) return false;
595								if (smer == 'hore' && $(this).attr('data-j')*1 >= td.attr('data-j')) return false;
596								return true;
597							}).find('.etest-contenteditable');
598							
599							lastEditable = smer == 'hore' ? lastEditable.last() : lastEditable.first();
600							
601							if (lastEditable.length > 0) {						
602								ETestUtils.focusContentEditable(lastEditable.get(0), smer == 'hore' ? 'zaciatok' : 'koniec');
603							} else {
604								
605							}
606						}				
607					}
608				}
609				
610
611				editor.keystrokes.set([38], function(data, cancel) {				
612					handleVArrow(data, cancel);
613				});
614				editor.keystrokes.set([40], function(data, cancel) {				
615					handleVArrow(data, cancel);
616				});
617
618
619				editor.keystrokes.set([37], function(data, cancel) {				
620					handleHArrow(data, cancel);
621				});					
622				editor.keystrokes.set([39], function(data, cancel) {				
623					handleHArrow(data, cancel);
624				});					
625				
626				editor.keystrokes.set([9], function(data, cancel) {
627					var elem0 = data.domTarget;
628					var nextElem =  ETestUtils.contentEditableFocusNext(elem0);
629					if (nextElem) {
630						cancel();				
631					}
632				});
633				
634				editor.keystrokes.set(['shift',9], function(data, cancel) {
635					var elem0 = data.domTarget;				
636					var options = $(elem0).data('ckeditorOptions');
637					cancel();
638					if (options && options.onKeyTab && (data.shiftKey || $j(elem0).closest('.etest-table').length > 0)) {
639						var isHandled = options.onKeyTab.call(elem0, editor, data, cancel);
640						if (isHandled) {
641							return;
642						}
643					}
644				});
645				
646				editor.listenTo( editor.editing.view.document, 'enter', function( evt, data ) {
647					var elem0 = data.domTarget;
648					var options = $(elem0).data('ckeditorOptions');
649
650					if (options && options.onKeyEnterHandler && !data.shiftKey && !data.ctrlKey) {				
651						options.onKeyEnterHandler.call(elem0, editor, data.domEvent, function() {
652							data.preventDefault();
653							data.stopPropagation();
654							evt.stop();
655						});
656					} else
657					if (options && options.onKeyEnter && !data.shiftKey && !data.ctrlKey && EdubarUtils.mozePreskocit(elem0,'dole')) {				
658						data.preventDefault();
659						data.stopPropagation();
660						evt.stop();
661						options.onKeyEnter.call(elem0);
662					}
663					
664				}, {priority: 'highest'}); 
665				
666				editor.keystrokes.set([13], function(data, cancel) {
667					
668					var elem0 = data.domTarget;
669					var options = $(elem0).data('ckeditorOptions') || {};
670
671					if (options.onKeyEnter && !data.shiftKey && !data.ctrlKey && EdubarUtils.mozePreskocit(elem0,'dole')) {
672						
673						cancel();
674						
675						var doc = editor.model.document;
676						var root = doc.getRoot($(elem0).data('ckrootName') || 'main');
677						
678						editor.model.change(function(writer) {				
679							if (root.childCount > 0) {
680								var lastChild = root.childCount > 0 ? root.getChild(root.childCount-1) : root;
681							
682								writer.setSelection( lastChild, 'end');
683							} else {
684								writer.setSelection( root, 'in');
685							}
686						} );
687						
688					}
689				}, {priority: 'highest'});
690				
691				
692				editor.model.on('ascUndoChanged',function(data, op) {				
693					var pos = op.position || (op.range && op.range.start) || op.sourcePosition || op.targetPosition || op.deletionPosition || op.insertionPosition || op.splitPosition || op.graveyardPosition || op.moveTargetPosition || null;
694					if (!pos) {					
695						return;
696					}
697					var rootName = pos.root.rootName;
698					var elem0 = ETestUtils.ckroots[rootName];
699					if (!elem0) {					
700						return;
701					}
702					var etestw = $(elem0).closest('.etestw').data('etestWidget');
703					if (!etestw) {					
704						return;
705					} 
706					var options = $(elem0).data('ckeditorOptions') || {};
707
708					if (options && options.processUndo === false) return;
709
710					var dataBefore = $.extend({}, $j(elem0).data('ckDataBefore'));
711					var editorData = $j(elem0).data('ckeditorData')
712
713					var getEditorData = $j(elem0).data('getEditorDataFunc');
714					
715					$j(elem0).trigger('undochange');
716					
717					etestw.performChange(function() {
718					
719						$j(elem0).data('ckDataBefore',etestw.prepareLaterChange());
720						$j(elem0).data('ckeditorData', getEditorData());
721
722						
723					}, dataBefore, editorData);
724
725					
726					
727					setTimeout(function() {									
728						$j(elem0).parent().toggleClass('etest-editable-parent-empty',$.trim($j(elem0).text()) == '').toggleClass('empty',$.trim($j(elem0).text()) == '');
729					},10);
730					
731				});
732				editor.commands.get('undo').on('execute',function(data, evt) {
733					
734					
735				});
736				
737				editor.commands.get('redo').on('execute',function(data, evt) {
738					
739				});
740				
741				
742				var positionChangeTimeout = null;
743				var lastSelectionRef = {current: null};
744				var lastPositionChangeTs = null;
745				function triggerPositionChange() {
746					/*if (!lastPositionChangeTs || Date.now() > lastPositionChangeTs + 500) {
747						triggerPositionChange0();
748						return;
749					}*/
750					
751					if (positionChangeTimeout) clearTimeout(positionChangeTimeout);
752					positionChangeTimeout = setTimeout(function() {
753						positionChangeTimeout = null;
754						triggerPositionChange0();
755					},Math.max(10, Math.min(500, 500 - Date.now() - lastPositionChangeTs)));
756				}
757
758				function triggerPositionChange0() {
759					var selection = lastSelectionRef.current;
760					if (!selection) return;
761
762					
763
764				
765					
766					var position = selection.getFirstPosition();
767					var viewPosition = editor.editing.mapper.toViewPosition(position);
768					var rootName = position.root.rootName;
769					var elem0 = ETestUtils.ckroots[rootName];
770					if ($(elem0).data('cardEditorSelectionItem') && $(elem0).closest('body').length >0) {
771						var selItem = $(elem0).data('cardEditorSelectionItem');
772						lastPositionChangeTs = Date.now();
773					
774						ETestUtils.lastEditorSelection = {
775							domElement: selItem.domElement,
776							qelem: selItem.qelem,
777							selectedText: selItem.selectedText							
778						};
779						
780						$(window).trigger('etestEditorSelectionChange', [selItem.domElement, selItem.qelem, selItem.selectedText, null, null]);
781						
782						return;
783
784					}
785					
786					var selectedText = '';
787					var domElem = null;
788					var qelem = null;
789					if (!viewPosition) {
790						
791					} else {
792						var domRange = null;
793						try {
794							domRange = editor.editing.view.domConverter.viewRangeToDom(
795								editor.editing.view.createRange(viewPosition, viewPosition)
796							);
797						} catch (e) {
798							return;
799						}
800						if (!domRange) return;
801
802						domElement = domRange.startContainer;
803						qelem = $(domElement).closest('.etest-question');
804
805						if ($(domElement).closest('.etestw.selected').length ==0) return;
806						
807						if (selection.isCollapsed) {
808							
809							selectedText = $(domElement).closest('li,p,div,pre,h1,h2,h3,h4,h5,h6').text()
810						} else {
811							
812							var range = selection.getFirstRange();
813						
814
815							if (range) {								
816								var modelFragment = editor.model.getSelectedContent(selection);								
817								selectedText = $.trim(undoet(editor.data.stringify(modelFragment)));
818							}
819
820						}
821					}
822
823					lastPositionChangeTs = Date.now();
824					
825					ETestUtils.lastEditorSelection = {
826						domElement: domElement,
827						qelem: qelem.get(0),
828						selectedText: selectedText							
829					};
830					
831					$(window).trigger('etestEditorSelectionChange', [domElement, qelem.get(0), selectedText, selection, editor]);
832					
833					
834				}
835				
836				
837				editor.model.document.on( 'change', function(data, evt) {	
838					var selection = editor.model.document.selection;
839					lastSelectionRef.current = selection;
840					triggerPositionChange();
841					
842					if (!evt.operations) return;
843					var elem0 = null;
844					for (var i=0;i<evt.operations.length;i++) {
845						var op = evt.operations[i];
846						if (!op) {					
847							continue;
848						}
849						var pos = op.position || (op.range && op.range.start) || op.sourcePosition || op.targetPosition || op.deleti
849onPosition || op.insertionPosition || op.splitPosition || op.graveyardPosition || op.moveTargetPosition || null;
850						if (!pos) {
851							
852							continue;	
853						}
854						
855						var rootName = pos.root.rootName;
856						elem0 = ETestUtils.ckroots[rootName];
857						if (elem0) break;
858					}
859					if (!elem0) {					
860						return;
861					}
862
863					var html =  editor.getData({rootName: $(elem0).data('ckrootName') || 'main'})
864					if (($j(elem0).data('ckeditorHtml') || $j(elem0).data('ckeditorHtml') === '') && html != $j(elem0).data('ckeditorHtml')) {														
865						setTimeout(function() {				
866							$j(elem0).parent().toggleClass('etest-editable-parent-empty',$.trim($j(elem0).text()) == '').toggleClass('empty',$.trim($j(elem0).text()) == '');
867						},10);
868						
869						$j(elem0).trigger('contentchange');					
870						$j(elem0).data('ckeditorHtml', html);
871					}
872				});
873
874				//ETestUtils._getGlobalMultirootEditorPromise = null;			
875				resolve(editor);
876			});
877		});
878	});
879}
880
881ETestUtils.lastEditorSelection = null;
882
883ETestUtils.getEditorEidForElem = function(domElement) {
884	if (!domElement) return null;
885	var $domElement = $(domElement);
886	var eid = null;
887	if ($domElement.closest('.etest-alist-answer[data-answerid]').length) {
888		eid = $domElement.closest('.etest-alist-answer[data-answerid]').attr('data-answerid');
889		return eid;
890	}
891
892	var eidElem = $domElement.closest('*[data-eid]');
893	if (eidElem.length == 0) return null;
894	eid = eidElem.attr('data-eid');
895
896	return eid;
897}
898
899ETestUtils.initEditor5mr = function(elem, options, doneFunc, multiElems) {
900	var that = elem;
901	
902	if ($j(elem).data('ckeditorObj') && $(elem).data('ckrootName')) {
903		if (doneFunc) doneFunc($j(elem).data('ckeditorObj'));
904		return;
905	}
906	
907	if ($(elem).closest('body').length ==0) {		
908		//nemozeme inicializovat nieco co nie je v body
909		
910		if (doneFunc) doneFunc(null);
911		return;
912	}
913
914	var etestw = $(elem).closest('.etestw').data('etestWidget');
915
916	var elems = multiElems ? multiElems : [elem];
917
918	var sourceNames = {};
919	for (var i=0;i<elems.length;i++) {
920
921		var elem0 = elems[i];
922
923		if (!ETestUtils.ckeditorNumRoots) ETestUtils.ckeditorNumRoots = 0;
924		ETestUtils.ckeditorNumRoots++;
925		var rootName = 'ckr'+ETestUtils.ckeditorNumRoots;
926		if (etestw) {
927			qw = etestw.getQuestionWidget();
928			if (qw) {
929				rootName = 'qw'+qw.id+'_'+rootName;
930			}
931		}
932		
933
934
935		$(elem0).data('ckrootName',rootName);
936		if (!ETestUtils.ckroots) ETestUtils.ckroots = {};
937		ETestUtils.ckroots[rootName] = elem0;
938		sourceNames[rootName] = elem0;		
939	}
940	
941
942	
943
944
945	ETestUtils.initGlobalMultiRootEditor(sourceNames, elem, options).then(function(editor) {
946		try {
947			editor.addSourceElement(rootName, elem);
948		} catch (e) {
949			//console.log(e);
950		}
951
952		$j(elem).data('ckeditorObj',editor);
953		$j(elem).data('ckeditorinited', true);
954		$j(elem).data('ckeditorOptions',options);
955		$j(elem).removeAttr("title");		
956
957		$j(elem).parent().toggleClass('etest-editable-parent-empty',$.trim($j(elem).text()) == '').toggleClass('empty',$.trim($j(elem).text()) == '');
958								
959		
960		$j(elem).toggleClass('ckeditorInited',true);
961
962		initEtestwUndo(elem);
963
964		//setTimeout(function() {
965		ETestUtils._initingGlobalMultirootEditor = false;
966		$j(that).trigger('ckeditorInited');
967		
968		if (doneFunc) doneFunc(editor);
969		//},10);
970
971		
972		
973		
974	});
975		
976	$j(elem).on('remove',function() {		
977		var editor = $j(elem).data('ckeditorObj');
978		if (editor) {
979			editor.removeSourceElement($(elem).data('ckrootName'));			
980		}
981	});
982
983	function initEtestwUndo(elem) {
984		var etestw = $(elem).closest('.etestw').data('etestWidget');
985		if (!etestw) return;
986		var editor = ETestUtils.getGlobalMultirootEditor();				
987		function getEditorData() {
988			//var editor = ETestUtils.getGlobalMultirootEditor();
989			var ed = {};
990			
991			ed.selectionRanges = editor.model.document.selection.getRanges();
992			ed.selectionPosition = editor.model.document.selection.getLastPosition();
993			ed.contentEditable = $(elem);
994			ed.editor = editor;
995			
996			var ind = 0;
997			
998			etestw.element.find('.etest-contenteditable').each(function() {
999				if (this == elem) {
1000					return false;
1001				}
1002				ind++;
1003			});
1004			
1005			
1006			ed.contentEditableIndex = ind;
1007			
1008			return ed;
1009		}
1010				
1011					
1012		$j(elem).data('getEditorDataFunc',getEditorData);
1013					
1014		$j(elem).data('ckDataBefore',etestw.prepareLaterChange());
1015		$j(elem).data('ckeditorData', getEditorData());
1016		$j(elem).data('ckeditorHtml', editor.getData({rootName: $(elem).data('ckrootName') || 'main'}));
1017	}
1018
1019	
1020	return;	
1021}
1022
1023ETestUtils.initEditor5 = function(elem, options) {
1024	var that = elem;
1025	
1026	var toolbarItems = [							
1027		'heading',
1028		'|',
1029		'fontsize',				
1030		'|',
1031		'bold',
1032		'italic',
1033		'underline',				
1034		'strikethrough',
1035		'code',
1036		'|',
1037		'fontcolor',
1038		'fontbackgroundcolor',
1039		'|',
1040		'superscript',
1041		'subscript',
1042		'|',
1043		'alignment',
1044		'|',
1045		'numberedList',
1046		'bulletedList',
1047		'|',
1048		'outdent', 'indent',
1049		'|',
1050		'link',
1051		'blockquote',
1052		'codeBlock',
1053		
1054		/*'insertTable',
1055		'ascInsertImage',*/
1056	]
1057	if (edubar && edubar.options && edubar.options.isAsc) {
1058		toolbarItems.push('pre');
1059		toolbarItems.push('ascInsertImage');
1060	}
1061	toolbarItems.push('ascInsertMath');
1062	/*if (options && options.onAscInsertObject) {
1063		toolbarItems.push('ascInsertObject');
1064	}*/
1065	
1066	InlineEditor.create(elem, {
1067		
1068		entities: false,
1069		removePlugins: ['ImageCaption'],
1070		image: {
1071			resizeUnit: 'px'
1072		},
1073	 	language: EdubarUtils.getLang() ? EdubarUtils.getLang() : 'en',
1074		toolbar: {
1075			items: toolbarItems,
1076			shouldNotGroupWhenFull: true
1077		},
1078		heading: {			 
1079 			options: [
1080 				{ model: 'paragraph', title: ls(12034), class: 'ck-heading_paragraph' },
1081 				{ model: 'heading1', view: 'h1', title: ls(1044)+' 1', class: 'ck-heading_heading1' },
1082 				{ model: 'heading2', view: 'h2', title: ls(1044)+' 2', class: 'ck-heading_heading2' },
1083				{ model: 'heading3', view: 'h3', title: ls(1044)+' 3', class: 'ck-heading_heading3' },
1084				{ model: 'heading4', view: 'h4', title: ls(1044)+' 4', class: 'ck-heading_heading4' }			
1085 			] 		
1086		},
1087		table: {
1088            contentToolbar: [
1089                'tableColumn', 'tableRow', 'mergeTableCells',
1090                'tableProperties', 'tableCellProperties'
1091            ]
1092		}
1093	}).then(function(editor) {		
1094		$j(that).data('ckeditorObj',editor);
1095		$j(that).data('ckeditorinited', true);
1096		
1097		$j(elem).removeAttr("title");		
1098	
1099		var $elem = $j(elem); 
1100		var isDown = false;
1101		var wasAtStart = false;
1102		
1103		
1104		editor.editing.view.document.on( 'clipboardInput', function( evt, data ) {
1105		    if ( editor.isReadOnly ) {
1106		        return;
1107		    }
1108		    
1109		    var dataTransfer = data.dataTransfer;
1110			if (!dataTransfer.getData( 'text/plain' )) {
1111				evt.stop();
1112			}			
1113			var val = dataTransfer.getData( 'text/html' );
1114			if (val) {
1115
1116				var elem = $('<div>'+val+'</div>');
1117				
1118				if (elem.find('li div, li p, li h1, li h2, li h3, li h4').length > 0) {
1119
1120					function removeBlocks0(e) {
1121						
1122						var blocks = e.find('div, p, h1, h2, h3, h4');
1123						blocks.each(function() {
1124							$(this).replaceWith($(this).text()+'<br>');
1125						})						
1126					}
1127
1128					elem.find('li').each(function() {
1129						removeBlocks0($(this));
1130					});					
1131					val = elem.html();
1132					evt.stop();					
1133					editor.plugins.get( 'Clipboard' ).fire( 'inputTransformation', { content:editor.data.processor.toView( val ) } );
1134				}	
1135			}
1136
1137		}, {'priority':'high'});
1138
1139		if (options && options.onAscInsertObject) {
1140			editor.on('ascInsertObject', function(evt, data) {							
1141				options.onAscInsertObject(data);				
1142			});
1143		}
1144		
1145		
1146		var tableElem = $(elem).closest('.etest-table-inner');
1147		if (tableElem.length > 0) {
1148			
1149			var td = $(elem).closest('td');
1150			
1151			editor.keystrokes.set([38], function(data, cancel) {
1152				
1153				if (EdubarUtils.mozePreskocit(that,'hore',data.domEvent)) {
1154					cancel();					
1155					
1156					//ETestUtils.contentEditableFocusPrev(that);
1157					
1158					var lastEditable = tableElem.find('td[data-j="'+td.attr('data-j')+'"]').filter(function() {
1159						if ($(this).attr('data-i')*1>=td.attr('data-i')) return false;
1160						return true;
1161					}).find('.etest-contenteditable').last();
1162					
1163					if (lastEditable.length > 0) {
1164						
1165						ETestUtils.focusContentEditable(lastEditable.get(0), 'zaciatok');
1166					} else {
1167						ETestUtils.contentEditableFocusPrev(tableElem.find('.etest-contenteditable').first().get(0), 'zaciatok');
1168					}
1169				}
1170			});
1171			
1172			editor.keystrokes.set([40], function(data, cancel) {
1173				
1174				if (EdubarUtils.mozePreskocit(that,'dole',data.domEvent)) {
1175					cancel();
1176					
1177					//ETestUtils.contentEditableFocusNext(that);
1178					
1179					var lastEditable = tableElem.find('td[data-j="'+td.attr('data-j')+'"]').filter(function() {
1180						if ($(this).attr('data-i')*1<=td.attr('data-i')) return false;
1181						return true;
1182					}).find('.etest-contenteditable').first();
1183					
1184					if (lastEditable.length > 0) {						
1185						ETestUtils.focusContentEditable(lastEditable.get(0), true);
1186					} else {
1187						ETestUtils.contentEditableFocusNext(tableElem.find('.etest-contenteditable').last().get(0), null, true);
1188					}
1189				}				
1190			});
1191			
1192			
1193			editor.keystrokes.set([37], function(data, cancel) {
1194				
1195				if (EdubarUtils.mozePreskocit(that,'hore',data.domEvent)) {
1196					cancel();
1197					
1198					//ETestUtils.contentEditableFocusNext(that);
1199					
1200					var lastEditable = tableElem.find('td[data-i="'+td.attr('data-i')+'"]').filter(function() {
1201						if ($(this).attr('data-j')*1 >= td.attr('data-j')) return false;
1202						return true;
1203					}).find('.etest-contenteditable').last();
1204					
1205					if (lastEditable.length > 0) {						
1206						ETestUtils.focusContentEditable(lastEditable.get(0), 'zaciatok');
1207					} else {
1208						
1209					}
1210				}				
1211			});
1212			
1213			editor.keystrokes.set([39], function(data, cancel) {
1214				
1215				if (EdubarUtils.mozePreskocit(that,'dole',data.domEvent)) {
1216					cancel();
1217					
1218					//ETestUtils.contentEditableFocusNext(that);
1219					
1220					var lastEditable = tableElem.find('td[data-i="'+td.attr('data-i')+'"]').filter(function() {
1221						if ($(this).attr('data-j')*1 <= td.attr('data-j')) return false;
1222						return true;
1223					}).find('.etest-contenteditable').first();
1224					
1225					if (lastEditable.length > 0) {						
1226						ETestUtils.focusContentEditable(lastEditable.get(0), true);
1227					} else {
1228						
1229					}
1230				}				
1231			});
1232		} else {
1233			
1234			editor.keystrokes.set([38], function(data, cancel) {
1235				
1236				if (EdubarUtils.mozePreskocit(that,'hore',data.domEvent)) {
1237					cancel();
1238					ETestUtils.contentEditableFocusPrev(that, 'zaciatok');
1239				}
1240			});
1241			
1242			editor.keystrokes.set([40], function(data, cancel) {
1243				
1244				if (EdubarUtils.mozePreskocit(that,'dole',data.domEvent)) {
1245					cancel();
1246					ETestUtils.contentEditableFocusNext(that, null, true);
1247				}
1248			});
1249			
1250		}
1251		
1252		editor.keystrokes.set([9], function(data, cancel) {
1253			
1254			var nextElem =  ETestUtils.contentEditableFocusNext(that);
1255			if (nextElem) {
1256				cancel();				
1257			}
1258		});
1259		
1260		editor.keystrokes.set(['shift',9], function(data, cancel) {
1261			cancel();
1262			if (options.onKeyTab && (data.shiftKey|| $j(that).closest('.etest-table').length > 0)) {
1263				var isHandled = options.onKeyTab.call(that, editor, data, cancel);
1264				if (isHandled) {
1265					return;
1266				}
1267			}
1268		});
1269		
1270		editor.listenTo( editor.editing.view.document, 'enter', function( evt, data ) {
1271			if (options.onKeyEnterHandler && !data.shiftKey && !data.ctrlKey) {				
1272				options.onKeyEnterHandler.call(that, editor, data.domEvent, function() {
1273					data.preventDefault();
1274					data.stopPropagation();
1275					evt.stop();
1276				});
1277			} else
1278			if (options.onKeyEnter && !data.shiftKey && !data.ctrlKey && EdubarUtils.mozePreskocit(that,'dole')) {				
1279				data.preventDefault();
1280				data.stopPropagation();
1281				evt.stop();
1282				options.onKeyEnter.call(that);
1283			}
1284			
1285		}, {priority: 'highest'}); 
1286		
1287		editor.keystrokes.set([13], function(data, cancel) {
1288			
1289			if (options.onKeyEnter && !data.shiftKey && !data.ctrlKey&& EdubarUtils.mozePreskocit(that,'dole')) {
1290				
1291				cancel();
1292				
1293				var doc = editor.model.document;
1294				var root = doc.getRoot();
1295				
1296				editor.model.change(function(writer) {				
1297					if (root.childCount > 0) {
1298						var lastChild = root.childCount > 0 ? root.getChild(root.childCount-1) : root;
1299					
1300				    	writer.setSelection( lastChild, 'end');
1301					} else {
1302				  		 writer.setSelection( root, 'in');
1303					}
1304				} );
1305				
1306			}
1307		}, {priority: 'highest'});
1308		
1309		$(elem).on('remove',function() {
1310			editor.destroy();
1311		});
1312		
1313		
1314		if (!options.useBalloonToolbar) {
1315	
1316			var etestw = $elem.closest('.etestw').data('etestWidget');
1317			
1318			function getEditorData() {
1319				var ed = {};
1320				
1321				ed.selectionRanges = editor.model.document.selection.getRanges();
1322				ed.selectionPosition = editor.model.document.selection.getLastPosition();
1323				ed.contentEditable = $elem;
1324				ed.editor = editor;
1325				
1326				var ind = 0;
1327				
1328				etestw.element.find('.etest-contenteditable').each(function() {
1329					if (this == elem) {
1330						return false;
1331					}
1332					ind++;
1333				});
1334				
1335				
1336				ed.contentEditableIndex = ind;
1337				
1338				return ed;
1339			}
1340			
1341			
1342			$j(that).data('getEditorDataFunc',getEditorData);
1343			
1344			var dataBefore = etestw.prepareLaterChange();
1345			var editorData = getEditorData();
1346			
1347			
1348			editor.model.on('ascUndoChanged',function() {
1349				
1350				if (etestw) {
1351					etestw.performChange(function() {
1352						dataBefore = etestw.prepareLaterChange();
1353						editorData = getEditorData();
1354					}, dataBefore, editorData);
1355				}			
1356				
1357			});
1358			editor.commands.get('undo').on('execute',function() {
1359				
1360				
1361			});
1362			
1363			editor.commands.get('redo').on('execute',function() {
1364				
1365			});
1366		
1367		
1368			
1369			$('#etestckeditortoolbar').append($(editor.ui.view.toolbar.element).closest('.ck-body'));
1370		}
1371		
1372		editor.model.document.on( 'change', function() {
1373			
1374			setTimeout(function() {				
1375				$j(elem).parent().toggleClass('empty',$.trim($j(elem).text()) == '');
1376			},10);
1377			$j(elem).trigger('contentchange');
1378		});
1379		$j(elem).parent().toggleClass('empty',$.trim($j(elem).text()) == '');
1380		
1381		
1382		$j(that).click();	
1383		
1384		if (options.triggerMouseDown) {
1385			var e = options.triggerMouseDown;
1386			var position = ETestUtils.getCaretPositionFromPoint(e.clientX, e.clientY);
1387			
1388			var posv = editor.editing.view.domConverter.domPositionToView(position.node, position.offset);			
1389			var pos = editor.editing.mapper.toModelPosition(posv);
1390			
1391			if (pos) {
1392				editor.model.change(function(writer) {
1393												
1394				  	writer.setSelection( pos.parent, pos.offset);
1395					
1396				} );
1397				
1398			}
1399			setTimeout(function() {
1400				
1401				
1402				
1403				if (pos) {
1404					editor.model.change(function(writer) {
1405													
1406					  	writer.setSelection( pos.parent, pos.offset);
1407						
1408					} );
1409					
1410					
1411					
1412				}
1413				
1414			},10);			
1415		} 
1416
1417		$j(that).trigger('ckeditorInited');
1418		
1419	});
1420	
1421	return;	
1422}
1423
1424ETestUtils.getCaretPositionFromPoint = function(x,y) {
1425	if (document.caretPositionFromPoint) {
1426	    range = document.caretPositionFromPoint(x, y);
1427	    textNode = range.offsetNode;
1428	    offset = range.offset;
1429	  } else if (document.caretRangeFromPoint) {
1430	    range = document.caretRangeFromPoint(x, y);
1431	    textNode = range.startContainer;
1432	    offset = range.startOffset;
1433	  }
1434	  
1435	  return {
1436	  	node: textNode,
1437	  	offset: offset,
1438	  	range: range
1439	  }
1440}
1441
1442ETestUtils.contentEditableFocusNext = function(elem, inElem, kurzorNaKoniec) {
1443	var nextElem = null;
1444	var foundElem = false;
1445	var foundNext = false;
1446	if (!inElem) inElem = $j(elem).closest('.etest-main');
1447	inElem.find('.etest-contenteditable').each(function() {		
1448		nextElem = this;		
1449		if (foundElem) {
1450			foundNext = true;
1451			return false;
1452		}
1453		if (this == elem) {
1454			foundElem = true;								
1455		}
1456	});
1457	if (nextElem) {		
1458		ETestUtils.focusContentEditable(nextElem, kurzorNaKoniec);		
1459	}
1460	
1461	return foundNext ? nextElem : null;
1462}
1463
1464
1465ETestUtils.contentEditableFocusSmer = function(smer, elem, kurzorNaKoniec, inElem) {
1466	if (smer == 'hore') {
1467		return ETestUtils.contentEditableFocusPrev(elem, kurzorNaKoniec, inElem) 
1468	} 
1469	return ETestUtils.contentEditableFocusNext(elem, inElem, kurzorNaKoniec)	 
1470}
1471
1472
1473ETestUtils.focusContentEditable = function(elem, kurzorNaKoniec, retry) {
1474	if (!elem) return;
1475	if (elem.tagName == 'INPUT') {
1476		$(elem).focus().select();
1477	} else
1478	if (!$j(elem).data('ckeditorinited')) {
1479		$j(elem).click();
1480		
1481		ETestUtils.initEditor5mrDelayed($(elem).get(0), $j(elem).data('ckeditorInitOptions'), true);
1482
1483		
1484		$j(elem).focusin().one('ckeditorInited',function() {	
1485				
1486			var editor = $j(elem).data('ckeditorObj');				
1487			if (!editor) return;
1488			editor.editing.view.focus();
1489					
1490			if (kurzorNaKoniec) {	
1491				
1492				var doc = editor.model.document;
1493				var root = $(elem).data('ckrootName') ? doc.getRoot($(elem).data('ckrootName')) : doc.getRoot();
1494				
1495				editor.model.change(function(writer) {				
1496					writer.setSelection( root, 'in');
1497					var range = doc.selection.getFirstRange();
1498					var startRange = editor.model.schema.getNearestSelectionRange( range.start );
1499					var endRange = editor.model.schema.getNearestSelectionRange( range.end );
1500		
1501					range.start = kurzorNaKoniec == 'zaciatok' ? startRange.start : endRange.start;
1502					range.end = kurzorNaKoniec == 'zaciatok' ? startRange.end : endRange.end;
1503					
1504					writer.setSelection( range );
1505				} );
1506				
1507			} else {
1508				
1509					
1510				var doc = editor.model.document;
1511				var root = $(elem).data('ckrootName') ? doc.getRoot($(elem).data('ckrootName')) : doc.getRoot();
1512					
1513				editor.model.change(function(writer) {
1514					writer.setSelection( root, 'in');
1515					var range = doc.selection.getFirstRange();
1516					var startRange = editor.model.schema.getNearestSelectionRange( range.start );
1517					var endRange = editor.model.schema.getNearestSelectionRange( range.end );
1518		
1519					range.start = startRange.start;
1520					range.end = endRange.end;
1521					
1522					writer.setSelection( range );
1523				} );
1524				if (!retry) {
1525					setTimeout(function() {	
1526						ETestUtils.focusContentEditable(elem, kurzorNaKoniec, true);
1527					},20);		
1528				}
1529			}
1530			
1531		});
1532		
1533		
1534	} else {
1535		var editor = $j(elem).data('ckeditorObj');
1536		
1537		if (kurzorNaKoniec) {
1538			var doc = editor.model.document;
1539			var root = $(elem).data('ckrootName') ? doc.getRoot($(elem).data('ckrootName')) : doc.getRoot();
1540			
1541			editor.model.change(function(writer) {
1542							
1543				
1544				writer.setSelection( root, 'in');
1545					var range = doc.selection.getFirstRange();
1546					var startRange = editor.model.schema.getNearestSelectionRange( range.start );
1547	   				var endRange = editor.model.schema.getNearestSelectionRange( range.end );
1548	    
1549					range.start = kurzorNaKoniec == 'zaciatok' ? startRange.start : endRange.start;
1550					range.end = kurzorNaKoniec == 'zaciatok' ? startRange.end : endRange.end;
1551					
1552					writer.setSelection( range );
1553			
1554			} );
1555		} else {
1556			
1557			var doc = editor.model.document;
1558			var root = $(elem).data('ckrootName') ? doc.getRoot($(elem).data('ckrootName')) : doc.getRoot();
1559			
1560			editor.model.change(function(writer) {
1561				
1562			   	writer.setSelection( root, 'in');
1563				var range = doc.selection.getFirstRange();
1564				var startRange = editor.model.schema.getNearestSelectionRange( range.start );
1565				var endRange = editor.model.schema.getNearestSelectionRange( range.end );
1566	
1567				range.start = startRange.start;
1568				range.end = endRange.end;
1569				
1570				writer.setSelection( range );
1571							
1572			} );
1573			
1574		}
1575		editor.editing.view.focus();
1576		$j(elem).click();
1577		
1578	}
1579
1580	ETestUtils.ensureElementInFocusRect($(elem), null, {
1581		scrollContainer: $(elem).scrollParent(),
1582		offsetV: $(window).height()*0.05
1583	});
1584}
1585
1586ETestUtils.contentEditableFocusPrev = function(elem, kurzorNaKoniec, inElem) {
1587	var prevElem = null;
1588	var foundElem = false;
1589	if (!inElem) inElem = $j(elem).closest('.etest-main');
1590	inElem.find('.etest-contenteditable').each(function() {
1591		if (this == elem) {
1592			foundElem = true;
1593			return false;
1594		}
1595		prevElem = this;
1596	});
1597	if (prevElem) {
1598		ETestUtils.focusContentEditable(prevElem, kurzorNaKoniec);		
1599	}
1600	
1601	return foundElem ? prevElem : null;
1602}
1603
1604ETestUtils.cardsData = {};
1605ETestUtils.cacheCardData = function(cardid, row) {
1606	this.cardsData[cardid] = row;
1607}
1608
1609ETestUtils.cacheCardsData = function(cardsData) {
1610	for (var cardid in cardsData) {
1611
1612		var row = cardsData[cardid];
1613		row["content"] = ETestUtils.parseCardContent(row["content"]);
1614		
1615		this.cardsData[cardid] = row;
1616	}
1617}
1618
1619ETestUtils.ge
1619tCardsData = function(cardids, doneFunc, failFunc, req) {		
1620	
1621	var self = this;
1622	var needCardids = [];
1623	
1624	for (var i=0;i<cardids.length;i++) {
1625		var cardid = cardids[i];
1626		if (this.cardsData[cardid]) continue;
1627		if (cardid == 'forceWaiting') continue;
1628		needCardids.push(cardid);
1629	}
1630	
1631	if (needCardids.length == 0) {
1632		doneFunc(self.cardsData);
1633		return;
1634	}
1635	
1636		
1637	var postData = {
1638		cardids: needCardids.join(';')
1639	}
1640	
1641	var jqxhr = $.post('/elearning/?cmd=EtestCreator&akcia=getCardsData',postData, function(data) {								
1642		for (var cardid in data) {
1643			var row = data[cardid];
1644			row["content"] = ETestUtils.parseCardContent(row["content"]);
1645			self.cardsData[cardid] = row;
1646		}
1647		
1648		doneFunc(self.cardsData);			
1649	},'json').fail(function() {
1650		if (failFunc) failFunc();
1651	});
1652	if (failFunc) {
1653		jqxhr.isErrorHandled = true;
1654	}
1655}
1656
1657ETestUtils.parseCardContent = function(content) {	
1658	if (!content) content = '';
1659	if (typeof content != "string") return content;
1660	ret = {};
1661	try {
1662		ret = JSON.parse(content.replace(/&semicolon&/gi,';'));
1663	} catch (e) {
1664		console.log('cannot parse: '+content);
1665	}
1666	return ret;
1667}
1668ETestUtils.getQuestionWidget = function(cardid) {
1669	if (!this.questionWidgets) this.questionWidgets = {};
1670	if (!this.questionWidgets[cardid]) {
1671	
1672		var card = this.cardsData[cardid];
1673		if (!card) return null;
1674		var q = new QuestionETestWidget();
1675		q.loadData(card.content);
1676		q.setCardid(cardid);
1677		this.questionWidgets[cardid] = q;
1678	}
1679	
1680	return this.questionWidgets[cardid];		
1681}
1682
1683ETestUtils.ensureElementInFocusRect = function(elem, rect, options) {			
1684	var scrollContainer = $j(options && options.scrollContainer && $(options.scrollContainer).get(0) != document ? options.scrollContainer : window);
1685	var sl = scrollContainer.scrollLeft();
1686	var st = scrollContainer.scrollTop();
1687	
1688	var co = scrollContainer.offset();
1689	if (!co) co = {left: 0, top: 0};
1690	
1691	var cw = scrollContainer.width();
1692	var ch = scrollContainer.height();
1693	
1694		
1695	var eo = elem.offset();
1696	if (!eo) return;
1697	
1698	
1699	if (scrollContainer.get(0) != window) {
1700		eo.top += st - co.top;
1701		eo.left += sl - co.left;
1702	}
1703	
1704	var ew = elem.outerWidth();
1705	var eh = elem.outerHeight();
1706	
1707	if (!rect) {
1708		var offsetV = options && options.offsetV ?  options.offsetV : 0;
1709		var offsetBottom = options && (options.offsetBottom || options.offsetBottom === 0) ?  options.offsetBottom : offsetV;
1710		var offsetTop = options && (options.offsetTop || options.offsetTop === 0) ?  options.offsetTop : offsetV;
1711		rect = {
1712			x: 0,
1713			y: offsetTop,
1714			width: cw,
1715			height: ch-offsetBottom-offsetTop
1716		}
1717	}
1718	
1719	var setScroll = {};
1720	if (!options || options.useHorizScrolling !== false) {
1721		if (eo.left - sl  < rect.x) {
1722			setScroll.scrollLeft = Math.max(0,eo.left - rect.x - 100);
1723			//scrollContainer.scrollLeft(Math.max(0,eo.left - rect.x - 100)); 
1724		} else if (eo.left + ew - sl  > rect.x+rect.width) {
1725			setScroll.scrollLeft = Math.max(0, (eo.left - cw) + ew + 100 + (cw - rect.x - rect.width));
1726			//scrollContainer.scrollLeft(Math.max(0, (eo.left - cw) + ew + 100 + (cw - rect.x - rect.width)));
1727		}
1728	}
1729	
1730	if ((eo.top) - st < rect.y) {		
1731		setScroll.scrollTop = Math.max(0,eo.top - rect.y - 100);
1732		//scrollContainer.scrollTop(Math.max(0,eo.top - rect.y - 100));
1733		
1734	} else if (eo.top + eh  - st  > rect.y+rect.height) {
1735		setScroll.scrollTop = Math.max(0, (eo.top  - ch) + eh + 100 + (ch - rect.y - rect.height));		
1736		//scrollContainer.scrollTop(Math.max(0, (eo.top  - ch) + eh + 100 + (ch - rect.y - rect.height)));		
1737	}
1738	if (options && options.animate) {
1739		scrollContainer.stop().animate(setScroll, 400, 'swing',function() {
1740			
1741			if (options && options.highlightElem) {
1742				$(elem).toggleClass('etest-focus-highlighted', true);
1743				setTimeout(function() {
1744					$(elem).toggleClass('etest-focus-highlighted', false);
1745				}, 1000);
1746			}
1747		});
1748	} else {
1749		for (var f in setScroll) {
1750			scrollContainer[f](setScroll[f]);			
1751		}
1752	}
1753} 
1754ETestUtils.openImageBrowser = function(props) {
1755	if (MobileAppBridge.isActive()) {
1756		EdupageApp.pushReactComponentView("/app/pics/jsw/views/elearning/ImageBrowserView.js", props);
1757	} else {
1758		barNewDialog({
1759			source: '/elearning/?cmd=ImageBrowser',
1760			postData: {
1761				svgOnly: props.svgOnly,
1762				lottieOnly: props.lottieOnly
1763			},		
1764			dialogClass: 'whiteDialog etest-dialog-full-height',
1765			returnFunc: function(img) {
1766				if (props.returnFunc) props.returnFunc(img);
1767			}
1768		});
1769	}
1770}
1771ETestUtils.openCardEditor = function(options) {
1772	if (!options) options = {};	
1773
1774	var postData = {
1775		cardids: options.cardids ? options.cardids.join(';') : '',
1776		duplicate: options.duplicate ? '1' : '',
1777		duplicateGroupid: options.duplicateGroupid ? options.duplicateGroupid : '',
1778		defaultSubjectid: options.defaultSubjectid ? options.defaultSubjectid : '',
1779		defaultCardType: options.defaultCardType ? options.defaultCardType  : '',
1780		etestType: options.etestType ? options.etestType : '0',
1781	}
1782
1783	if (MobileAppBridge.isActive() /*&& options.allowDialoginInAppLegacyView*/) {
1784		
1785		/*EdupageApp.pushLegacyUrlView({
1786			source: '/elearning/?cmd=CardEditor',
1787			postData: postData
1788		});*/
1789		if (options.returnFunc) {
1790			options.submitFunc = options.returnFunc;
1791		}
1792		EdupageApp.pushReactComponentView("/app/pics/jsw/views/elearning/CardEditorView.js", options);
1793		return;
1794	}
1795	options.fullScreen = true;
1796	if (!options.addToElem) options.addToElem = MobileAppBridge.isV2Active() ? $j('.edubarMainNoSkin').first() : $j('.edubarMainNoSkin').last();
1797	var editorTopElem = ETestUtils.openFullScreenDialog(options);
1798	
1799	
1800	
1801	
1802	$j.post('/elearning/?cmd=CardEditor',postData, function(data) {
1803		editorTopElem.html(data);
1804	});	
1805}
1806
1807ETestUtils.splitKeywords = function(str) {
1808	var keywords = [];
1809	var pom = str.split(new RegExp(";|,|\n","gi"));
1810	if (!pom) return pom = [];
1811	for (var i=0;i<pom.length;i++) {
1812		var word = pom[i];
1813		word = $j.trim(word);
1814		if (!word) continue;
1815		
1816		keywords.push(word);
1817	}
1818	
1819	return keywords;
1820}
1821
1822ETestUtils.shuffleArray = function(array, seed, keepOrig) {
1823	
1824	var prng = seed ? new Math.seedrandom(seed) : new Math.seedrandom();
1825
1826	if (keepOrig) {
1827		var pom = [];
1828		for (var i = 0; i < array.length; i++) {
1829			pom.push(array[i]);
1830		}
1831		array = pom;
1832	}
1833		 
1834	for (var i = array.length - 1; i > 0; i--) {
1835		var j = Math.floor(prng() * (i + 1));
1836		var temp = array[i];
1837		array[i] = array[j];
1838		array[j] = temp;
1839	}
1840	return array;
1841}
1842
1843
1844
1845ETestUtils.pack = function(digits, radixes) {
1846    var n = 0;
1847    for (var i = 0; i < digits.length; i++) {
1848        n = n * radixes[i] + digits[i];
1849    }
1850    return n;
1851}
1852
1853ETestUtils.unpack = function(n, radixes) {
1854    var digits = [];
1855    for (var i = radixes.length - 1; i >= 0; i--) {
1856        digits.unshift(n % radixes[i]);
1857        n = Math.floor(n / radixes[i]);
1858    }
1859    return digits;
1860}
1861
1862
1863ETestUtils.nthPermutation = function(n, l, arr) {
1864	var arr0 = [];
1865	var arrn = arr.map(function(r) {return r});
1866	for (var i=0;i<l;i++) {
1867		arr0.push(arr.length -i);//- l+i+1);
1868	}
1869	
1870	var u = ETestUtils.unpack(n, arr0);	
1871    var ret = [];
1872    for (var i=0;i<u.length;i++) {
1873		var ind = u[i];
1874		var item = arrn.splice(ind,1);
1875		ret.push(item[0]);		
1876	}
1877    return ret;
1878}
1879
1880
1881ETestUtils.factorial = function(n) {
1882	var r = 1;
1883	while (n > 1) r *= n--;
1884	return r;
1885}
1886
1887ETestUtils.isValidAnswerVal = function(val) {
1888	return val || val === 0;
1889}
1890
1891ETestUtils.strsToIndexes = {
1892	'a': 0,
1893	'b': 1,
1894	'c': 2,
1895	'd': 3,
1896	'e': 4,
1897	'f': 5,
1898	'g': 6,
1899	'h': 7,
1900	'i': 8,
1901	'j': 9,
1902	'k': 10,
1903	'l': 11,
1904	'm': 12,
1905	'n': 13,
1906	'o': 14,
1907	'p': 15,
1908	'q': 16,
1909	'r': 17,
1910	's': 18,
1911	't': 19,
1912	'u': 20,
1913	'v': 21,
1914	'w': 22,
1915	'x': 23,
1916	'y': 24,
1917	'z': 25,	
1918}
1919
1920ETestUtils.answerIndexes = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
1921
1922ETestUtils.getStrIndex = function(str) {
1923	var str = str.toLowerCase();
1924	if (!isNaN(parseInt(str)) && isFinite(str)) {
1925		return parseInt(str);
1926	}
1927	if (ETestUtils.strsToIndexes[str] || ETestUtils.strsToIndexes[str] == 0) return ETestUtils.strsToIndexes[str];
1928
1929	if (str == '') return 0;
1930
1931	if (str.length > 1) {
1932		var ret = 0;
1933		for (var i=0;i<str.length;i++) {
1934			var c = str.charAt(i);
1935			var val = ETestUtils.strsToIndexes[c];
1936			if (!val && val !== 0) return null;
1937			if (i < str.length-1) val = val+1;
1938			ret += Math.pow(ETestUtils.answerIndexes.length, (str.length-i-1))*val;
1939		}
1940		return ret;
1941	}
1942	
1943	return null; 
1944}
1945
1946ETestUtils.parsePrintVariantsStr = function(str) {
1947	if (!str) return [0];
1948	var items = str.replace(/\s+/gi, '').split(/[;,]+/gi);
1949	var ret = [];
1950	for (var i=0;i<items.length;i++) {
1951		var pom = items[i].split('-');
1952		var startStr = pom[0];
1953		var endStr = pom.length>1 && pom[1] ? pom[1] : startStr;
1954
1955		var startInd = ETestUtils.getStrIndex(startStr) || 0;
1956		var endInd = ETestUtils.getStrIndex(endStr) || 0;
1957
1958		for (var v=startInd;v<=endInd;v++) {
1959			ret.push(v);
1960		}
1961	}
1962	return ret;
1963}
1964
1965ETestUtils.variantsToPrintStr = function(arr) {
1966	var intervals = [];
1967	arr.sort();
1968	var cint = null;
1969	for (var i=0;i<arr.length;i++) {
1970		var v = arr[i];
1971		if (!cint) {
1972			cint = [v,v];
1973		} else if (cint[1] == v || cint[1] == v-1) {
1974			cint[1] = v;
1975		} else {
1976			intervals.push(cint);
1977			cint = [v,v];
1978		}
1979	}
1980	if (cint) {
1981		intervals.push(cint);
1982	}
1983
1984	var ret = [];
1985	for (var i=0;i<intervals.length;i++) {
1986		var cint = intervals[i];
1987		if (cint[0] == cint[1]) {
1988			ret.push(ETestUtils.indexToStr(cint[0]).toUpperCase());
1989		} else {
1990			ret.push(ETestUtils.indexToStr(cint[0]).toUpperCase()+'-'+ETestUtils.indexToStr(cint[1]).toUpperCase());
1991		}
1992	}
1993	return ret.join(', ');
1994}
1995
1996ETestUtils.indexToStr = function(index) {	
1997	var cw = index;
1998	var ret = '';
1999	if (cw == 0) return 'a';
2000	var i = 0;
2001	while (cw>0) {
2002		var val = cw%ETestUtils.answerIndexes.length;
2003		if (i>0) val = val-1;
2004		ret = ETestUtils.answerIndexes[val]+ret;
2005		cw = Math.floor(cw / ETestUtils.answerIndexes.length);		
2006		i++;
2007	}
2008	return ret
2009}
2010
2011ETestUtils.downloadCompetences = function(competenceids, doneFunc, needPlanyTemaById) {	
2012	var competencesData = ETestUtils.getCached('competencesData');
2013	if (!competencesData) competencesData = {};
2014	var toDownload = [];
2015	for (var i=0;i<competenceids.length;i++) {
2016		var c = competenceids[i];		
2017		if (!c) continue;
2018		c = c.toString();
2019		if (c.substr(0,5) == 'ctid/') {
2020			var pom = c.split('/');
2021			c = pom[2];
2022		}
2023		if (!competencesData[c]) {
2024			toDownload.push(c);
2025		}
2026	}
2027	
2028	if (toDownload.length > 0 || (needPlanyTemaById && needPlanyTemaById.length > 0)) {
2029		var postData = {
2030			competences: toDownload.join(';'),
2031			needPlanyTemaById: needPlanyTemaById ? needPlanyTemaById.join(';') : ''
2032		};
2033		$j.post('/elearning/?cmd=CompetenceSelector&akcia=getCompetences',postData,function(data) {
2034			for (var i=0;i<data.competences.length;i++) {
2035				var r = data.competences[i];
2036				if (!data.subjects[r.subjectid]) continue;
2037				if (!data.grades[r.gradeid]) continue;
2038				r.subjectName = data.subjects[r.subjectid]["name"];
2039				r.gradeName = data.grades[r.gradeid]["name"];
2040				r.grp = r.gradeName+' - '+r.titlename;
2041				competencesData[r.competenceid] = r;
2042			}
2043			
2044			ETestUtils.setCached('competencesData',competencesData);
2045			doneFunc(competencesData, data.planyTemaById);
2046		},'json');
2047	} else {
2048		doneFunc(competencesData);
2049	}
2050	
2051}  
2052
2053ETestUtils.openPlayer = function(options) {
2054	if (!options) options = {};
2055	
2056	if (MobileAppBridge.isActive() && !MobileAppBridge.useInWebviewPlayer()) {
2057		if (!options.co_som) options.co_som = 'etest';
2058		if (options.mode == 'testCompetences' || options.mode == 'testCompetencesResults') options.co_som = 'etestme';
2059		
2060		if (options.materialData && !options.testid && !options.superid && !options.pridelenieid) {
2061			options.mode = 'testCompetences';
2062			options.co_som = 'etestme';
2063			options.competenceids = [];
2064			for (var i=0;i<options.materialData.cardids.length;i++) {
2065				options.competenceids.push('Cardid:'+options.materialData.cardids[i]);
2066			}
2067			
2068		}
2069		
2070		MobileAppBridge.runFlexMethod('playETest', {options: options});
2071		return;
2072	} else {
2073		options.fullScreen = true;
2074	}
2075
2076	if (options.cosom == 'test' || options.cosom == 'lekcia' || options.cosom == 'projekt') {
2077		if (!options.returnFunc && options.closeFunc) {
2078			options.returnFunc = options.closeFunc;
2079		}		
2080		ETestUtils.launchPlayer(options);
2081		return;
2082	}
2083	
2084	
2085	if (!options.addToElem) options.addToElem = MobileAppBridge.isV2Active() ? $j('.edubarMainNoSkin').first() : $j('.edubarMainNoSkin').last();
2086	
2087	var playerTopElem = ETestUtils.openFullScreenDialog(options);
2088	
2089	playerTopElem.etestPlayer(options);
2090
2091	return playerTopElem;
2092}
2093
2094ETestUtils.openFullScreenDialog = function(options) {	
2095	if (!options) options = {};
2096	
2097	var $ = $j;
2098	var scrollTop = $j(window).scrollTop();
2099	var appendToElem = options.addToElem 
2100						? options.addToElem 
2101						: ($j('#bar_mainDiv > .edubarMainNoSkin').length > 0 ? $j('#bar_mainDiv > .edubarMainNoSkin') : ($j('#bar_mainDiv').length > 0 ? $j("#bar_mainDiv") : $(".app-view.app-view-active").last()));
2102	
2103	var level = appendToElem.find('.etest-overlay, .fullScreenDialogEx').length;
2104	var chatWasVisible = $('#bar_chatPanel').is(':visible');
2105	var aiWasVisible = $('#edubarAiPanel').is(':visible');
2106
2107	appendToElem.children().filter(function() {return $(this).attr('id') != 'edubarAiPanel'}).toggleClass('etest-overlay-hidden',true).each(function() {
2108		if (!$j(this).hasClass('etest-overlay-level')) {
2109			$j(this).toggleClass('etest-overlay-level', true).toggleClass('etest-overlay-level-'+level, true);
2110		}
2111	});
2112	
2113	var s = '<div class="etest-overlay etest-return-div app-color-bg-white '+et(options.className ? options.className : '')+'"><div style="padding: 30px;box-sizing:border-box;height:100vh;"><i class="fa fa-spinner fa-pulse" style="opacity:0.2;position:absolute;'+ertl('left','right')+':50%;top:50%;margin-top:-24px;margin-'+ertl('left','right')+':-24px;font-size:48px"></i></div></div>';
2114	var editorTopElem = $j(s).appendTo(appendToElem);	
2115	
2116	editorTopElem.data('restoreScrollTop', scrollTop);
2117	editorTopElem.data('opts', options.opts);
2118	
2119	if (options.fullScreen) {		
2120		
2121		var wasHidden = $j('#bar_mainDiv').hasClass('edubarHeaderHidden');
2122		barToggleEdubarHeader(false);
2123		barToggleSideBar(false);	
2124		
2125		$('#bar_chatPanel').hide();
2126    	editorTopElem.on('remove',function() {			
2127    		barToggleEdubarHeader(!wasHidden);
2128			barToggleSideBar(!wasHidden);
2129			$('#bar_chatPanel').toggle(chatWasVisible);
2130    	});  	
2131	} 
2132	
2133	
2134	editorTopElem.data('returnFunc',function(data){	
2135		var restoreScrollTop = editorTopElem.data('restoreScrollTop');		
2136		var args = arguments;
2137		appendToElem.children().each(function() {			
2138			if ($j(this).hasClass('etest-overlay-level-'+level)) {
2139				$j(this).toggleClass('etest-overlay-level', false).toggleClass('etest-overlay-level-'+level, false).toggleClass('etest-overlay-hidden',false);
2140				if ($j(this).hasClass('ui-dialog')) {
2141					$j(this).css('display','');
2142				}
2143			}
2144		});
2145		if (MobileAppBridge.isActive()) {
2146			
2147			if (restoreScrollTop) {
2148				$j(window).scrollTop(restoreScrollTop);
2149			}
2150			if (options.returnFunc) {
2151				options.returnFunc.apply(this, args);
2152				options.returnFunc = null;
2153			}
2154			editorTopElem.remove();
2155			$j(window).resize();		
2156		} else {
2157			
2158			if (options.returnFunc) {
2159				options.returnFunc.apply(this, args);
2160				options.returnFunc = null;
2161			}
2162			if (edubar && edubar.popStateHandlers && edubar.popStateHandlers[edubar.popStateHandlers.length-1] && edubar.popStateHandlers[edubar.popStateHandlers.length-1].elem == editorTopElem.get(0)) {	
2163				
2164				
2165				window.history.back();
2166			} else {
2167				//barUnregisterPopstateHandler(editorTopElem.get(0));
2168				editorTopElem.remove();
2169				$j(window).resize();
2170				if (restoreScrollTop) {
2171					$j(window).scrollTop(restoreScrollTop);
2172				}
2173			}
2174		}
2175	});
2176	
2177	/*if (MobileAppBridge.isActive() && options.registerBack && !MobileAppBridge.isV2Active()) {
2178		
2179		MobileAppBridge.registerBackHandler(editorTopElem, function() {  
2180			if (ETestUtils.closeFullScreenDialog(editorTopElem) === false) {
2181				MobileAppBridge.skipBack();
2182			}
2183		});
2184	} */
2185
2186	barRegisterPopstateHandler(editorTopElem.get(0), function(e) {		
2187		ETestUtils.closeFullScreenDialog(editorTopElem);
2188	});
2189	
2190	
2191	return editorTopElem;
2192}
2193
2194ETestUtils.closeFullScreenDialog = function(elem) {	
2195	var editorTopElem = elem.closest('.etest-overlay');
2196	var checkForChangesFunc = editorTopElem.data('checkChangesFunc');
2197	var returnFunc = editorTopElem.data('returnFunc');
2198	if (checkForChangesFunc) {
2199		var ret = checkForChangesFunc(function() {
2200			if (returnFunc) {
2201				returnFunc();
2202			}
2203		});
2204
2205		if (!ret) {
2206			return false;
2207		}
2208		if (returnFunc) {
2209			returnFunc();
2210		}
2211	} else {
2212		if (returnFunc) {
2213			returnFunc();
2214		}
2215	}
2216}
2217	
2218
2219ETestUtils.launchPlayer = function(options) {
2220	if (!options) options = {};
2221	
2222	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2223	
2224	
2225	var postData = {
2226		testid: options.testid,
2227		superid: options.superid,
2228		pridelenieid: options.pridelenieid,
2229		vysledokid: options.vysledokid
2230	}  
2231	postData["etestMode"] = '1';
2232	$j.post('/elearning/?cmd=MaterialPlayer',postData, function(data) {		
2233		editorTopElem.html(data);
2234	});		
2235}
2236
2237
2238
2239
2240ETestUtils.launchCardBrowser = function(options) {
2241	if (!options) options = {};
2242	options.registerBack = true;
2243	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2244	
2245	
2246	var postData = options.params ? options.params : {};
2247
2248	$j.post('/elearning/?cmd=CardBrowser',postData, function(data) {		
2249		editorTopElem.html(data);
2250	});			
2251}
2252
2253
2254ETestUtils.openTestmeTopic = function(subjectid, titleid, competenceid) {
2255	if (MobileAppBridge.isActive()) {
2256		ASC.requireAsync('/app/pics/jsw/actions/testme/TestmeAction.js').then(function(c){
2257			c.startTestmeAction({
2258				subjectid: subjectid,
2259				titleid: competenceid ? titleid : '',
2260				gotoid: competenceid ? competenceid : titleid
2261			})
2262		});
2263	} else {
2264		barSmartLoadPage(barEncLink(barAddBackUrl('/elearning/?cmd=Testme&subjectid=' + encodeURIComponent(subjectid) + '&titleid=' + encodeURIComponent(competenceid ? title : '') + '&gotoid=' + (competenceid ? competenceid : titleid))));
2265	}
2266}
2267
2268ETestUtils.launchCardBrowserCards = function(options) {
2269	if (!options) options = {};
2270	var s = '';
2271	s += '<div class="etest-meditor-search-results-simple-outer '+et(MobileAppBridge.isActive() ? 'etest-mobileMode' : '')+'">';					  	
2272	
2273		s += '<div class="etest-meditor-search-results-tests-info fixedLeft">';
2274			s += '<div >';
2275				s += '<a class="ecourse-link-button closeBtn" style="color: inherit"><i class="material-icons" style="font-size: 64px">&#xE5C4;</i></a>';
2276			s += '</div>';
2277		s += '</div>';	
2278		s += '<div class=" etest-meditor-search-content-unattached etest-meditor-search-results-tests-inner etest-card-browser-dlg etest-search-simple">';
2279			
2280		s += '</div>';
2281	s += '</div>';
2282	s = renderS(s, {});
2283	var editorTopElem = null;
2284	if (MobileAppBridge.isActive()) {
2285		editorTopElem = barNewDialog({
2286			allowDialoginInAppLegacyView: true,
2287			content: s
2288		})
2289	} else {
2290		editorTopElem = $(s).appendTo(options.appendToElem || $('body'));
2291	}
2292	editorTopElem.find('.etest-card-browser-dlg').etestCardBrowser({
2293		cs_pohladStart: 'simple',
2294		searchCardids: options.cards,
2295		prioritizeStandards: options.prioritizeStandards,
2296		simpleHeader: {
2297			title: options.title,
2298			subtitle: options.subtitle
2299		}
2300	});		
2301	
2302	editorTopElem.find('.closeBtn').on('click', function() {
2303		editorTopElem.remove();
2304	});
2305
2306	barRegisterPopstateHandler(editorTopElem, function() {
2307		editorTopElem.remove();
2308	});
2309	
2310}
2311
2312ETestUtils.launchOldEditor = function(options) {
2313	if (!options) options = {};
2314	
2315	options.fullScreen = true;
2316	var cosom = options.cosom ? options.cosom : 'test';
2317	
2318	cosom = cosom.substr(0,1).toUpperCase()+cosom.substr(1);
2319	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2320	
2321	
2322	var postData = {
2323		test: options.testid		
2324	}  
2325	$j.post('/elearning/?cmd='+cosom+'Creator',postData, function(data) {
2326		editorTopElem.html(data);
2327	});		
2328}
2329
2330ETestUtils.assignStandardsDialog = function(options) {
2331	if (!options) options = {};
2332	
2333	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2334	
2335	var postData = {
2336		planid: options.planid,
2337		temaid: options.temaid,
2338		triedaid: options.triedaid,
2339		predmetid: options.predmetid
2340	}  
2341	
2342	$j.post('/elearning/?cmd=CompetencePlanBrowser',postData, function(data) {
2343		editorTopElem.html(data);
2344	});		
2345}
2346
2347
2348ETestUtils.openResultsEditor = function(options) {
2349	if (!options) options = {};	
2350	options.cspohladStart = 'tests';
2351	ETestUtils.openMaterialEditor(options);
2352	return;
2353	
2354	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2355	var postData = {
2356		testid: options.testid,
2357		superid: options.superid,
2358		cspohladStart: 'tests'
2359	} 
2360	$j.post('/elearning/?cmd=ResultsEditor',postData, function(data) {
2361		editorTopElem.html(data);
2362	});	
2363}
2364
2365
2366ETestUtils.openMaterialEditor = function(options) {
2367	if (!options) options = {};	
2368	
2369	var editorTopElem = ETestUtils.openFullScreenDialog(options);
2370	var postData = {
2371		test: options.testid,
2372		superid: options.superid,		
2373		'triedaid': options.triedaid,
2374		'predmetid': options.predmetid,
2375		'planid': options.planid,
2376		'mode': options.mode ? options.mode : ''
2377	}  
2378	var moreOpts = ['pohlad','hideCancelTest','forceEditingMode','etestType','temaid','cspohladStart'];
2379	
2380	for (var i=0;i<moreOpts.length;i++) {
2381		var f = moreOpts[i];
2382		if (options[f]) {
2383			postData[f] = options[f];
2384		}
2385	} 
2386	
2387	$j.post('/elearning/?cmd=EtestCreator',postData, function(data) {
2388		editorTopElem.html(data);
2389	});	
2390}
2391
2392ETestUtils.cache = {};
2393ETestUtils.getCached = function(key) {
2394	if (this.cache[key]) return this.cache[key];
2395	if (this.cache.hasOwnProperty(key)) return this.cache[key];
2396	return null;
2397}
2398
2399ETestUtils.setCached = function(key, val) {
2400	this.cache[key] = val;
2401}
2402
2403
2404ETestUtils.clearCachedLike = function(keyLike) {
2405	for (var x in this.cache) {
2406		if (x.substr(0,keyLike.length) == keyLike) {
2407			delete this.cache[x];
2408		}
2409	}	
2410}
2411
2412
2413
2414ETestUtils.isEqual = function(x,y, ignore, ignoreEmpty) {	
2415	if (x === y) return true;
2416	// if both x and y are null or undefined and exactly the same
2417
2418	if (!( x instanceof Object ) || !( y instanceof Object )) return false;
2419	// if they are not strictly equal, they both need to be Objects
2420
2421	if (x.constructor !== y.constructor) {
2422		return false;
2423	}
2424	// they must have the exact same prototype chain, the closest we can do is
2425	// test there constructor.
2426	if ($j.isArray(x) != $j.isArray(y)) {
2427
2428		return false;
2429	}
2430	if ($j.isArray(x)) {
2431		if (x.length != y.length) {				
2432			return false;
2433		}
2434		
2435		for (var i=0;i<x.length;i++) {
2436			if (! ETestUtils.isEqual(x[i], y[i], ignore, ignoreEmpty)) {
2437				return false;
2438			}
2439		}
2440		return true;
2441	}  
2442	
2443	for (var p in x ) {
2444		
2445		if (! x.hasOwnProperty(p)) {
2446			continue;
2447		}
2448		if (ignore && ignore[p]) continue;
2449		// other properties were tested using x.constructor === y.constructor
2450		if (ignoreEmpty && !x[p] && !y[p]) continue;
2451
2452		if (! y.hasOwnProperty(p)) {			
2453			return false;
2454		}
2455		// allows to compare x[ p ] and y[ p ] when set to undefined
2456
2457		if (x[p] === y[p])
2458			continue;
2459		// if they have the same strict value or identity then they are equal
2460
2461		if ( typeof (x[p] ) !== "object") {			
2462			return false;
2463		}
2464		// Numbers, Strings, Functions, Booleans must be strictly equal
2465
2466		if (! ETestUtils.isEqual(x[p], y[p], ignore, ignoreEmpty)) {			
2467			return false;
2468		}
2469		// Objects and Arrays must be tested recursively
2470	}
2471
2472	for (p in y ) {
2473		if (ignore && ignore[p]) continue;
2474		if (ignoreEmpty && !x[p] && !y[p]) continue;
2475		if (y.hasOwnProperty(p) && ! x.hasOwnProperty(p)) {			
2476			return false;
2477		}
2478		// allows x[ p ] to be set to undefined
2479	}
2480	return true;
2481
2482}
2483
2484ETestUtils.competencesById = {};
2485ETestUtils.titleById = {};
2486ETestUtils.topicsById = {};
2487
2488ETestUtils.addTopicsById = function(planid, topicsById) {
2489	if (!this.topicsById[planid]) this.topicsById[planid] = {};
2490	for (var id in topicsById) {
2491		this.topicsById[planid][id] = topicsById[id];
2492	}
2493}
2494
2495ETestUtils.addCompetencesById = function(competencesById, titleById) {
2496	
2497	for (var id in competencesById) {
2498		this.competencesById[id] = competencesById[id];
2499	}
2500	
2501	for (var id in titleById) {
2502		this.titleById[id] = titleById[id];
2503	}
2504}
2505
2506ETestUtils.objektyDoTem = function(temyById, objekty, options) {
2507	if (!options) options = {};
2508	var ret = {};
2509	ret.objekty = [];
2510	for (var i=0;i<objekty.length;i++) {
2511		ret.objekty.push(objekty[i]);
2512	}
2513	
2514	ret.objektyVTeme = {};
2515	ret.objektById = {};
2516	ret.objektByFolder = {};
2517	ret.superidNaObjekt = {};
2518	ret.pocetNeprazdnychPodadresarov = {};
2519	
2520	ret.objekty.sort(function(a,b) {
2521		
2522		if (options.sortBy == 'timestamp') {
2523			if (a.timestamp > b.timestamp) return -1;
2524			if (a.timestamp < b.timestamp) return 1;
2525		} else {
2526			if (a.folder > b.folder) return -1;
2527			if (a.folder < b.folder) return 1;
2528			
2529			if (a.typ == 'folder' && b.typ != 'folder') return -1;
2530			if (a.typ != 'folder' && b.typ == 'folder') return 1;
2531			
2532			if (a.typ == 'test' && b.typ != 'test') return -1;
2533			if (a.typ != 'test' && b.typ == 'test') return 1;
2534			if (a.poradie > b.poradie) return 1;
2535			if (a.poradie < b.poradie) return -1;
2536			if (a.timestamp > b.timestamp) return -1;
2537			if (a.timestamp < b.timestamp) return 1;
2538		}
2539		return 0;
2540	});	
2541	
2542	for (var i=0;i<ret.objekty.length;i++) {
2543		var objekt = ret.objekty[i];
2544		
2545		var temaid = objekt.temaid ? objekt.temaid : '-1';
2546		
2547		if (!ret.objektyVTeme[temaid]) ret.objektyVTeme[temaid] = [];
2548		ret.objektyVTeme[temaid].push(objekt);
2549		
2550		ret.objektById[objekt.objektid] = objekt;			
2551		
2552		if (objekt.superid) {
2553			ret.superidNaObjekt[objekt.superid] = objekt;
2554		}
2555		var labels = objekt.folder ? objekt.folder.split(';') : [];
2556		
2557		
2558		
2559		for (var j=0;j<labels.length;j++) {			
2560			var label = labels[j];
2561			if (!label) continue;
2562			var temaFolder = objekt.temaid+'@'+label;
2563			if (options && options.availableLabels && !options.availableLabels[label]) continue;
2564			
2565			if (!ret.objektByFolder[temaFolder]) ret.objektByFolder[temaFolder] = [];
2566			ret.objektByFolder[temaFolder].push(objekt);
2567			
2568			if (!ret.pocetNeprazdnychPodadresarov[temaFolder]) ret.pocetNeprazdnychPodadresarov[temaFolder] = 0;
2569			ret.pocetNeprazdnychPodadresarov[temaFolder]++;
2570			
2571			if (!ret.pocetNeprazdnychPodadresarov[objekt.temaid+'@']) ret.pocetNeprazdnychPodadresarov[objekt.temaid+'@'] = 0;
2572			ret.pocetNeprazdnychPodadresarov[objekt.temaid+'@']++; 
2573		} 
2574		
2575	}
2576	
2577	for (var temaFolder in ret.objektByFolder) {
2578		
2579		ret.pocetNeprazdnychPodadresarov[temaFolder] = ETestUtils.getPocetNeprazdnychPodadresarov(temaFolder, ret.objektByFolder);
2580	}
2581	
2582	return ret;
2583}
2584
2585ETestUtils.getObdobiePreDatum = function(datum) {
2586	var obdobia = Znamky.getNadobdobia();
2587	
2588	for (var i=0;i<obdobia.length;i++) {
2589		var op = Znamky.getObdobieParams(obdobia[i].id);
2590		if (datum<= op.do_r) {
2591			return op.id;
2592		}
2593	}
2594	return obdobia[obdobia.length-1].id;
2595}
2596
2597ETestUtils.getNumStars = function(percent) {	
2598	var numStars = 0;
2599	if (percent >= 50) numStars++;
2600	if (percent >= 70) numStars++;
2601	if (percent >= 90) numStars++;
2602	return numStars;
2603}
2604
2605ETestUtils.getSuperpridelenieTab = function(r) {
2606	if (!r) return '0';
2607	if (r.co_som == 'bb') return 'bb';
2608	if (r.typ == ETestUtils.etestTypeTest || r.typ == ETestUtils.etestTypeProject || r.typ == ETestUtils.etestTypeExam) return '0';
2609	return r.typ;
2610}
2611
2612ETestUtils.filterSuperprideleniaOptions = {};
2613ETestUtils.filterSuperpridelenia = function(superpridelenia, options) {
2614	if (!options) options = ETestUtils.filterSuperprideleniaOptions;
2615	if (!options.hasOwnProperty('showHidden')) {
2616		options.showHidden = ETestUtils.filterSuperprideleniaOptions.showHidden;
2617	}
2618	
2619	if (!options.hasOwnProperty('showDone')) {
2620		options.showDone = ETestUtils.filterSuperprideleniaOptions.showDone;
2621	}
2622
2623	var obdobie = options.obdobie || '';	
2624	var op = obdobie ? Znamky.getObdobieParams(obdobie, true) : null;
2625	
2626	if (!superpridelenia) superpridelenia = [];
2627	var ret = [];
2628	
2629	var sqFields = ["nazov"];
2630	var sq = options.searchQuery ? options.searchQuery.toLowerCase().replace(/[\s,\.;\?\!]+/,'').latinize() : "";
2631
2632	var numByTab = {};
2633	
2634	for (var i=0;i<superpridelenia.length;i++) {
2635		var r = superpridelenia[i];
2636		var hwflags = r.hwflags ? r.hwflags : {};
2637		
2638		if (!options.showHidden && hwflags.flag_hidden) {
2639			
2640			continue;
2641		}
2642		
2643		if (!options.uncategorizedOnly && r.uncategorizedCourse) {
2644			continue;
2645		} 
2646		
2647		if (options.uncategorizedOnly && !r.uncategorizedCourse) {
2648			continue;
2649		}
2650
2651		var mainCas = r.koniec_timezone 
2652						? r.koniec_timezone
2653						: r.zaciatok_timezone
2654						? r.zaciatok_timezone
2655						: r.cas_timezone;
2656
2657		mainCas = (mainCas || "").substr(0,10);
2658		
2659		//if (op && !(op.od_r <= mainCas && op.do_r >= mainCas)) continue;	
2660		if (options.obdobie && ETestUtils.getObdobiePreDatum(mainCas) != options.obdobie) continue;
2661
2662		if (!r.typ) r.typ = '0';
2663
2664		var tab =  ETestUtils.getSuperpridelenieTab(r);
2665		
2666		if (options.etestType == 'all') {
2667
2668		} else if (options.etestType && tab != options.etestType) {
2669			continue;
2670		}
2671		/*if (options.etestType == 'bb') {			
2672			if (r.co_som != 'bb') continue;
2673		} else {					
2674			if (!options.uncategorizedOnly) {
2675				if (options.etestType == '0') {
2676					if (r.co_som == 'bb') continue;
2677					if (r.typ != ETestUtils.etestTypeTest &&r.typ != ETestUtils.etestTypeProject && r.typ != ETestUtils.etestTypeExam) {
2678						continue;
2679					}  
2680				} else 
2681				if (options.etestType && (r.typ != options.etestType || r.co_som == 'bb')) {			
2682					continue;
2683				}
2684			}
2685		}*/
2686		
2687		if (options.showDone === false && hwflags.flag_done) continue;
2688		
2689		if (options.onlyImportant && !hwflags.flag_important) continue;
2690
2691		if (sq) {
2692			
2693			var nasiel = false;
2694			for (var si=0;si<sqFields.length;si++) {
2695				var f = sqFields[si];
2696				var v = r[f] || "";
2697				v = v.toLowerCase().replace(/[\s,\.;\?\!]+/," ").latinize();
2698				if (v.indexOf(sq) >=0) {
2699					nasiel = true;
2700					break;
2701				}
2702			}
2703			if (!nasiel) continue;
2704		}
2705
2706		if (!numByTab[tab]) numByTab[tab] = 0;
2707		
2708
2709		r.tab = tab;		
2710		r.tabInd = numByTab[tab];
2711
2712		numByTab[tab]++;
2713				
2714		ret.push(r);
2715	}
2716
2717
2718	for (var i=0;i<ret.length;i++) {
2719		var r = ret[i];
2720		var tab = r.tab;
2721		r.tabInd = numByTab[tab]-r.tabInd;
2722		r.tabColor = ETestUtils.colors[(r.tabInd - 1)%ETestUtils.colors.length];		
2723	}
2724	return ret;
2725}
2726
2727ETestUtils.getPocetNeprazdnychPodadresarov = function(temaFolder, objektByFolder) {
2728	var objekty = objektByFolder[temaFolder] ? objektByFolder[temaFolder] : [];
2729	var ret = 0;
2730	for (var i=0;i<objekty.length;i++) {
2731		var r = objekty[i];
2732		if (r.typ == 'folder') {
2733			var f = temaFolder+(temaFolder.substr(-1) == ';' ? ';' : '/')+r.objektid;
2734			if (objektByFolder[f] && objektByFolder[f].length>0) {
2735				ret++;
2736			}
2737		}
2738	}
2739	return ret;
2740}
2741
2742ETestUtils.getObjektIcon = function(objekt) {
2743	if (objekt.typ == 'folder') {
2744		if (objekt.data && objekt.data.type == 'presentations') {
2745			return {icon: 'fa-slideshare ', color: '#2980B9'};
2746		} else if (objekt.data && objekt.data.type == 'questions') {
2747			return {icon: 'fa-question-circle', color: '#2980B9'};
2748		} else if (objekt.data && objekt.data.type == 'images') {
2749			return {icon: 'fa-photo', color: '#2980B9'};
2750		}
2751		return {icon: 'fa-folder', color: '#2980B9'};
2752	} else if (objekt.typ == 'test') {
2753		if ((objekt.testyp == ETestUtils.etestTypePresentation && objekt.testcosom == 'etest')
2754			|| objekt.testcosom == 'lekcia') {
2755			return {icon: 'fa-desktop', color: objekt.testcosom == 'etest' ? '#2196F3' : '#607D8B'};
2756		}
2757		
2758		if (objekt.testcosom == 'projekt') {
2759			return {icon: 'fa-lightbulb-o', color: '#607D8B'};
2760		}
2761		
2762		
2763		return {icon: 'fa-check-square-o', color: objekt.testcosom == 'etest' ? '#9C27B0' : '#607D8B'};
2764	} else if (objekt.typ == 'card') {
2765		var q = objekt.questionWidget;
2766		if (!q) {
2767			q = new QuestionETestWidget();
2768			
2769			q.loadData(objekt.cardContent ? objekt.cardContent : {});
2770			objekt.questionWidget = q;
2771		}
2772		
2773		var aw = q.getAnswerWidgets(q);
2774		if (aw.length > 0) {
2775			return {icon: 'fa-question', color: '#4CAF50'};
2776		}
2777		
2778		var fw = q.findByWidgetClass('FileETestWidget');
2779		if (fw.length >0) {
2780			return {icon: 'fa-link', color: '#009688'};
2781		}
2782		return {icon: 'fa-puzzle-piece', color: '#00BCD4'};
2783	} else if (objekt.typ == 'standards') {
2784		return {icon: 'fa-globe', color: '#4CAF50'};
2785	}
2786	return {icon: 'fa-th-large', color: '#607D8B'};
2787}
2788
2789
2790
2791ETestUtils.etestCustomCheckbox = function($) {
2792	$.fn.etestCustomCheckbox = function(options) {        
2793	    
2794	    var opts = $.extend( {}, $.fn.etestCustomCheckbox.defaults, options);
2795	    
2796	    function main() {     
2797		    var mainElem = $j(this);	
2798			var iconElem = null;
2799			
2800			
2801			mainElem.toggleClass('isInited',true);
2802			
2803			if (mainElem.attr('data-icon')) {
2804				var s  = renderS('<i class="fa {iconCls}"></i>', {
2805							iconCls: mainElem.attr('data-icon')
2806							});
2807				iconElem = $j(s).appendTo(mainElem);
2808				mainElem.toggleClass('withIcon', true);
2809			}
2810			if (mainElem.attr('data-isCircle') == 'true') {
2811				mainElem.toggleClass('circle', true);
2812			}
2813		    
2814		    var checkbox = mainElem.find('input[type="checkbox"]').on('change',function() {
2815		    	mainElem.toggleClass('checked',this.checked);
2816		    	mainElem.trigger('changecustom',[this]);
2817		    }).on('click',function() {		    	
2818				mainElem.toggleClass('checked',this.checked);
2819				mainElem.trigger('changecustom',[this]);
2820			});
2821			
2822			   
2823			    
2824			Object.defineProperty(checkbox.get(0), "checkedCustom", {
2825				set: function(value) { 
2826					this.checked = value;
2827					mainElem.toggleClass('checked',this.checked);				
2828					
2829				},
2830				get: function() {
2831					return this.checked;
2832				}
2833			});		
2834			
2835			 Object.defineProperty(checkbox.get(0), "isEmptySubtree", {
2836				set: function(value) { 
2837					if (this._isEmptySubtree !== value) {
2838						this._isEmptySubtree = value;				
2839							
2840						mainElem.toggleClass('emptySubtree',this._isEmptySubtree);			
2841					}						
2842				},
2843				get: function() {
2844					return this._isEmptySubtree;
2845				}
2846			});		
2847		}   
2848		
2849		
2850		    
2851		return this.each(main);
2852	};
2853		
2854	$.fn.etestCustomCheckbox.defaults = {	    	
2855			
2856	};
2857}
2858
2859ETestUtils.etestCustomCheckbox(jQuery);
2860
2861
2862ETestUtils.planTriedaPredmetSelector = function($) {
2863	$.fn.planTriedaPredmetSelector = function(options) {        
2864	    
2865	    var opts = $.extend( {}, $.fn.planTriedaPredmetSelector.defaults, options);
2866	    
2867	    function main() {     
2868		    var mainElem = $j(this);
2869		    
2870		    var selectedClass = null;
2871		    var selectedSubject = null;
2872		    var selectedPlan = null;
2873		    function createContent() {	
2874				if (opts.poradie == 'pt') {
2875					initPredmetCombo();
2876					initTriedaCombo();
2877				} else {
2878					initTriedaCombo();
2879					initPredmetCombo();
2880				}
2881					
2882				
2883				
2884				barRefreshPage(mainElem);
2885				
2886		    }		 
2887		    
2888		    function initTriedaCombo() {		    			    
2889		    	var s = '';
2890				
2891				s += '<div style="display: inline-block">';
2892									
2893					s += '<div class="dropDownBtn triedaDropDownBtn">';
2894					
2895						var triedaRow = opts.triedy[opts.triedaid];
2896					
2897						s += '<a class="ecourse-dropdown-btn">';
2898																	
2899							s += '<span class="ecourse-dropdown-title">';
2900								s += '<div style="font-size:10px;opacity:0.6;">'+lset(1263)+':</div>';
2901								s += "<b>"+et(triedaRow ? triedaRow.Meno : '???')+'</b>';
2902							s += '</span>';						
2903						s += '</a>';
2904						
2905				
2906						s += '<div class="dropDown " style="overflow-y:auto;overflow-x:hidden;padding:0">';
2907						
2908							var planySorted = sortPlany(opts.plany);
2909							
2910							var planyByPredmet = groupPlanyByPredmet(planySorted);
2911							var planyByTrieda = groupPlanyByTrieda(planyByPredmet[opts.predmetid] ? planyByPredmet[opts.predmetid] : {});
2912							
2913							
2914														
2915							s += '<ul class="ecourse-dropdownlist"  style="width: 300px;border: 0;">';															
2916								for (var i =0;i<opts.mojeTriedy.length;i++) {					
2917									var t = opts.mojeTriedy[i];		
2918									var tid = t["TriedaID"];	
2919									var planyTrieda = opts.poradie == 'pt' ? (planyByTrieda[tid] ? planyByTrieda[tid] : []) : [];
2920									for (var j=0;j<planyTrieda.length;j++) { 		
2921										var p = planyTrieda[j];
2922										
2923										var nazovPlanu = p["nazov"] ? p["nazov"] : '';
2924										var menoUcitela =  p.ucitelid == 0 ? lset(1675) : p.menaUcitelov;
2925										
2926										s += '<li class="'+et(opts.planid == p.planid ? 'marked' : '')+'">';
2927											s += '<a style="cursor:pointer;position: relative;padding-'+ertl('right','left')+':20px;" data-planid="'+et(p.planid)+'" class="planLink cutTextEllipsis">';
2928											s += et(t["Meno"]);
2929											s += '<div style="font-size:10px;color: #888">';										
2930												s += ' <i class="fa fa-fw fa-user"></i> '+et(menoUcitela);
2931											
2932												if (nazovPlanu) {
2933													s += ' <i class="fa fa-fw fa-file"></i> '+et(nazovPlanu);
2934												}
2935											s += '</div>';								
2936											s += '</a>';														
2937										s += '</li>';
2938										
2939										if (opts.planid == p.planid) {
2940											selectedClass = t;
2941											selectedPlan = p;
2942										}
2943									}
2944									if (planyTrieda.length == 0) {				
2945										s += '<li class="'+et(opts.triedaid == tid ? 'marked' : '')+'" >';
2946											s += '<a style="cursor:pointer;position: relative;padding-'+ertl('right','left')+':20px;" data-tid="'+et(tid)+'" class="triedaLink cutTextEllipsis">';
2947											s += et(t["Meno"]);		
2948											if (opts.poradie == 'pt') {
2949												s += '<div style="font-size:10px;color: #888">';
2950													s += '<i class="fa fa-fw fa-file"></i> ('+lset(3599)+')';
2951												s += '</div>';
2952											}							
2953											s += '</a>';													
2954										s += '</li>';
2955										
2956										if (opts.triedaid == tid) {
2957											selectedClass = t;
2958											selectedPlan = null;
2959										}
2960									}							
2961								}						
2962							
2963								s += '<li class="separator">Tools</li>';	
2964								if (!EdubarUtils.isAdmin()) {
2965								
2966									s += '<li>';									 					
2967										s += '<a href="/customize/wizard.php#stepid=skupiny" class="edubarSmartLink">';									
2968										s += lset(3466);
2969										s += '</a>';		
2970									s += '</li>';					
2971								}
2972						
2973								if (opts.poradie == 'pt') {
2974									s += '<li>';
2975										s += '<a class="novyPlanBtn">'+lset(3599)+'</a>';
2976									s += '</li>';
2977									
2978									s += '<li>';
2979										s += '<a href="/plany/" class="edubarSmartLink">'+lset(4223)+'</a>';
2980									s += '</li>';
2981								}
2982								if (!EdubarUtils.isAdmin() && opts.showRecommendedSwitch) {
2983									s += '<div style="position: relative;clear:both;">';
2984										s += '<a class="recommendedOnlyBtn hoverSelect'+et(opts.recommendedOnly ? ' selected' : '')+'" style="padding:3px 5px;display:block;text-align:'+ertl('left','right')+';cursor:pointer;position:absolute;bottom:2px;'+ertl('right','left')+':2px"';
2985										s += ' title="'+et(opts.recommendedOnly ? ls(3881) : ls(3882))+'"';
2986										s += '>';
2987										s += '<img src="/znamky/pics/schedule_ok_25.png" alt="" style="vertical-align:middle;width:25px;height:25px;">';							
2988										s += '</a>';						
2989									s += '</div>';
2990								}
2991							s += '</ul>';
2992						s += '</div>';
2993					s += '</div>';
2994				s += '</div>';
2995				
2996				var triedaElem = $j(s).appendTo(mainElem);
2997				
2998				triedaElem.find('.triedaLink').on('click',function() {
2999					opts.triedaid = $j(this).attr('data-tid');					
3000					opts.planid = '';
3001					if (opts.changeFunc) {
3002						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3003					}									
3004				});
3005				
3006				triedaElem.find('a.recommendedOnlyBtn').on('click',function() {
3007				
3008					opts.recommendedOnly = !opts.recommendedOnly;
3009					if (opts.changeFunc) {
3010						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3011					}   			
3012				});
3013				
3014				triedaElem.find('.planLink').on('click',function() {
3015					opts.planid = $j(this).attr('data-planid');
3016					if (opts.changeFunc) {
3017						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3018					}	
3019								
3020				});
3021		    }  
3022		    
3023		    
3024		     function initPredmetCombo() {			     	  	
3025		    	var s = '';
3026		    	s += '<div  style="display: inline-block">';
3027						
3028					
3029					s += '<div class="dropDownBtn predmetDropDownBtn">';
3030								
3031						var predmetRow = opts.predmety[opts.predmetid] 
3032											? opts.predmety[opts.predmetid]
3033											: {};	
3034										
3035						
3036						var planySorted = sortPlany(opts.plany);
3037						var planyByTrieda = groupPlanyByTrieda(planySorted);
3038						var planyByPredmet = groupPlanyByPredmet(planyByTrieda[opts.triedaid] ? planyByTrieda[opts.triedaid] : {});
3039						var predmety = opts.mojePredmety;
3040						
3041						
3042						
3043						s += '<a class="ecourse-dropdown-btn">';
3044							//s += '<img class="ecourse-dropdown-img" src="/global/pics/ui/subject_32.png" alt="">';
3045							//s += '<i class="material-icons" style="color:#2980B9">&#xE865;</i>';															
3046							s += '<span class="ecourse-dropdown-title">';			
3047								s += '<div style="font-size:10px;opacity:0.6">'+lset(1299)+':</div>';					
3048								s += "<b>"+et(predmetRow ? predmetRow.p_meno : '???')+'</b>';
3049							s += '</span>';						
3050						s += '</a>';	
3051						
3052						s += '<div class="dropDown ecourse-subjects-dropdown" style="overflow-y:auto;overflow-x:hidden;padding:0">';
3053							
3054							s += '<ul class="ecourse-dropdownlist"  style="width: 300px;border: 0;">';
3055								if (opts.subjectsPrefix) {
3056									s += opts.subjectsPrefix;
3057								}	
3058								var bolGlobalSubjectsSeparator = false;
3059								for (var i=0;i<predmety.length;i++) {
3060									pr = predmety[i];		
3061									var pid = pr["PredmetID"];	
3062									if (pid.toString().substr(0,9) == 'globalid:' && !bolGlobalSubjectsSeparator) {
3063										s += '<li class="separator">Unpaired global subjects</li>';
3064										bolGlobalSubjectsSeparator= true;
3065									}									
3066									var planyPredmet = opts.poradie == 'tp' ? (planyByPredmet[pid] ? planyByPredmet[pid] : []) : [];
3067									for (var j=0;j<planyPredmet.length;j++) { 		
3068										var p = planyPredmet[j];
3069										
3070										var nazovPlanu = p["nazov"] ? p["nazov"] : '';
3071										var menoUcitela =  p.ucitelid == 0 ? lset(1675) : p.menaUcitelov;
3072										
3073										s += '<li class="'+et(opts.planid == p.planid ? 'marked' : '')+'">';
3074											s += '<a data-planid="'+et(p.planid)+'" class="planLink cutTextEllipsis">';
3075												s += et(pr["p_meno"]);
3076												s += '<div style="font-size:10px;color: #888">';										
3077													s += ' <i class="fa fa-fw fa-user"></i> '+et(menoUcitela);
3078												
3079													if (nazovPlanu) {
3080														s += ' <i class="fa fa-fw fa-file"></i> '+et(nazovPlanu);
3081													}
3082												s += '</div>';								
3083											s += '</a>';														
3084										s += '</li>';
3085										
3086										if (opts.planid == p.planid) {
3087											selectedSubject = pr;
3088											selectedPlan = p;
3089										}
3090									}
3091									if (planyPredmet.length == 0) {
3092										s += '<li class="'+et(opts.predmetid == pid ? 'marked' : '')+'">';
3093											s += '<a data-predmetid="'+et(pid)+'" class="predmetLink cutTextEllipsis">';
3094											s += et(pr["p_meno"]);
3095											if (opts.poradie == 'tp') {
3096												s += '<div style="font-size:10px;color: #888">';
3097													s += '(no plan)';
3098												s += '</div>';
3099											}				
3100											s += '</a>';														
3101										s += '</li>';
3102										
3103										if (opts.predmetid == pid) {
3104											selectedSubject = pr;
3105											selectedPlan = null;
3106										}
3107									}
3108								}
3109							
3110							
3111							
3112							
3113							
3114							if (opts.poradie == 'tp') {
3115								s += '<li class="separator">Tools</li>';	
3116								s += '<li>';
3117									s += '<a class="novyPlanBtn">'+ls(3599)+'</a>';
3118								s += '</li>';
3119								
3120								s += '<li>';
3121									s += '<a href="/plany/" class="edubarSmartLink">'+ls(4223)+'</a>';
3122								s += '</li>';
3123							}
3124							
3125							
3126							
3127							if (!EdubarUtils.isAdmin() && opts.showRecommendedSwitch) {
3128								s += '<div style="position: relative;clear:both;">';
3129									s += '<a class="recommendedOnlyBtn hoverSelect'+et(opts.recommendedOnly ? ' selected' : '')+'" style="padding:3px 5px;display:block;text-align:'+ertl('left','right')+';cursor:pointer;position:absolute;bottom:2px;'+ertl('right','left')+':2px"';
3130									s += ' title="'+et(opts.recommendedOnly ? ls(3881) : ls(3882))+'"';
3131									s += '>';
3132									s += '<img src="/znamky/pics/schedule_ok_25.png" alt="" style="vertical-align:middle;width:25px;height:25px;">';							
3133									s += '</a>';						
3134								s += '</div>';
3135							}
3136							s += '</ul>';
3137						s += '</div>';
3138										
3139					s += '</div>';
3140				
3141				s += '</div>';	
3142				var predmetElem = $j(s).appendTo(mainElem);
3143				
3144				predmetElem.find('.planLink').on('click',function() {
3145					opts.planid = $j(this).attr('data-planid');
3146					if (opts.changeFunc) {
3147						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3148					}	
3149								
3150				});
3151				
3152				
3153				
3154				predmetElem.find('.predmetLink').on('click',function() {
3155					opts.predmetid = $j(this).attr('data-predmetid');
3156					opts.planid = '';
3157					if (opts.changeFunc) {
3158						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3159					}						
3160				});
3161				
3162				predmetElem.find('a.recommendedOnlyBtn').on('click',function() {
3163				
3164					opts.recommendedOnly = !opts.recommendedOnly;
3165					if (opts.changeFunc) {
3166						opts.changeFunc(opts.planid, opts.predmetid, opts.triedaid, opts.recommendedOnly);
3167					}   			
3168				});
3169	    	}
3170		    
3171		    function sortPlany(plany) {				
3172				var usp = [];
3173				for (var planid in plany) {
3174					usp.push(plany[planid]);					
3175				}
3176				
3177				usp.sort(function(pa,pb) {
3178												
3179					var nta = opts.triedy[pa["triedaid"]] ? opts.triedy[pa["triedaid"]]["Meno"] : '';
3180					var npa = opts.predmety[pa["predmetid"]] ? opts.predmety[pa["predmetid"]]["p_meno"] : '';
3181					var nla = pa["nazov"] ? pa["nazov"] : nta+(nta ? ' - ' : '')+npa;
3182					
3183					var ntb = opts.triedy[pb["triedaid"]] ? opts.triedy[pb["triedaid"]]["Meno"] : '';
3184					var npb = opts.predmety[pb["predmetid"]] ? opts.predmety[pb["predmetid"]]["p_meno"] : '';
3185					var nlb = pb["nazov"] ? pb["nazov"] : ntb+(ntb ? ' - ' : '')+npb;
3186					
3187					return (nta+' '+npa+' '+nla).localeCompare(ntb+' '+npb+' '+nlb);				
3188				});		
3189				return usp;
3190			}
3191			
3192			function groupPlanyByPredmet(plany) {
3193				var ret = {};
3194				for (var i=0;i<plany.length;i++) {
3195					var p = plany[i];
3196					if (p.planid == 'new') continue;
3197					var predmetid = p["predmetid"];
3198					if (!ret[predmetid]) ret[predmetid] = [];
3199					ret[predmetid].push(p);
3200				}
3201				return ret;
3202			}
3203			
3204			function groupPlanyByTrieda(plany) {
3205				var ret = {};
3206				for (var i=0;i<plany.length;i++) {
3207					var p = plany[i];
3208					var triedaid = p["triedaid"];
3209					if (!ret[triedaid]) ret[triedaid] = [];
3210					ret[triedaid].push(p);
3211				}
3212				return ret;
3213			}
3214			
3215			
3216			var publicActions = {};
3217		    
3218		    publicActions.getSelectedClass = function() {
3219		    	return selectedClass;
3220		    }
3221		    
3222		    publicActions.getSelectedSubject = function() {
3223		    	return selectedSubject;
3224		    }
3225		    
3226		    publicActions.getSelectedPlan = function() {
3227		    	return selectedPlan;
3228		    }
3229		    
3230		    publicActions.getPlanMenaUcitelov = function() {		    	
3231		    	var p = selectedPlan;
3232		    	if (!p) {
3233		    		return opts.loggedUserName ? opts.loggedUserName : '';
3234		    	}
3235		    	return p.ucitelid == 0 ? lset(1675) : p.menaUcitelov;;
3236		    }
3237		    
3238		    $j(this).data('publicActions',publicActions);
3239		   	createContent(); 
3240		}   
3241		
3242		
3243		    
3244		return this.each(main);
3245	};
3246		
3247	$.fn.planTriedaPredmetSelector.defaults = {	    	
3248		mojeTriedy: [],
3249		mojePredmety: [],
3250		plany: {},
3251		predmety: {},
3252		triedy: {},
3253		planid: '',
3254		triedaid: '',
3255		predmetid: '',
3256		showRecommendedSwitch: false,
3257		recommendedOnly: false,
3258		poradie: 'tp'			
3259	};
3260}
3261
3262ETestUtils.planTriedaPredmetSelector(jQuery);
3263
3264
3265
3266ETestUtils.openAddDialog = function(opts) {
3267	if (!opts) {
3268		opts = {};
3269	}
3270	
3271	var dlg = barNewDialog({
3272		content: '<div class="etestAddItem"></div>',
3273		dialogClass: 'whiteDialog noPadding',
3274		width: 940
3275	});
3276	
3277	dlg.find('.etestAddItem').etestAddItem(opts);
3278	
3279}
3280
3281
3282var ECourseClasses = {};
3283
3284ECourseClasses.addObject = function(data, opts) {
3285	if (!opts) opts = {};
3286	var postData = {
3287		planid: opts.planid ? opts.planid : '',
3288		temaid: opts.temaid ? opts.temaid : '-1',
3289		
3290		folder: opts.folder ? opts.folder : '',
3291		competenceids: opts.competenceids ? opts.competenceids : '',
3292		data: JSON.stringify(data)
3293	}
3294	
3295	if (!opts.formurl) opts.formurl = '/elearning/?cmd=ETestCreator';
3296	
3297	$.post(opts.formurl+'&akcia=addObjects', postData, function(data) {		
3298		if (opts.doneFunc) {
3299			opts.doneFunc(data);
3300		}								
3301	},'json');
3302};
3303
3304
3305
3306ECourseClasses.setObjectTopics = function(objektids, dstPlanid, topicids, opts, doneFunc) {
3307	if (!opts) opts = {};
3308	var postData = {
3309		dstPlanid: dstPlanid,
3310		topicids: topicids.join(';'),
3311		objektids: objektids.join(';'),
3312		options: JSON.stringify(opts) 
3313	}
3314	
3315	if (!opts.formurl) opts.formurl = '/elearning/?cmd=ETestCreator';
3316	
3317	$.post(opts.formurl+'&akcia=setObjectTopics', postData, function(data) {		
3318		if (doneFunc) {
3319			doneFunc(data);
3320		}								
3321	},'json');
3322};
3323
3324if ($j.ui && $j.ui.selectmenu) {
3325$j.widget( "edupage.iconselectmenu", $j.ui.selectmenu, {
3326     
3327	_renderItem: function( ul, item ) {
3328		var li = $j("<li>"), wrapper = $j("<div>", {
3329			text : item.label
3330		});
3331
3332		if (item.disabled) {
3333			li.addClass("ui-state-disabled");
3334		}
3335		
3336		if (item.element.attr('data-htmlText')) {
3337			wrapper.html(item.element.attr('data-htmlText'));
3338		}
3339
3340		if (item.element.attr('data-htmlTextR')) {
3341			wrapper.html(item.element.attr('data-htmlTextR'));
3342		}
3343		var icon = item.element.attr('data-icon');
3344		if (icon) {
3345			
3346			var s = '';
3347			s += '<span class="etest-menu-icon etest-selectmenu-icon'+et(this.options.itemIconClass ? ' '+this.options.itemIconClass : '')+'" >';
3348			if (icon.substr(0,1) == '!') {
3349				s += icon.substr(1);
3350			} else 
3351			if (icon.substr(0,3) == 'fa-') {
3352				s += renderS('<i class="fa {icon}" style="color: {color}"></i>',{icon: icon, color: item.element.attr('data-iconcolor')});
3353			} else {
3354				s += renderS('<img src="{icon}" alt="">', {
3355						icon: icon
3356					 });  
3357			}
3358			s += '</span>';
3359			
3360			$j(s).prependTo(wrapper);
3361		}
3362		
3363		var bgcolor = item.element.attr('data-bgcolor');
3364		if (bgcolor) {
3365			li.css('background-color',bgcolor);
3366		}
3367		
3368		return li.append(wrapper).appendTo(ul);
3369	},
3370	_renderButtonItem: function(item ) {
3371		
3372		
3373		var buttonItem = $j("<span>", {
3374			"class" : "ui-selectmenu-text"
3375		});		
3376		
3377		
3378		if (!item.value && item.element.attr('data-emptyifempty') == '1') {
3379			this._setText(buttonItem, '');
3380		} else {
3381			this._setText(buttonItem, item.label);
3382		} 
3383
3384		if (item.element.attr('data-htmlText')) {
3385			buttonItem.html(item.element.attr('data-htmlText'));
3386		}
3387
3388		
3389		var icon = item.element.attr('data-icon');
3390		if (icon) {
3391			
3392			var s = '';
3393			s += '<span class="etest-menu-icon etest-selectmenu-icon'+et(this.options.buttonIconClass ? ' '+this.options.buttonIconClass : '')+'" style="">';
3394			if (icon.substr(0,1) == '!') {
3395				s += icon.substr(1);
3396			} else 
3397			if (icon.substr(0,3) == 'fa-') {
3398				s += renderS('<i class="fa {icon}" style="color: {color}"></i>',{icon: icon, color: item.element.attr('data-iconcolor')});
3399			} else {
3400				s += renderS('<img src="{icon}" alt="" style="">', {
3401						icon: icon
3402					 });  
3403			}
3404			s += '</span>';
3405			
3406			$j(s).prependTo(buttonItem);
3407		}
3408		
3409		var bgcolor = item.element.attr('data-bgcolor');
3410		if (bgcolor) {
3411			buttonItem.css('background-color',bgcolor);
3412		}
3413		var color = item.element.attr('data-color');
3414		if (color) {
3415			buttonItem.css('color',color);
3416		}
3417		
3418		return buttonItem;
3419	}
3420});
3421}
3422
3423/*
3424
3425Seed random
3426Copyright 2014 David Bau.
3427
3428Permission is hereby granted, free of charge, to any person obtaining
3429a copy of this software and associated documentation files (the
3430"Software"), to deal in the Software without restriction, including
3431without limitation the rights to use, copy, modify, merge, publish,
3432distribute, sublicense, and/or sell copies of the Software, and to
3433permit persons to whom the Software is furnished to do so, subject to
3434the following conditions:
3435
3436The above copyright notice and this permission notice shall be
3437included in all copies or substantial portions of the Software.
3438
3439THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3440EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3441MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3442IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
3443CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
3444TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
3445SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3446*/
3447!function(a,b){function c(c,j,k){var n=[];j=1==j?{entropy:!0}:j||{};var s=g(f(j.entropy?[c,i(a)]:null==c?h():c,3),n),t=new d(n),u=function(){for(var a=t.g(m),b=p,c=0;a<q;)a=(a+c)*l,b*=l,c=t.g(1);for(;a>=r;)a/=2,b/=2,c>>>=1;return(a+c)/b};return u.int32=function(){return 0|t.g(4)},u.quick=function(){return t.g(4)/4294967296},u.double=u,g(i(t.S),a),(j.pass||k||function(a,c,d,f){return f&&(f.S&&e(f,t),a.state=function(){return e(t,{})}),d?(b[o]=a,c):a})(u,s,"global"in j?j.global:this==b,j.state)}function d(a){var b,c=a.length,d=this,e=0,f=d.i=d.j=0,g=d.S=[];for(c||(a=[c++]);e<l;)g[e]=e++;for(e=0;e<l;e++)g[e]=g[f=s&f+a[e%c]+(b=g[e])],g[f]=b;(d.g=function(a){for(var b,c=0,e=d.i,f=d.j,g=d.S;a--;)b=g[e=s&e+1],c=c*l+g[s&(g[e]=g[f=s&f+b])+(g[f]=b)];return d.i=e,d.j=f,c})(l)}function e(a,b){return b.i=a.i,b.j=a.j,b.S=a.S.slice(),b}function f(a,b){var c,d=[],e=typeof a;if(b&&"object"==e)for(c in a)try{d.push(f(a[c],b-1))}catch(a){}return d.length?d:"string"==e?a:a+"\0"}function g(a,b){for(var c,d=a+"",e=0;e<d.length;)b[s&e]=s&(c^=19*b[s&e])+d.charCodeAt(e++);return i(b)}function h(){try{var b;return j&&(b=j.randomBytes)?b=b(l):(b=new Uint8Array(l),(k.crypto||k.msCrypto).getRandomValues(b)),i(b)}catch(b){var c=k.navigator,d=c&&c.plugins;return[+new Date,k,d,k.screen,i(a)]}}function i(a){return String.fromCharCode.apply(0,a)}var j,k=this,l=256,m=6,n=52,o="random",p=b.pow(l,m),q=b.pow(2,n),r=2*q,s=l-1;if(b["seed"+o]=c,g(b.random(),a),"object"==typeof module&&module.exports){module.exports=c;}else"function"==typeof define&&define.amd&&define(function(){return c})}([],Math);
3448
3449
3450
3451ETestUtils.getSuperprideleniaTestu = function(testid, doneFunc) {	
3452	var superpridelenia = ETestUtils.getCached('superpridelenia_'+testid);
3453		
3454	if (!superpridelenia) {	    		
3455		$.post('/elearning/?cmd=ETestCreator&akcia=getSuperprideleniaTestu',{testids:testid}, function(pdata) {
3456			var data = pdata["superpridelenia"];
3457			superpridelenia = data[testid] ? data[testid] : [];
3458			ETestUtils.setCached('superpridelenia_'+testid, data);
3459			
3460			
3461			
3462			doneFunc(superpridelenia, pdata);
3463			
3464		},'json');
3465	} else {
3466		doneFunc(superpridelenia[testid] ? superpridelenia[testid] : [], superpridelenia);
3467	}	 
3468}
3469
3470
3471ETestUtils.deleteMaterial = function(options) {
3472	
3473	var testids = [];
3474	var cardids = [];
3475	var editableCards = [];
3476	var objektids = [];
3477	var globalCardids = [];
3478	var schoolCardids = [];
3479	
3480	if (options.testid) testids.push(options.testid);
3481	if (options.superid) testids.push('superid:'+options.superid);
3482	if (options.kurz_objektid) objektids.push(options.kurz_objektid);
3483	
3484	if (options.rows) {			
3485		for (var i=0;i<options.rows.length;i++) {
3486			var r = options.rows[i];
3487			
3488			var cardid = r.cardid.toString();
3489			
3490			if (cardid.substr(0,4) == 'Test') {
3491				var testid = cardid.substr(4);
3492				if (testid>0) {	
3493					testids.push(cardid.substr(4));
3494				} else {
3495					globalCardids.push(cardid);
3496				}
3497			} else if (cardid.substr(0,5) == 'Super') {
3498				testids.push('superid:'+cardid.substr(5));
3499			} else if (cardid.substr(0,4) == 'Card') {
3500				if (ETestUtils.isNumeric(cardid.substr(4))) {	
3501					if (r.userid != '0') {			
3502						editableCards.push(cardid.substr(4));
3503					}
3504					cardids.push(cardid.substr(4));
3505				} else {
3506					globalCardids.push(cardid.substr(4));
3507				}
3508			} else {
3509				if (ETestUtils.isNumeric(cardid)) {		
3510					if (r.userid != '0') {
3511						editableCards.push(cardid);
3512					}
3513					cardids.push(cardid);
3514				} else {
3515					globalCardids.push(cardid);
3516				}
3517			}
3518			
3519			if (r.objektid) {
3520				objektids.push(r.objektid);
3521			}
3522			
3523			if (r.inSchool) {
3524				schoolCardids.push(r.inSchool);
3525			}
3526		}
3527	}
3528		
3529	var s = '';
3530	
3531	//s += '<i class="fa fa-warning" style="color: #43A047;font-size:32px;float:'+ertl('left','right')+';margin:10px 20px 10px 10px;display:inline-block;"></i>';
3532	s += '<div style="margin-'+ertl('left','right')+':0px" class="mainContent">';	
3533	
3534	s += '</div>';
3535	s += '<div style="text-align:'+ertl('right','left')+';margin-top:10px;clear:both;">';
3536		s += '<input type="button" class="button-gray closeBtn" value="{#1038}" onclick="barCloseDialog(this)">';
3537	
3538	s += '</div>';
3539	
3540	s += '<div class="loadingDiv loading-background"></div>';
3541	
3542	var dlg = barNewDialog({
3543		'title': ls(8419),
3544		'content': renderS(s, {}),
3545		'dialogClass': MobileAppBridge.isActive() ? 'whiteDialog mobileDlgPadding fixedPos' : '',
3546		'width': 400,
3547		'close': function() {
3548			
3549		}
3550	});	
3551	dlg.find('.loadingDiv').show();
3552	
3553	
3554	
3555	function createInnerContent(superpridelenia, pdata, showAdvanced) {	
3556		dlg.find('.loadingDiv').hide();
3557		
3558		
3559		var buttons = [];
3560		var advancedButtons = [];
3561		
3562
3563		
3564		if (superpridelenia.length > 0) {
3565			advancedButtons.push({label: ls(8407), cssClass: 'button-red', action: 'superids'});
3566		}
3567		
3568		if (testids.length > 0) {
3569			advancedButtons.push({label: ls(8408), cssClass: 'button-red', action: 'all'});
3570		} else if (editableCards.length >0) {
3571			advancedButtons.push({label: ls(8409)+' ('+editableCards.length+')', cssClass: 'button-red', action: 'all'});
3572		}
3573		
3574		
3575		
3576		if (schoolCardids.length > 0) {
3577			advancedButtons.push({label: ls(8411)+' ('+schoolCardids.length+')', cssClass: 'button-aqua', action: 'schoolids'});
3578		}
3579		
3580		if (objektids.length == 0 || showAdvanced) {
3581			for (var i=0;i<advancedButtons.length;i++) {
3582				buttons.push(advancedButtons[i]);
3583			}
3584		}
3585
3586		if (objektids.length > 0) {
3587			buttons.push({label: ls(8410)+' ('+objektids.length+')', cssClass: 'button-aqua', action: 'objektids'});
3588		} 
3589		
3590		var s = '';
3591		if (testids.length == 1 && cardids.length == 0) {
3592			
3593			s += renderS('<p style="text-align:'+ertl('left','right')+'">'+et(lsf(8412,{name: pdata.testname}))+'</p>', {
3594					'name': pdata.testname
3595				 });
3596		} else if (cardids.length > 0 || testids.length > 0) {
3597			var items = [];
3598			if (cardids.length > 0 || globalCardids.length > 0) {
3599				items.push(ls(7886)+': '+cardids.length);
3600			}
3601			
3602			if (testids.length > 0) {
3603				items.push(ls(4964)+': '+testids.length);
3604			}
3605			s += renderS('<p style="text-align:'+ertl('left','right')+'">'+et(lsf(8413, {items: items.join(', ')}))+'</p>', {
3606					items: items.join(', ')
3607				 }); 
3608			 
3609		}
3610		
3611		if (globalCardids.length > 0) {
3612			
3613			s += renderS('<p style="text-align:'+ertl('left','right')+';margin-top:10px;">'+lset(8414, {count: globalCardids.lengt})+'</p>', {
3614					globalCardids: globalCardids.length
3615				 }); 
3616		}
3617		
3618		//s += '<br>';
3619		if (superpridelenia 
3620			&& testids.length == 1 
3621			&& cardids.length == 0
3622			&& (objektids.length == 0 || showAdvanced) ) {
3623			s += '<div class="materialAssignations">';
3624				if (superpridelenia.length == 0) {
3625					s += '<b style="opacity: 0.6">{#8415}</b>';
3626				} else {
3627					s += '<b>{#8416}:</b>';
3628					s += '<div style="padding: 10px 0px 0 0" class="etest-hwakcia-pridelenialist">';
3629						
3630						for (var i=0;i<superpridelenia.length;i++) {
3631				    		var sr = superpridelenia[i];
3632				    		
3633				    		var ss = '';
3634					    	ss += '<div data-id="{sr.superid}" style="color:inherit;padding:5px 10px 5px 45px;position: relative;border-bottom: 1px dashed rgba(0,0,0,0.1);border-top: 1px dashed rgba(0,0,0,0.1);margin-top:-1px;">';
3635					    		ss += '<label>';
3636						    		ss += '<div style="position:absolute;'+ertl('left','right')+':5px;top:5px;">';
3637						    			ss += '<input type="checkbox" name="superids" value="{sr.superid}" {checked} class="superidsCheck">';
3638						    		ss += '</div>';
3639						    		ss += '<div>';
3640							    		ss += '<div style="font-size:1.1em;">'
3641											ss += '{classname}';
3642										ss += '</div>';
3643										ss += '<div style="opacity: 0.7;font-weight: normal">';
3644											 ss += '{cas}';
3645										ss += '</div>';
3646									ss += '</div>';
3647								ss += '</label>';
3648								
3649								ss += '<div style="font-weight: bold;position:absolute;'+ertl('right','left')+':5px;top:5px;">';
3650									
3651									ss += '<a href="{href}" class="edubarSmartLink ecourse-link-button" style="padding:4px;color: inherit;text-decoration:none;">';
3652										ss += '{sr.vysledkov} / {sr.prideleni}';
3653									
3654										ss += ' <i class="fa fa-fw fa-external-link"></i>';
3655									ss += '</a>';
3656									
3657								ss += '</div>';
3658																			
3659					    	ss += '</div>';
3660					    	
3661					    	var classname = sr.planname 
3662					    					? sr.planname
3663					    					: (sr.classname+' - '+sr.subjectname);
3664					    	s += renderS(ss, {
3665					    			checked:  options.superid && options.superid == sr.superid ? 'checked' : '',
3666					    			sr: sr,		    			
3667									cas: sr.cas ? Date.fromDbString(sr.cas).format('d. M Y H:i') : '',
3668									classname: classname,
3669									href: barEncLink('/elearning/?cmd=EtestCreator&planid='+sr.planid+'&triedaid='+sr.triedaid+'&predmetid='+sr.predmetid+'&superid='+sr.superid)
3670				    			 });
3671				    	}
3672					
3673					s += '</div>';
3674				}
3675			s += '</div>';
3676		}
3677		
3678		
3679		s += '<div style="text-align:'+ertl('left','right')+';margin-top:10px;">';
3680		for (var i=0;i<buttons.length;i++) {
3681			var btn = buttons[i];
3682			s += '<div style="padding: 5px;">';
3683			s += renderS('<a  class="{btnCls} customBtn" data-ind="{ind}" style="display:block;padding:10px 15px;text-decoration:none;box-sizing: border-box">{title}</a>', {
3684					btnCls: btn.cssClass ? btn.cssClass : 'button-gray',
3685					title: btn.label,
3686					ind: i
3687				 });	
3688			s += '</div>';			
3689		}		
3690
3691		if (advancedButtons.length>0) {
3692			s += '<div style="padding: 5px;">';
3693			s += renderS('<label><input type="checkbox" name="showAdvanced" value="1" class="showAdvancedBtn" {checked}>{#2943}</label>', {					
3694					checked: showAdvanced ? 'checked' : ''										
3695				 });	
3696			s += '</div>';		
3697		}
3698		s += '</div>';
3699		s = renderS(s, {});
3700		
3701		dlg.find('.mainContent').html(s);
3702
3703		dlg.find(".showAdvancedBtn").on('click',function() {
3704			createInnerContent(superpridelenia, pdata, !showAdvanced);
3705		});
3706		
3707		dlg.find('.customBtn').click(function() {
3708			
3709			var ind = $j(this).attr('data-ind');
3710			var action = buttons[ind].action;
3711			var superids = [];
3712			
3713			dlg.find('.superidsCheck').each(function() {
3714				if (this.checked) {
3715					superids.push(this.value);
3716				}
3717			});
3718			
3719			if (action == 'superids' && superids.length == 0) {
3720				barShowMessageBox(ls(8417),'fa-info');
3721				return;
3722			}
3723			
3724			
3725			function doDelete() {
3726				dlg.find('.loadingDiv').show();
3727				var postData = {
3728					todelete: action,
3729					xsuperid: superids.join(';'),
3730					xtestid: testids.join(';'),
3731					xobjektid: objektids.join(';'),
3732					xcardids: cardids.join(';'),
3733					xschoolCardids: schoolCardids.join(';') 
3734				}
3735				$.post('/elearning/?cmd=EtestCreator&akcia=deleteMaterial', postData, function(data) {
3736					if (data.status == 'ok') {
3737						ETestUtils.clearCachedLike('superpridelenia_');
3738						barCloseDialog(dlg);
3739						if (options.doneFunc) {
3740							options.doneFunc();
3741						}
3742					}
3743				},'json');
3744			}
3745			
3746			if (buttons.length == 1 && action != 'all') {
3747				doDelete();
3748			} else {
3749				barShowMessageBox(ls(1054), 'fa-question', {
3750					confirm: function() {
3751						doDelete();	
3752					}
3753				});		
3754			}
3755		});
3756		
3757		barCenterDialog(dlg);
3758		barRefreshPage(dlg);
3759	}
3760	
3761	
3762	if (testids.length == 1 && cardids.length == 0) {		
3763		ETestUtils.getSuperprideleniaTestu(testids[0], createInnerContent);
3764	} else if (testids.length == 0 && cardids.length == 1) {
3765		createInnerContent([], {});
3766	} else {
3767		createInnerContent([], {});
3768	}
3769}
3770
3771
3772ETestUtils.deleteCard = function(options) {	
3773	var s = '';
3774	
3775	s += '<i class="fa fa-warning" style="color: #43A047;font-size:32px;float:'+ertl('left','right')+';margin:10px 20px 10px 10px;display:inline-block;"></i>';
3776	s += '<div style="margin-'+ertl('left','right')+':70px" class="mainContent">';	
3777	
3778	s += '</div>';
3779	s += '<div style="text-align:'+ertl('right','left')+';margin-top:10px;clear:both;">';
3780		s += '<input type="button" class="button-gray closeBtn" value="{#1038}" onclick="barCloseDialog(this)">';
3781	
3782	s += '</div>';
3783	
3784	s += '<div class="loadingDiv loading-background"></div>';
3785	
3786	var dlg = barNewDialog({
3787		'title': ls(8419),
3788		'content': renderS(s, {}),
3789		'width': 450,
3790		'close': function() {
3791			
3792		}
3793	});	
3794	dlg.find('.loadingDiv').show();
3795	ETestUtils.getSuperprideleniaTestu(options.testid ? options.testid : 'superid:'+options.superid, function(superpridelenia, pdata) {	
3796		dlg.find('.loadingDiv').hide();
3797		
3798		
3799		var buttons = [];
3800		if (superpridelenia.length > 0) {
3801			buttons.push({label: ls(8407), cssClass: 'button-red', action: 'superids'});
3802		}
3803		buttons.push({label: ls(8418), cssClass: 'button-red', action: 'testids'});
3804		
3805		if (options.kurz_objektid) {
3806			buttons.push({label: ls(8420), cssClass: 'button-aqua', action: 'objektids'});
3807		}
3808		
3809		var s = '';
3810			
3811		s += renderS('<p style="text-align:'+ertl('left','right')+'">'+et(lsf(8412,{name: pdata.testname}))+'</p>', {
3812				'name': pdata.testname
3813			 });
3814		
3815		s += '<br>';
3816		s += '<div class="materialAssignations">';
3817			s += '<b>All assignations of the material:</b>';
3818			s += '<div style="padding: 10px 0px 0 0" class="etest-hwakcia-pridelenialist">';
3819				
3820				for (var i=0;i<superpridelenia.length;i++) {
3821		    		var sr = superpridelenia[i];
3822		    		
3823		    		var ss = '';
3824			    	ss += '<div data-id="{sr.superid}" style="color:inherit;padding:5px 10px 5px 45px;position: relative;border-bottom: 1px dashed rgba(0,0,0,0.1);border-top: 1px dashed rgba(0,0,0,0.1);margin-top:-1px;">';
3825			    		ss += '<label>';
3826				    		ss += '<div style="position:absolute;'+ertl('left','right')+':5px;top:5px;">';
3827				    			ss += '<input type="checkbox" name="superids" value="{sr.superid}" {checked} class="superidsCheck">';
3828				    		ss += '</div>';
3829				    		ss += '<div>';
3830					    		ss += '<div style="font-size:1.1em;">'
3831									ss += '{classname}';
3832								ss += '</div>';
3833								ss += '<div style="opacity: 0.7;font-weight: normal">';
3834									 ss += '{cas}';
3835								ss += '</div>';
3836							ss += '</div>';
3837						ss += '</label>';
3838						
3839						ss += '<div style="font-weight: bold;position:absolute;'+ertl('right','left')+':5px;top:5px;">';
3840							
3841							ss += '<a href="{href}" class="edubarSmartLink ecourse-link-button" style="padding:4px;color: inherit;text-decoration:none;">';
3842								ss += '{sr.vysledkov} / {sr.prideleni}';
3843							
3844								ss += ' <i class="fa fa-fw fa-external-link"></i>';
3845							ss += '</a>';
3846							
3847						ss += '</div>';
3848																	
3849			    	ss += '</div>';
3850			    	
3851			    	var classname = sr.planname 
3852			    					? sr.planname
3853			    					: (sr.classname+' - '+sr.subjectname);
3854			    	s += renderS(ss, {
3855			    			checked:  options.superid && options.superid == sr.superid ? 'checked' : '',
3856			    			sr: sr,		    			
3857							cas: sr.cas ? Date.fromDbString(sr.cas).format('d. M Y H:i') : '',
3858							classname: classname,
3859							href: barEncLink('/elearning/?cmd=EtestCreator&planid='+sr.planid+'&triedaid='+sr.triedaid+'&predmetid='+sr.predmetid+'&superid='+sr.superid)
3860		    			 });
3861		    	}
3862			
3863			s += '</div>';
3864		s += '</div>';
3865		
3866		s += '<div style="text-align:'+ertl('left','right')+';margin-top:10px;">';
3867		for (var i=0;i<buttons.length;i++) {
3868			var btn = buttons[i];
3869			s += '<div style="padding: 5px;">';
3870			s += renderS('<input type="button" class="{btnCls} customBtn" value="{title}" data-ind="{ind}" style="padding:10px 15px;width:250px">', {
3871					btnCls: btn.cssClass ? btn.cssClass : 'button-gray',
3872					title: btn.label,
3873					ind: i
3874				 });	
3875			s += '</div>';			
3876		}		
3877		s += '</div>';
3878		s = renderS(s, {});
3879		dlg.find('.mainContent').html(s);
3880		
3881		dlg.find('.customBtn').click(function() {
3882			
3883			var ind = $j(this).attr('data-ind');
3884			var action = buttons[ind].action;
3885			var superids = [];
3886			
3887			dlg.find('.superidsCheck').each(function() {
3888				if (this.checked) {
3889					superids.push(this.value);
3890				}
3891			});
3892			
3893			if (action == 'superids' && superids.length == 0) {
3894				barShowMessageBox(ls(8417),'fa-info');
3895				return;
3896			}
3897			
3898			
3899			
3900			
3901			barShowMessageBox(ls(1054), 'fa-question', {
3902				confirm: function() {
3903					dlg.find('.loadingDiv').show();
3904					var postData = {
3905						todelete: action,
3906						xsuperid: superids.join(';'),
3907						xtestid: options.testid,
3908						xobjektid: options.kurz_objektid
3909					}
3910					$.post('/elearning/?cmd=EtestCreator&akcia=deleteMaterial', postData, function(data) {
3911						if (data.status == 'ok') {
3912							ETestUtils.clearCachedLike('superpridelenia_');
3913							barCloseDialog(dlg);
3914							if (options.doneFunc) {
3915								options.doneFunc();
3916							}
3917						}
3918					},'json');
3919				}
3920			});		
3921		});
3922		
3923		barCenterDialog(dlg);
3924		barRefreshPage(dlg);
3925	});
3926}
3927
3928ETestUtils.getResultCirc = function(options) {
3929	if (!options) options = {};
3930	var stats = options.stats;
3931	
3932	var s3 = '';
3933	s3 += '<div class=" etest-pie-chart {tips} {moreClasses}" data-action="{action}"';
3934			s3 += ' data-superid="{superid}" data-testid="{testid}" title="{title}"';
3935			if (options.cardids) {
3936				s3 += renderS(' data-cardids="{cardids}"', {cardids: options.cardids.join(';')}); 
3937			}
3938			s3 += '>';
3939		s3 += '<svg viewBox="0 0 32 32" >';
3940			s3 += '<circle class="outer2" r="16" cx="16" cy="16" style="stroke-dasharray: {correctPercentInt} 100;fill:{colorBg};stroke:{color}"/>';
3941			if (options.innerCircle !== false) {
3942				s3 += '<circle class="inner2" r="{innerRadius}" cx="16" cy="16" style="stroke-dasharray: {correctPercentInt} 100;fill:{innerFill}"/>';
3943			}
3944		s3 += '</svg>';
3945		s3 += '<div class="title">';											
3946		s3 += '{!percentStrI}';
3947		s3 += '</div>';
3948	s3 += '</div>';
3949	var percentVal = stats.total_count == 0 ? 0 : Math.round(stats.correct_count/stats.total_count*1000)/10;
3950	var c = stats.total_count == 0 ? (options.emptyColor ? options.emptyColor : '#607D8B') : '#F44336';
3951	
3952	var title = '';
3953	if (options.cas || options.casStr || options.nazov) {
3954		title += '<span style="opacity:0.7">{cas}</span><br><b>{nazov}</b><br>';
3955	}
3956	title += '<div style="white-space:nowrap">{correct_count} {#8011} {stats.total_count} = {percentStr}%</div>';
3957	if (stats.card_count) {
3958		title += '({#7886}: {stats.card_count})';
3959	}
3960	
3961	title = renderS(title, {				
3962				stats: stats,
3963				correct_count: stats.correct_count ? parseFloat(stats.correct_count).toFixed(2) : 0,
3964				percentStr: percentVal.toFixed(1)+'',
3965				cas: options.casStr ? options.casStr : (options.cas ? Date.fromDbString(options.cas).format('d. F Y') : ''),
3966				nazov: options.nazov ? options.nazov : ''
3967			 });
3968	var s = renderS(s3,{
3969			tips: options.useTips !== false ? 'tips' : '',
3970			superid: options.superid ? options.superid : '',
3971			testid: options.testid ?  options.testid : '',
3972			moreClasses: options.classes ? options.classes : '',
3973			action: options.action ? options.action : '',			 
3974			stats: stats,
3975			color: '',
3976			colorBg: c,
3977			innerFill: options.innerFill ? options.innerFill : '#ffffff',
3978			innerRadius: options.innerRadius ? options.innerRadius : '11',
3979			percentVal: percentVal,			
3980			correctPercentInt: Math.round(percentVal),
3981			percentStr: stats.total_count == 0 ? '-' : percentVal.toFixed(0)+'',
3982			percentStrI: options.innerText ? options.innerText : (stats.total_count == 0 ? '<i class="fa fa-hourglass-half"></i>' : percentVal.toFixed(0)+''),			
3983			title: title					    						
3984		  });
3985	 
3986	 return s;
3987}
3988
3989ETestUtils.getWeekStr = function(week, reverse, maxDate, minDate) {
3990	var weekStr = '';		    				
3991	var ds = Date.fromDbString(week);
3992	var de = Date.fromDbString(week);
3993	de.setDate(ds.getDate()+6);
3994
3995	if (maxDate && de.format('Y-m-d')> maxDate) de = Date.fromDbString(maxDate);
3996	if (minDate && ds.format('Y-m-d') < minDate) ds = Date.fromDbString(minDate);
3997
3998
3999	if (reverse) {
4000		var pom = ds;
4001		ds = de;
4002		de = pom;		
4003	}
4004	var weekStr = ds.format('F d');
4005	var oldM = ds.getMonth();
4006	weekStr += ' - ';
4007	
4008	if (oldM != de.getMonth()) {
4009		weekStr += de.format('F ');
4010	}
4011	weekStr += de.format('d');	
4012	return weekStr;
4013}
4014
4015ETestUtils.getInvalidCourseMsg = function(row) {
4016	var s = '';
4017	s += '<div style="max-width:800px">';
4018	if (row && row.name) s += '<b style="opacity: 0.8">'+et(row.name)+':</b><br>';
4019	s += lset(8421);
4020	s += '</div>';
4021	if (!MobileAppBridge.isActive()) {
4022		s += '<div style="margin-top:10px;">';
4023			s += '<a class="flat-button flat-button-greenm actionButton etest-action-button" data-action="showPlanSettings" style="color:#fff">';
4024				s += lset(1090);
4025			s += '</a>';
4026			
4027			s += ' <a class="flat-button flat-button-greenm actionButton etest-action-button" data-action="showQIntro" data-introid="courses_notofficial" style="color:#fff">';
4028				s += lset(8081);
4029			s += '</a>';
4030
4031
4032			s += ' <a class="flat-button flat-button-greenm actionButton etest-action-button" data-action="switchCourse" data-introid="courses_notofficial" style="color:#fff">';
4033				s += lset(8690);
4034			s += '</a>';
4035		s += '</div>';
4036	}
4037	return s;
4038}
4039
4040ETestUtils.handleActionGlobal = function(elem) {
4041	var action = $(elem).attr('data-action');
4042	if (action == 'showQIntro') {
4043		$.post('/quickintro/?cmd=QIntroSlider&forceShow=1&template='+$(elem).attr('data-introid'), {}, function(data) {
4044			$j('body').append(data);	
4045		});	
4046		
4047		return true;	
4048	} else
4049	if (action == 'getHelp') {
4050		var id = $(elem).attr('data-id') || '';
4051		var hid = $(elem).attr('data-hid') || '';
4052		var path = $(elem).attr('data-p') || '';
4053		barNewDialog({			
4054			'source': '/customize/helpus.php?cmd=HelpusHelpDialog&helpid='+id+'&hashid='+hid+'&helpp='+path
4055		});	
4056		return true;	
4057	} else 
4058	if (action == 'switchCourse') {
4059
4060		barSmartLoadPage('/elearning/?cmd=Standards&ed=last')
4061
4062		return true;
4063	}
4064	return false;
4065}
4066
4067ETestUtils.handleActionButton = function(elem, actionFuncs, event) {
4068	if (ETestUtils.handleActionGlobal(elem)) return;
4069	    	
4070	var action = $(elem).attr('data-action');
4071	if (actionFuncs[action]) {
4072		actionFuncs[action](elem, event);
4073		return true;
4074	} else {
4075		barShowMessageBox('FIXME: this feature has to be implemented', 'fa-cog');
4076	}
4077	
4078	return false; 	
4079}
4080
4081
4082ETestUtils.hashArray = function(arr) {
4083	
4084	var ret = {};
4085	if (arr) {
4086		for (var i=0;i<arr.length;i++) {
4087			var r = arr[i];
4088			ret[r] = true;
4089		}
4090	}
4091	
4092	return ret;
4093}
4094
4095ETestUtils.groupArray = function(arr, key, singleItem) {
4096	
4097	var ret = {};
4098	if (arr) {
4099		for (var i=0;i<arr.length;i++) {
4100			var r = arr[i];
4101			var ind = r[key] ? r[key] : '';
4102			
4103			if (singleItem) {
4104				ret[ind] = r;
4105			} else {
4106				if (!ret[ind]) ret[ind] = [];
4107				ret[ind].push(r);
4108			}
4109			
4110		}
4111	}
4112	
4113	return ret;
4114}
4115
4116ETestUtils.renderKatex = function(elem) {
4117	
4118	renderMathInElement(elem, {
4119		delimiters: [
4120			{left: "$$", right: "$$", display: true},
4121			{left: "$", right: "$", display: false}
4122		],
4123		errorCallback: function(msg, err) {			
4124	        console.log(msg+err.message);
4125	    },
4126		throwOnError: false,
4127		unicodeTextInMathMode: true
4128	});	
4129	
4130}
4131
4132ETestUtils.renderMarkdownToHtml = function(text) {
4133	return text;
4134}
4135
4136ETestUtils.compareWords = function(s,t) {
4137	if (!s) s = '';
4138	if (!t) t = '';
4139	t = t.toString();
4140	s = s.toString();
4141	
4142	var m = s.length;
4143	var n = t.length;
4144	
4145	var d = [];
4146	var i,j;
4147	for (i=0;i<=m;i++) {
4148		var x = [];
4149		for (var j=0;j<n;j++) {
4150			x.push(null);
4151		}
4152		d.push(x);
4153	}
4154	
4155	var item;
4156	for (i=0;i<=m;i++) {
4157		item = {}
4158		item["cost"]=i;
4159		item["fromx"]=i-1;
4160		item["fromy"]=0;
4161		item["zmena"]=1;
4162		d[i][0]=item;
4163	}
4164	for (i=0;i<=n;i++) {
4165		item = {}
4166		item["cost"]=i;
4167		item["fromx"]=0;
4168		item["fromy"]=i-1;
4169		item["zmena"]=0;
4170		d[0][i]=item;
4171	}
4172	for (i=1;i<=m;i++) {
4173		for (j=1;j<=n;j++) {
4174			item = {}
4175			var pom = 0;
4176			if (s.charAt(i-1)!=t.charAt(j-1)) pom=1;
4177			item["cost"]=d[i-1][j-1]["cost"]+pom;
4178			item["fromx"]=i-1;
4179			item["fromy"]=j-1;
4180			item["zmena"]=pom;
4181			if (d[i][j-1]["cost"]+1<item["cost"]) {
4182				item["cost"]=d[i][j-1]["cost"]+1;
4183				item["fromx"]=i;
4184				item["fromy"]=j-1;
4185				item["zmena"]=-1;
4186			}
4187			if (d[i-1][j]["cost"]+1<item["cost"]) {
4188				item["cost"]=d[i-1][j]["cost"]+1;
4189				item["fromx"]=i-1;
4190				item["fromy"]=j;
4191				item["zmena"]=1;
4192			}
4193			d[i][j]=item;	
4194		}
4195	}
4196	var akx = m;
4197	var aky = n;
4198	var olx = m;
4199	var oly = n;
4200
4201	var ret = new Array(m);
4202	
4203	for (i=0;i<m;i++) ret[i]=0;
4204	while (akx>0 || aky>0) {
4205		if (d[akx][aky]["zmena"]==1) {
4206			if (akx>0)
4207				ret[akx-1]=1
4208		}
4209		if (d[akx][aky]["zmena"]==-1) {
4210			if (akx>0) {
4211			//	ret[akx-1]=1;
4212			}
4213			if (akx<m) {
4214				ret[akx]=1;
4215			}			
4216		}
4217		olx = akx;oly = aky;
4218		akx = d[olx][oly]["fromx"];
4219		aky = d[olx][oly]["fromy"];
4220	}
4221	
4222	return ret;
4223}
4224
4225ETestUtils.markChangesInWords = function(s,t) {
4226	if (!t) t = '';
4227	if (!s) s = '';
4228	var zmeny = [];
4229	for (var j=0;j<t.length;j++) {
4230		zmeny.push(0);
4231	}
4232	
4233	
4234	var pom = ETestUtils.compareWords(t, s);
4235	for (var k=0;k<pom.length;k++) {
4236		zmeny[k]+= pom[k];
4237	}
4238	
4239	var ht = '';
4240	for (var j=0;j<t.length;j++) {
4241		var c = t.charAt(j);
4242		if (zmeny[j]>0) {
4243			ht += '<span style="color:red">'+et(c)+'</span>';
4244		} else {
4245			ht += et(c);
4246		}
4247	}
4248	return ht;
4249}
4250
4251ETestUtils.openImagePreview = function(options) {	
4252	var images = options.images ? options.images : [];
4253	var mamVideo = false;
4254	for (var i=0;i<images.length;i++) {
4255		var src = images[i];
4256		
4257		if (src.substr(0,8) == 'youtube:') {
4258			mamVideo = true;
4259			break;
4260		}
4261	}
4262	if (mamVideo && !options.useImageFunc) {
4263		return ETestUtils.openImagePreview0(options);	
4264	}
4265	
4266	if (options.allowMultiple && MobileAppBridge.isActive() && window["EdupageApp"]) {
4267		return ETestUtils.openImagePreviewMulti(options);
4268	}
4269	return ETestUtils.openImagePreview1(options);
4270}
4271
4272ETestUtils.openImagePreviewMulti = function(options) {
4273	EdupageApp.pushReactComponentView("/app/pics/jsw/views/noticeboard/GalleryView.js",{
4274		noTransitions: true,
4275		photosData: {
4276			status: 'loaded',
4277			data: {
4278				photos: (options.images || []).map(function(r0) { 
4279					var r = typeof r0 == 'string' ? {src: r0} : r0;
4280					return {
4281						src: r.src,
4282						hdsrc: r.src,
4283						thumb: r.src,
4284						title: r.title || "",
4285						time: r.time || "",
4286						name: r.name || ""
4287					}
4288				}),
4289				index: options.index ? parseInt(options.index) : 0,
4290				galleryTitle: "",
4291				galleryDesc: ""
4292			}
4293		}
4294	}, {
4295		viewClass: 'GalleryView'
4296	})
4297
4298	var etestImagePreview = {};
4299	etestImagePreview.close = function() {
4300		
4301	};
4302	etestImagePreview.gotoSlide = function(index, playVideo) {
4303		
4304	}
4305	return etestImagePreview;
4306}
4307ETestUtils.openImagePreview1 = function(options) {
4308	var wasFullScreenElem = (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
4309	var dlgElem = ETestUtils.openFullScreenDialog({
4310		className: 'etest-overlay-photoswipe etest-player-front',
4311		addToElem: $('body'),
4312		fullScreen: true,
4313		returnFunc: function(val)  {
4314			//ReactDOM.unmountComponentAtNode(dlgElem.get(0));			
4315		}
4316	});
4317
4318	dlgElem.on('remove',function() {
4319		ReactDOM.unmountComponentAtNode(dlgElem.get(0));		
4320	});
4321
4322	function close() {
4323		barCloseDialog(dlgElem);
4324		
4325		if (wasFullScreenElem) {
4326			setTimeout(function() {	
4327				var isFullScreen = (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
4328				if (!isFullScreen) {
4329					if (wasFullScreenElem.requestFullScreen) {
4330						wasFullScreenElem.requestFullScreen();
4331					} else if(wasFullScreenElem.mozRequestFullScreen) {
4332						wasFullScreenElem.mozRequestFullScreen();
4333					} else if(wasFullScreenElem.webkitRequestFullScreen) {
4334						wasFullScreenElem.webkitRequestFullScreen();		
4335					} else if(element.msRequestFullscreen) {
4336						wasFullScreenElem.msRequestFullscreen();		
4337					}
4338				}
4339			},20);
4340		}
4341		if (options.onclose) {
4342			options.onclose();
4343		}	
4344	}
4345	
4346	var imageProps = options.imageProps ? options.imageProps : [];
4347
4348	var props = {
4349		photos: [],
4350		onclose: function() {
4351			close();
4352		},
4353		onslideChange: function(index) {
4354			if (options.onslideChange) {
4355				options.onslideChange(index);
4356			}
4357		},		
4358		index: options.index ? parseInt(options.index) : 0,
4359		answerComment:  options.answerComment || "",
4360		showAnswerComment: !!options.showAnswerComment,
4361		wasFullScreenBefore: wasFullScreenElem ? true : false,
4362		/*answerCommentReadonly: !!options.answerCommentReadonly,
4363		onChangeComment: options.onChangeComment*/
4364	};
4365
4366
4367	if (options.photos && options.photos.length > 0) {
4368		props.photos = [];
4369		for (var i=0;i<options.photos.length;i++) {
4370			var f = $.extend({}, options.photos[i]);
4371			/*if (f.src) {
4372				var fsrc = f.src || "";
4373				if (!fsrc.endsWith('v=3')) {
4374					fsrc += (fsrc.indexOf('?')>= 0 ? '&' : '?')+'v=3';
4375				}
4376				f.src = fsrc;
4377			}*/
4378			props.photos.push(f);
4379		}
4380	} else {
4381		var images = options.images ? options.images : [];
4382		for (var i=0;i<images.length;i++) {
4383			var src = images[i];
4384			var fsrc = src || "";
4385			/*if (!fsrc.endsWith('v=3')) {
4386				fsrc += (fsrc.indexOf('?')>= 0 ? '&' : '?')+'v=3';
4387			}*/
4388			props.photos.push({
4389				src: fsrc,
4390				title: ""
4391			});
4392		}
4393	}
4394	
4395	for (var x in options) {
4396		if (!props[x]) {
4397			props[x] = options[x];
4398		}
4399	}
4400
4401	var src = '/elearning/pics/jsw/AscPhotoSwipe.js';
4402	var componentName = 'AscPhotoSwipe';
4403	barJsLibraryLoad(edubar && edubar.options && edubar.options.srcv ? edubar.options.srcv : '/global/pics/js/srcv.js?v='+(new Date()).getTime(), function() {	
4404		ASC.requireAsync(src).then(function(c){
4405			ASC.requireAsync('react-dom').then(function(ReactDOM){
4406				window.ReactDOM = ReactDOM;
4407				var React=ASC.require('react');
4408				ReactDOM.render(React.createElement(c[componentName],props),dlgElem.get(0));
4409				//barNewReactDlg(React.createElement(c[componentName],props), options);
4410			});
4411		});
4412	});
4413
4414	var etestImagePreview = {};
4415	etestImagePreview.close = function() {
4416		close();
4417	};
4418	etestImagePreview.gotoSlide = function(index, playVideo) {
4419		var pswp = dlgElem.data('pswp');
4420		if (pswp) {
4421			pswp.goTo(parseInt(index));		
4422		}
4423	}
4424	return etestImagePreview;
4425}
4426
4427ETestUtils.openImagePreview0 = function(options) {
4428	if (!options) options = {};
4429
4430	var etestImagePreview = {};
4431	
4432
4433	barCssLoad('/global/pics/js/jquery/royalSlider/skins/edupage/rs-edupage-info.css?v=2');
4434	barJsLibraryLoad('/global/pics/js/jquery/jquery.royalslider.min.js?v=5', function() {
4435		var appendToElem = options.appendToElem ? options.appendToElem : $j('body');
4436		var images = options.images ? options.images : [];
4437		var imageProps = options.imageProps ? options.imageProps : [];
4438		var mamVideo = false;
4439		var s = '';
4440		s += '<div class="etest-image-preview etest-player-front ui-front">';
4441			s += '<div class="etest-image-preview-inner">';
4442				s += '<div class="etest-image-preview-slider royalSlider rsDefault" style="width:100vw;height:100vh">';
4443					for (var i=0;i<images.length;i++) {
4444						var src = images[i];
4445						var rsvideo = '';
4446						if (src.substr(0,8) == 'youtube:') {
4447							mamVideo = true;
4448							var code = src.substr(8);
4449							src = 'https://img.youtube.com/vi/'+et(code)+'/0.jpg';
4450							
4451							
4452								s += renderS('<img src="{src}" class="rsImg" alt="{caption}" data-rsVideo="https://www.youtube.com/watch?v='+et(code)+'">', {
4453									src: src,
4454									caption: '',									
4455								});							
4456						} else {
4457							s += renderS('<div class="etest-image-preview-img-outer"><img src="{src}" class="etest-image-preview-img" alt="{caption}"></div>', {
4458									src: src,
4459									caption: imageProps[i] && imageProps[i].caption ? imageProps[i].caption: '',									
4460								});
4461						}
4462					}
4463				s += '</div>';
4464			s += '</div>';
4465			s += '<a class="etest-image-preview-close">';
4466				s += '<i class="fa fa-fw fa-close"></i>';
4467			s += '</a>'; 
4468			
4469			if (options.useImageFunc) {
4470				s += '<a class="flat-button flat-button-blue flat-button-big useImageBtn" style="position: fixed;bottom: 20px;'+ertl('right','left')+':20px;box-shadow: 1px 1px 3px rgba(0,0,0,0.4);z-index: 10000;padding: 10px 15px;font-size:16px;">{#8422}</a>';
4471			}
4472
4473			if (true) {
4474				s += '<div class="etest-image-preview-controls">';
4475					s += 
4476				s += '</div>';
4477			}
4478		s += '</div>';
4479		
4480		s = renderS(s, {
4481				
4482			});
4483		
4484		
4485		
4486		var elem = $j(s).appendTo($j(appendToElem));
4487		
4488		
4489		function close() {
4490			
4491			barUnregisterPopstateHandler(elem.get(0));
4492			$j(elem).remove();
4493			$j(elem).off();
4494			$j(document).off('keydown.etestimagepreview');
4495			
4496			window.skipDialogClose = false;
4497						
4498			$(window).off('popstate.etestimagepreview');	
4499			
4500			if (options.onclose) {
4501				options.onclose();
4502			}			
4503		}
4504		
4505		elem.on('remove',function() {			
4506			$j(document).off('keydown.etestimagepreview');
4507		});		
4508
4509		
4510		slider = elem.find(".etest-image-preview-slider").royalSlider({            
4511			keyboardNavEnabled: true,
4512			arrowsNavAutoHide: false,
4513			autoScale: false,
4514			imageScaleMode: mamVideo ? "fill" : "fit",
4515			startSlideId: options.index ? options.index : 0,
4516			controlNavigation: images.length > 10 ? 'none' : 'bullets'  ,
4517			globalCaption: options.imageProps ? true : false,
4518			video: {
4519				autoHideControlNav: true,
4520				youTubeCode: '<div  data-code="%id%" id="etestPreviewVideoPlayer"></div>',//<iframe class="etest-video-iframe" src="https://www.youtube.com/embed/%id%?autoplay=1&origin='+et(window.location.origin)+'" frameborder="0" allowfullscreen></iframe>',//<iframe src="https://www.youtube.com/embed/%id%?rel=1&autoplay=1&showinfo=0" allowfullscreen frameborder="no"></iframe>'                      
4521			}
4522		}).data('royalSlider');
4523		
4524		
4525		slider.ev.on('rsBeforeAnimStart', function(event) {
4526			// triggers after slide change			
4527			if (options.onslideChange) {
4528				options.onslideChange(slider.currSlideId);
4529			}			
4530		});
4531
4532		slider.ev.on('rsVideoPlay', function(event) {
4533			// triggers after slide change		
4534			console.log('play');	
4535				
4536			var code = $('#etestPreviewVideoPlayer').attr('data-code');
4537			barLoadYoutubeApi(function() {	
4538				new YT.Player('etestPreviewVideoPlayer', {
4539					height: '100%',
4540					width: '100%',
4541					videoId: code,
4542					playerVars: {
4543						enablejsapi: '1',
4544						fs: '1',
4545						iv_load_policy: '3',
4546						origin: window.location.origin,					
4547						controls: '1',
4548						modestbranding: '1',
4549						autohide: '1',
4550						rel: '0'
4551					},
4552					events: {
4553						'onReady': function(event) {						
4554							event.target.playVideo();	
4555							$('#etestPreviewVideoPlayer').data('ytplayer',event.target);
4556							if (options.onvideoPlay) {
4557								options.onvideoPlay(slider.currSlideId);
4558							}	
4559						},
4560						'onStateChange': function(event) {
4561							if (event.data == 1) {
4562								if (options.onvideoPlay) {
4563									options.onvideoPlay(slider.currSlideId);
4564								}
4565							}
4566							if (event.data == 2) {
4567								if (options.onvideoStop) {
4568									options.onvideoStop(slider.currSlideId);
4569								}	
4570							}						
4571						}
4572					}
4573				});
4574			});
4575		});
4576
4577		slider.ev.on('rsVideoStop', function(event) {	
4578			if (options.onvideoStop) {
4579				options.onvideoStop(slider.currSlideId);
4580			}			
4581		});
4582
4583		elem.find('.etest-image-preview-close').click(function() {			
4584			close()
4585		});
4586		
4587		elem.find('.rsGCaption').click(function() {
4588			var ind = slider.currSlideId;
4589			if (imageProps[ind].url) {
4590				window.open(imageProps[ind].url);
4591			}
4592		});
4593		
4594		if (options.useImageFunc) {
4595			elem.find('.useImageBtn').click(function() {
4596				var ind = slider.currSlideId;
4597				close();
4598				options.useImageFunc(ind);		
4599			});
4600		}
4601		window.skipDialogClose = true;
4602		
4603		$j(document).off('keydown.etestimagepreview').on('keydown.etestimagepreview',function(event) {			
4604			if (event.which == 27) {
4605				
4606				event.stopPropagation();
4607				event.preventDefault();
4608				close();
4609			}
4610		});
4611				
4612		
4613		if (MobileAppBridge.isActive()) {
4614			MobileAppBridge.registerBackHandler(elem.get(0), function() {
4615				close();
4616			});
4617		} else {
4618			barRegisterPopstateHandler(elem.get(0), function() {
4619				close();
4620			});
4621			
4622		}
4623
4624		if (options.videoPlaying) {
4625			slider.playVideo();
4626		}
4627
4628
4629		etestImagePreview.close = close;
4630		etestImagePreview.gotoSlide = function(index, playVideo) {
4631			slider.goTo(index);
4632			var ytplayer = $('#etestPreviewVideoPlayer').data('ytplayer');
4633			if (ytplayer) {
4634				if (playVideo) {
4635					ytplayer.playVideo();
4636				} else {
4637					ytplayer.pauseVideo();
4638				}
4639			} else 
4640			if (playVideo) {
4641				slider.playVideo();
4642			} 
4643		}
4644		
4645	});
4646
4647	return etestImagePreview;
4648}
4649
4650
4651ETestUtils.scaleToFitWindow = function(elem, options) {
4652	if(!options) options = {};
4653	var appendToElem = options.appendToElem ? options.appendToElem : $(window);
4654	var sizeElem = $(window);//options.sizeElem ? options.sizeElem : appendToElem;
4655	var ww0 = $(window).width();
4656	var ww = $(sizeElem).outerWidth() - (options.padding ? options.padding*2 : 0);
4657	var wh = $(sizeElem).outerHeight() - (options.padding ? options.padding*2 : 0);
4658	
4659	var padding = 0;
4660		
4661	var sw = Math.min(800, ww);	
4662	var sh = sw/ww*wh;
4663
4664
4665	elem.outerWidth(sw-padding);
4666
4667	var eoh = elem.outerHeight()
4668	if (!elem.data('orig-height')) {
4669		elem.data('orig-height',eoh);
4670	}
4671	
4672	elem.css('min-height',(sh-padding)+'px');//.outerHeight(sh-padding);
4673	
4674	var sc = Math.floor(((ww)/(sw))*100)/100;
4675	var translateX = 0;
4676	if (sc > 1.005 && elem.outerHeight()*sc > wh) {
4677		//ak zoomujeme a sme vacsi ako vyska, skusime sa pozriet na to, ci mensi			
4678		var sc2 = wh/eoh;		
4679		if (sc2 >= 1 || eoh < 600) {
4680			sc = Math.min(sc, sc2);
4681			translateX = Math.max(0,(ww-sw*sc) / 2);
4682		} 
4683	}
4684		
4685	if (Math.abs(sc-1) > 0.005) {
4686		var transformStr = '';
4687		if (translateX > 0) {
4688			//transformStr += ' translateX('+translateX.toFixed(1)+'px)';
4689		}
4690		transformStr += ' scale('+sc.toFixed(2)+')';
4691		elem.css('transform',transformStr);
4692		elem.attr('data-scale',sc.toFixed(2));
4693	} else {
4694		elem.css('transform','');
4695		elem.attr('data-scale','');
4696	}
4697		
4698	var elemH = (Math.ceil(eoh*sc));
4699	var qh = elem.data('orig-height');
4700	if (qh) {			
4701		elemH += Math.max(0, Math.min(90, 90-(elemH-qh*sc)));
4702	}
4703		
4704	//elem.css('min-height',(elemH).toString()+'px');
4705		
4706	if (!options.retryFlag && ww0 != $(window).width()) {
4707		//asi doslo k pridaniu vertikalneho scrollbaru medzicasom, skusime sa tomu prisposobit
4708		options.retryFlag = true;
4709		ETestUtils.scaleToFitWindow(elem, options);	
4710	}
4711}
4712
4713ETestUtils.getPrintHtml = function(elem, options, readyFunc) {
4714	var imagesData = {};
4715	var cssFiles = {};
4716		
4717		
4718	var pagePadding = mainWidgetElem.find('.etest-page-inner').first().css('padding');
4719
4720	elem.find('img').each(function() {			
4721	
4722     	imagesData[$(this).attr('src')] = this.src;	        
4723	});		
4724	
4725	var pocTotal = 0;
4726	var pocDownloaded = 0;
4727	$('head').find('link[rel="stylesheet"]').each(function() {
4728		var href = $(this).attr('href');
4729		pocTotal++;
4730		$.get(href, function(data) {
4731			cssFiles[href] = data
4732		}).always(function() {
4733			pocDownloaded++;
4734			
4735			if (pocDownloaded >= pocTotal) {
4736				
4737				allDownloadedFunc();
4738			}
4739		});
4740	});
4741	
4742	function allDownloadedFunc() {
4743		var s = '<html>';
4744		s += '<head>';
4745			var boliCsska = {};
4746			$('head').children().filter(function() {				
4747				if (this.tagName == 'SCRIPT') return false;
4748				if ($(this).attr('id') == 'mainCssStyle') return false;
4749								
4750				if (this.tagName == 'LINK' && $(this).attr('rel') != 'stylesheet') return false;
4751				if (this.tagName == 'LINK' && $(this).attr('rel') == 'stylesheet') {
4752					var src = $(this).attr('href');					
4753					if (src) {
4754						if (boliCsska[src]) return false;
4755					
4756						boliCsska[src] = true;
4757					}
4758				}
4759				return true;
4760			}).each(function() {	
4761							
4762				if ($(this).attr('rel') == 'stylesheet' && cssFiles && cssFiles[$(this).attr('href')]) {
4763					s += '<style type="text/css">';
4764					s += cssFiles[$(this).attr('href')];
4765					s += '</style>';					
4766				} else {					
4767					s += this.outerHTML;
4768				}
4769			});
4770			
4771			
4772			s += '<style type="text/css">';
4773				s += '@page {size: auto; margin: 0;} ';
4774				s += '.edubarMainSkin {overflow: visible; height: auto;min-height: 100%} ';
4775				
4776				s += "@font-face {font-family: 'FontAwesome2'; src: url('/global/pics/fonts/fontawesome-webfont.ttf');font-weight: normal; font-style: normal;} ";
4777				s += " .fa { font-family: 'FontAwesome2' !important;} ";					
4778			s += '</style>';	
4779		s += '</head>';
4780		s += '<body id="docbody">';
4781			s += '<div>';	
4782				s += elem.html();
4783			s += '</div>';	
4784		s += '</body>';
4785		s += '</html>';
4786		if (readyFunc) {
4787			
4788			readyFunc(s, imagesData);
4789		}
4790	}	
4791}
4792
4793$j.ui.ddmanager.prepareOffsets = function( t, event ) {
4794    var i, j,
4795        m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
4796        type = event ? event.type : null, // workaround for #2317
4797        list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
4798
4799    droppablesLoop: for ( i = 0; i < m.length; i++ ) {
4800
4801        // No disabled and non-accepted
4802        if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
4803            continue;
4804        }
4805
4806        // Filter out elements in the current dragged item
4807        for ( j = 0; j < list.length; j++ ) {
4808            if ( list[ j ] === m[ i ].element[ 0 ] ) {
4809                m[ i ].proportions().height = 0;
4810                continue droppablesLoop;
4811            }
4812        }
4813
4814        m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
4815        if ( !m[ i ].visible ) {
4816            continue;
4817        }
4818
4819        // Activate the droppable if used directly from draggables
4820        if ( type === "mousedown" ) {
4821            m[ i ]._activate.call( m[ i ], event );
4822        }
4823
4824        m[ i ].offset = m[ i ].element.offset();
4825        
4826        var r =  m[ i ].element[ 0 ].getBoundingClientRect();
4827        var currentZoom = r.width / m[ i ].element[ 0 ].offsetWidth;
4828        
4829        m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth * currentZoom, height: m[ i ].element[ 0 ].offsetHeight * currentZoom });
4830    }
4831
4832};
4833
4834
4835$j.widget( "edupage.zoomsortable", $j.ui.sortable, {
4836     
4837		
4838	_intersectsWith: function( item ) {
4839		
4840		//var r =  this.element[ 0 ].getBoundingClientRect();
4841        var currentZoom = this._getZoom();//r.width / this.element[ 0 ].offsetWidth;
4842		
4843		//console.log('_intersectsWith:w:'+item.width+';h:'+item.height+';t:'+item.top+';l:'+item.left);
4844		var x1 = this.positionAbs.left,
4845			x2 = x1 + this.helperProportions.width*currentZoom,
4846			y1 = this.positionAbs.top,
4847			y2 = y1 + this.helperProportions.height*currentZoom,
4848			l = item.left,
4849			r = l + item.width*currentZoom,
4850			t = item.top,
4851			b = t + item.height*currentZoom,
4852			dyClick = this.offset.click.top,
4853			dxClick = this.offset.click.left,
4854			isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
4855				( y1 + dyClick ) < b ),
4856			isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
4857				( x1 + dxClick ) < r ),
4858			isOverElement = isOverElementHeight && isOverElementWidth;
4859
4860		if ( this.options.tolerance === "pointer" ||
4861			this.options.forcePointerForContainers ||
4862			( this.options.tolerance !== "pointer" &&
4863				this.helperProportions[ this.floating ? "width" : "height" ] >
4864				item[ this.floating ? "width" : "height" ] )
4865		) {
4866			
4867			return isOverElement;
4868			
4869		} else {
4870
4871			return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
4872				x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
4873				t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
4874				y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
4875
4876		}
4877	},
4878
4879	_intersectsWithPointer: function( item ) {		
4880		//console.log('_intersectsWithPointer:w:'+item.width+';h:'+item.height+';
4880t:'+item.top+';l:'+item.left);
4881		var currentZoom = this._getZoom();
4882
4883		var minItemX = this.minItemX;
4884		var maxItemX = this.maxItemX;
4885		var minItemY = this.minItemY;
4886		var maxItemY = this.maxItemY;		
4887		
4888		
4889		var verticalDirection, horizontalDirection,
4890			isOverElementHeight = ( this.options.axis === "x" ) 
4891									|| this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height*currentZoom ) 
4892									|| (this.positionAbs.top + this.offset.click.top <= minItemY && Math.abs(item.top - minItemY)<2) // sme mimo nalavo
4893									|| (this.positionAbs.top + this.offset.click.top >= maxItemY && Math.abs(item.top+item.height*currentZoom - maxItemY) < 2);// sme mimo napravo
4894			isOverElementWidth = ( this.options.axis === "y" ) 
4895									||	this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width*currentZoom )
4896									|| (this.positionAbs.left + this.offset.click.left < minItemX && item.left <= minItemX) // sme mimo hore
4897									|| (this.positionAbs.left + this.offset.click.left > maxItemX && item.left+item.width*currentZoom  >= maxItemX); //sme mimo dole
4898			isOverElement = isOverElementHeight && isOverElementWidth;
4899
4900		if ( !isOverElement ) {
4901			return false;
4902		}
4903		
4904		verticalDirection = this._getDragVerticalDirection();
4905		horizontalDirection = this._getDragHorizontalDirection();
4906				
4907		return this.floating ?
4908			( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
4909			: ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
4910
4911	},
4912	_isFloating: function( item ) {
4913		if (this.options.organization == 'horizontal') return true;
4914		if (this.options.organization == 'vertical') return false;
4915		return ( /left|right/ ).test( item.css( "float" ) ) ||
4916			( /inline|table-cell/ ).test( item.css( "display" ) );
4917	},
4918	_mouseStart: function( event, overrideHandle, noActivation ) {
4919		this._super( event, overrideHandle, noActivation);
4920
4921		this._currentZoom = null;		
4922        var currentZoom = this._getZoom();
4923		
4924		var minItemX = 9999999;
4925		var maxItemX = 0;
4926		var minItemY = 9999999;
4927		var maxItemY = 0;		
4928		var that = this;
4929		$.each( this.items, function() {
4930	
4931			if (this.top < minItemY) minItemY = this.top;
4932			if (this.top + this.height*currentZoom > maxItemY) maxItemY = this.top + this.height*currentZoom ;
4933
4934			if (this.left < minItemX) minItemX = this.left;
4935			if (this.left + this.width*currentZoom > maxItemX) maxItemX = this.left + this.width*currentZoom ;
4936		});
4937
4938		this.minItemX = minItemX;
4939		this.maxItemX = maxItemX;
4940		this.minItemY= minItemY;
4941		this.maxItemY = maxItemY;
4942	},
4943	_getZoom: function() {
4944		if (!this._currentZoom) {
4945			var r =  this.element[ 0 ].getBoundingClientRect();
4946			this._currentZoom = r.width / this.element[ 0 ].offsetWidth;
4947		}
4948		return this._currentZoom;
4949	},
4950	_generatePosition: function( event ) {
4951
4952		var top, left,
4953			o = this.options,
4954			pageX = event.pageX,
4955			pageY = event.pageY,
4956			scroll = this.cssPosition === "absolute" &&
4957				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
4958				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
4959					this.offsetParent :
4960					this.scrollParent,
4961				scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
4962
4963		// This is another very weird special case that only happens for relative elements:
4964		// 1. If the css position is relative
4965		// 2. and the scroll parent is the document or similar to the offset parent
4966		// we have to refresh the relative offset during the scroll so there are no jumps
4967		if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
4968				this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
4969			this.offset.relative = this._getRelativeOffset();
4970		}
4971
4972		/*
4973		 * - Position constraining -
4974		 * Constrain the position to a mix of grid, containment.
4975		 */
4976
4977		if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
4978
4979			if ( this.containment ) {
4980				if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
4981					pageX = this.containment[ 0 ] + this.offset.click.left;
4982				}
4983				if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
4984					pageY = this.containment[ 1 ] + this.offset.click.top;
4985				}
4986				if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
4987					pageX = this.containment[ 2 ] + this.offset.click.left;
4988				}
4989				if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
4990					pageY = this.containment[ 3 ] + this.offset.click.top;
4991				}
4992			}
4993
4994			if ( o.grid ) {
4995				top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
4996					o.grid[ 1 ] ) * o.grid[ 1 ];
4997				pageY = this.containment ?
4998					( ( top - this.offset.click.top >= this.containment[ 1 ] &&
4999						top - this.offset.click.top <= this.containment[ 3 ] ) ?
5000							top :
5001							( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
5002								top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
5003								top;
5004
5005				left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
5006					o.grid[ 0 ] ) * o.grid[ 0 ];
5007				pageX = this.containment ?
5008					( ( left - this.offset.click.left >= this.containment[ 0 ] &&
5009						left - this.offset.click.left <= this.containment[ 2 ] ) ?
5010							left :
5011							( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
5012								left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
5013								left;
5014			}
5015
5016		}
5017		var ret = {
5018			top: (
5019
5020				// The absolute mouse position
5021				pageY -
5022
5023				// Click offset (relative to the element)
5024				this.offset.click.top -
5025
5026				// Only for relative positioned nodes: Relative offset from element to offset parent
5027				this.offset.relative.top -
5028
5029				// The offsetParent's offset without borders (offset + border)
5030				this.offset.parent.top +
5031				( ( this.cssPosition === "fixed" ?
5032					-this.scrollParent.scrollTop() :
5033					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
5034			),
5035			left: (
5036
5037				// The absolute mouse position
5038				pageX -
5039
5040				// Click offset (relative to the element)
5041				this.offset.click.left -
5042
5043				// Only for relative positioned nodes: Relative offset from element to offset parent
5044				this.offset.relative.left -
5045
5046				// The offsetParent's offset without borders (offset + border)
5047				this.offset.parent.left +
5048				( ( this.cssPosition === "fixed" ?
5049					-this.scrollParent.scrollLeft() :
5050					scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
5051			)
5052		};
5053		if (this.options.parentIsZoomed === false) {
5054			var currentZoom = this._getZoom();
5055			ret.left = ret.left/currentZoom;
5056			ret.top = ret.top/currentZoom;
5057		}
5058		return ret;
5059
5060	},
5061	_convertPositionTo: function( d, pos ) {
5062
5063		if ( !pos ) {
5064			pos = this.position;
5065		}
5066		var mod = d === "absolute" ? 1 : -1,
5067			scroll = this.cssPosition === "absolute" &&
5068				!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
5069				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
5070					this.offsetParent :
5071					this.scrollParent,
5072			scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
5073
5074		var currentZoom = this._getZoom();
5075		var zoomKoef = this.options.parentIsZoomed === false ? (mod == 1 ? currentZoom : 1/currentZoom) : 1;
5076		var ret = {
5077			top: (
5078
5079				// The absolute mouse position
5080				pos.top*zoomKoef	+
5081
5082				// Only for relative positioned nodes: Relative offset from element to offset parent
5083				this.offset.relative.top * mod +
5084
5085				// The offsetParent's offset without borders (offset + border)
5086				this.offset.parent.top * mod -
5087				( ( this.cssPosition === "fixed" ?
5088					-this.scrollParent.scrollTop() :
5089					( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
5090			),
5091			left: (
5092
5093				// The absolute mouse position
5094				pos.left*zoomKoef +
5095
5096				// Only for relative positioned nodes: Relative offset from element to offset parent
5097				this.offset.relative.left * mod +
5098
5099				// The offsetParent's offset without borders (offset + border)
5100				this.offset.parent.left * mod	-
5101				( ( this.cssPosition === "fixed" ?
5102					-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
5103					scroll.scrollLeft() ) * mod )
5104			)
5105		};
5106
5107		return ret;
5108
5109	},
5110});
5111
5112
5113/*!
5114 * jQuery UI Touch Punch 0.2.3
5115 *
5116 * Copyright 2011–2014, Dave Furfero
5117 * Dual licensed under the MIT or GPL Version 2 licenses.
5118 *
5119 * Depends:
5120 *  jquery.ui.widget.js
5121 *  jquery.ui.mouse.js
5122 */
5123!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document || true,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
5124
5125
5126
5127
5128
5129ETestUtils.etestAudioPlayerPlayedSounds = {};
5130ETestUtils.etestAudioPlayer = function($) {
5131	$.fn.etestAudioPlayer = function(options) {        
5132	    
5133	    var opts = $.extend( {}, $.fn.etestAudioPlayer.defaults, options);
5134	    
5135	    function main() {     
5136			var mainElem = $j(this);	
5137		    
5138			var src = mainElem.attr('data-src');			
5139			if (ETestUtils.fixIOSSrc) {				
5140				src = ETestUtils.fixIOSSrc(src);
5141			}
5142			
5143			var extension = mainElem.attr('data-extension');
5144		    
5145		    
5146			var audioElem = null;
5147			var isPlaying = false;
5148			var errorRetries = 0;
5149
5150			function wasPlayed() {
5151				return sessionStorage.getItem('etestaudioplayed_'+src) == '1' &&  !EdubarUtils.isUcitel();
5152				//return !!ETestUtils.etestAudioPlayerPlayedSounds[src]
5153			}
5154			function allowReplay() {
5155				return opts.allowReplay != 'no';
5156			}
5157			
5158
5159			function allowRewind() {
5160				return opts.allowReplay == 'seek';				
5161			}
5162			
5163		    function createContent() {
5164		    	var s = '';
5165
5166				if (allowReplay() && allowRewind()) {
5167					
5168					s += '<audio controls><source src="{src}" type="audio/{extension}">Your browser does not support the <code>audio</code> element.</audio>';					
5169					s = renderS(s, {
5170						src: src,
5171						extension: extension
5172					})
5173					mainElem.html(s);
5174				} else {
5175		    	
5176		    	
5177					if (mainElem.find('.etest-audio-play-button').length == 0) {
5178						s += '<div class="etest-audio-play-button">';					
5179							s += '<div class="etest-audio-play-button-icon" title="'+lset(15271)+'" aria-label="'+lset(15271)+'">';
5180								
5181								s += '<i class="material-icons">play_arrow</i>';
5182								
5183							s += '</div>';
5184						s += '</div>';
5185						
5186						
5187						s = renderS(s, {
5188								src: src,
5189								extension: extension
5190							});
5191						
5192						mainElem.html(s);
5193					}
5194					mainElem.find('.etest-audio-play-button-icon').attr('title',ls(15271)).attr('aria-label',ls(15271));
5195					
5196					//audioElem = mainElem.find('audio').get(0);
5197					
5198					mainElem.find('.etest-audio-play-button').on('click touchstart',function(e) {
5199						e.preventDefault();
5200						e.stopPropagation();
5201						//setTimeout(function() {						
5202							if (isPlaying) {
5203								pause();
5204							} else {
5205								play();
5206							}
5207						//},5);
5208					}).keypressToClick();
5209					
5210					if (!allowReplay()) {
5211						mainElem.toggleClass('wasPlayed',wasPlayed());
5212						mainElem.toggleClass('isPlaying',false);
5213						if (wasPlayed()) {
5214							mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">done</i>').attr('title',ls(10403)).attr('aria-label',ls(10403));
5215						}
5216					}
5217				}
5218			}
5219		    
5220			var _checkerrorsTimer = null;
5221		    function checkErrors() {
5222				if (_checkerrorsTimer) clearTimeout(_checkerrorsTimer);
5223				_checkerrorsTimer = setTimeout(function() {
5224					if (audioElem && audioElem.networkState == 3) {
5225						retryOnError();
5226					} else {
5227						checkErrors();
5228					}
5229				},100);
5230			}
5231
5232			function retryOnError() {
5233				//console.log('Cannot load audio: '+src);
5234				errorRetries++;
5235				if (errorRetries <= 5) {
5236
5237					sessionStorage.setItem('etestaudioplayed_'+src,'0');
5238					audioElem = null;
5239					
5240					initAudio();
5241					
5242					if (isPlaying) {
5243						play0();
5244					}
5245				} else {
5246					isPlaying = false;
5247					var s = '';
5248					s += '<i class="material-icons">play_arrow</i>';
5249					if (lastErr && lastErr.toString().toLowerCase().indexOf('notallowed')>=0) {
5250
5251					} else {
5252						s += '<i class="fa fa-exclamation" style="position:absolute;font-size:12px;right:10px;color: #F44336;bottom:6px;"></i>'
5253					}
5254					mainElem.find('.etest-audio-play-button-icon').html(s).attr('title',lset(12698)).attr('aria-label',lset(12698));
5255				}
5256			}
5257		    function initAudio() {
5258		    	
5259		    	if (!audioElem) {
5260		    		
5261		    		var s = '';
5262		    		s += '<audio>';
5263						s += '<source src="{src}" type="audio/{extension}"> ';
5264						s += 'Your browser does not support the audio element.';
5265					s += '</audio>';
5266					
5267					s = renderS(s, {
5268						src: src,
5269						extension: extension
5270					});
5271					
5272					mainElem.find('audio').remove();
5273					mainElem.append(s);
5274					
5275					audioElem = mainElem.find('audio').get(0);
5276					
5277					$(audioElem).on('playing', function() {
5278						if (!allowReplay()) {
5279							mainElem.toggleClass('isPlaying',true);
5280							mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">hearing</i>');
5281						} else {
5282							mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">stop</i>').attr('title',lset(3810)).attr('aria-label',lset(3810));
5283						}
5284					});
5285					
5286					$(audioElem).on('waiting', function() {						
5287						mainElem.find('.etest-audio-play-button-icon').html('<i class="fa fa-spinner fa-spin"></i>').attr('title',lset(3358)).attr('aria-label',lset(3358));
5288					});	
5289
5290					$(audioElem).on('error', function(e) {						
5291						retryOnError();
5292					});
5293					
5294					$(audioElem).on('ended paused', function() {
5295						if (!allowReplay()) {
5296							mainElem.toggleClass('isPlaying',false);
5297							mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">done</i>').attr('title',ls(10403)).attr('aria-label',ls(10403));
5298							mainElem.toggleClass('wasPlayed',true);
5299						} else {
5300							mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">play_arrow</i>').attr('title',lset(15271)).attr('aria-label',lset(15271));
5301						}
5302						isPlaying = false;
5303
5304					});
5305
5306					checkErrors();
5307		    	}
5308		    }
5309		    
5310			function play() {				
5311				initAudio();
5312				errorRetries = 0;
5313				if (wasPlayed() && !allowReplay()) {
5314					barShowMessage(ls(10403))
5315					return;
5316				}
5317
5318				if (!allowReplay()) {
5319					barShowMessageBox(ls(10402), 'fa-file-sound-o', {
5320						okLbl: ls(8020),
5321						confirm: function() {
5322							play0();
5323						}
5324					})
5325				} else {
5326					play0();
5327				}
5328			}
5329
5330			var playPromise = null;
5331			var lastErr = null;
5332			function play0() {
5333				
5334
5335				isPlaying = true;
5336				var wasPaused = audioElem.paused;
5337				
5338				
5339				if (audioElem.readyState < 2) {
5340					mainElem.find('.etest-audio-play-button-icon').html('<i class="fa fa-spinner fa-pulse"></i>').attr('title',lset(3358)).attr('aria-label',lset(3358));
5341				} else {
5342					mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">stop</i>').attr('title',lset(3810)).attr('aria-label',lset(3810));
5343				}
5344				try {
5345					playPromise = audioElem.play();
5346					checkErrors();
5347					if (playPromise) {
5348						playPromise.then(function() {
5349							playPromise = null;
5350							if (_checkerrorsTimer) clearTimeout(_checkerrorsTimer);
5351						}, function(err) {
5352							lastErr = err;
5353							playPromise = null;						
5354							if (_checkerrorsTimer) clearTimeout(_checkerrorsTimer);
5355							retryOnError();
5356						});
5357					}
5358				} catch (e) {
5359					if (_checkerrorsTimer) clearTimeout(_checkerrorsTimer);
5360					retryOnError();
5361				}
5362				sessionStorage.setItem('etestaudioplayed_'+src,'1');
5363				
5364			}	
5365			
5366			function pause() {
5367				if (!allowReplay()) {
5368					return;
5369				}
5370				if (playPromise) {
5371					playPromise.then(function() {
5372						audioElem.pause();
5373					});
5374					return;
5375				} 
5376				isPlaying = false;
5377				try {
5378					audioElem.pause();
5379				} catch (e) {
5380					
5381				}
5382				mainElem.find('.etest-audio-play-button-icon').html('<i class="material-icons">play_arrow</i>').attr('title',lset(15271)).attr('aria-label',lset(15271));
5383			}	    
5384			
5385			createContent();
5386		}   
5387		
5388		
5389		    
5390		return this.each(main);
5391	};
5392		
5393	$.fn.etestAudioPlayer.defaults = {	    	
5394			
5395	};
5396}
5397
5398ETestUtils.etestAudioPlayer(jQuery);
5399
5400
5401
5402
5403/*var fon = $j.fn.on;
5404
5405$j.fn.on = function(events, selector, data, handler) {
5406	//if ($(this) == $(window) || $(this) == $(document)) {
5407		console.log(events);
5408		console.log(this);
5409	//}
5410	
5411	return fon.call(this, events, selector, data, handler);
5412};*/
5413
5414
5415/*!
5416* Clamp.js 0.5.1
5417*
5418* Copyright 2011-2013, Joseph Schmitt http://joe.sh
5419* Released under the WTFPL license
5420* http://sam.zoy.org/wtfpl/
5421*/
5422(function(){window.$clamp=function(c,d){function s(a,b){n.getComputedStyle||(n.getComputedStyle=function(a,b){this.el=a;this.getPropertyValue=function(b){var c=/(\-([a-z]){1})/g;"float"==b&&(b="styleFloat");c.test(b)&&(b=b.replace(c,function(a,b,c){return c.toUpperCase()}));return a.currentStyle&&a.currentStyle[b]?a.currentStyle[b]:null};return this});return n.getComputedStyle(a,null).getPropertyValue(b)}function t(a){a=a||c.clientHeight;var b=u(c);return Math.max(Math.floor(a/b),0)}function x(a){return u(c)*
5423a}function u(a){var b=s(a,"line-height");"normal"==b&&(b=1.2*parseInt(s(a,"font-size")));return parseInt(b)}function l(a){if(a.lastChild.children&&0<a.lastChild.children.length)return l(Array.prototype.slice.call(a.children).pop());if(a.lastChild&&a.lastChild.nodeValue&&""!=a.lastChild.nodeValue&&a.lastChild.nodeValue!=b.truncationChar)return a.lastChild;a.lastChild.parentNode.removeChild(a.lastChild);return l(c)}function p(a,d){if(d){var e=a.nodeValue.replace(b.truncationChar,"");f||(h=0<k.length?
5424k.shift():"",f=e.split(h));1<f.length?(q=f.pop(),r(a,f.join(h))):f=null;
5424m&&(a.nodeValue=a.nodeValue.replace(b.truncationChar,""),c.innerHTML=a.nodeValue+" "+m.innerHTML+b.truncationChar);if(f){if(c.clientHeight<=d)if(0<=k.length&&""!=h)r(a,f.join(h)+h+q),f=null;else return c.innerHTML}else""==h&&(r(a,""),a=l(c),k=b.splitOnChars.slice(0),h=k[0],q=f=null);if(b.animate)setTimeout(function(){p(a,d)},!0===b.animate?10:b.animate);else return p(a,d)}}function r(a,c){a.nodeValue=c+b.truncationChar}d=d||{};
5425var n=window,b={clamp:d.clamp||2,useNativeClamp:"undefined"!=typeof d.useNativeClamp?d.useNativeClamp:!0,splitOnChars:d.splitOnChars||[".","-","\u2013","\u2014"," "],animate:d.animate||!1,truncationChar:d.truncationChar||"\u2026",truncationHTML:d.truncationHTML},e=c.style,y=c.innerHTML,z="undefined"!=typeof c.style.webkitLineClamp,g=b.clamp,v=g.indexOf&&(-1<g.indexOf("px")||-1<g.indexOf("em")),m;b.truncationHTML&&(m=document.createElement("span"),m.innerHTML=b.truncationHTML);var k=b.splitOnChars.slice(0),
5426h=k[0],f,q;"auto"==g?g=t():v&&(g=t(parseInt(g)));var w;z&&b.useNativeClamp?(e.overflow="hidden",e.textOverflow="ellipsis",e.webkitBoxOrient="vertical",e.display="-webkit-box",e.webkitLineClamp=g,v&&(e.height=b.clamp+"px")):(e=x(g),e<=c.clientHeight&&(w=p(l(c),e)));return{original:y,clamped:w}}})();
5427
5428
5429
5430
5431ETestUtils.getLang = function() {
5432	if (ETestUtils.currentLang) return ETestUtils.currentLang;
5433	
5434	var ret = EdubarUtils.getLang();
5435	if (ret) return ret;
5436	return 'en';
5437}
5438
5439ETestUtils.getAvailableLangs = function() {
5440	return ['sk','en','de','cz','tr','fr','ge','pl','es'];	
5441}
5442
5443ETestUtils.etestTranslatiosnEditor = function($) {
5444	$.fn.etestTranslatiosnEditor = function(options) {        
5445	    
5446	    var opts = $.extend( {}, $.fn.etestTranslatiosnEditor.defaults, options);
5447	    
5448	    function main() {     
5449			var mainElem = $j(this);	
5450		    
5451		    function initProperties() {				
5452		    	if (!opts.l1) opts.l1 = ETestUtils.getLang();
5453		    	
5454		    	
5455				
5456				var mamL1 = false;
5457				var mamL2 = false;
5458				var mamEn = false;
5459				
5460				for (var i=0;i<opts.trs.length;i++) {
5461					var tr = opts.trs[i].tr;
5462
5463					if (tr[opts.l1]) {
5464						mamL1 = true;
5465					}
5466					
5467					if (tr[opts.l2]) {
5468						mamL2 = true;
5469					}
5470
5471					if (tr['en']) {
5472						mamEn = true;
5473					}
5474				}
5475
5476				if (!opts.l2) {
5477					opts.l2 = mamEn ? 'en' : 'sk';					
5478				}
5479
5480				if (opts.l1 == opts.l2) {
5481		    		for (var i=0;i<opts.availableLangs.length;i++) {
5482		    			if (opts.l1 != opts.availableLangs[i]) {
5483		    				opts.l2 = opts.availableLangs[i];
5484		    				break;
5485		    			}
5486		    		}
5487				}
5488		    }
5489		    function createContent() {
5490		    	var s = '';
5491		    	
5492		    	s += '<div style="max-height:calc(90vh - 50px);overflow:auto;">';
5493		    		s += '<h2>{#8175}</h2>';
5494			    	s += '<table class="etest-translations-table">';
5495			    	s += '<thead>';
5496			    		
5497			    		for (var li=1;li<=2;li++) {
5498				    		s += '<th style="width: 50%">';
5499				    			
5500				    			s += renderS('<select name="l{li}" class="langSelect">', {li: li});
5501				    				for (var i=0;i<opts.availableLangs.length;i++) {
5502				    					if (li == 2 && opts.availableLangs[i] == opts.l1) continue;
5503				    					s += renderS('<option value="{l}" {selected}>{l}</option>', {
5504				    							l: opts.availableLangs[i],
5505				    							selected: opts.availableLangs[i] == opts['l'+li.toString()] ? ' selected' : ''
5506				    						 });
5507				    				}
5508				    			s += '</select>';
5509					    		
5510				    		s += '</th>';
5511			    		}
5512			    	s += '</thead>';
5513			    	
5514					s += '<tbody>';
5515					
5516			    	for (var i=0;i<opts.trs.length;i++) {
5517			    		var tr = opts.trs[i].tr;
5518			    		
5519			    		s += '<tr>';
5520			    		for (var li=1;li<=2;li++) {		    			
5521			    			var l = opts['l'+li];
5522			    			
5523			    			var ss = '';
5524			    			ss += '<td>';
5525			    				ss += '<div class="etest-treditor-field {contenteditable}" data-index="{i}" data-l="{l}" {contenteditable}>';
5526			    					ss += '{!text}';
5527			    				ss += '</div>';
5528							ss += '</td>';
5529							
5530							var sp = renderS(ss, {
5531									tr: tr,
5532									i: i,
5533									l: l,
5534									text: tr[l] ? tr[l] : '',
5535									contenteditable: !opts.translateableLangs || EdubarUtils.indexOf(opts.translateableLangs, l) != -1 ? 'contenteditable' : ''
5536								});
5537							
5538			    			s += sp;
5539			    		}
5540			    		s += '</tr>';
5541			    	}
5542			    	
5543			    	s += '</tbody>';
5544			    	s += '</table>';
5545			    s += '</div>';
5546			    
5547		    	s += '<div style="text-align:'+ertl('right','left')+';margin-top: 15px;">';
5548		    		s += '<input type="button" class="flat-button flat-button-greenm saveBtn flat-button-bigger" value="{#1529}"> ';
5549		    		s += '<input type="button" class="flat-button flat-button-gray flat-button-bigger" value="{#1038}" onclick="barCloseDialog(this)">';
5550		    	s += '</div>';
5551		    	
5552		    	s = renderS(s, {}, {skipNotAvailable: true});
5553		    	mainElem.html(s);	
5554		    	
5555		    	mainElem.find('.langSelect').on('change',function() {
5556		    		opts[this.name] = this.value;
5557		    		initProperties();
5558		    		createContent();
5559		    	});  
5560		    	
5561		    	mainElem.find('.etest-treditor-field').on('blur keyup paste input', function(event) {
5562					var $this = $(this);
5563					var cnt = $this.html();
5564					
5565					var i = $this.attr('data-index');
5566					var l = $this.attr('data-l');
5567					
5568					if (opts.trs[i].tr[l] != cnt) {
5569						opts.trs[i].tr[l] = cnt;	
5570						opts.trs[i].tr['info:'+l] = {
5571							time: (new Date()).format('Y-m-d H:i:s'),
5572							edupage: EdubarUtils.getEdupage()
5573						}
5574					}
5575				});
5576				
5577				barJsLibraryLoad('/global/pics/js/ckeditor5/ckeditor.es6.js', function() {
5578					mainElem.find('.etest-treditor-field.contenteditable').each(function() {
5579						ETestUtils.initContentEditable($(this), {useBalloonToolbar: true});
5580					});
5581				});
5582				
5583				
5584				mainElem.find('.saveBtn').click(function() {
5585					if (options.saveFunc) {
5586						options.saveFunc(opts.trs);
5587					}
5588					barCloseDialog(mainElem);
5589				});
5590				
5591				
5592			}
5593		    
5594		    initProperties();
5595		   
5596			createContent();
5597		}   
5598		
5599		
5600		    
5601		return this.each(main);
5602	};
5603		
5604	$.fn.etestTranslatiosnEditor.defaults = {	    	
5605		trs: [],
5606		l1: null,
5607		l2: '',
5608		availableLangs: ETestUtils.getAvailableLangs()
5609	};
5610}
5611
5612
5613
5614ETestUtils.etestTranslatiosnEditor(jQuery);
5615
5616ETestUtils.openTranslationsEditor = function(options) {
5617	var s = '';
5618	s += '<div class="etest-translationsEditor"></div>';
5619	var dlg = barNewDialog({
5620		content: s,
5621		title: ls(8175),
5622		width: 800,
5623		dialogClass: 'whiteDialog noPadding'
5624	});
5625	
5626	dlg.find('.etest-translationsEditor').etestTranslatiosnEditor(options);
5627}
5628
5629
5630ETestUtils.toggleSvgClass = function(elem, cls, val) {
5631	var classes = elem.attr('class');
5632	classes = classes ? classes.split(' ') : [];
5633	var pom = [];
5634	for (var ci =0;ci<classes.length;ci++) {
5635		if (classes[ci] == cls) continue;
5636		pom.push(classes[ci]);
5637	}
5638	if (val) {
5639		pom.push(cls);
5640	}
5641	elem.attr('class', pom.join(' '));
5642}
5643
5644ETestUtils.hasSvgClass = function(elem, cls) {
5645	var classes = elem.attr('class');
5646	classes = classes ? classes.split(' ') : [];
5647	
5648	return EdubarUtils.indexOf(classes, cls) != -1;
5649}
5650
5651ETestUtils.openCardPropsEditor = function(cardids, opts) {
5652	barNewDialog({
5653		source: '/elearning/?cmd=CardProps&cardid='+cardids.join(';'),
5654		dialogClass: 'whiteDialog noPadding',		
5655		autoHeight: true,
5656		returnFunc: function() {			
5657			if (opts && opts.returnFunc) {
5658				opts.returnFunc();
5659			}		
5660			
5661		}				
5662	})
5663}
5664
5665ETestUtils.getCoursesToolbarOpts = function(planid, courseById, subjectsById) {
5666
5667	var ret = {};
5668	ret.courseid = planid;
5669	
5670	if (!planid) planid = '';
5671	planid = planid.toString();
5672	
5673	if ((planid.substr(0,10) == 'standards:' || planid.substr(0,11) == 'globalPlan:') && subjectsById) {
5674		
5675		var subjectid = planid.substr(0,10) == 'standards:' ? planid.substr(10) : planid.substr(11);
5676		if (subjectsById[subjectid]) {
5677			ret.courserow = subjectsById[subjectid];
5678			ret.courserow.valid = '1';
5679		}
5680	} else {
5681		ret.courserow = courseById[planid];
5682	}
5683	return ret;
5684}
5685
5686ETestUtils.nameTTGroups = function(gns) {
5687	if (!gns || gns.length == 0) {
5688		return '('+ls(3529)+')';
5689	}
5690	var s = '';
5691	for (var gi=0;gi<gns.length;gi++) {
5692		if (s) s += '+';
5693		if (gns[gi] == '') {
5694			s += ls(1904);
5695		} else {
5696			s += gns[gi].replace('seminargroup:',ls(7513)+' ');
5697		}
5698	}
5699
5700	return s;
5701}
5702
5703
5704ETestUtils.handleCourseTip = function(tip, planid, returnFunc) {
5705	if (tip.type == 'groups') {
5706		barNewDialog({
5707			'title': 'EduPage',
5708			'source': '/plany/?jwgc=PlanyCreator&mode=kompetencie&planid='+planid,
5709			'postData': {
5710				ps: 'groups'
5711			},
5712			'returnFunc': function(data) {					
5713				if (returnFunc) {
5714					returnFunc();
5715				}		
5716			}		
5717		});
5718	} else {
5719		var helpid = tip.helpid 
5720						? tip.helpid 
5721						: tip.type == 'selectStudents'
5722						? 'u1037'
5723						: '2129';				
5724		barNewDialog({			
5725			'source': '/customize/helpus.php?cmd=HelpusHelpDialog&helpid='+helpid
5726		});	
5727	}	
5728}
5729
5730ETestUtils._prngs = {};
5731ETestUtils.initRandom = function(seed, name) {
5732	if (!name) name = 'etestw';
5733
5734	ETestUtils._prngs[name] = new Math.seedrandom(seed);	
5735}
5736
5737ETestUtils.nextRandom = function(name) {
5738	if (!name) name = 'etestw';
5739	if (!ETestUtils._prngs[name]) {
5740		ETestUtils._prngs[name] = new Math.seedrandom();
5741	}
5742
5743	return ETestUtils._prngs[name]();
5744}
5745
5746ETestUtils.getRandomStr = function(length) {
5747	var prng = new Math.seedrandom();
5748	var chars = 'abcdefghijklmnopqrstuvwxyz01234567890';
5749	var ret = '';
5750	for (var i=0;i<length;i++) {		
5751		ret += chars.charAt(Math.abs(prng.int32())%chars.length);
5752	}
5753	return ret;
5754}
5755
5756
5757ETestUtils.getRandomStrEx = function(length) {
5758	var ret = "";
5759	if (window.crypto) {
5760		var iv = new Uint8Array(length);
5761	
5762		crypto.getRandomValues(iv);
5763
5764		var s = '', h = '0123456789ABCDEF';
5765		iv.forEach(function(v) { s += h[v >> 4] + h[v & 15]; });
5766		return s;
5767	} 
5768	return ETestUtils.getRandomStr(length);	
5769}
5770
5771
5772ETestUtils.getVysledokStavy = function() {
5773	var ret = {
5774		'new': {//prebieha vypracovanie otazok
5775			order: 1, 
5776			name: ls(9017), 
5777			description: 'No answers are registered yet',
5778			autoDummy: 'evaluation',
5779			icon: '/elearning/pics/vstav/new.svg',
5780			//icon_w: '/elearning/pics/vstav/white/new.svg',
5781			icon_w: '/elearning/pics/vstav/white2/new.svg',
5782			altColor: '#f1c40f'
5783		}, 
5784		'saved': {//ulozene priebezne vypracovanie
5785			order: 2, 
5786			name: ls(9016), 
5787			description: 'Student has saved some answers, but the attempt is not submitted',
5788			autoDummy: 'evaluation',
5789			icon: '/elearning/pics/vstav/saved.svg',
5790			//icon_w: '/elearning/pics/vstav/white/saved.svg',
5791			icon_w: '/elearning/pics/vstav/white2/saved.svg',
5792			altColor: '#f1c40f',
5793		}, 
5794		'submitted': { //odovzdane vypracovanie - student nemoze editovat
5795			order: 3,
5796			name: ls(9014), 
5797			description: 'Student has submitted his / her answers. He cannot make changes to this attempt',
5798			autoDummy: 'evaluation',
5799			icon: '/elearning/pics/vstav/submitted.svg',
5800			//icon_w: '/elearning/pics/vstav/white/submitted.svg',
5801			icon_w: '/elearning/pics/vstav/white2/sent.svg',
5802			altColor: '#8abadb',
5803		},
5804		'seen_only': { //vysledok bez odpovedovych kariet - score znamena kolko percent videl
5805			order: 4, 
5806			name: ls(8891), 
5807			description: 'The material does not contain any questions. The score represents percentage of material seen by student.',
5808			autoDummy: 'evaluation',
5809			icon: '/elearning/pics/vstav/seen_only.svg',
5810			//icon_w: '/elearning/pics/vstav/white/seen_only.svg',
5811			icon_w: '/elearning/pics/vstav/white2/seen_only.svg',
5812			altColor: '#92ccaa'
5813		},
5814		'evaluated': { //vyhodnotene vsetky otazky - automaticky sa nastavi po absolvovani online testu bez otvorenych otazok
5815			order: 5,
5816			name: ls(8382), 
5817			description: 'All questions are evaluated, the score is final',
5818			autoDummy: 'evaluation',
5819			icon: '/elearning/pics/vstav/evaluatedg.svg',
5820			//icon_w: '/elearning/pics/vstav/white/evaluatedg.svg',
5821			icon_w: '/elearning/pics/vstav/white2/ok.svg',
5822			altColor: '#6ccc95'
5823		},	
5824		'dline': {
5825			order: 6, 
5826			name: ls(10225), 
5827			description: '', 
5828			color: '#F48FB1',
5829			autoDummy: 'evaluation',
5830			icon: '/elearning/pics/vstav/dline_man.svg',
5831			//icon_w: '/elearning/pics/vstav/white/excused.svg',
5832			icon_w: '/elearning/pics/vstav/white2/dline_man.svg'
5833		},
5834		
5835		'sub_man':{ 
5836			order: 7, 
5837			name: ls(9014), 
5838			description: ls(9014), 
5839			color: '#3498db',
5840			icon: '/elearning/pics/vstav/submitted.svg',
5841			//icon_w: '/elearning/pics/vstav/white/submitted.svg',
5842			icon_w: '/elearning/pics/vstav/white2/sent.svg'
5843		},	
5844		'ev_man': { //vyhodnotene vsetky otazky - automaticky sa nastavi po absolvovani online testu bez otvorenych otazok
5845			order: 8,
5846			name: ls(8382), 
5847			description: 'All questions are evaluated, the score is final, count grade',			
5848			color: '#2ecc71',
5849			icon: '/elearning/pics/vstav/evaluated.svg',
5850			//icon_w: '/elearning/pics/vstav/white/evaluated.svg'
5851			icon_w: '/elearning/pics/vstav/white2/ok.svg'
5852		},	
5853		'rework': {//na prepracovanie - ucitel to moze nastavit
5854			order: 9, 
5855			name: ls(9015), 
5856			description: 'Send this attempt for rework - student can create a new attempt with updated answers.',
5857			color: '#f39c12',
5858			icon: '/elearning/pics/vstav/rework.svg',
5859			//icon_w: '/elearning/pics/vstav/white/rework.svg'
5860			icon_w: '/elearning/pics/vstav/white2/rework.svg'
5861		}, 
5862		'cancelled': { //zrusene hodnotenie - ignoruj tento vysledok	
5863			order: 10, 
5864			name: ls(1987), 
5865			description: 'Do not count this attempt, ignore it',
5866			color: '#666666',
5867			icon: '/elearning/pics/vstav/cancelled.svg',
5868			//icon_w: '/elearning/pics/vstav/white/cancelled.svg'
5869			icon_w: '/elearning/pics/vstav/white2/cancelled.svg'
5870		},
5871		'done':	{
5872			order: 11, 
5873			name: ls(6456), 
5874			description: '', 
5875			color: '#81C784',
5876			icon: '/elearning/pics/vstav/done.svg',
5877			//icon_w: '/elearning/pics/vstav/white/done.svg',
5878			icon_w: '/elearning/pics/vstav/white2/ok.svg'
5879		},
5880		'missing': {
5881			order: 12, 
5882			name: ls(6457), 
5883			description: '', 
5884			color: '#EF9A9A',
5885			icon: '/elearning/pics/vstav/missing.svg',
5886			//icon_w: '/elearning/pics/vstav/white/missing.svg',
5887			icon_w: '/elearning/pics/vstav/white2/missing.svg'
5888		},
5889		'part': {
5890			order: 13, 
5891			name: ls(6458), 
5892			description: '', 
5893			color: '#FFB74D',
5894			icon: '/elearning/pics/vstav/part.svg',
5895			//icon_w: '/elearning/pics/vstav/white/part.svg'
5896			icon_w: '/elearning/pics/vstav/white2/part.svg'
5897		},
5898		'nexttime': {
5899			order: 14, 
5900			name: ls(6459), 
5901			description: '', 
5902			color: '#4FC3F7',
5903			icon: '/elearning/pics/vstav/nexttime.svg',
5904			//icon_w: '/elearning/pics/vstav/white/nexttime.svg',
5905			icon_w: '/elearning/pics/vstav/white2/nexttime.svg'
5906		},
5907		'excused': {
5908			order: 15, 
5909			name: ls(3127), 
5910			description: '', 
5911			color: '#FFEB3B',
5912			icon: '/elearning/pics/vstav/excused.svg',
5913			//icon_w: '/elearning/pics/vstav/white/excused.svg',
5914			icon_w: '/elearning/pics/vstav/white2/excused.svg'
5915		},
5916		'dline_man': {
5917			order: 16, 
5918			name: ls(10225), 
5919			description: '', 
5920			color: '#F48FB1',
5921			icon: '/elearning/pics/vstav/dline_man.svg',
5922			//icon_w: '/elearning/pics/vstav/white/excused.svg',
5923			icon_w: '/elearning/pics/vstav/white2/dline_man.svg'
5924		},
5925		'': {
5926			order: 17, 
5927			name: ls(1215), 
5928			description: '', 
5929			color: '#ffffff',
5930			icon: '/elearning/pics/vstav/auto.svg',
5931			icon_w: '/elearning/pics/vstav/white/auto.svg'
5932		}		
5933	};
5934
5935	for (var x in ret) {
5936		ret[x].id = x;
5937		ret[x].text = ret[x].name;
5938		ret[x].altColor = ret[x].altColor || ret[x].color;
5939	}
5940
5941	return ret;
5942}
5943
5944ETestUtils.getVysledokStavyArr = function() {
5945	return EdubarUtils.sortObject(ETestUtils.getVysledokStavy(),['order']);
5946}
5947
5948
5949ETestUtils.getVysledokStavObj = function(stav) {
5950	if (!this.vysledokStavy) {
5951		this.vysledokStavy = ETestUtils.getVysledokStavy();
5952	}
5953	if (!this.vysledokStavy[stav]) stav ='new';
5954	return this.vysledokStavy[stav];
5955}
5956
5957ETestUtils.renderCompetenceName = function(name, structured) {
5958	if (!name) name = '';
5959	var s = et($.trim(name.ucfirst()).replace(/[\,]+$/,''));
5960	
5961	var level = 0;
5962	var lastLevelType = '';
5963	s = s.replace(/(\s[a-z]\)\s|\s[0-9]\.\s)/g, function(match) {	
5964		if (structured || true) {
5965			var patt = /^\s[a-z]\)\s$/;
5966			var levelType = patt.test(match) ? 'lower-alpha' : 'decimal';
5967			var ss = '';
5968			
5969			if (level>0) {
5970				ss += '</li>';
5971			}
5972
5973			if (levelType != lastLevelType) {
5974				if ($.trim(match) == 'a)' || $.trim(match) == '1.') {
5975					//zaciname novy 
5976					level++;
5977					ss += '<ol style="margin-'+ertl('left','right')+':20px">';
5978				} else if (level > 0) {
5979					level--;
5980					ss += '</ol>';
5981				}
5982				lastLevelType = levelType;
5983			}
5984			
5985			ss += '<li style="list-style-type:'+et(levelType)+'">';
5986			return ss;
5987		} else {	
5988			return '<b>'+match+'</b>';
5989		}
5990	});
5991	if (level>0) {
5992		for (i=level;i>=0;i--) {
5993			s += '</li></ol>';
5994		}
5995	}
5996
5997	return renderMath(s);
5998}
5999
6000ETestUtils.openBoard = function(boardid, pin, currentWnd, bbeid, returnFunc) {
6001	localStorage.setItem('cbl'+boardid, '1');	
6002	var url = '/bb/?cmd=BBMain&clearss=1&boardid='+boardid+'&pin='+pin;
6003	if (window.AscMobileAppVersion) {
6004		url += '&mobileApp='+encodeURIComponent(window.AscMobileAppVersion);
6005	} else if (bbeid) {
6006		url += '&bbeid='+encodeURIComponent(bbeid);
6007	}
6008	url = barEncLink(url);	
6009	localStorage.setItem('cbl'+boardid,'1');
6010	localStorage.setItem('cbl','1');
6011	if (MobileAppBridge.isV2Active()) {
6012		var options = {};
6013		options.addToElem = $('body');
6014		options.fullScreen = true;
6015		options.returnFunc = returnFunc;
6016		options.className = 'bb-player-fs-main';
6017		var editorTopElem = ETestUtils.openFullScreenDialog(options);
6018		var postData = {
6019			
6020		}
6021		
6022		
6023		
6024		$j.post(url,postData, function(data) {
6025			editorTopElem.html(data);
6026		});	
6027	} else
6028	if (currentWnd) {
6029
6030		if (MobileAppBridge.isActive()) {
6031			barSmartLoadPage(url);
6032		} else {
6033			window.location = url;
6034		}
6035	} else {
6036		if (MobileAppBridge.isActive()) {
6037			MobileAppBridge.runFlexMethod('openBoard',[boardid]);
6038		} else {
6039			if (!window.name) {
6040				window.name = 'bbopener'+boardid;
6041			}
6042
6043			ETestUtils.bbOpenWnd(url);
6044		}
6045	}
6046}
6047
6048ETestUtils.bbOpenWnd = function(url) {
6049	var wnd = window.open(url+'#'+(new Date()).getTime(),'bbwnd');
6050			   
6051	if(!wnd || wnd.closed || typeof wnd.closed=='undefined') 
6052	{ 				
6053		barShowMessageBox(ls(9509), 'fa-warning',{
6054			okLbl: ls(9267),
6055			confirm: function() {
6056				ETestUtils.bbOpenWnd(url);
6057			}		
6058		});
6059	}
6060}
6061
6062ETestUtils.bbPlayCardids = function(cardids, mode, planid, doneFunc) {
6063	var bdata = {
6064		cardids: cardids,		
6065	}
6066
6067	if (!planid && edubar && edubar.editorState) {
6068		planid = edubar.editorState.planid;
6069	}
6070	if (!planid) {
6071		planid = '';
6072	}
6073
6074	var postData = {
6075		planid: planid,
6076		bdata: JSON.stringify(bdata),
6077		appendMode: mode
6078	}
6079
6080	barStartLoading();
6081	$.post('/elearning/?cmd=ETestCreator&akcia=createBoard', postData, function(data) {
6082		if (data.boardid) {			
6083		
6084			if (!MobileAppBridge.isActive() && EdubarUtils.isUcitel() && edubar) {
6085				edubar.toggleBBPopup(true);
6086			}
6087			ETestUtils.openBoard(data.boardid, data.teacher_pin);	
6088			if (doneFunc) {
6089				doneFunc(data);
6090			}				
6091		}
6092	},'json').always(function() {		
6093		barEndLoading();
6094	});
6095}
6096
6097ETestUtils.getCipherKey = function(key, doneFunc) {
6098	var typedArray = new Uint8Array(key.match(/[\da-f]{2}/gi).map(function (h) {
6099		return parseInt(h, 16);
6100	}));
6101
6102
6103	var buffer = typedArray.buffer
6104	var crypto = window.crypto || window.msCrypto;
6105	var ret = crypto.subtle.importKey(
6106		"raw",
6107		buffer,
6108		{ "name": "AES-CBC"},
6109		true,
6110		["encrypt", "decrypt"]
6111	);
6112		
6113	ret.then(function(val) {		
6114		doneFunc(val);
6115	}).catch(function(error) {		
6116		console.log(error);
6117	});
6118}
6119
6120ETestUtils.ab2str = function(buf) {
6121	return String.fromCharCode.apply(null, new Uint16Array(buf));
6122}
6123  
6124ETestUtils.str2ab = function(str) {
6125	var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
6126	var bufView = new Uint16Array(buf);
6127	for (var i=0, strLen=str.length; i<strLen; i++) {
6128		bufView[i] = str.charCodeAt(i);
6129	}
6130	return buf;
6131}
6132ETestUtils.encryptionEnabled = function() {
6133	var crypto = window.crypto;
6134	if (!crypto || !crypto.subtle || !crypto.subtle.importKey || !crypto.getRandomValues || !crypto.subtle.encrypt || !crypto.subtle.decrypt) {
6135		return false;
6136	}
6137
6138	return true;
6139}
6140
6141ETestUtils.simpleEncrypt = function(message, keyStr, doneFunc) {
6142	var crypto = window.crypto;
6143	if (!ETestUtils.encryptionEnabled()) {
6144		doneFunc('');
6145		return;
6146	};
6147	ETestUtils.getCipherKey(keyStr, function(key) {
6148		var encodedBuff =  ETestUtils.str2ab(message);
6149		var iv = new Uint8Array(8);
6150		crypto.getRandomValues(iv)
6151		iv = ETestUtils.str2ab(ETestUtils.ab2str(iv));
6152	
6153		
6154		ret = crypto.subtle.encrypt(
6155			{
6156				name: "AES-CBC",
6157				iv: iv
6158			},
6159			key,
6160			encodedBuff
6161		);
6162
6163		
6164		ret.then(function(cipherTextBuffer) {			
6165			var cipherText = ETestUtils.ab2str(cipherTextBuffer);
6166			var ivStr = ETestUtils.ab2str(iv);
6167			var lstr = ivStr.length.toString();
6168			if (ivStr.length < 10) {
6169				lstr = '0'+lstr;
6170			}
6171			doneFunc(lstr+ivStr+cipherText);
6172		}).catch(function(error) {				
6173			console.log(error);			
6174		})
6175		
6176
6177	});
6178}
6179
6180ETestUtils.simpleDecrypt = function(ciphertext, keyStr, doneFunc) {
6181	if (!ciphertext) {
6182		doneFunc('');
6183		return;
6184	}
6185	var crypto = window.crypto;
6186	if (!ETestUtils.encryptionEnabled()) {
6187		doneFunc('');
6188		return;
6189	};
6190	ETestUtils.getCipherKey(keyStr, function(key) {		
6191		var ivlength = ciphertext.substr(0,2);
6192		
6193		var ivStr = ciphertext.substr(2,ivlength*1);
6194
6195		var binary_string =  ciphertext.substr(2+ivlength*1);
6196	
6197		var iv = ETestUtils.str2ab(ivStr);
6198		var encodedBuff =  ETestUtils.str2ab(binary_string);
6199	
6200		var ret = crypto.subtle.decrypt(
6201				{
6202					name: "AES-CBC",
6203					iv: iv
6204				},
6205				key,
6206				encodedBuff
6207		);
6208
6209		ret.then(function(plainTextBuffer) {		
6210			var msg = ETestUtils.ab2str(plainTextBuffer);			
6211			doneFunc(msg);
6212		}).catch(function(error) {					
6213			console.log(error);	
6214			doneFunc('');
6215		});
6216	});	
6217}
6218
6219ETestUtils.groupidToColor = function(groupid) {
6220	var ind = 0;
6221	for (var i=0;i<groupid.length;i++) {
6222		var c = groupid.charCodeAt(i);
6223		ind = (ind * 256 + c)%ETestUtils.colors.length;
6224	}
6225
6226	return ETestUtils.colors[ind % ETestUtils.colors.length];
6227}
6228
6229ETestUtils.getAvailableLabels = function() {
6230	var ret = {
6231		'basic':  {'name': ls(8298), 'icon': 'fa-tag', 'color': '#E91E63', 'short': ls(3688), 'desc': ls(8518), 'id': 'basic',index:0},
6232		'advanced':  {'name': ls(8299), 'icon': 'fa-tag', 'color': '#9C27B0', 'short': ls(1601), 'desc': ls(8519), 'id': 'advanced',index:1}
6233	};
6234	
6235	return ret
6236}
6237
6238ETestUtils.isProjectMode = function(etestType) {
6239	return true;
6240	return etestType == ETestUtils.etestTypeProject 
6241			|| etestType == ETestUtils.etestTypeHomework
6242			|| etestType == ETestUtils.etestTypePresentation;
6243};
6244
6245ETestUtils.isImageAttachement = function(f) {
6246	return (f && f.src && (f.src.startsWith('/elearning/ruqjzfpvimg') || f.src.startsWith('/elearning/ruqjzfpvsvg') || f.src.startsWith('data:image')));
6247}
6248
6249
6250ETestUtils.showCommentEditor = function(opts) {
6251
6252	var attachements = opts.commentAtts || [];
6253	var s = '';
6254	
6255	s += '<form action="?" method="post">';
6256		s += '<div style="opacity:0.7;margin-bottom:4px;">';
6257			s += et(opts.msg);
6258		s += '</div>';
6259		s += '<div>';
6260			s += '<textarea name="comment" class="etest-commenteditor-text">{opts.comment}</textarea>';
6261		s += '</div>';
6262		s += '<div class="etest-atts-selector"></div>';
6263
6264		s += '<div class="barDialogActionButtons">';
6265		s += '<input type="submit" value="{#1573}" class="button-green">';
6266		s += '<input type="button" value="{#1038}" class="button-gray" onclick="barCloseDialog(this)">';
6267		s += '</div>';
6268	s += '</form>';
6269	
6270	s = renderS(s, {
6271		opts: opts
6272	});
6273	var dlg = barNewDialog({
6274		content: s,
6275		title: opts.title,
6276		width: 500
6277	});
6278
6279	dlg.find('.etest-atts-selector').etestAttachementsSelector({
6280		attachements: attachements,
6281		onChange: function(val) {
6282			attachements = val;
6283		}
6284	});
6285
6286	dlg.find('form').on('submit',function(e) {
6287		e.preventDefault();
6288		if (opts.confirm) {
6289			opts.confirm(dlg.find('textarea').val(), attachements);
6290		}
6291		barCloseDialog(dlg);
6292	});
6293
6294	dlg.find('textarea').each(function() {
6295		autosize($(this));
6296	}).on('autosize:resized', function(){
6297		console.log('textarea height updated');
6298	  })
6299};
6300
6301
6302(function($) {
6303$.fn.etestAttachementsSelector = function(options) {        
6304	var opts = $.extend( {}, $.fn.etestAttachementsSelector.defaults, options);
6305	
6306	
6307	function main() {     
6308		var mainElem = $(this);
6309		var attachmentsListElem = null;
6310		
6311		var lastUploadid = 0;
6312		var uploadingFiles = [];
6313
6314		var attachements = [];
6315
6316
6317		function initProperties(obj) {
6318	    	for (var x in obj) {
6319	    		opts[x] = obj[x];
6320			}
6321			attachements = opts.attachements || [];  	    
6322		}
6323
6324		function createContent() {
6325
6326			var s = '';
6327
6328			s += '<div class="etest-atts-outer '+et(opts.readonly ? 'readonly' : '')+'">';				
6329				if (!opts.readonly ) {
6330					s += '<input type="file" name="files" class="uploadWidget" style="display:none" multiple>';
6331					if (!opts.noAddButton) {
6332						s += '<div class="etest-atts-btns">';					
6333							s += '<a class="actionButton ecourse-link-button" data-action="addAttachement" title="{#6083}" style="padding: 6px;vertical-align:middle;"><i class="material-icons" style="font-size:18px;display:block">
6333attach_file</i></a>';
6334						s += '</div>';
6335					}
6336				}
6337				s += '<div class="etest-atts-list">';
6338					
6339				s += '</div>';
6340			s += '</div>';
6341
6342
6343			mainElem.html(renderS(s));
6344
6345			attachmentsListElem = mainElem.find('.etest-atts-list');
6346
6347			handleActionButtons(mainElem);
6348
6349			mainElem.find('.uploadWidget').fileupload({
6350				url: '/timeline/?akcia=uploadAtt',
6351				sequentialUploads: true,
6352				dataType: 'json',
6353				autoUpload: false,
6354				paramName: 'att',
6355				multiple: true,
6356				dropZone: mainElem.closest('.ui-dialog').length > 0 ? mainElem.closest('.ui-dialog') : mainElem,
6357				pasteZone: opts.pasteZone || (mainElem.closest('.ui-dialog').length > 0 ? mainElem.closest('.ui-dialog') : mainElem),
6358				formData: {
6359					cloudProvider: opts.cloudProvider || 'elearn_comments'
6360				}
6361			}).on('fileuploadadd', function(e, fileData) {
6362				lastUploadid++;
6363				//var uploadingMsg = barShowMessageEx(lset(6674)+' ...',null,{keepOpen: true});
6364				var uploadid = lastUploadid;
6365				var jqxhr = fileData.submit().progress(function(e, data) {
6366					var progress = parseInt(data.loaded / data.total * 100, 10);			
6367					//uploadingMsg.html(lset(6674)+' ... '+progress.toString()+'%');
6368					mainElem.find('.etest-atts-item-progress[data-id="'+et(uploadid)+'"]').css('width',progress.toString()+'%');
6369				}).success(function(data) {
6370					
6371					if (data.status == 'ok') {
6372						//barShowMessageEx(lset(9202),4000);	
6373						attachements.push({src: data.data.file, name: data.data.name});
6374
6375					} else {
6376						//if (uploadingMsg) uploadingMsg.remove();
6377						barShowMessageBox(ls(7234), 'fa-info');
6378					}
6379
6380					var nfiles = [];
6381					for (var i=0;i<uploadingFiles.length;i++) {
6382						var r = uploadingFiles[i];
6383						if (r.id == uploadid) continue;
6384						nfiles.push(r);
6385					}
6386
6387					uploadingFiles = nfiles;
6388
6389					renderAttachments();
6390					handleChange();
6391				}).fail(function() {
6392						
6393					//if (uploadingMsg) uploadingMsg.remove();
6394						
6395					var nfiles = [];
6396					for (var i=0;i<uploadingFiles.length;i++) {
6397						var r = uploadingFiles[i];
6398						if (r.id == uploadid) continue;
6399						nfiles.push(r);
6400					}
6401
6402					uploadingFiles = nfiles;
6403					renderAttachments();
6404				});
6405				
6406				uploadingFiles.push({
6407					id: uploadid,
6408					name: fileData.files[0] ? fileData.files[0].name : '',
6409					jqxhr: jqxhr,
6410					error: ''
6411				});
6412				renderAttachments();
6413
6414				if (opts.onFileAdded) {
6415					opts.onFileAdded();
6416				}
6417			});	
6418			renderAttachments();
6419		}
6420
6421		function renderAttachments() {
6422			var s = '';
6423			if ((attachements.length>0 || uploadingFiles.length) && opts.attachementsTitle !== false) {
6424				s += '<div style="margin: 10px 0px 0 0px;display:block;padding: 0"><b>'+lset(4037)+' - '+lset(4018)+':</b></div>';
6425			}
6426			for (var i=0;i<attachements.length;i++) {
6427				var file = attachements[i];		
6428									
6429				var ss = '';
6430				ss += '<div class="etest-atts-item app-color-bg-hover" data-file="{fileSrc}" style="display:{display}">';
6431					if (ETestUtils.isImageAttachement(file)) {	
6432						ss += '<a class="etest-atts-img-link" data-link="{fileSrc}" data-ind={i}>';
6433					} else {
6434						ss += '<a href="{fileSrc}" target="_blank">';
6435					}
6436						if (opts.readonly) {
6437							ss += '<i class="material-icons" style="vertical-align:middle;font-size:18px;margin-left:-4px;margin-right:4px;">
6437attach_file</i>';
6438						}
6439						ss += '{file.name}';
6440					ss += '</a>';
6441						
6442					if (!opts.readonly) {
6443						ss += '<a class="actionButton app-color-bg-hover" style="cursor:pointer" data-action="removeAttachment" data-ind="{i}"><i class="fa fa-fw fa-remove"></i></a>';
6444					}
6445				ss += '</div>';
6446
6447				s += renderS(ss, {
6448					file: file,
6449					display: opts.hideCommentAtts && file.forSrc ? 'none' : '',
6450					fileSrc: Timeline.validateLink(file.src),
6451					i: i
6452				})
6453			}
6454
6455			for (var i=0;i<uploadingFiles.length;i++) {
6456				var file = uploadingFiles[i];					
6457				var ss = '';
6458				ss += '<div class="etest-atts-item uploading app-color-bg-hover" data-file="{fileSrc}">';
6459					ss += '<a><i class="fa fa-fw fa-spinner fa-spin" style="vertical-align:middle"></i> {file.name}</a>';
6460					ss += '<a class="actionButton app-color-bg-hover" style="cursor:pointer;" data-action="cancelUpload" data-id="{file.id}"><i class="fa fa-fw fa-remove"></i></a>';
6461					ss += '<div class="etest-atts-item-progress" data-id="{file.id}"></div>';
6462				ss += '</div>';
6463
6464				s += renderS(ss, {
6465					file: file,
6466					i: i
6467				})
6468			}
6469			
6470			attachmentsListElem.html(s);
6471
6472			handleActionButtons(attachmentsListElem);
6473			attachmentsListElem.find('.etest-atts-img-link').on('click',function() {
6474				actionFuncs.showImages($(this));
6475			});
6476		}
6477
6478		function handleChange() {
6479			if (opts.onChange) {
6480				var atts = [];
6481				for (var i=0;i<attachements.length;i++) {
6482					atts.push(attachements[i]);
6483				}
6484				opts.onChange(atts);				
6485			}
6486		}
6487		function handleActionButtons(elem) {
6488			elem.find('.actionButton').off('click.actionButton touchstart.actionButton').on('click.actionButton touchstart.actionButton',function(e) {
6489				e.preventDefault();
6490				ETestUtils.handleActionButton(this, actionFuncs);
6491			});
6492		}
6493
6494		var actionFuncs = {};
6495		actionFuncs.showImages = function(elem) {
6496			var images = [];
6497			var ind0 = $(elem).attr('data-ind');
6498			var ind = 0;
6499			for (var i=0;i<attachements.length;i++) {			
6500				var file = attachements[i];		
6501				
6502				if (ETestUtils.isImageAttachement(file)) {
6503					if (i == ind0) ind = images.length;
6504					images.push(file);
6505				}
6506			}
6507
6508			ETestUtils.openImagePreview1({
6509				photos: images,
6510				index: ind,
6511			});
6512		}
6513
6514		actionFuncs.cancelUpload = function(elem) {				
6515			var uploadid = $(elem).attr('data-id');
6516			barShowMessageBox(ls(10220), 'fa-question', {
6517				confirm: function() {
6518					var nfiles = [];
6519					for (var i=0;i<uploadingFiles.length;i++) {
6520						var r = uploadingFiles[i];
6521						if (r.id == uploadid) {
6522							if (r.jqxhr) r.jqxhr.abort();
6523							continue;
6524						}
6525							
6526						nfiles.push(r);
6527					}
6528
6529					uploadingFiles = nfiles;
6530
6531					renderAttachments();
6532					barShowMessage(ls(1311));		
6533				}
6534			});
6535		}
6536
6537		actionFuncs.removeAttachment = function(elem) {
6538			var ind = $(elem).attr('data-ind')*1;
6539			var oldAttachments = [];
6540			for (var i=0;i<attachements.length;i++) {
6541				oldAttachments.push(attachements[i]);
6542			}
6543			attachements.splice(ind,1);
6544			renderAttachments();
6545			barShowMessage(lset(1311)+'. <a class="ecourse-link-button">'+lset(7482)+'</a>',10000, 'undoMsg', function() {				
6546				attachements = oldAttachments;
6547				renderAttachments();
6548				handleChange();
6549			});
6550			handleChange();
6551		}
6552
6553		actionFuncs.addAttachement = function(elem) {
6554			if (opts.showAlert) {
6555				barShowMessageBox(opts.showAlert, 'fa-info', {
6556					okLbl: ls(8589),
6557					confirm: function() {
6558						mainElem.find('.uploadWidget').click();
6559					}
6560				});
6561			} else {
6562				mainElem.find('.uploadWidget').click();
6563			}
6564		}
6565
6566		actionFuncs.resetAttachments = function() {
6567			attachements = [];
6568			renderAttachments();
6569		}
6570	
6571		initProperties({});
6572		createContent();
6573		mainElem.data('publicActions',actionFuncs);
6574 	}   
6575 
6576	return this.each(main);
6577};
6578
6579$.fn.etestAttachementsSelector.defaults = {	    	
6580	
6581};
6582}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.