Iterate through Superglobal with dynamic name - javascript

For a school assignment I have to build a client side shopping cart. The assignment states that I can only use PHP for sending the order confirmation. I am using hidden form fields (that are generated after iterating through cookies) to send the order details to a checkout page, where PHP will take over.
The form fields on one page
NumberOrdered = 0;
NumberOrdered = readCookie("NumberOrdered");
for (i=1; i <= NumberOrdered; i++){
NewOrder = "Order"+ i;
thisCookie = "";
thisCookie = readCookie(NewOrder);
fields = new Array();
fields = dezeCookie.split("|");
document.write("<input type=hidden name=\"ID_"+ i +"\" value=\"" + fields[0] + "\">");
document.write("<input type=hidden name=\"BRAND_"+ i +"\" value=\"" + fields[1] + "\">");
document.write("<input type=hidden name=\"MODEL_"+ i +"\" value=\"" + fields[2] + "\">");
document.write("<input type=hidden name=\"MATERIAL_"+ i +"\" value=\"" + fields[3] + "\">");
document.write("<input type=hidden name=\"PRICE_"+ i +"\" value=\"" + fields[4] + "\">");
}
Im having troubles iterating trough the values of the $_POST superglobal. I want to use a for loop that stores the values in an array. I am really doing this wrong though.
After Submit
<?php
for ($i = 1; $i > 12; $i){
if(!empty($_POST["ID_$i"]) && !empty($_POST["BRAND_$i"]) && !empty($_POST["MODEL_$i"]) && !empty($_POST["MATERIAL_$i"]) && !empty($_POST["PRICE$i"])){
$i = array ('id' => $_POST["ID_$i"],
'brand' => $_POST["BRAND_$i"],
'model' => $_POST["MODEL_$i"],
'material' => $_POST["MATERIAL_$i"],
'price' => $_POST["PRICE_$i"],
);
echo "$i";
}
}
?>
Iterating through the $_POST superglobal does not work.. What would work?

