Javascript function in PHP generated Table only works in Row 1 - javascript

I have a PHP generated table that shows x number of rows based upon the number of product that is expected for that particular order. The idea is that a user can input an order number and the script will validate the input text against what is expected a return a Pass or Fail status.
This works for row 1, but after that it will not validate any of the other rows.
Reading about I am pretty sure it is due to duplicate id's, so i created a auto increment row field in the database to serve as the id. However it is beyond my skill to set the id as the row number and then validate against the order number.
Table Code:
if (sqlsrv_num_rows($getres) > 0) {
echo '<table cellpadding="0" cellspacing="0" class="db-table">';
echo '<tr><th>Row</th><th>Works Order</th><th>Scan</th></tr>';
echo 'T-Clip Scan: <br/>';
echo '<br/>';
while ($add_info = sqlsrv_fetch_array($getres)){
$row = ($add_info['row']);
$worksorder = ($add_info['id']);
print ("<tr> <td/> $row <td/> $worksorder
<td/>
<input id= 'worksorder' value='' />
<p id='TR'></p>
<script>
document.getElementById('worksorder').onblur = function() {myFunction()};
function myFunction() {
var worksorder, test;
worksorder = document.getElementById('worksorder').value;
test = (worksorder == '".$_SESSION["worksorder"]."') ? 'PASS':'FAIL';
document.getElementById('TR').innerHTML = test;
}
</script>
</tr>");
}
Screenshot of issue
Any help it getting it to work for all rows is appreciated,
Thanks

The problem is likely because you're using creating <input id='worksorder'> and using document.getElementById('worksorder') to reference it within a loop.
HTML IDs are supposed to be unique on the page, so getElementById will only ever return a single element, that being the first element in the code that has the named ID.
If you want to do this in a loop, then you need to make sure that the ID for each element you generate is unique. Typically this would be done by adding the row ID to the generated HTML ID.
eg <input id= 'worksorder_{$add_info['id']}'> or similar, and then reference that in the JS code.
Alternatively, use an HTML class instead of an ID, since class names do not need to be unique, and then write your JS code to use document.querySelector() to query by classname instead of getElemenetById(). If you do it that way, then the JS code doesn't need to be in the loop, as it will be run once and apply to all the matching elements in one go.

You don't have to use a separate script for every row. You can create a single script to hande all the rows.
Firstly, provide ids to the <tr> tag and the <input> tag to receive the values and add an onblur listener. You can use the autoincrementing column value for the ids that you get from database.
e.g.
echo "<tr> <td/> $row<td/> $worksorder <td/>
<input id='".$id."' value='' /><p id='TR_'".$id."' onblur='myFunction(this)'></p>";
Also, add the onblur listener and pass the object to myFunction().
Then add a single myFunction() at the end.
<script>
function myFunction(param) {
var worksorder, test, id;
worksorder = param.value;
id = param.id;
console.log("order " +worksorder + ' '+id);
test = (worksorder == '".$_SESSION["worksorder"]."') ? 'PASS':'FAIL';
document.getElementById('TR_'+id).innerHTML = test;
};
</script>
This will handle all the rows for you. I hope it helps you.
Working JS fiddle

You are setting all the input fields with the same id. Html cannot handle same ids. You should either use incremental ids or use classes instead of ids, and adapt the JS function to use parameters, so not to have a JS function in every row. One function is enough and you can call it with the row number as parameter

Related

javascript get element by ID within ID

I would like to calculate the total price of the if check box is checked by using JavaScript
I'm not allow to separate the id to 2 section of by adding div
for example.
<form id="bookingForm">
<section id = "checkcost">
<h2>Total cost</h2>
Total <input type="text" name="total" value="$0.00" size="10" readonly />
</section>
</form>
First, i use this method get the id
var frm = document.getElementById('bookingForm')
i m trying to do by using the following code but this is not the correct method
frm.checkcost.total = calculate()
Since the input area to shows the total cost is inside the id="bookingForm", how should i display the total cost once the check box is checked??
ps: here is the link i had try but it didn't work, and now i'm trying other method
onclick in php echo with error invalid unexpected token
If there's only one field named total in the form, you don't need to worry about the section at all:
var frm = document.getElementById('bookingForm');
frm.total = calculate();
or
document.querySelector("#bookingForm [name=total]").value = calculate();
If you have multiple fields named total, then you just use the ID of the section:
document.querySelector("#checkcost [name=total]").value = calculate();
// ----------------------^
document.querySelector finds the first element that matches a given CSS selector. You can use the full power of CSS to find elements in the document. There's also document.querySelectorAll which finds a list of matching elements. Finally, individual elements also have both methods, which look only within those elements. So for instance, we could also do this:
var frm = document.getElementById('bookingForm');
frm.querySelector("#checkcost [name=total]").value = calculate();
(But that's just an example, not a suggestion; it's more round-about than necessary.)

How to uniquely identify HTML contents of list elements(li) that is generated in a loop?

I am auto generating a unordered list by putting one list element in a php loop, like this:
while($row = $result->fetch_assoc()) {
echo "". $row["Header"]." ";
}
$conn->close();
Lets say there are 10 rows in a table (table xyz contains 2 columns: id, header) where you pull the 'id' and 'header' from the database where the headers are shown as a list in an html page as a navigation bar (or menu).
How can I uniquely identify(find the id) when someone clicks on one of the list element and execute some code based on their selection?
(for example: when someone click one of the list item, I need to be able to send the id of this selected list item to a different php page and execute some code that is custom to that particular id/index.)
Note: The index/id of each list item cannot be manually typed in since the list is generated using a loop which pulls the headers from a database to full each list item as you can find above.
Please don't give a solution based on Jquery or other frameworks. Only simple concise php or javascript code please.
Javascript Solution :
You should attach click event to every element with class list-group-item, using getElementsByClassName() that will return an array of all objects with given class name so you could use for to loop through everyone of them and associate it with function you want to trigger on click (in my example this function called my_function), check example bellow :
function my_function() {
//get the index of clicked li
};
var class_names= document.getElementsByClassName("list-group-item");
for (var i = 0; i < class_names.length; i++) {
class_names[i].addEventListener('click', my_function, false);
}
I suggest to add data attribute called index like #dandavis mentioned in comment, your code will be :
$i=0;
while($row = $result->fetch_assoc()) {
echo "<a data-index='".$i."' href='ArticleViewPage.php' class='list-group-item col-sm'>". $row["Header"]."</a> ";
$i++;
}
And you can get the index in your function using getAttribute() :
function my_function() {
var current_item_index = this.getAttribute('data-index');
};
Hope this helps.
add a variable like $count=0; before the loop, and print it within link 'href="ArticleViewPage.php?id=". $count ."";' then $count++; last statement in loop
You can do that by generating all of the links in an element that you have an id on (or any query selector) so that you can access it with JavaScript.
For example, if this is my generated HTML:
<div id="links">
First
Second
Third
Fourth
Fifth
</div>
I can use the following JavaScript to add a data attribute that will be the index of it, and add the click event listener and get access to that index:
enumerateLinks();
function enumerateLinks() {
var links = document.getElementById('links');
Array.prototype.slice.call(links.children)
.forEach(function (link, index) {
link.setAttribute('data-index', index);
link.addEventListener('click', handleClick);
});
}
function handleClick(evt) {
evt.preventDefault(); // Prevents navigation
var clickIndex = evt.target.dataset.index;
alert('Click index: ' + clickIndex);
}
Here is a CodePen.
You could also add a class to target each link as another person suggested but you would have to make sure that class wasn't used elsewhere.
You don't need any Javascript to accomplish this. If you want to pass the id from your query to ArticleViewPage.php, you can just append it as the query string to the href in your link.
while($row = $result->fetch_assoc()) {
echo '<a href="ArticleViewPage.php?id=' .$row['id'] .'" class="list-group-item col-sm">'
.$row["Header"] ."</a> ";
}
Then in ArticleViewPage.php the value will be available in $_GET['id'].
Simplest solution will be just include the id and write inline code like
while($row = $result->fetch_assoc()) {
echo "". $row["id"]." ";
}
Define a doAction function and you get the database id of the row

dynamically created form depending on <select> does not work

I'm developing a website which must display particular forms for various products depending on the value that the user selects (in <select>) - so a number various forms are created dynamically in a loop by means of a javascript function (buildform() ). The code does not work, e.g. the forms are not created/appended to the wrappers. I narrowed down the problem where i think the problem relates to a different values for the jquery selectors/div-id's (#ecorpproductwrapper"+ecorp_eprodselectid).
When I use (just as a test) #ecorpproductwrapper" (without the variable ecorp_eprodselectid; see also in code below under ALTERNATIVE WORKS) the code works fine, e.g. the forms are built. I checked by means of the console that the ecorpproductwrapper"+ecorp_eprodselectid values are the same for the div-id's and jquery selectors, so I dont understand what goes wrong?
Pls see the simplified code below:
for(var i=0;i<5;i==){
var ecorp_eprodselectid; //will have various values
//function to build form depending on selected value in <select class= eprodtype"+ecorp_eprodselectid >
$(".eprodtype"+ecorp_eprodselectid).focus(function () {
var previous;
// Store the current value on focus and on change
previous = this.value; //old select value
}).change(function() {
var optionsform = buildform(this.value);
console.log('append form'+optionsform);
//NEXT 2 lines doe NOT WORK
$("#ecorpproductwrapper"+ecorp_eprodselectid).children().remove(); //remove previous form
$("#ecorpproductwrapper"+ecorp_eprodselectid).append(optionsform);
//ALTERNATIVE works: $('#ecorpproductwrapper').children().remove(); //remove previous tariif struct form
//ALTERNATIVE works: $('#ecorpproductwrapper').append(optionsform);
var str = "#ecorpproductwrapper"+ecorp_eprodselectid;
console.log('STRING ECORP PRODUCT APPEND: '+str);
console.log('change eprod val: '+this.value);
previous = this.value;
});//$("").focus(function () {
}//for i
//function to build form
var buildform = function(ecorp_eproductid) {
//some code here
//NEXT LINE does not work:
form += '<td> <div id="ecorpproductwrapper'+ ecorp_eprodselectid+'"> </div> </td> </tr>'; //cell with wrapper for ecorp product info
//ALTERNATIVE WORKS: form += '<td> <div id="ecorpproductwrapper"> </div> </td> </tr>'; //cell with wrapper for ecorp product info
//some code here; returns form
}//function buildform
I think you forgot to add ecorp_eprodselectid in your function.
var buildform = function(ecorp_eprodselectid ) {
Few things we assume concerning given text above:
You know this.value works
console.log shows optionsform have HTML that it should have. Not said in OP but if not, the function does not work. function seems to be missing already var buildform = function(someVar) as noted by buysDB
As I cannot see your code, I would try first clear everything 100% by chaning this:
$("#ecorpproductwrapper"+ecorp_eprodselectid).children().remove();
to:
$("#ecorpproductwrapper"+ecorp_eprodselectid).html("");
Then:
$("#ecorpproductwrapper"+ecorp_eprodselectid).html(optionsform);
No need for append if you have no intention to keep anything in DIV.
If you have text also in (#ecorpproductwrapper"+ecorp_eprodselectid) which is why you use children(), consider selecting the DIV that can be cleared.
If that still does not work, something is left out that needs consideration.

Dynamically generated form field loses value when new field is added

I am generating a dynamic fieldset with javascript. For adding fields, I use the following function (this function actually adds more than one field)
//add test
function addTest() {
var location = document.getElementById('addTestLocation');
var num = document.getElementById('addTestCount');
var newnum = (document.getElementById('addTestCount').value -1)+ 2;
num.value = newnum;
location.innerHTML += "<div id='testContainer_"+newnum+"'><label for='test_"+newnum+"'>Test name: </label><input type='text' name='test_"+newnum+"' id='test_"+newnum+"'/> <a href='javascript: removeTest("+newnum+")'>- Remove test</a><br/><br/><span id='addObjectLocation'></span><br/><select id='select_"+newnum+"'><option>True or False</option><option>Single choice</option><option>Multiple choice</option><option>Short definition</option><option>Fill in the blanks</option></select><input type='hidden' id='addObjectCount' value='0'/> <a href='javascript:addObject();'>+ add question</a><br/><br/><hr/><br/></div>";
}
I use innerHTML instead of append because there is a lot of code i'd have to append, the markup is so much shorter this way.
Now, my problem is that whenever I add (or remove) a field, all the data from the other dynamically generated data would be lost. How can I fix this? Saving the value and then adding it to every field would be again, very complicated in my case. Any ideas?
Setting the innerHTML of the parent element causes the entire content to be serialized and then re-parsed, losing all the values in the process (the values aren't serialized back into value attributes). I can think of three workarounds:
Create your outer div (the testContainer) using createElement, set its innerHTML and then append the div into the parent element
Create all the elements using DOM. It's trivial to create a bunch of helper functions to make creating the elements easier.
Use jQuery which does all this for you: $(location).append('html goes here');

How do I get the cell value from a table using JavaScript?

<td> <input type="button" name="buton" id="x2" value="2" onclick="swap(id)";/> </td>
This is the button in a table when it is clicked it's id is passed as parameter to function "swap" as below:
function swap(x)
{
document.write(x);
}
It is successful in getting the id but not the value;when i am trying in this way:
function swap(x)
{
document.write(x.value);
}
The output is shown as undefined. Can you tell me how to get the cell value using the cell id?
I believe that what you are looking for is document.getElementById(x).value;
Also if you want the button just pass this to the function like this:
<button onclick="foo(this)"/>
I guess use jQuery for the purpose,it allows to traverse in DOM very easily.
<table id="mytable">
<tr><th>Customer Id</th><th>Result</th></tr>
<tr><td>123</td><td></td></tr>
<tr><td>456</td><td></td></tr>
<tr><td>789</td><td></td></tr>
</table>
If you can, it might be worth using a class attribute on the TD containing the customer ID so you can write:
$('#mytable tr').each(function() {
var customerId = $(this).find(".customerIDCell").html();
}
Essentially this is the same as the other solutions (possibly because I copypasted), but has the advantage that you won't need to change the structure of your code if you move around the columns, or even put the customer ID into a < span >, provided you keep the class attribute with it.
By the way, I think you could do it in one selector:
$('#mytable .customerIDCell').each(function()
{
alert($(this).html());
});
If that makes things easier
Code will be more or less more reliable on cross bowser issue
z = document.getElementById(id); first, and then you should be able to use z.firstChild.textContent
You need to get the cell using var cell = document.getElementById(x). Then use cell.firstChild.nodeValue.
function swap(x)
{
var cell = document.getElementById(x);
document.write(cell.firstChild.nodeValue);
}
EDIT: Tested this on both FF3.5 and IE8 and it works.
If you are passing the id of the element you might want to use document.getElementById(x) to access it.

Categories