Как динамически генерировать список кнопок существующих вопросов без перезагрузки страницы?


у меня просто разработана небольшая оценка, которая имеет 4 варианта ответа на вопрос и с таймером времени, разрешенным для решения вопросов.

в коде нет проблем, в противном случае мне нравится простой способ, как он соответствует задуманному.

с помощью файла TestPage.php мы получаем вопросы, записанные в таблице данных.

<?php
    session_start();
    $conn = mysqli_connect("localhost","root","","1_examen") or die("Connection failed".mysqli_connect_error());
        date_default_timezone_set("Asia/Kolkata");
        $imageview = 0;
        $val = $_GET["val"];
        if(isset($_COOKIE["clock"]))
            $clock = $_COOKIE["clock"];
        else
            $clock = 300;
        $sql = "SELECT * FROM Question WHERE Id=".$val;
        $result = $conn->query($sql);
        $row = mysqli_fetch_assoc($result);
            $question = $row["Question"];
            $a1 = $row["A1"];
            $a2 = $row["A2"];
            $a3 = $row["A3"];
            $a4 = $row["A4"];
            $image = $row["Image"];
            $answer = $row["Answer"];
            if($image != null)
                $imageview = 1;
    if(isset($_POST["submit"]))
    {
        $temp = $val - 1;
        $ans = $_POST["q"];
        $_SESSION["answer"][$temp]=$ans;
        if($ans == $answer)
        {
            $_SESSION["result"][$temp] = 1;
        }
        else
        {
            $_SESSION["result"][$temp] = 0;
        }
        if($val == 10)
            header('Location:Result.php');
        else
            header('Location:TestPage.php?val='.($val+1));
    }
?>
<html>
<head>
<title></title>
<script>
function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10)
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds;
        var temp = timer-1;
        document.cookie = "clock="+temp;
        if (--timer < 0) {
            alert("Times Up");
            location.href="Result.php";
        }
    }, 1000);
}
</script>
<script>
    window.onload = function () {
    var fiveMinutes = <?php echo $clock; ?>,
    display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
    };

    function select(){
        var radios = document.getElementsByName("q");
        var formValid = false;
        var i = 0;
        while (!formValid && i < radios.length) {
        if (radios[i].checked) formValid = true;
        i++;        
        }
        if (!formValid) alert("Please Select Your Answer !!!");
        return formValid;
    }
    </script>


    <fieldset id = "timer">
    <h4>Time Left : <span id="time"></span></h4>
    </fieldset>
    <center>
        <fieldset id="field">
            <h3>ONLINE ENTRANCE TEST</h3>
            <hr>
            <form action="" method="POST" name="form" onsubmit="return select()">
            <?php echo "<h4 id='h41'>Q".$val." ".$question."</h4>"; ?>
            <hr>
            <?php
                if($imageview == 1)
                {
                    echo "<img style='width:100px;height:100px;' src='data:image/jpeg;base64,".base64_encode($image)."'/>";                 
                    echo "<hr>";
                }
            ?>
            <ul class="answers">
                <table>
                    <tr><td>A)</td><td><input type="radio" name="q" id="q" value="<?php echo $a1;?>" id="q1a"><?php echo $a1;?></td></tr>
                    <tr><td>B)</td><td><input type="radio" name="q" id="q" value="<?php echo $a2;?>" id="q1b"><?php echo $a2;?></td></tr>
                    <tr><td>C)</td><td><input type="radio" name="q" id="q" value="<?php echo $a3;?>" id="q1c"><?php echo $a3;?></td></tr>
                    <tr><td>D)</td><td><input type="radio" name="q" id="q" value="<?php echo $a4;?>" id="q1d"><?php echo $a4;?></td></tr>
                </table>
            </ul>
            <hr>
            <input type="submit" name="submit" value="Next   ->" id="submitbutton">
        </form>
    </fieldset>
    </center>

с помощью файла MainPage.php выполняется оценка, вопросы появляются с помощью MainPage.php?val=1 Вопрос 1: val=1, " вопрос 2: val=2, вопрос 3: val=3 и так далее.

