How to calculate the difference in example below - php

I want to calculate difference between the "Total Marks" in a question, and the text inputs for each answer in a question. Also if a question has only one answer, then it should display the text input as a readonly and display the same value as the number under the "Total Mark" for that question in that text input.
Below is a screenshot which shows the table and the written problem I have with both scenarios:
Below is the current jquery variable which should be doing the calculation and display the readonly textbox when necessary. But at the moment it is not working. Also at the moment I have display the number for total marks to be fixed as "5" when doing the calculations, well this is incorrect as that it should be the number for within each row, so I believe the variable $sessionMarks that should be the number, not 5.
$(function(){
var questions = $('#markstbl td[class*="_ans"]').length-1;
//disable single entry
for (var i=0;i<=questions;i++){
if($("[class*=q"+i+"_mark]").length ==1){
$("[class*=q"+i+"_mark]").attr("disabled","disabled")
}
}
//find each question set and add listeners
for (var i=0;i<=questions;i++){
$('input[class*="q'+i+'"]').keyup(function(){
var cl = $(this).attr('class').split(" ")[1]
var questionno = cl.substring(cl.indexOf('q')+1,cl.indexOf('_'))
var t=0;
$("[class*=q"+questionno+"_mark]").each(function(){
var num = (isNaN(parseInt($(this).val())))?0:parseInt($(this).val());
t+=parseInt(num);
})
var fixedno = 5;
$(".q"+questionno+"_ans").text((t>fixedno)?fixedno:t);
})
}
})
Below is the code for the table, from the query it outputs the details of each question from the database and then it displays it in a table:
<?php
$assessment = $_SESSION['id'] . $sessionConcat;
include('connect.php');
$query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, an.Answer, q.QuestionMarks
FROM Session s
INNER JOIN Question q ON s.SessionId = q.SessionId
JOIN Answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
WHERE s.SessionName = ?
ORDER BY q.QuestionId, an.Answer
";
// prepare query
$stmt=$mysqli->prepare($query);
// You only need to call bind_param once
$stmt->bind_param("s", $assessment);
// execute query
$stmt->execute();
// This will hold the search results
$searchQuestionId = array();
$searchQuestionContent = array();
$searchAnswer = array();
$searchMarks = array();
// Fetch the results into an array
// get result and assign variables (prefix with db)
$stmt->bind_result($dbSessionId, $dbSessionName, $dbQuestionId, $dbQuestionContent, $dbAnswer, $dbQuestionMarks);
while ($stmt->fetch()) {
$searchQuestionId[] = $dbQuestionId;
$searchQuestionContent[] = $dbQuestionContent;
$searchAnswer[] = $dbAnswer;
$searchMarks[] = $dbQuestionMarks;
}
?>
....
<tbody>
<tr>
<?php
$previous_question_id = null;
$rowspans = array_count_values($searchQuestionId);
$output = "";
$questionid = 0; //whole question
$questionno = 0; //part of question
foreach ($searchQuestionContent as $key => $question) {
if ($previous_question_id != $searchQuestionId[$key]){
$questionno=0;
}
// removed logic, not necessary to set empty strings if you're skipping them
$output.= '<tr class="questiontd">' . PHP_EOL;
if ($previous_question_id != $searchQuestionId[$key]) {
$output.= '<td class="questionnumtd" name="numQuestion" rowspan="' . $rowspans[$searchQuestionId[$key]] . '">' . htmlspecialchars($searchQuestionId[$key]) . '</td>' . PHP_EOL;
$output.= '<td class="questioncontenttd q{$questionno++}_mark{$questionid}" rowspan="' . $rowspans[$searchQuestionId[$key]] . '">' . htmlspecialchars($question) . '</td>' . PHP_EOL;
}
$output.= '<td class="answertd" name="answers[]">';
$output.= $searchAnswer[$key];
$output.= '</td>';
$output.= '<td class="answermarkstd"><input class="individualMarks" q_group="1" name="answerMarks[]" id="individualtext" type="text" /></td>' . PHP_EOL;
if ($previous_question_id != $searchQuestionId[$key]) {
$output.= '<td class="noofmarkstd q{$questionid++}_ans" q_group="1" rowspan="' . $rowspans[$searchQuestionId[$key]] . '">' . htmlspecialchars($searchMarks[$key]) . '</td>' . PHP_EOL;
}
// moved this to the end
if ($previous_question_id != $searchQuestionId[$key]) {
$previous_question_id = $searchQuestionId[$key];
}
}
echo $output;
?>
</tr>
</tbody>
Update:
In the sample HTML which is in this fiddle, I can get it to work (except I want the calculation to be total marks minus number entered in text input, not what it is doing now which is when I enter a number in text input it performs an addition from 0 to whatever number entered in text input), but when I tried to edit the code above to do the same thing, then it doesn't work, nothing happens.
The sample html is below:
<form id="Marks" action="/u0867587/Mobile_app/individualmarks.php" method="post">
<table border='1' id='markstbl'>
<thead>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>
</thead>
<tbody>
<tr class="questiontd">
<td class="questionnumtd" name="numQuestion" rowspan="3">1</td>
<td class="questioncontenttd" rowspan="3">Name three features in a ROM</td>
<td class="answertd" name="answers[]">A</td>
<td class="answermarkstd">
<input class="individualMarks q0_mark_0" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
<td class="noofmarkstd q0_ans" q_group="1" rowspan="3">5</td>
</tr>
<tr class="questiontd">
<td class="answertd" name="answers[]">B</td>
<td class="answermarkstd">
<input class="individualMarks q0_mark_1" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
</tr>
<tr class="questiontd">
<td class="answertd" name="answers[]">D</td>
<td class="answermarkstd">
<input class="individualMarks q0_mark_2" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
</tr>
<tr class="questiontd">
<td class="questionnumtd" name="numQuestion" rowspan="1">2</td>
<td class="questioncontenttd" rowspan="1">Here is a single answer</td>
<td class="answertd" name="answers[]">True</td>
<td class="answermarkstd">
<input class="individualMarks q1_mark_0" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
<td class="noofmarkstd q1_ans" q_group="1" rowspan="1">5</td>
</tr>
</tbody>
</table>
</form>
Below is what the database tables looks like, (this will follow the same data as the ones in the screenshot)
Session Table: (Where the exam details is stored)
SessionId SessionName
1 AAA
Question Table: (Where questions for each exams are stored)
SessionId QuestionId QuestionContent Total Marks
1 1 Name three features in a ROM 5
1 2 Here is a single answer 5
Answer Table: (Stores answers for each question in each exam)
AnswerId(auto) SessionId QuestionId Answer
1 1 1 A
2 1 1 B
3 1 1 D
4 1 2 True
Individual_Answer Table: (Stores each individual mark for each individual answer)
AnswerId AnswerMarks
1 2
2 2
3 1
4 5

