I have a form that is a table built with php to pull a bunch of information from the database. In these, i have a checkbox that, when clicked, pulls the value of the estimatedCost and throws it into a JavaScript function that calculates it and keeps a running total of all the objects checked.
What i'm trying to do is create a check all and uncheck all option that will still pass the needed variables into the other javascript functions. Let me demonstrate with some code:
This draws the checkbox next to the title.
foreach($replace as $key => $value)
{
$jScript = 'onclick=\'calcTotals("'.$replace[$key]['estimatedCost'].'","'.$replace[$key]['optionItem_id_replaceOrRepair'].'","'.$replace[$key]['service_title'].'","'.$replace[$key]['maintenanceitem_id'].'");\'';
$checkbox = sprintf('<input type="checkBox" name="ids[]" id="%s" value="%s" %s>', $replace[$key]['maintenanceitem_id'], $replace[$key]['maintenanceitem_id'], $jScript).' ';
$replace[$key]['title'] = $checkbox.$replace[$key]['title'];
$replace[$key]['estimatedCost'] = $replace[$key]['estimatedCost'];
}
This is the current check all and uncheck all links:
echo '<a href="#" onClick=\'setCheckboxes("budgeting", true); return false;\'>Check All</a> | ';
echo '<a href="#" onClick=\'setCheckboxes("budgeting", false); return false;\'>Uncheck All</a>';
Now the current functions i have in javascript:
function setBudgetCheckboxes(the_form, do_check) {
var elts = (typeof(document.forms[the_form].elements['ids[]']) != 'undefined')
? document.forms[the_form].elements['ids[]']
: (typeof(document.forms[the_form].elements['ids[]']) != 'undefined')
? document.forms[the_form].elements['ids[]']
: document.forms[the_form].elements['ids[]'];
var elts_cnt = (typeof(elts.length) != 'undefined')
? elts.length
: 0;
if (elts_cnt) {
for (var i = 0; i < elts_cnt; i++) {
elts[i].checked = do_check;
var name = document.getElementById(name);
} // end for
} else {
elts.checked = do_check;
} // end if... else
return true;
}
And the other, which handles the clicks one at a time:
function calcTotals(amount, type, service, name) {
if(amount[0] == '$') {
amount = amount.substr(1,amount.length);
}
var id = type+"_"+service+"_selected";
var grand_id = "Grand_selected";
var grand_service_id = "Grand_"+service+"_selected";
var type_id = type+"_selected";
var checked = document.getElementById(name).checked;
var multiplier = -1;
if(checked) {
multiplier = 1;
}
amount = amount * multiplier;
addBudgetValue(amount, id);
addBudgetValue(amount, grand_id);
addBudgetValue(amount, grand_id+"_h");
addBudgetValue(amount, type_id);
addBudgetValue(amount, grand_service_id);
addBudgetValue(amount, grand_service_id+"_h");
}
function addBudgetValue(amount, id) {
var current_value = document.getElementById(id).innerHTML;
var curtmp = 0;
if(current_value == "$0") {
current_value = amount;
}
else {
curtmp = parseFloat(current_value.substr(1,current_value.length));
current_value = (curtmp+parseFloat(amount));
}
var newVal = "$"+Number(current_value).toFixed(2);
if(newVal == "$0.00")
newVal = "$0";
document.getElementById(id).innerHTML = newVal;
}
So the question is this: How do you get the check all to check all the boxes, and pass the information into the calcTotals function so that the values are added correctly?
Here's a jsfiddle that does what (I think) you're looking for: http://jsfiddle.net/kz9gU/1/
I'm using a custom data-* attribute to store the estimated cost (spec compliant as per HTML5), so it's defined in the checkboxes' tags. Each checkbox then calls an updateTotal() function when checked/unchecked, but doesn't pass any arguments. updateTotal() then loops through the checkboxes, reading each amount from the data-cost attribute, and displays the sum.
The check/uncheck functions then don't need to calculate any values; they just check/uncheck everything and call updateTotal() afterwards.
Edit: Heh, just realized you're not using jQuery. I'm just starting to take jQuery for granted, even though I actually don't use jQuery myself. What you see in the fiddle is probably the longest piece of jQuery-based JS, I've actually written :)
At any rate, it's almost always a good idea to use some sort of library to smooth out browser differences, and jQuery is king of the heap right now.
But library or not, the code should give you an idea of how you could proceed.
I hope I understood you currectly, you want a check/uncheck all feature? http://jetlogs.org/jquery/jquery_select_all.html after that get the checkbox array with php and pass the information, in PHP do a loop to check the values of the array and execute your statements.
Related
I tried to make a function that would generate a number of list items based on the user input from a prompt. It does not work although I believe it should.
I'm looking for an explanation of what's wrong with my code even if an alternate solution is also provided, if possible.
On the HTML side I have entered <div class="freshList"></div> in the body so that it can be picked up by the function and have the list placed in that location
Code is below:
function makeAList()
{
var freshList = document.getElementsByClassName("freshList");
var listLength = prompt("Enter number of list items");
var listString = "<ul>";
for (var i=0; i < listLength; i++)
{
listString+= "<li>"+"</li>"
}
listString += "</ul>"
document.innerHTML = listString;
}
makeAList();
// end code
Now the only way I have been able to get this to work was by accident when using the document.Write method at various points in the code to see what was working (I tried console log first which said that the function was called and the loop was proceeding but no output was coming so I switched to doc.write instead). I used document.Write(listString); and this was able to forcibly print the bullet points onto the screen but that is not my desire. I want it in the HTML not just printed on the screen (so that I can manipulate it with other functions I have made).
Altogether I wanted to make a series of functions to perform the following action: Ask if the user would like to make a new list. Call the makeNewList function which would prompt the user for the number of items. Then ask the user if they would like to edit the list and call the editList function with new prompts for each list item. Finally leaving an output of # of bullet points with user input on each point. I am sure this is a ridiculous idea that nobody would use but it was more a lesson for myself to try an idea I had rather than something functional. Full (attempted) code below:
function makeAList()
{
var freshList = document.getElementsByClassName("freshList");
var listLength = prompt("Enter number of list items");
var listString = "<ul>";
for (var i=0; i < listLength; i++)
{
listString+= "<li>"+"</li>"
}
listString += "</ul>"
document.innerHTML = listString;
}
makeAList();
function editAList() {
var list = document.getElementsByTagName("li");
for (var i = 0; i < list.length; i++)
{
list[i].innerHTML = prompt("Place list text below","")
}
function checkList(){
var resp1 = confirm("Would you like to make a new list?")
if(resp1 == true)
{
makeAList();
}
else
{
}
if(resp1 === false){
var resp2 = prompt("Would you like to edit an existing list instead?")
}
else if(resp2 === true){
editAList();
}
else{
alert("You have chosen not to make a new list or edit an existing one")
}
}
checkList();
My friend looked at my code and made some changes as well as detailed comments with the places I went wrong. For anyone who views this question in the future here is his response. All credit to him but I don't know his stack overflow handle to tag him.
Here is his js bin updated and heavily commented code
Code below in case that link dies:
// hi
// i've changed a few things, i've left the original code in comments (//)
function makeAList()
{
// what does the following code return? a single element? a list of elements?
//var freshList = document.getElementsByClassName("freshList")
var freshList = document.getElementById("freshList");
var listLength = prompt("Enter number of list items");
// var listString = "<ul>";
// you can create a 'ul' element and append the list string later
// https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append
var ul = document.createElement('ul');
ul.setAttribute('id', 'theList');
// there's an even shorter way of doing all this, but since you're starting out, we can save that for later
for (var i=0; i < listLength; i++)
{
//i would probably append here too, but just demonstrating insertAdjacent
ul.insertAdjacentHTML('beforeend', '<li></li>');
}
// document.innerHtml = listString //this was the reason why this function didn't work
// document has no inner html, instead, you want to append the list to the .freshList div that you created
// and then append that to the listOfLists that you queried
// the reason why we don't want to manually set innerHTML is because the DOM has to be reparsed and recreated
// every time innerHTML is set. if you have 1000s of lists, this would be extremely slow
// there are DOM apis that create and insert html elements much more faster and efficient (appendChild)
// if you want to create html elements as strings, as you have done previously, use insertAdjacentHTML: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
// it is faster and more efficient
freshList.appendChild(ul);
}
makeAList();
function editAList() {
var list = document.getElementsByTagName("li");
// there's a much more efficient way to do this, but keep this here for now
var insertText = function(i) {
var input = prompt("Place list text below", "");
console.log(i);
list[i].append(input);
}
for (var i = 0; i < list.length; i++)
{
// why would we use settimeout? http://www.w3schools.com/jsref/met_win_settimeout.asp
setTimeout(insertText.bind(null, i), 1000); // why bind? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
}
}
editAList();
// function checkList(){
// var resp1 = confirm("Would you like to make a new list?")
// if(resp1 == true)
// {
// makeAList();
// }
// else
// {
// }
// if(resp1 === false){
// var resp2 = prompt("Would you like to edit an existing list instead?")
// }
// else if(resp2 === true){
// editAList();
// }
// else{
// alert("You have chosen not to make a new list or edit an existing one")
// }
// }
// checkList();
I have some code here that will make validations of whether or not the input from a text box is NOT an empty string and isNaN. When i do these validations on amounts entered, i would like it to add them up.. however when a user does not enter anything in one or more amount fields the program should just add entered fields. But instead i get NaN showing in the total field.
link to full code: http://jsfiddle.net/KxNqQ/
var $ = function (id) {
return document.getElementById(id);
}
var calculateBills = function () {
var myErrorFlag = "N";
for (i = 1; i <= 4; i++) {
AmountNumber = 'amount' + i;
AmountValue = $(AmountNumber).value;
if (AmountValue != "" && isNaN(AmountValue)) {
$(AmountNumber).style.color = "red";
myErrorFlag = "Y";
} else {
$(AmountNumber).style.color = "black";
myErrorFlag = "N";
}
}
if (myErrorFlag != "Y") {
var Amount = 0;
for (i = 1; i <= 4; i++) {
Amount += parseInt($('amount' + i).value,10);
}
$('total').value = Amount;
}
}
var clearFields = function () {
for (i = 1; i <= 4; i++) {
itemName = 'item' + i;
$(itemName).value = "";
}
for (i = 1; i <= 4; i++) {
amountName = 'amount' + i;
$(amountName).value = "";
}
$('total').value = "";
}
window.onload = function () {
$("clearfields").onclick = clearFields;
$("addbills").onclick = calculateBills;
}
I think you've got your requirements a little bit confused, or at the very least I was confused by them. So in order to answer your question, I'm going to rephrase the requirements so I understand them better. This is a useful exercise that I try to do when I'm not 100% sure of the requirements; if I can't get the requirements right, what's to say I'll get the code right?
So the requirements – as I understand them – are:
Given each amount input
When the input has a value
And that value is a number
Then add the value to the total
And make the input color black
But if the input does not have a value
Or that value is not a number
Then make the input color red
Going through your code, I can see a number of problems with it. First, I noticed that both AmountNumber and AmountValue are global variables, because they were not declared local with the var keyword. So before fixing our code, let's change that. Let's also change the variable names to something that more accurately describe what they are, hopefully making the code easier to understand:
var input = $('amount' + i);
var value = input.value;
Now, note that I chose to store the element in the input variable. This is so we don't have to look it up multiple times within the loop. Looking things up in the DOM can be expensive so we'll want to keep it to a minimum. There are other was to look up elements as well, such as getElementsByClassName, querySelector and querySelectorAll; those are left as an exercise for the reader to research and evaluate.
Next, in each iteration of the loop, you check that AmountValue is not a string and simultaneously is not a number:
if (AmountValue != "" && isNaN(AmountValue)) {
This will be true so long as AmountValue is truthy (which is the case for non-empty strings) and so long as isNaN thinks it's a number (which is the case for strings that contain numbers.) It really is rather confusing; if I understand your code correctly this clause is there to check for invalid input and if it is true should mark the input field red and set a flag. I.e. this is the but clause in the aforementioned requirements.
Let's rewrite this to be the when clause instead, we'll take care of the but later. Before we do that, let's look at the myErrorFlag. It's used – I think – to see whether all input is well formed and in that case, add it all up. Well, validation and summation can be done in one fell swoop, so let's get rid of the flag and sum the values while validating them. So we replace myErrorFlag with a total variable:
var total = 0;
Now, let's get back to our clause. The requirements say:
When the input has a value
And that value is a number
Then add the value to the total
In code, that should look something like this:
if (value && !isNaN(value)) {
total += parseInt(value, 10);
input.style.color = 'black';
}
There are a couple of things going on here. For one, the if statement has been turned on its head a bit from what it was. It first checks to see that value is truthy, then that it is a number. The second check can be a bit tricky to read, because it is essentially a double negation; in english it reads "is not not a number", i.e. "is a number". I'll leave it as an exercise for the reader to figure out whether there's a more easily understood way of writing this check.
Now what about the but clause in our requirements?
But if the input does not have a value
Or that value is not a number
Then make the input color red
Well, it's essentially the inverse of our previous statement, so let's simply add an else clause:
else {
input.style.color = 'red';
}
Because the requirements doesn't mention the total variable in this clause, it is simply ignored and doesn't show up in the end result.
Adding it all up (no pun intended) the code – with comments – looks like this:
var calculateBills = function () {
var total = 0;
for (i = 1; i <= 4; i++) {
// Given each amount input
var input = $('amount' + i);
var value = input.value;
if (value && !isNaN(value)) {
// When the input has a value
// And that value is a number
// Then add the value to the total
total += parseInt(value, 10);
// And make the input color black
input.style.color = 'black';
} else {
// But if the input does not have a value
// Or that value is not a number
// Then make the input color red
input.style.color = 'red';
}
}
$('total').value = total;
};
There are more things that could be learned from this to make for better code. For instance, this code will break if the number of inputs change, or if their id names change. This is because they are selected specifically by their IDs and as such, if those change then this code will no longer function.
Another potential issue is that we're setting inline styles on the inputs as we loop over them. This means that in order to keep this code up to date with the styling of the site, it'll have to change. Generally, mixing styling and functionality like this is not a good idea and should be avoided. One way of doing so is to use class names instead, and toggle these on and off. Incidentally, this could also help the previous problem I mentioned.
There are other problems as well, but we'll leave those for another day. Hope this helps!
Try this
var calculateBills = function () {
var Amount = 0;
for (i = 1; i <= 4; i++) {
var AmountElement = $('amount' + i),
AmountValue = AmountElement.value;
if (AmountValue != "" && !isNaN(AmountValue)) {
AmountElement.style.color = "red";
Amount += parseInt(AmountValue,10);
} else {
AmountElement.style.color = "";
}
}
$('total').value = Amount;
};
Demo
Anyway, instead of using elements with id like id="amount1", id="amount2", id="amount3", etc., you could use classes (e.g class="amount") and get them with .getElementsByClassName
I am writing a javascript recursion function but in always gave me 0 value. Below is my code snippet and a screenshot showing the markup:
getOdometerEnd: function(object){
var previous = jQuery(object).closest('tr').prevAll();
var odometerEnd = parseInt(previous.find('input[name=odometer_end\\[\\]]').val());
console.log(previous.find('input[name=destination\\[\\]]').val());
if(odometerEnd == 0){
this.getOdometerEnd(previous);
}
return odometerEnd;
},
updateOdometer: function(){
var self = this;
var distance = 0;
var odometerStart = 0;
var odometerEnd = 0;
jQuery('.app-table tr').each(function(index, object){
distance = jQuery(object).find('input[name=distance\\[\\]]').val();
if(typeof distance != 'undefined' && distance > 0){
if(index == 1){
odometerStart = jQuery(object).find('input[name=vehicle_odometer\\[\\]]').val();
}else {
odometerStart = self.getOdometerEnd(object);
}
odometerEnd = parseInt(odometerStart)+parseInt(self.userDistance(distance));
jQuery(object).find('input[name=odometer_start\\[\\]]').val(odometerStart);
jQuery(object).find('input[name=odometer_end\\[\\]]').val(odometerEnd);
}
});
},
I don't know where I have mistaken, but it gives me the correct value at second last recursion but at last it again returns 0.
Can you help me please.
I've attached an image showing my markup here.
P.S. Stack overflow didn't allowed me to post image. Alternatively you can view image here: http://www.yourcarlog.com/odometer-problem.jpg
Thanx in advance.
First, give the elements classes to make selection easier and quicker. Selection by name is cumbersome.
Second, you will find it much simpler and probably no less efficient to :
maintain a running odo_cumulative variable, thus avoiding the need to sniff up the table for a valid earlier value of odo_end.
set the odo_start and odo_end values unconditionally, thus allowing odo_cumulative to propagate through null rows.
(if you must) perform a second row-scan to zero out odo_start and odo_end in null rows.
Replace updateOdometer with the following version:
updateOdometer: function(){
var self = this;
var odo_cumulative;
var $rows = jQuery('.app-table tr').each(function(index, tr){
var $tr = jQuery(tr);
if(!odo_cumulative) {
odo_cumulative = parseInt($tr.find('input.vehicle_odometer').val());
}
var odo_start = odo_cumulative;
var odo_cumulative = odo_end = parseInt(odo_start) + parseInt(self.userDistance($tr.find('input.distance').val()));
$tr.find('input.odometer_start').val(odo_start);
$tr.find('input.odometer_end').val(odo_end);
});
//Now, if you absolutely must, :) DESPITE BEING TOTALLY ILLOGICAL AND AGAINST ALL MY ADVICE :), scan the table rows again to zero out the start/end values where distance ==0;
$rows.each(function(index, tr){
var $tr = jQuery(tr);
if(parseInt($tr.find('input.distance').val()) == 0){
$tr.find('input.odometer_start, input.odometer_end').val(0);
}
});
},
untested
Third, the getOdometerEnd method is no longer called so can be deleted unless needed elsewhere.
EDIT:
And if that works, then so should this, which is even simpler, avoiding the need to double scan:
updateOdometer: function(){
var self = this,
odo_cumulative;
var $rows = jQuery('.app-table tr').each(function(index, tr){
var $tr = jQuery(tr),
$inputs = $tr.find('input'),
distance = parseInt(self.userDistance($inputs.filter('.distance').val()));
if(!odo_cumulative) {
odo_cumulative = parseInt($inputs.filter('.vehicle_odometer').val());
}
$inputs.filter('.odometer_start').val((distance == 0) ? 0 : odo_cumulative);
odo_cumulative += distance;
$inputs.filter('.odometer_end').val((distance == 0) ? 0 : odo_cumulative);
});
},
untested
I am completely new to JavaScript.
I have size and color dropdowns on a page for users to order a product, but only certain combinations are available i.e. pink is the only color in large sizes.
I thought I'd make an array of allowed sizes and test the user input against these.
If the choice is invalid then I want a popup to tell the user why.
In the real world I'll use SQL & PHP to create the array of allowed choices, in the example below I've hard coded 3 valid choices for testing. Unfortunately the code below doesn't do anything.
I'm sure it's a simple newb mistake. I really don't know what I'm doing :)
Can somebody help me out?
The validation function is supposed to happen when user clicks the form submit...
<form id="form1" name="form1" method="post" onsubmit="return validate_form()"
action="cart.php">
Here's the function:
<script type="text/javascript">
function validate_form() {
var allowed = new Array();
allowed[0]="10,beige";
allowed[1]="10,black";
allowed[2]="10,pink";
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenSizeText+","+chosenColText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
if (allowed[i]=chosenSizeCol) {
found = "true";
}
}
if (found = "false") {
alert( 'The variation you have selected is currently unavailable. Please select another.' );
return false;
} else {
return true;
}
}
</script>
There are a few lines where you use the assignment operator (that is single equals =) instead of one of the equality operators (that is double or triple equals, triple is usually preferred in JavaScript). Example:
if (found = "false") {
Would appear to be the problem at first sight - it's an assignment not a comparison :) use triple equals === instead of single:
if(found === "false") {
Also, consider the following (commented) updates to your code, which reflects more the typical style of JavaScript code:
function validate_form() {
//no need to use new Array(), use array literal instead
var allowed = [
"10,beige",
"10,black",
"10,pink"
];
var chosenColInd = document.getElementById("colID");
var chosenColText = colID.options[colID.selectedIndex].text;
var chosenSizeInd = document.getElementById("sizeID");
var chosenSizeText = sizeID.options[sizeID.selectedIndex].text;
var chosenSizeCol = chosenColText+","+chosenSizeText;
var found = "false";
for ( var i = 0; i < allowed.length; i++ ) {
//use equality operator instead of assignment
if (allowed[i]===chosenSizeCol) {
found = true; //may as well use a boolean rather than string
break; //exit loop early, no need to continue if we've already found
}
}
if (!found) { //no need to do a comparison with already boolean values
alert( 'The variation you have selected is currently unavailable. Please select another.' );
}
//may as well just return found here now that we're using a boolean
return found;
}
I am validating some check boxes and would like for the user to be able to select only 4 (from 7 possible) and disable the others if the current box is being checked(if there are already 3 checked) or enable the everything if the current box is being unchecked. I'm really not sure where's the problem. This is my first experience with JavaScript...
function verify_selected(selected_check_box_id) {
var count = 0;
var selected_check_boxes = new Array();
var check_boxes = new Array();
var inputs = document.getElementsByTagName("input");
for( var i in inputs ) {
if( inputs[i].type == "checkbox" ) check_boxes.push( inputs[i] );
}
// get current checkbox
for( var i in check_boxes ) if( check_boxes[i].id == selected_check_box_id ) var current_check_box = check_boxes[i];
var current_check_box_is_checked = current_check_box.checked;
// get all "checked"
for( var i in check_boxes ) {
if( check_boxes[i].checked ) {
selected_check_boxes.push( check_boxes[i] );
count += 1;
}
}
if( current_check_box_is_checked ) {
// checking
if( count < 4 ) {
current_check_box.checked = true;
// count = 4 - disabling
if( count == 4 ) {
for( var i in check_boxes ) {
if( !check_boxes[i].checked ) check_boxes[i].disabled = true;
}
}
}
else current_check_box.checked = false;
} else {
// unchecking
// count is < 4 -> enabling
for( var i in check_boxes ) {
check_boxes[i].disabled = false;
}
}
}
Any help is welcome,
thanks in advance.
There were a couple of things wrong. Lets give the good version first.
I also put up a demo at: http://jsbin.com/ajimi
function verify_selected(currentCheckbox) {
var count = 0;
var selected_check_boxes = []; // this will be fine...
var check_boxes [];
var inputs = document.getElementsByTagName("input");
for( var i in inputs ) {
if( inputs[i].type == "checkbox" ) check_boxes.push( inputs[i] );
}
// get all "checked"
for( var i in check_boxes ) {
if( check_boxes[i].checked ) {
count += 1;
}
}
if( currentCheckbox.checked && (count == 4)) {
for( var i in check_boxes )
if( !check_boxes[i].checked )
check_boxes[i].disabled = true;
} else {
for( var i in check_boxes )
check_boxes[i].disabled = false;
}
}
In the original version, you've got a piece of code which looked like:
if (count < 4) {
if (count == 4) {
Not gonna happen. So, that was corrected.
As you saw also in another answer, we changed the function to take out looking for an ID. Rather than figuring out the ID in some separate function (I assume you're tracking the "last clicked" by some other function which occurs), just use the this modifier to pass it into the function.
Alright, last but not least, what this would look like in jQuery. Hopefully this will help a little as to understanding how it works and why it's worth using:
(see example: http://jsbin.com/ihone)
function limitSelected(e) {
// get all of your checkboxes
var checkBoxes = $(e.currentTarget).parent().children().filter('input:checkbox');
// get the number of checkboxes checked, if 4, we'll disable
var disableCheckBoxes = (checkBoxes.filter(':checked').length == 4);
// enable checkboxes if we have < 4, disable if 4
checkBoxes.filter(':not(:checked)').each(function() {
this.disabled = disableCheckBoxes;
});
}
// when the document is ready, setup checkboxes to limit selection count
// if you have a particular div in which these checkboxes reside, you should
// change the selector ("input:checkbox"), to ("#yourDiv input:checkbox")
$(function() {
$('input:checkbox').click(limitSelected);
});
The other thing I will note about this version is that it works on the group of checkboxes within a div, as opposed to your version which will pick up checkboxes on the entire page. (which is limiting.
From a brief skim, your code seems much too complex for the task.
Can I suggest using something like jquery? You can quite easily select the relevant check boxes using the psudeo-selector ':checked'. Also, have a look at this check box tutorial.
If you don't want to use a library, I'd suggest first creating a function that can count the number of checked check boxes. Then create a function that can disable or enable all unchecked check boxes. Finally, combine the two, and register a function to trigger on the click event for the check boxes.
As cofiem said, your code looks rather complex for what you want to achieve; I recommend breaking it down into a few, smaller functions, to re-use code and make less complex.
First, implement a function to get all of the checkboxes on the page:
function getCheckboxes()
{
var inputs = document.getElementsByTagName("input");
var checkboxes = new Array();
for(var i=0;i<inputs.length;++i) {
if(inputs[i].type=="checkbox")
checkboxes.push(inputs[i]);
}
return checkboxes;
}
Then a function to enable/disable the checkboxes:
function setDisabled(state) {
var checkboxes = getCheckboxes();
for(i=0;i<checkboxes.length;++i) {
//Only unchecked checkboxes will need to be enabled/disabled
if(!checkboxes[i].checked)
checkboxes[i].disabled = state;
}
}
Now implement your function to verify whether the checkboxes need to be enabled or disabled:
function verify_selected(checkbox) {
var checkboxes = getCheckboxes();
var count=0;
for(i=0;i<checkboxes.length;++i) {
if(checkboxes[i].checked)
count++;
}
if(count>=4)
setDisabled(true);
else
setDisabled(false);
}
I have changed your function declaration to pass the actual checkbox object rather than an identifier string; this is much easier to call the function:
<input type="checkbox" onClick="verify_selected(this);">
//Insert 7 of these..
As you can see the code is much easier to read and maintain, and it is much less complex.