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.