It is not good practice to get and put values from html elements using html() which somehow belong to calculation or integers values, Therefore always use hidden fields for this type of problems, like I have included two hidden fields one for original value and one for the final value and at the end you can get the total marks values easily from the hidden field.
The code is updated for dynamic data. Use your own code for queries, mine is a rough code.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(function() {
var questions = $('#markstbl td[class*="_ans"]').length;
//disable single entry
for (var i=1;i<=questions;i++){
if($("[class*=q"+i+"_marks]").length ==1){
var t_marks = $("[class*=q"+i+"_ans]").html();
alert(t_marks);
$("[class*=q"+i+"_marks]").val(t_marks).attr("disabled","disabled");
//$("[class*=q"+i+"_mark]").attr("disabled","disabled");
}
}
//find each question set and add listeners
for (var i=0;i<=questions;i++){
$('input[class*="q'+i+'"]').keyup(function(){
var cl = $(this).attr('class').split(" ")[1]
var questionno = cl.substring(cl.indexOf('q')+1,cl.indexOf('_'));
var tot_marks = $(".q"+questionno+"_ans_org").val();
var ans_t=0;
$("[class*=q"+questionno+"_marks]").each(function(){
var num = (isNaN(parseInt($(this).val())))?0:parseInt($(this).val());
ans_t+=parseInt(num);
});
ans_t=tot_marks-ans_t;
var ans = (parseInt(ans_t)<0)?tot_marks:ans_t;
$(".q"+questionno+"_ans").val(ans);
$(".q"+questionno+"_ans_text").html(ans);
});
}
});
</script>
</head>
<body>
<form id="Marks" action="/u0867587/Mobile_app/individualmarks.php" method="post">
<?php
$ident = mysqli_connect('localhost','root','');
mysqli_select_db($ident,'testdata');
$query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, an.Answer, q.QuestionMarks
FROM session s
INNER JOIN question q ON s.SessionId = q.SessionId
JOIN answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
ORDER BY q.QuestionId, an.Answer
";
$res = mysqli_query($ident,$query);
$searchQuestionId = array();
$searchQuestionContent = array();
$searchAnswer = array();
$searchMarks = array();
while ($row = mysqli_fetch_array($res)) {
$searchQuestionId[] = $row['QuestionId'];
$searchQuestionContent[] = $row['QuestionContent'];
$searchAnswer[] = $row['Answer'];
$searchMarks[] = $row['QuestionMarks'];
}
?>
<form id="Marks" action="/u0867587/Mobile_app/individualmarks.php" method="post">
<table border='1' id='markstbl'>
<thead>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>
</thead>
<tbody>
<?php
$row_span = array_count_values($searchQuestionId);
$output = '';
$rowCount = 1;
$newQuest_id = true;
foreach($searchQuestionId as $key=>$questionId){
if($newQuest_id == true){
$output.= '<tr class="questiontd">';
$output.= '<td class="questionnumtd" name="numQuestion" rowspan="'.$row_span[$questionId].'">'.$questionId.' <input type="hidden" name="q'.$questionId.'_ans_org" class="q'.$questionId.'_ans_org" value="'.$searchMarks[$key].'"><input type="hidden" name="q'.$questionId.'_ans" class="q'.$questionId.'_ans" value="'.$searchMarks[$key].'"></td>';
$output.= '<td class="questioncontenttd" rowspan="'.$row_span[$questionId].'">'.$searchQuestionContent[$key].' </td>';
}
$output.= '<td class="answertd" name="answers[]">'.$searchAnswer[$key].'</td>';
$output.= '<td class="answermarkstd">';
$output.= '<input class="individualMarks q'.$questionId.'_marks" q_group="1" name="answerMarks[]" id="individualtext" type="text" />';
$output.= '</td>';
if($newQuest_id == true){
$output.= '<td class="noofmarkstd q'.$questionId.'_ans_text" q_group="1" rowspan="'.$row_span[$questionId].'">'.$searchMarks[$key].'</td>';
$newQuest_id = false;
}
$output.= '</tr>';
if($row_span[$questionId] == $rowCount){
$newQuest_id = true;
}
$rowCount++;
}
echo $output;
?>
</tbody>
</table>
</form>
</form>
</body>
</html>