<?php
    session_start();
    $conn = mysqli_connect("localhost","root","","1_examen") or die("Connection failed".mysqli_connect_error());
        date_default_timezone_set("Asia/Kolkata");
        setcookie("clock", "", time() - 3600);
    if(isset($_POST["submit"]))
    {
        $name = $_POST["name"];
        $_SESSION["name"] = $name;
        $_SESSION["result"] = array(0,0,0,0,0,0,0,0,0,0);
        $_SESSION["answers"]=array("","","","","","","","","","");
        header('Location:TestPage.php?val=1');
    }
?>
<html>
<head>
<title></title>
<script>
function select(){
        var x = document.forms["form"]["name"].value;
        if (x == "") {
        alert("Please Enter Your Name");
        return false;
    }
    }
</script>
</head>
<body>
    <center>
        <fieldset id="field">
            <h3>ONLINE ENTRANCE TEST</h3>
            <hr><br>
            <form action="" method="POST" name="form" onsubmit="return select()">
            Please Enter Name: <input type="text" id="name" name="name" autofocus><br><br>
            <hr><br>
            <input type="submit" name="submit" value="Begin Test" id="submitbutton">
        </form>
    </fieldset>
    </center>
</body>
</html>

с помощью следующего файла PHP Result.php, отображается оценка и ошибки неправильных ответов, отображается выбранный вопрос и правильный ответ.

<?php
    session_start();
    $conn = mysqli_connect("localhost","root","admin","Examination") or die("Connection failed".mysqli_connect_error());
        date_default_timezone_set("Asia/Kolkata");
        $score = 0;
    $results = $_SESSION["result"];
    $name = $_SESSION["name"];
    $answers = array();
    setcookie("clock", "", time() - 3600);
    for($i=0;$i<sizeof($results);$i++)
    {
        if($results[$i] == 1)
            $score++;
    }
            $t=0;
    $sql = "SELECT * FROM question";
        $result = $conn->query($sql);
        while($row = mysqli_fetch_assoc($result)){
        $answers[$t] = $row["Answer"];
        $t++;
    }
    if(isset($_POST["submit"])){
    $sql = "INSERT INTO user(Name,Score) values('$name',$score)";
    $conn->query($sql);
    header('Location:MainPage.php');
    }
?>
<html>
<head>
<title></title>
</head>
<body>
    <center>
        <fieldset id="field">
            <h3>ONLINE ENTRANCE TEST</h3>
            <hr>
            <form action="" method="POST" name="form">
            <h4>Congrats <?php echo $name;?> , Your Score : <?php echo $score;?>/10. !!!</h4>
            <hr><br>
            <div style="overflow-x:auto;">
            <table border="1px" id="table">
                <tr><th>Question</th><th>Your Answer</th><th>Correct Answer</th><th>Points Scored</th></tr>
                <?php
                for($i=0;$i<10;$i++)
                    {
                        $temp = $i+1;
                        if($results[$i] == 0)
                        echo "<tr style='background-color: #FADBD8  ;'>";
                        else
                        echo "<tr style='background-color: #D5F5E3  ;'>";
                        echo "<td>".$temp."</td><td>".$_SESSION["answer"][$i]."</td><td>".$answers[$i]."</td><td>".$results[$i]."</td></tr>";
                    }
                ?>
            </table>
        </div>
            <hr><br>
            <input type="submit" name="submit" value="Back To Main Page" id="submitbutton">
        </form>
    </fieldset>
    </center>
</body>
</html>

структура таблицы выглядит следующим образом:

