I have this code and I want to disable all the inputs when the checkbox is not checked.
<tr class="select_tr">
<td><?= ucwords($food_name); ?></td>
<td class="form-group text-center">
<input value="<?= $order_food_id; ?>" type="checkbox" name="select_food[]" checked>
</td>
<td class="form-group">
<input value="<?= $order_food_total_members; ?>" type="text" name="total_members[]" class="form-control" placeholder="Total Members">
</td>
<td class="form-group ">
<input value="<?= $order_food_date; ?>" type="date" name="food_date" class="form-control">
</td>
<td class="form-group ">
<input value="<?= $order_food_time; ?>" type="time" name="food_time" class="form-control">
</td>
</tr>
I have used this code but it is disabling only the first input and I don't know how to taget the remaining two.
$('input[type="checkbox"]').click(function () {
if(!this.checked) {
$(this).closest('td').next('td').find('input:text').attr('disabled' , true);
} else {
$(this).closest('td').next('td').find('input:text').attr('disabled' , false);
}
});
Whatever you have done is partially correct, what you have done is you have targetted with $(this) so obviously it will take the checkbox input and will find the closest 'td' and disable only the first input tag because it is the one which is closest rather you can do this by targetting the element which has this form-control class and disable the event so it will apply to all the input field which has this class which is indirectly the other three input field.
$('input[type="checkbox"]').click(function () {
if(!this.checked) {
$('.form-control').attr('disabled' , true);
} else {
$('.form-control').attr('disabled' , false);
}
});
Or the second choice is you can use this each statement to update the input element.
You should be able to do something like this - get all of the elements and then disable. You'll have to do it onclick of the checkbox.
var inputs, index;
inputs = document.getElementsByTagName('input'); // get all of the input elements
for (index = 0; index < inputs.length; ++index) { // loop through them
inputs[index].disabled = true; // disable them
}
The issue is that you are only selecting a single element:
$(this).closest('td').next('td').find('input:text')
This will find the closest <td> ancestor element to the checkbox, then select the next sibling <td> element, and finally get the descendants of that <td> element that matches the selector input:text. This will result in a single element because only one of your inputs is of type "text", and you are only selecting inside of a single <td>.
What you want to do instead is select all of the input elements that are not checkboxes in the table row <tr> (class .select_tr):
$(this).closest('.select_tr').find('input:not([type=checkbox])')
This will select the parent <tr> with class .select_tr and then select all input children of it that do not have type=checkbox.
Example:
$('.select_tr input:checkbox').change(function() {
$(this).closest('.select_tr').find('input:not([type=checkbox])').prop("disabled", !this.checked);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr class="select_tr">
<td>
<?= ucwords($food_name); ?>
</td>
<td class="form-group text-center">
<input value="<?= $order_food_id; ?>" type="checkbox" name="select_food[]" checked>
</td>
<td class="form-group">
<input value="<?= $order_food_total_members; ?>" type="text" name="total_members[]" class="form-control" placeholder="Total Members">
</td>
<td class="form-group ">
<input value="<?= $order_food_date; ?>" type="date" name="food_date" class="form-control">
</td>
<td class="form-group ">
<input value="<?= $order_food_time; ?>" type="time" name="food_time" class="form-control">
</td>
</tr>
</table>
Your code isn't selecting all the inputs. Use nextAll() for selecting each td after the closest('td').
$('input[type="checkbox"]').click(function(){
if(!this.checked){
$(this).closest('td').nextAll('td').find('input').attr('disabled' , true);
}else{
$(this).closest('td').nextAll('td').find('input').attr('disabled' , false);
}
});
JQuery.next() is used for selecting the first matched element after the selected element
So, your code is just affecting the first next only.
JQuery.nextAll() is used for select the next all matched elements after the selected element.
So, using nextAll() instead of next() may solve your problem.
You can try something like this:
var elemCheckbox = document.querySelectorAll('[type="checkbox"]')[0];
var elemInputs = document.querySelectorAll('.form-control');
function toggleInputs() {
// https://stackoverflow.com/questions/9887360/check-if-checkbox-is-checked-javascript#answer-9887439
var shallDisable = !elemCheckbox.checked;
// https://css-tricks.com/snippets/javascript/loop-queryselectorall-matches/
for (i = 0, len = elemInputs.length; i < len; ++i) {
// https://stackoverflow.com/questions/7526601/setattributedisabled-false-changes-editable-attribute-to-false#answer-7526666
elemInputs[i].disabled = shallDisable;
}
}
elemCheckbox.addEventListener("click", toggleInputs);
Find the explanation in the comments.
This example won’t disable the checkbox (if you meant it like that).
I would recommend to add an id to the checkbox. This will guarantee an explicit element selection.
You can then get like document.getElementById("<yourUniqueId>");
Related
For an application I am working on, I want to autocomplete a field using the input of the other field. My form will contain several pairs of inputs, which causes the problem for me to only change one specific input field.
$(function () {
$(".master").change(function () {
word = $(this).val();
$(this).parents('tr').find(".slave").val(word);
});
});
To add extra fields to the form, the script below is used.
$(document).ready(function() {
var max_fields = 1000; //maximum input boxes allowed
var wrapper = $(".input_fields_wrap"); //Fields wrapper
var add_button = $(".add_field_button"); //Add button ID
var x = 1; //initlal text box count
$(add_button).click(function(e){ //on add input button click
e.preventDefault();
if(x < max_fields){ //max input box allowed
x++; //text box increment
$(wrapper).append('<tr><td><div class="form-group"><input type="text" class="master" name="or['+x+']"></div></td><td> </td><td><div class="form-group"><input type="text" class="slave" name="tr['+x+']"></div></td></tr>'); //add input box
}
});
});
This is the form I'm using. This is one of the 100 rows in this form.
<form method="POST">
<table width="100%" class="input_fields_wrap">
<tr>
<td width="48%">
<div class="form-group">
<select id="original" name="original" class="form-control">
<option value="nederlands">Nederlands</option>
</select>
</div>
</td>
<td width="4%"></td>
<td width="48%">
<div class="form-group">
<select id="translated" name="translated" class="form-control">
<option value="frans">Frans</option>
</select>
</div>
</td>
</tr>
<tr>
<td>
<div class="form-group"><input type="text" class="master" name="or[0]"></div>
</td>
<td> </td>
<td>
<div class="form-group"><input type="text" class="slave" name="tr[0]"></div>
</td>
</tr>
</table>
<button type="submit" id="save" class="btn btn-success pull-right">Opslaan</button>
</form>
So just to be clear, I want to change the value of the "translation" input according to the value of the input in the same row. As my form contains so many rows, I don't know how to change that specific input according to the input in the same table row. Thanks in advance!
Here you go, I had to take out the ajax call but if you need help adding it back in just let me know.
I changed your html a bit by using classes instead of id's and this is the relevant js.
$(function () {
$("table").on('change', '.master', function () {
word = $(this).val();
$(this).parents('tr').find(".slave").val(word);
});
});
https://jsfiddle.net/6LaLm33t/4/
What you can do is get the parent, and then find the #translation of that parent. original and translation should probably be classes.
var word = '';
$(function () {
$(".original").change(function () {
word = $(this).val();
var arr;
$.ajax({ type: "POST", async: false, url: 'wordsuggestion' + word, success: function(data) {
arr = data;
$(this).parents('tr').find(".translation").val(arr);
}});
});
});
If you don't want (or can't, for some reason) to change HTML (you will have to do it, anyway, if there are multiple id's!), this is one of the ways to get desired result:
$('table tr td:first-child input').on("keyup", function() {
$(this).closest('tr').find('td:last-child input').val($(this).val());
});
So, if you have 3 cells (td's) in row, first selector will 'grab' first input, second one will find last/second input in the same row.
$('table tr td:first-child input').on("keyup", function() { //or desired event...change...input..
$(this).closest('tr').find('td:last-child input').val($(this).val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr><td>
<div class="form-group"><div class="ui-widget"><input type="text" id="original" class="form-control" name="or[0]"></div></div>
</td>
<td> </td>
<td>
<div class="form-group"><input type="text" id="translation" class="form-control tags" name="tr[0]"></div>
</td>
</tr>
<tr><td>
<div class="form-group"><div class="ui-widget"><input type="text" id="original" class="form-control" name="or[0]"></div></div>
</td>
<td> </td>
<td>
<div class="form-group"><input type="text" id="translation1" class="form-control tags" name="tr[0]"></div>
</td>
</tr>
<tr><td>
<div class="form-group"><div class="ui-widget"><input type="text" id="original1" class="form-control" name="or[0]"></div></div>
</td>
<td> </td>
<td>
<div class="form-group"><input type="text" id="translation2" class="form-control tags" name="tr[0]"></div>
</td>
</tr>
</table>
The autocomplete jquery shows list of all users in the database, when atleast 2 characters are entered in the textbox. The autocomplete is working on a normal input field, but when genereated through innerHTML it is not working.
The autocomplete is working on the following field:-
<input type="text" id="j_d_permit_by[]" name="j_d_permit_by[]" >
A click on the button will add other fields as well calling the addjobdesc function:-
<img src="images/add.png" width="12" height="12"> Add New Job Description<br />
The function:-
function addjobdesc() {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = '<table id="tblObs" name="tblObs" width="70%" bgcolor="#CCCCCC"><tr bordercolor="#FFFFFF">
<td colspan="5"><b>Job Description (Work Ppermit/ Activity)</b></td></tr>
<tr bgcolor="#33CC00">
<td ><center> <b>Exact Location</b> </center></td> <td><b><center>Permit Initiated By<br />/<br />Activity Supervised by</center></b></td>
<td><b><center>Permit Accepted By<br />/<br />aActivity Executor</center></b></td><td><b><center>For What Permit Issued</center></b></td>
<td><b><center>Observation</center></b></td></tr>
<tr><td><center><select name="s_area[]" id="s_area" onchange="addSubArea()">
<option value="0">Chose Sub Area</option></select></center></td>
<td><input type="text" id="j_d_permit_by_add" name="j_d_permit_by[]"></td>
<td><center><select id="j_d_accept_by[]" name="j_d_accept_by[]" ><option value="0">Select User</option><?php $users = getUserS();
while($usersss = mysql_fetch_array($users)){ ?>
<option value="<?php echo $usersss[0];?>"><?php echo $usersss[4]." ".$usersss[5]; ?></option>
<?php } ?>
</select></td>
<td><center><textarea name="permit_ref[]" cols="30"> </textarea></center></td>
<td><center><textarea name="obs_permit[]" id="obs_permit" cols="30"></textarea></center></td></tr></table><input class="submit" type="button" value="Remove" onclick="removeR0ow__(this)">';
<!--<input type="hidden" name="j_d_Location[]" id="j_d_Location" value="" /><input type="text" name="area_Location[]" id="area_Location" value="" readonly="readonly" />-->
document.getElementById('job_desc').appendChild(div);
jQuery(document).ready(function(){
$('#j_d_permit_by_add').autocomplete({
source: 'suggest_name.php',
minLength:2
});
});
var Max_Length = parseInt(document.getElementsByName('s_area[]').length)-1;
document.getElementsByName('s_area[]').item(Max_Length).innerHTML = '';
document.getElementsByName('s_area[]').item(Max_Length).innerHTML = document.getElementById('sarea_div').innerHTML;
}
I want the autcomplete to work on the generated j_d_permit_by[] field in the innerHTML.
Really appreciate your help.
You have bind the autocomplete in jQuery(document).ready but at that time there is no input exists with id =j_d_permit_by_add and hence the function is not bind to the input. You are generating the input dynamically so you have to bind autocomplete function in following way..
Try this to Bind the autocomplete function:
jQuery(document).ready(function(){
$(document).on('#j_d_permit_by_add', selector, function() {
$(this).autocomplete({
source: 'suggest_name.php',
minLength:2
});
});
});
You can refer https://stackoverflow.com/a/25114244/1659563
#Guruprasad is also right, you can bind the autocomplete function after the input is generated dynamically in function addjobdesc()
I am having trouble getting the text box nearest to my selected radio button. Here is what I have tried so far which keeps returning me 'undefined'.
HTML:
<fieldset class="capacity-field">
<legend>Capacity</legend>
<table style="margin-bottom: 20px">
<tr>
<td>
<input type="radio" name="capacity" value="raw" checked>Raw (TB):
</td>
<td>
<input type="text" name="raw-capacity" value="256" size="2"> TB
</td>
</tr>
<tr>
<td>
<input type="radio" name="capacity" value="usable">Usable (TB):
</td>
<td>
<input type="text" name="usable-capacity" value="161.28" size="2"> TB
</td>
</tr>
<tr>
<td>
<input type="radio" name="capacity" value="effective">Effective (TB):
</td>
<td>
<input type="text" name="effective-capacity" value="161.28" size="2"> TB
</td>
</tr>
</table>
JavaScript/jQuery
function cap_growth_update(toUpdate) {
var capacity = $("input[name='capacity']:checked").next("input[type='text']").val();
alert(capacity);
}
$(document).ready(function(){
cap_growth_update("T");
});
I know the value of toUpdate is arbitrary at this point, but it will be used as a selector later down the line and thus is included.
The jQuery next() function looks for a sibling element, but since these elements are separated under different td elements, you'll have to climb up the DOM:
$("input[name='capacity']:checked").closest("tr").find("input[type='text']").val();
So what it does, is to go to the closest parent, and then search for the children text input.
Try using parents() with eq() and find()
$("input[name='capacity']:checked").parents().eq(1).find("input[type='text']").val();
Note this is only a suggestion I make based on your markup, your goal could be achieved in other ways (jQuery is a rich library to traverse and manipulate DOM)
$(function() {
$("input:radio").click(function() {
if ($(this).is(":checked")) {
var value = $(this).closest("tr").find("input:text").val();
}
});
});
The code checks for a click event on a radio element then check if the element is checked, if it's checked then obtain the parent row of the radio element, find an input text inside the row an get the value of the input text the it saves the value at the var value, so you can do whatever with the value :)
Regards!
Let me explain:
I have a table form and some fields are required and I am trying to create custom validation.
example:
<table>
<tr>
<td class="required">Description</td>
<td>
<input id="input1" />
</td>
<td>Phone</td>
<td>
<input id="input2" />
</td>
</tr>
<tr>
<td class="required">Location</td>
<td>
<select id="select1"/>
</td>
<td>Email</td>
<td>
<input id="input3"/>
</td>
</tr>
</table>
What I wanna do is find all elements with class required
which is pretty easy using:
var requiredElements = document.querySelectorAll(".required");
And then I want to find their closest control element and check if it's value is empty. The problem is I don't know if it's gonna be input or select. I was thinking of using the .closest() function but it could lead to unwanted results if two different inputs are equally close to a required (like in the example above).
Any help would be much appreciated.
You can select a control regardless of type with jQuery by using any one of a number of selectors and combining it with one or more additional selectors.
In the code snippet you provide, the controls you want to select (input1 and select1) are child elements of a table cell element that is a sibling of the cell with the class "required", so we can build a selection thus:
$(".required + td").child
which breaks down as:
Find the elements with the "required" class applied to them.
This will give us the 2 table cells:
<td class="required">Description</td>
and
<td class="required">Location</td>
For each element returned by 1. use the "next adjacent" selector + with td to get the next table cell:
<td><input id="input1" /></td>
and
<td><select id="select1" /></td>
For each element returned by 2. get the child element:
<input id="input1" />
and
<select id="select1" />
There is also a jsFiddle to illustrate actions on the targets (change border to dark red).
Edit
This works because the layout in your snippet consistently places the elements you want to target in the same position relative to the element with your selection criteria. You must have some consistent way of finding elements that are not marked with a class/id otherwise you can't achieve your objective.
Although I like Raad's answer I'd like to post this answer to say what I did to solve my problem.
First of all I added a custom attribute labelFor to every label td with value equal to the id of it's corresponding input as follows:
<table>
<tr>
<td class="required" labelFor="input1">Description</td>
<td>
<input id="input1" />
</td>
<td labelFor="input2">Phone</td>
<td>
<input id="input2" />
</td>
</tr>
<tr>
<td class="required" labelFor="select1">Location</td>
<td>
<select id="select1"/>
</td>
<td labelFor="input3">Email</td>
<td>
<input id="input3"/>
</td>
</tr>
</table>
Then I used the following Validation function:
function validateForm () {
var self = this;
var validationPassed = true;
//First I will gather every .required element in an Array
var requiredTags = document.querySelectorAll(".required");
//Then I will loop through the array
for (var i = 0; i < requiredTags.length; i++) {
//Get value of attribute "labelFor" which would be the controlId that this label refers to
var controlId = $(requiredTags[i]).attr("labelFor");
//Then I use this to check if that control's value is empty.
if ($("#" + controlId).val() == ('' || null)) {
validationPassed = false;
}
}
if (!validationPassed) {
alert("Please fill all the required fields");
}
return validationPassed;
}
This way I check if all required fields are not empty and return true, or return false and an alert to warn user.
I find that the problem Raad described in his Edit is the main reason why this approach could be more useful. You don't have to worry if your input element is always in the same position relatively to your label td element.
Hoping someone can help me overcome my Javascript ignorance.
I've got a form that includes checkboxes and I've got a piece of JS that toggles selecting/deselecting all the boxes. And so far, it all works as expected.
The wrench in the works is that I've got multiple groups of checkboxes in this form and I would like to select/deselect by group, not all the checkboxes in the form. This is a sample of the php and html. As you can see, the form is in a table and there is a checkbox in the header row that performs the action. 'resources_req' is the name of the checkbox element in the form
<form method="post" name="add_reservation">
<?php for($x=0; $x<count($groups); $x++) : // make seperate display for each group ?>
<div class="group_<?php echo $group_label; ?>">
<table class="res">
<tr>
<!-- form: checkbox all -->
<?php if($make_res == 'enter') : // adds checkbox to check all ?>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<?php endif; ?>
<!-- end form: checkbox all -->
</tr>
...
foreach($resources as $resource) { // for each resource/laptop
$form_start = '<td>';
$form_start .= '<input type="checkbox" name="resources_req[]" value="'.$resource['id'].'"';
$form_start .= ' />';
$form_start .= '</td>';
}
...
</table>
</div>
<?php endfor; // loop for each group ?>
<input type="submit" name="add_reservation" value="Make this reservation" />
</form>
Here is the JS being called:
function toggle(source, element) {
checkboxes = document.getElementsByName(element);
for(var i in checkboxes)
checkboxes[i].checked = source.checked;
}
Best I can put together, the 'this' in the script call is referring to the form. I thought if maybe I put each of these groups in to their own div class, I could then somehow refer to just that but now I'm just lost. Any help or suggestions appreciated!
EDIT: I asked for suggestions and it's been suggested I post only the html:
<form method="post" name="add_reservation">
<div class="group_A">
<table>
<tr>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<th>Name</th>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="1" /></td>
<td>John</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="2" /></td>
<td>Bill</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="3" /></td>
<td>Fred</td>
</tr>
</table>
</div>
<div class="group_b">
<table>
<tr>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<th>Name</th>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="4" /></td>
<td>George</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="5" /></td>
<td>Tom</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="6" /></td>
<td>Raymons</td>
</tr>
</table>
</div>
<input type="submit" name="add_reservation" value="Make this reservation" />
</form>
I changed a few things:
First, instead of passing the value of name, I'm passing the tagName of 'input' instead.
<input type="checkbox" onClick="toggle(this, 'input')" />
Then in the toggle() function, I select the parentNode of the source element, and do a getElementsByTagName() so that I only get the input elements in the local div.
Also, I changed the for-in loop to a standard for loop, which is the proper type of loop to iterate over indexed elements. The for-in can actually give some problems.
function toggle(source, element) {
var checkboxes = source.parentNode.getElementsByTagName(element);
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Live Example: http://jsfiddle.net/37mT2/
Alternatives:
Instead of parentNode, select the ancestor <div> element by assigning it an ID, and passing it to your toggle() function.
<input type="checkbox" onClick="toggle(this, 'input', 'someUniqueId_1')" />
<input type="checkbox" onClick="toggle(this, 'input', 'someUniqueId_2')" />
function toggle(source, element, id) {
var checkboxes = document.getElementById( id ).getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Or you could traverse up the parent nodes until you reach your first <div> element:
<input type="checkbox" onClick="toggle(this, 'input')" />
function toggle(source, element) {
while( source && source = source.parentNode && source.nodeName.toLowerCase() === 'div' ) {
; // do nothing because the logic is all in the expression above
}
var checkboxes = source.getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Or you could give the <div> elements at that level a common class name and traverse up the parent nodes until you reach that class. In the code below, your <div> elements class is "someClassName":
<input type="checkbox" onClick="toggle(this, 'input')" />
function toggle(source, element) {
while( source && source = source.parentNode && source.className === 'someClassName' ) {
; // do nothing because the logic is all in the expression above
}
var checkboxes = source.getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
EDIT: Fixed a typo. I had getElementsById instead of getElementById.
Best I can put together, the 'this' in the script call is referring to the form. I thought if maybe I put each of these groups in to their own div class, I could then somehow refer to just that but now I'm just lost. Any help or suggestions appreciated!
http://jsfiddle.net/JG4uf/
JavaScript Loops: for...in vs for