Related

Readonly text input not appearing for single answer

I have a jsfiddle here
Please look at Question 2 in the jsfiddle table as that question contains only a single answer.
In the jquery function what I have tried to do it state that if a question only
contains 1 answer, then the text input under the Marks Per Answer
column for that answer should be readonly and display the same value
as the Total Marks Remaining for that question.
Also if you look in the jsfiddle, it states that under Total Marks Remaining column for that single row, it displays the number 5, it should display number 0. As that number 5 in the readonly text input minus the original number for total marks Remaining (which was 5) means that the number under Total Marks Remaining should be 0 for that row.
My question is that what do I need to include in the jquery function in the jsfiddle so that:
if a question has a single answer, that text input is readonly
displays the total marks number in the text input
displays 0 under "Total Marks Remaining" for that row as it should
of perform the calculation between the number in the read only text
input and the original Total Marks Remaining number.
Below is the code for the jquery function:
Jquery:
$(function () {
//alert("here");
var questions = $('#markstbl td[class*="_ans"]').length - 1;
//disable single entry
for (var i = 0; i <= questions; i++) {
if ($("[class*=q" + i + "_mark]").length == 1) {
var t_marks = $("[class*=q" + i + "_ans]").html();
//alert(t_marks);
$("[class*=q" + i + "_mark]").val(t_marks)
.attr("disabled", "disabled");
//$("[class*=q"+i+"_mark]").attr("disabled","disabled");
}
}
//find each question set and add listeners
for (var i = 0; i <= questions; i++) {
$('input[class*="q' + i + '"]').keyup(function () {
var cl = $(this).attr('class').split(" ")[1]
var questionno = cl.substring(cl.indexOf('q') + 1, cl.indexOf('_'));
var tot_marks = $(".q" + questionno + "_ans_org").val();
//alert(tot_marks);
var ans_t = 0;
$("[class*=q" + questionno + "_mark]").each(function () {
var num = (isNaN(parseInt($(this).val()))) ? 0 : parseInt($(this).val());
ans_t += parseInt(num);
});
ans_t = tot_marks - ans_t;
//alert(ans_t);
//var fixedno = tot_marks;
var ans = (parseInt(ans_t) < 0) ? tot_marks : ans_t;
$(".q" + questionno + "_ans").val(ans);
$(".q" + questionno + "_ans_text").html(ans);
});
}
});​
Below is the dynamic HTML Table:
HTML:
<table border='1' id='markstbl'>
<thead>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='totalmarksth'>Total Marks</th>
<th class='emptyth'></th>
</tr>
</thead>
<tbody>
<?php
$row_span = array_count_values($searchQuestionId);
$prev_ques = '';
foreach($searchQuestionId as $key=>$questionId){
?>
<tr class="questiontd">
<?php
if($questionId != $prev_ques){
?>
<td class="questionnumtd" name="numQuestion" rowspan="<?php echo$row_span[$questionId]?>"><?php echo$questionId?> <input type="hidden" name="q<?php echo$questionId?>_ans_org" class="q<?php echo$questionId?>_ans_org" value="<?php echo$searchMarks[$key]?>"><input type="hidden" name="q<?php echo$questionId?>_ans" class="q<?php echo$questionId?>_ans" value="<?php echo$searchMarks[$key]?>"></td>
<td class="questioncontenttd" rowspan="<?php echo$row_span[$questionId]?>"><?php echo$searchQuestionContent[$key]?> </td>
<?php
}
?>
<td class="answertd" name="answers[]"><?php echo$searchAnswer[$key]?></td>
<td class="answermarkstd">
<input class="individualMarks q<?php echo$questionId?>_mark_0" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
<?php
if($questionId != $prev_ques){
?>
<td class="totalmarkstd" rowspan="<?php echo$row_span[$questionId]?>"><?php echo$totalMarks[$key]?></td>
<td class="noofmarkstd q<?php echo$questionId?>_ans_text" q_group="1" rowspan="<?php echo$row_span[$questionId]?>"><?php echo"<strong>Marks Remaining:<br/>".$searchMarks[$key]."</strong>"?></td>
<?php
}
?>
</tr>
<?php
$prev_ques = $questionId;
}
?>
</tbody>
</table>
Your disabling loop is only checking the first of the two questions; a classic out-by-one error. Try this:
var questions = $('#markstbl td[class*="_ans"]').length;
questions will now be 2 instead of 1 and both questions will be looped over.