CREATE TABLE `question` (
  `id` int(11) NOT NULL,
  `question` varchar(150) NOT NULL,
  `a1` varchar(100) NOT NULL,
  `a2` varchar(100) NOT NULL,
  `a3` varchar(100) NOT NULL,
  `a4` varchar(100) NOT NULL,
  `image` longblob,
  `answer` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

чего я хочу достичь в этом небольшой код дает возможность пользователю вернуться назад или просмотреть или выбрать вопрос В указать, если я не хочу, чтобы начать с начала к концу, если не от конца к началу дать эту возможность для этого вы должны генерировать кнопки по существующим вопросам, но все динамически, то есть без перезагрузки страницы.

то, что я хочу достичь, это следующее:

introducir la descripción de la imagen aquí

Author: Jacks, 2018-09-26

1 answers

Я бы обработал все на front, используя массив вопросов, для каждого из которых вы рисуете квадрат с номером вопроса и контейнер с текстом ответов и их соответствующим набором опций. Последний невидим.

По мере того, как вы двигаетесь вперед или назад, стиль применяется к квадрату, и вопрос меняется, контейнер опций для этого вопроса становится видимым.

Counter я установил его через минуту, чтобы вы могли видеть, что происходит с окончательный. На самом деле, что должно произойти, так это то, что при отправке ответов или по истечении времени вы отправляете полную форму на бэкэнд.

var preguntas = [{
    pregunta: 'Cuanto es 2+2?',
    alternativas: [1, 2, 3, 4],
    respuesta: null
  },
  {
    pregunta: 'Vive en una Piña debajo del mar',
    alternativas: ['Bob Esponja', 'Patricio Estrella', 'Calamardo', 'Aquaman'],
    respuesta: null
  },
  {
    pregunta: 'Cuanto es 3 x 6 ?',
    alternativas: [18, 36, '3x6', 4],
    respuesta: null
  },
  {
    pregunta: 'Mejor sitio web de preguntas y respuestas?',
    alternativas: ['stackoverflow español', 'quora', 'answers.org', 'gmail'],
    respuesta: null
  },
  {
    pregunta: 'Cuanto es 3+3?',
    alternativas: [3, 12, 6, 33],
    respuesta: null
  },
  {
    pregunta: 'Capital de USA?',
    alternativas: ['New York', 'Washington', 'Metropolis', 'Ciudad Gótica'],
    respuesta: null
  },
];
var pregunta_actual = 0;

$(document).ready(() => {
  var getOpciones = function() {
    $('#preguntas li').removeClass('current').eq(pregunta_actual).addClass('current');
    var respuesta_actual = $('.respuesta').eq(pregunta_actual);
    $('.respuesta').removeClass('actual');
    respuesta_actual.addClass('actual');
  };



  var inicio = new Date(),
    segundos = 90, // tiempo para responder, en segundos
    intervalo = setInterval(() => {
      if (!segundos--) {
        alert('Se acabó el tiempo!');
        enviarRespuestas();
      }
      inicio.setTime(inicio.getTime() - 1000);
      $('#tiempo_restante').text(inicio.toTimeString().split(' ')[0]);
    }, 1000);


  function enviarRespuestas() {
    clearInterval(intervalo);
    console.log(preguntas);
    $('#container').empty().text('Resultados enviados');
  }

  $('#enviar').on('click', enviarRespuestas);

  inicio.setHours(0, 0, segundos); // cuanto tiempo queda
  $('#tiempo_restante').text(inicio.toTimeString().split(' ')[0]);

  preguntas.forEach((elemento, index) => {
    $('#preguntas').append(`<li rel="${index}">${index+1}</li>`);

    var respuesta = $(`<span class="respuesta"><div>${elemento.pregunta}</div></span>`);

    $('.respuestas').append(respuesta);
    elemento.alternativas.forEach((alternativa) => {
      var option = jQuery(`
      <label >
      <input type="radio" name="respuesta_${index}" value="${alternativa}" >
      ${alternativa}
      <label>`);
      respuesta.append(option);

    });
  });
  $('.respuesta').find('input').on('click', function() {
    preguntas[pregunta_actual].respuesta=$(this).val();
    $('#preguntas li').eq(pregunta_actual).addClass('respondida');
  });
  getOpciones();

  $('#preguntas li').on('click', function() {
    pregunta_actual = $(this).attr('rel');
    getOpciones();
  });

  $('#retroceder').on('click', () => {
    if (pregunta_actual === 0) {
      return;
    }
    pregunta_actual--;
    getOpciones();
  });

  $('#avanzar').on('click', () => {
    if (pregunta_actual === preguntas.length - 1) {
      return;
    }
    pregunta_actual++;
    getOpciones();
  });
});
#container {
  float: left;
  height: 200px;
  width: 500px;
}

.container1 {
  width: 100px;
  float: left;
  padding: 0 20px;
  height: 100%;
}

