xref: /plugin/mikioplugin/script.js (revision 61729b71b07b4881860491a1169c0ffb1e41ae7d)
1
2
3jQuery().ready(function () {
4    var stripHtml = function(htmlString) {
5        var tempDiv = document.createElement("div");
6        tempDiv.innerHTML = htmlString;
7        return tempDiv.textContent || tempDiv.innerText || "";
8    };
9
10    var urlMatches = function(url) {
11        const windowURL = new URL(window.location);
12        const urlObject = new URL(url.startsWith('http') ? url : window.origin + url);
13        let match = true;
14
15        if(windowURL.origin !== urlObject.origin) {
16            return false;
17        }
18
19        urlObject.searchParams.forEach((val, key) => {
20            if(!windowURL.searchParams.has(key) || windowURL.searchParams.get(key) !== val) {
21                match = false;
22            }
23        });
24
25        return match;
26    };
27
28    jQuery('.mikiop-button').on('click', function (event) {
29        if (jQuery(this).hasClass('mikiop-disabled')) {
30            event.preventDefault();
31        }
32
33        if (jQuery(this).attr('data-toggle') == 'collapse') {
34            event.preventDefault();
35            jQuery(jQuery(this).attr('data-target')).slideToggle();
36        }
37    });
38
39    jQuery('.mikiop-accordian-title').on('click', function (event) {
40        event.preventDefault();
41        let accordianBody = jQuery(this).siblings('.mikiop-accordian-body');
42        if (!accordianBody.is(':visible')) {
43            let accordian = jQuery(this).closest('.mikiop-accordian');
44            if (accordian.hasClass('mikiop-autoclose')) {
45                accordian.find('.mikiop-accordian-body:visible').slideUp();
46            }
47        }
48
49        jQuery(this).siblings('.mikiop-accordian-body').slideToggle();
50    });
51
52    jQuery('.mikiop-alert-close').on('click', function (event) {
53        event.preventDefault();
54        jQuery(this).closest('.mikiop-alert').hide();
55    });
56
57    jQuery('.mikiop-carousel').each(function () {
58        var items = jQuery(this).find('.mikiop-carousel-item');
59        var indicators = '';
60        var active = false;
61
62        for (var i = 0; i < items.length; i++) {
63            if (jQuery(items[i]).hasClass('mikiop-active')) {
64                active = true;
65                indicators += '<li class="mikiop mikiop-carousel-indicator mikiop-active"></li>';
66            } else {
67                indicators += '<li class="mikiop mikiop-carousel-indicator"></li>';
68            }
69        };
70
71        jQuery(this).find('.mikiop-carousel-indicators').html(indicators);
72
73        if (!active) {
74            jQuery(this).find('.mikiop-carousel-item').first().addClass('mikiop-active');
75            jQuery(this).find('.mikiop-carousel-indicator').first().addClass('mikiop-active');
76        }
77
78        if (jQuery(this).attr('data-auto-start') == 'true') {
79            var carousel = jQuery(this);
80            timeout = carousel.find('.mikiop-carousel-item.mikiop-active').attr('data-interval');
81
82            if (timeout == 0) {
83                timeout = 3;
84            }
85
86            var nextSlide = function () {
87                var timeout = carouselNext(carousel);
88
89                if (timeout == 0) {
90                    timeout = 3;
91                }
92
93                window.setTimeout(nextSlide, (timeout * 1000) + 500);
94            };
95
96            window.setTimeout(nextSlide, (timeout * 1000) + 500);
97        }
98    });
99
100    jQuery('.mikiop-carousel-control-prev').on('click', function (event) {
101        event.preventDefault();
102
103        var parent = jQuery(this).parent();
104        carouselPrev(parent);
105    });
106
107    function carouselPrev(parent) {
108
109        var slides = parent.find('.mikiop-carousel-item');
110
111        for (var i = 0; i < slides.length; i++) {
112            if (jQuery(slides[i]).hasClass('mikiop-active')) {
113                var target = null;
114                var next = 0;
115
116                if (i == 0) {
117                    next = slides.length - 1;
118                } else {
119                    next = i - 1;
120                }
121                target = jQuery(slides[next]);
122
123                if (jQuery(parent).hasClass('mikiop-transition-fade')) {
124                    target.css('z-index', 0).addClass('mikiop-active');
125                    jQuery(slides[i]).fadeOut(function () {
126                        jQuery(this).removeClass('mikiop-active').css('display', '');
127                        target.css('z-index', '');
128                    });
129                } else if (jQuery(parent).hasClass('mikiop-transition-slide')) {
130                    target.css('left', '-100%').addClass('mikiop-active');
131                    target.animate({ left: '0' }, 500);
132                    jQuery(slides[i]).animate({ left: '100%' }, 500, function () {
133                        jQuery(this).removeClass('mikiop-active').css('left', '');
134                        target.css('left', '');
135                    })
136                } else {
137                    target.addClass('mikiop-active');
138                    jQuery(slides[i]).removeClass('mikiop-active');
139                }
140
141                parent.find('.mikiop-carousel-indicator').removeClass('mikiop-active');
142                parent.find('.mikiop-carousel-indicator:nth-child(' + (next + 1) + ')').addClass('mikiop-active');
143
144                break;
145            }
146        }
147    };
148
149    jQuery('.mikiop-carousel-control-next').on('click', function (event) {
150        event.preventDefault();
151        var parent = jQuery(this).parent();
152
153        carouselNext(parent);
154    });
155
156    function carouselNext(parent) {
157        var slides = parent.find('.mikiop-carousel-item');
158        var delay = 0;
159
160        for (var i = 0; i < slides.length; i++) {
161
162
163            if (jQuery(slides[i]).hasClass('mikiop-active')) {
164                var target = null;
165                var next = 0;
166
167
168                if (i == slides.length - 1) {
169                    next = 0;
170                } else {
171                    next = i + 1;
172                }
173                target = jQuery(slides[next]);
174
175                delay = target.attr('data-interval');
176                if (typeof delay == 'undefined') {
177                    delay = 0;
178                }
179
180                if (jQuery(parent).hasClass('mikiop-transition-fade')) {
181                    target.css('z-index', 0).addClass('mikiop-active');
182                    jQuery(slides[i]).fadeOut(function () {
183                        jQuery(this).removeClass('mikiop-active').css('display', '');
184                        target.css('z-index', '');
185                    });
186                } else if (jQuery(parent).hasClass('mikiop-transition-slide')) {
187                    target.css('left', '100%').addClass('mikiop-active');
188                    target.animate({ left: '0' }, 500);
189                    jQuery(slides[i]).animate({ left: '-100%' }, 500, function () {
190                        jQuery(this).removeClass('mikiop-active').css('left', '');
191                        target.css('left', '');
192                    })
193                } else {
194                    target.addClass('mikiop-active');
195                    jQuery(slides[i]).removeClass('mikiop-active');
196                }
197
198                parent.find('.mikiop-carousel-indicator').removeClass('mikiop-active');
199                parent.find('.mikiop-carousel-indicator:nth-child(' + (next + 1) + ')').addClass('mikiop-active');
200
201                break;
202            }
203        }
204
205        return (delay);
206    };
207
208    jQuery('.mikiop-carousel-indicator').on('click', function (event) {
209        event.preventDefault();
210
211        var parent = jQuery(this).closest('.mikiop-carousel-indicators');
212        if (parent) {
213            var group = jQuery(this).closest('.mikiop-carousel');
214            if (group) {
215                var items = jQuery(group).find('.mikiop-carousel-indicator');
216
217                var item = -1;
218                var active = 0;
219                for (var i = 0; i < items.length; i++) {
220                    if (jQuery(items[i]).hasClass('mikiop-active')) {
221                        active = i;
222                    }
223
224                    if (items[i] == jQuery(this)[0]) {
225                        item = i;
226                    }
227                }
228
229                if (item != active) {
230                    if (jQuery(group).hasClass('mikiop-transition-fade')) {
231                        var target = jQuery(group).find('.mikiop-carousel-item:nth-child(' + (item + 1) + ')');
232
233                        target.css('z-index', 0).addClass('mikiop-active');
234                        jQuery(group).find('.mikiop-carousel-item:nth-child(' + (active + 1) + ')').fadeOut(function () {
235                            jQuery(this).removeClass('mikiop-active').css('display', '');
236                            target.css('z-index', '');
237                        });
238
239                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (item + 1) + ')').addClass('mikiop-active');
240                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (active + 1) + ')').removeClass('mikiop-active');
241                    } else if (jQuery(group).hasClass('mikiop-transition-slide')) {
242                        var target = jQuery(group).find('.mikiop-carousel-item:nth-child(' + (item + 1) + ')');
243
244                        if (item < active) {
245                            target.css('left', '-100%').addClass('mikiop-active');
246                            target.animate({ left: '0' }, 500);
247                            jQuery(group).find('.mikiop-carousel-item:nth-child(' + (active + 1) + ')').animate({ left: '100%' }, 500, function () {
248                                jQuery(this).removeClass('mikiop-active').css('left', '');
249                                target.css('left', '');
250                            });
251                        } else {
252                            target.css('left', '100%').addClass('mikiop-active');
253                            target.animate({ left: '0' }, 500);
254                            jQuery(group).find('.mikiop-carousel-item:nth-child(' + (active + 1) + ')').animate({ left: '-100%' }, 500, function () {
255                                jQuery(this).removeClass('mikiop-active').css('left', '');
256                                target.css('left', '');
257                            });
258                        }
259
260                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (item + 1) + ')').addClass('mikiop-active');
261                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (active + 1) + ')').removeClass('mikiop-active');
262                    } else {
263                        jQuery(group).find('.mikiop-carousel-item:nth-child(' + (item + 1) + ')').addClass('mikiop-active');
264                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (item + 1) + ')').addClass('mikiop-active');
265                        jQuery(group).find('.mikiop-carousel-item:nth-child(' + (active + 1) + ')').removeClass('mikiop-active');
266                        jQuery(group).find('.mikiop-carousel-indicator:nth-child(' + (active + 1) + ')').removeClass('mikiop-active');
267                    }
268                }
269            }
270        }
271    });
272
273    jQuery('.mikiop-tab-item a').on('click', function (event) {
274        event.preventDefault();
275
276        var parent = jQuery(this).closest('.mikiop-tab-item');
277        if (parent) {
278            var group = jQuery(parent).closest('.mikiop-tab-group');
279            if (group) {
280                var items = jQuery(group).find('.mikiop-tab-item');
281
282                var item = -1;
283                for (var i = 0; i < items.length; i++) {
284                    if (items[i] == parent[0]) {
285                        item = i;
286                        break;
287                    }
288                }
289
290                if (item != -1) {
291                    var panes = jQuery(group).siblings('.mikiop-tab-content').find('.mikiop-tab-pane');
292
293                    if (panes.length > item) {
294                        if (!jQuery(panes[item]).hasClass('mikiop-show')) {
295                            jQuery(panes).removeClass('mikiop-show');
296                            jQuery(panes[item]).addClass('mikiop-show');
297
298                            jQuery(items).find('a').removeClass('mikiop-active');
299                            jQuery(items[item]).find('a').addClass('mikiop-active');
300                        }
301                    }
302                }
303            }
304        }
305    });
306
307    // Quiz
308    var quizReset = function(quizRef) {
309        quizRef.find('.mikiop-quiz-button-prev').attr('disabled', true);
310        quizRef.find('.mikiop-quiz-result').hide();
311        quizRef.find('.mikiop-quiz-button-submit').show().attr('disabled', false);
312        quizRef.find('.mikiop-quiz-button-reset').hide();
313
314        var status = quizRef.attr('data-status');
315        status = status.replace('$1', '1');
316        status = status.replace('$2', quizRef.children('.mikiop-quiz-item').length);
317        quizRef.find('.mikiop-quiz-status-text').html(status);
318
319        if (quizRef.children('.mikiop-quiz-item').length == 1) {
320            quizRef.find('.mikiop-quiz-button-next').attr('disabled', true);
321        } else {
322            quizRef.find('.mikiop-quiz-button-next').attr('disabled', false);
323        }
324
325        quizRef.children('.mikiop-quiz-item').find('input[type="radio"], input[type="checkbox"]').prop('checked', false);
326
327        var full = quizRef.attr('data-full');
328        if(!full) {
329            quizRef.children('.mikiop-quiz-item').not(':first-child').hide();
330            quizRef.children('.mikiop-quiz-item:first-child').show();
331        } else {
332            quizRef.children('.mikiop-quiz-item').show();
333        }
334    };
335
336    jQuery('.mikiop-quiz').each(function () {
337        quizReset(jQuery(this));
338    });
339
340    jQuery('.mikiop-quiz-button-prev').on('click', function (event) {
341        var parent = jQuery(this).closest('.mikiop-quiz');
342        var questions = parent.children('.mikiop-quiz-item');
343        parent.find('.mikiop-quiz-button-next').attr('disabled', false);
344
345        for (var i = 0; i < questions.length; i++) {
346            if (jQuery(questions[i]).is(':visible')) {
347                i--;
348
349                if (i <= 0) {
350                    jQuery(this).attr('disabled', true);
351                }
352
353                jQuery(questions[i + 1]).hide();
354                jQuery(questions[i]).show();
355                parent.find('.mikiop-quiz-status-number').html(i + 1);
356
357                var status = parent.attr('data-status');
358                status = status.replace('$1', i + 1);
359                status = status.replace('$2', parent.children('.mikiop-quiz-item').length);
360                parent.find('.mikiop-quiz-status-text').html(status);
361
362                break;
363            }
364        }
365    });
366
367    jQuery('.mikiop-quiz-button-next').on('click', function (event) {
368        var parent = jQuery(this).closest('.mikiop-quiz');
369        var questions = parent.children('.mikiop-quiz-item');
370        parent.find('.mikiop-quiz-button-prev').attr('disabled', false);
371
372        for (var i = 0; i < questions.length; i++) {
373            if (jQuery(questions[i]).is(':visible')) {
374                i++;
375
376                if (i >= questions.length - 1) {
377                    jQuery(this).attr('disabled', true);
378                }
379
380                jQuery(questions[i - 1]).hide();
381                jQuery(questions[i]).show();
382
383                var status = parent.attr('data-status');
384                status = status.replace('$1', i + 1);
385                status = status.replace('$2', parent.children('.mikiop-quiz-item').length);
386                parent.find('.mikiop-quiz-status-text').html(status);
387
388                break;
389            }
390        }
391    });
392
393    jQuery('.mikiop-quiz-button-submit').on('click', function (event) {
394        var parent = jQuery(this).closest('.mikiop-quiz');
395        var questions = parent.children('.mikiop-quiz-item');
396        var correct = 0;
397        var totalScore = 0;
398        var result = '<div class="mikiop-quiz-question">Result</div>';
399
400        var usingScoring = false;
401        var usingCorrect = false;
402        var questionCount = 0;
403
404        parent.find('.mikiop-quiz-button-prev').attr('disabled', true);
405        parent.find('.mikiop-quiz-button-next').attr('disabled', true);
406        parent.find('.mikiop-quiz-button-submit').attr('disabled', true);
407        parent.find('.mikiop-quiz-status-text').html('');
408
409        var resetButton = parent.find('.mikiop-quiz-button-reset');
410        if(resetButton.length > 0) {
411            parent.find('.mikiop-quiz-button-submit').hide();
412            resetButton.show();
413        }
414
415
416        for (var i = 0; i < questions.length; i++) {
417            var showNewLine = true;
418            var question = stripHtml(jQuery(questions[i]).attr('data-question'));
419            var regex = /^((\w+ ?)*[):])/;
420
421            if (regex.test(question)) {
422                question = question.match(regex)[1];
423                showNewLine = false;
424            }
425
426            result += '<p class="mikiop-quiz-result-question"><strong>' + question + '</strong>' + (showNewLine ? '<br>' : ' ');
427
428            var checked = jQuery(questions[i]).find("input:checked");
429            var answer = jQuery(questions[i]).attr('data-answer');
430            var value = checked.val();
431
432            if(answer != undefined) {
433                usingCorrect = true;
434                questionCount++;
435            }
436
437            if (typeof value == 'undefined') {
438                result += 'Not answered';
439            } else {
440                // check that input radio groups with the same name have at least 1 answer
441                let radioPass = true;
442                let radioGroups = {};
443                const radios = jQuery(questions[i]).find('input[type="radio"]');
444
445                radios.each(function () {
446                    const groupName = jQuery(this).attr('name');
447
448                    if (!radioGroups[groupName]) {
449                        radioGroups[groupName] = [];
450                    }
451
452                    radioGroups[groupName].push(jQuery(this));
453                });
454
455                for (const key in radioGroups) {
456                    if (radioGroups.hasOwnProperty(key)) {
457                        const group = radioGroups[key];
458                        const anySelected = group.some(function (radio) {
459                            return radio.prop('checked');
460                        });
461
462                        if (!anySelected) {
463                            result += 'An option was not answered';
464                            radioPass = false;
465                            break;
466                        }
467                    }
468                }
469
470                if(radioPass) {
471                    var totalItemScore = 0;
472                    var selectedItems = [];
473                    var itemIsScored = false;
474
475                    checked.each(function() {
476                        var item = jQuery(this);
477
478                        var score = item.attr('data-score');
479
480                        if(score != undefined && score.length > 0) {
481                            usingScoring = true;
482                            itemIsScored = true;
483                            totalItemScore += parseInt(score, 10);
484                        } else if(answer != undefined) {
485                            usingCorrect = true;
486                            selectedItems.push(item.val());
487                        }
488                    });
489
490                    if(itemIsScored) {
491                        var scorePlaceholder = parent.attr('data-result-score');
492                        result += scorePlaceholder.replace('$1', totalItemScore);
493                        totalScore += totalItemScore;
494                    } else {
495                        var correctText = parent.attr('data-correct');
496                        var incorrectText = parent.attr('data-incorrect');
497
498                        result += selectedItems.join(", ") + ' - ';
499
500                        if(answer == undefined) {
501                            result += "No answer set for question";
502                        } else if(answer.indexOf('|') !== -1) {
503                            var answerArray = answer.split('|');
504                            if(answerArray.length == selectedItems.length) {
505                                var totalMatch = true;
506                                answerArray.forEach(function(answerItem) {
507                                    var matching = selectedItems.some(function(selectedItem) {
508                                        return answerItem.localeCompare(selectedItem) === 0;
509                                    });
510
511                                    if(!matching) {
512                                        totalMatch = false;
513                                    }
514                                });
515
516                                if(totalMatch) {
517                                    correct++;
518                                    result += correctText;
519                                } else {
520                                    result += incorrectText;
521                                }
522                            } else {
523                                result += incorrectText;
524                            }
525                        } else {
526                            if (selectedItems.length > 0 && answer.localeCompare(selectedItems[0]) == 0) {
527                                correct++;
528                                result += correctText;
529                            } else {
530                                result += incorrectText;
531                            }
532                        }
533                    }
534                }
535            }
536
537            result += '</p>';
538
539            jQuery(questions[i]).hide();
540        }
541
542        var status = [];
543
544        if(usingScoring) {
545            status.push(parent.attr('data-result-score-total').replace('$1', totalScore));
546        }
547
548        if(usingCorrect) {
549            status.push(parent.attr('data-result-correct').replace('$1', correct).replace('$2', questionCount));
550        }
551
552        result += '<p class="mikiop-quiz-result-total">' + status.join('<br>') + '</p>';
553
554        parent.find('.mikiop-quiz-result').html(result).show();
555    });
556
557    jQuery('.mikiop-quiz-button-reset').on('click', function (event) {
558        quizReset(jQuery(this).closest('.mikiop-quiz'));
559    });
560
561    // Pagination
562    var pages = jQuery('.mikiop-pagination').find('li:not(.mikiop-pagination-prev,.mikiop-pagination-next)');
563    if (pages.length > 0) {
564        var active = -1;
565        var found = -1;
566        var location = window.location.pathname + window.location.search;
567
568        if (window.location.search == '') {
569            location += '?id=start';
570        }
571
572        for (i = 0; i < pages.length; i++) {
573            if (jQuery(pages[i]).hasClass('mikiop-active')) {
574                if (active != -1) {
575                    jQuery(pages[i]).removeClass('mikiop-active')
576                } else {
577                    active = i;
578                }
579            }
580
581            var link = jQuery(pages[i]).find('a').attr('href');
582            if(urlMatches(link)) {
583                found = i;
584            }
585        }
586
587        if (active == -1 && found != -1) {
588            active = found;
589            jQuery(pages[found]).addClass('mikiop-active');
590        }
591
592        if (active != -1) {
593            if (active == 1) {
594                jQuery('.mikiop-pagination').find('.mikiop-pagination-prev').addClass('mikiop-disabled');
595            } else {
596                jQuery('.mikiop-pagination').find('.mikiop-pagination-prev').find('a').attr('href', jQuery(pages[active - 1]).find('a').attr('href'));
597            }
598
599            if (active == pages.length - 1) {
600                jQuery('.mikiop-pagination').find('.mikiop-pagination-next').addClass('mikiop-disabled');
601            } else {
602                jQuery('.mikiop-pagination').find('.mikiop-pagination-next').find('a').attr('href', jQuery(pages[active + 1]).find('a').attr('href'));
603            }
604        } else {
605            jQuery('.mikiop-pagination').find('.mikiop-pagination-prev').addClass('mikiop-disabled');
606            jQuery('.mikiop-pagination').find('.mikiop-pagination-next').addClass('mikiop-disabled');
607        }
608    } else {
609        jQuery('.mikiop-pagination').find('.mikiop-pagination-prev').addClass('mikiop-disabled');
610        jQuery('.mikiop-pagination').find('.mikiop-pagination-next').addClass('mikiop-disabled');
611    }
612
613    // Reveal
614    jQuery('.mikiop-box').on('mouseenter', function () {
615        jQuery(this).children('.mikiop-reveal').fadeOut();
616    });
617
618    jQuery('.mikiop-box').on('mouseleave', function () {
619        jQuery(this).children('.mikiop-reveal').fadeIn();
620    });
621
622    // Tooltip
623    jQuery('.mikiop-tooltip').hover(function (event) {
624        jQuery('<div class="mikiop-tooltip-banner">' + jQuery(this).attr('data-tooltip') + '</div>').appendTo('body');
625    }, function () {
626        jQuery('.mikiop-tooltip-banner').remove();
627    });
628
629    jQuery('.mikiop-tooltip').on('mousemove', function (event) {
630        var moveLeft = 20;
631        var moveDown = 10;
632        jQuery('.mikiop-tooltip-banner').css('top', event.pageY + moveDown).css('left', event.pageX + moveLeft);
633    });
634
635    // Nav
636    jQuery('.mikiop-nav').on('click', function (event) {
637        jQuery(this).toggleClass('mikiop-nav-open');
638    });
639    jQuery(document).on('click', function (event) {
640        if (!jQuery(event.target).closest('.mikiop-nav').length) {
641            // Hide the dropdown if clicked outside
642            jQuery('.mikiop-nav').removeClass('mikiop-nav-open');
643        }
644    });
645
646    jQuery('.mikiop-collapse').hide();
647});
648