PageSourceSearch

https://canlanguage.com/wp-content/plugins/learndash-advance-quizz…/js/wpProQuiz_front.js?ver=1791417663

js canlanguage.com collected 2026-10-08 00:01:35 UTC 283,454 bytes, 6,436 lines download raw bytes

1var gumStream;                      //stream from getUserMedia()
2var recorder;                       //WebAudioRecorder object
3var input;                          //MediaStreamAudioSourceNode  we'll be recording
4var blobAudio;
5
6(function ($) {
7    /**
8     * @memberOf $
9     */
10    $.wpProQuizFront = function (element, options) {
11
12        var $e = $(element);
13        var config = options;
14        var result_settings = {};
15        var plugin = this;
16        var results = new Object();
17        var catResults = new Object();
18        var startTime = 0;
19        var currentQuestion = null;
20        var quizSolved = [];
21        var is_quiz_resume_in_process = "no";
22        var question_resumed = [];
23        var is_resume_save_event_attached = false;
24        var lastButtonValue = '';
25        var inViewQuestions = false;
26        var currentPage = 1;
27        var timespent = 0;
28        var sending_timer = null;
29
30        var cookie_name = '';
31        var cookieSendTimer = false;
32        var cookie_value = '';
33        var cookieExpireDate = 0;
34        var cookieSending = false;
35        var quiz_resume_data = {};
36
37        var bitOptions = {
38            randomAnswer: 0,
39            randomQuestion: 0,
40            disabledAnswerMark: 0,
41            checkBeforeStart: 0,
42            preview: 0,
43            cors: 0,
44            isAddAutomatic: 0,
45            quizSummeryHide: 0,
46            skipButton: 0,
47            reviewQustion: 0,
48            autoStart: 0,
49            forcingQuestionSolve: 0,
50            hideQuestionPositionOverview: 0,
51            formActivated: 0,
52            maxShowQuestion: 0,
53            sortCategories: 0
54        };
55
56        var quizStatus = {
57            isQuizStart: 0,
58            isLocked: 0,
59            loadLock: 0,
60            isPrerequisite: 0,
61            isUserStartLocked: 0
62        };
63
64        /*
65            var QuizRepeats = {
66                quizRepeats: 0,
67                userAttemptsTaken: 0,
68                userAttemptsLeft: 0,
69            };
70        */
71        var globalNames = {
72            check: 'input[name="check"]',
73            next: 'input[name="next"]',
74            tip: 'input[name="tip"]',
75            questionList: '.wpProQuiz_questionList',
76            skip: 'input[name="skip"]',
77            singlePageLeft: 'input[name="wpProQuiz_pageLeft"]',
78            singlePageRight: 'input[name="wpProQuiz_pageRight"]',
79            save: 'input[name="save"]', //Added by webxity
80            resume: 'input[name="resume"]' //Added by webxity
81        };
82
83        var globalElements = {
84            back: $e.find('input[name="back"]'),
85            next: $e.find(globalNames.next),
86            quiz: $e.find('.wpProQuiz_quiz'),
87            questionList: $e.find('.wpProQuiz_list'),
88            results: $e.find('.wpProQuiz_results'),
89            sending: $e.find('.wpProQuiz_sending'),
90            quizStartPage: $e.find('.wpProQuiz_text'),
91            timelimit: $e.find('.wpProQuiz_time_limit'),
92            toplistShowInButton: $e.find('.wpProQuiz_toplistShowInButton'),
93            listItems: $(),
94            save: $(".ld_advance_quiz_save"), //Added by webxity
95            resume: $(".ld_advance_quiz_resume"), //Added by webxity
96            save_as_next: $("#ld_advanced_save_as_next").val() //Added by webxity
97        };
98
99        var toplistData = {
100            token: '',
101            isUser: 0
102        };
103
104        var formPosConst = {
105            START: 0,
106            END: 1
107        };
108
109        var viewedQuestions = [];
110        var checkedQuestions = [];
111        var resumedQuestions = [];
112        var saveQuizTrigger = 'button'; //Added by Webxity to save state trigger source
113
114        //Added by Webxity - Start
115        var retake_quiz_enabled = LDAdvancedQuizVars.retake_quiz_enabled;
116        var quiz_question_timer_enabled = LDAdvancedQuizVars.quiz_disable_question_time_limit === "0";
117        var is_negative_marking_enabled = LDAdvancedQuizVars.is_negative_marking_enabled;
118        var lastViewedQuestion = 0;
119        //Added by Webxity - End
120
121        /**
122         * @memberOf timelimit
123         */
124        if (LDAdvancedQuizVars.time_limit_enabled == 'on') {
125            /**
126         * @memberOf timelimit
127         */
128            var timelimit = {
129                counter: config.timelimit,
130                intervalId: 0,
131                instance: {},
132                // set cookie for different users and different quizzes
133                timer_cookie: 'ldadv-time-limit-' + config.user_id + '-' + config.quizId,
134
135                stop: function () {
136                    if (this.counter) {
137                        $.removeCookie(this.timer_cookie);
138                        window.clearInterval(this.intervalId);
139                        globalElements.timelimit.hide();
140                    }
141                },
142                start: function () {
143                    if (!this.counter) {
144                        return;
145                    }
146                    this.timer_cookie
147                    $.cookie.raw = true;
148
149                    var full = this.counter * 1000;
150                    var tick = jQuery.cookie(this.timer_cookie);
151                    var limit = 0;
152
153                    if (tick) {
154                        limit = tick;
155                    } else {
156                        limit = this.counter;
157                    }
158                    
159                    if( typeof learndash_prepare_quiz_resume_data == 'function' ) {
160                        var resume_data = learndash_prepare_quiz_resume_data(config);
161                        if (resume_data !== false) {
162                            if (resume_data[this.timer_cookie]) {
163                                limit = resume_data[this.timer_cookie];
164                            }
165                        }
166                    }
167                    
168
169                    var x = limit * 1000;
170
171                    var $timeText = globalElements.timelimit.find('span').text(plugin.methode.parseTime(limit));
172                    var $timeDiv = globalElements.timelimit.find('.wpProQuiz_progress');
173
174                    globalElements.timelimit.show();
175
176                    var beforeTime = +new Date();
177
178                    this.intervalId = window.setInterval(function () {
179                        var diff = (+new Date() - beforeTime);
180                        var remainingTime = x - diff;
181
182                        if (diff >= 500) {
183                            tick = remainingTime / 1000;
184                            $timeText.text(plugin.methode.parseTime(Math.ceil(tick)));
185                            $.cookie(this.timer_cookie, tick);
186                        }
187
188                        $timeDiv.css('width', (remainingTime / full * 100) + '%');
189
190                        if (remainingTime <= 0) {
191                            this.stop();
192                            plugin.methode.finishQuiz(true);
193                        }
194                    }.bind(this), 16);
195
196                    if (config.quiz_resume_enabled === '1' && !cookieSendTimer) {
197                        plugin.methode.startCookieSendTimer();
198                    }
199                },
200                pause: function () {
201                    if (this.counter) {
202                        //$.removeCookie(timer_cookie);
203                        window.clearInterval(this.intervalId);
204                        globalElements.timelimit.hide();
205                        this.intervalId = 0;
206                    }
207                },
208            };
209        } else {
210            var timelimit = (function () {
211                var _counter = config.timelimit;
212                var _intervalId = 0;
213                var instance = {};
214
215                // set cookie for different users and different quizzes
216                var timer_cookie = "ldadv-time-limit-" + config.user_id + "-" + config.quizId;
217
218                instance.stop = function () {
219                    if (_counter) {
220                        $.removeCookie(timer_cookie);
221                        window.clearInterval(_intervalId);
222                        globalElements.timelimit.hide();
223                        _intervalId = 0;
224                    }
225                };
226                instance.getInterval = function () {
227                    return _intervalId;
228                };
229                //section by webxity
230                instance.pause = function () {
231                    if (_counter) {
232                        //$.removeCookie(timer_cookie);
233                        window.clearInterval(_intervalId);
234                        globalElements.timelimit.hide();
235                        _intervalId = 0;
236                    }
237                };
238                //End section by webxity;
239                instance.start = function () {
240
241                    //section by webxity
242                    var differnt_limit = $("#ld_advanced_question_time_limit").val();
243
244                    if (differnt_limit == 'yes' && quiz_question_timer_enabled) {
245                        _counter = config.timelimit;
246                    }
247                    if (_counter == 0) {
248                        _counter.NaN;
249                    }
250                    //End section by webxity;
251
252                    if (!_counter) return;
253
254                    $.cookie.raw = true;
255
256                    var full = _counter * 1000;
257                    var tick = $.cookie(timer_cookie);
258                    var limit = tick ? tick : _counter;
259                    var x = limit * 1000;
260
261                    var $timeText = globalElements.timelimit
262                        .find("span")
263                        .text(plugin.methode.parseTime(limit));
264                    var $timeDiv = globalElements.timelimit.find(".wpProQuiz_progress");
265
266                    globalElements.timelimit.show();
267
268                    var beforeTime = +new Date();
269
270                    _intervalId = window.setInterval(function () {
271                        var diff = +new Date() - beforeTime;
272                        var remainingTime = x - diff;
273
274                        if (diff >= 500) {
275                            tick = remainingTime / 1000;
276                            $timeText.text(plugin.methode.parseTime(Math.ceil(tick)));
277                            $.cookie(timer_cookie, tick);
278                        }
279
280                        $timeDiv.css("width", (remainingTime / full) * 100 + "%");
281
282                        if (remainingTime <= 0) {
283                            instance.stop();
284
285                            //Section by webxity
286                            var differnt_limit = $("#ld_advanced_question_time_limit").val();
287                            if (differnt_limit == "yes" && quiz_question_timer_enabled) plugin.methode.nextQuestion();
288                            else {
289                                plugin.methode.finishQuiz(true);
290                            }
291
292                            $(".wp_pro_quiz_message")
293                                .html("")
294                                .css("display", "none");
295                            //End Section by webxity
296                        }
297                    }, 16);
298                };
299
300                return instance;
301            })();
302
303
304        }
305        var current_index = 0;
306        //var mySwipe = null;
307        var mySwipe = [];
308        var not_started_yet = true;
309        function myswipefunction() {
310            mySwipe = [];
311            var swipe_elements = document.getElementsByClassName(
312                "laq_advanced_swipe_questions_slides"
313            );
314            for (var i = 0; i < swipe_elements.length; i++) {
315                var swipe_element = swipe_elements[i];
316                var currid = mySwipe.length;
317                mySwipe[currid] = $.laq_slide(
318                    swipe_element,
319                    $e,
320                    plugin.methode,
321                    config
322                );
323            }
324        }
325
326        /**
327         * @memberOf reviewBox
328         */
329        const reviewBox = new (function () {
330            let $contain = [],
331                $cursor = [],
332                $list = [],
333                $items = [];
334            let x = 0,
335                offset = 0,
336                diff = 0,
337                top = 0,
338                max = 0;
339            const itemsStatus = [];
340
341            this.init = function () {
342                $contain = $e.find('.wpProQuiz_reviewQuestion');
343                $cursor = $contain.find('div');
344                $list = $contain.find('ol');
345                $items = $list.children();
346
347                if (config.mode != 2) {
348                    $(
349                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-correct'
350                    ).hide();
351                    $(
352                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-incorrect'
353                    ).hide();
354                }
355
356                this.reset();
357
358                const resume_data = learndash_prepare_quiz_resume_data(config);
359                if (config.ld_script_debug == true) {
360                    console.log('resume_data[%o]', resume_data);
361                }
362
363                if (typeof resume_data.reviewBox !== 'undefined') {
364                    jQuery(resume_data.reviewBox).each(function (idx, item) {
365                        if (typeof item === 'object') {
366                            const item_tmp = item;
367                            item = {};
368                            if (typeof item_tmp.solved !== 'undefined') {
369                                item.solved = true;
370                            }
371
372                            if (typeof item_tmp.correct !== 'undefined') {
373                                item.correct = true;
374                            }
375
376                            if (typeof item_tmp.incorrect !== 'undefined') {
377                                item.incorrect = true;
378                            }
379
380                            if (typeof item_tmp.skip !== 'undefined') {
381                                item.skip = true;
382                            }
383
384                            if (typeof item_tmp.review !== 'undefined') {
385                                item.review = true;
386                            }
387                        }
388                        itemsStatus[idx] = item;
389                        setColor(idx);
390                    });
391                }
392
393                $cursor.on('mousedown', function (e) {
394                    e.preventDefault();
395                    e.stopPropagation();
396
397                    offset = e.pageY - $cursor.offset().top + top;
398
399                    $(document).on('mouseup.scrollEvent', endScroll);
400                    $(document).on('mousemove.scrollEvent', moveScroll);
401                });
402
403                $items.on('click', function (e) {
404                    plugin.methode.showQuestion($(this).index());
405
406                    if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
407                        //Add by webxity
408                        if (globalElements.save_as_next == "yes") {
409                            var question_id = $e.find(".wpProQuiz_listItem").eq($(this).index()).data('question-meta').question_pro_id;
410                            saveQuizTrigger = "questionsNavigation";
411                            viewedQuestions.push(question_id);
412                            lastViewedQuestion = $(this).index();
413                            plugin.methode.saveQuestionClicked();
414                        }
415                        //Add by webxity end
416                    }
417                });
418
419                $e.on('questionSolved', function (e) {
420                    itemsStatus[e.values.index].solved = e.values.solved;
421                    setColor(e.values.index);
422                    updateItemsStatus();
423                });
424
425                $e.on('questionSolvedCorrect', function (e) {
426                    itemsStatus[e.values.index].correct = true;
427                    setColor(e.values.index);
428                    updateItemsStatus();
429                });
430
431                $e.on('questionSolvedIncorrect', function (e) {
432                    itemsStatus[e.values.index].incorrect = true;
433                    setColor(e.values.index);
434                    updateItemsStatus();
435                });
436
437                $e.on('changeQuestion', function (e) {
438                    // On Matrix sort questions we need to set the sort capture UL to full height.
439                    if (e.values.item[0] != 'undefined') {
440                        const questionItem = e.values.item[0];
441                        plugin.methode.setupMatrixSortHeights();
442                    }
443
444                    $items.removeClass('wpProQuiz_reviewQuestionTarget');
445                    //$items.removeClass('wpProQuiz_reviewQuestionSolved');
446                    //$items.removeClass('wpProQuiz_reviewQuestionReview');
447
448                    $items
449                        .eq(e.values.index)
450                        .addClass('wpProQuiz_reviewQuestionTarget');
451                    //updateItemsStatus();
452
453                    scroll(e.values.index);
454                });
455
456                $e.on('skipQuestion', function (e) {
457                    itemsStatus[e.values.index].skip =
458                        !itemsStatus[e.values.index].skip;
459                    setColor(e.values.index);
460                    updateItemsStatus();
461                });
462
463                $e.on('reviewQuestion', function (e) {
464                    itemsStatus[e.values.index].review =
465                        !itemsStatus[e.values.index].review;
466                    setColor(e.values.index);
467                    updateItemsStatus();
468                });
469
470                /*
471                $contain.on('mousewheel DOMMouseScroll', function(e) {
472                    e.preventDefault();
473
474                    var ev = e.originalEvent;
475                    var w = ev.wheelDelta ? -ev.wheelDelta / 120 : ev.detail / 3;
476                    var plus = 20 * w;
477
478                    var x = top - $list.offset().top  + plus;
479
480                    if(x > max)
481                        x = max;
482
483                    if(x < 0)
484                        x = 0;
485
486                    var o = x / diff;
487
488                    $list.attr('style', 'margin-top: ' + (-x) + 'px !important');
489                    $cursor.css({top: o});
490
491                    return false;
492                });
493                */
494            };
495
496            this.show = function (save) {
497                if (bitOptions.reviewQustion) {
498                    $contain.parent().show();
499                }
500
501                $e.find('.wpProQuiz_reviewDiv .wpProQuiz_button2').show();
502
503                if (save) {
504                    return;
505                }
506
507                $list.attr('style', 'margin-top: 0px !important');
508                $cursor.css({ top: 0 });
509
510                const h = $list.outerHeight();
511                const c = $contain.height();
512                x = c - $cursor.height();
513                offset = 0;
514                max = h - c;
515                diff = max / x;
516
517                //this.reset();
518
519                if (h > 100) {
520                    $cursor.show();
521                }
522
523                top = $cursor.offset().top;
524            };
525
526            this.hide = function () {
527                $contain.parent().hide();
528            };
529
530            this.toggle = function () {
531                if (bitOptions.reviewQustion) {
532                    // The toggle is called after the quiz submit. So we want to hide the 'review' and 'answered' legend items.
533                    $(
534                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-current'
535                    ).hide();
536                    $(
537                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-review'
538                    ).hide();
539                    $(
540                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-answered'
541                    ).hide();
542
543                    // And show the 'correct' and 'incorrect' indicators.
544                    $(
545                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-correct'
546                    ).show();
547                    $(
548                        '.wpProQuiz_reviewLegend li.learndash-quiz-review-legend-item-incorrect'
549                    ).show();
550
551                    $contain.parent().toggle();
552                    $items.removeClass('wpProQuiz_reviewQuestionTarget');
553                    $e.find('.wpProQuiz_reviewDiv .wpProQuiz_button2').hide();
554
555                    $list.attr('style', 'margin-top: 0px !important');
556                    $cursor.css({ top: 0 });
557
558                    const h = $list.outerHeight();
559                    const c = $contain.height();
560                    x = c - $cursor.height();
561                    offset = 0;
562                    max = h - c;
563                    diff = max / x;
564
565                    if (h > 100) {
566                        $cursor.show();
567                    }
568
569                    top = $cursor.offset().top;
570                }
571            };
572
573            this.reset = function () {
574                for (let i = 0, c = $items.length; i < c; i++) {
575                    itemsStatus[i] = {};
576                }
577
578                //$items.removeClass('wpProQuiz_reviewQuestionTarget').css('background-color', '');
579                $items.removeClass('wpProQuiz_reviewQuestionTarget');
580                $items.removeClass('wpProQuiz_reviewQuestionSolved');
581                $items.removeClass('wpProQuiz_reviewQuestionReview');
582            };
583
584            function scroll(index) {
585                /*
586                var $item = $items.eq(index);
587                var iTop = $item.offset().top;
588                var cTop = $contain.offset().top;
589                var calc = iTop - cTop;
590
591                if((calc - 4) < 0 || (calc + 32) > 100) {
592                    var x = cTop - $items.eq(0).offset().top - (cTop - $list.offset().top)  + $item.position().top;
593
594                    if(x > max)
595                        x = max;
596
597                    var o = x / diff;
598
599                    $list.attr('style', 'margin-top: ' + (-x) + 'px !important');
600                    $cursor.css({top: o});
601                }
602                */
603            }
604
605            function setColor(index) {
606                const itemStatus = itemsStatus[index];
607
608                $items
609                    .eq(index)
610                    .removeClass(
611                        'wpProQuiz_reviewQuestionSolved wpProQuiz_reviewQuestionReview wpProQuiz_reviewQuestionSkip'
612                    );
613
614                if (0 === Object.keys(itemStatus).length) {
615                    return;
616                }
617
618                let css_class = '';
619
620                if (itemStatus.correct) {
621                    css_class = 'wpProQuiz_reviewQuestionSolvedCorrect';
622                } else if (itemStatus.incorrect) {
623                    css_class = 'wpProQuiz_reviewQuestionSolvedIncorrect';
624                } else if (
625                    itemStatus.solved === true ||
626                    itemStatus.solved === false
627                ) {
628                    css_class = 'wpProQuiz_reviewQuestionSolved';
629                } else if (itemStatus.review) {
630                    css_class = 'wpProQuiz_reviewQuestionReview';
631                } else if (itemStatus.skip) {
632                    css_class = 'wpProQuiz_reviewQuestionSkip';
633                }
634
635                if (css_class != '') {
636                    $items.eq(index).addClass(css_class);
637                }
638            }
639
640            function moveScroll(e) {
641                e.preventDefault();
642
643                let o = e.pageY - offset;
644
645                if (o < 0) {
646                    o = 0;
647                }
648
649                if (o > x) {
650                    o = x;
651                }
652
653                const v = diff * o;
654
655                $list.attr('style', 'margin-top: ' + -v + 'px !important');
656
657                $cursor.css({ top: o });
658            }
659
660            function endScroll(e) {
661                e.preventDefault();
662
663                $(document).unbind('.scrollEvent');
664            }
665
666            function updateItemsStatus() {
667                plugin.methode.saveMetaDataToCookie({ reviewBox: itemsStatus });
668            }
669        })();
670
671        function QuestionTimer() {
672            let questionStartTime = 0;
673            let currentQuestionId = -1;
674            let quizStartTimer = 0;
675            let isQuizStart = false;
676            
677            this.questionStart = function (questionId) {
678                if (currentQuestionId != -1) {
679                    this.questionStop();
680                }
681                //Section by webxity
682                if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
683                    $e.find(".wpProQuiz_questionList").each(function () {
684                        var $this = $(this);
685                        var question_Id = $this.data("question_id");
686                        if (question_Id == questionId) {
687                            var tmLimit = $(this)
688                                .parent(".wpProQuiz_question")
689                                .siblings(".ld_advanced_time_limit")
690                                .val();
691                            config.timelimit = parseInt(tmLimit);
692                        }
693                    });
694                    var differnt_limit = $("#ld_advanced_question_time_limit").val();
695                    if (differnt_limit == "yes" && quiz_question_timer_enabled) {
696                        timelimit.start();
697                    }
698                    //End Section by webxity
699                }
700                
701                currentQuestionId = questionId;
702                questionStartTime = +new Date();
703            };
704            
705            this.questionStop = function () {
706                if (currentQuestionId == -1) {
707                    return;
708                }
709                
710                // MISSING CODE FROM SECOND FUNCTION - Advanced time limit stop handling:
711                if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
712                    //Section by webxity
713                    var differnt_limit = $("#ld_advanced_question_time_limit").val();
714                    if (differnt_limit == "yes" && quiz_question_timer_enabled) {
715                        timelimit.stop();
716                    }
717                    //End Section by webxity
718                }
719                
720                results[currentQuestionId].time += Math.round(
721                    (new Date() - questionStartTime) / 1000
722                );
723                currentQuestionId = -1;
724            };
725            
726            this.startQuiz = function () {
727                if (isQuizStart) {
728                    this.stopQuiz();
729                }
730
731                quizStartTimer = +new Date();
732
733                // Use server start time when quiz is resumed.
734                if (
735                    config.quiz_resume_enabled === '1' &&
736                    typeof config.quiz_resume_quiz_started === 'string'
737                ) {
738                    if ('0' !== config.quiz_resume_quiz_started) {
739                        quizStartTimer = parseInt(
740                            config.quiz_resume_quiz_started,
741                            10
742                        );
743                    }
744                }
745
746                isQuizStart = true;
747            };
748            
749            this.getQuizStart = function () {
750                if (!isQuizStart) {
751                    return;
752                }
753                return quizStartTimer;
754            };
755            
756            this.stopQuiz = function () {
757                if (!isQuizStart) {
758                    return;
759                }
760                quizEndTimer = +new Date();
761                results.comp.quizTime += Math.round(
762                    (quizEndTimer - quizStartTimer) / 1000
763                );
764                
765                // MISSING CODE FROM SECOND FUNCTION - Stop timelimit on quiz stop:
766                // timelimit.stop();
767                
768                results.comp.quizEndTimestamp = quizEndTimer;
769                results.comp.quizStartTimestamp = quizStartTimer;
770                isQuizStart = false;
771            };
772            
773            this.init = function () {};
774        }
775        
776        const questionTimer = new QuestionTimer();
777
778        var readResponses = function (name, data, $question, $questionList, lockResponse) {
779            //if (config.ld_script_debug == true) {
780            //  console.log('readResponses: name[%o], data[%o], $question[%o], $questionList[%o], lockResponse[%o]', name, data, $question, $questionList, lockResponse);
781            //}
782
783            if (lockResponse == undefined) {
784                lockResponse = true;
785            }
786            var response = {};
787            var func = {
788                singleMulti: function () {
789                    var input = $questionList.find('.wpProQuiz_questionInput');
790                    if (lockResponse == true) {
791                        $questionList.find('.wpProQuiz_questionInput').attr('disabled', 'disabled');
792                    }
793                    //$questionList.children().each(function(i) {
794                    // Changed in v2.3 from the above. children() was pickup up some other random HTML elements within the UL like <p></p>.
795                    // Now we are targetting specifically the .wpProQuiz_questionListItem HTML elements.
796                    jQuery('.wpProQuiz_questionListItem', $questionList).each(function (i) {
797                        var $item = $(this);
798                        var index = $item.attr('data-pos');
799                        if (typeof index !== 'undefined') {
800                            response[index] = input.eq(i).is(':checked');
801                        }
802                    });
803                },
804
805                sort_answer: function () {
806                    var $items = $questionList.children('li.wpProQuiz_questionListItem');
807                    var idx = 0;
808                    $items.each(function (item_idx, item) {
809                        var data_pos = jQuery(item).data('pos');
810                        if (typeof data_pos !== 'undefined') {
811                            response[idx] = data_pos;
812                            idx++;
813                        }
814                    });
815
816                    if (lockResponse == true) {
817                        $questionList.sortable("destroy");
818                    }
819                },
820
821                matrix_sort_answer: function () {
822                    var $items = $questionList.children();
823                    var matrix = new Array();
824                    statistcAnswerData = { 0: -1 };
825
826                    $items.each(function () {
827                        var $this = $(this);
828                        var id = $this.attr("data-pos");
829                        var $stringUl = $this.find(".wpProQuiz_maxtrixSortCriterion");
830                        var $stringItem = $stringUl.children();
831
832                        if ($stringItem.length)
833                            statistcAnswerData[$stringItem.attr("data-pos")] = id;
834
835                        response = statistcAnswerData;
836                    });
837                    if (lockResponse == true) {
838                        $question
839                            .find(
840                                ".wpProQuiz_sortStringList, .wpProQuiz_maxtrixSortCriterion"
841                            )
842                            .sortable("destroy");
843                    }
844                },
845
846                free_answer: function () {
847                    var $li = $questionList.children();
848                    var value = $li.find(".wpProQuiz_questionInput").val();
849                    if (lockResponse == true) {
850                        $li.find(".wpProQuiz_questionInput").attr("disabled", "disabled");
851                    }
852                    response = value;
853                },
854
855                cloze_answer: function () {
856                    response = {};
857                    $questionList.find(".wpProQuiz_cloze").each(function (i, v) {
858                        var $this = $(this);
859                        var cloze = $this.children();
860                        var input = cloze.eq(0);
861                        var span = cloze.eq(1);
862                        var inputText = plugin.methode.cleanupCurlyQuotes(input.val());
863                        response[i] = inputText;
864                        if (lockResponse == true) {
865                            input.attr("disabled", "disabled");
866                        }
867                    });
868                },
869
870                assessment_answer: function () {
871                    correct = true;
872                    var $input = $questionList.find('.wpProQuiz_questionInput');
873                    if (lockResponse == true) {
874                        $questionList.find('.wpProQuiz_questionInput').attr('disabled', 'disabled');
875                    }
876                    var val = 0;
877
878                    $input.filter(":checked").each(function () {
879                        val += parseInt($(this).val());
880                    });
881
882                    response = val;
883                },
884
885                essay: function () {
886                    var question_id = $question
887                        .find("ul.wpProQuiz_questionList")
888                        .data("question_id");
889                    if (lockResponse == true) {
890                        $questionList
891                            .find(".wpProQuiz_questionEssay")
892                            .attr("disabled", "disabled");
893                    }
894
895                    var essayText = $questionList.find(".wpProQuiz_questionEssay").val();
896                    var essayFiles = $questionList
897                        .find("#uploadEssayFile_" + question_id)
898                        .val();
899
900                    if (typeof essayText != "undefined") {
901                        response = essayText;
902                    }
903
904                    if (typeof essayFiles != "undefined") {
905                        response = essayFiles;
906                    }
907                },
908                laq_jumbled_sentence: function () {
909                    var question_id = $question
910                        .find("ul.wpProQuiz_questionList")
911                        .data("question_id");
912                    var jumbled = [];
913                    var is_added_already = [];
914
915                    $question.find(".question_options").each(function (i) {
916                        var $item = $(this);
917                        var data_id = $item.attr('id');
918
919                        if ($item.data('pts_for_each_usage') == 'no') {
920                            jumbled[jumbled.length] = {
921                                id: $item.attr("id"),
922                                name: $item.attr("name"),
923                                pts_each_usage: $item.data('pts_for_each_usage'),
924                                option: $item.val(),
925                                correct: $question
926                                    .find(".correct_options")
927                                    .eq(i)
928                                    .val(),
929                                pts: $question
930                                    .find(".correct_points")
931                                    .eq(i)
932                                    .val()
933                            };
934                        } else {
935                            if (!in_array(is_added_already, $item.attr('id'))) {
936                                is_added_already[data_id] = $item.attr('id');
937                                jumbled[jumbled.length] = {
938                                    id: $item.attr("id"),
939                                    name: $item.attr("name"),
940                                    pts_each_usage: $item.data('pts_for_each_usage'),
941                                    option: $item.val(),
942                                    correct: $question
943                                        .find(".correct_options")
944                                        .eq(i)
945                                        .val(),
946                                    pts: $question
947                                        .find(".correct_points")
948                                        .eq(i)
949                                        .val()
950                                };
951                            }
952                        }
953                    });
954                    response = jumbled;
955
956                    if (lockResponse == true) {
957                        $questionList
958                            .find(".laq_jumbled_sentence_dropdown")
959                            .attr("disabled", "disabled");
960                    }
961                },
962                laq_jumble_dnd_sentence: function () {
963                    var question_id = $question
964                        .find("ul.wpProQuiz_questionList")
965                        .data("question_id");
966                    var jumbled = [];
967                    var is_added_already = [];
968
969                    $question.find(".ldavq-jumbled-dnd-dropzone").each(function (i) {
970                        var $item = $(this);
971                        var data_id = $item.data('id');
972
973                        var ld_adv_correct = $question.find('#correct_options' + data_id).val();
974                        var ld_adv_pts = $question.find('#correct_points' + data_id).val();
975                        if ($item.data('pts_for_each_usage') == 'no') {
976                            jumbled[jumbled.length] = {
977                                id: $item.attr("id"),
978                                name: $item.attr("name"),
979                                pts_each_usage: $item.data('pts_for_each_usage'),
980                                option: $item.val(),
981                                correct: ld_adv_correct,
982                                pts: ld_adv_pts
983                            };
984                        } else {
985                            if (!in_array(is_added_already, $item.attr('id'))) {
986                                is_added_already[data_id] = $item.attr('id');
987                                jumbled[jumbled.length] = {
988                                    id: $item.attr("id"),
989                                    name: $item.attr("name"),
990                                    pts_each_usage: $item.data('pts_for_each_usage'),
991                                    option: $item.val(),
992                                    correct: ld_adv_correct,
993                                    pts: ld_adv_pts
994                                };
995                            }
996                        }
997                    });
998
999                    response = jumbled;
1000
1001                    if (lockResponse == true) {
1002                        $questionList
1003                            .find(".ldavq-jumbled-dnd-dropzone")
1004                            .attr("disabled", "disabled");
1005                    }
1006                },
1007
1008                laq_swipe_questions: function () {
1009                    var question_id = $question
1010                        .find("ul.wpProQuiz_questionList")
1011                        .data("question_id");
1012                    var swipes = [];
1013                    $question.find(".laq_advanced_swipe_selection").each(function (i) {
1014                        var $item = $(this);
1015                        swipes[swipes.length] = {
1016                            id: $item.attr("id"),
1017                            name: $item.attr("name"),
1018                            pts_each_usage: $item.data('pts_for_each_usage'),
1019                            selection: $item.val(),
1020                            attempted: $question
1021                                .find(".laq_advanced_swipe_attempted")
1022                                .eq(i)
1023                                .val(),
1024                            correct: $question
1025                                .find(".laq_advanced_swipe_correct")
1026                                .eq(i)
1027                                .val(),
1028                            pts: $question
1029                                .find(".laq_advanced_swipe_points")
1030                                .eq(i)
1031                                .val()
1032                        };
1033                    });
1034                    response = swipes;
1035                },
1036
1037                laq_calculated_formula: function () {
1038                    var question_id = $question
1039                        .find("ul.wpProQuiz_questionList")
1040                        .data("question_id");
1041
1042                    var calculations = [];
1043
1044                    $question
1045                        .find(".laq_advanced_calculated_selection")
1046                        .each(function (i) {
1047                            var $item = $(this);
1048                            var data_id = $item.attr('id');
1049                            calculations[calculations.length] = {
1050                                id: data_id,
1051                                selection: $item.val(),
1052                                correct: $question
1053                                    .find(".laq_advanced_calculated_correct")
1054                                    .eq(i)
1055                                    .val(),
1056                                variables: $question.find('.card_calculation').eq(i).data('formula_values'),
1057                                work: $question
1058                                    .find(".ld-advanced-calculated-work")
1059                                    .eq(i)
1060                                    .val(),
1061                                pts: $question
1062                                    .find(".laq_advanced_calculated_points")
1063                                    .eq(i)
1064                                    .val()
1065                            };
1066                        });
1067
1068
1069                    response = calculations;
1070                },
1071                laq_audio_questions: function () {
1072                    var question_id = $question
1073                        .find("ul.wpProQuiz_questionList")
1074                        .data("question_id");
1075                    if (lockResponse == true) {
1076                        $questionList
1077                            .find(".wpProQuiz_questionEssay")
1078                            .attr("disabled", "disabled");
1079                    }
1080                    
1081                    
1082                    var audioFiles = $("#uploadAudioFile_" + question_id).val();
1083                   
1084                    if (typeof audioFiles != "undefined") {
1085                        response = audioFiles;
1086                    }
1087                }
1088            };
1089            func[name]();
1090
1091            return { response: response };
1092        };
1093
1094        function in_array(arr, obj) {
1095            for (var i = 0; i < arr.length; i++) {
1096                if (arr[i] == obj) return true;
1097            }
1098        }
1099
1100        // Called from the Cookie handler logic. If the Quiz is loaded and a cookie is present the values of the cookie are used
1101        // to set the Quiz elements here. Once the value is set we call the trigger 'questionSolved' to update the question overview panel.
1102        function setResponse(
1103            question_data,
1104            question_value,
1105            question,
1106            $questionList,
1107            lockQuestion
1108        ) {
1109            var lockQuestion = lockQuestion || false;
1110            if (question_data.type == "single" || question_data.type == "multiple") {
1111                $questionList.children().each(function (i) {
1112                    var $item = $(this);
1113                    var index = $item.attr("data-pos");
1114
1115                    if (question_value[index] != undefined) {
1116                        var index_value = question_value[index];
1117                        if (index_value == true) {
1118                            $(".wpProQuiz_questionInput", $item).prop("checked", "checked");
1119
1120                            $e.trigger({
1121                                type: "questionSolved",
1122                                values: {
1123                                    item: question,
1124                                    index: question.index(),
1125                                    solved: true
1126                                }
1127                            });
1128                        }
1129                    }
1130                });
1131            } else if (question_data.type == "free_answer") {
1132                $questionList.children().each(function (i) {
1133                    var $item = $(this);
1134                    $(".wpProQuiz_questionInput", this).val(question_value);
1135                });
1136                $e.trigger({
1137                    type: "ques
1137tionSolved",
1138                    values: { item: question, index: question.index(), solved: true }
1139                });
1140            } else if (question_data.type == "sort_answer") {
1141                jQuery.each(question_value, function (pos, key) {
1142                    var this_li = $('li.wpProQuiz_questionListItem[data-pos="' + key + '"]', $questionList);
1143                    var this_li_inner = $('div.wpProQuiz_sortable', this_li);
1144                    var this_li_inner_value = $(this_li_inner).text();
1145
1146                    jQuery($questionList).append(this_li);
1147
1148                });
1149                $e.trigger({ type: 'questionSolved', values: { item: question, index: question.index(), solved: true } });
1150            } else if (question_data.type == "matrix_sort_answer") {
1151                jQuery.each(question_value, function (pos, key) {
1152                    var question_response_item = $(
1153                        '.wpProQuiz_matrixSortString .wpProQuiz_sortStringList li[data-pos="' +
1154                        pos +
1155                        '"]',
1156                        question
1157                    );
1158                    var question_destination_outer_li = $(
1159                        'li.wpProQuiz_questionListItem[data-pos="' +
1160                        key +
1161                        '"] ul.wpProQuiz_maxtrixSortCriterion',
1162                        $questionList
1163                    );
1164
1165                    jQuery(question_response_item).appendTo(
1166                        question_destination_outer_li
1167                    );
1168                });
1169                $e.trigger({
1170                    type: "questionSolved",
1171                    values: { item: question, index: question.index(), solved: true }
1172                });
1173            } else if (question_data.type == "cloze_answer") {
1174                // Get the input fields within the questionList parent
1175                jQuery('span.wpProQuiz_cloze input[type="text"]', $questionList).each(
1176                    function (index) {
1177                        if (typeof question_value[index] !== "undefined") {
1178                            $(this).val(question_value[index]);
1179                        }
1180                    }
1181                );
1182                $e.trigger({
1183                    type: "questionSolved",
1184                    values: { item: question, index: question.index(), solved: true }
1185                });
1186            } else if (question_data.type == "assessment_answer") {
1187                $('input.wpProQuiz_questionInput[value="' + question_value + '"]', $questionList).attr('checked', 'checked');
1188                // if (lockQuestion) {
1189                    $('.wpProQuiz_questionListItem input[type="radio"][value="' + question_value + '"]').prop('checked', true);
1190                    // navigationElementslockQuestion(question);
1191                // }
1192                $e.trigger({ type: 'questionSolved', values: { item: question, index: question.index(), solved: true } });
1193            } else if (question_data.type == "essay") {
1194                // The 'essay' value is generic. We need to figure out if this is an upload or inline essay.
1195                if (
1196                    $questionList.find('#uploadEssayFile_' + question_data.id)
1197                        .length
1198                ) {
1199                    const question_input = $questionList.find(
1200                        '#uploadEssayFile_' + question_data.id
1201                    );
1202                    $(question_input).val(question_value);
1203                    $('<p>' + basename(question_value) + '</p>').insertAfter(
1204                        question_input
1205                    );
1206                    if (lockQuestion) {
1207                        $questionList
1208                            .find('form[name="uploadEssay"]')
1209                            .css('pointer-events', 'none');
1210                        navigationElementslockQuestion(question);
1211                    }
1212                    $e.trigger({
1213                        type: 'questionSolved',
1214                        values: {
1215                            item: question,
1216                            index: question.index(),
1217                            solved: true,
1218                        },
1219                    });
1220                } else if (
1221                    $questionList.find('.wpProQuiz_questionEssay').length
1222                ) {
1223                    $questionList
1224                        .find('.wpProQuiz_questionEssay')
1225                        .text(learndash_decodeHTML(question_value));
1226                    if (lockQuestion) {
1227                        $questionList
1228                            .find('.wpProQuiz_questionEssay')
1229                            .attr('disabled', 'disabled');
1230                        navigationElementslockQuestion(question);
1231                    }
1232                    $e.trigger({
1233                        type: 'questionSolved',
1234                        values: {
1235                            item: question,
1236                            index: question.index(),
1237                            solved: true,
1238                        },
1239                    });
1240                }
1241                //Added by Webxity
1242            } else if (question_data.type == "laq_jumbled_sentence") {
1243
1244                for (var i = 0; i < question_value.length; i++) {
1245                    var record = question_value[i];
1246                    
1247                    if (record.option != null && record.option != "") {
1248                        // Set value by select name (matches your data: x, y, z)
1249                        $('ul.wpProQuiz_questionList .laq_jumbled_sentence_question select[name="' + record.name + '"]').val(record.option).change();
1250                        
1251                        // Or alternatively, set by select id (since id matches name in your HTML)
1252                        // $('#' + record.id).val(record.option).change();
1253                    }
1254                }
1255
1256                // Trigger the questionSolved event once after all values are set
1257                var hasValidOptions = question_value.some(function(item) {
1258                    return item.option != null && item.option != "";
1259                });
1260
1261                if (hasValidOptions) {
1262                    $e.trigger({
1263                        type: "questionSolved",
1264                        values: { 
1265                            item: question, 
1266                            index: question.index(), 
1267                            solved: true 
1268                        }
1269                    });
1270                }
1271            } else if (question_data.type == "laq_jumble_dnd_sentence") {
1272                // Iterate through each saved value and set the corresponding dropzone
1273                question_value.forEach(function(item, index) {
1274                    var dropzoneId = '#' + item.id;
1275                    $(dropzoneId).val(item.option);
1276                });
1277                $e.trigger({
1278                    type: "questionSolved",
1279                    values: { item: question, index: question.index(), solved: true }
1280                });
1281            } else if (question_data.type == "laq_swipe_questions") {
1282
1283
1284                if(jQuery('.ld_aq_swipe_controls').length < 1){
1285                    var swipeIndex = 0;
1286                    var swipeControls = `
1287                        <div class="ld_aq_swipe_controls">
1288                            <a href="javascript:void(0);" class="ld_aq_swipe_button ld_aq_swipe_button_restart" data-idx="${swipeIndex}">
1289                                <span class="dashicons dashicons-image-rotate"></span>
1290                            </a>
1291                        </div>
1292                    `;
1293                    $('.ld_aq_swipe_main_wrap').append(swipeControls);
1294                }
1295                var cardParents = $('.ld_aq_swipe_main_wrap .card_parent').toArray();
1296
1297                cardParents.sort((a, b) => $(b).data('id') - $(a).data('id'));
1298
1299                $(cardParents).each(function(index) {
1300                    var parent = $(this).closest('.ld_aq_swipe_main_wrap');
1301                    var match = question_value[index];
1302
1303                    if (match) {
1304                        parent.find('#laq_advanced_swipe_selection' + index).val(match.selection);
1305                        parent.find('#laq_advanced_swipe_attempted' + index).val(match.attempted);
1306
1307                        var slideCount = parseInt(parent.find('.header #laq_slides_count').text(), 10) || 0;
1308                        parent.find('.header #laq_slides_count').text(slideCount - 1);
1309
1310                        $('.laq_advanced_swipe_questions_slides_backup').append($(this));
1311                    }
1312                });
1313
1314                
1315                $e.trigger({
1316                    type: "questionSolved",
1317                    values: { item: question, index: question.index(), solved: true }
1318                });
1319            } else if (question_data.type == "laq_calculated_formula") {
1320
1321                $('.laq_advanced_calculated_selection').each(function(index,value){
1322                    $(this).val(question_value[index].selection)
1323                });
1324                $e.trigger({
1325                    type: "questionSolved",
1326                    values: { item: question, index: question.index(), solved: true }
1327                });
1328            } else if (question_data.type == "laq_audio_questions") {
1329                var $audioSource = $('#audio-source');
1330                var $audioPlayer = $('#ldavq-audio-player');
1331                var $audioDuration = $('#audio-duration');
1332
1333                if(question_value && !$audioSource.attr('src')) { // Check if audio source is already set
1334                    $audioPlayer.show();
1335                    fetch(question_value)
1336                        .then(response => response.blob())
1337                        .then(blob => {
1338                            var blobUrl = URL.createObjectURL(blob);
1339                            $audioSource.attr('src', blobUrl);
1340                            var audioElement = $audioPlayer[0];
1341                            audioElement.load();
1342                            $audioPlayer.on('loadedmetadata', function() {
1343                                var duration = $audioPlayer[0].duration;
1344                                $('#timer_num').text(formatTime(duration));
1345                            });
1346                    });
1347                }
1348
1349                if ($questionList.find("#uploadAudioFile_" + question_data.id).length) {
1350                    var question_input = $questionList.find("#uploadAudioFile_" + question_data.id);
1351                    
1352                    // Check if value is already set to prevent duplicates
1353                    if (!$(question_input).val()) {
1354                        $(question_input).val(question_value);
1355                        $("<p>" + basename(question_value) + "</p>").insertAfter(question_input);
1356                        $e.trigger({
1357                            type: "questionSolved",
1358                            values: { item: question, index: question.index(), solved: true }
1359                        });
1360                    }
1361                }
1362            } else {
1363                //console.log('unsupported type[%o]', question_data.type);
1364                //console.log('setResponse: question_data[%o] question_value[%o] question[%o], $questionList[%o]', question_data, question_value, question, $questionList);
1365            }
1366            function formatTime(seconds) {
1367                const h = Math.floor(seconds / 3600).toString().padStart(2, '0');
1368                const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0');
1369                const s = Math.floor(seconds % 60).toString().padStart(2, '0');
1370                return `${h}:${m}:${s}`;
1371            }
1372        }
1373
1374        function basename(path) {
1375            if (path != undefined) {
1376                return path.split("/").reverse()[0];
1377            }
1378            return "";
1379        }
1380
1381        var formClass = {
1382            funcs: {
1383                isEmpty(str) {
1384                    str = str.trim();
1385                    return !str || 0 === str.length;
1386                },
1387            },
1388            typeConst: {
1389                TEXT: 0,
1390                TEXTAREA: 1,
1391                NUMBER: 2,
1392                CHECKBOX: 3,
1393                EMAIL: 4,
1394                YES_NO: 5,
1395                DATE: 6,
1396                SELECT: 7,
1397                RADIO: 8,
1398            },
1399            checkForm() {
1400                let check = true;
1401                const that = this;
1402                $e.find(
1403                    '.wpProQuiz_forms input, .wpProQuiz_forms textarea, .wpProQuiz_forms .wpProQuiz_formFields, .wpProQuiz_forms select'
1404                ).each(function () {
1405                    const $this = $(this);
1406                    const isRequired = $this.data('required') == 1;
1407                    const type = $this.data('type');
1408                    let test = true;
1409                    const value = $this.val().trim();
1410
1411                    switch (type) {
1412                        case that.typeConst.TEXT:
1413                        case that.typeConst.TEXTAREA:
1414                        case that.typeConst.SELECT:
1415                            if (isRequired) {
1416                                test = !that.funcs.isEmpty(value);
1417                            }
1418
1419                            break;
1420                        case that.typeConst.NUMBER:
1421                            if (isRequired || !that.funcs.isEmpty(value)) {
1422                                test =
1423                                    !that.funcs.isEmpty(value) && !isNaN(value);
1424                            }
1425
1426                            break;
1427                        case that.typeConst.EMAIL:
1428                            if (isRequired || !that.funcs.isEmpty(value)) {
1429                                //test = !funcs.isEmpty(value) && new RegExp(/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/)
1430                                //      .test(value);
1431
1432                                // Use the same RegEx as the HTML5 email field. Per https://emailregex.com
1433                                test =
1434                                    !that.funcs.isEmpty(value) &&
1435                                    new RegExp(
1436                                        /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
1437                                    ).test(value);
1438                            }
1439
1440                            break;
1441                        case that.typeConst.CHECKBOX:
1442                            if (isRequired) {
1443                                test = $this.is(':checked');
1444                            }
1445
1446                            break;
1447                        case that.typeConst.YES_NO:
1448                        case that.typeConst.RADIO:
1449                            if (isRequired) {
1450                                test =
1451                                    $this
1452                                        .find('input[type="radio"]:checked')
1453                                        .val() !== undefined;
1454                            }
1455
1456                            break;
1457                        case that.typeConst.DATE:
1458                            var num = 0,
1459                                co = 0;
1460
1461                            $this.find('select').each(function () {
1462                                num++;
1463                                co += that.funcs.isEmpty($(this).val()) ? 0 : 1;
1464                            });
1465
1466                            if (isRequired || co > 0) {
1467                                test = num == co;
1468                            }
1469
1470                            break;
1471                    }
1472
1473                    if (test) {
1474                        $this.siblings('.wpProQuiz_invalidate').hide();
1475                    } else {
1476                        check = false;
1477                        $this.siblings('.wpProQuiz_invalidate').show();
1478                    }
1479                });
1480
1481                return check;
1482            },
1483            getFormData() {
1484                const data = {};
1485                const that = this;
1486                $e.find(
1487                    '.wpProQuiz_forms input, .wpProQuiz_forms textarea, .wpProQuiz_forms .wpProQuiz_formFields, .wpProQuiz_forms select'
1488                ).each(function () {
1489                    const $this = $(this);
1490                    const id = $this.data('form_id');
1491                    const type = $this.data('type');
1492
1493                    switch (type) {
1494                        case that.typeConst.TEXT:
1495                        case that.typeConst.TEXTAREA:
1496                        case that.typeConst.SELECT:
1497                        case that.typeConst.NUMBER:
1498                        case that.typeConst.EMAIL:
1499                            data[id] = $this.val();
1500                            break;
1501                        case that.typeConst.CHECKBOX:
1502                            data[id] = $this.is(':checked') ? 1 : 0;
1503                            break;
1504                        case that.typeConst.YES_NO:
1505                        case that.typeConst.RADIO:
1506                            data[id] = $this
1507                                .find('input[type="radio"]:checked')
1508                                .val();
1509                            break;
1510                        case that.typeConst.DATE:
1511                            data[id] = {
1512                                day: $this
1513                                    .find(
1514                                        'select[name="wpProQuiz_field_' +
1515                                            id +
1516                                            '_day"]'
1517                                    )
1518                                    .val(),
1519                                month: $this
1520                                    .find(
1521                                        'select[name="wpProQuiz_field_' +
1522                                            id +
1523                                            '_month"]'
1524                                    )
1525                                    .val(),
1526                                year: $this
1527                                    .find(
1528                                        'select[name="wpProQuiz_field_' +
1529                                            id +
1530                                            '_year"]'
1531                                    )
1532                                    .val(),
1533                            };
1534                            break;
1535                    }
1536                });
1537
1538                return data;
1539            },
1540            saveFormDataToCookie() {
1541                const formData = {};
1542                const that = this;
1543                $e.find(
1544                    '.wpProQuiz_forms input, .wpProQuiz_forms textarea, .wpProQuiz_forms .wpProQuiz_formFields, .wpProQuiz_forms select'
1545                ).each(function () {
1546                    const $this = $(this);
1547                    const id = $this.data('form_id');
1548                    // Don't save duplicated form fields.
1549                    if (typeof id === 'undefined') {
1550                        return;
1551                    }
1552                    const type = $this.data('type');
1553
1554                    formData.id = id;
1555                    switch (type) {
1556                        case that.typeConst.TEXT:
1557                        case that.typeConst.TEXTAREA:
1558                        case that.typeConst.SELECT:
1559                        case that.typeConst.NUMBER:
1560                        case that.typeConst.EMAIL:
1561                            formData.value = $this.val();
1562                            formData.type = type;
1563                            break;
1564                        case that.typeConst.CHECKBOX:
1565                            formData.value = $this.is(':checked') ? 1 : 0;
1566                            formData.type = type;
1567                            break;
1568                        case that.typeConst.YES_NO:
1569                        case that.typeConst.RADIO:
1570                            formData.value = $this
1571                                .find('input[type="radio"]:checked')
1572                                .val();
1573                            formData.type = type;
1574                            break;
1575                        case that.typeConst.DATE:
1576                            formData.value = {
1577                                day: $this
1578                                    .find(
1579                                        'select[name="wpProQuiz_field_' +
1580                                            id +
1581                                            '_day"]'
1582                                    )
1583                                    .val(),
1584                                month: $this
1585                                    .find(
1586                                        'select[name="wpProQuiz_field_' +
1587                                            id +
1588                                            '_month"]'
1589                                    )
1590                                    .val(),
1591                                year: $this
1592                                    .find(
1593                                        'select[name="wpProQuiz_field_' +
1594                                            id +
1595                                            '_year"]'
1596                                    )
1597                                    .val(),
1598                            };
1599                            formData.type = type;
1600                            break;
1601                    }
1602
1603                    plugin.methode.CookieSaveResponse(
1604                        'formData' + formData.id,
1605                        formData.id,
1606                        formData.type,
1607                        formData.value
1608                    );
1609                });
1610            },
1611            setFormDataFromServer() {
1612                if (config.quiz_resume_enabled !== '1') {
1613                    return;
1614                }
1615
1616                if (config.quiz_resume_data == undefined) {
1617                    return;
1618                }
1619
1620                const resume_data = learndash_prepare_quiz_resume_data(config);
1621                if (resume_data === false) {
1622                    return;
1623                }
1624
1625                const that = this;
1626                $e.find(
1627                    '.wpProQuiz_forms input, .wpProQuiz_forms textarea, .wpProQuiz_forms .wpProQuiz_formFields, .wpProQuiz_forms select'
1628                ).each(function () {
1629                    const $this = $(this);
1630                    const id = $this.data('form_id');
1631                    const type = $this.data('type');
1632                    const formId = 'formData' + id;
1633                    if (resume_data[formId]) {
1634                        if (resume_data[formId].type === type) {
1635                            switch (type) {
1636                                case that.typeConst.TEXT:
1637                                case that.typeConst.TEXTAREA:
1638                                case that.typeConst.SELECT:
1639                                case that.typeConst.NUMBER:
1640                                case that.typeConst.EMAIL:
1641                                    var form_value = resume_data[formId].value;
1642                                    form_value =
1643                                        learndash_decodeHTML(form_value);
1644                                    $this.val(form_value);
1645                                    break;
1646                                case that.typeConst.CHECKBOX:
1647                                    if (resume_data[formId].value) {
1648                                        $this.attr('checked', true);
1649                                    }
1650
1651                                    break;
1652                                case that.typeConst.YES_NO:
1653                                case that.typeConst.RADIO:
1654                                    if (resume_data[formId].value) {
1655                                        $this
1656                                            .find(
1657                                                'input[type="radio"][value="' +
1658                                                    resume_data[formId].value +
1659                                                    '"]'
1660                                            )
1661                                            .attr('checked', true);
1662                                    }
1663
1664                                    break;
1665                                case that.typeConst.DATE:
1666                                    $this
1667                                        .find(
1668                                            'select[name="wpProQuiz_field_' +
1669                                                id +
1670                                                '_day"]'
1671                                        )
1672                                        .val(resume_data[formId].value.day);
1673                                    $this
1674                                        .find(
1675                                            'select[name="wpProQuiz_field_' +
1676                                                id +
1677                                                '_month"]'
1678                                        )
1679                                        .val(resume_data[formId].value.month);
1680                                    $this
1681                                        .find(
1682                                            'select[name="wpProQuiz_field_' +
1683                                                id +
1684                                                '_year"]'
1685                                        )
1686                                        .val(resume_data[formId].value.year);
1687
1688                                    break;
1689                            }
1690                        }
1691                    }
1692                });
1693            },
1694        };
1695
1696        var fetchAllAnswerData = function (resultData) {
1697            $e.find(".wpProQuiz_questionList").each(function () {
1698                var $this = $(this);
1699                var questionId = $this.data("question_id");
1700                var type = $this.data("type");
1701                var data = {};
1702
1703                if (type == "single" || type == "multiple") {
1704                    $this.find(".wpProQuiz_questionListItem").each(function () {
1705                        data[$(this).attr("data-pos")] = +$(this)
1706                            .find(".wpProQuiz_questionInput")
1707                            .is(":checked");
1708                    });
1709                } else if (type == "free_answer") {
1710                    data[0] = $this.find(".wpProQuiz_questionInput").val();
1711                } else if (type == "sort_answer") {
1712                    return true;
1713                    //                  $this.find('.wpProQuiz_questionListItem').each(function() {
1714                    //                      data[$(this).index()] = $(this).attr('data-pos');
1715                    //                  });
1716                } else if (type == "matrix_sort_answer") {
1717                    return true;
1718                    //                  $this.find('.wpProQuiz_questionListItem').each(function() {
1719                    //                      data[$(this).attr('data-pos')] = $(this).find('.wpProQuiz_answerCorrect').length;
1720                    //                  });
1721                } else if (type == "cloze_answer") {
1722                    var i = 0;
1723                    $this.find(".wpProQuiz_cloze input").each(function () {
1724                        data[i++] = $(this).val();
1725                    });
1726                } else if (type == "assessment_answer") {
1727                    data[0] = '';
1728
1729                    $this.find('.wpProQuiz_questionInput:checked').each(function () {
1730                        data[$(this).data('index')] = $(this).val();
1731                    });
1732                } else if (type == "essay") {
1733                    return;
1734                } else if (type == "laq_audio_questions") {
1735                    return;
1736                } else if (type == "laq_video_questions") {
1737                    return;
1738                } else if (type == "laq_jumbled_sentence") {
1739                    var i = 0;
1740                    $(this).find('.laq_jumbled_sentence_dropdown').each(function () {
1741
1742                        var option_index = $(this).data('id');
1743
1744                        var ld_adv_q_temp_data = {};
1745
1746                        ld_adv_q_temp_data.id = $(this).attr('id');
1747                        ld_adv_q_temp_data.name = $(this).attr('name');
1748                        ld_adv_q_temp_data.pts_each_usage = $(this).data('pts_for_each_usage');
1749                        ld_adv_q_temp_data.option = $(this).val();
1750                        ld_adv_q_temp_data.correct = $(this).siblings('#correct_options' + option_index).val();
1751                        ld_adv_q_temp_data.pts = $(this).siblings('#correct_options' + option_index).next('#correct_points').val();
1752
1753                        data[i++] = ld_adv_q_temp_data;
1754                    });
1755                } else if (type == "laq_jumble_dnd_sentence") {
1756                    var i = 0;
1757                    $(this).find('.ldavq-jumbled-dnd-dropzone').each(function () {
1758
1759                        var option_index = $(this).data('id');
1760
1761                        var ld_adv_q_temp_data = {};
1762                        ld_adv_q_temp_data.id = $(this).attr('id');
1763                        ld_adv_q_temp_data.name = $(this).attr('name');
1764                        ld_adv_q_temp_data.pts_each_usage = $(this).data('pts_for_each_usage');
1765                        ld_adv_q_temp_data.option = $(this).val();
1766                        ld_adv_q_temp_data.correct = $('#laq_jumble_dnd_sentence_' + option_index).find('#correct_options' + option_index).val();
1767                        ld_adv_q_temp_data.pts = $('#laq_jumble_dnd_sentence_' + option_index).find('#correct_points' + option_index).val();
1768
1769                        data[i++] = ld_adv_q_temp_data;
1770                    });
1771                } else if (type == "laq_swipe_questions") {
1772
1773                    var parent_ele = $(this);
1774
1775                    parent_ele.find('.ld_aq_swipe_main_wrap input.laq_advanced_swipe_selection').each(function (index) {
1776                        data[index] = {};
1777
1778                        data[index].selection = $(this).val();
1779                        data[index].attempted = parent_ele.find('.ld_aq_swipe_main_wrap > input.laq_advanced_swipe_attempted:eq("' + index + '")').val();
1780                        data[index].correct = parent_ele.find('.ld_aq_swipe_main_wrap > input.laq_advanced_swipe_correct:eq("' + index + '")').val();
1781                        data[index].pts = parent_ele.find('.ld_aq_swipe_main_wrap > input.laq_advanced_swipe_points:eq("' + index + '")').val();
1782                    });
1783                } else if (type == "laq_calculated_formula") {
1784
1785                    var parent_ele = $(this);
1786
1787                    parent_ele.find('.card_calculation').each(function (index) {
1788                        data[index] = {};
1789                        data[index].id = index;
1790                        data[index].id = $(this).find('input.laq_advanced_calculated_selection').val();
1791                        data[index].selection = $(this).find('input.laq_advanced_calculated_selection').val();
1792                        data[index].correct = $(this).find('input.laq_advanced_calculated_correct').val();
1793                        data[index].pts = $(this).find('input.laq_advanced_calculated_points').val();
1794                        data[index].variables = $(this).data('formula_values');
1795                        data[index].work = $(this).parents('#laq_advanced_calculated_questions_main').find('.ld-advanced-calculated-work').val();
1796                        const values = $(this).parents('#laq_advanced_calculated_questions_main').find('.ld-advanced-calculated-work').val();
1797                        const formattedValues = values.split('\n').map(value => `<br>${value}`).join('');
1798                        data[index].work = formattedValues;
1799
1800                    });
1801                }
1802
1803                resultData[questionId]["data"] = data;
1804            });
1805        };
1806
1807
1808        plugin.methode = {
1809            /**
1810             * @memberOf plugin.methode
1811             */
1812
1813            parseBitOptions() {
1814                if (co
1814nfig.bo) {
1815                    bitOptions.randomAnswer = config.bo & (1 << 0);
1816                    bitOptions.randomQuestion = config.bo & (1 << 1);
1817                    bitOptions.disabledAnswerMark = config.bo & (1 << 2);
1818                    bitOptions.checkBeforeStart = config.bo & (1 << 3);
1819                    bitOptions.preview = config.bo & (1 << 4);
1820                    bitOptions.isAddAutomatic = config.bo & (1 << 6);
1821                    bitOptions.reviewQustion = config.bo & (1 << 7);
1822                    bitOptions.quizSummeryHide = config.bo & (1 << 8);
1823                    bitOptions.skipButton = config.bo & (1 << 9);
1824                    bitOptions.autoStart = config.bo & (1 << 10);
1825                    bitOptions.forcingQuestionSolve = config.bo & (1 << 11);
1826                    bitOptions.hideQuestionPositionOverview =
1827                        config.bo & (1 << 12);
1828                    bitOptions.formActivated = config.bo & (1 << 13);
1829                    bitOptions.maxShowQuestion = config.bo & (1 << 14);
1830                    bitOptions.sortCategories = config.bo & (1 << 15);
1831
1832                    const cors = config.bo & (1 << 5);
1833
1834                    if (
1835                        cors &&
1836                        jQuery.support != undefined &&
1837                        jQuery.support.cors != undefined &&
1838                        jQuery.support.cors == false
1839                    ) {
1840                        bitOptions.cors = cors;
1841                    }
1842                }
1843            },
1844
1845            setClozeStyle() {
1846                $e.find('.wpProQuiz_cloze input').each(function () {
1847                    const $this = $(this);
1848                    let word = '';
1849                    const wordLen = $this.data('wordlen');
1850
1851                    for (let i = 0; i < wordLen; i++) {
1852                        word += 'w';
1853                    }
1854
1855                    const clone = $(document.createElement('span'))
1856                        .css('visibility', 'hidden')
1857                        .text(word)
1858                        .appendTo($('body'));
1859
1860                    const width = clone.width();
1861
1862                    clone.remove();
1863
1864                    $this.width(width + 5);
1865                });
1866            },
1867
1868            parseTime(sec) {
1869                let seconds = parseInt(sec % 60);
1870                let minutes = parseInt((sec / 60) % 60);
1871                let hours = parseInt((sec / 3600) % 24);
1872
1873                seconds = (seconds > 9 ? '' : '0') + seconds;
1874                minutes = (minutes > 9 ? '' : '0') + minutes;
1875                hours = (hours > 9 ? '' : '0') + hours;
1876
1877                return hours + ':' + minutes + ':' + seconds;
1878            },
1879
1880            cleanupCurlyQuotes(str) {
1881                str = str.replace(/\u2018/, "'");
1882                str = str.replace(/\u2019/, "'");
1883
1884                str = str.replace(/\u201C/, '"');
1885                str = str.replace(/\u201D/, '"');
1886
1887                //return str.trim().toLowerCase();
1888
1889                // Changes in v2.5 to NOT set cloze answers to lowercase
1890                return str.trim();
1891            },
1892
1893            resetMatrix(selector) {
1894                selector.each(function () {
1895                    const $this = $(this);
1896                    const $list = $this.find('.wpProQuiz_sortStringList');
1897
1898                    $this.find('.wpProQuiz_sortStringItem').each(function () {
1899                        $list.append($(this));
1900                    });
1901                });
1902            },
1903
1904            marker(e, correct) {
1905                if (!bitOptions.disabledAnswerMark) {
1906                    if (correct === true) {
1907                        e.addClass('wpProQuiz_answerCorrect');
1908                    } else if (correct === false) {
1909                        e.addClass('wpProQuiz_answerIncorrect');
1910                    } else {
1911                        e.addClass(correct);
1912                    }
1913                }
1914            },
1915            startQuiz(loadData) {
1916                if (config.ld_script_debug == true) {
1917                    console.log('in startQuiz');
1918                }
1919
1920                if (quizStatus.loadLock) {
1921                    quizStatus.isQuizStart = 1;
1922
1923                    return;
1924                }
1925
1926                quizStatus.isQuizStart = 0;
1927
1928                if (quizStatus.isLocked) {
1929                    globalElements.quizStartPage.hide();
1930                    $e.find('.wpProQuiz_lock').show();
1931
1932                    return;
1933                }
1934
1935                if (quizStatus.isPrerequisite) {
1936                    globalElements.quizStartPage.hide();
1937                    $e.find('.wpProQuiz_prerequisite').show();
1938
1939                    return;
1940                }
1941
1942                if (quizStatus.isUserStartLocked) {
1943                    globalElements.quizStartPage.hide();
1944                    $e.find('.wpProQuiz_startOnlyRegisteredUser').show();
1945
1946                    return;
1947                }
1948
1949                if (bitOptions.maxShowQuestion && !loadData) {
1950                    if (config.formPos == formPosConst.START) {
1951                        if (!formClass.checkForm()) {
1952                            return;
1953                        }
1954                    }
1955
1956                    globalElements.quizStartPage.hide();
1957                    $e.find('.wpProQuiz_loadQuiz').show();
1958
1959                    plugin.methode.loadQuizDataAjax(true);
1960
1961                    return;
1962                }
1963
1964                if (
1965                    bitOptions.formActivated &&
1966                    config.formPos == formPosConst.START
1967                ) {
1968                    if (!formClass.checkForm()) {
1969                        return;
1970                    }
1971                }
1972
1973                plugin.methode.loadQuizData();
1974                quiz_resume_data = learndash_prepare_quiz_resume_data(config);
1975
1976                if (quiz_resume_data === false) {
1977                    quiz_resume_data = {};
1978                }
1979
1980                // Init our Cookies
1981                //if (config.quiz_resume_enabled === "1") {
1982                //  cookie_name = "ld_save_" + config.quizId + "_quiz_responses";
1983                //  plugin.methode.CookieInit();
1984                //} else if (config.timelimitcookie !== 0) {
1985                //  cookie_name = "ld_" + config.quizId + "_quiz_responses";
1986                //  plugin.methode.CookieInit();
1987                //}
1988
1989                questionTimer.startQuiz();
1990
1991                if (
1992                    bitOptions.randomQuestion &&
1993                    jQuery.isEmptyObject(quiz_resume_data) &&
1994                    !quiz_resume_data.randomQuestions
1995                ) {
1996                    plugin.methode.random(
1997                        globalElements.questionList,
1998                        'question'
1999                    );
2000                }
2001
2002                if (bitOptions.randomAnswer) {
2003                    plugin.methode.random($e.find(globalNames.questionList));
2004                }
2005
2006                if (bitOptions.sortCategories) {
2007                    plugin.methode.sortCategories();
2008                }
2009
2010                // randomize the matrix sort question items
2011                plugin.methode.random($e.find('.wpProQuiz_sortStringList'));
2012
2013                // randomize the sort question answers
2014                // MISSING CODE FROM SECOND FUNCTION - ADDING THIS LINE:
2015                plugin.methode.random($e.find('.wpProQuiz_questionList[data-type="sort_answer"]'));
2016
2017                $e.find('.wpProQuiz_listItem').each(function (i, v) {
2018                    const $this = $(this);
2019                    $this
2020                        .find('.wpProQuiz_question_page span:eq(0)')
2021                        .text(i + 1);
2022                    $this.find('> h5 span').text(i + 1);
2023
2024                    $this
2025                        .find('.wpProQuiz_questionListItem')
2026                        .each(function (i, v) {
2027                            $(this)
2028                                .find('> span:not(.wpProQuiz_cloze)')
2029                                .text(i + 1 + '. ');
2030                        });
2031                });
2032
2033                globalElements.next = $e.find(globalNames.next);
2034
2035                switch (config.mode) {
2036                    case 3:
2037                        $e.find('input[name="checkSingle"]').show();
2038                        break;
2039                    case 2:
2040                        $e.find(globalNames.check).show();
2041
2042                        if (
2043                            !bitOptions.skipButton &&
2044                            bitOptions.reviewQustion
2045                        ) {
2046                            $e.find(globalNames.skip).show();
2047                        }
2048
2049                        break;
2050                    case 1:
2051                        $e.find('input[name="back"]').slice(1).show();
2052                    case 0:
2053                        globalElements.next.show();
2054                        break;
2055                }
2056
2057                if (
2058                    bitOptions.hideQuestionPositionOverview ||
2059                    config.mode == 3
2060                ) {
2061                    $e.find('.wpProQuiz_question_page').hide();
2062                }
2063
2064                //Change last name
2065                const $lastButton = globalElements.next.last();
2066                lastButtonValue = $lastButton.val();
2067                $lastButton.val(config.lbn);
2068
2069                const $listItem = globalElements.questionList.children();
2070
2071                globalElements.listItems = $e.find('.wpProQuiz_list > li');
2072
2073                //quiz_resume_data.lastQuestion = parseInt(quiz_resume_data.lastQuestion);
2074
2075                if (
2076                    config.mode === 3 &&
2077                    'number' !== typeof quiz_resume_data.lastQuestion
2078                ) {
2079                    plugin.methode.showSinglePage(0);
2080                }
2081
2082                if ('number' !== typeof quiz_resume_data.lastQuestion) {
2083                    quiz_resume_data.lastQuestion = 0;
2084                }
2085
2086                // Original
2087                /*
2088                if ( config.mode !== 3 ) {
2089                    currentQuestion = $listItem.eq( 0 ).show();
2090                    var questionId = currentQuestion.find( globalNames.questionList ).data( 'question_id' );
2091                    questionTimer.questionStart( questionId );
2092                }
2093                */
2094
2095                if (config.mode !== 3) {
2096                    if (config.ld_script_debug == true) {
2097                        console.log(
2098                            'line 1359: quiz_resume_data.lastQuestion[%o]',
2099                            quiz_resume_data.lastQuestion
2100                        );
2101                    }
2102
2103                    if (quiz_resume_data.lastQuestion > 0) {
2104                        $listItem.each(function (q_idx, q_item) {
2105                            const q_id = $(q_item)
2106                                .find('.wpProQuiz_questionList')
2107                                .data('question_id');
2108
2109                            if (config.ld_script_debug == true) {
2110                                console.log(
2111                                    'q_id[%o] quiz_resume_data.lastQuestion[%o]',
2112                                    q_id,
2113                                    quiz_resume_data.lastQuestion
2114                                );
2115                            }
2116
2117                            if (q_id === quiz_resume_data.lastQuestion) {
2118                                currentQuestion = $listItem.eq(q_idx);
2119                                if (config.ld_script_debug == true) {
2120                                    console.log(
2121                                        'currentQuestion[%o]',
2122                                        currentQuestion
2123                                    );
2124                                    console.log('$listItem[%o]', $listItem);
2125                                }
2126
2127                                //$listItem.eq(q_idx).show();
2128                                return false;
2129                            }
2130                        });
2131                    } else {
2132                        if (config.ld_script_debug == true) {
2133                            console.log(
2134                                'line 1382: ELSE: quiz_resume_data.lastQuestion zero'
2135                            );
2136                            console.log('$listItem[%o]', $listItem);
2137                        }
2138                        currentQuestion = $listItem.eq(0);
2139
2140                        if (config.ld_script_debug == true) {
2141                            console.log('currentQuestion[%o]', currentQuestion);
2142                        }
2143
2144                        $listItem.eq(0).show();
2145                    }
2146                    
2147                    // MISSING CODE FROM SECOND FUNCTION - ADDING questionTimer.questionStart():
2148                    if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
2149                        var questionId = currentQuestion
2150                            .find(globalNames.questionList)
2151                            .data("question_id");
2152                        questionTimer.questionStart(questionId);
2153                    }
2154                } else {
2155                    if (config.ld_script_debug == true) {
2156                        console.log('line 1390: ELSE: condif.mode = 3');
2157                    }
2158                    currentQuestion = $listItem.eq(0);
2159                }
2160                if (config.ld_script_debug == true) {
2161                    console.log('after currentQuestion[%o]', currentQuestion);
2162                }
2163
2164                // MISSING CODE FROM SECOND FUNCTION - SIMPLIFIED SORTABLE HANDLING:
2165                $e.find(".wpProQuiz_sortable")
2166                    .parents("ul")
2167                    .sortable({
2168                        update: function (event, ui) {
2169                            var $p = $(this).parents(".wpProQuiz_listItem");
2170                            $e.trigger({
2171                                type: "questionSolved",
2172                                values: { item: $p, index: $p.index(), solved: true }
2173                            });
2174                        }
2175                    })
2176                    .disableSelection();
2177
2178                // Keep the existing advanced sortable handling from first function:
2179                // Backwards compatibility with templates older than 4.21.3.
2180                $e.find(
2181                    '.wpProQuiz_sortable:not(.ld-sortable__item-handle)'
2182                ).each(function (index, sortableHandle) {
2183                    const $sortable = $(sortableHandle).parents(
2184                        '.wpProQuiz_questionList'
2185                    );
2186
2187                    $sortable
2188                        .sortable({
2189                            scroll: true,
2190                            scrollSensitivity: 10 || config.scrollSensitivity,
2191                            scrollSpeed: 10 || config.scrollSpeed,
2192                            update() {
2193                                const $p = $(this).parents(
2194                                    '.wpProQuiz_listItem'
2195                                );
2196
2197                                $e.trigger({
2198                                    type: 'questionSolved',
2199                                    values: {
2200                                        item: $p,
2201                                        index: $p.index(),
2202                                        solved: true,
2203                                    },
2204                                });
2205                            },
2206                        })
2207                        .disableSelection();
2208                });
2209
2210                $e.find('.ld-sortable--sort_answer').each(function (
2211                    index,
2212                    sortable
2213                ) {
2214                    let instance = sortable?.ldSortable;
2215
2216                    if (!instance) {
2217                        instance =
2218                            learndash.forms.sortable.initSortable(sortable);
2219                    }
2220
2221                    const callback = (container, item) => {
2222                        const $p = $(container).parents('.wpProQuiz_listItem');
2223
2224                        $e.trigger({
2225                            type: 'questionSolved',
2226                            values: {
2227                                item: $p,
2228                                index: $p.index(),
2229                                solved: true,
2230                            },
2231                        });
2232                    };
2233
2234                    instance.on('dropped', callback);
2235                    instance.on('reorder', callback);
2236                });
2237
2238                $e.find(
2239                    '.wpProQuiz_sortStringList, .wpProQuiz_maxtrixSortCriterion'
2240                )
2241                    .sortable({
2242                        connectWith:
2243                            '.wpProQuiz_maxtrixSortCriterion:not(:has(li)), .wpProQuiz_sortStringList',
2244                        placeholder: 'wpProQuiz_placehold',
2245                        scroll: true,
2246                        scrollSensitivity: 10 || config.scrollSensitivity,
2247                        scrollSpeed: 10 || config.scrollSpeed,
2248                        update(event, ui) {
2249                            const $p = $(this).parents('.wpProQuiz_listItem');
2250                            $e.trigger({
2251                                type: 'questionSolved',
2252                                values: {
2253                                    item: $p,
2254                                    index: $p.index(),
2255                                    solved: true,
2256                                },
2257                            });
2258                        },
2259                    })
2260                    .disableSelection();
2261
2262                quizSolved = [];
2263
2264                if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
2265                    //section by webxity;
2266                    var differnt_limit = $("#ld_advanced_question_time_limit").val();
2267
2268                    if (differnt_limit != "yes") {
2269                        timelimit.start();
2270                    } else if (!quiz_question_timer_enabled) {
2271                        timelimit.start();
2272                    }
2273                    //End section by webxity;
2274                } else {
2275                    timelimit.start();
2276                }
2277
2278                startTime = +new Date();
2279
2280                results = {
2281                    comp: { points: 0, correctQuestions: 0, quizTime: 0 },
2282                };
2283
2284                $e.find('.wpProQuiz_questionList').each(function () {
2285                    const questionId = $(this).data('question_id');
2286
2287                    results[questionId] = { time: 0 };
2288                });
2289
2290                catResults = {};
2291
2292                $.each(options.catPoints, function (i, v) {
2293                    catResults[i] = 0;
2294                });
2295
2296                globalElements.quizStartPage.hide();
2297                $e.find('.wpProQuiz_loadQuiz').hide();
2298                globalElements.quiz.show();
2299                reviewBox.show();
2300
2301                // Force restore scroll functionality
2302                setTimeout(function() {
2303                    // Clear any conflicting events
2304                    $(document).off('mousewheel.quiz DOMMouseScroll.quiz wheel.quiz');
2305                    $(window).off('scroll.quiz');
2306                    
2307                    // Reset scroll-blocking CSS
2308                    $('body, html').css({
2309                        'overflow': 'auto',
2310                        'height': 'auto',
2311                        'touch-action': 'auto'
2312                    });
2313                    
2314                    // Clear animation queues that might interfere
2315                    $('html, body').stop(true, true);
2316                    
2317                    // Force cookie save to trigger scroll restoration
2318                    if (config.quiz_resume_enabled === '1' && Ob
2318ject.keys(cookie_value).length > 0) {
2319                        cookieSending = false; // This is what wp_pro_quiz_cookie_save_quiz sets
2320                    }
2321                }, 100);
2322
2323                // UPDATED COOKIE INITIALIZATION - SIMPLIFIED FROM SECOND FUNCTION:
2324                // Init our Cookie
2325                plugin.methode.CookieInit();
2326
2327                // Keep the existing conditional cookie initialization from first function:
2328                if (config.timelimitcookie !== 0) {
2329                    cookie_name = 'ld_' + config.quizId + '_quiz_responses';
2330                    plugin.methode.CookieInit();
2331                }
2332
2333                if (config.quiz_resume_enabled === '1') {
2334                    cookie_name =
2335                        'ld_save_' + config.quizId + '_quiz_responses';
2336                    plugin.methode.CookieInit();
2337                }
2338
2339                //$('li.wpProQuiz_listItem', globalElements.questionList).each( function (idx, questionItem) {
2340                plugin.methode.setupMatrixSortHeights();
2341                //});
2342
2343                if (config.ld_script_debug == true) {
2344                    console.log(
2345                        'currentQuestion.index [%o] currentQuestion[%o]',
2346                        currentQuestion.index(),
2347                        currentQuestion
2348                    );
2349                }
2350                if (config.mode != 3) {
2351                    $e.trigger({
2352                        type: 'changeQuestion',
2353                        values: {
2354                            item: currentQuestion,
2355                            index: currentQuestion.index(),
2356                        },
2357                    });
2358                }
2359                plugin.methode.mark_drag_fill_nav_link();
2360                plugin.methode.load_save_resume();
2361                $(".laq_advanced_swipe_attempted").val("no");
2362                myswipefunction();
2363            },
2364
2365            // viewUserQuizStatistics: function (button) {
2366            //     //console.log('in viewUserQuizStatistics');
2367
2368            //     var refId = jQuery(button).data("ref_id");
2369            //     //console.log('refId[%o]', refId);
2370            //     var quizId = jQuery(button).data("quiz_id");
2371            //     //console.log('quizId[%o]', quizId);
2372
2373            //     var post_data = {
2374            //         action: "wp_pro_quiz_admin_ajax",
2375            //         func: "statisticLoadUser",
2376            //         data: {
2377            //             quizId: quizId,
2378            //             userId: 0,
2379            //             refId: refId,
2380            //             avg: 0
2381            //         }
2382            //     };
2383
2384            //     jQuery("#wpProQuiz_user_overlay, #wpProQuiz_loadUserData").show();
2385            //     var content = jQuery("#wpProQuiz_user_content").hide();
2386
2387            //     jQuery.ajax({
2388            //         type: "POST",
2389            //         url: WpProQuizGlobal.ajaxurl,
2390            //         dataType: "json",
2391            //         cache: false,
2392            //         data: post_data,
2393            //         error: function (jqXHR, textStatus, errorThrown) { },
2394            //         success: function (reply_data) {
2395            //             if (typeof reply_data.html !== "undefined") {
2396            //                 content.html(reply_data.html);
2397            //                 jQuery("#wpProQuiz_user_content").show();
2398
2399            //                 jQuery("#wpProQuiz_loadUserData").hide();
2400
2401            //                 content.find(".statistic_data").click(function () {
2402            //                     jQuery(this)
2403            //                         .parents("tr")
2404            //                         .next()
2405            //                         .toggle("fast");
2406
2407            //                     return false;
2408            //                 });
2409            //             }
2410            //         }
2411            //     });
2412
2413            //     jQuery("#wpProQuiz_overlay_close").click(function () {
2414            //         jQuery("#wpProQuiz_user_overlay").hide();
2415            //     });
2416            // },
2417
2418            showSingleQuestion(question) {
2419                //console.log('in showSingleQuestion question[%o]', question);
2420
2421                const page = question ? Math.ceil(question / config.qp
2421p) : 1;
2422
2423                if (
2424                    config.mode === 3 &&
2425                    'number' !== typeof quiz_resume_data.lastQuestion
2426                ) {
2427                    this.showSinglePage(page);
2428                } else {
2429                    this.singlePageNavigationQuizResume(question);
2430                }
2431            },
2432            showSinglePage(page) {
2433                $listItem = globalElements.questionList.children().hide();
2434
2435                if (!config.qpp) {
2436                    $listItem.show();
2437
2438                    return;
2439                }
2440
2441                page = page ? +page : 1;
2442
2443                const maxPage = Math.ceil(
2444                    $e.find('.wpProQuiz_list > li').length / config.qpp
2445                );
2446
2447                if (page > maxPage) {
2448                    return;
2449                }
2450
2451                const pl = $e.find(globalNames.singlePageLeft).hide();
2452                const pr = $e.find(globalNames.singlePageRight).hide();
2453                const cs = $e.find('input[name="checkSingle"]').hide();
2454
2455                if (page > 1) {
2456                    pl.val(pl.data('text').replace(/%d/, page - 1)).show();
2457                }
2458
2459                if (page == maxPage) {
2460                    cs.show();
2461                } else {
2462                    pr.val(pr.data('text').replace(/%d/, page + 1)).show();
2463                }
2464
2465                currentPage = page;
2466
2467                const start = config.qpp * (page - 1);
2468
2469                $listItem.slice(start, start + config.qpp).show();
2470                //plugin.methode.scrollTo( globalElements.quizStartPage );
2471
2472                /**
2473                 * LEARNDASH-6591 On Quiz Start the scroll to the top of the page
2474                 * because the quiz element is hidden. So within the scrollTo()
2475                 * function the element position can't determined.
2476                 *
2477                 * Also changed the scroll element to the outer quiz wrapper.
2478                 */
2479                if (globalElements.self !== undefined) {
2480                    if (globalElements.self.is(':hidden')) {
2481                        globalElements.self.show();
2482                    }
2483                    plugin.methode.scrollTo(globalElements.self);
2484                }
2485            },
2486
2487            nextQuestion() {
2488                if (
2489                    config.timelimitcookie !== 0 ||
2490                    config.quiz_resume_enabled === '1'
2491                ) {
2492                    if (
2493                        currentQuestion
2494                            .find(globalNames.next)
2495                            .data('question-lock') === true
2496                    ) {
2497                        plugin.methode.CookieProcessQuestionResponse(
2498                            currentQuestion,
2499                            true
2500                        );
2501                    } else {
2502                        plugin.methode.CookieProcessQuestionResponse(
2503                            currentQuestion
2504                        );
2505                    }
2506                }
2507
2508                if (config.quiz_resume_enabled === '1') {
2509                    // current Question (before pressing Next)
2510                    plugin.methode.saveMetaDataToCookie({
2511                        lastQuestion: jQuery(currentQuestion[0]).data(
2512                            'question-meta'
2513                        ).question_pro_id,
2514                    });
2515
2516                    // next Question
2517                    const nextQuestion = jQuery(currentQuestion.next()[0]);
2518                    if (
2519                        typeof nextQuestion.data('question-meta') !==
2520                        'undefined'
2521                    ) {
2522                        plugin.methode.saveMetaDataToCookie({
2523                            nextQuestion:
2524                                nextQuestion.data('question-meta')
2525                                    .question_pro_id,
2526                        });
2527                    }
2528                }
2529
2530                jQuery('.mejs-pause').trigger('click');
2531                this.showQuestionObject(currentQuestion.next());
2532            },
2533
2534            prevQuestion() {
2535                this.showQuestionObject(currentQuestion.prev());
2536                plugin.methode.mark_drag_fill_nav_link();
2537                plugin.methode.load_save_resume();
2538            },
2539
2540            showQuestion(index) {
2541                const $element = globalElements.listItems.eq(index);
2542
2543                if (config.mode == 3 || inViewQuestions) {
2544                    if (config.qpp) {
2545                        plugin.methode.showSingleQuestion(index + 1);
2546                    }
2547                    plugin.methode.scrollTo($element, 1);
2548                    questionTimer.startQuiz();
2549                    return;
2550                }
2551
2552                this.showQuestionObject($element);
2553            },
2554
2555            showQuestionObject(obj) {
2556                if (config.ld_script_debug == true) {
2557                    //console.trace();
2558                    console.log('showQuestionObject: obj[%o]', obj);
2559                }
2560
2561                // We hide the current question IF it is set.
2562                if (
2563                    typeof currentQuestion !== 'undefined' &&
2564                    currentQuestion.length > 0
2565                ) {
2566                    globalElements.questionList.children().each(function () {
2567                        if (
2568                            $(this).data('question-meta').question_pro_id !==
2569                            currentQuestion.data('question-meta')
2570                                .question_pro_id
2571                        ) {
2572                            $(this).hide();
2573                        }
2574                    });
2575                }
2576
2577                if (
2578                    !obj.length &&
2579                    bitOptions.forcingQuestionSolve &&
2580                    bitOptions.quizSummeryHide &&
2581                    bitOptions.reviewQustion
2582                ) {
2583                    // First get all the questions...
2584                    list = globalElements.questionList.children();
2585
2586                    if (list != null) {
2587                        list.each(function () {
2588                            const $this = $(this);
2589                            const $questionList = $this.find(
2590                                globalNames.questionList
2591                            );
2592                            const question_id =
2593                                $questionList.data('question_id');
2594                            const data =
2595                                config.json[$questionList.data('question_id')];
2596
2597                            // Within the following logic. If the question type is 'sort_answer' there is a chance
2598                            // the sortable answers will be displayed in the correct order. In that case the user will click
2599                            // the next button.
2600                            // The trigger to set the question was answered is normally a function of the sort/drag action
2601                            // by the user. So we need to set the question answered flag in the case the Quiz summary is enabled.
2602                            //if (data.type == 'sort_answer') {
2603                            //  $e.trigger({type: 'questionSolved', values: {item: $this, index: $this.index(), solved: true}});
2604                            //}
2605                        });
2606                    }
2607
2608                    for (
2609                        let i = 0, c = $e.find('.wpProQuiz_listItem').length;
2610                        i < c;
2611                        i++
2612                    ) {
2613                        if (!quizSolved[i]) {
2614                            alert(WpProQuizGlobal.questionsNotSolved);
2615                            return false;
2616                        }
2617                    }
2618                }
2619
2620                //globalElements.questionList.children().hide();
2621                currentQuestion.hide();
2622
2623                currentQuestion = obj.show();
2624
2625                plugin.methode.scrollTo(globalElements.quiz);
2626
2627                $e.trigger({
2628                    type: 'changeQuestion',
2629                    values: {
2630                        item: currentQuestion,
2631                        index: currentQuestion.index(),
2632                    },
2633                });
2634
2635                if (!currentQuestion.length) {
2636                    plugin.methode.showQuizSummary();
2637                } else {
2638                    const questionId = currentQuestion
2639                        .find(globalNames.questionList)
2640                        .data('question_id');
2641                    questionTimer.questionStart(questionId);
2642                }
2643            },
2644
2645            skipQuestion() {
2646                $e.trigger({
2647                    type: 'skipQuestion',
2648                    values: {
2649                        item: currentQuestion,
2650                        index: currentQuestion.index(),
2651                    },
2652                });
2653                plugin.methode.nextQuestion();
2654            },
2655            reviewQuestion() {
2656                $e.trigger({
2657                    type: 'reviewQuestion',
2658                    values: {
2659                        item: currentQuestion,
2660                        index: currentQuestion.index(),
2661                    },
2662                });
2663            },
2664
2665            uploadFile: function (event) {
2666                var question_id = event.currentTarget.id.replace('uploadEssaySubmit_', '');
2667                var file = $('#uploadEssay_' + question_id)[0].files[0];
2668
2669                if (typeof file !== 'undefined') {
2670                    var nonce = $('#_uploadEssay_nonce_' + question_id).val();
2671                    var uploadEssaySubmit = $('#uploadEssaySubmit_' + question_id);
2672
2673                    var uploadEssayMessage = $('#uploadEssayMessage_' + question_id);
2674                    uploadEssayMessage.removeClass('uploadEssayMessage_fail');
2675                    uploadEssayMessage.removeClass('uploadEssayMessage_success');
2676                    uploadEssayMessage.html(config.essayUploading);
2677
2678                    var data = new FormData();
2679                    data.append('action', 'learndash_upload_essay');
2680                    data.append('nonce', nonce);
2681                    data.append('question_id', question_id);
2682                    data.append('course_id', config.course_id);
2683                    data.append('essayUpload', file);
2684
2685                    $.ajax({
2686                        method: 'POST',
2687                        type: 'POST',
2688                        url: WpProQuizGlobal.ajaxurl,
2689                        data: data,
2690                        cache: false,
2691                        contentType: false,
2692                        processData: false,
2693                        success: function (response) {
2694                            // Update the response message. Then later apply the class for the color.
2695                            if (typeof response.data.message !== 'undefined') {
2696                                uploadEssayMessage.html(response.data.message);
2697                            }
2698
2699                            if (response.success == true && typeof response.data.filelink !== 'undefined') {
2700                                uploadEssayMessage.addClass('uploadEssayMessage_success');
2701                                $('#uploadEssayFile_' + question_id).val(response.data.filelink);
2702
2703                                // disable the upload button. Only one file per quiz.
2704                                uploadEssaySubmit.attr('disabled', 'disabled');
2705
2706                                var $item = $('#uploadEssayFile_' + question_id).parents('.wpProQuiz_listItem');
2707                                $e.trigger({ type: 'questionSolved', values: { item: $item, index: $item.index(), solved: true } });
2708                            } else {
2709                                uploadEssayMessage.addClass('uploadEssayMessage_fail');
2710                                uploadEssaySubmit.removeAttr('disabled');
2711                            }
2712                        },
2713                    });
2714                }
2715                event.preventDefault();
2716            },
2717
2718            uploadAudio: function (event) {
2719                
2720                var question_id = event.currentTarget.id.replace('ldavq_submitBtn_', '');
2721                // var question = question.split('_');
2722                // var question_id = question[1];
2723                var nonce = $('#_uploadAudio_nonce_' + question_id).val();
2724                var uploadEssayMessage = $('#uploadAudioMessage_' + question_id);
2725                uploadEssayMessage.removeClass('uploadEssayMessage_fail');
2726                uploadEssayMessage.removeClass('uploadEssayMessage_success');
2727                uploadEssayMessage.html(config.essayUploading);
2728
2729                var form_ = document.getElementById('uploadfile_form');
2730                var data = new FormData(form_);
2731                
2732                data.set("uploadfiles[]", blobAudio, 'recording_audio.mp3');
2733                data.append('action', 'learndash_upload_audio');
2734                data.append('ldavq-audio-player', blobAudio);
2735                data.append('nonce', nonce);
2736                data.append('question_id', question_id);
2737                data.append('course_id', config.course_id);
2738                
2739                $.ajax({
2740                    method: 'POST',
2741                    type: 'POST',
2742                    url: ajax_app.url,
2743                    data: data,
2744                    cache: false,
2745                    contentType: false,
2746                    processData: false,
2747                    success: function (response) {
2748                        
2749                        if (response.success == true && typeof response.data.filelink !== 'undefined') {
2750                            uploadEssayMessage.addClass('uploadEssayMessage_success').html(response.data.message);
2751                            $('#uploadAudioFile_' + question_id).val(response.data.filelink).data('file', response.data);
2752                            var $item = $('#uploadAudioFile_' + question_id).parents('.wpProQuiz_listItem');
2753                            $e.trigger({ type: 'questionSolved', values: { item: $item, index: $item.index(), solved: true } });
2754                        } else {
2755                            uploadEssayMessage.addClass('uploadEssayMessage_fail').html(response.data.message);
2756                        }
2757                    },
2758                    error: function (error) {
2759                        console.error(error);
2760                    }
2761                });
2762                event.preventDefault();
2763            },
2764
2765            showQuizSummary() {
2766                questionTimer.questionStop();
2767                questionTimer.stopQuiz();
2768                cookieSending = true;
2769
2770                if (bitOptions.quizSummeryHide || !bitOptions.reviewQustion) {
2771                    if (
2772                        bitOptions.formActivated &&
2773                        config.formPos == formPosConst.END
2774                    ) {
2775                        reviewBox.hide();
2776                        globalElements.quiz.hide();
2777                        plugin.methode.scrollTo(
2778                            $e.find('.wpProQuiz_infopage').show()
2779                        );
2780                    } else {
2781                        plugin.methode.finishQuiz();
2782                    }
2783
2784                    return;
2785                }
2786
2787                const quizSummary = $e.find('.wpProQuiz_checkPage');
2788
2789                // Clone the Review questions and legand and add to the
2790                //$e.find('.wpProQuiz_checkPage .wpProQuiz_reviewSummary').html('');
2791                $e.find('.wpProQuiz_checkPage .wpProQuiz_reviewSummary').append(
2792                    $e
2793                        .find('.wpProQuiz_reviewDiv .wpProQuiz_reviewQuestion')
2794                        .clone()
2795                );
2796
2797                $e.find('.wpProQuiz_checkPage .wpProQuiz_reviewSummary').append(
2798                    $e
2799                        .find('.wpProQuiz_reviewDiv .wpProQuiz_reviewLegend')
2800                        .clone()
2801                );
2802
2803                $e.find(
2804                    '.wpProQuiz_checkPage .wpProQuiz_reviewSummary .wpProQuiz_reviewQuestion li'
2805                ).removeClass('wpProQuiz_reviewQuestionTarget');
2806
2807                $e.find(
2808                    '.wpProQuiz_checkPage .wpProQuiz_reviewSummary .wpProQuiz_reviewQuestion li'
2809                ).on('click', function (event) {
2810                    $e.find(
2811                        '.wpProQuiz_checkPage .wpProQuiz_reviewSummary'
2812                    ).html('');
2813
2814                    quizSummary.hide();
2815                    globalElements.quiz.show();
2816                    reviewBox.show(true);
2817
2818                    const index = $(this).index();
2819                    plugin.methode.showQuestion(index);
2820                });
2821
2822                let cSolved = 0;
2823
2824                for (let i = 0, c = quizSolved.length; i < c; i++) {
2825                    if (quizSolved[i]) {
2826                        cSolved++;
2827                    }
2828                }
2829
2830                quizSummary.find('span:eq(0)').text(cSolved);
2831
2832                reviewBox.hide();
2833                globalElements.quiz.hide();
2834
2835                quizSummary.show();
2836
2837                plugin.methode.scrollTo(quizSummary);
2838            },
2839
2840
2841            finishQuiz: function (timeover) {
2842                // LEARNDASH-4412 : Disable final buttons on submit.
2843                globalElements.next.last().attr('disabled', 'disabled');
2844                $e.find('input[name="checkSingle"]').attr('disabled', 'disabled');
2845
2846                questionTimer.questionStop();
2847                questionTimer.stopQuiz();
2848                timelimit.stop();
2849
2850                var time = (+new Date() - startTime) / 1000;
2851                time =
2852                    config.timelimit && time > config.timelimit ? config.timelimit : time;
2853                timespent = time;
2854                $e.find(".wpProQuiz_quiz_time span").text(
2855                    plugin.methode.parseTime(time)
2856                );
2857
2858                if (timeover) {
2859                    globalElements.results.find(".wpProQuiz_time_limit_expired").show();
2860                }
2861
2862                plugin.methode.checkQuestion(
2863                    globalElements.questionList.children(),
2864                    true
2865                );
2866            },
2867
2868            finishQuizEnd: function () {
2869                if (config.mode == "2") {
2870                    results.comp.points = 0;
2871                    results.comp.correctQuestions = 0;
2872                    config.globalPoints = 0;
2873                    $.each(results, function (question_id, result) {
2874                        if (question_id != "comp") {
2875                            results.comp.points =
2876                                results.comp.points + parseInt(result.points);
2877                            if (result.correct == 1 || result.correct == "1") {
2878                                results.comp.correctQuestions += 1;
2879                            }
2880
2881                            config.globalPoints =
2882                                config.globalPoints + parseInt(result.possiblePoints);
2883                        }
2884                    });
2885                }
2886
2887                $e.find(".wpProQuiz_correct_answer").text(
2888                    results.comp.correctQuestions
2889                );
2890
2891                results.comp.result =
2892                    Math.round((results.comp.points / config.globalPoints) * 100 * 100) /
2893                    100;
2894
2895                var hasNotGradedQuestion = false;
2896                $.each(results, function () {
2897                    if (
2898                        typeof this.graded_status !== "undefined" &&
2899                        this.graded_status == "not_graded"
2900                    ) {
2901                        hasNotGradedQuestion = true;
2902                    }
2903                });
2904
2905                if (typeof certificate_details !== 'undefined' && certificate_details.certificateLink != undefined && certificate_details.certificateLink != '') {
2906                    var certificateContainer = $e.find('.wpProQuiz_certificate');
2907                    if (results.comp.result >= certificate_details.certificate_threshold * 100) {
2908                        //if (true == hasNotGradedQuestion && typeof certificate_pending !== 'undefined') {
2909                        //  certificateContainer.append('<br />'+certificate_pending );
2910                        //}
2911                        certificateContainer.show();
2912                    } else if (true == hasNotGradedQuestion && typeof certificate_pending !== 'undefined') {
2913                        certificateContainer.html(certificate_pending);
2914                        certificateContainer.show();
2915                    }
2916                }
2917
2918                var quiz_continue_link = $e.find('.quiz_continue_link');
2919
2920                var show_quiz_continue_buttom_on_fail = false;
2921                if (jQuery(quiz_continue_link).hasClass('show_quiz_continue_buttom_on_fail')) {
2922                    show_quiz_continue_buttom_on_fail = true;
2923                }
2924
2925                if ((typeof options.passingpercentage !== 'undefined') && (parseFloat(options.passingpercentage) >= 0.0)) {
2926                    if ((results.comp.result >= options.passingpercentage) || (show_quiz_continue_buttom_on_fail)) {
2927                        $e.addClass('ld-quiz-result').addClass('ld-quiz-result-passed');
2928                        $e.removeClass('ld-quiz-result-failed');
2929
2930                        $e.trigger({ type: 'learndash-quiz-finished', values: { status: 'passed', item: $e, results: results } });
2931                        $e.trigger({ type: 'learndash-quiz-finished-passed', values: { status: 'passed', item: $e, results: results } });
2932
2933                        //For now, Just append the HTML to the page
2934                        if (typeof continue_details !== 'undefined') {
2935                            $e.find('.quiz_continue_link').html(continue_details);
2936                            $e.find('.quiz_continue_link').show();
2937                        }
2938                    } else {
2939                        $e.removeClass('ld-quiz-result-passed');
2940                        $e.addClass('ld-quiz-result').addClass('ld-quiz-result-failed');
2941
2942                        $e.trigger({ type: 'learndash-quiz-finished', values: { status: 'failed', item: $e, results: results } });
2943                        $e.trigger({ type: 'learndash-quiz-finished-failed', values: { status: 'failed', item: $e, results: results } });
2944
2945                        $e.find('.quiz_continue_link').hide();
2946                    }
2947                } else if (typeof continue_details !== 'undefined') {
2948                    $e.find('.quiz_continue_link').html(continue_details);
2949                    $e.find('.quiz_continue_link').show();
2950                }
2951
2952                $pointFields = $e.find(".wpProQuiz_points span");
2953                $gradedPointsFields = $e.find(".wpProQuiz_graded_points span");
2954
2955                $pointFields.eq(0).text(results.comp.points);
2956                $pointFields.eq(1).text(config.globalPoints);
2957                $pointFields.eq(2).text(results.comp.result + "%");
2958
2959                $gradedQuestionCount = 0;
2960                $gradedQuestionPoints = 0;
2961
2962                $.each(results, function (question_id, result) {
2963                    if ($.isNumeric(question_id) && result.graded_id) {
2964                        var possible = result.possiblePoints - result.points;
2965                        if (possible > 0) {
2966                            $gradedQuestionPoints += possible;
2967                            $gradedQuestionCount++;
2968                        }
2969                    }
2970                });
2971
2972                if ($gradedQuestionCount > 0) {
2973                    $(".wpProQuiz_points").hide();
2974                    $(".wpProQuiz_graded_points").show();
2975                    $gradedPointsFields.eq(0).text(results.comp.points);
2976                    $gradedPointsFields.eq(1).text(config.globalPoints);
2977                    $gradedPointsFields.eq(2).text(results.comp.result + "%");
2978                    $gradedPointsFields.eq(3).text($gradedQuestionCount);
2979                    $gradedPointsFields.eq(4).text($gradedQuestionPoints);
2980                }
2981
2982                $e.find(".wpProQuiz_resultsList > li")
2983                    .eq(plugin.methode.findResultIndex(results.comp.result))
2984                    .show();
2985
2986                plugin.methode.setAverageResult(results.comp.result, false);
2987
2988                this.setCategoryOverview();
2989
2990                plugin.methode.sendCompletedQuiz();
2991
2992                if (bitOptions.isAddAutomatic && toplistData.isUser) {
2993                    plugin.methode.addToplist();
2994                }
2995
2996                reviewBox.hide();
2997
2998                $e.find(".wpProQuiz_checkPage, .wpProQuiz_infopage").hide();
2999                globalElements.quiz.hide();
3000            },
3001
3002            sending: function (start, end, step_size) {
3003                globalElements.sending.show();
3004                var sending_progress_bar = globalElements.sending.find(
3005                    ".sending_progress_bar"
3006                );
3007                var i;
3008                if (typeof start == undefined || start == null) {
3009                    i =
3010                        parseInt(
3011                            (sending_progress_bar.width() * 100) /
3012                            sending_progress_bar.offsetParent().width()
3013                        ) + 156;
3014                } else i = start;
3015
3016                if (end == undefined) var end = 80;
3017
3018                if (step_size == undefined) step_size = 1;
3019
3020                if (sending_timer != null && typeof sending_timer != undefined) {
3021                    clearInterval(sending_timer);
3022                }
3023                sending_timer = setInterval(function () {
3024                    var currentWidth = parseInt(sending_progress_bar.width() * 100 / sending_progress_bar.offsetParent().width());
3025                    if (currentWidth >= end) {
3026                        clearInterval(sending_timer);
3027                        if (currentWidth >= 100) {
3028                            setTimeout(plugin.methode.showResults(), 2000);
3029                        }
3030                    }
3031                    sending_progress_bar.css('width', i + '%');
3032                    i = i + step_size;
3033                }, 300);
3034            },
3035
3036            showResults: function () {
3037                globalElements.sending.hide();
3038                globalElements.results.show();
3039                $('.audio-container').hide();
3040                plugin.methode.scrollTo(globalElements.results);
3041            },
3042
3043            setCategoryOverview: function () {
3044                results.comp.cats = {};
3045                $e.find(".wpProQuiz_catOverview li").each(function () {
3046                    var $this = $(this);
3047                    var catId = $this.data("category_id");
3048                    if (config.catPoints[catId] === undefined) {
3049                        $this.hide();
3050                        return true;
3051                    }
3052
3053                    var r =
3054                        Math.round(
3055                            (catResults[catId] / config.catPoints[catId]) * 100 * 100
3056                        ) / 100;
3057
3058                    results.comp.cats[catId] = r;
3059
3060                    $this.find(".wpProQuiz_catPercent").text(r + "%");
3061
3062                    $this.show();
3063                });
3064            },
3065
3066            questionSolved: function (e) {
3067                //if (config.ld_script_debug == true) {
3068                //  console.log('questionSolved: e.values[%o]', e.values);
3069                //}
3070                if (typeof e.values.item.data('question-meta') != 'undefined') {
3071                    var question_id = e.values.item.data('question-meta').question_pro_id;
3072
3073                    viewedQuestions.push(question_id);
3074                }
3075                lastViewedQuestion = e.values.index;
3076                saveQuizTrigger = 'button';
3077                quizSolved[e.values.index] = e.values.solved;
3078            },
3079            sendCompletedQuiz: function () {
3080                if (bitOptions.preview) return;
3081                fetchAllAnswerData(results);
3082                var formData = formClass.getFormData();
3083                $.each(results, function (question_id, result) {
3084                    if (results[question_id].data == null) {
3085                        results[question_id].data = [];
3086                    }
3087                });
3088                
3089                jQuery.ajax({
3090                    type: 'POST',
3091                    url: WpProQuizGlobal.ajaxurl,
3092                    dataType: "json",
3093                    cache: false,
3094                    data: { 
3095                        action: "wp_pro_quiz_completed_quiz",
3096                        course_id: config.course_id,
3097                        lesson_id: config.lesson_id,
3098                        topic_id: config.topic_id,
3099                        quiz: config.quiz,
3100                        quizId: config.quizId,
3101                        results: JSON.stringify(results),
3102                        res2: JSON.stringify(results),
3103                        timespent: timespent,
3104                        forms: formData,
3105                        quiz_nonce: config.quiz_nonce
3106                    },
3107                    success: function (json) {
3108                        if (json != null) {
3109                            if (typeof config['quizId'] !== 'undefined') {
3110                                var quiz_pro_id = parseInt(config['quizId']);
3111                                if ((typeof json[quiz_pro_id] !== 'undefined') && (typeof json[quiz_pro_id]['quiz_result_settings'] !== 'undefined')) {
3112                                    result_settings = json[quiz_pro_id]['quiz_result_settings'];
3113                                    plugin.methode.afterSendUpdateIU(result_settings);
3114                                }
3115                            }
3116                        }
3117                        plugin.methode.sending(null, 100, 15); //Complete the remaining progress bar faster and show results
3118
3119                        //code by webxity
3120                        // console.log('hello');console.log(json);
3121                        if (
3122                            typeof json.total_quiz_correct !== "undefined" &&
3123                            typeof json.total_quiz_questions !== "undefined"
3124                        ) {
3125                            $e.find(".wpProQuiz_correct_answer").text(
3126                                json.total_quiz_correct
3127                            );
3128                            $e.find(".wpProQuiz_correct_answer")
3129                                .next("span")
3130                                .text(json.total_quiz_questions);
3131
3132                            $pointFields = $e.find(".wpProQuiz_points span");
3133
3134                            $pointFields.eq(0).text(json.points);
3135                            $pointFields.eq(1).text(json.globalPoints);
3136                            $pointFields.eq(2).text(json.result + "%");
3137                        }
3138
3139                        if (retake_quiz_enabled === '1') {
3140                            plugin.methode.setRetakeResult(results, timespent, formData);
3141                        }
3142                        //code by webxity end
3143
3144                        // Clear Cookie on restart
3145                        plugin.methode.CookieDelete();
3146                    }
3147                });
3148            },
3149
3150            setRetakeResult: function (results, timespent, formData) {
3151                jQuery.ajax({
3152                    type: 'POST',
3153                    url: WpProQuizGlobal.ajaxurl,
3154                    dataType: "json",
3155                    cache: false,
3156                    data: {
3157                        action: 'ld_rq_set_retake_result',
3158                        course_id: config.course_id,
3159                        lesson_id: config.lesson_id,
3160                        topic_id: config.topic_id,
3161                        quiz: config.quiz,
3162                        quizId: config.quizId,
3163                        results: JSON.stringify(results),
3164                        timespent: timespent,
3165                        forms: formData,
3166                        quiz_nonce: config.quiz_nonce,
3167                    },
3168                    success: function (json) {
3169                        if ((typeof json.total_quiz_correct !== 'undefined') && (typeof json.total_quiz_questions !== 'undefined')) {
3170
3171                            $e.find('.wpProQuiz_correct_answer').text(json.total_quiz_correct);
3172                            $e.find('.wpProQuiz_correct_answer').next('span').text(json.total_quiz_questions);
3173
3174                            $pointFields = $e.find('.wpProQuiz_points span');
3175
3176                            $pointFields.eq(0).text(json.points);
3177                            $pointFields.eq(1).text(json.globalPoints);
3178                            $pointFields.eq(2).text(json.result + '%');
3179                        }
3180                    }
3181                });
3182            },
3183
3184            afterSendUpdateIU: function (quiz_result_settings) {
3185
3186                if (typeof quiz_result_settings["showAverageResult"] !== "undefined") {
3187                    if (!quiz_result_settings["showAverageResult"]) {
3188                        $e.find(".wpProQuiz_resultTable").remove();
3189                    }
3190                }
3191
3192                if (typeof quiz_result_settings["showCategoryScore"] !== "undefined") {
3193                    if (!quiz_result_settings["showCategoryScore"]) {
3194                        $e.find(".wpProQuiz_catOverview").remove();
3195                    }
3196                }
3197
3198                if (
3199                    typeof quiz_result_settings["showRestartQuizButton"] !== "undefined"
3200                ) {
3201                    if (!quiz_result_settings["showRestartQuizButton"]) {
3202                        $e.find('input[name="restartQuiz"]').remove();
3203                    }
3204                }
3205
3206                if (typeof quiz_result_settings["showResultPoints"] !== "undefined") {
3207                    if (!quiz_result_settings["showResultPoints"]) {
3208                        $e.find(".wpProQuiz_points").remove();
3209                    }
3210                }
3211
3212                if (typeof quiz_result_settings["showResultQuizTime"] !== "undefined") {
3213                    if (!quiz_result_settings["showResultQuizTime"]) {
3214                        $e.find(".wpProQuiz_quiz_time").remove();
3215                    }
3216                }
3217
3218                if (
3219                    typeof quiz_result_settings["showViewQuestionButton"] !== "undefined"
3220                ) {
3221                    if (!quiz_result_settings["showViewQuestionButton"]) {
3222                        $e.find('input[name="reShowQuestion"]').remove();
3223                    }
3224                }
3225
3226                if (typeof quiz_result_settings["showContinueButton"] !== "undefined") {
3227                    if (!quiz_result_settings["showContinueButton"]) {
3228                        $e.find(".quiz_continue_link").remove();
3229                    }
3230                }
3231            },
3232            findResultIndex: function (p) {
3233                var r = config.resultsGrade;
3234                var index = -1;
3235                var diff = 999999;
3236
3237                for (var i = 0; i < r.length; i++) {
3238                    var v = r[i];
3239
3240                    if (p >= v && p - v < diff) {
3241                        diff = p - v;
3242                        index = i;
3243                    }
3244                }
3245
3246                return index;
3247            },
3248
3249            showQustionList: function () {
3250                inViewQuestions = !inViewQuestions;
3251                globalElements.toplistShowInButton.hide();
3252                globalElements.quiz.toggle();
3253                $e.find('.wpProQuiz_QuestionButton').hide();
3254                globalElements.questionList.children().show();
3255                reviewBox.toggle();
3256
3257                //Added by Webxity
3258                $e.find(".ld_advance_quiz_resume").hide();
3259                $e.find(".ld_advance_quiz_save").hide();
3260                $(".laq_advanced_swipe_questions_slides_wrapper").css(
3261                    "display",
3262                    "none"
3263                );
3264                $(".laq_total_slides_wrap").css("display", "none");
3265                $(".laq_swipe_buttons_wrap").css("display", "none");
3266
3267                $(".swipe_question_note").css("display", "none");
3268                $(".laq_advanced_swipe_questions_slides_backup").css(
3269                    "display",
3270                    "block"
3271                );
3272                $(".laq_advanced_swipe_questions_slides_backup .card_parent").each(
3273                    function (index) {
3274                        var parent_node = $(this)
3275                            .parent()
3276                            .parent();
3277                        var idex = $(this).data("id");
3278                        idex = parseInt(idex) - 1;
3279                        var correct = parent_node
3280                            .find("#laq_advanced_swipe_correct" + idex)
3281                            .val();
3282                        var selection = parent_node
3283                            .find("#laq_advanced_swipe_selection" + idex)
3284                            .val();
3285                        var attempted = parent_node
3286                            .find("#laq_advanced_swipe_attempted" + idex)
3287                            .val();
3288                        if (attempted == "yes") {
3289                            if (correct == selection) {
3290                                $(this)
3291                                    .addClass("wpProQuiz_answerCorrect")
3292                                    .css("margin", "5px");
3293                            } else {
3294                                $(this)
3295                                    .addClass("wpProQuiz_answerIncorrect")
3296                                    .css("margin", "5px");
3297                            }
3298                        }
3299                    }
3300                );
3301                $(".card_calculation").each(function (index) {
3302                    var correct = $(this)
3303                        .find("#laq_advanced_calculated_correct")
3304                        .val();
3305                    var selection = $(this)
3306                        .find("#laq_advanced_calculated_selection")
3307                        .val();
3308                    if (correct == selection) {
3309                        $(this)
3310                            .addClass("wpProQuiz_answerCorrect")
3311                            .css("margin", "5px");
3312                    } else {
3313                        $(this)
3314                            .addClass("wpProQuiz_answerIncorrect")
3315                            .css("margin", "5px");
3316                    }
3317                });
3318                $(".laq_jumbled_sentence_question select").each(function (index) {
3319                    var parent_node = $(this).parents(".laq_jumbled_sentence_question");
3320                    var idx = $(this).data("id");
3321                    var correct = parent_node.find("#correct_options" + idx).val();
3322
3323                    var selection = $(this).val().trim();
3324                    var correct_array = correct.trim().split('|');
3325
3326                    if ($.inArray(selection, correct_array) >= 0) {
3327                        $(this).addClass("wpProQuiz_answerCorrect")
3328                            .css("margin", "5px");
3329                    } else {
3330                        $(this)
3331                            .addClass("wpProQuiz_answerIncorrect")
3332                            .css("margin", "5px");
3333                    }
3334                });
3335                $(".ldavq-jumbled-dnd-dropzone").each(function (index) {
3336                    var parent_node = $(this).parents(".laq_jumble_dnd_sentence_question");
3337                    var idx = $(this).data("id");
3338                    var correct = parent_node.find("#correct_options" + idx).val();
3339                    var selection = $(this).val();
3340
3341                    if (correct.replace(/[^a-zA-Z0-9]/g, '') == selection.replace(/[^a-zA-Z0-9]/g, '')) {
3342                        $(this)
3343                            .addClass("wpProQuiz_answerCorrect")
3344                            .css("margin", "5px");
3345                    } else {
3346                        $(this)
3347                            .addClass("wpProQuiz_answerIncorrect")
3348                            .css("margin", "5px");
3349                    }
3350                });
3351                //End Added by Webxity
3352
3353                $e.find(".wpProQuiz_question_page").hide();
3354            },
3355
3356            random: function (group) {
3357                group.each(function () {
3358                    var e = $(this)
3359                        .children()
3360                        .get()
3361                        .sort(function () {
3362                            return Math.round(Math.random()) - 0.5;
3363                        });
3364                    if (e) {
3365                        if (e[0]) {
3366                            $(e).appendTo(e[0].parentNode);
3367                        }
3368                    }
3369                });
3370            },
3371
3372            sortCategories: function () {
3373                var e = $(".wpProQuiz_list")
3374                    .children()
3375                    .get()
3376                    .sort(function (a, b) {
3377                        var aQuestionId = $(a)
3378                            .find(".wpProQuiz_questionList")
3379                            .data("question_id");
3380                        var bQuestionId = $(b)
3381                            .find(".wpProQuiz_questionList")
3382                            .data("question_id");
3383
3384                        return (
3385                            config.json[aQuestionId].catId - config.json[bQuestionId].catId
3386                        );
3387                    });
3388
3389                if (e) {
3390                    if (e[0]) {
3391                        $(e).appendTo(e[0].parentNode);
3392                    }
3393                }
3394            },
3395
3396            restartQuiz: function () {
3397                globalElements.results.hide();
3398                //globalElements.quizStartPage.show();
3399                globalElements.questionList.children().hide();
3400                globalElements.toplistShowInButton.hide();
3401                reviewBox.hide();
3402
3403                $e.find('.wpProQuiz_questionInput, .wpProQuiz_cloze input').removeAttr('disabled').removeAttr('checked')
3404                    .css('background-color', '');
3405
3406                // Reset all the question types to empty values. This really should be moved into a reset function to be called at other times like at Quiz Init.
3407                //              $e.find('.wpProQuiz_cloze input').val('');
3408                $e.find('.wpProQuiz_questionListItem input[type="text"]').val('');
3409
3410                $e.find('.wpProQuiz_answerCorrect, .wpProQuiz_answerIncorrect').removeClass('wpProQuiz_answerCorrect wpProQuiz_answerIncorrect');
3411
3412                $e.find('.wpProQuiz_listItem').data('check', false);
3413                $e.find('textarea.wpProQuiz_questionEssay').val('');
3414                $e.find('input.uploadEssayFile').val('');
3415                $e.find('input.uploadAudioFile').val('');
3416                $e.find('input.wpProQuiz_upload_essay').val('');
3417
3418                $e.find('.wpProQuiz_response').hide().children().hide();
3419
3420                plugin.methode.resetMatrix($e.find('.wpProQuiz_listItem'));
3421
3422                $e.find('.wpProQuiz_sortStringItem, .wpProQuiz_sortable').removeAttr('style');
3423
3424                $e.find('.wpProQuiz_clozeCorrect, .wpProQuiz_QuestionButton, .wpProQuiz_resultsList > li').hide();
3425
3426                $e.find('.wpProQuiz_question_page, input[name="tip"]').show();
3427
3428                $e.find('.wpProQuiz_certificate').attr('style', 'display: none !important');
3429
3430                globalElements.results.find('.wpProQuiz_time_limit_expired').hide();
3431
3432                globalElements.next.last().val(lastButtonValue);
3433
3434                inViewQuestions = false;
3435
3436                // Clear Cookie on restart
3437                //plugin.methode.CookieDelete();
3438
3439                plugin.methode.load_save_resume();
3440            },
3441            showSpinner: function () {
3442                $e.find(".wpProQuiz_spinner").show();
3443            },
3444            hideSpinner: function () {
3445                $e.find(".wpProQuiz_spinner").hide();
3446            },
3447            checkQuestion: function (list, endCheck) {
3448                var finishQuiz = list == undefined ? false : true;
3449                var responses = {};
3450                var r = {};
3451
3452                if (list == undefined && config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3453                    return;
3454                }
3455
3456                list = list == undefined ? currentQuestion : list;
3457
3458                list.each(function () {
3459                    var $this = $(this);
3460                    var question_index = $this.index();
3461                    var $questionList = $this.find(globalNames.questionList);
3462                    var question_id = $questionList.data("question_id");
3463                    var data = config.json[$questionList.data("question_id")];
3464                    var name = data.type;
3465                    var resumedQuestion = resumedQuestions[question_id];
3466
3467                    if (config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3468
3469                        if (!checkedQuestions.includes(question_id)) {
3470                            return true;
3471                        } else if (data.type == 'laq_swipe_questions') {
3472                            let is_attempted = false;
3473
3474                            $.each(resumedQuestion.response, function (index, response) {
3475                                if (response.attempted == 'yes') {
3476                                    is_attempted = true;
3477                                    return;
3478                                }
3479                            });
3480
3481                            if (!is_attempted) {
3482                                return true;
3483                            }
3484                        } else if (data.type == 'laq_calculated_formula') {
3485                            return true;
3486                        }
3487                    }
3488
3489                    questionTimer.questionStop();
3490
3491                    if ($this.data("check")) {
3492                        return true;
3493                    }
3494
3495                    if (data.type == "single" || data.type == "multiple") {
3496                        name = "singleMulti";
3497                    }
3498                    //if (config.ld_script_debug == true) {
3499                    //  console.log('checkQuestion: calling readResponses');
3500                    //}
3501
3502                    responses[question_id] = readResponses(
3503                        name,
3504                        data,
3505                        $this,
3506                        $questionList,
3507                        true
3508                    );
3509                    responses[question_id]["question_pro_id"] = data["id"];
3510                    responses[question_id]["question_post_id"] = data["question_post_id"];
3511
3512                    plugin.methode.CookieSaveResponse(
3513                        question_id,
3514                        question_index,
3515                        data.type,
3516                        responses[question_id]
3517                    );
3518                });
3519
3520
3521                config.checkAnswers = {
3522                    list: list,
3523                    responses: responses,
3524                    endCheck: endCheck,
3525                    finishQuiz: finishQuiz
3526                };
3527
3528                if (config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3529                    finishQuiz = false;
3530                }
3531
3532                if (finishQuiz) {
3533                    plugin.methode.sending(1, 80, 3);
3534                } else {
3535                    plugin.methode.showSpinner();
3536                }
3537
3538                plugin.methode.ajax(
3539                    {
3540                        action: "ld_advance_adv_quiz_pro_ajax", //changed for advance addon
3541                        func: "checkAnswers",
3542                        data: {
3543                            quizId: config.quizId,
3544                            quiz: config.quiz,
3545                            course_id: config.course_id,
3546                            quiz_nonce: config.quiz_nonce,
3547                            responses: JSON.stringify(responses)
3548                        }
3549                    },
3550                    function (json) {
3551                        plugin.methode.hideSpinner();
3552                        var list = config.checkAnswers.list;
3553
3554                        var responses = config.checkAnswers.responses;
3555                        var r = config.checkAnswers.r;
3556                        var endCheck = config.checkAnswers.endCheck;
3557                        var finishQuiz = config.checkAnswers.finishQuiz;
3558
3559                        if (config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3560                            finishQuiz = false;
3561                        }
3562
3563                        list.each(function () {
3564                            var $this = $(this);
3565                            var $questionList = $this.find(globalNames.questionList);
3566                            var question_id = $questionList.data("question_id");
3567                            //var data = {id: question_id};
3568
3569                            if (config.mode == 2) {
3570                                if (is_quiz_resume_in_process == 'yes') {
3571                                    if (!checkedQuestions.includes(question_id)) {
3572                                        return true;
3573                                    }
3574                                } else {
3575                                    if (!checkedQuestions.includes(question_id)) {
3576                                        checkedQuestions.push(question_id);
3577                                    }
3578                                }
3579                            }
3580
3581                            if ($this.data("check")) {
3582                                return true;
3583                            }
3584
3585                            if (typeof json[question_id] !== "undefined") {
3586                                var result = json[question_id];
3587
3588                                data = config.json[$questionList.data("question_id")];
3589
3590                                $this.find(".wpProQuiz_response").show();
3591                                $this.find(globalNames.check).hide();
3592                                $this.find(globalNames.skip).hide();
3593                                $this.find(globalNames.next).show();
3594
3595                                results[data.id].points = result.p;
3596                                if (typeof result.p_nonce !== "undefined")
3597                                    results[data.id].p_nonce = result.p_nonce;
3598                                else results[data.id].p_nonce = "";
3599
3600                                results[data.id].correct = Number(result.c);
3601                                results[data.id].data = result.s;
3602                                if (typeof result.a_nonce !== "undefined")
3603                                    results[data.id].a_nonce = result.a_nonce;
3604                                else results[data.id].a_nonce = "";
3605                                results[data.id].possiblePoints = result.e.possiblePoints;
3606
3607                                // If the sort_answer or matrix_sort_answer question type is not 100% correct then the returned
3608                                // result.s object will be empty. So in order to pass the user's answers to the server for the
3609                                // sendCompletedQuiz AJAX call we need to grab the result.e.r object and store into results.
3610                                if (jQuery.isEmptyObject(results[data.id].data)) {
3611                                    if (
3612                                        result.e.type != undefined &&
3613                                        (result.e.type == "sort_answer" ||
3614                                            result.e.type == "matrix_sort_answer")
3615                                    ) {
3616                                        results[data.id].data = result.e.r;
3617                                    }
3618                                }
3619
3620                                if (
3621                                    typeof result.e.graded_id !== "undefined" &&
3622                                    result.e.graded_id > 0
3623                                ) {
3624                                    results[data.id].graded_id = result.e.graded_id;
3625                                }
3626
3627                                if (typeof result.e.graded_status !== "undefined") {
3628                                    results[data.id].graded_status = result.e.graded_status;
3629                                }
3630
3631                                results["comp"].points += result.p;
3632
3633                                $this.find(".wpProQuiz_response").show();
3634                                $this.find(globalNames.check).hide();
3635                                $this.find(globalNames.skip).hide();
3636                                $this.find(globalNames.next).show();
3637
3638                                //results[data.id].points = result.p;
3639                                //results[data.id].correct = Number(result.c);
3640                                //results[data.id].data = result.s;
3641
3642                                // If the sort_answer or matrix_sort_answer question type is not 100% correct then the returned
3643                                // result.s object will be empty. So in order to pass the user's answers to the server for the
3644                                // sendCompletedQuiz AJAX call we need to grab the result.e.r object and store into results.
3645                                if (jQuery.isEmptyObject(results[data.id].data)) {
3646                                    if (typeof result.e.type !== "undefined") {
3647                                        if (
3648                                            result.e.type == "sort_answer" ||
3649                                            result.e.type == "matrix_sort_answer"
3650                                        ) {
3651                                            if (typeof result.e.r !== "undefined") {
3652                                                results[data.id].data = result.e.r;
3653                                            }
3654                                        }
3655
3656                                        if (result.e.type == 'essay') {
3657                                            if (typeof result.e.graded_id !== 'undefined') {
3658                                                results[data.id].data = { graded_id: result.e.graded_id };
3659                                            }
3660                                        }
3661
3662                                        if (result.e.type == 'laq_audio_questions') {
3663                                            if (typeof result.e.graded_id !== 'undefined') {
3664                                                results[data.id].data = { graded_id: result.e.graded_id };
3665                                            }
3666                                        }
3667
3668
3669                                    }
3670                                }
3671
3672                                catResults[data.catId] += result.p;
3673
3674                                //Marker
3675                                plugin.methode.markCorrectIncorrect(result, $this, $questionList);
3676
3677                                if (result.c) {
3678                                    if (typeof result.e.AnswerMessage !== "undefined") {
3679                                        $this
3680                                            .find(".wpProQuiz_correct")
3681                                            .find(".wpProQuiz_AnswerMessage")
3682                                            .html(result.e.AnswerMessage);
3683                                        $this
3684                                            .find(".wpProQuiz_correct")
3685                                            .trigger("learndash-quiz-answer-response-contentchanged");
3686                                    }
3687                                    $e.trigger({ type: 'questionSolvedCorrect', values: { item: $this, index: $this.index(), solved: true, result: result } });
3688
3689                                    $this.find(".wpProQuiz_correct").show();
3690                                    results["comp"].correctQuestions += 1;
3691                                } else {
3692                                    if (typeof result.e.AnswerMessage !== "undefined") {
3693                                        $this.find('.wpProQuiz_incorrect').find('.wpProQuiz_AnswerMessage').html(result.e.AnswerMessage);
3694                                        $this.find('.wpProQuiz_incorrect').trigger('learndash-quiz-answer-response-contentchanged');
3695                                    }
3696                                    $e.trigger({ type: 'questionSolvedIncorrect', values: { item: $this, index: $this.index(), solved: true, result: result } });
3697
3698                                    $this.find('.wpProQuiz_incorrect').show();
3699                                }
3700
3701                                $this.find(".wpProQuiz_responsePoints").text(result.p);
3702
3703                                $this.data("check", true);
3704
3705                                if (!endCheck)
3706                                    $e.trigger({
3707                                        type: "questionSolved",
3708                                        values: { item: $this, index: $this.index(), solved: true }
3709                                    });
3710                            }
3711                        });
3712
3713                        //Added by abbas
3714                        results["comp"].points = 0;
3715                        results["comp"].result = 0;
3716                        results["comp"].correctQuestions = 0;
3717                        //config.globalPoints = json.globalPoints;possiblePoints
3718                        $possiblePoints = 0;
3719                        $.each(json, function (question_id, result) {
3720
3721                            if (checkedQuestions.includes(question_id) && config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3722                                return true;
3723                            }
3724
3725                            if (results[question_id] == null) {
3726                                results[question_id] = {};
3727                            }
3728                            if (results["comp"] == null) {
3729                                results["comp"] = {};
3730                            }
3731
3732                            results[question_id].points = result.p;
3733                            if (typeof result.p_nonce !== "undefined")
3734                                results[question_id].p_nonce = result.p_nonce;
3735                            else results[question_id].p_nonce = "";
3736
3737                            results[question_id].correct = Number(result.c);
3738                            results[question_id].data = result.s;
3739                            if (typeof result.a_nonce !== "undefined")
3740                                results[question_id].a_nonce = result.a_nonce;
3741                            else results[question_id].a_nonce = "";
3742                            results[question_id].possiblePoints = result.e.possiblePoints;
3743                            $possiblePoints += result.e.possiblePoints;
3744
3745                            if (jQuery.isEmptyObject(results[question_id].data)) {
3746                                if (
3747                                    result.e.type != undefined &&
3748                                    (result.e.type == "sort_answer" ||
3749                                        result.e.type == "matrix_sort_answer")
3750                                ) {
3751                                    results[question_id].data = result.e.r;
3752                                }
3753                            }
3754
3755                            if (
3756                                typeof result.e.graded_id !== "undefined" &&
3757                                result.e.graded_id > 0
3758                            ) {
3759                                results[question_id].graded_id = result.e.graded_id;
3760                            }
3761
3762                            if (typeof result.e.graded_status !== "undefined") {
3763                                results[question_id].graded_status = result.e.graded_status;
3764                            }
3765
3766                            if (result.c || result.apa || is_negative_marking_enabled) {
3767                                results["comp"].points += result.p;
3768                            }
3769
3770                            if (result.c && result.o == "no") {
3771                                results["comp"].correctQuestions += 1;
3772                            }
3773
3774                            if (jQuery.isEmptyObject(results[question_id].data)) {
3775                                if (typeof result.e.type !== "undefined") {
3776                                    if (
3777                                        result.e.type == "sort_answer" ||
3778                                        result.e.type == "matrix_sort_answer"
3779                                    ) {
3780                                        if (typeof result.e.r !== "undefined") {
3781                                            results[question_id].data = result.e.r;
3782                                        }
3783                                    }
3784
3785                                    if (result.e.type == "essay") {
3786                                        if (typeof result.e.graded_id !== "undefined") {
3787                                            results[question_id].data = {
3788                                                graded_id: result.e.graded_id
3789                                            };
3790                                        }
3791                                    }
3792
3793                                    if (result.e.type == "laq_audio_questions") {
3794                                        if (typeof result.e.graded_id !== "undefined") {
3795                                            results[question_id].data = {
3796                                                graded_id: result.e.graded_id
3797                                            };
3798                                        }
3799                                    }
3800
3801                                    if (result.e.type == "laq_swipe_questions") {
3802                                        if (typeof result.e.r !== "undefined") {
3803                                            // results[question_id] = {
3804
3805                                            // }
3806                                        }
3807                                    }
3808                                }
3809                            }
3810                        });
3811
3812                        if (config.mode != 2) {
3813                            config.globalPoints = $possiblePoints;
3814                        }
3815                        //Added by abbas
3816                        // Set a default just in case.
3817                        //results.comp.p_nonce = '';
3818
3819                        //if ( typeof json['comp'] !== 'undefined' ) {
3820                        //  if ( ( typeof json['comp']['p'] !== 'undefined' ) && ( typeof json['comp']['p_nonce'] !== 'undefined' ) ) {
3821                        //      results.comp.points = json['comp']['p'];
3822                        //      results.comp.p_nonce = json['comp']['p_nonce'];
3823                        //  }
3824                        //}
3825
3826                        if (config.mode == 2 && is_quiz_resume_in_process == 'yes') {
3827                            is_quiz_resume_in_process = "no";
3828                        }
3829
3830                        if (finishQuiz) plugin.methode.finishQuizEnd();
3831
3832                    }
3833                );
3834            },
3835
3836            markCorrectIncorrect: function (result, $question, $questionList) {
3837                if (typeof result.e.c == "undefined") return;
3838
3839                switch (result.e.type) {
3840                    case "single":
3841                    case "multiple":
3842                        $questionList.children().each(function (i) {
3843                            var $item = $(this);
3844                            var index = $item.attr("data-pos");
3845                            //                  var checked = input.eq(i).is(':checked');
3846
3847                            if (result.e.c[index]) {
3848                                var checked = $("input.wpProQuiz_questionInput", $item).is(
3849                                    ":checked"
3850                                );
3851                                if (checked) {
3852                                    plugin.methode.marker($item, true);
3853                                } else {
3854                                    plugin.methode.marker(
3855                                        $item,
3856                                        "wpProQuiz_answerCorrectIncomplete"
3857                                    );
3858                                }
3859                            } else {
3860                                if (!result.c && result.e.r[index])
3861                                    plugin.methode.marker($item, false);
3862                            }
3863                        });
3864                        break;
3865                    case "free_answer":
3866                        var $li = $questionList.children();
3867                        if (result.c) plugin.methode.marker($li, true);
3868                        else plugin.methode.marker($li, false);
3869                        break;
3870
3871                    case "cloze_answer":
3872                        $questionList.find(".wpProQuiz_cloze").each(function (i, v) {
3873                            var $this = $(this);
3874                            var cloze = $this.children();
3875                            var input = cloze.eq(0);
3876                            var span = cloze.eq(1);
3877                            var inputText = plugin.methode.cleanupCurlyQuotes(input.val());
3878
3879                            if (result.s[i]) {
3880                                //input.css('background-color', '#B0DAB0');
3881                                input.addClass('wpProQuiz_answerCorrect');
3882                            } else {
3883                                input.addClass('wpProQuiz_answerIncorrect');
3884                                //input.css('background-color', '#FFBABA');
3885
3886                                if (typeof result.e.c[i] != "undefined") {
3887                                    span.html("(" + result.e.c[i].join() + ")");
3888                                    span.show();
3889                                }
3890                            }
3891                            input.attr("disabled", "disabled");
3892                        });
3893                        break;
3894                    case 'sort_answer':
3895                        var $items = $questionList.children('li.wpProQuiz_questionListItem');
3896
3897                        $items.each(function (i, v) {
3898                            var $this = $(this);
3899
3900                            if (result.e.c[i] == $this.attr("data-pos")) {
3901                                plugin.methode.marker($this, true);
3902                            } else {
3903                                plugin.methode.marker($this, false);
3904                            }
3905                        });
3906
3907                        $items.children().css({ "box-shadow": "0 0", cursor: "auto" });
3908
3909                        //                      $questionList.sortable("destroy");
3910
3911                        var index = new Array();
3912                        jQuery.each(result.e.c, function (i, v) {
3913                            index[v] = i;
3914                        });
3915                        $items.sort(function (a, b) {
3916                            return index[$(a).attr("data-pos")] > index[$(b).attr("data-pos")]
3917                                ? 1
3918                                : -1;
3919                        });
3920
3921                        $questionList.append($items);
3922                        break;
3923                    case "laq_jumbled_sentence":
3924                        $questionList
3925                            .find(".laq_jumbled_sentence_dropdown")
3926                            .each(function (index) {
3927                                var correct = $questionList
3928                                    .find(".laq_jumbled_sentence_correct")
3929                                    .eq(index)
3930                                    .val().trim();
3931                                var curr_val = ($(this).val() || '').trim();
3932                                var correct_array = correct.trim().split('|');
3933
3934                                $questionList
3935                                    .find(".laq_jumbled_sentence_correct_ans")
3936                                    .eq(index)
3937                                    .html(
3938                                        "<span " +
3939                                        ($.inArray(curr_val.trim(), correct_array) >= 0 ? 'style="display: none;"' : "") +
3940                                        ' class="wpProQuiz_clozeCorrect" style="color:green">(' +
3941                                        correct +
3942                                        ")</span>"
3943                                    );
3944                                if ($.inArray(curr_val.trim(), correct_array) >= 0) {
3945                                    $(this).addClass("wpProQuiz_answerCorrect");
3946                                } else {
3947                                    $(this).addClass("wpProQuiz_answerIncorrect");
3948                                }
3949                            });
3950
3951                        break;
3952                    case "laq_jumble_dnd_sentence":
3953                        $questionList
3954                            .find(".ldavq-jumbled-dnd-dropzone")
3955                            .each(function (index) {
3956                                var data_id = $(this).data('id');
3957                                var correct = $questionList.find("#correct_options" + data_id).val().trim();
3958
3959                                var curr_val = $(this).val().trim();
3960                                $questionList
3961                                    .find("#laq_jumble_dnd_sentence_correct_ans" + data_id)
3962                                    .html(
3963                                        "<span " +
3964                                        (correct == curr_val ? 'style="display: none;"' : "") +
3965                                        ' class="wpProQuiz_clozeCorrect" style="color:green">(' +
3966                                        correct +
3967                                        ")</span>"
3968                                    );
3969                                if (correct.replace(/[^a-zA-Z0-9]/g, '') == curr_val.replace(/[^a-zA-Z0-9]/g, '')) {
3970                                    $(this).addClass("wpProQuiz_answerCorrect");
3971                                } else {
3972                                    $(this).addClass("wpProQuiz_answerIncorrect");
3973                                }
3974                            });
3975
3976                        break;
3977                    case "laq_swipe_questions":
3978                        $questionList
3979                            .find(".laq_advanced_swipe_questions_slides_wrapper")
3980                            .css("display", "none");
3981
3982                        $questionList.find(".swipe_question_note").css("display", "none");
3983
3984                        $questionList
3985                            .find(".laq_advanced_swipe_questions_slides_backup")
3986                            .css("display", "block");
3987
3988                        $questionList
3989                            .find(".laq_advanced_swipe_questions_slides_backup .card_parent")
3990                            .each(function (index) {
3991
3992                                var parent_node = $(this).parent().parent();
3993
3994                                var id = parseInt($(this).data("id")) - 1;
3995
3996                                var correct = parent_node.find("#laq_advanced_swipe_correct" + id).val();
3997                                var selection = parent_node.find("#laq_advanced_swipe_selection" + id).val();
3998                                var attempted = parent_node.find("#laq_advanced_swipe_attempted" + id).val();
3999
4000                                if (attempted == "yes") {
4001                                    if (correct == selection) {
4002                                        $(this)
4003                                            .addClass("wpProQuiz_answerCorrect")
4004                                            .css("margin", "5px");
4005                                    } else {
4006                                        $(this)
4007                                            .addClass("wpProQuiz_answerIncorrect")
4008                                            .css("margin", "5px");
4009                                    }
4010                                }
4011                            });
4012
4013                        $('.laq_advanced_swipe_questions_slides_backup').parent().show();
4014                        $('.ld_aq_swipe_main_wrap > div.header').hide();
4015                        $('.ld_aq_swipe_controls').hide();
4016
4017                        break;
4018                    case "laq_calculated_formula":
4019                        $questionList.find(".card_calculation").each(function (index) {
4020                            var correct = $(this)
4021                                .find("#laq_advanced_calculated_correct")
4022                                .val();
4023                            var selection = $(this)
4024                                .find("#laq_advanced_calculated_selection")
4025                                .val();
4026
4027                            if (correct == selection) {
4028                                $(this)
4029                                    .find("#laq_advanced_calculated_selection")
4030                                    .addClass("wpProQuiz_answerCorrect");
4031                                $(this).parent().parent()
4032                                    .find(".ld-advance-calculated-right-col")
4033                                    .addClass("wpProQuiz_answerCorrect");
4034
4035                            } else {
4036                                $(this)
4037                                    .find("#laq_advanced_calculated_selection")
4038                                    .addClass("wpProQuiz_answerIncorrect");
4039                                $(this).parent().parent()
4040                                    .find(".ld-advance-calculated-right-col")
4041                                    .addClass("wpProQuiz_answerIncorrect").attr('disabled', 'disabled');
4042                            }
4043                            $(this)
4044                                .find("#laq_advanced_calculated_selection")
4045                                .parent()
4046                                .append(
4047                                    '<span class="wpProQuiz_clozeCorrect" style="color:green">(' +
4048                                    correct +
4049                                    ")</span>"
4050                                );
4051                            $(this)
4052                                .find("#laq_advanced_calculated_selection").attr('disabled', 'disabled');
4053                            $(this).parent().parent().find(".ld-advanced-calculated-work").attr('disabled', 'disabled');
4054                        });
4055                        break;
4056                    case "matrix_sort_answer":
4057                        var $items = $questionList.children();
4058                        var matrix = new Array();
4059                        statistcAnswerData = { 0: -1 };
4060
4061                        $items.each(function () {
4062                            var $this = $(this);
4063                            var id = $this.attr("data-pos");
4064                            var $stringUl = $this.find(".wpProQuiz_maxtrixSortCriterion");
4065                            var $stringItem = $stringUl.children();
4066                            var i = $stringItem.attr("data-pos");
4067
4068                            if (
4069                                $stringItem.length &&
4070                                result.e.c[i] == $this.attr("data-pos")
4071                            ) {
4072                                plugin.methode.marker($this, true);
4073                            } else {
4074                                plugin.methode.marker($this, false);
4075                            }
4076
4077                            matrix[i] = $stringUl;
4078                        });
4079
4080                        plugin.methode.resetMatrix($question);
4081
4082                        $question
4083                            .find(".wpProQuiz_sortStringItem")
4084                            .each(function () {
4085                                var x = matrix[$(this).attr("data-pos")];
4086                                if (x != undefined) x.append(this);
4087                            })
4088                            .css({ "box-shadow": "0 0", cursor: "auto" });
4089
4090                        //  $question.find('.wpProQuiz_sortStringList, .wpProQuiz_maxtrixSortCriterion').sortable("destroy");
4091                        break;
4092                }
4093            },
4094
4095            setCheckedStatusFromData: function (data, question, list) {
4096                var dataObjects = [quiz_resume_data, cookie_value];
4097                jQuery(dataObjects).each(function (index, dataObject) {
4098                    if (dataObject.hasOwnProperty('checked' + data.id)) {
4099                        for (var element in dataObject) {
4100                            if (element.startsWith('checked')) {
4101                                var elementId = element.replace('checked', '');
4102                                if (elementId == data.id) {
4103                                    questionResult = dataObject[element];
4104                                    plugin.methode.markCorrectIncorrect(questionResult, question, list);
4105
4106                                    if (questionResult.c) {
4107                                        if (typeof questionResult.e.AnswerMessage !== 'undefined') {
4108                                            question.find('.wpProQuiz_correct').find('.wpProQuiz_AnswerMessage').html(questionResult.e.AnswerMessage);
4109                                            question.find('.wpProQuiz_correct').trigger('learndash-quiz-answer-response-contentchanged');
4110                                        }
4111
4112                                        question.find('.wpProQuiz_response').show();
4113                                        question.find('.wpProQuiz_correct').show();
4114                                    } else {
4115                                        if (typeof questionResult.e.AnswerMessage !== 'undefined') {
4116                                            question.find('.wpProQuiz_incorrect').find('.wpProQuiz_AnswerMessage').html(questionResult.e.AnswerMessage);
4117                                            question.find('.wpProQuiz_incorrect').trigger('learndash-quiz-answer-response-contentchanged');
4118                                        }
4119
4120                                        question.find('.wpProQuiz_response').show();
4121                                        question.find('.wpProQuiz_incorrect').show();
4122                                    }
4123                                    // question.find( '.wpProQuiz_responsePoints' ).text( questionResult.p );
4124                                }
4125                            }
4126                        }
4127                    }
4128                });
4129            },
4130
4131            showTip: function () {
4132                var $this = $(this);
4133                var id = $this.siblings('.wpProQuiz_question').find(globalNames.questionList).data('question_id');
4134
4135                $this.siblings('.wpProQuiz_tipp').toggle('fast');
4136
4137                results[id].tip = 1;
4138
4139                $(document).bind("mouseup.tipEvent", function (e) {
4140                    var $tip = $e.find(".wpProQuiz_tipp");
4141                    var $btn = $e.find('input[name="tip"]');
4142
4143                    if (
4144                        !$tip.is(e.target) &&
4145                        $tip.has(e.target).length == 0 &&
4146                        !$btn.is(e.target)
4147                    ) {
4148                        $tip.hide("fast");
4149                        $(document).unbind(".tipEvent");
4150                    }
4151                });
4152            },
4153
4154            ajax: function (data, success, dataType) {
4155                dataType = dataType || "json";
4156
4157                if (bitOptions.cors) {
4158                    jQuery.support.cors = true;
4159                }
4160
4161                if (data["quiz"] === undefined) {
4162                    data["quiz"] = config.quiz;
4163                }
4164                if (data["course_id"] === undefined) {
4165                    data["course_id"] = config.course_id;
4166                }
4167                if (data["quiz_nonce"] === undefined) {
4168                    data["quiz_nonce"] = config.quiz_nonce;
4169                }
4170
4171                $.ajax({
4172                    method: "POST",
4173                    type: "POST",
4174                    url: WpProQuizGlobal.ajaxurl,
4175                    data: data,
4176                    success: success,
4177                    dataType: dataType
4178                });
4179
4180                if (bitOptions.cors) {
4181                    jQuery.support.cors = false;
4182                }
4183            },
4184
4185            checkQuizLock: function () {
4186                quizStatus.loadLock = 1;
4187
4188                plugin.methode.ajax(
4189                    {
4190                        action: "wp_pro_quiz_check_lock",
4191                        quizId: config.quizId
4192                    },
4193                    function (json) {
4194                        if (json.lock != undefined) {
4195                            quizStatus.isLocked = json.lock.is;
4196
4197                            /*
4198                                                        if (json.lock.pre) {
4199                                                            $e.find('input[name="restartQuiz"]').hide();
4200                                                        }
4201                            */
4202                        }
4203
4204                        if (json.prerequisite != undefined) {
4205                            quizStatus.isPrerequisite = 1;
4206                            $e.find(".wpProQuiz_prerequisite span").text(json.prerequisite);
4207                        }
4208
4209                        if (json.startUserLock != undefined) {
4210                            quizStatus.isUserStartLocked = json.startUserLock;
4211                        }
4212
4213                        quizStatus.loadLock = 0;
4214
4215                        if (quizStatus.isQuizStart) {
4216                            plugin.methode.startQuiz();
4217                        }
4218                    }
4219                );
4220            },
4221
4222            loadQuizData: function () {
4223                plugin.methode.ajax(
4224                    {
4225                        action: "wp_pro_quiz_load_quiz_data",
4226                        quizId: config.quizId
4227                    },
4228                    function (json) {
4229                        if (json.toplist) {
4230                            plugin.methode.handleToplistData(json.toplist);
4231                        }
4232
4233                        if (json.averageResult != undefined) {
4234                            plugin.methode.setAverageResult(json.averageResult, true);
4235                        }
4236                    }
4237                );
4238            },
4239
4240            setAverageResult: function (p, g) {
4241                var v = $e.find(".wpProQuiz_resultValue:eq(" + (g ? 0 : 1) + ") > * ");
4242
4243                v.eq(1).text(p + "%");
4244                v.eq(0).css("width", (240 * p) / 100 + "px");
4245            },
4246
4247            handleToplistData: function (json) {
4248                var $tp = $e.find(".wpProQuiz_addToplist");
4249                var $addBox = $tp
4250                    .find(".wpProQuiz_addBox")
4251                    .show()
4252                    .children("div");
4253
4254                if (json.canAdd) {
4255                    $tp.show();
4256                    $tp.find(".wpProQuiz_addToplistMessage").hide();
4257                    $tp.find(".wpProQuiz_toplistButton").show();
4258
4259                    toplistData.token = json.token;
4260                    toplistData.isUser = 0;
4261
4262                    if (json.userId) {
4263                        $addBox.hide();
4264                        toplistData.isUser = 1;
4265
4266                        if (bitOptions.isAddAutomatic) {
4267                            $tp.hide();
4268                        }
4269                    } else {
4270                        $addBox.show();
4271
4272                        var $captcha = $addBox.children().eq(1);
4273
4274                        if (json.captcha) {
4275                            $captcha
4276                                .find('input[name="wpProQuiz_captchaPrefix"]')
4277                                .val(json.captcha.code);
4278                            $captcha
4279                                .find(".wpProQuiz_captchaImg")
4280                                .attr("src", json.captcha.img);
4281                            $captcha.find('input[name="wpProQuiz_captcha"]').val("");
4282
4283                            $captcha.show();
4284                        } else {
4285                            $captcha.hide();
4286                        }
4287                    }
4288                } else {
4289                    $tp.hide();
4290                }
4291            },
4292
4293            scrollTo: function (e, h) {
4294                var x = e.offset().top - 100;
4295
4296                if (h || (window.pageYOffset || document.body.scrollTop) > x) {
4297                    $("html,body").animate({ scrollTop: x }, 300);
4298                }
4299            },
4300
4301            addToplist: function () {
4302                if (bitOptions.preview) return;
4303
4304                var $addToplistMessage = $e
4305                    .find(".wpProQuiz_addToplistMessage")
4306                    .text(WpProQuizGlobal.loadData)
4307                    .show();
4308                var $addBox = $e.find(".wpProQuiz_addBox").hide();
4309
4310                plugin.methode.ajax(
4311                    {
4312                        action: "wp_pro_quiz_add_toplist",
4313                        quizId: config.quizId,
4314                        quiz: config.quiz,
4315                        quiz_nonce: config.quiz_nonce,
4316                        token: toplistData.token,
4317                        name: $addBox.find('input[name="wpProQuiz_toplistName"]').val(),
4318                        email: $addBox.find('input[name="wpProQuiz_toplistEmail"]').val(),
4319                        captcha: $addBox.find('input[name="wpProQuiz_captcha"]').val(),
4320                        prefix: $addBox.find('input[name="wpProQuiz_captchaPrefix"]').val(),
4321                        //points: 99, //results.comp.points, // LD v2.4.3 Calculated on server
4322                        results: JSON.stringify(results),
4323                        //p_nonce: results.comp.p_nonce, // LD v2.4.3 Calculated on server
4324                        //totalPoints:config.globalPoints, // LD v2.4.3 Calculated on server
4325                        timespent: timespent
4326                    },
4327                    function (json) {
4328                        $addToplistMessage.text(json.text);
4329
4330                        if (json.clear) {
4331                            $addBox.hide();
4332                            plugin.methode.updateToplist();
4333                        } else {
4334                            $addBox.show();
4335                        }
4336
4337                        if (json.captcha) {
4338                            $addBox
4339                                .find(".wpProQuiz_captchaImg")
4340                                .attr("src", json.captcha.img);
4341                            $addBox
4342                                .find('input[name="wpProQuiz_captchaPrefix"]')
4343                                .val(json.captcha.code);
4344                            $addBox.find('input[name="wpProQuiz_captcha"]').val("");
4345                        }
4346                    }
4347                );
4348            },
4349
4350            updateToplist: function () {
4351                if (typeof wpProQuiz_fetchToplist == "function") {
4352                    wpProQuiz_fetchToplist();
4353                }
4354            },
4355
4356            registerSolved: function () {
4357                // Free Input field
4358                $e.find('.wpProQuiz_questionInput[type="text"]').change(function (e) {
4359                    var $this = $(this);
4360                    var $p = $this.parents(".wpProQuiz_listItem");
4361                    var s = false;
4362
4363                    if ($this.val() != "") {
4364                        s = true;
4365                    }
4366
4367                    $e.trigger({
4368                        type: "questionSolved",
4369                        values: { item: $p, index: $p.index(), solved: s }
4370                    });
4371                });
4372
4373                // Free Input field
4374                $e.find(".ldavq-jumbled-dnd-dropzone").change(function (e) {
4375                    var $this = $(this);
4376                    var $p = $this.parents(".wpProQuiz_listItem");
4377                    var s = false;
4378
4379                    if ($this.val() != "") {
4380                        s = true;
4381                    }
4382
4383                    $e.trigger({
4384                        type: "questionSolved",
4385                        values: { item: $p, index: $p.index(), solved: s }
4386                    });
4387                });
4388
4389                $e.find(".laq_jumbled_sentence_dropdown").change(function (e) {
4390                    var $this = $(this);
4391                    var $p = $this.parents(".wpProQuiz_listItem");
4392                    var s = false;
4393
4394                    if ($this.val() != "") {
4395                        s = true;
4396                    }
4397
4398                    $e.trigger({
4399                        type: "questionSolved",
4400                        values: { item: $p, index: $p.index(), solved: s }
4401                    });
4402                });
4403                // Free Input field
4404                $e.find(
4405                    '.laq_advanced_calculated_selection[type="text"], .laq_advanced_calculated_selection[type="number"]'
4406                ).change(function (e) {
4407                    var $this = $(this);
4408                    var $p = $this.parents(".wpProQuiz_listItem");
4409                    var s = false;
4410
4411                    if ($this.val() != "") {
4412                        s = true;
4413                    }
4414
4415                    $e.trigger({
4416                        type: "questionSolved",
4417                        values: { item: $p, index: $p.index(), solved: s }
4418                    });
4419                });
4420
4421                // Free Input field
4422                $e.find(".laq_advanced_swipe_attempted").change(function (e) {
4423                    var $this = $(this);
4424                    var $p = $this.parents(".wpProQuiz_listItem");
4425                    var s = false;
4426
4427                    if ($this.val() != "") {
4428                        s = true;
4429                    }
4430
4431                    $e.trigger({
4432                        type: "questionSolved",
4433                        values: { item: $p, index: $p.index(), solved: s }
4434                    });
4435                });
4436
4437                // Single Choice field
4438                $e.find(
4439                    '.wpProQuiz_questionList[data-type="single"] .wpProQuiz_questionInput, .wpProQuiz_questionList[data-type="assessment_answer"] .wpProQuiz_questionInput'
4440                ).change(function (e) {
4441                    var $this = $(this);
4442                    var $p = $this.parents(".wpProQuiz_listItem");
4443                    var s = this.checked;
4444
4445                    $e.trigger({
4446                        type: "questionSolved",
4447                        values: { item: $p, index: $p.index(), solved: s }
4448                    });
4449                });
4450
4451                // Cloze field
4452                $e.find(".wpProQuiz_cloze input").change(function () {
4453                    var $this = $(this);
4454                    var $p = $this.parents(".wpProQuiz_listItem");
4455                    var s = true;
4456
4457                    $p.find(".wpProQuiz_cloze input").each(function () {
4458                        if ($(this).val() == "") {
4459                            s = false;
4460                            return false;
4461                        }
4462                    });
4463
4464                    $e.trigger({
4465                        type: "questionSolved",
4466                        values: { item: $p, index: $p.index(), solved: s }
4467                    });
4468                });
4469
4470                // ?? field
4471                $e.find(
4472                    '.wpProQuiz_questionList[data-type="multiple"] .wpProQuiz_questionInput'
4473                ).change(function (e) {
4474                    var $this = $(this);
4475                    var $p = $this.parents(".wpProQuiz_listItem");
4476                    var c = 0;
4477
4478                    $p.find(
4479                        '.wpProQuiz_questionList[data-type="multiple"] .wpProQuiz_questionInput'
4480                    ).each(function (e) {
4481                        if (this.checked) c++;
4482                    });
4483
4484                    $e.trigger({
4485                        type: "questionSolved",
4486                        values: { item: $p, index: $p.index(), solved: c ? true : false }
4487                    });
4488                });
4489
4490                // Essay textarea field. For Essay file uploads look into uploadFile() function
4491                $e.find('.wpProQuiz_questionList[data-type="essay"] textarea.wpProQuiz_questionEssay').on('change', function (e) {
4492                    var $this = $(this);
4493                    var $p = $this.parents('.wpProQuiz_listItem');
4494                    var s = false;
4495
4496                    if ($this.val() != '') {
4497                        s = true;
4498                    }
4499                    $e.trigger({ type: 'questionSolved', values: { item: $p, index: $p.index(), solved: s } });
4500                });
4501
4502                // Audio textarea field. For Audio file uploads look into uploadFile() function
4503                $e.find('.wpProQuiz_questionList[data-type="laq_audio_questions"]').on('change', function (e) {
4504                    var $this = $(this);
4505                    var $p = $this.parents('.wpProQuiz_listItem');
4506                    var s = false;
4507
4508                    if ($this.val() != '') {
4509                        s = true;
4510                    }
4511                    $e.trigger({ type: 'questionSolved', values: { item: $p, index: $p.index(), solved: s } });
4512                });
4513            },
4514
4515            loadQuizDataAjax: function (quizStart) {
4516                //console.log('config[%o]', config.quizId);
4517
4518                plugin.methode.ajax(
4519                    {
4520                        action: "wp_pro_quiz_admin_ajax",
4521                        func: "quizLoadData",
4522                        data: {
4523                            quizId: config.quizId,
4524                            quiz: config.quiz,
4525                            quiz_nonce: config.quiz_nonce
4526                        }
4527                    },
4528                    function (json) {
4529                        config.globalPoints = json.globalPoints;
4530                        config.catPoints = json.catPoints;
4531                        config.json = json.json;
4532
4533                        globalElements.quiz.remove();
4534
4535                        $e.find(".wpProQuiz_quizAnker").after(json.content);
4536
4537                        $(
4538                            "table.wpProQuiz_toplistTable caption span.wpProQuiz_max_points"
4539                        ).html(config.globalPoints);
4540
4541                        //Reinit globalElements
4542                        globalElements = {
4543                            back: $e.find('input[name="back"]'),
4544                            next: $e.find(globalNames.next),
4545                            quiz: $e.find(".wpProQuiz_quiz"),
4546                            questionList: $e.find(".wpProQuiz_list"),
4547                            results: $e.find(".wpProQuiz_results"),
4548                            sending: $e.find(".wpProQuiz_sending"),
4549                            quizStartPage: $e.find(".wpProQuiz_text"),
4550                            timelimit: $e.find(".wpProQuiz_time_limit"),
4551                            toplistShowInButton: $e.find(".wpProQuiz_toplistShowInButton"),
4552                            listItems: $(),
4553                            save: $(".ld_advance_quiz_save"), //Added by webxity
4554                            resume: $(".ld_advance_quiz_resume"), //Added by webxity
4555                            save_as_next: $("#ld_advanced_save_as_next").val() //Added by webxity
4556                        };
4557
4558                        plugin.methode.initQuiz();
4559
4560                        if (quizStart) plugin.methode.startQuiz(true);
4561
4562                        // load script to show player for ajax content
4563                        var data = json.content;
4564                        var audiotag = data.search("wp-audio-shortcode");
4565                        var videotag = data.search("wp-video-shortcode");
4566                        if (audiotag != "-1" || videotag != "-1") {
4567                            $.getScript(
4568                                json.site_url +
4569                                "/wp-includes/js/mediaelement/mediaelement-and-player.min.js"
4570                            );
4571                            $.getScript(
4572                                json.site_url +
4573                                "/wp-includes/js/mediaelement/wp-mediaelement.js"
4574                            );
4575                            $("<link/>", {
4576                                rel: "stylesheet",
4577                                type: "text/css",
4578                                href:
4579                                    json.site_url +
4580                                    "/wp-includes/js/mediaelement/mediaelementplayer.min.css"
4581                            }).appendTo("head");
4582                        }
4583                    }
4584                );
4585            },
4586
4587            saveQuestionClicked: function () {
4588                var quizId = config.quizId;
4589
4590                var quizPostId = config.quiz;
4591                if (globalElements.save_as_next != "yes") {
4592
4593                    // timelimit.pause();
4594                    var time = (+new Date() - startTime) / 1000;
4595                    time =
4596                        config.timelimit && time > config.timelimit
4597                            ? config.timelimit
4598                            : time;
4599                    timespent = time;
4600                    $e.find(".wpProQuiz_quiz_time span").text(
4601                        plugin.methode.parseTime(time)
4602                    );
4603                }
4604
4605                var finishQuiz = list == undefined ? false : true;
4606                var responses = {};
4607                var r = {};
4608                var list = globalElements.questionList.children();
4609                var endCheck = true;
4610                var list = globalElements.questionList.children();
4611                list = list == undefined ? currentQuestion : list;
4612
4613                list.each(function () {
4614                    var $this = $(this);
4615                    var question_index = $this.index();
4616                    var $questionList = $this.find(globalNames.questionList);
4617                    var question_id = $questionList.data("question_id");
4618                    var data = config.json[$questionList.data("question_id")];
4619                    var name = data.type;
4620
4621                    if (data.type == "single" || data.type == "multiple") {
4622                        name = "singleMulti";
4623                    }
4624
4625                    //if (config.ld_script_debug == true) {
4626                    //  console.log('checkQuestion: calling readResponses');
4627                    //}
4628
4629                    responses[question_id] = readResponses(
4630                        name,
4631                        data,
4632                        $this,
4633                        $questionList,
4634                        false
4635                    );
4636
4637
4638                    responses[question_id]["question_pro_id"] = data["id"];
4639                    responses[question_id]["question_post_id"] = data["question_post_id"];
4640
4641                    plugin.methode.CookieSaveResponse(
4642                        question_id,
4643                        question_index,
4644                        data.type,
4645                        responses[question_id]
4646                    );
4647                });
4648                plugin.methode.ajax(
4649                    {
4650                        action: "ld_advance_save_quiz_pro", //changed for advance addon
4651                        func: "checkAnswers",
4652                        data: {
4653                            quizId: config.quizId,
4654                            quiz: config.quiz,
4655                            course_id: config.course_id,
4656                            quiz_nonce: config.quiz_nonce,
4657                            responses: JSON.stringify(responses),
4658                            viewedQuestions: viewedQuestions,
4659                            lastViewedQuestion: lastViewedQuestion,
4660                            saveQuizTrigger: saveQuizTrigger,
4661                            checkedQuestions: checkedQuestions
4662                        }
4663                    },
4664                    function (json) {
4665                        plugin.methode.hideSpinner();
4666                        jQuery(".ld_advance_quiz_resume").show();
4667
4668                        if (globalElements.save_as_next != "yes") {
4669                            $(".wp_pro_quiz_message")
4670                                .html("Quiz state is saved.")
4671                                .css("display", "block");
4672                            // location.reload();
4673                        }
4674                    }
4675                );
4676            },
4677            
4678            load_save_resume: function () {
4679
4680                if (is_resume_save_event_attached == false) {
4681                    if (globalElements.save)
4682                        globalElements.save.click(plugin.methode.saveQuestionClicked); // added by webxity
4683
4684                    if (globalElements.resume)
4685                        globalElements.resume.click(plugin.methode.resumeQuestionClicked); // added by webxity
4686                    is_resume_save_event_attached = true;
4687                }
4688            },
4689            mark_drag_fill_nav_link: function () {
4690                
4691                $('.ldavq-jumbled-dnd-dropzone').on('drop', function () {
4692                    if (currentQuestion) {
4693                        $e.trigger({ type: 'questionSolved', values: { item: currentQuestion, index: currentQuestion.index(), solved: true } });
4694                    }
4695                })
4696                
4697                $(document).on('touchend', function(e) {
4698                    if (currentQuestion) {
4699                        $e.trigger({ type: 'questionSolved', values: { item: currentQuestion, index: currentQuestion.index(), solved: true } });
4700                    }
4701                }); 
4702                
4703            },
4704            
4705            resumeQuestionClicked: function (e) {
4706                e.preventDefault();
4707                is_quiz_resume_in_process = "yes";
4708                var post_data = {
4709                    action: "ld_advance_resume_quiz",
4710                    quizId: config.quizId,
4711                    quizPostId: config.quiz
4712                };
4713
4714                jQuery.ajax({
4715                    type: "POST",
4716                    url: WpProQuizGlobal.ajaxurl,
4717                    dataType: "json",
4718                    cache: false,
4719                    data: post_data,
4720                    error: function (jqXHR, textStatus, errorThrown) { },
4721                    success: function (reply_data) {
4722                        if( reply_data.type && reply_data.type == 'limit_reached' ){
4723                            $(".wp_pro_quiz_message")
4724                                .html(reply_data.message)
4725                                .css({
4726                                    "display": "block",
4727                                    "background-color": "red"
4728                                });
4729                            return;
4730                        }
4731                        viewedQuestions = Object.values(reply_data.viewedQuestions).map(Number);
4732                        checkedQuestions = Object.values(reply_data.checkedQuestions).map(Number);
4733                        saveQuizTrigger = reply_data.saveQuizTrigger;
4734
4735                        $(".wp_pro_quiz_message")
4736                            .html("")
4737                            .css("display", "none"); //added by webxity
4738
4739                        resumedQuestions = reply_data.data.questions;
4740                        var list = globalElements.questionList.children();
4741                        var swipe_element_index = -1;
4742
4743                        list.each(function () {
4744                            var $this = $(this);
4745                            var $questionList = $this.find(globalNames.questionList);
4746                            var question_id = $questionList.data("question_id");
4747                            var data = config.json[$questionList.data("question_id")];
4748
4749
4750                            if (!viewedQuestions.includes(question_id)) return;
4751
4752                            var question = Array();
4753                            if (resumedQuestions) {
4754                                if (resumedQuestions[question_id]) {
4755                                    if (resumedQuestions[question_id]["response"]) {
4756                                        question = resumedQuestions[question_id]["response"];
4757                                    }
4758                                }
4759                            }
4760                            if (data.type == "laq_swipe_questions") {
4761                                swipe_element_index++;
4762                            }
4763
4764                            //if( question.length>0 )
4765                            {
4766                                var main_index = list.index($this);
4767
4768                                switch (data.type) {
4769                                    case "single":
4770
4771                                        jQuery(".wpProQuiz_questionListItem", $questionList).each(
4772                                            function (i) {
4773                                                var $item = $(this);
4774                                                var index = $item.attr("data-pos");
4775
4776                                                if (question[index] == true) {
4777                                                    $item
4778                                                        .find("input[type=radio]")
4779                                                        .prop("checked", true);
4780                                                    $e.trigger({
4781                                                        type: "questionSolved",
4782                                                        values: {
4783                                                            item: $this,
4784                                                            index: main_index,
4785                                                            solved: true
4786                                                        }
4787                                                    });
4788                                                }
4789                                            }
4790                                        );
4791
4792                                        break;
4793                                    case "multiple":
4794
4795                                        jQuery(".wpProQuiz_questionListItem", $questionList).each(
4796                                            function (i) {
4797                                                var $item = $(this);
4798                                                var index = $item.attr("data-pos");
4799
4800                                                if (question[index] == true) {
4801                                                    $item
4802                                                        .find("input[type=checkbox]")
4803                                                        .prop("checked", true);
4804                                                    $e.trigger({
4805                                                        type: "questionSolved",
4806                                                        values: {
4807                                                            item: $this,
4808                                                            index: main_index,
4809                                                            solved: true
4810                                                        }
4811                                                    });
4812                                                }
4813                                            }
4814                                        );
4815                                        break;
4816                                    case "free_answer":
4817
4818                                        var $li = $questionList.children();
4819                                        var value = $li
4820                                            .find(".wpProQuiz_questionInput")
4821                                            .val(question);
4822                                        $li
4823                                            .find(".wpProQuiz_questionInput")
4824                                            .attr("disabled", false);
4825                                        if (question != "") {
4826                                            $e.trigger({
4827                                                type: "questionSolved",
4828                                                values: {
4829                                                    item: $this,
4830                                                    index: main_index,
4831                                                    solved: true
4832                                                }
4833                                            });
4834                                        }
4835                                        break;
4836                                    case "cloze_answer":
4837
4838                                        $questionList
4839                                            .find(".wpProQuiz_cloze")
4840                                            .each(function (i, v) {
4841                                                var $this = $(this);
4842                                                $this.find("input[type=text]").val(question[i]);
4843                                                if (question[i] != "") {
4844                                                    $e.trigger({
4845                                                        type: "questionSolved",
4846                                                        values: {
4847                                                            item: $this,
4848                                                            index: main_index,
4849                                                            solved: true
4850                                                        }
4851                                                    });
4852                                                }
4853                                            });
4854                                        break;
4855
4856                                    case "sort_answer":
4857
4858                                        var $items = $questionList.children();
4859                                        var sort_questions = "";
4860                                        for (var i = 0; i < question.length; i++) {
4861                                            var curr_id = question[i];
4862
4863                                            $items.each(function (i, v) {
4864                                                var $this = $(this);
4865
4866                                                var node_id = $this.attr("data-pos");
4867                                                if (node_id == curr_id
4867) {
4868                                                    $e.trigger({
4869                                                        type: "questionSolved",
4870                                                        values: {
4871                                                            item: $this,
4872                                                            index: main_index,
4873                                                            solved: true
4874                                                        }
4875                                                    });
4876                                                    sort_questions +=
4877                                                        '<li class="wpProQuiz_questionListItem" data-pos="' +
4878                                                        curr_id +
4879                                                        '">' +
4880                                                        $this.html() +
4881                                                        "</li>";
4882                                                }
4883                                            });
4884                                        }
4885                                        if (sort_questions) $questionList.html(sort_questions);
4886                                        break;
4887                                    case "matrix_sort_answer":
4888
4889                                        $sortable_items = $questionList
4890                                            .parent()
4891                                            .find(".wpProQuiz_sortStringList");
4892                                        for (var j = 0; j < question.length; j++) {
4893                                            var curr_id = question[j];
4894                                            jQuery(
4895                                                ".wpProQuiz_questionListItem",
4896                                                $questionList
4897                                            ).each(function (i) {
4898                                                var $item = $(this);
4899                                                var index = $item.attr("data-pos");
4900                                                if (curr_id == index) {
4901                                                    $sortable_items.find("li").each(function () {
4902                                                        var $inner_item = $(this);
4903                                                        var inner_index = $inner_item.attr("data-pos");
4904                                                        if (inner_index == j) {
4905                                                            var element = $inner_item.detach();
4906                                                            $item
4907                                                                .find(".wpProQuiz_maxtrixSortCriterion")
4908                                                                .append(element);
4909                                                        }
4910                                                    });
4911                                                    $e.trigger({
4912                                                        type: "questionSolved",
4913                                                        values: {
4914                                                            item: $this,
4915                                                            index: main_index,
4916                                                            solved: true
4917                                                        }
4918                                                    });
4919                                                }
4920                                            });
4921                                        }
4922                                        break;
4923                                    case "assessment_answer":
4924                                        jQuery(
4925                                            ".wpProQuiz_questionListItem input",
4926                                            $questionList
4927                                        ).each(function (i) {
4928                                            var $item = $(this);
4929                                            var index = $item.attr("data-pos");
4930                                            if (parseInt(question) == parseInt($item.val())) {
4931                                                $item.prop("checked", true);
4932                                                $e.trigger({
4933                                                    type: "questionSolved",
4934                                                    values: {
4935                                                        item: $this,
4936                                                        index: main_index,
4937                                                        solved: true
4938                                                    }
4939                                                });
4940                                            }
4941                                        });
4942                                        break;
4943                                    case "essay":
4944
4945                                        var $li = $questionList.children();
4946                                        $li.find("textarea").val(question);
4947
4948                                        if (question != "") {
4949
4950                                            //Essay Upload Start
4951                                            var uploadEssaySubmit = $("#uploadEssaySubmit_" + question_id);
4952                                            $("#uploadEssayFile_" + question_id).val(
4953                                                question
4954                                            );
4955
4956                                            uploadEssaySubmit.attr("disabled", "disabled");
4957                                            uploadEssaySubmit.val(config.essaySuccess);
4958                                            //Essay Upload End
4959
4960                                            $e.trigger({
4961                                                type: "questionSolved",
4962                                                values: {
4963                                                    item: $this,
4964                                                    index: main_index,
4965                                                    solved: true
4966                                                }
4967                                            });
4968                                        }
4969                                        break;
4970                                    case "laq_audio_questions":
4971
4972                                        // let audio = top_parent.find(".ldavq-audio-player");
4973                                        // let source = top_parent.find(".audio-source");
4974                                        // var downloadButton  = top_parent.find('.ldavq_downloadLink');
4975                                        // source.src = url;
4976                                        // audio.load(); //call this to just preload the audio without playing
4977
4978                                        var $li = $questionList.children();
4979                                        $li.find("textarea").val($li);
4980                                        if (question != "") {
4981                                            
4982                                            let audios = document.getElementsByClassName("ldavq-audio-player-"+question_id);
4983                                            if( audios.length > 0 ) {
4984                                                let audio = audios[0];
4985                                                audio.style.display = 'block';
4986                                                let sources = document.getElementsByClassName("ldavq-audio-source-player-"+question_id);
4987                                                if( sources.length > 0 ) {
4988                                                    let source = sources[0];
4989                                                    source.src = question;
4990                                                }
4991                                                audio.load();
4992                                            }
4993
4994                                            //Essay Upload Start
4995                                            var uploadaudioSubmit = $("#ldavq_submitBtn_" + question_id);
4996                                            $("#uploadAudioFile_" + question_id).val(
4997                                                question
4998                                            );
4999
5000                                            // uploadaudioSubmit.attr("disabled", "disabled");
5001                                            uploadaudioSubmit.val(config.essaySuccess);
5002                                            //Essay Upload End
5003
5004                                            $e.trigger({
5005                                                type: "questionSolved",
5006                                                values: {
5007                                                    item: $this,
5008                                                    index: main_index,
5009                                                    solved: true
5010                                                }
5011                                            });
5012                                        }
5013                                        break;
5014                                    case "laq_jumbled_sentence":
5015                                        for (var i = 0; i < question.length; i++) {
5016                                            var record = question[i];
5017                                            jQuery(
5018                                                "select[name=" + record.name + "]",
5019                                                $questionList
5020                                            ).val(record.option);
5021                                            if (record.option != "") {
5022                                                $e.trigger({
5023                                                    type: "questionSolved",
5024                                                    values: {
5025                                                        item: $this,
5026                                                        index: main_index,
5027                                                        solved: true
5028                                                    }
5029                                                });
5030                                            }
5031                                        }
5032                                        break;
5033                                    case "laq_jumble_dnd_sentence":
5034
5035                                        for (var i = 0; i < question.length; i++) {
5036                                            var record = question[i];
5037
5038                                            $this.find('#' + record.id).val(record.option)
5039
5040                                            if (record.option != "") {
5041                                                $e.trigger({
5042                                                    type: "questionSolved",
5043                                                    values: {
5044                                                        item: $this,
5045                                                        index: main_index,
5046                                                        solved: true
5047                                                    }
5048                                                });
5049                                            }
5050                                        }
5051                                        break;
5052                                    case "laq_swipe_questions":
5053                                        for (var i = 0; i < question.length; i++) {
5054                                            var record = question[i];
5055                                            if (record.attempted == "yes") {
5056                                                $e.trigger({
5057                                                    type: "questionSolved",
5058                                                    values: {
5059                                                        item: $this,
5060                                                        index: main_index,
5061                                                        solved: true
5062                                                    }
5063                                                });
5064                                                if (parseInt(record.selection) == 0) {
5065                                                    mySwipe[swipe_element_index].shiftSlide(
5066                                                        -1,
5067                                                        "drag",
5068                                                        "outside"
5069                                                    );
5070                                                } else {
5071                                                    mySwipe[swipe_element_index].shiftSlide(
5072                                                        1,
5073                                                        "drag",
5074                                                        "outside"
5075                                                    );
5076                                                }
5077                                            }
5078                                            $this
5079                                                .find("#laq_advanced_swipe_attempted" + i)
5080                                                .val(record.attempted);
5081                                        }
5082
5083                                        break;
5084                                    case "laq_calculated_formula":
5085
5086                                        //if(config.mode==2) {
5087                                        break; //Keep this question type unsolved on resume, as it has a variable answer so user must attempt it after clicking quiz resume
5088                                        //}
5089                                        for (var i = 0; i < question.length; i++) {
5090                                            var record = question[i];
5091                                            $itm = jQuery(".card_calculation", $questionList).eq(i);
5092                                            $itm
5093                                                .find(".laq_advanced_calculated_selection")
5094                                                .val(record.selection);
5095                                            if (record.selection != "") {
5096                                                $e.trigger({
5097                                                    type: "questionSolved",
5098                                                    values: {
5099                                                        item: $this,
5100                                                        index: main_index,
5101                                                        solved: true
5102                                                    }
5103                                                });
5104                                            }
5105                                        }
5106                                        break;
5107                                }
5108                            }
5109                        });
5110
5111                        jQuery(".ld_advance_quiz_resume").hide();
5112                        if (config.mode == 2) {
5113                            plugin.methode.checkQuestion(list);
5114                        } else {
5115                            is_quiz_resume_in_process = "no";
5116                        }
5117
5118                        //Set lastViewed question index from the resume response data
5119                        lastViewedQuestion = parseInt(reply_data.lastViewedQuestion);
5120                        if (saveQuizTrigger !== 'questionsNavigation') {
5121                            if (lastViewedQuestion > 0 && globalElements.save_as_next == "yes") {
5122                                lastViewedQuestion = lastViewedQuestion - 1;
5123                            }
5124                            plugin.methode.showQuestion(lastViewedQuestion);
5125                        }
5126
5127                        var $questionList = list.parents('.wpProQuiz_content').find('.wpProQuiz_reviewQuestion');
5128                        var $question = $questionList.find("li:not('.wpProQuiz_reviewQuestionSolved')");
5129                        plugin.methode.showQuestion(parseInt($question.html
5129()) - 1);
5130                    }
5131                });
5132
5133                if (LDAdvancedQuizVars.time_limit_enabled != 'on') {
5134                    if (timelimit.getInterval() == 0) {
5135                        timelimit.start();
5136                    }
5137                }
5138            },
5139
5140            nextQuestionClicked() {
5141                if (currentQuestion.data('type').trim() == 'laq_jumbled_sentence') {
5142                    var empty_count = 0;
5143                    currentQuestion.find('.laq_jumbled_sentence_dropdown').each(function () {
5144                        var $this = $(this);
5145                        if ($(this).val().trim() == '') {
5146                            $(this).addClass('ldavq_jumbled_sentence_empty_error');
5147                            empty_count += 1;
5148                        } else {
5149                            $(this).removeClass('ldavq_jumbled_sentence_empty_error');
5150                        }
5151
5152                    });
5153
5154                    if (empty_count > 0)
5155                        return;
5156                }
5157
5158
5159                const $questionList = currentQuestion.find(
5160                    globalNames.questionList
5161                );
5162                const data = config.json[$questionList.data('question_id')];
5163
5164                // Within the following logic. If the question type is 'sort_answer' there is a chance
5165                // the sortable answers will be displayed in the correct order. In that case the user will click
5166                // the next button.
5167                // The trigger to set the question was answered is normally a function of the sort/drag action
5168                // by the user. So we need to set the question answered flag in the case the Quiz summary is enabled.
5169                //if (data.type == 'sort_answer') {
5170                //  var question_index = currentQuestion.index();
5171                //  if ( typeof quizSolved[question_index] === 'undefined') {
5172                //      $e.trigger({type: 'questionSolved', values: {item: currentQuestion, index: question_index, solved: true}});
5173                //  }
5174                //}
5175
5176                if (
5177                    bitOptions.forcingQuestionSolve &&
5178                    !quizSolved[currentQuestion.index()] &&
5179                    (bitOptions.quizSummeryHide || !bitOptions.reviewQustion)
5180                ) {
5181                    // Would really like to do something more stylized instead of a simple alert popup. yuk!
5182                    alert(WpProQuizGlobal.questionNotSolved);
5183                    return false;
5184                }
5185
5186                plugin.methode.nextQuestion();
5187            },
5188            initQuiz() {
5189                //if (config.ld_script_debug == true) {
5190                //  console.log('in initQuiz');
5191                //}
5192
5193                //plugin.methode.setClozeStyle();
5194                plugin.methode.registerSolved();
5195
5196                globalElements.next.on(
5197                    'click',
5198                    plugin.methode.nextQuestionClicked
5199                );
5200
5201                globalElements.back.on('click', function (e) {
5202                    //console.log('back button clicked [%o]', e);
5203                    plugin.methode.prevQuestion();
5204                });
5205                plugin.methode.load_save_resume();
5206                plugin.methode.mark_drag_fill_nav_link();
5207                $e.find(globalNames.check).on('click', function () {
5208                    if (
5209                        bitOptions.forcingQuestionSolve &&
5210                        !quizSolved[currentQuestion.index()]
5211                    ) {
5212                        alert(WpProQuizGlobal.questionNotSolved);
5213                        return false;
5214                    }
5215                    plugin.methode.checkQuestion();
5216                });
5217
5218                $e.find('input[name="checkSingle"]').on('click', function () {
5219                    // First get all the questions...
5220                    const list = globalElements.questionList.children();
5221                    if (list != null) {
5222                        list.each(function () {
5223                            const $this = $(this);
5224                            const $questionList = $this.find(
5225                                globalNames.questionList
5226                            );
5227                            const question_id =
5228                                $questionList.data('question_id');
5229                            const data =
5230                                config.json[$questionList.data('question_id')];
5231
5232                            // Within the following logic. If the question type is 'sort_answer' there is a chance
5233                            // the sortable answers will be displayed in the correct order. In that case the user will click
5234                            // the next button.
5235                            // The trigger to set the question was answered is normally a function of the sort/drag action
5236                            // by the user. So we need to set the question answered flag in the case the Quiz summary is enabled.
5237                            //if (data.type == 'sort_answer') {
5238                            //  //var question_index = $this.index();
5239                            //  //if ( typeof quizSolved[question_index] === 'undefined') {
5240                            //      $e.trigger({type: 'questionSolved', values: {item: $this, index: $this.index(), solved: true}});
5241                            //  //}
5242                            //}
5243                        });
5244                    }
5245
5246                    if (
5247                        bitOptions.forcingQuestionSolve &&
5248                        (bitOptions.quizSummeryHide ||
5249                            !bitOptions.reviewQustion)
5250                    ) {
5251                        for (
5252                            let i = 0,
5253                                c = $e.find('.wpProQuiz_listItem').length;
5254                            i < c;
5255                            i++
5256                        ) {
5257                            if (!quizSolved[i]) {
5258                                alert(WpProQuizGlobal.questionsNotSolved);
5259                                return false;
5260                            }
5261                        }
5262                    }
5263
5264                    plugin.methode.showQuizSummary();
5265                });
5266
5267                $e.find('input[name="tip"]').on(
5268                    'click',
5269                    plugin.methode.showTip
5270                );
5271                $e.find('input[name="skip"]').on(
5272                    'click',
5273                    plugin.methode.skipQuestion
5274                );
5275
5276                $e.find('input[name="wpProQuiz_pageLeft"]').on(
5277                    'click',
5278                    function () {
5279                        plugin.methode.showSinglePage(currentPage - 1);
5280                        plugin.methode.setupMatrixSortHeights();
5281                    }
5282                );
5283
5284                $e.find('input[name="wpProQuiz_pageRight"]').on(
5285                    'click',
5286                    function () {
5287                        plugin.methode.showSinglePage(currentPage + 1);
5288
5289                        plugin.methode.setupMatrixSortHeights();
5290                        //Add by webxity
5291                        if (globalElements.save_as_next == "yes") {
5292                            plugin.methode.saveQuestionClicked();
5293                        }
5294                        //Add by webxity end
5295                    }
5296                );
5297
5298                $e.find('input[id^="uploadEssaySubmit"]').on(
5299                    'click',
5300                    plugin.methode.uploadFile
5301                );
5302                $e.find('.ldavq_submitBtn_audio').each(function(index, element) {
5303
5304                    $('.uploadAudioFile').val('');
5305                    $(this).on( "click", plugin.methode.uploadAudio );
5306
5307                });
5308                // Added in LD v2.4 to allow external notification when quiz init happens.
5309                $e.trigger('learndash-quiz-init');
5310            },
5311            // Setup the Cookie specific to the Quiz ID.
5312            CookieInit() {
5313                // Comment out to force clear cookie on init.
5314                // jQuery.cookie(cookie_name, '');
5315
5316                if (config.ld_script_debug == true) {
5317                    console.log('in CookieInit');
5318                }
5319
5320                // Temporarily disable raw mode for this operation
5321                var originalRawSetting = $.cookie.raw;
5322                $.cookie.raw = false;
5323                
5324                cookie_value = jQuery.cookie(cookie_name);
5325                // console.log('hereeeeee',cookie_value);
5326                
5327                // Restore original raw setting
5328                $.cookie.raw = originalRawSetting;
5329                
5330                if (
5331                    !cookie_value ||
5332                    cookie_value == undefined ||
5333                    cookie_value === '%7B%7D'
5334                ) {
5335                    cookie_value = {};
5336                } else {
5337                    // Additional check to ensure we have a string before parsing
5338                    if (typeof cookie_value === 'string') {
5339                        try {
5340                            cookie_value = JSON.parse(cookie_value);
5341                            //console.log("cookie_value[%o]", cookie_value );
5342                        } catch (exception) {
5343                            console.log('JSON.parse error [%o]', exception);
5344                            cookie_value = {};
5345                        }
5346                    } else {
5347                        // console.log('Cookie value is not a string, resetting to empty object');
5348                        cookie_value = {};
5349                    }
5350                }
5351
5352                if (config.ld_script_debug == true) {
5353                    console.log('after parse: cookie_value[%o]', cookie_value);
5354                }
5355
5356                // If we have form entries at the start, save them to cookie.
5357                if (
5358                    bitOptions.formActivated &&
5359                    config.formPos === formPosConst.START &&
5360                    formClass.checkForm()
5361                ) {
5362                    formClass.saveFormDataToCookie();
5363                }
5364
5365                plugin.methode.CookieSetResponses();
5366                plugin.methode.CookieResponseTimer();
5367            },
5368            CookieDelete() {
5369                //if (config.ld_script_debug == true) {
5370                //  console.log('CookieDelete: config.timelimitcookie[%o]', config.timelimitcookie);
5371                //}
5372                //if (config.ld_script_debug == true) {
5373                //  console.log('CookieDelete: cookie_name[%o]', cookie_name);
5374                //}
5375                jQuery.cookie(cookie_name, '');
5376            },
5377            CookieProcessQuestionResponse(list, lockQuestion) {
5378                var lockQuestion = lockQuestion || false;
5379                if (list != null) {
5380                    list.each(function () {
5381                        const $this = $(this);
5382
5383                        const question_index = $this.index();
5384                        const $questionList = $this.find(
5385                            globalNames.questionList
5386                        );
5387                        const question_id = $questionList.data('question_id');
5388                        const data =
5389                            config.json[$questionList.data('question_id')];
5390                        
5391                        // Add safety check to prevent TypeError
5392                        if (!data || !data.type) {
5393                            console.warn('Question data not found for question ID:', question_id);
5394                            return; // Skip this question and continue with the next one
5395                        }
5396                        
5397                        let name = data.type;
5398                        if (data.type == 'single' || data.type == 'multiple') {
5399                            name = 'singleMulti';
5400                        }
5401
5402                        const question_response = readResponses(
5403                            name,
5404                            data,
5405                            $this,
5406                            $questionList,
5407                            false
5408                        );
5409                        
5410                        plugin.methode.saveMetaDataToCookie({
5411                            lastQuestion: question_id,
5412                        });
5413                        plugin.methode.CookieSaveResponse(
5414                            question_id,
5415                            question_index,
5416                            data.type,
5417                            question_response,
5418                            lockQuestion
5419                        );
5420                    });
5421                }
5422            },
5423            // Save the answer(response) to the cookie. This is called from 'checkQuestion' and cookie timer functions.
5424            CookieSaveResponse(
5425                question_id,
5426                question_index,
5427                question_type,
5428                question_response,
5429                lockQuestion
5430            ) {
5431                var lockQuestion = lockQuestion || false;
5432                // set the value
5433                if (question_id === 'formData' + question_index) {
5434                    cookie_value[question_id] = {
5435                        index: question_index,
5436                        value: question_response,
5437                        type: question_type,
5438                    };
5439                } else {
5440                    cookie_value[question_id] = {
5441                        index: question_index,
5442                        value: question_response.response,
5443                        type: question_type,
5444                        lockQuestion,
5445                    };
5446                }
5447                // console.log('CookieSaveResponse',cookie_value);
5448                // Calculate the cookie date to expire
5449                plugin.methode.calculateCookieExpiry();
5450
5451                // store the values.
5452                jQuery.cookie(cookie_name, JSON.stringify(cookie_value), {
5453                    expires: cookieExpireDate,
5454                });
5455
5456                if (config.quiz_resume_enabled === '1') {
5457                    plugin.methode.startCookieSendTimer();
5458                }
5459            },
5460            calculateCookieExpiry() {
5461                cookieExpireDate = new Date();
5462                if (
5463                    config.timelimitcookie &&
5464                    !config.quiz_resume_cookie_expiration
5465                ) {
5466                    cookieExpireDate.setTime(
5467                        cookieExpireDate.getTime() +
5468                            config.timelimitcookie * 1000
5469                    );
5470                }
5471
5472                if (
5473                    config.quiz_resume_cookie_expiration &&
5474                    !config.timelimitcookie
5475                ) {
5476                    cookieExpireDate.setTime(
5477                        cookieExpireDate.getTime() +
5478                            config.quiz_resume_cookie_expiration * 1000
5479                    );
5480                }
5481            },
5482            saveMetaDataToCookie(id, metadata) {
5483                var metadata = metadata || false;
5484                // Calculate the cookie date to expire.
5485                plugin.methode.calculateCookieExpiry();
5486
5487                if (!cookie_value || cookie_value == undefined) {
5488                    cookie_value = {};
5489                }
5490
5491                if (typeof id === 'string' && typeof metadata === 'object') {
5492                    cookie_value[id] = {};
5493                    for (var element in metadata) {
5494                        // @todo Test in IE11
5495                        const obj = { [element]: metadata[element] };
5496                        Object.assign(cookie_value[id], obj);
5497                    }
5498                } else if (typeof id === 'string' && !metadata) {
5499                    cookie_value[id] = true;
5500                } else if (typeof id === 'object') {
5501                    for (var element in id) {
5502                        cookie_value[element] = id[element];
5503                    }
5504                }
5505
5506                // store the values.
5507                jQuery.cookie(cookie_name, JSON.stringify(cookie_value), {
5508                    expires: cookieExpireDate,
5509                });
5510
5511                if (config.quiz_resume_enabled === '1' && !cookieSendTimer) {
5512                    plugin.methode.startCookieSendTimer();
5513                }
5514            },
5515            // The cookie timer loops every 5 seconds to save the last response from the user.
5516            // This only effect Essay questions as there is some current logic where once
5517            // 'readResponses' is called the question is locked.
5518            CookieResponseTimer() {
5519                // Hook into the 'questionSolved' triggered event. This is much better than
5520                // a timer to grab the answer values. With the event trigger we only process the
5521                // single question when the user makes a change.
5522                $e.on('questionSolved', function (e) {
5523                    //if (config.ld_script_debug == true) {
5524                    //  console.log('CookieResponseTimer: e.values[%o]', e.values);
5525                    //}
5526                    if (
5527                        config.timelimitcookie !== 0 ||
5528                        config.quiz_resume_enabled === '1'
5529                    ) {
5530                        plugin.methode.CookieProcessQuestionResponse(
5531                            e.values.item
5532                        );
5533                    }
5534                });
5535            },
5536            // Load the Cookie (if present) and sets the values of the Quiz questions to the cookie saved value
5537            CookieSetResponses() {
5538                if (config.ld_script_debug == true) {
5539                    console.log('In CookieSetResponses');
5540                }
5541
5542                if (
5543                    (cookie_value == undefined ||
5544                        !Object.keys(cookie_value).length) &&
5545                    !config.quiz_resume_id
5546                ) {
5547                    // console.log( 'returning' );
5548                    return;
5549                }
5550
5551                const list = globalElements.questionList.children();
5552                list.each(function () {
5553                    const $this = $(this);
5554
5555                    const $questionList = $this.find(globalNames.questionList);
5556                    const form_question_id = $questionList.data('question_id');
5557
5558                    // Handle server-side data
5559                    if (quiz_resume_data[form_question_id] != undefined) {
5560                        const quiz_resume_question_data =
5561                            quiz_resume_data[form_question_id];
5562                        var form_question_data =
5563                            config.json[$questionList.data('question_id')];
5564
5565                        if (
5566                            form_question_data.type ===
5567                            quiz_resume_question_data.type
5568                        ) {
5569                            setResponse(
5570                                form_question_data,
5571                                quiz_resume_question_data.value,
5572                                $this,
5573                                $questionList,
5574                                quiz_resume_question_data.lockQuestion
5575                            );
5576                        }
5577                    }
5578                    // Handle cookie data
5579                    if (cookie_value[form_question_id] != undefined) {
5580                        const cookie_question_data =
5581                            cookie_value[form_question_id];
5582
5583                        var form_question_data =
5584                            config.json[$questionList.data('question_id')];
5585                        if (
5586                            form_question_data.type ===
5587                            cookie_question_data.type
5588                        ) {
5589                            setResponse(
5590                                form_question_data,
5591                                cookie_question_data.value,
5592                                $this,
5593                                $questionList,
5594                                cookie_question_data.lockQuestion
5595                            );
5596                        }
5597                    }
5598
5599                    // Move to next unanswered question
5600                    if (
5601                        typeof quiz_resume_data !== 'undefined' &&
5602                        typeof cookie_value !== 'undefined'
5603                    ) {
5604                        if (config.ld_script_debug == true) {
5605                            console.log(
5606                                "CookieSet: cookie_value['nextQuestion'][%o]",
5607                                cookie_value.nextQuestion
5608                            );
5609                            console.log(
5610                                'CookieSet: quiz_resume_data[%o]',
5611                                quiz_resume_data
5612                            );
5613                        }
5614                        if (
5615                            typeof cookie_value.nextQuestion !== 'undefined' &&
5616                            cookie_value.nextQuestion
5617                        ) {
5618                            //console.log('cookie_value[%o]', cookie_value);
5619                            plugin.methode.moveToNextUnansweredQuestion(
5620                                cookie_value
5621                            );
5622                        } else {
5623                            //console.log('quiz_resume_data[%o]', quiz_resume_data);
5624                            plugin.methode.moveToNextUnansweredQuestion(
5625                                quiz_resume_data
5626                            );
5627                        }
5628                    }
5629                });
5630            },
5631            startCookieSendTimer() {
5632                // Immediately send the first cookie entry to the server
5633                // to trigger the Continue Quiz logic when no server-side
5634                // data exists.
5635
5636                // If timer is already running, don't start another one.
5637                if (cookieSendTimer) {
5638                    return;
5639                }
5640
5641                // Set flag before starting timer.
5642                cookieSendTimer = true;
5643
5644                if (
5645                    undefined === quiz_resume_data ||
5646                    quiz_resume_data.length === 0
5647                ) {
5648                    plugin.methode.prepareSendCookieData();
5649                }
5650
5651                // Start the Timer
5652                setInterval(function () {
5653                    if (!cookieSending) {
5654                        plugin.methode.prepareSendCookieData();
5655                    }
5656                }, config.quiz_resume_cookie_send_timer * 1000);
5657            },
5658            prepareSendCookieData() {
5659                // Get Timelimit cookie data.
5660                if (config.timelimit) {
5661                    plugin.methode.addTimelimitCookieData();
5662                }
5663
5664                const cookieLength =
5665                    plugin.methode.getObjectLength(cookie_value);
5666                if (cookieLength > 0) {
5667                    const cookieKeys =
5668                        plugin.methode.getObjectKeys(cookie_value);
5669
5670                    // Flag we are sending an ajax request.
5671                    cookieSending = true;
5672                    plugin.methode.sendCookieData(cookieKeys);
5673                }
5674            },
5675            getObjectLength(object) {
5676                return Object.keys(object).length;
5677            },
5678            getObjectKeys(object) {
5679                return Object.keys(object);
5680            },
5681            excludeKeysFromCount(object, exclude) {
5682                const allKeys = plugin.methode.getObjectKeys(object);
5683                let count = 0;
5684                allKeys.forEach(function (key) {
5685                    if (!key.startsWith(exclude)) {
5686                        count++;
5687                    }
5688                });
5689                return count;
5690            },
5691            addTimelimitCookieData() {
5692                const quizTimelimitCookie = jQuery.cookie(
5693                    timelimit.timer_cookie
5694                );
5695                if ('undefined' !== typeof quizTimelimitCookie) {
5696                    plugin.methode.saveMetaDataToCookie({
5697                        [timelimit.timer_cookie]:
5698                            JSON.parse(quizTimelimitCookie),
5699                    });
5700                }
5701            },
5702            moveToNextUnansweredQuestion(data) {
5703                if (config.ld_script_debug == true) {
5704                    console.log('moveToNextUnansweredQuestion: data[%o]', data);
5705                }
5706
5707                if (typeof data !== 'undefined') {
5708                    let nextQuestion =
5709                        typeof data.nextQuestion === 'number'
5710                            ? data.nextQuestion
5711                            : 0;
5712                    const lastQuestion =
5713                        typeof data.lastQuestion === 'number'
5714                            ? data.lastQuestion
5715                            : 0;
5716
5717                    if (config.ld_script_debug == true) {
5718                        console.log(
5719                            'moveToNextUnansweredQuestion: nextQuestion[%o]',
5720                            nextQuestion
5721                        );
5722                        console.log(
5723                            'moveToNextUnansweredQuestion: lastQuestion[%o]',
5724                            lastQuestion
5725                        );
5726                        console.log(
5727                            'moveToNextUnansweredQuestion: config.mode[%o]',
5728                            config.mode
5729                        );
5730                    }
5731
5732                    if (config.mode === 3) {
5733                        if (!config.qpp) {
5734                            jQuery(globalElements.questionList)
5735                                .children()
5736                                .show();
5737                            jQuery(globalElements.listItems).each(function (
5738                                index,
5739                                listItem
5740                            ) {
5741                                if (
5742                                    $(listItem).data('question-meta')
5743                                        .question_pro_id === lastQuestion
5744                                ) {
5745                                    plugin.methode.scrollTo(
5746                                        globalElements.listItems.eq(index),
5747                                        1
5748                                    );
5749                                }
5750                            });
5751                        } else {
5752                            jQuery(globalElements.listItems).each(function (
5753                                index,
5754                                listItem
5755                            ) {
5756                                if (
5757                                    $(listItem).data('question-meta')
5758                                        .question_pro_id === lastQuestion
5759                                ) {
5760                                    plugin.methode.singlePageNavigationQuizResume(
5761                                        index
5762                                    );
5763                                }
5764                            });
5765                        }
5766                    } else {
5767                        if (config.mode == 1 && nextQuestion > 0) {
5768                            nextQuestion = lastQuestion;
5769                        } else if (nextQuestion == 0 && lastQuestion > 0) {
5770                            nextQuestion = lastQuestion;
5771                        }
5772                        jQuery(globalElements.listItems).each(function (
5773                            index,
5774                            listItem
5775                        ) {
5776                            if (
5777                                $(listItem).data('question-meta')
5778                                    .question_pro_id === nextQuestion
5779                            ) {
5780                                if (config.ld_script_debug == true) {
5781                                    console.log(
5782                                        'moveToNextUnansweredQuestion: match: listItem[%o]',
5783                                        listItem
5784                                    );
5785                                }
5786
5787                                currentQuestion =
5788                                    globalElements.listItems.eq(index);
5789
5790                                const questionId = currentQuestion
5791                                    .find(globalNames.questionList)
5792                                    .data('question_id');
5793
5794                                questionTimer.questionStart(questionId);
5795                                plugin.methode.showQuestionObject(
5796                                    currentQuestion
5797                                );
5798
5799                                return false; // break out of the loop.
5800                            }
5801                            // if (config.ld_script_debug == true) {
5802                            //  console.log("moveToNextUnansweredQuestion: not match: listItem[%o]", listItem);
5803                            // }
5804                        });
5805                    }
5806                }
5807            },
5808            // Variation of showSinglePage()
5809            singlePageNavigationQuizResume(index) {
5810                const answeredQuestions = config.qpp >= 1 ? index : index + 1;
5811                const maxPage = Math.ceil(
5812                    $e.find('.wpProQuiz_list > li').length / config.qpp
5813                );
5814                const activePage = Math.ceil(answeredQuestions / config.qpp);
5815
5816                if (activePage <= maxPage) {
5817                    const $listItem = globalElements.questionList
5818                        .children()
5819                        .hide();
5820                    const pl = $e.find(globalNames.singlePageLeft).hide();
5821                    const pr = $e.find(globalNames.singlePageRight).hide();
5822                    const cs = $e.find('input[name="checkSingle"]').hide();
5823
5824                    if (activePage > 1) {
5825                        pl.val(
5826                            pl.data('text').replace(/%d/, activePage - 1)
5827                        ).show();
5828                    }
5829
5830                    if (activePage === maxPage) {
5831                        cs.show();
5832                    } else {
5833                        pr.val(
5834                            pr.data('text').replace(/%d/, activePage 
5834+ 1)
5835                        ).show();
5836                    }
5837
5838                    currentPage = activePage;
5839
5840                    const start = config.qpp * (activePage - 1);
5841
5842                    $listItem.slice(start, start + config.qpp).show();
5843                    if (globalElements.listItems.length === index) {
5844                        index = index - 1;
5845                    }
5846                    plugin.methode.scrollTo(
5847                        globalElements.listItems.eq(index),
5848                        0
5849                    );
5850                }
5851            },
5852            sendCookieData(keys) {
5853                jQuery.ajax({
5854                    type: 'POST',
5855                    url: WpProQuizGlobal.ajaxurl,
5856                    dataType: 'json',
5857                    cache: false,
5858                    data: {
5859                        action: 'wp_pro_quiz_cookie_save_quiz',
5860                        course_id: config.course_id,
5861                        quiz: config.quiz,
5862                        quizId: config.quizId,
5863                        quiz_started: questionTimer.getQuizStart(),
5864                        results: JSON.stringify(cookie_value),
5865                        quiz_nonce: config.quiz_nonce,
5866                    },
5867                    success(response) {
5868                        if (response.success) {
5869                            if (
5870                                plugin.methode.compareObjectKeys(
5871                                    response.data,
5872                                    cookie_value
5873                                )
5874                            ) {
5875                                plugin.methode.deleteCookieKeys(keys);
5876                            }
5877                            cookieSending = false;
5878                        }
5879                    },
5880                    error(xhr) {
5881                        console.log('xhr[%o]', xhr);
5882                        const response = JSON.parse(xhr.responseText);
5883                        console.log(response.data.message);
5884                        cookieSending = false;
5885                    },
5886                });
5887            },
5888            compareObjectKeys(a, b) {
5889                const keysObjectA = Object.keys(a).sort();
5890                const keysObjectB = Object.keys(b).sort();
5891                return (
5892                    JSON.stringify(keysObjectA) === JSON.stringify(keysObjectB)
5893                );
5894            },
5895            deleteCookieKeys(keys) {
5896                // Remove saved keys from cookie object
5897                keys.forEach(function (key) {
5898                    delete cookie_value[key];
5899                });
5900
5901                // Write changed cookie object to cookie
5902                jQuery.cookie(cookie_name, JSON.stringify(cookie_value), {
5903                    expires: cookieExpireDate,
5904                });
5905            },
5906            setupMatrixSortHeights() {
5907                /**
5908                 * Here we have to do all the questions because the current logic when using X questions
5909                 * per page doesn't allow that information.
5910                 */
5911                $('li.wpProQuiz_listItem', globalElements.questionList).each(
5912                    function (idx, questionItem) {
5913                        const question_type = $(questionItem).data('type');
5914                        if ('matrix_sort_answer' === question_type) {
5915                            // On the draggable items get the items max height and set the parent ul to that.
5916                            let sortitems_height = 0;
5917                            $(
5918                                'ul.wpProQuiz_sortStringList li',
5919                                questionItem
5920                            ).each(function (idx, el) {
5921                                const el_height = $(el).outerHeight();
5922                                if (el_height > sortitems_height) {
5923                                    sortitems_height = el_height;
5924                                }
5925                            });
5926                            if (sortitems_height > 0) {
5927                                $(
5928                                    'ul.wpProQuiz_sortStringList',
5929                                    questionItem
5930                                ).css('min-height', sortitems_height);
5931                            }
5932
5933                            $(
5934                                'ul.wpProQuiz_maxtrixSortCriterion',
5935                                questionItem
5936                            ).each(function (idx, el) {
5937                                const parent_td = $(el).parent('td');
5938                                if (typeof parent_td !== 'undefined') {
5939                                    const parent_td_height =
5940                                        $(parent_td).height();
5941                                    if (parent_td_height) {
5942                                        $(el).css('height', parent_td_height);
5943                                        $(el).css(
5944                                            'min-height',
5945                                            parent_td_height
5946                                        );
5947                                    }
5948                                }
5949                            });
5950                        }
5951                    }
5952                );
5953            },
5954        };
5955
5956        /**
5957         * @memberOf plugin
5958         */
5959        plugin.preInit = function () {
5960            plugin.methode.parseBitOptions();
5961            reviewBox.init();
5962
5963            $e.find('input[name="startQuiz"]').on('click', function () {
5964                plugin.methode.startQuiz();
5965                return false;
5966            });
5967
5968            if (bitOptions.checkBeforeStart && !bitOptions.preview) {
5969                plugin.methode.checkQuizLock();
5970            }
5971
5972            $e.find('input[name="reShowQuestion"]').on('click', function () {
5973                plugin.methode.showQustionList();
5974            });
5975
5976            $e.find('input[name="restartQuiz"]').on('click', function () {
5977                plugin.methode.restartQuiz();
5978            });
5979
5980            $e.find('input[name="review"]').on(
5981                'click',
5982                plugin.methode.reviewQuestion
5983            );
5984
5985            $e.find('input[name="wpProQuiz_toplistAdd"]').on(
5986                'click',
5987                plugin.methode.addToplist
5988            );
5989
5990            $e.find('input[name="quizSummary"]').on(
5991                'click',
5992                plugin.methode.showQuizSummary
5993            );
5994
5995            $e.find('input[name="endQuizSummary"]').on('click', function () {
5996                if (bitOptions.forcingQuestionSolve) {
5997                    // First get all the questions...
5998                    list = globalElements.questionList.children();
5999                    if (list != null) {
6000                        list.each(function () {
6001                            const $this = $(this);
6002                            const $questionList = $this.find(
6003                                globalNames.questionList
6004                            );
6005                            const question_id =
6006                                $questionList.data('question_id');
6007                            const data =
6008                                config.json[$questionList.data('question_id')];
6009
6010                            // Within the following logic. If the question type is 'sort_answer' there is a chance
6011                            // the sortable answers will be displayed in the correct order. In that case the user will click
6012                            // the next button.
6013                            // The trigger to set the question was answered is normally a function of the sort/drag action
6014                            // by the user. So we need to set the question answered flag in the case the Quiz summary is enabled.
6015                            //if (data.type == 'sort_answer') {
6016                            //  var question_index = $this.index();
6017                            //  if ( typeof quizSolved[question_index] === 'undefined') {
6018                            //      $e.trigger({type: 'questionSolved', values: {item: $this, index: question_index, solved: true}});
6019                            //  }
6020                            //}
6021                        });
6022                    }
6023
6024                    for (
6025                        let i = 0, c = $e.find('.wpProQuiz_listItem').length;
6026                        i < c;
6027                        i++
6028                    ) {
6029                        if (!quizSolved[i]) {
6030                            alert(WpProQuizGlobal.questionsNotSolved);
6031                            return false;
6032                        }
6033                    }
6034                }
6035
6036                if (
6037                    bitOptions.formActivated &&
6038                    config.formPos == formPosConst.END &&
6039                    !formClass.checkForm()
6040                ) {
6041                    return;
6042                }
6043
6044                plugin.methode.finishQuiz();
6045            });
6046
6047            $e.find('input[name="endInfopage"]').on('click', function () {
6048                if (formClass.checkForm()) {
6049                    plugin.methode.finishQuiz();
6050                }
6051            });
6052
6053            $e.find('input[name="showToplist"]').on('click', function () {
6054                globalElements.quiz.hide();
6055                globalElements.toplistShowInButton.toggle();
6056            });
6057
6058            $e.on('questionSolved', plugin.methode.questionSolved);
6059
6060            if (!bitOptions.maxShowQuestion) {
6061                plugin.methode.initQuiz();
6062            }
6063
6064            if (bitOptions.autoStart) {
6065                plugin.methode.startQuiz();
6066            }
6067
6068            // If the form is shown before the quiz, we need to check if we have saved data.
6069            if (
6070                bitOptions.formActivated &&
6071                config.formPos === formPosConst.START
6072            ) {
6073                formClass.setFormDataFromServer();
6074            }
6075        };
6076
6077        plugin.preInit();
6078    };
6079
6080    $.fn.wpProQuizFront = function (options) {
6081        return this.each(function () {
6082            if (undefined == $(this).data('wpProQuizFront')) {
6083                $(this).data(
6084                    'wpProQuizFront',
6085                    new $.wpProQuizFront(this, options)
6086                );
6087            }
6088        });
6089    };
6090
6091    /**
6092     * Autosize the input field.
6093     * 
6094     * @since 4.21.4
6095     * 
6096     * @param {jQuery} $input       - The input field to autosize.
6097     * @param {number} [$padding=0] - The padding to add to the input field.
6098     */
6099    function autosizeInput($input, $padding = 0) {
6100        const $sizer = $('<span>').css({
6101            position: 'absolute',
6102            visibility: 'hidden',
6103            whiteSpace: 'pre',
6104            font: $input.css('font'),
6105        }).appendTo('body');
6106        
6107        function update() {
6108            $sizer.text($input.val() || $input.attr('placeholder') || '');
6109            $input.width($sizer.width() + 6 + $padding);
6110        }
6111        
6112        $input.on('input', update);
6113        update();
6114    }
6115
6116    // Easy Time instance
6117    var timer = new easytimer.Timer();
6118
6119    // Load Dom Content
6120    $(document).ready(function () {
6121    //window.addEventListener('DOMContentLoaded', function () {
6122        //webkitURL is deprecated but nevertheless
6123        URL = window.URL || window.webkitURL;
6124
6125        // Shim for AudioContext when it's not avb. 
6126        var AudioContext = window.AudioContext || window.webkitAudioContext;
6127        var audioContext; //new audio context to help us record
6128
6129        $('.ldavq_recordBtn').each(function(index, element) {
6130            $(this).on( "click", startRecording )
6131        });
6132        $('.ldavq_stopBtn').each(function(index, element) {
6133            $(this).on( "click", stopRecording );
6134        });
6135        $('.ldavq_pauseBtn').each(function(index, element) {
6136            $(this).on( "click", pauseRecording )
6137        });
6138
6139        // recordButton.addEventListener("click", startRecording);
6140        // stopButton.addEventListener("click", stopRecording);
6141        // // submitButton.addEventListener("click", submitRecording);  
6142        // pauseButton.addEventListener("click", pauseRecording);
6143
6144        // var recordButton = document.getElementById("ldavq_recordBtn");
6145        // var stopButton = document.getElementById("ldavq_stopBtn");
6146        // var downloadButton = document.getElementById("ldavq_downloadBtn");
6147        // var pauseButton = document.getElementById("ldavq_pauseBtn");
6148
6149        var duration;
6150        var question_id;
6151        var top_parent;
6152        // question_id = recordButton.getAttribute('data-questionId');
6153        // duration = recordButton.getAttribute('data-timer');
6154        // question_id = stopButton.getAttribute('data-questionId');
6155        // duration = stopButton.getAttribute('data-timer');
6156        // question_id = pauseButton.getAttribute('data-questionId');
6157        // duration = pauseButton.getAttribute('data-timer');
6158
6159        //var submitButton = document.getElementById("ldavq_submitBtn_" + question_id);
6160
6161        var data = [];
6162
6163        var countdown;
6164        var counter;
6165
6166        // duration = 1;
6167
6168        // Not create event listners if DOM element is not present / missing
6169        // if (recordButton !== null) {
6170        //     recordButton.addEventListener("click", startRecording);
6171        //     stopButton.addEventListener("click", stopRecording);
6172        //     // submitButton.addEventListener("click", submitRecording);  
6173        //     pauseButton.addEventListener("click", pauseRecording);
6174        // }
6175
6176        $('.audio-items .values').each(function(index, element) {
6177            var value = $(this);
6178            timer.addEventListener('secondsUpdated', function (e) {
6179                document.querySelector('.ldavq-audio-items-'+question_id+' .values').innerHTML = timer.getTimeValues().toString();
6180            });
6181    
6182            timer.addEventListener('started', function (e) {
6183                document.querySelector('.ldavq-audio-items-'+question_id+' .values').innerHTML = timer.getTimeValues().toString();
6184            });
6185    
6186            timer.addEventListener('reset', function (e) {
6187                document.querySelector('.ldavq-audio-items-'+question_id+' .values').innerHTML = timer.getTimeValues().toString();
6188            });
6189        });
6190        // Update timer according to functions
6191        
6192
6193
6194        // Start recording
6195        function startRecording() {
6196            var recordButton    = $(this);
6197            question_id         = recordButton.data('questionid');
6198            top_parent          = $(this).parents('.audio-container');
6199            var pauseButton     = top_parent.find('.ldavq_pauseBtn');
6200            var stopButton      = top_parent.find('.ldavq_stopBtn');
6201            var submitButton    = top_parent.find('.ldavq_submitBtn_audio');
6202            var downloadButton  = top_parent.find('.ldavq_downloadLink'); 
6203            duration = recordButton.data('timer');
6204            
6205
6206            var constraints = { audio: true, video: false }
6207            
6208            // We're using the standard promise based getUserMedia() 
6209            // https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
6210            navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
6211                audioContext = new AudioContext();
6212
6213                //assign to gumStream for later use
6214                gumStream = stream;
6215
6216                //use the stream
6217                input = audioContext.createMediaStreamSource(stream);
6218
6219                /* Create the Recorder object and configure to record mono sound (1 channel) Recording 2 channels will double the file size */
6220                recorder = new Recorder(input, {
6221                    numChannels: 1
6222                })
6223
6224                top_parent.find('#timer_num').css('display', 'block');
6225                top_parent.find('#duration_text').css('display', 'block');
6226                
6227                // Start the recording process 
6228                recorder.record()
6229
6230                // Start timer
6231                timer.start();
6232
6233                // Stop recording once duration is completed
6234                setTimeout(stopRecording, duration);
6235            }).catch(function (err) {
6236                //enable the record button if getUSerMedia() fails
6237                recordButton.parent().parent().css('display', 'block');
6238                stopButton.parent().parent().css('display', 'none');
6239                pauseButton.parent().parent().css('display', 'none');
6240
6241            });
6242            recordButton.parent().parent().css('display', 'none');
6243            stopButton.parent().parent().css('display', 'block');
6244            pauseButton.parent().parent().css('display', 'block');
6245            submitButton.parent().parent().css('display', 'none');
6246            downloadButton.parent().parent().parent().css('display', 'none');
6247            downloadButton.addClass("disabled");
6248            top_parent.find('#ldavq-audio-player').css('display', 'none');
6249        }
6250
6251        // Stop Recording function
6252        function stopRecording() {
6253
6254            var stopButton    = $(this);
6255            var top_parent      = $(this).parents('.audio-container');
6256            var pauseButton     = top_parent.find('.ldavq_pauseBtn');
6257            var recordButton    = top_parent.find('.ldavq_recordBtn');
6258            var submitButton    = top_parent.find('.ldavq_submitBtn_audio');
6259            var downloadButton  = top_parent.find('.ldavq_downloadLink'); 
6260
6261            // stop microphone access
6262            gumStream.getAudioTracks()[0].stop();
6263            timer.stop();
6264
6265            top_parent.find('#ldavq-audio-player').css('display', 'block');
6266            top_parent.find('#timer_num').css('display', 'none');
6267            top_parent.find('#duration_text').css('display', 'none');
6268
6269            pauseButton.innerHTML = '<span><i class="fas fa-pause"></i> Pause Recording</span>';
6270            submitButton.parent().parent().css('display', 'block');
6271            //submitButton.disabled = false;
6272            // recordButton.disabled = false;
6273            if (ajax_app.download == true) {
6274                downloadButton.removeClass("disabled").css('display', 'block');
6275            }
6276            recorder.exportWAV(createDownloadLink);
6277            
6278            // recordButton.disabled = false;
6279            // stopButton.disabled = true;
6280            // pauseButton.disabled = true;
6281            downloadButton.removeClass("disabled");
6282            recordButton.parent().parent().css('display', 'block');
6283            stopButton.parent().parent().css('display', 'none');
6284            pauseButton.parent().parent().css('display', 'none');
6285            downloadButton.parent().parent().parent().css('display', 'block');
6286        }
6287
6288        // Pause recording function
6289        function pauseRecording() {
6290            
6291            var pauseButton    = $(this);
6292            var top_parent      = $(this).parents('.audio-container');
6293            var stopButton      = top_parent.find('.ldavq_stopBtn');
6294            var recordButton    = top_parent.find('.ldavq_recordBtn');
6295            var submitButton    = top_parent.find('.ldavq_submitBtn_audio');
6296            var downloadButton  = top_parent.find('.ldavq_downloadLink'); 
6297
6298            if (recorder.recording) {
6299                recorder.stop();
6300                timer.pause();
6301                // recordButton.disabled = true;
6302                // stopButton.disabled = false;
6303                recordButton.parent().parent().css('display', 'none');
6304                stopButton.parent().parent().css('display', 'block');
6305                pauseButton.parent().parent().css('display', 'block');
6306
6307                pauseButton.innerHTML = '<span><i class="fas fa-play"></i> Resume Recording</span>';
6308            } else {
6309                recorder.record();
6310                timer.start();
6311                recordButton.parent().parent().css('display', 'none');
6312                stopButton.parent().parent().css('display', 'block');
6313                pauseButton.parent().parent().css('display', 'block');
6314                pauseButton.innerHTML = '<span><i class="fas fa-pause"></i> Pause Recording</span>';
6315            }
6316        }
6317
6318        // Audio download link
6319        function createDownloadLink(blob) {
6320            blobAudio = blob;
6321            let url = URL.createObjectURL(blob);
6322            
6323            let audios = document.getElementsByClassName("ldavq-audio-player-"+question_id);
6324            if( audios.length > 0 ) {
6325                let audio = audios[0];
6326                audio.style.display = 'block';
6327                let sources = document.getElementsByClassName("ldavq-audio-source-player-"+question_id);
6328                if( sources.length > 0 ) {
6329                    let source = sources[0];
6330                    source.src = url;
6331                }
6332                audio.load();
6333            }
6334            //let source = document.getElementById("audio-source");
6335            var downloadButton  = top_parent.find('.ldavq_downloadLink');
6336            //source.src = url;
6337            //audio.load(); //call this to just preload the audio without playing
6338            //audio.play(); //call this to play the song right away
6339            let tagA = downloadButton;
6340            tagA.href = url;
6341            
6342            tagA.download = new Date().toISOString() + '.wav';
6343            
6344            downloadButton.attr('href', url );
6345            downloadButton.attr('target','_blank');
6346            document.getElementById('uploadAudioFile_' + question_id).value = url;
6347            var blobfile = document.getElementById('uploadAudioFileData_' + question_id);
6348            // const keysArr = JSON.parse(blobfile.dataset.blob);
6349            // keysArr.push(blobAudio);
6350            // set array to dataset again
6351            // blobfile.dataset.blob = JSON.stringify(blobAudio);
6352            ajax_app.uploadBlob = blobAudio;
6353        }
6354
6355        // Submit recording and create audio submission 
6356        function submitRecording() {
6357            var form_ = document.getElementById('uploadfile_form');
6358            const formData = new FormData(form_);
6359
6360            formData.set("uploadfiles[]", blobAudio, 'recording_audio.mp3');
6361            formData.append("action", ajax_app.action);
6362            formData.append("nonce", ajax_app.nonce);
6363
6364            jQuery.ajax({
6365                type: 'post',
6366                url: ajax_app.url,
6367                data: formData,
6368                enctype: 'multipart/form-data',
6369                processData: false,
6370                contentType: false,
6371                success: function( result ){ 
6372                    // location.reload()
6373                    $('#uploadEssayFile_' + question_id).val(response.data.filelink);
6374
6375                    // disable the upload button. Only one file per quiz.
6376                    // uploadEssaySubmit.attr('disabled', 'disabled');
6377
6378                    var $item = $('#uploadAudioFile_' + question_id).parents('.wpProQuiz_listItem');
6379                    $e.trigger({ type: 'questionSolved', values: { item: $item, index: $item.index(), solved: true } });
6380                },
6381                error: function( result ){ console.log( result ); }
6382            });  
6383        }
6384    });
6385    // Allow only numbers and arithmetic operators
6386    document.querySelectorAll('.laq_advanced_calculated_selection').forEach(function(input) {
6387        input.addEventListener('input', function() {
6388            this.value = this.value.replace(/[^0-9+.-]/g, '');
6389        });
6390    });
6391
6392})(jQuery);
6393
6394var learndash_prepare_quiz_resume_data = function (config) {
6395    if (config.quiz_resume_enabled === 'undefined') {
6396        return false;
6397    }
6398    if (config.quiz_resume_enabled !== '1') {
6399        return false;
6400    }
6401
6402    if (config.quiz_resume_data === 'undefined') {
6403        return false;
6404    }
6405
6406    let resume_data = {};
6407    if (config.ld_script_debug == true) {
6408        console.log(
6409            'config.quiz_resume_data (raw)[%o]',
6410            config.quiz_resume_data
6411        );
6412    }
6413    try {
6414        resume_data = JSON.parse(config.quiz_resume_data);
6415        if (config.ld_script_debug == true) {
6416            console.log('resume_data (parsed)[%o]', resume_data);
6417        }
6418    } catch (exception) {
6419        console.log('JSON.parse error [%o]', exception);
6420    }
6421
6422    return resume_data;
6423};
6424
6425var learndash_decodeHTML = function (html) {
6426    html = html || '';
6427
6428    if (html.length > 0 && typeof html === 'string') {
6429        const txt = document.createElement('textarea');
6430        txt.innerHTML = html;
6431
6432        html = txt.value;
6433    }
6434
6435    return html;
6436};

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.