#preguntas {
  margin: 0;
  padding: 0;
  margin-top: 10px;
  list-style: none;
}

.controles {
  text-align: center;
  margin: 0 auto 5px;
}

.controles a {
  padding: 5px 7px;
  margin: 0 5px;
  background-color: #5c76d8;
  border-radius: 4px;
  color: white;
  font-weight: bold;
  cursor: pointer;
}

#preguntas li {
  list-style: none;
  padding: 10px;
  float: left;
  background-color: #CCC;
  display: inline-block;
  border: 1px solid #999;
  cursor: pointer;
}

#preguntas li:hover {
  list-style: none;
  padding: 10px;
  float: left;
  background-color: #EEE;
  display: inline-block;
  border: 1px solid #999;
  cursor: pointer;
}

#preguntas li.current {
  padding: 9px;
  border: 2px solid #369;
}

#preguntas li.respondida {
  background-color: #CCC;
}

#preguntas li.respondida {
  background-color: #93e485;
}

.respuestas {
  float: left;
  height: 100%;
}

label {
  clear: left;
  display: block;
}

.respuesta {
  display: none;
}

.respuesta.actual {
  display: inline-block;
}

.respuesta>div {
  margin-bottom: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
  <div class="controles">
    <a id="retroceder">
      < retroceder </a>
        <a id="avanzar"> avanzar > </a>
        <a id="enviar"> enviar respuestas </a>
  </div>
  <hr>
  <div class="container1">
    <div id="tiempo_restante"></div>
    <ul id="preguntas">

    </ul>
  </div>
  <div class="respuestas">
  </div>

</div>

Бонус-Трек

Чтобы принести вам данные из PHP в интерфейс, подобный тому, который я показал вам, вы приносите все вопросы из таблицы и помещаете их в массив. В отличие от того, что я сделал, вы также присваиваете атрибут name каждому вопросу, который вы задаете позволяет выводить идентификатор строки.

 $preguntas=[];
 $sql = "SELECT * FROM Question";
 $result = $conn->query($sql);
 while($row = mysqli_fetch_assoc($result)) {
   $preguntas[] = [
     'name' => 'respuesta_'.$row["id"],
     'pregunta' => $row["Question"],
     'alternativas' => [$row["A1"], $row["A2"],$row["A3"],$row["A4"]],
     'respuesta' => null
   ]
 }

В конце этого цикла, если бы ваши вопросы были похожи на те, которые я поставил в Примере, массив был бы в форме:

[
    [
        'name'         => 'respuesta_1',
        'pregunta'     => 'Cuanto es 2+2?',
        'alternativas' => [1, 2, 3, 4],
        'respuesta'    => null,
    ],
    [
        'name'         => 'respuesta_2',
        'pregunta'     => 'Vive en una Piña debajo del mar',
        'alternativas' => ['Bob Esponja', 'Patricio Estrella', 'Calamardo', 'Aquaman'],
        'respuesta'    => null,
    ],
    [
        'name'         => 'respuesta_3',
        'pregunta'     => 'Cuanto es 3 x 6 ?',
        'alternativas' => [18, 36, '3x6', 4],
        'respuesta'    => null,
    ],
    [
        'name'         => 'respuesta_4',
        'pregunta'     => 'Mejor sitio web de preguntas y respuestas?',
        'alternativas' => ['stackoverflow español', 'quora', 'answers.org', 'gmail'],
        'respuesta'    => null,
    ],
    [
        'name'         => 'respuesta_5',
        'pregunta'     => 'Cuanto es 3+3?',
        'alternativas' => [3, 12, 6, 33],
        'respuesta'    => null,
    ],
    [
        'name'         => 'respuesta_6',
        'pregunta'     => 'Capital de USA?',
        'alternativas' => ['New York', 'Washington', 'Metropolis', 'Ciudad Gótica'],
        'respuesta'    => null,
    ],
];

Это вы запускаете, прежде чем начать печать HTML, в форме

<?php

  ...llenas la variable $preguntas...

?>
<html>
  <head>
    <script>
       var preguntas = <?php echo json_encode($preguntas); ?>;
    </script>
  ...otras cosas del head...
  </head>
  <body>
    ... el html del formulario...
  </body>

</html>

Если вы посмотрите, когда вы пишете свой HTML (это не красиво ,но работает), вы объявляете переменную preguntas como

<script>
   var preguntas = <?php echo json_encode($preguntas); ?>;
</script>

И с этим вы заполнили массив вопросов на интерфейсе, с помощью которого вы уже можете нарисовать свой тест альтернативы.

Теперь я поставил атрибут name для каждой группы опций, используя индекс вопроса в массиве. Вы должны использовать атрибут name, который вы отправляете из бэкэнда (потому что мы не знаем, являются ли ваши идентификаторы строго корреляционными или вы, возможно, удалили строку)

Итак, где я поставил:

preguntas.forEach((elemento, index) => {
  $('#preguntas').append(`<li rel="${index}">${index+1}</li>`);
  var respuesta = $(`<span class="respuesta"><div>${elemento.pregunta}</div></span>`);
  $('.respuestas').append(respuesta);

  elemento.alternativas.forEach((alternativa) => {
    var option = jQuery(`
    <label >
    <input type="radio" name="respuesta_${index}" value="${alternativa}" >
    ${alternativa}
    <label>`);
    respuesta.append(option);
  });

});

Вместо использования name="respuesta_${index}" Вы бы назначили параметрам атрибут name вопроса:

elemento.alternativas.forEach((alternativa) => {
  var option = jQuery(`
   <label >
   <input type="radio" name="${elemento.name}" value="${alternativa}" >
    ${alternativa}
    <label>`);
    respuesta.append(option);
  });

Теперь, чтобы отправить форма, мы должны сделать еще одно изменение. Я обернул вопросы в div:

<div class="respuestas">
   ...aquí se insertan las alternativas dinámicamente
</div>

Вы могли бы заменить это на form

<form id="formulario" class="respuestas" method="POST" action="evaluar.php">
   ...aquí se insertan las alternativas dinámicamente
</form>

Затем, если вы нажмете кнопку отправки, будет отправлена форма:

$('#enviar').on('click', function() {
    $('#formulario').submit();
});

То же самое, когда время истекает:

if (!segundos--) {
    clearInterval(intervalo);
    alert('Se acabó el tiempo!');
    $('#formulario').submit();
}

Теперь вам не хватает, чтобы сделать скрипт evaluar.php, который получает ответы. Они придут в виде:

$respuesta1 = $_POST['respuesta_1']
$respuesta2 = $_POST['respuesta_2']

Но это неэффективно, потому что вам придется писать 100 раз почти одно. Итак, поскольку вы уже знаете, сколько вопросов вы отправили, вы можете выполнить тот же запрос при запуске, но теперь выполните:

 $puntaje = 0;
 $sql = "SELECT * FROM Question";
 $result = $conn->query($sql);
 while($row = mysqli_fetch_assoc($result)) {
     $name = 'respuesta_'.$row["id"];
     if(isset($_POST[$name]) && $_POST[$name] == $row['answer']) {
       $puntaje++;
     }    
 }

В фоновом режиме вы отправили имена, которые должны были иметь каждую группу вариантов. Таким образом, Вы читаете то же значение в суперглобале $_POST. Чтобы добавить 1 к баллу, необходимо выполнить ответ на вопрос (isset($_POST[$name])) и ответ соответствует столбцу answer вашей таблицы.

В конце этой итерации вы уже знаете окончательный счет и вы можете распечатать его на экране с барабанами и тарелками.

Edit: не хватало чего-то фундаментального

В первом примере (snippet) каждый раз, когда был выбран ответ, поле было помечено зеленым цветом, но атрибут respuesta соответствующего вопроса не был заполнен. На заднем плане, где говорилось:

 $('.respuesta').find('input').on('click', function() {
    $('#preguntas li').eq(pregunta_actual).addClass('respondida');
 });

Читать:

 $('.respuesta').find('input').on('click', function() {
    preguntas[pregunta_actual].respuesta=$(this).val();
    $('#preguntas li').eq(pregunta_actual).addClass('respondida');
 });
 10
Author: ffflabs, 2018-10-28 18:07:18