I am getting a blank dynamic html table

I am trying to create dynamic html table but the problem is that it is not displaying any data in the table. I know the query is correct because I tested the query in sql and it outputs the data. The problem I have I am guessing is the dynamic html table itself. Below is the code:
JavaScript/JQuery:
//javascript below will perform calculation between adding numbers between text inputs per each question
//answer for each calculation per question is stored under "Total Marks Remaining" Column
/*If a question only has one answer, then the text input under the "Marks Per Answer" column becomes
read only and displays the same number as the total marks under the "Total Marks Remaining" column
for that question*/
$(function() {
//alert("here");
var questions = $('#markstbl td[class*="_ans"]').length-1;
//disable single entry
for (var i=0;i<=questions;i++){
if($("[class*=q"+i+"_mark]").length ==1){
var t_marks = $("[class*=q"+i+"_ans]").html();
//alert(t_marks);
$("[class*=q"+i+"_mark]").val(t_marks).attr("disabled","disabled");
//$("[class*=q"+i+"_mark]").attr("disabled","disabled");
}
}
//find each question set and add listeners
for (var i=0;i<=questions;i++){
$('input[class*="q'+i+'"]').keyup(function(){
var cl = $(this).attr('class').split(" ")[1]
var questionno = cl.substring(cl.indexOf('q')+1,cl.indexOf('_'));
var tot_marks = $(".q"+questionno+"_ans_org").val();
//alert(tot_marks);
var ans_t=0;
$("[class*=q"+questionno+"_mark]").each(function(){
var num = (isNaN(parseInt($(this).val())))?0:parseInt($(this).val());
ans_t+=parseInt(num);
});
ans_t=tot_marks-ans_t;
//alert(ans_t);
//var fixedno = tot_marks;
var ans = (parseInt(ans_t)<0)?tot_marks:ans_t;
$(".q"+questionno+"_ans").val(ans);
$(".q"+questionno+"_ans_text").html(ans);
});
}
});
</script>
PHP:
<?php
if (isset($_POST['id'])) {
$_SESSION['id'] = $_POST['id'];
}
$assessment = $_SESSION['id'];
include('connect.php');
$query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, an.Answer, q.QuestionMarks
FROM Session s
INNER JOIN Question q ON s.SessionId = q.SessionId
JOIN Answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
WHERE s.SessionName = ?
ORDER BY q.QuestionId, an.Answer";
// prepare query
$stmt=$mysqli->prepare($query);
// You only need to call bind_param once
$stmt->bind_param("s", $assessment);
// execute query
$stmt->execute();
// This will hold the search results
$searchQuestionId = array();
$searchQuestionContent = array();
$searchAnswer = array();
$searchMarks = array();
// Fetch the results into an array
// get result and assign variables (prefix with db)
$stmt->bind_result($dbSessionId, $dbSessionName, $dbQuestionId, $dbQuestionContent, $dbAnswer, $dbQuestionMarks);
while ($stmt->fetch()) {
$searchQuestionId[] = $dbQuestionId;
$searchQuestionContent[] = $dbQuestionContent;
$searchAnswer[] = $dbAnswer;
$searchMarks[] = $dbQuestionMarks;
}?>
HTML:
<form id="Marks" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
<table border='1' id='markstbl'>
<thead>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>
</thead>
<?php
$row_span = array_count_values($searchQuestionId);
$prev_ques = '';
foreach($searchQuestionId as $key=>$questionId){?>
<tbody>
<tr class="questiontd">
<?php
if($questionId != $prev_ques){?>
<td class="questionnumtd" name="numQuestion" rowspan="<?=$row_span[$questionId]?>"><?=$questionId?> <input type="hidden" name="q<?=$questionId?>_ans_org" class="q<?=$questionId?>_ans_org" value="<?=$searchMarks[$key]?>"><input type="hidden" name="q<?=$questionId?>_ans" class="q<?=$questionId?>_ans" value="<?=$searchMarks[$key]?>"></td>
<td class="questioncontenttd" rowspan="<?=$row_span[$questionId]?>"><?=$searchQuestionContent[$key]?> </td>
<?php
}else{?>
<td class="questionnumtd" name="numQuestion" ></td>
<td class="questioncontenttd" ></td>
<?php
}?>
<td class="answertd" name="answers[]"><?=$searchAnswer[$key]?></td>
<td class="answermarkstd">
<input class="individualMarks q<?=$questionId?>_mark_0" q_group="1" name="answerMarks[]" id="individualtext" type="text" />
</td>
<?php
if($questionId != $prev_ques){?>
<td class="noofmarkstd q<?=$questionId?>_ans_text" q_group="1" rowspan="<?=$row_span[$questionId]?>"><?=$searchMarks[$key]?></td>
<?php
}else{?>
<td class="noofmarkstd" q_group="1"></td>
<?php
}?>
</tr>
<?php
$prev_ques = $questionId;
}?>
</tbody>
</table>
</form>
Below is the screenshot of what it is displaying:
Below is what the table should display (The Marks per Answer Column contains text inputs for each row)
Below is database design so you can see where the data is coming from:
Session Table: (Where the exam details is stored)
SessionId SessionName
1 AAA
Question Table: (Where questions for each exams are stored)
SessionId QuestionId QuestionContent Total Marks
1 1 Name three features in a ROM 5
1 2 Here is a single answer 5
Answer Table: (Stores answers for each question in each exam)
AnswerId(auto) SessionId QuestionId Answer
1 1 1 A
2 1 1 B
3 1 1 D
4 1 2 True
Individual_Answer Table: (Stores each individual mark for each individual answer)
AnswerId AnswerMarks
1 2
2 2
3 1
4 5
UPDATE:
Looking at my html code, why is it displaying the table like this below:
Check for missing php open tag <?php before include('connect.php');
Also avoid short tags like <?= and replace them with <?php echo
place <tbody> outside the foreach loop
foreach($searchQuestionId as $key=>$questionId){
?>
<tbody>
to
</thead>
<tbody>
....
....
foreach($searchQuestionId as $key=>$questionId){
?>
Unless there is some code that is not being displayed here, perhaps it's as simple as the $assessment variable not being set, so nothing is being sent to the query?
Also, to confirm that you are actually getting the results back AND binding them OK, I'd be doing a var_dump on the arrays like searchQuestionContent to make sure they have the content you expect in them, if not you know your problem is in the query / binding data. If they do have the content you expect, then you know the problem lies in the table output.

How to display answers in separate rows in a HTML table

I have this query below:
SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, GROUP_CONCAT(DISTINCT Answer ORDER BY Answer SEPARATOR '') AS Answer, q.QuestionMarks
FROM Session s
INNER JOIN Question q ON s.SessionId = q.SessionId
JOIN Answer an ON q.QuestionId = an.QuestionId
AND an.SessionId = q.SessionId
WHERE s.SessionName = "GHWSW1" AND q.QuestionId = 1
GROUP BY an.SessionId, an.QuestionId
ORDER BY q.QuestionId, an.Answer
The query above outputs this result below:
SessionId SessionName QuestionId QuestionContent Answer QuestionMarks
1 GHWSW1 1 Here are 2 answers BD 5
So I included the query in the code below and set up a html table:
$assessment = "GHWSW1";
$number = 1;
$query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent,
GROUP_CONCAT(DISTINCT Answer ORDER BY Answer SEPARATOR '') AS Answer, q.QuestionMarks
FROM Session s
INNER JOIN Question q ON s.SessionId = q.SessionId
JOIN Answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
WHERE s.SessionName = ? AND q.QuestionId = ?
GROUP BY an.SessionId, an.QuestionId
ORDER BY q.QuestionId, an.Answer
";
// prepare query
$stmt=$mysqli->prepare($query);
// You only need to call bind_param once
$stmt->bind_param("si", $assessment, $number);
// execute query
$stmt->execute();
// This will hold the search results
$searchQuestionId = array();
$searchQuestionContent = array();
$searchAnswer = array();
$searchMarks = array();
// Fetch the results into an array
// get result and assign variables (prefix with db)
$stmt->bind_result($dbSessionId, $dbSessionName, $dbQuestionId, $dbQuestionContent, $dbAnswer, $dbQuestionMarks);
while ($stmt->fetch()) {
$searchQuestionId[] = $dbQuestionId;
$searchQuestionContent[] = $dbQuestionContent;
$searchAnswer[] = $dbAnswer;
$searchMarks[] = $dbQuestionMarks;
}
?>
</head>
<body>
<form id="QandA" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
<?php
echo "<table border='1' id='markstbl'>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>\n";
foreach ($searchQuestionContent as $key=>$question) {
echo '<tr class="questiontd">'.PHP_EOL;
echo '<td class="optiontypetd">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
echo '<td>'.htmlspecialchars($question).'</td>' . PHP_EOL;
echo '<td class="answertd">'.htmlspecialchars($searchAnswer[$key]).'</td>' ;
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
}
echo "</table>" . PHP_EOL;
?>
So the HTML table displays it like this:
QuestionId QuestionContent Answer QuestionMarks
1 Here are 2 answers BD 5
But I want it like this in the html table:
QuestionId QuestionContent Answer QuestionMarks
1 Here are 2 answers B 5
D
The second Answer D should be in a seperate row and the other rows should have a rowspan. But how can this be achieved?
Session Table:
SessionId (auto) SessionName
1 AAA
Question Table:
SessionId QuestionId (auto) QuestionContent
1 1 What is 2+2?
Answer Table:
AnswerId (auto) SessionId QuestionId Answer
1 1 1 B
2 1 1 D
try this
foreach ($searchQuestionContent as $key=>$question) {
echo '<tr class="questiontd">'.PHP_EOL;
echo '<td class="optiontypetd">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
echo '<td>'.htmlspecialchars($question).'</td>' . PHP_EOL;
echo '<td class="answertd">'.htmlspecialchars($searchAnswer[$key]).'</td>' ;
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
echo '</tr>';
}
you forget to close the tr tag
Remove the GROUP BY clause and add make the foreach loop look like this:
echo "<table border='1' id='markstbl'>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>\n";
$previous_question_id = null;
foreach ($searchQuestionContent as $key=>$question) {
if ($previous_question_id == $searchQuestionId[$key]) {
$searchQuestionId[$key] = '';
$question = '';
$searchMarks[$key] = '';
}else{
$previous_question_id = $searchQuestionId[$key];
}
echo '<tr class="questiontd">'.PHP_EOL;
echo '<td class="optiontypetd">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
echo '<td>'.htmlspecialchars($question).'</td>' . PHP_EOL;
echo '<td class="answertd">';
echo $searchAnswer[$key];
echo '</td>' ;
echo '<td class="answermarkstd"><input class="individualMarks" name="answerMarks[]" id="individualtext" type="text" "/></td>' . PHP_EOL;
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
}
echo '</tr>';
echo "</table>" . PHP_EOL;

is text input correct and can table layout be changed slightly

I have 2 small questions I need help on which deals with the code below:
echo "<table border='1' id='markstbl'>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='answermarksth'>Marks per Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>\n";
$previous_question_id = null;
foreach ($searchQuestionContent as $key=>$question) {
if ($previous_question_id == $searchQuestionId[$key]) {
$searchQuestionId[$key] = '';
$question = '';
$searchMarks[$key] = '';
}else{
$previous_question_id = $searchQuestionId[$key];
}
echo '<tr class="questiontd">'.PHP_EOL;
echo '<td class="optiontypetd">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
echo '<td>'.htmlspecialchars($question).'</td>' . PHP_EOL;
echo '<td class="answertd">';
echo $searchAnswer[$key];
echo '</td>' ;
echo '<td class="answermarkstd"><input class="individualMarks" name="answerMarks[]" id="individualtext" type="text" "/></td>' . PHP_EOL;
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
}
echo '</tr>';
echo "</table>" . PHP_EOL;
Question 1: If you look at the table above, I have a a column where it will contain text inputs. Now each text input will belong to each answer in the "Answer" column. My question is that is the text input set up correctly with me including a [] in the name attribute to set up an array? Should I include [] and is there anything else I should include in the text input code?
Question 2: At the moment the code above makes the table look like this example in JSFIDDLE1. But I want the table to be displayed as this example JSFIDDLE2. As you can see the blank rows in the other table have been rowspan so that it looks like the question and the total marks looks like its in one cell. How can I get the table above to look like JSFIDDLE2?
UPDATE:
Below is the full code, I am still receiving undefined index whenver $rowspans[.... is used. Is the code below correct:
$assessment = $_SESSION['id'] . $sessionConcat;
$query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, an.Answer, q.QuestionMarks
FROM Session s
INNER JOIN Question q ON s.SessionId = q.SessionId
JOIN Answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
WHERE s.SessionName = ?
ORDER BY q.QuestionId, an.Answer
";
// prepare query
$stmt=$mysqli->prepare($query);
// You only need to call bind_param once
$stmt->bind_param("s", $assessment);
// execute query
$stmt->execute();
// This will hold the search results
$searchQuestionId = array();
$searchQuestionContent = array();
$searchAnswer = array();
$searchMarks = array();
// Fetch the results into an array
// get result and assign variables (prefix with db)
$stmt->bind_result($dbSessionId, $dbSessionName, $dbQuestionId, $dbQuestionContent, $dbAnswer, $dbQuestionMarks);
while ($stmt->fetch()) {
$searchQuestionId[] = $dbQuestionId;
$searchQuestionContent[] = $dbQuestionContent;
$searchAnswer[] = $dbAnswer;
$searchMarks[] = $dbQuestionMarks;
}
?>
</head>
<body>
<form id="QandA" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
<?php
echo "<table border='1' id='markstbl'>
<tr>
<th class='questionth'>Question No.</th>
<th class='questionth'>Question</th>
<th class='answerth'>Answer</th>
<th class='noofmarksth'>Total Marks</th>
</tr>\n";
$previous_question_id = null;
$rowspans = array_count_values($searchQuestionId);
foreach ($searchQuestionContent as $key=>$question) {
if ($previous_question_id == $searchQuestionId[$key]) {
$searchQuestionId[$key] = '';
$question = '';
$searchMarks[$key] = '';
}else{
$previous_question_id = $searchQuestionId[$key];
}
echo '<tr class="questiontd">'.PHP_EOL;
echo '<td class="optiontypetd">'.htmlspecialchars($rowspans[$searchQuestionId[$key]]).'</td>' . PHP_EOL;
echo '<td>'.htmlspecialchars($question).'</td>' . PHP_EOL;
echo '<td class="answertd">';
echo $searchAnswer[$key];
echo '</td>'; echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
}
echo '</tr>';
echo "</table>" . PHP_EOL;
?>
<p><input id="submitBtn" name="submitMarks" type="submit" value="Submit Marks" /></p>
</form>
Q1. Yes, you could even specify a name between the [].
Q2. It seems that $searchQuestionId is filled before your loop, right? In that case you could use array_count_values to store the frequency of each ID and access that array during the loop:
before your loop: $rowspans = array_count_values($searchQuestionId);
access rowspan value during loop with: $rowspans[$searchQuestionId[$key]].
You'll have to remove the line $searchQuestionId[$key] = ''; or else you won't be able to access the correct $rowspan key.
Finally, you'll have to set up some more if statements to skip the <td>s on certain rows.
$previous_question_id = null;
$rowspans = array_count_values($searchQuestionId);
foreach ($searchQuestionContent as $key=>$question) {
// removed logic, not necessary to set empty strings if you're skipping them
echo '<tr class="questiontd">'.PHP_EOL;
if ($previous_question_id != $searchQuestionId[$key]) {
echo '<td class="optiontypetd" rowspan="'.$rowspans[$searchQuestionId[$key]].'">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
echo '<td rowspan="'.$rowspans[$searchQuestionId[$key]].'">'.htmlspecialchars($question).'</td>' . PHP_EOL;
}
echo '<td class="answertd">';
echo $searchAnswer[$key];
echo '</td>' ;
echo '<td class="answermarkstd"><input class="individualMarks" name="answerMarks[]" id="individualtext" type="text" "/></td>' . PHP_EOL;
if ($previous_question_id != $searchQuestionId[$key]) {
echo '<td class="noofmarkstd" rowspan="'.$rowspans[$searchQuestionId[$key]].'">'.htmlspecialchars($searchMarks[$key]).'</td>' . PHP_EOL;
}
// moved this to the end
if ($previous_question_id != $searchQuestionId[$key]) {
$previous_question_id = $searchQuestionId[$key];
}
}

PHP Search Code from HTML form

I had a previous question on here a few minutes ago about a syntax error that was sorted. I need help getting this script working or at least for someone to point me in the right direction.
This is a search script to search by multiple fields. The search() array works fine and is a series of tickboxes with the following code:
<td width="22"><input type="checkbox" name="search[olevel = 'Yes']" id="search[olevel = 'Yes']" value="1"/>
The postcode box is a text box with the following code:
<input name="postcode[]" type="text" id="postcode[]" size="12" maxlength="12" /></td>
When I tick the olevel box it returns all the records that have Yes in the olevel field. That works as I expect.
If I put in anything in the postcode box it returns no results.
Here is the php code for the search engine.
<?php
include ('c1.php');
if ($_COOKIE["auth"] == "1") {
$display_block = "<p>You are an authorized user.</p>";
} else {
header("Location: userlogin.html");
exit;
}
doDB();
$display_block = "<h1>Results</h1>";
if (isset($_POST['search']) && !empty($_POST['search'])) {
foreach ($_POST['search'] as $key => $value) {
if ($value == 1)
$search[] = "$key";
$searchstring = implode(' AND ', $search);
$post_map = array(
'postcode' => 'candididate_contact_details.postcode'
);
}
if (isset($_POST['postcode']) && !empty($_POST['postcode'])) {
foreach ($_POST['postcode'] as $key => $value) {
if (array_key_exists($key, $post_map))
$search[] = $post_map[$key] . '=' . mysql_real_escape_string($value);
echo $searchstring;
echo $search;
$query = "SELECT candidate_id.master_id, candidate_contact_details.first_name, candidate_contact_details.last_name, candidate_contact_details.home_phone, candidate_contact_details.work_phone, candidate_contact_details.mobile_phone, candidate_contact_details.email FROM candidate_id, candidate_contact_details, qualifications, security_experience, previous_career WHERE qualifications.active = 'finished' and candidate_id.master_id = candidate_contact_details.master_id and candidate_id.master_id = qualifications.master_id and candidate_id.master_id = security_experience.master_id and candidate_id.master_id = previous_career.master_id and $searchstring";
$query_res = mysqli_query($mysqli, $query)
or die(mysqli_error($mysqli));
// $search = mysqli_query($mysqli, $query)or die(mysqli_error($mysqli));
{
$display_block .= "
<table width=\"98%\" cellspacing=\"2\" border=\"1\">
<tr>
<th>Registration Number</th>
<th>First Name</th>
<th>Last Name</th>
<th>Home Number</th>
<th>Work Number</th>
<th>Mobile Number</th>
<th>E-Mail</th>
</tr>";
while ($result = mysqli_fetch_array($query_res)) {
$regnum = $result['master_id'];
$first_name = $result['first_name'];
$last_name = $result['last_name'];
$home_phone = $result['home_phone'];
$work_phone = $result['work_phone'];
$mobile_phone = $result['mobile_phone'];
$email = $result['email'];
$display_block .= "
<tr>
<td align=\"center\">$regnum <br></td>
<td align=\"center\">$first_name <br></td>
<td align=\"center\">$last_name <br></td>
<td align=\"center\">$home_phone <br></td>
<td align=\"center\">$work_phone <br></td>
<td align=\"center\">$mobile_phone <br></td>
<td align=\"center\">$email <br></td>
</tr>";
}
$display_block .= "</table>";
}
}
}
}
?>
<html>
<head>
<title> Display results</title>
</head>
<body>
<?php echo $display_block; ?>
</body>
</html>
I know I am doing something wrong but cannot quite figure it out. Thanks in advance.
if I understand correctly, you have several postcodes per form.
then id="postcode[]" is wrong as there will be several id named the same in dom.
just delete that from your code.

Categories