Miss interpretation of concatenation:
$_POST['ID_' . $i],
$_POST['BRAND_' . $i],
Alternatively if you always have the same number of fields with values, like, for sure, you could set name for each field as ID[], and access as a normal array: $_POST['ID'][0], $_POST['ID'][1], $_POST['ID'][2], ...
Though you have to be sure that all fields have some value. Empty, null or missing values will not be represented as empty value to $_POST and relation between data would be lost.
Btw, your $i = array(... would overwrite your own counting variable
And your for loop is wrong. You would never reach a loop, actually, because you have written: for ($i = 1; $i > 12; $i++);

Related

JS/PHP <--> embedded PHP HTML

I’m beginner to JS/PHP/MySQL development. I want to populate a select HTML element with table (nearly 4000 Records) from MySQL DB, relevant code is below.
<body onload="jsonload()">
<label>Beneficier Employee:</label>
<select item class = "BenEmpNo" name = "BenEmpNo" id = "BenEmpNo" onchange="jsEmpNoOnChg()" >
</select>
</body>
<script language="javascript" type="text/javascript">
function jsonload()
{
let jsSelBenEmpNo = document.getElementById("BenEmpNo");
let jsBenEmpNoDataAry;
jsSelBenEmpNo.innerHTML = "<option value='-select-'>-Select-</option>";
oReq = new XMLHttpRequest();
oReq.open('POST', "../php/oh-get_BenEmpNo.php", true);
oReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
oReq.onload = function () {
jsBenEmpNoAry = this.responseText.split('|');
for (let i = 1; i < jsBenEmpNoAry.length; i++)
{
jsBenEmpNoDataAry = jsBenEmpNoAry[i].split('~');
jsSelBenEmpNo.innerHTML += "<option value='" + jsBenEmpNoDataAry[0] +"'>" + "(" + jsBenEmpNoDataAry[0] + ")" + jsBenEmpNoDataAry[1] + "</option>";
}
}
oReq.send("parsparm=" + "|");
}
</script>
</html>
---- PHP ---
<?php
$sql = "select EmpNo, EngName from beneficiary";
$ResultSet = "";
require_once("oh-dbcon.php");
if ($result = mysqli_query($db_con, $sql))
{
while ($row = mysqli_fetch_row($result))
{
$ResultSet = $ResultSet . "|" . $row[0] . "~" . $row[1];
};
$ResultSet = $ResultSet . "~OK";
}else
$ResultSet = "ERROR Result (" . mysqli_error($db_con) . ")-(" . $sql . ")";
mysqli_close($db_con);
echo $ResultSet;
?>***
When I used pure JS (XMLHttpRequest) it takes long time (around 50s) to populate the select, during which the page is froze.
But when using HTML embedded PHP code, it is almost instantly populating the select element (below code).
<label>Beneficier Employee:</label>
<select item class = "BenEmpNo" name = "BenEmpNo" id = "BenEmpNo" onchange="jsEmpNoOnChg()" >
<option value = "-Select-">-Select-</option>
<?php
include("ohdadbcon.php");
$sql_phrase_ben = "select EmpNo, EngName from beneficiary";
$qry_result_ben = #mysqli_query($db_con, $sql_phrase_ben);
while ($row_ben = mysqli_fetch_assoc($qry_result_ben))
{
?>
<option value = "<?php echo $row_ben['EmpNo']?>" >
<?php
echo $row_ben['EngName'] . " | " . $row_ben['EmpNo'] ;
?>
</option>
<?php
}
mysqli_free_result($qry_result_ben);
?>
</select>
I want to use JS request only. Is there any other way or workaround for the slowness to this request?, or I’m doing something wrong here?
2 options... Tweak to only modify the DOM once:
let options = '';
for (let i = 1; i < jsBenEmpNoAry.length; i++)
{
jsBenEmpNoDataAry = jsBenEmpNoAry[i].split('~');
options += "<option value='" + jsBenEmpNoDataAry[0] +"'>" + "(" + jsBenEmpNoDataAry[0] + ")" + jsBenEmpNoDataAry[1] + "</option>";
}
jsSelBenEmpNo.innerHTML = options;
OR
You could also potentially generate the select or options list with PHP, and have THAT returned via AJAX. Then all the JS has to do is add/replace a single element in the DOM. This will move the entire loop to the server instead of the browser.
Though as others have mentioned, 4K items in a drop-down is going to be slow (not to mention very hard to use) just due to the size of the list. I would expect machines with low resources to get a bit choppy when the select is opened.

InnerHTML creation issue, doesn't load in the correct order, possible processing issue

I am using a series of JavaScript functions to load information from a database and use the information in the creation of a thumbnail image and a radio button corresponding to each 'comic' record that the user has theoretically created and uploaded to the database.
My problem arises when the HTML tags are created. While the image and button are both created correctly with no errors, they are outputted in the wrong order. They should be loaded alphabetically by 'comicName', which is represented in the radio button's text, for example:
Comic A (img)
Comic B (img)
Comic C (img)
I have checked the array 'arr' of 'comicID's that determine the order of outputted html objects at several stages in the code using window alerts, and at all stages the comics are ordered correctly in the array, even when outputting incorrectly. There is an odd circumstance when I have quite a lot of alerts opening up at once; the items DO in fact output in the correct order. (In this case there were around six 'comicID's in the array and each ID had an alert pop up for it at three different times).
I therefore think that the code is creating them in the correct order and trying to output them as such, but some items may be loading sooner than others due to image size or some other processing reason. If this is indeed the case how would I go about sorting it to make sure they load correctly?
Thanks in advance.
Javascript:
<script>
// Loads the user's comic list from the database.
function loadComic()
{
var xmlhttp = new XMLHttpRequest();
var getID = '<?php echo $_SESSION["userID"]; ?>';
var url = "loadCom.php?userID="+getID;
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
loadComicJSON(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
// JSON parsing for 'loadComic'.
function loadComicJSON(response)
{
var arr = JSON.parse(response);
var i;
var out = "";
document.getElementById("loadList").innerHTML="";
if (arr.length == 0)
{
document.getElementById("uploadTagID").innerHTML="";
document.getElementById("uploadTagID").innerHTML="No Comics Uploaded";
document.getElementById("btnDeleteComic").disabled=true;
document.getElementById("btnEditComic").disabled=true;
document.getElementById("btnDelAllComics").disabled=true;
$("#listButtons").hide();
}
else
{
document.getElementById("loadList").innerHTML="<br>";
for(i = 0; i < arr.length; i++)
{
tempID = (arr[i].comicID);
getCoverJSON(arr, i, tempID);
}
document.getElementById("uploadTagID").innerHTML="";
document.getElementById("uploadTagID").innerHTML="<u>Uploaded Comics</u>";
document.getElementById("btnDeleteComic").disabled=false;
document.getElementById("btnEditComic").disabled=false;
document.getElementById("btnDelAllComics").disabled=false;
$("#listButtons").show();
}
}
</script>
<script>
// Function to prevent $.get from technically being inside a loop (fixes an issue when loading more than one item).
function getCoverJSON(arr, i, tempID)
{
$.get("getCover.php", {'comicID': tempID}, function(result)
{
getCover(result, arr, i);
}
);
}
</script>
<script>
// Function to create a list of radio buttons and associated images from a user's comic list.
function getCover(result, arr, i)
{
var buildLine = document.getElementById("loadList").innerHTML;
if (result[0].pageLocation == "nocvr")
{
var out = "<hr><br><input name='comicList' type='radio' id='" + arr[i].comicID + "' value='" + arr[i].comicID + "'>" + arr[i].comicName + " </option><br><br><img name = '" + ('cm' + arr[i].comicID) + "' id='" + ('com' + arr[i].comicID) + "' onclick='resizeThumb(this)' height='100px;' src='assets/img/nocvr.jpg'><br><br>";
document.getElementById("loadList").innerHTML="";
document.getElementById("loadList").innerHTML=(buildLine + out);
}
else
{
var getImg = result[0].pageLocation;
var out = "<hr><br><input name='comicList' type='radio' id='" + arr[i].comicID + "' value='" + arr[i].comicID + "'>" + arr[i].comicName + " </option><br><br><img name = '" + ('cm' + arr[i].comicID) + "' id='" + ('com' + arr[i].comicID) + "' onclick='resizeThumb(this)' height='100px;' src='" + getImg + "'><br><br>";
document.getElementById("loadList").innerHTML="";
document.getElementById("loadList").innerHTML=(buildLine + out);
}
}
</script>
PHP (loadCom.php):
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
$user = $_GET['userID'];
include_once('includes/conn.inc.php');
$query = ("SELECT comicID, comicName FROM comic WHERE userID = '$user' ORDER BY comicName ASC");
$result = mysqli_query($conn, $query);
$outp = "[";
while($rs = $result->fetch_array(MYSQLI_ASSOC))
{
if ($outp != "[")
{
$outp .= ",";
}
$outp .= '{"comicID":"' . $rs["comicID"] . '",';
$outp .= '"comicName":"' . $rs["comicName"] . '"}';
}
$outp .="]";
$conn->close();
echo ($outp);
?>
PHP (getCover.php)
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
if (isset($_GET["comicID"]))
{
include_once('includes/conn.inc.php');
$checkID = $_GET["comicID"];
$query = ("SELECT pageLocation FROM page WHERE comicID = '$checkID' ORDER BY pageNum");
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) == 0)
{
$outp = '[{"pageLocation":"nocvr"}]';
echo ($outp);
}
else
{
$outp = "[";
while($rs = $result->fetch_array(MYSQLI_ASSOC))
{
if ($outp != "[")
{
$outp .= ",";
}
$outp .= '{"pageLocation":"' . $rs["pageLocation"] . '"}';
}
$outp .="]";
$conn->close();
echo ($outp);
}
}
else
{
$checkID = null;
echo "Error. No comic found.";
}
?>
You're using AJAX calls, which are by default asynchronous - there is NO guarantee whatsoever as to what order the responses come back in. e.g. if you have requests A,B,C, then the response to A might come 20 minutes after the C response, because someone's backhoe severed an optic cable somewhere and caused the A request to take a much longer path to the server than C's.
You can switch to synchronous, but that will lock the browser while the requests are pending, which is a bad user experience.
You'd be better off simplifying the code. Instead of doing one ajax call per fetch, you should have ONE call, and send over all of the ids you want to fetch.
In other words, instead of
$.get('getCover.php', {id:1});
$.get('getCover.php', {id:2});
$.get('getCover.php', {id:3});
switch your code over to
$.get('getCover.php', {ids:[1,2,3]});
Now it's one single ajax request, one single json response, and within that response, you can order your data however you want.

Hidden field returned by php is set properly but 'undefined' when getting the value with jquery

I have a javascript file posting data to php files which are suppose to get data from a mysql database, then populate fields with specified data. When I call the php function to store the names of the fields in the database, it returns a hidden field with how many fields are in the table stored as the value to the hidden field:
$i = 0;
$field_names = [];
while($i < mysql_num_fields($request)){
$field = mysql_fetch_field($request, $i);
$field_names[] = $field->name;
if(!$field){
die('something is wrong with the field var');
};
echo('<div class="fields" id="field_' . $i . '">' . $field->name . '<br /></div>');
$i++;
};
echo('<input type="hidden" value="' . $_POST['postselecttbl'] . '" id="hidden_tbl" />' .
'<input type="hidden" value="' . count($field_names) . '" id="num_fields" />');
$_SESSION['field_names'] = $field_names;
Everything appears to work. The hidden field '#num_fields' gets set with how many fields there are. But when I get the val() of '#num_fields' with jquery, it returns undefined until you run the function again, then it has the value from the previous time it was ran.
$.post('php/get_flds.php', {postdbhost: dbhost, postdbuser: dbuser, postdbpass: dbpass, postselectdb: selectdb, postselecttbl: selecttbl},
function(d){
$('#display_out').html(d);
}
);
var num_flds = $('#num_fields').val();
alert('about to pop ' + num_flds);
for(var i = 0; i < num_flds; i++){
alert('populating ' + i);
pop_fld(i);
};
Is the hidden input not being set correctly? I mean, it shows in the html code as being set, but jquery is not cooperating.
Is this hidden field called from ajax request? If so then try following:
$.post('php/get_flds.php', {postdbhost: dbhost, postdbuser: dbuser, postdbpass: dbpass, postselectdb: selectdb, postselecttbl: selecttbl},
function(d){
$('#display_out').html(d);
var num_flds = $('#num_fields').val();
alert('about to pop ' + num_flds);
for(var i = 0; i < num_flds; i++){
alert('populating ' + i);
pop_fld(i);
};
}
);
Otherwise the jquery doesn't know the value yet as this DOM is not in the document yet.
Post is an asynchronous call I think. var num_fields is set BEFORE post request ends and you should update it's value when post is done.
Try something like :
var num_flds = $('#num_fields').val();
$.post('php/get_flds.php', {postdbhost: dbhost, postdbuser: dbuser, postdbpass: dbpass, postselectdb: selectdb, postselecttbl: selecttbl},
function(d){
$('#display_out').html(d);
num_fields = $('#num_fields').val();
}
);
alert('about to pop ' + num_flds);
for(var i = 0; i < num_flds; i++){
alert('populating ' + i);
pop_fld(i);
};

Using only one function to update different columns of a table in database

id car make sales
1 panamera porsche 100
2 italia ferrari 200
3 volante astonmartin 300
4 avantador lamborghini 400
5 slk mercedes 500
So guys, i have this simple table in my database. And i'm gonna echo this table in a while loop.
<ul>
<?php
$query = "SELECT * FROM inplace LIMIT 0, 6";
$result = mysql_query($query) or die ('Query couldn\'t be executed');
while ($row = mysql_fetch_assoc($result)) {
echo '<li class="editable" id="'.$row['id'].'">'.$row['car'].'</li>';
echo '<li class="editable2" id="'.$row['id'].'">'.$row['make'].'</li>';
}
?>
</ul>
The idea is to update this table using jQuery in-place editor. So here is the code-
$(document).ready(function()
{
$(".editable").bind("dblclick", replaceHTML);
$(".editable2").bind("dblclick", replaceHTML2);
$(".btnSave, .btnDiscard").live("click", handler);
function handler()
{
if ($(this).hasClass("btnSave"))
{
var str = $(this).siblings("form").serialize();
$.ajax({
type: "POST",
async: false,
url: "handler.php",
data: str,
});
}
}
function replaceHTML()
{
var buff = $(this).html()
.replace(/"/g, """);
$(this).addClass("noPad")
.html("<form><input type=\"text\" name=\"car\" value=\"" + buff + "\" /> <input type=\"text\" name=\"buffer\" value=\"" + buff + "\" /><input type=\"text\" name=\"id\" value=\"" + $(this).attr("id") + "\" /></form>Save changes Discard changes")
.unbind('dblclick', replaceHTML);
}
function replaceHTML2()
{
var buff = $(this).html()
.replace(/"/g, """);
$(this).addClass("noPad")
.html("<form><input type=\"text\" name=\"make\" value=\"" + buff + "\" /> <input type=\"text\" name=\"buffer\" value=\"" + buff + "\" /><input type=\"text\" name=\"id\" value=\"" + $(this).attr("id") + "\" /></form>Save changes Discard changes")
.unbind('dblclick', replaceHTML);
}
}
);
This is an in-place edit code i got it from the internet and i just tore it down to basic level just to understand the codes. Dont worry bout the update query, its is in "handler.php".
The problem here is, i have to write separate function for each column. In this case, i have to write a separate function to update 'car' column, separate function to update 'make' column and goes on. I dont think this is the correct method to do. Because, here i just have 3 columns. What if i had 10 to 15 columns? I dont think writing 15 functions is the correct method. And "$(this).html()" takes only one form's value. Please help.
Modify your PHP script to generate HTML similar to this:
<table>
<tbody>
<tr data-id="1">
<td data-col="car">panamera</td>
<td data-col="make">porsche</td>
<td data-col="sales">100</td>
</tr>
</tbody>
</tbody>
The id of the database row corresponding to each HTML table row is specified with data-id in each tr. And each td specifies to which DB column it corresponds using data-col.
Using these information you can pass enough information back to the PHP script that updates the database. So essentially when a cell is clicked, you can get its column name using:
$(this).data('col')
And you can get the ID for its row using:
$(this).parent('tr').data('id')
Then you can pass these to the PHP page that updates the DB.
EDIT 1:
You can use ul/li instead of table/tr/td. You can also use class=car, class=make, etc. instead of data-col='car', data-col='make', etc. if you are using an older version of jQuery that does not support HTML5-style data- attributes.
EDIT 2: Complete solution
Change your while loop to this:
while ($row = mysql_fetch_assoc($result)) {
echo '<li class="editable" data-id="'.$row['id'].'" data-col="car">'.$row['car'].'</li>';
echo '<li class="editable" data-id="'.$row['id'].'" data-col="make">'.$row['make'].'</li>';
}
As you can see we store the database row ID in data-id and the database column name in data-col.
Now with this setup you would only need one handler:
function replaceHTML()
{
var rowId = $(this).data('id');
var colName = $(this).data('col');
var buff = $(this).html().replace(/"/g, """); // Are you sure you need this?
$(this).addClass("noPad")
.html("<form><input type=\"text\" name=\"" + colName + "\" value=\"" + buff + "\" /> <input type=\"text\" name=\"buffer\" value=\"" + buff + "\" /><input type=\"text\" name=\"id\" value=\"" + rowId + "\" /></form>Save changes Discard changes")
.unbind('dblclick', replaceHTML);
}
$(".editable").bind("dblclick", replaceHTML);
Finally, always try to write readable code! Please! :)
EDIT 3: JSFiddle
Please see this live solution. It shows how you can get the column name and row ID. You just have to adopt it to work with your PHP script.

