简体   繁体   中英

How to change the contents of the modal through javascript function?

Hi I am making Quiz module. In which student can take quiz. once submitted, if the quiz is not passed, than students can 'retake quiz'. Once students click on 'retake quiz', only questions for which user gave wrong answer will be showed up. I am using php and HTML modal for showing the questions for the first time when student take quiz. Than using jquery and javascript, I am passing the responses of user to backend and checking if it is passed or failed. If failed, than I have wrong questions id, whihc I want to display when they take 'requiz'. Following a code:

Index.php

//When user clicks this button, modal will be pop-up and questions will be displayed one by one.
<a href="#" class="btn btn-danger btn-lg" data-toggle="modal" data-target="#Quiz" id="start-quiz">Start Quiz</a>


<!-- Quiz Modal -->
<div class="modal fade quiz-modal" id="Quiz">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <? foreach ($questions as $i=>$question) { ?>
            <div class='question'>
                <div class="modal-header">
                    <div class="row">
                        <h4>QUIZ</h4>
                    </div>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <div id="quest-content" class="quest">
                            <h4 class="question-title"><?=$question->number?>) <?=$question->title?></h4>
                            <ul class="list-unstyled">
                                <? foreach ($question->getAnswers() as $answer) { ?>
                                    <li>
                                        <div class="checkbox">
                                                <input class="cb" type="checkbox" name="answer[]" value="<?=$answer->title?>">
                                                <?=$answer->title?> 
                                        </div>
                                    </li>
                                <? } ?> 
                            </ul>
                            <br>
                            <br>
                            <p class='error'>Please select an answer</p>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <p class='quest_num'><?=$question->number?> of <?=count($questions)?></p>
                    <?  if( count($questions) === 1 ) { ?>
                        <a class="btn button btn-lg quiz-btn">Submit Quiz</a>
                    <? } else if ( count($questions) === $i +1 ) { ?>
                        <a class="btn button btn-lg quiz-btn">Submit Quiz</a>
                    <? }  else { ?>
                        <a href="" class=" btn button btn-lg quiz-btn">Next Question</a>
                    <? } ?>
                </div>
            </div>
            <? } ?>
        </div>
    </div>
</div>

Following is <script> where I am doing couple of things: if there are more questions, button will show 'Next' and if it's a last question- button will show 'Submit'. Once submit the quiz, it will send user's responses to backend through $.post and get back the array of questions IDs that were wrong. Using this wrong question's ids, when user clicks on 'Retake Quiz', it should show quiz again with these ids only.

<script type="text/javascript">
$(document).on('ready', function(){
    var answers = [];
    $('.quiz-btn').click(function(e){
        e.preventDefault()
        var checkbox = $(this).parents('.question').children('.modal-body').children('.row').children('.quest').children('ul').children('li').children('.checkbox').children('.icheckbox_square');
        var btn = $(this).parents('.question').children('.modal-footer').children('.quiz-btn')
        var next = false
        var submit = false
        console.log(checkbox)
        $(checkbox).each(function(){
            if ( $(this).hasClass('checked') && $(btn).html() == 'Next Question' ) {
                answers.push($(this).children('.cb:checked').val());
                console.log(answers);
                next = true
            } 
            else if ($(this).hasClass('checked') && $(btn).html() == 'Submit Quiz') {
                answers.push($(this).children('.cb:checked').val());
                submit = true
            }
        });

        if ( next ) {
            e.preventDefault();
            $(this).parents('.question').slideUp(500);
            $(this).parents('.question').next('.question').delay(500).slideDown(500);
        } else if ( submit ) {
            e.preventDefault();
            $.post('/student/submit_quiz',{answers: answers, module: <?=$model->course_module->id?>}, function(data){
                var correct = data['correct'];
                var incorrect = data['incorrect'];

                if(incorrect){
                    if(incorrect.length > 0){
                        var div = $('.quest')[$('.quest').length - 1];
                        var footer = $('.modal-footer')[$('.modal-footer').length - 1];
                        var progress = (correct.length*100)/(<?=count($questions)?>);
                        div.innerHTML = "<h4 class='question-title'>" + (correct.length)+"/<?=count($questions)?> questions correct <h4>";
                        div.innerHTML += "<div class='error'><p><strong>We are sorry but you have " + incorrect.length +" answers incorrect</strong><br>Please go back and review and reanswer those questions.</p></div>";
                        footer.innerHTML = "<a onclick='retakeQuiz(["+incorrect+"])' class='btn btn-success btn-lg quiz-btn'>Retake Quiz</a>";
                    } else {
                        var div = $('.quest')[$('.quest').length - 1];
                        var footer = $('.modal-footer')[$('.modal-footer').length - 1];
                        var progress = (correct.length*100)/(<?=count($questions)?>);
                        div.innerHTML = "<h4 class='question-title'> Congratulations!! You Passed this Module.<h4>";
                        footer.innerHTML = "<a href='/student/course/<?=$model->course->id?>' class='btn btn-default btn-lg'>Continue</a>";
                    }
                }
            });
        } else {
            console.log(next)
            $('.quest .error').fadeIn();
        }
    });
});

function retakeQuiz(incorrect) {
    $.each(incorrect, function(key, val) {
        alert('index ' + key + ' points to file ' + val);
        //Here incorrect is the array of Wrong Question's IDs. How can I use that id to show only this questions in my above modal. 
    });
}
</script>

I would like to know you all that I have only one Modal- that shows the quiz questions one after another and when quiz is completed and user submit the quiz, it will show the message of pass or fail along with the respective button say 'Continue' or 'Retake Quiz'. If 'Retake Quiz' is clicked, wrong questions will be displayed on the modal. So I have only one modal, but just changing the contents dynamically through javascript.

I tried my best to explain my question and code. Hope to get some help. Help is highly appreciated.

Doing manipulating from two sides like this always ends up in a bit of a tizy. Instead of changing the questions by using jQuery, can you change your PHP endpoint to return modal content given a set of ids? Here is the big idea:

Your PHP code has an endpoint that takes in a list of ids. These ids get passed off to the PHP code which does it thing and returns a list of questions of the ids (and corresponding answers). When a user first visits your page, your PHP code auto-loads all of the questions into the modal so the user gets the entire quiz (similarly to how you are loading on initial page load now).

Once they finish the quiz, you said you stored the ids of the questions they got wrong. What I would recommend is sending the ids to your php code to return a newly generated modal only including the ids of questions they got wrong. Then, you can simply replace the modal content with the result. Something like this perhaps (this is all psuedo-code, but I hope it gets the idea across)

// user has finished taking the quiz

$.get({
    "url": "/yourendpoint" + ids.toString()
    "method": "GET"
}.then(function(data){
    $(".modal-content").html(data);
});

My suggestion is to add attribute id to the every question divison with the value of question id like below

<? foreach ($questions as $i=>$question) { ?>
        <div class='question' id="<? $question->id ?>">
          // Your remaining code here
        </div>
<? } ?>

After submitting the form, in your callback of ajax call, remove the question divs with the ids those are not present in the response like below

function retakeQuiz(incorrect) {
    // I am assuming incorrect as [id, id, id] for example
    $('.question').each(function (index, question) {
       if (!incorrect.includes($(question).attr('id'))) {
           $(question).remove();
       }
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM