Hi, I'm having some trouble with a portion of code I am writing. The code works the first time round, but then becomes unresponsive on one part. What I am trying to have is the following... Enter a value in the input field, check box gets ticked. Untick checkbox. clears value in the input field Tick checkbox , sets a value in the input field Untick checkbox. clears value in the input field Enter a value in the input field, check box gets ticked. Untick checkbox. clears value in the input field Tick checkbox , sets a value in the input field Untick checkbox. clears value in the input field But this is whats happening ... Enter a value in the input field, check box gets ticked. - working Untick checkbox. clears value in the input field - working Tick checkbox , sets a value in the input field - working Untick checkbox. clears value in the input field - working Enter a value in the input field, check box gets ticked. - not working Tick checkbox , sets a value in the input field - working Untick checkbox. clears value in the input field - working I cant work out why it becomes unresponsive. Probably something I am over looking. Any help appreciated. <div class="fixed"> <ul> <li class="list-item"> <input type="checkbox" name="cb" id ="cb"> </li> <li class="list-item"> <label>Job#: </label><input type="number" name="jobNumber" id ="j" min = "1"></li> </ul> </div> <script> // looks for value in job# input document.getElementById('j').addEventListener('change', recInput); function recInput() { // sets CB[0] to checked document.getElementById('cb').setAttribute('checked', 'checked'); } // looks for checkbox uncheck var checkbox = document.getElementById('cb'); document.getElementById('cb').addEventListener('click', function() { if (this.checked) { document.getElementById('j').value="1"; // console.log("Checkbox is checked.."); } else { //console.log("Clear J[0] input value here"); document.getElementById('j').value=null; } }); </script> HTML:
so, we're not going to shoot the messenger, right?! What we have is an infuriating bug that's been around for years. See: https://bugzilla.mozilla.org/show_bug.cgi?id=327020 See it in action at https://jsfiddle.net/d5ncyjgo/ var checkbox = document.getElementById('cb'); var job = document.getElementById('job'); // looks for value in job# input function recInput(e) { // sets CB[0] to checked console.log('changed input value to '+this.value); console.log('checkbox: ' + (checkbox.checked?'checked':'not')); if (!checkbox.checked){ //https://bugzilla.mozilla.org/show_bug.cgi?id=327020 //checkbox.setAttribute('checked', 'checked'); checkbox.click(); } } // looks for checkbox uncheck function recCheck(e) { console.log(this.checked); console.log(job.value); if (this.checked) { if (job.value === "") { job.value = "1"; } // console.log("Checkbox is checked.."); } else { //console.log("Clear J[0] input value here"); job.value = ''; } } job.addEventListener('change', recInput); checkbox.addEventListener('click', recCheck); Code (JavaScript):
Thank you very much. I was tearing what little hair I have left out trying to understand why it doesn't work. You efforts in tickling / rewriting the code for an inexperienced wanna be coder are very much appreciated.
Gotta help the "West Islanders" before the mouse plague gets them What else can go wrong this decade?
True that. Could I be so bold as to further my request? If I wanted to have multiple "checkbox/input" combinations, what would be the best way to handle those. Would I need a separate script for each?
Thanks. I found this (which I think you responded with a suggestion) which I think has given me an idea, but happy to look at lots of ways to do things. Its how we learn... https://forums.digitalpoint.com/threads/trying-to-use-same-javascript-multiple-times-on-same-page.2865083/
so that didn't happen last night but here you go. I can see from your code that you know that the "name" of an input can be an array and I've used that. ID, though, can't. We also have a handy little dataset so we can add whatever extra info we need and that makes life so much easier. We know what got clicked or changed so we can use "this" and then by using the index value we can quickly get to the other element. var checkbox = document.getElementById('cb'+ this.dataset.idx); New fiddle at https://jsfiddle.net/itamer/hqsoz6d4/19/ <form id='frmFixed'> <div class="fixed"> <ul> <li class="list-item"> <input type="checkbox" name="cb[1]" id="cb1" data-idx=1> </li> <li class="list-item"> <label for='job1'>Job#: </label><input type="number" name="jobNumber[1]" id="job1" min="1" data-idx=1></li> <li class="list-item"> <input type="checkbox" name="cb[2]" id="cb2" data-idx=2> </li> <li class="list-item"> <label for='job2'>Job#: </label><input type="number" name="jobNumber[2]" id="job2" min="1" data-idx=2></li> <li class="list-item"> <input type="checkbox" name="cb[3]" id="cb3" data-idx=3> </li> <li class="list-item"> <label for='job3'>Job#: </label><input type="number" name="jobNumber[3]" id="job3" min="1" data-idx=3></li> </ul> </div> </form> HTML: // looks for value in job# input var frmFixed = document.getElementById('frmFixed'); function recInput(e) { console.log('input idx: ' + this.dataset.idx); var checkbox = document.getElementById('cb'+ this.dataset.idx); if (!checkbox.checked) { checkbox.click(); } } // looks for checkbox uncheck function recCheck(e) { console.log('checkbox idx: ' + this.dataset.idx); var job = document.getElementById('job' + this.dataset.idx); if (this.checked) { if (job.value === "") { job.value = "1"; } } else { job.value = ''; } } frmFixed.querySelectorAll('input[type=checkbox]').forEach(item => { item.addEventListener('click', recCheck); }); frmFixed.querySelectorAll('input[type=number]').forEach(item => { item.addEventListener('change', recInput); }); Code (JavaScript): Now, the HTML probably looks a bit clunky but if you're using PHP to generate the form you might have something like this snippet where $max is the number of rows you want. <form id='frmFixed'> <div class="fixed"> <ul> <?PHP for ($i = 0; $i <= $max; $i++){ echo "<li class='list-item'> <input type='checkbox' name='cb[{$i}]' id='cb{$i}' data-idx={$i}> </li> <li class='list-item'> <label for='job{$i}'>Job#: </label><input type='number' name='jobNumber[{$i}]' id='job{$i}' min='1' data-idx={$i}></li>"; }?> </ul> </div> </form> PHP:
Hi, So Ive been playing with this code and am seeing that I should have learnt javascript a long time ago. I discovered php years ago but never really worried about doing much manipulation on the client side, I would just let php handle it, reloading the page etc. I have this working really well now, with all the variables being set correctly when I post the form. I thought it would be good to be able to add some user defined items to the list, and have almost got it working. Anyway, in my learning I have confused myself completely and can not for the life of me work out how to get my "add" lines to drop into the div I created at the bottom. I guess it is because they are all having the same ID. I could create ne ID's, but when doing that, the code to populate the fields doesnt work. I also need to work out how to set the attributes of each of the inputs so that they too get passed correctly when the form is posted. Guess I would need to pass the value of $i to the javascript and then write that back out. Could you give me a pointer into what I am not seeing please? <html> <? $Part = array( "Bolt", "Nut", "Washer", "Rail" , "Bearing" ); $count=count($Part); ?> <head> <style> .container-2{ display:flex; } .container-1 div{ border:1px solid #ccc; padding:10px; font-size: 20pt } .container-2 div{ border:1px solid #ccc; padding:10px; font-size: 20pt } .box-1{ flex:.1; } .box-2{ flex:.3; } .box-3{ flex:.6; } .box-4{ flex:.3; } .box-5{ flex:1; } </style> </head> <body> <form method="POST" id='frmFixed'> <div id = "list"> <?PHP $i=0; while($i < $count) { echo" <div id='items' class='container-2' >"; echo " <div class='box-1'> <input type='checkbox' name='cb[{$i}]' id='cb{$i}' data-idx={$i}> </div> <div class='box-2'> <label for='job{$i}'>Job#: </label><input type='number' name='jobNumber[{$i}]' id='job{$i}' min='1' max = '99' data-idx={$i} > </div> <div class='box-3'><label for='part{$i}'>$Part[$i]</label> </div> <input name='part[{$i}]' type='hidden' value='$Part[$i]'> <div class='box-4'><label for='Qty{$i}'>Qty: </label><input type='number' name='Qty[{$i}]' id='Qty{$i}' min='1' data-idx={$i} > </div> <div class='box-5'><label for='Comment{$i}'>Comment: </label><input type='text' name='Comment[{$i}]' id='Comment{$i}' data-idx={$i} > </div> "; $i++; echo" </div>"; } ?> </div> </form> <form id="addForm" > <input type="submit" value="Add"> </form> <script> // add new line var form = document.getElementById('addForm'); var itemList = document.getElementById('items'); // Form submit event form.addEventListener('submit', addItem); // Delete event itemList.addEventListener('click', removeItem); // Add item function addItem(e){ e.preventDefault(); // Create new div for row var rowDiv = document.createElement("div"); rowDiv.id = "items"; rowDiv.className = "container-2"; // add the new div into the DOM document.getElementById("list").appendChild(rowDiv); // Create new <div> (for check box) var newDiv = document.createElement("div"); //Create <class= 'box-1'> newDiv.className = "box-1"; //Create checkbox var checkbox = document.createElement('input'); checkbox.type = "checkbox"; checkbox.name = "name"; checkbox.id = "id"; checkbox.idx = "idx"; // Add check box to <div> newDiv.appendChild((checkbox)); // add the newly created element and its content into div created (rowDiv) in the DOM document.getElementById("items").appendChild(newDiv); // Create new <div> (for Job Number) var newDiv = document.createElement("div"); //Create <class= 'box-2'> newDiv.className = "box-2"; //Create Text (same as what is in main table) var text = document.createTextNode('Job#'); text.style='font-size: 20pt'; // Add text to <div> newDiv.appendChild((text)); //Create input for Job# var input = document.createElement('input'); input.type = "number"; input.name = "name"; input.value = "value"; input.id = "id"; // Add Input to <div> newDiv.appendChild((input)); // add the newly created element and its content into the DOM document.getElementById("items").appendChild(newDiv); // Create new <div> (for Part Description) var newDiv = document.createElement("div"); //Create <class= 'box-3'> newDiv.className = "box-3"; //Create input for Description var input = document.createElement('input'); input.type = "text"; input.name = "name"; input.placeholder = "Enter Part Description"; input.id = "id"; // Add input to <div> newDiv.appendChild((input)); // add the newly created element and its content into the DOM document.getElementById("items").appendChild(newDiv); // Create new <div> (for Qty) var newDiv = document.createElement("div"); //Create <class= 'box-4'> newDiv.className = "box-4"; var text = document.createTextNode('Qty'); text.style='font-size: 20pt'; // Add text to <div> newDiv.appendChild((text)); var input = document.createElement('input'); input.type = "number"; input.name = "name"; input.value = "value"; input.id = "id"; // Add inputto <div> newDiv.appendChild((input)); // add the newly created element and its content into the DOM document.getElementById("items").appendChild(newDiv); // Create new <div> (for Comment) var newDiv = document.createElement("div"); //Create <class= 'box-5'> newDiv.className = "box-5"; var text = document.createTextNode('Comment: '); text.style='font-size: 20pt'; // Add text to <div> newDiv.appendChild((text)); var input = document.createElement('input'); input.type = "text"; input.name = "name"; input.placeholder = "Enter a comment"; input.id = "id"; // Add inputto <div> newDiv.appendChild((input)); // add the newly created element and its content into the DOM document.getElementById("items").appendChild(newDiv); // Create del button element var deleteBtn = document.createElement('button'); // Append text node deleteBtn.appendChild(document.createTextNode('Delete')); // Append button newDiv.appendChild(deleteBtn); itemList.appendChild(newDiv); } // Remove item function removeItem(e){ if(e.target.classList.contains('delete')){ var li = e.target.parentElement; itemList.removeChild(li); } } // Auto fill form. // If check box is selected, set QTY to 1 and job to 1 // If Qty is set, check checkbox and and set job to one // If Job is set, check checkbox and set qty to one // if checkbox is unchecked, clear all var frmFixed = document.getElementById('frmFixed'); function recInput(e) { console.log('input idx: ' + this.dataset.idx); var checkbox = document.getElementById('cb'+ this.dataset.idx); if (!checkbox.checked) { checkbox.click(); } } // looks for checkbox uncheck function recCheck(e) { console.log('checkbox idx: ' + this.dataset.idx); var job = document.getElementById('job' + this.dataset.idx); if (this.checked) { if (job.value === "") { job.value++; } } else { job.value = ''; } var Qty = document.getElementById('Qty' + this.dataset.idx); if (this.checked) { if (Qty.value === "") { Qty.value = "1"; } } else { Qty.value = ''; } } frmFixed.querySelectorAll('input[type=checkbox]').forEach(item => { item.addEventListener('click', recCheck); }); frmFixed.querySelectorAll('input[type=number]').forEach(item => { item.addEventListener('change', recInput); }); </script> </body> </html> Code (markup):
ok, taking a wade through this Some little things This code closes the div and orphans the input - move the </div> to the end of the line <div class='box-3'><label for='part{$i}'>$Part[$i]</label> </div> <input name='part[{$i}]' type='hidden' value='$Part[$i]'> PHP: Don't have two forms, put the add button into the main form <form id="addForm" > <input type="submit" value="Add"> </form> HTML: This might be picky & old school but don't use reserved words in your code. Instead of var form, use var frmFixed, var frm or another appropriate abbreviation var form = document.getElementById('addForm'); Code (JavaScript): You could move your index number up to either of these depending on how you're going to use it. "list" would just have the total count, "items" would have the index number. I've also given "items" a number so that the id is unique <div id="list"> <div id='items1' class='container-2'> HTML: I've changed the start of your javascript and have a fiddle going but it's untested and incomplete, I'm out of time, sorry : https://jsfiddle.net/itamer/hqsoz6d4/37/ // Add item function addItem(e) { e.preventDefault(); // itemList is the list div, not the item div itemList.dataset.idx++; var idx = itemList.dataset.idx; // Create new div for row var rowDiv = document.createElement("div"); rowDiv.id = "items" + idx; rowDiv.className = "container-2"; // add the new div into the DOM itemList.appendChild(rowDiv); Code (JavaScript):
Hi Sarah, So I had a fiddle with your fiddle and then created a fiddle of my own. https://jsfiddle.net/jon30442/m4qj1c6y/26/ I've got it working except with a few issues. All the div ID's are being created with unique ID's, all the attributes of the inputs are being set. The first three entries are populated from a SQL database, but for this I have made them static. When I add a line - works. If I add some data to the inputs, and then uncheck the line should clear - not working, it seems that adventlistener to clear these is not working on the added lines. The delete button is working like the add button, but throwing an error that its unable to remove the child. The "Submit List" button is used to send the list of parts to the next PHP file to process the data. This is working, I've just removed the link. I'm sure this is something simple that I have overlooked, Could I ask you to run your eye over it for me please.
I'm typing this as I go so it may be a bit disjointed. ref: https://jsfiddle.net/itamer/L7241jbg/14/ First up, to set the index number using your notation it needs to use the dataset notation // your code // the quote marks around "idx" give the index a string rather than the value of the variable input.idx = "idx"; // this works input.dataset.idx = idx; Code (JavaScript): I'm pretty sure this is brain fade, when you've been looking at your own code too long //so this: input.id = "job: " + idx; //should be this: input.id = "job" + idx; Code (JavaScript): and with those small changes your code is good to go! and a final wee note don't mix size measurements. You should be using em, or perhaps px, definitely not pt. Pick one and stick to it.
Hi Sarah, Yes definite brain fade, been looking at this so hard trying to find ways to solve issues! I've changed those index set ups, but its still not deleting the line, nor is it clearing the values when checkbox is unchecked. The "delete" button is working like a close of the "Add" and returns "<a class='gotoLine' href='#322:14'>322:14</a> Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node." in the console.
I forgot to mention that I added listeners to the new item, they're not automatically added. Your add button was technically a submit button, I've changed it to a standard button - and I've done the same for the delete button - and I've given it an index deleteBtn.type = 'button'; Code (JavaScript): because I've put the delete event listener onto the actual delete button the removeItem code can now look like this: // Remove item function removeItem(e) { let idx = e.target.dataset.idx; let del = document.getElementById("items" + idx); itemList.removeChild(del); } Code (JavaScript): ref: https://jsfiddle.net/itamer/L7241jbg/33/
The add / delete is working fantastic now. Thanks. The checkbox is still throwing an error tho, when it adds and when you change the value of Job or qty. Any ideas?
try this function recInput(e) { console.log('input idx: ' + e.target.dataset.idx); var checkbox = document.getElementById('cb' + e.target.dataset.idx); if (!checkbox.checked) { checkbox.click(); } } Code (JavaScript):
Yeah, I can make that work. Thanks for all your help. I've stumbled across another issue tho. If I add in another input field, it throws an error in the console. Doesn't seem to affect anything tho that I can see. Looks like it fires off 'recInput(e)' when you enter anything, but because that div doesn't have an idx it cant create the variables properly. this is what I added; <form method="POST" id='frmFixed'> <!-- NEW INPUT --> <div class= "ro-block"> <label>RO#</label> <input type="number" name="RONumber" required> </div> <!-- /NEW INPUT --> <div id="list" data-idx=3> <!-- get data-idx from number of common items in database --> <div id='items1' class='container-2'> <div class='box-1'> <input type='checkbox' name='cb[1]' id='cb1' data-idx='1'> </div> Code (markup): If its Ok to leave, there I will run with that and ignore it.
The simplest thing would be to check that the input has a idx value (or a class) and only check the values then. A more complex answer would be to make sure the listener is only listening to the fields inside an item row.