I have the following code to check a checkbox as soon as the user types something in the textbox. This works fine for a single text box.
function activateCheckbox() {
if (document.myForm.box1.checked == false) {
document.myForm.box1.checked = true;
}
}
<tr>
<td><input type="text" id="mySearch1" name="mySearch1" size="40" onkeypress="activateCheckbox()"/></td>
<td><input type="checkBox" id="box1" name="box1"/></td>
</tr>
However suppose there are more than one text boxes with a checkbox against each one and I want that only the corresponding checkbox should be checked. I modified the above code as shown below by passing a parameter to the function but it's not working, because "document.myForm.id.checked" doesn't work as it accepts the checkbox name instead of "id". Please suggest if there are better alternatives or how do I modify my code to make it working?
function activateCheckbox(id) {
if (document.myForm.id.checked == false) {
document.myForm.id.checked = true;
}
}
<tr>
<td><input type="text" id="mySearch1" name="mySearch1" size="40" onkeypress="activateCheckbox('box1')"/></td>
<td><input type="checkBox" id="box1" name="box1"/></td>
</tr>
<tr>
<td><input type="text" id="mySearch2" name="mySearch2" size="40" onkeypress="activateCheckbox('box2')"/></td>
<td><input type="checkBox" id="box2" name="box2"/></td>
</tr>
<tr>
<td><input type="text" id="mySearch3" name="mySearch3" size="40" onkeypress="activateCheckbox('box3')"/></td>
<td><input type="checkBox" id="box3" name="box3"/></td>
</tr>
You have a couple of options. You can do:
function activateCheckbox(id) {
if (document.myForm[id].checked == false) {
document.myForm[id].checked = true;
}
}
...or personally, I think this is a bit more clear:
function activateCheckbox(id) {
var checkbox = document.getElementById(id);
if (! checkbox.checked) {
checkbox.checked = true;
}
}
The first approach works because in JavaScript obj.someProperty means the same semantically as obj["someProperty"]. So if you have a variable that stores the name of the property you want to access, you can always do obj[name] to access the property.
The second approach is just finding the checkbox in the DOM by its id. It seems cleaner to me, since you are setting the id of each checkbox anyways and since you called your variable "id".
Also note that your if statement is superfluous. The checked attribute will only ever be true or false (you can subvert this by storing other things there, but that's a completely separate topic). So setting it to true whenever it is false is logically equivalent to always setting it to true, and you can implement your handler function with a single line, like:
function activateCheckbox(id) {
document.getElementById(id).checked = true;
}
.id means literally the id property. In case you want to have it set dynamically, use the [] notation:
function activateCheckbox(id) {
if (document.myForm[id].checked == false) {
document.myForm[id].checked = true;
}
}
['test'] means .test, ['abc'] means .abc. So [id] means: access the property that id has as its value.
I advise you to use a JQuery (www.jquery.com). By adding one code line
<script src="http://code.jquery.com/jquery-1.6.2.min.js" type="text/javascript"></script>
you can solve your problem problem by write just one code line:
$('#checkboxId').attr('checked','checked');
or you can check
$('input[type="checkbox"]').attr('checked','checked');
or unckeck
$('input[type="checkbox"]').attr('checked','');
all checkboxes in you document
Related
I don't really know how to word this question so I am sorry if this seems a bit ambiguous. I have a situation where I am generating a bunch of check boxes within a cfloop. Each checkbox has the same class name of check, but they represent a value within a database. Originally I was hoping that I can just check to see if the checked property exists using jQuery, but that doesn't work as I'd hoped. The issue it brings is that if there is one checkbox that is checked and if I check or uncheck a different checkbox the class still returns a true value which makes sense logically.
Here is the ColdFusion which sets the checked value and the loop which generates the html:
<cfloop>
<cfif ContainsSic.HasSiC EQ 1 >
<cfset CheckedResult = "checked=""checked""" >
<cfelse>
<cfset CheckedResult = "" >
</cfif>
<cfoutput>
<tr>
<td align="center">#Passed_CustomerName#</td>
<td align="center">#Passed_LotNumber#</td>
<td align="center">#Passed_SubLot#</td>
<td align="center">#Passed_CarbonAvg#</td>
<td align="center"><input type="button" onclick="location.href='';" value="Amend" /></td>
<td align="center"><input type="checkbox" onclick="ajax(#Passed_CustomerID#, #Passed_LotNumber#, #Passed_SubLot#)" #CheckedResult#/></td>
<td align="center">Red Tag Page</td>
</tr>
</cfoutput>
</cfloop>
And here is the jQuery which handles the ajax call and the checked value:
function ajax(CustomerID, LotNumber, SubLot) {
if ($("input:checkbox").is(":checked")) {
var Checked = true;
}
else {
var Checked = false;
}
var passed_data = {
method: 'UpdateHasSiC',
CustomerID : CustomerID,
LotNumber: LotNumber,
SubLot: SubLot,
Checked: Checked
}
console.log(passed_data);
$.ajax({
type: 'POST',
url: 'LecoXMLRead_Ajax.cfc',
data: passed_data,
dataType: 'JSON',
success: function(data) {
},
error: function(e){
}
})
}
The workflow behind this is when the page loads, it grabs values from a database which determines whether or not the checkbox should be selected. It writes the values given from the database into rows with its designated checked or unchecked checkbox. The user should then be able to alter the checkbox and when doing so, update the value within the database with a 1 or 0. 1 representing it was checked of course.
I hope this makes sense, I can provide clarification or whatever else is needed.
Thank you
You can add custom data attribute at checkbox and then used that attribute value to pick checkbox
<input type="checkbox" data-customerId="#Passed_CustomerID#" onclick="ajax(#Passed_CustomerID#, #Passed_LotNumber#, #Passed_SubLot#)" #CheckedResult#/>
In function you can use that customer id to identify that specific checkbox.
I am considering customer id as unique value.
function ajax(CustomerID, LotNumber, SubLot) {
if ( $('[data-customerId="'+CustomerID+'"]:checkbox').is(":checked")) {
var Checked = true;
}
else {
var Checked = false;
}
}
Get rid of the onclick action, and change your markup/js to:
HTML:
<input type="checkbox" data-customerid="#Passed_CustomerID#" data-lotnumber="#Passed_LotNumber#" data-sublot="#Passed_SubLot#" #CheckedResult# />
JS:
<script>
$(document).ready(function () {
$('input[type="checkbox"][data-customerid]').on('click', function(e) {
ajax($(this).data('customerid'), $(this).data('lotnumber'), $(this).data('sublot'), $(this).is(':checked'));
});
});
</script>
Then you would add the checked argument to your ajax function.
(I didn't test this, so look for syntax errors. LMK and I'll correct if found.)
There is a table with some input and select fields in a row. I want to check if all input and select fields of an row have a value. This is how I would think to do that, but do I have to use closest and find? I think this is not optimal.
HTML
<table>
<tr>
<td><select><option></option><option>Select anything</option></td>
<td><input type="text" name="field1"></td>
<td><input type="text" name="field2"></td>
</tr>
<tr>
<td><select><option></option><option>Select something</option></td>
<td><input type="text" name="field3"></td>
<td><input type="text" name="field4"></td>
</tr>
</table>
JS
'change #table input, change #table select': function(event) {
var $this = $(event.currentTarget),
$row = $this.closest('tr'),
$elements = $row.find('input, select');
var empty = false;
$elements.each(function(index) {
if (!$(this).val()) empty = true;
});
if (empty)
console.log('some value is missing')
else {
console.log('valide');
// do something with values
}
}
There are really two questions here:
Most optimal method to select all inputs in a table row
Ensure all the inputs have a value
For the first question there is a subliminal side to that. Ensure that it IS an input and then select it within the context of the current row of the changed input.
First off, jQuery uses the Sizzle (https://sizzlejs.com/) engine under the covers for selection. One thing to be aware of is the "right to left" processing of the selector string by that engine.
Thus the most optimal selection is somewhat browser specific but the fastest way to select is an ID followed in modern browsers by a class. Some older browsers do not select by class as well but let's leave that for your research.
Selection: Bad way to do stuff
So given that, let's look at a complex selector that you might use:
'div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td select, div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td input'
First off DO NOT USE THAT. Now to explore why not: Remember we talked about the "right to left" selector processing? For discussion let us narrow down out selector to the last part:
"div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td input"
What this does then in starting on the right:
"find all the inputs in the DOM",
use that list of those inputs, "find all the inputs in a td element
use those td elements, find all those in a tr
find all those tr in a .mytableclass element
find all those in an element with an id of mytable (remember this ID MUST be unique)
Now keep going, find that single element id that is a table element
That is an immediate child of an element with classmytablecontainer
That is a DIV element div
That is a child of an element with class mycontainer
That is a DIV element div
Whew that's a lot of work there. BUT we are NOT DONE! We have to do the same thing for the OTHER selector in there.
Selection: Better way to do stuff
NOW let's do this better; first off let's leverage the modern browser class selector by adding a class to all our "scoped" inputs - things we want to check for entry.
<input class="myinput" />
It does really need a type="" attribute but ignore that for now. Let's use that.
$('#mytable').find('.myinput');
What this does is:
Select the element with ID of 'mytable' which is the FASTEST selector in all browsers; we have already eliminated those 47 other tables in our DOM.
Find all the elements with a class of class="myinput"; within that table; in modern browsers this is also very fast
DONE. WOW! that was SO much less work.
Side note on the .find() instead of "#mytable input"
Remember our right to left once again? Find all inputs in the DOM, then narrow to those inputs we found that are in that table NO STOP THAT right now.
Or (better likely) "#mytable .myinput"
SO our "rules" of selecting a group of elements are:
Use an ID to limit scope to some container if at all possible
Use the ID by itself NOT part of a more complex selector
FIND elements within that limited scope (by class if we can)
Use classes as modern browsers have great selection optimization on that.
When you start to put a space " " or ">" in a selector be smart, would a .find() or .children() be better? In a small DOM perhaps maintenance might be easier, but also which is easier to understand in 4 years?
Second question: not specific but still there
You cannot simply globally use !$(this).val() for inputs.
For a check box that is invalid. What about radio buttons? What about that <input type="button" > someone adds to the row later? UGH.
SO simply add a class to all "inputs" you DO wish to validate and select by those:
<input type="text" class="validateMe" />
<select class="validateMe" >...
Side note you MIGHT want to sniff the TYPE of the input and validate based upon that: How to get input type using jquery?
EDIT: Keep in mind your validation input MIGHT have a "true/false" value so then this might fail: !$(this).val() (radio buttons, checkbox come to mind here)
Some code and markup:
<table id="mytable">
<tr>
<td>
<select class="myinput">
<option></option>
<option>Select anything</option>
</select>
</td>
<td>
<input class="myinput" type="text" name="field1" />
</td>
<td>
<input class="myinput" type="text" name="field2" />
</td>
</tr>
<tr>
<td>
<select class="myinput">
<option></option>
<option>Select something</option>
</select>
</td>
<td>
<input class="myinput" type="text" name="field3" />
</td>
<td>
<input class="myinput" type="text" name="field4" />
</td>
</tr>
</table>
<div id="results">
</div>
probably NOT want a global (namespace the "selectors")
var selectors = '.myinput';
$('#mytable').on('change', selectors, function(event) {
var $this = $(event.currentTarget),
$row = $this.closest('tr'),
$elements = $row.find(selectors);
var $filledElements = $elements.filter(function(index) {
return $(this).val() || this.checked;
});
var hasEmpty = $filledElements.length !== $elements.length
var rowIndex = $row.index();
$('#results').append("Row:" + rowIndex + " has " + $filledElements.length + ' of ' + $elements.length + ' and shows ' + hasEmpty + '<br />');
if (hasEmpty)
console.log('some value is missing');
else {
console.log('valide');
// do something with values
}
});
AND something to play with: https://jsfiddle.net/MarkSchultheiss/fqadx7c0/
If you're only selecting on particular element with knowing which parent to select with, you should try using .filter() to filter out only element that did't have a value like following :
$('button').click(function() {
var h = $('table :input').filter(function() {
return $(this).val() == "" && $(this);
}).length;
alert(h);
});
DEMO
I did this plunk
https://plnkr.co/edit/q3iXSbvVWEQdLSR57nEi
$(document).ready(function() {
$('button').click(function() {
var table = $('table');
var rows = table.find('tr');
var error = 0;
for (i = 0; i < rows.length; i++) {
var cell = rows.eq(i).find('td');
for (a = 0; a < cell.length; a++) {
var input = cell.eq(a).find(':input');
if (input.val() === "") {
input.css("border", "solid 1px red");
error++;
} else {
input.css("border", "solid 1px rgb(169, 169, 169)");
}
}
}
if (error > 0){
alert('Errors in the form!')
return false;
} else {
alert('Form Ok!')
return true;
}
})
})
Simple Jquery validation, searching all the inputs (including selects), if it's null, increment the error counter and change class. If the error counter is > 0, alert error and return false;
Maybe isn't the best solution, but it sure can help get started.
I'm trying to build a function using the .each() method in jQuery that scans for empty input fields, highlights them in red, and then provides an alert message to let the user know what needs to change.
Here's my sample html:
<tr>
<td><input type="number" class="amount required" name="amount" ></td>
<td><input type="number" class="carrier required" name="carrier" ></td>
<td><input type="number" class="kilo required" name="kilo" ></td>
</tr>
<button type="submit" class="analyze">Analyze</button>
Here's the function to loop through the table data and add the CSS:
$(".analyze").click(function() {
$(".required").each(function() {
if ($(this).val() === "") {
$(this).parents("td").addClass("redClass");
alert("Looks like some of the fields aren't filled out correctly. They're highlighted in red.");
}
});
});
The issue is that the code goes through the array one-by-one and creates an alert message for every single empty cell. Ideally it'd add .redClass to the empty fields all at once and just present one alert message at the end if any are empty.
Per my comment:
$(".analyze").click(function() {
var counter = 0;
$(".required").each(function() {
if ($(this).val() === "") {
$(this).parents("td").addClass("redClass");
counter++;
}
});
if(counter > 0){
alert("Looks like some of the fields aren't filled out correctly. They're highlighted in red.");
}
});
Try this:
$(".analyze").click(function () {
var req = $(".required");
req.each(function (i) {
if ($(this).val() === "") {
$(this).parent("td").addClass("redClass");
req.error = true;
}
});
if (req.error) {
alert("Looks like some of the fields aren't filled out correctly. They're highlighted in red."); }
});
.redClass {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<input type="number" class="amount required" name="amount">
</td>
<td>
<input type="number" class="carrier required" name="carrier">
</td>
<td>
<input type="number" class="kilo required" name="kilo">
</td>
</tr>
</table>
<button type="submit" class="analyze">Analyze</button>
Here's a fiddle http://jsfiddle.net/cga65pLh/1/
$(".analyze").click(function() {
//on click of element with class "analyze"
$(".required").removeClass("redClass"); //remove redClass from all elements
//remove redClass from all elements with class required
x=true;
//turn x to true so that we know a pop up hasn't occurred yet
$(".required").each(function() {
// loop through each element with the class required
if ($(this).val() === "") {
// if the value is empty
$(this).addClass("redClass");
//add redClass to the element, turning the background of the element red.
(x) ?
//check if x is true (this is a ternary statement)
// if x is true do the following:
(alert("Looks like some of the fields aren't filled out correctly. They're highlighted in red."),
x=false)
:
// if x is false simply return false and don't do anything
false;
}
});
});
What this does is, on click, it removes redClass from any element with class "required" this is so that it starts fresh each time the button is pressed. It then turns the value x to true. This way we can keep track of if there's an alert message or not. a.e if it's true there's been no alert.
For each element with class "required" we check if value is "". If it is, we apply the class "redClass" which turns the current box red and we check if x is true. If x is true we display an alert and turn x to false so that no other pop ups occur.
background
I have a table grid of checkboxes, grouped by name, and each checkbox contains a time value. An example of the HTML:
<td><input type="checkbox" name="tuesday[]" value="10am"></td>
<td><input type="checkbox" name="tuesday[]" value="11am"></td>
<td><input type="checkbox" name="tuesday[]" value="12pm"></td>
<td><input type="checkbox" name="tuesday[]" value="1pm"></td>
<td><input type="checkbox" name="tuesday[]" value="2pm"></td>
<td><input type="checkbox" name="tuesday[]" value="3pm"></td>
<td><input type="checkbox" name="tuesday[]" value="4pm"></td>
<td><input type="checkbox" name="tuesday[]" value="5pm"></td>
<td><input type="checkbox" name="tuesday[]" value="6pm"></td>
<td><input type="checkbox" name="tuesday[]" value="7pm"></td>
When the form is submitted, the values are POSTed how I want them to be; all the checked times are in the tuesday[] array.
problem
I want to do some client-side validation with jQuery. I want to check that at least one checkbox is checked.
I have tried storing it into a var like so:
var availTuesday = $("input:checkbox[name='tuesday']:checked");
But when I do so and the console.log(availTuesday);, nothing is shown (regardless on if something is checked or not). I have also tried console.log(availTuesday.serialize());
Question:
how can I retrieve the user-checked values for the tuesday[] checkbox group, as well as for the other dates (wednesday[], thursday[], etc)?
Thank you.
The selector is not correct, change it to:
var $tuesday = $("input[type=checkbox][name='tuesday[]']:checked");
For getting the values you can use .map() method which returns an array:
if ($tuesday.length) {
// Getting values of the checked checkboxes
var values = $tuesday.map(function(){
return this.value;
}).get();
// ...
} else {
// There is no checked `day[]` checkbox
}
In case that you have other similar set of checkboxes you can use an array:
var days = ['days', 'in', 'a', 'week'],
values = {},
errors = [],
$checkboxes = $("input[type=checkbox]");
$.each(days, function(_, day) {
var $set = $checkboxes.filter('[name="'+day+'[]"]:checked');
if ($set.length) {
values[day] = $set.map(function() {
return this.value;
}).get();
} else {
// There is no checked `day[]` checkbox
errors.push(day);
}
});
if (errors.length) {
// console.log('Please check at least one hour in ' + errors.join(', ') + ' days ...');
} else {
// console.log(values);
}
You can try
var availTuesday = [];
$('input[type=checkbox][name="tuesday[]"]:checked').each(function() {
availTuesday.push($(this).val());
});
JSFiddle
If you want the actual value
var values = $("input[type=checkbox][name='tuesday[]']:checked").map(function() {
return this.value;
}).get();
If all you are really after is if any boxes are selected you can do the following:
if($('input[type="checkbox"][name="tuesday[]"]:checked').length) {
...
} else {
...
}
The length value is a property of the jQuery object (superset of DOM object) that specifies how many nodes matched the selector. In this case, if you check the length and the value is 0, no :checked checkboxes with the name tuesday[] exist (i.e. the user has not checked any boxes so display your validation message). It's quick and dirty validation. If you're looking to retrieve the values, the multitude of other answers are probably better.
You'll need to fix the selector to match the name, as others have mentioned.
If you just want to test that one is checked, you can go straight to a boolean, like this:
var availTuesday = $("input:checkbox[name='tuesday[]']:checked").length > 0;
Again in problem
Actually I have following jsp code in which I have few text boxes which I have made disabled by using property disabled="disabled".
Now problem is each record that I will get from database in each text box using iterator which iterates values added from databse in arraylist.If database return more than one record then using that check box I can enable textboxes but if databse resultset return only one record then I am unable to enable textboxes and throws following ERROR:
Message: 'document.f1.chk' is null or not an object
Line: 26
Char: 10
Code: 0
<script type="text/javascript">
function enable()
{
for(i=0;i<document.preapp.chk.length;i++)
{
if(document.preapp.chk[i].checked==true)
{
document.preapp.id[i].disabled=false;
document.preapp.vname[i].disabled=false;
document.preapp.comp[i].disabled=false;
document.preapp.cont[i].disabled=false;
document.preapp.wtm[i].disabled=false;
document.preapp.intime[i].disabled=false;
}
else
if(document.preapp.chk[i].checked==false)
{
document.preapp.id[i].disabled=true;
document.preapp.vname[i].disabled=true;
document.preapp.comp[i].disabled=true;
document.preapp.cont[i].disabled=true;
document.preapp.wtm[i].disabled=true;
document.preapp.intime[i].disabled=true;
}
}
}
</script>
<CENTER>Back to Search</CENTER>
<form method="post" action="" name="preapp">
<table border="1" align="center" width="100%">
<%
Iterator itr;
try
{
ArrayList al=(ArrayList)request.getAttribute("sq");
int i=0;
for(itr=al.iterator();itr.hasNext();)
{
i=i+1;
%>
<tr>
<td></td><td><input type="checkbox" name="chk" onclick="enable(this)" ></td></tr></tr>
<tr><td>Id</td><td><input type="text" name="id" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td>Visitor Name</td><td><input type="text" name="vname" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td>Comapny</td><td><input type="text" name="comp" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td>Contact</td><td><input type="text" name="cont" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td>Meeting Scheduled With</td><td><input type="text" name="wtm" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td>Entry Made On</td><td><input type="text" name="intime" value="<%=itr.next()%>" disabled="disabled" size="100%"></td></tr>
<tr><td></td>
</tr>
<tr>
</tr>
<%
}
}
catch(Exception e)
{
e.printStackTrace();
System.out.println(e.getMessage());
}
%>
How Do solve this problem? please help me out!
It works like charm, except in the case you have only one TR block.
In that case, the .chk has no "length" attribute!
You should consider that case separately:
function enable()
{
if(document.preapp.chk.length == null)
{
disabledState = !document.preapp.chk.checked
document.preapp.id.disabled=disabledState;
document.preapp.vname.disabled=disabledState;
document.preapp.comp.disabled=disabledState;
document.preapp.cont.disabled=disabledState;
document.preapp.wtm.disabled=disabledState;
document.preapp.intime.disabled=disabledState;
} else {
for(i=0;i<document.preapp.chk.length;i++)
{
disabledState = !document.preapp.chk[i].checked
document.preapp.id[i].disabled=disabledState;
document.preapp.vname[i].disabled=disabledState;
document.preapp.comp[i].disabled=disabledState;
document.preapp.cont[i].disabled=disabledState;
document.preapp.wtm[i].disabled=disabledState;
document.preapp.intime[i].disabled=disabledState;
}
}
}
a couple of suggesions: instead of setting the properties of elements to true or false, try using the setAttribute and removeAttribute methods:
document.preapp.id[i].disabled=true;
//replace with:
document.preapp.id[i].setAttribute('disabled','disabled');
//to enable:
document.preapp.id[i].removeAttribute('disabled');
The way you're doing things works fine 99.9% of the time. I haven't seen the above code fail, though (I have had issues with the true/false approach).
Next: the error message you post, contains very useful information: check line 26 of your original code. 'document.f1.chk' is nowhere to be found in your snippet, so I can't check for typo's or other possible problems in your code there.
You're passing the element to the enable function, too. Why then, are you looping through all elements, checking all elems on the page?
function enable(elem)
{
var i = document.preapp.indexOf(elem);//
if (elem.checked === true)
{
document.preapp.id[i].removeAttribute('disabled');
//...
}
//functions have properties, exploit them:
if (typeof enable.previous === 'undefined' || enable.previous === i)
{
enable.previous = i;
return true;
}
document.preapp.id[enable.previous].setAttribute('disabled','disabled');
//...
enable.previous = i;
}
The last section of the enable function stores the index of the checkbox that was just clicked, so that when the enable function has been clicked before, there's no need to loop through all elements again: enable.previous holds the index of the checkbox that was clicked last time.
Lastly: there are no opening or closing bracket for the else block, and there is an extra line of whitespace. Else works fine without brackets, but only branches one line. In your code, this line is blank: either remove the else, or add brackets.
PS: Perhaps a fiddle would help to get a clear view of the situation?
As Teejay pointed out, in case of unique names, the elements are referenced directly, instead of a nodesList being passed.