Javascript passing parameters from form to function --> update DB

can anyone help please. I have a form generated dynamically, when it is submitted it should send values to a function and add them back to a database. I'm having real problems getting this to work, it seems simple: 1. Form --> 2. submit received --> 3. update function. The code is below:
Dynamically generated form:
function renderResults(tx, rs) {
e = $('#status');
e.html("");
for(var i=0; i < rs.rows.length; i++) {
r = rs.rows.item(i);
var f = $("<form>" +
"<input type=\"hidden\" name=\"rowId\" value=\"" + r.id + "\" />" +
"<input value=\"" + r.name + "\" name=\"name\" />" +
"<input value=\"" + r.amount + "\" name=\"amount\" />" +
"<input type=\"submit\" />" +
"</form>");
e.append("id: " + r.id, f);
f.submit(function(e)
{
updateRecord(this.rowId.value, this.name.value, this.amount.value);
});
}
}
Handles the form submit and passes to function:
$('#theform').submit(function() {
updateRecord($('#thename').val(), $('#theamount').val());
});
Function to set values:
function updateRecord(id, name, amount) {
db.transaction(function(tx) {
tx.executeSql('UPDATE groupOne SET (name, amount) VALUES (?, ?) WHERE id=?', [name, amount, id], renderRecords);
});
}
The DB update code has the id set to 4 as a test just to see if anything happens to row 4, i've been fiddling with this line for ages to get it to work. If i set it to:
tx.executeSql('UPDATE groupOne SET name = 4, amount = 5 WHERE id=?', [id], renderRecords);
it will work with set values, but can someone help me get the form values into it please.
You are missing the row id in your jQuery selector. You are passing:
$('#thename').val();
But your field has an id of "thename" + r["id"]:
'<input type="text" ... id="thename' + r['id'] + '" ...>'
You need to get your value by passing the full input id.
$("#thename" + rowId).val();
Edit: Looking more closely at your code, I notice you are creating multiple forms with the same id, which is invalid html. I see now that you've got one form per record. Good, just lose the id from the form and its inputs. Instead, use names for the inputs.
var f = $("<form>" +
"<input type=\"hidden\" name=\"rowId\" value=\"" + r.id + "\" />" +
"<input name=\"name\" />" +
"<input name=\"amount\" />" +
"<input type=\"submit\" />" +
"</form>");
e.append("id: " + r.id, f);
f.submit(function(e)
{
updateRecord(this.rowId.value, this.name.value, this.amount.value);
});

Categories

Resources