javascript function to validate radio buttons giving strange output. - php

I'm developing a quiz that pulls data out of a mysql database, and displays the results as radio buttons. The radio buttons are populated based off of key=>value and generated via a simple forloop. This has been done many times, simple google searching and research will yield all the results needed to accomplish this. The issue that I'm having, or was having (before I decided to just do this with jquery) was when I submit the form it would execute the javascript function to validate whether a button has been selected, but when you select any option other than the first radio button you'd receive the same "make a selection" alert that you would if you had not selected any buttons. Selecting the first radio button would return true and execute the getCheckedValue function call. It seems as though, the script only recognizes that I have one input type and doesn't understand to iterate through the rest of the buttons. I've refactored this function a dozen times, and still have no idea why this doesn't work.
<?php
foreach ($dataReturn as $j => $value){
echo "<input type='radio' class='answer' id='radiobtn' name='radiobtn' value='".$j."'>" .$value." </input><br/>";
}
?>
Above is the loop that generates the radio buttons (just for reference, $dataReturn is the return value of a shuffled associative array. (Which is working as intended)
When the submit button is clicked, it calls the below javascript function.
function isNull(){
var isChecked = false;
var radiobutton = document.getElementsByName('radiobtn');
for (var i=0; i <= radiobutton.length; i++){
if (radiobutton[i].checked){
return true;
var answer = radiobutton[i].value;
getCheckedValue(answer);//using this just for testing selected value
}else {
alert("Make a selection.");
}
return false;
}
}
I just can't figure out why this doesn't work. As stated above, using jquery this works perfectly.

Your FOR loop: since JS uses zero-based arrays, you can't have <=, otherwise it will look for an index one higher than what you have. Use < instead;
I moved your validation for whether any fields were checked outside the loop to make management easier. It's cleaner this way than worrying about breakout out of loops in the middle of them.
Here:
function isNull() {
var isChecked = false;
var radiobutton = document.getElementsByName('radiobtn');
for (var i=0; i < radiobutton.length; i++) {
if (radiobutton[i].checked) {
isChecked = true;
}
}
if ( !isChecked ) {
alert("Make a selection.");
return false;
}
}
I don't know how your form tag looks, but here is what you need to prevent the form from submitting if no radio fields are checked:
<form action="" method="post" onSubmit="return isNull();">

Try the code below. You do not want your alert to fire or return false until after the for loop is finished.
function isNull(){
var isChecked = false;
var radiobutton = document.getElementsByName('radiobtn');
for (var i=0; i <= radiobutton.length; i++){
if (radiobutton[i].checked){
var answer = radiobutton[i].value;
getCheckedValue(answer);//using this just for testing selected value
return true;
}
}
alert("Make a selection.");
return false;
}
Also, your php code gives all radio buttons the same id. That is bad; doing so violates w3c standards.

Related

Setting checkbox state correctly

I'm hoping I'm on the right track here....
I have some elements on my page (tables).. that are dynamically generated based on the results of querying a DB.... (I add inside of a container DIV)..
inside these tables are some text..and a handful of checkboxes... each table is the same (outside of the value of the text fields)..
When a user clicks on a checkbox.. I add an element to another container DIV off to the side.
If a user un-checks the checkbox.. it removes the element from the container DIV on the side. On each 'click' event..... I am also either adding or removing the 'selections' from an ARRAY (and also updating this array to my PHP SESSION)..
When the user is done.. they click a button and go to another page.. where this SESSION array is grabbed and reviews/summarizes their 'choices'..
*there is no FORM tags.. checkboxes are free-form in the tables (not wrapped in any FORM tags..so there is NO general POST action to grab everything.. hence the use of an array/SESSION)
If the user goes BACK to the original 'selection page' (with the tables/checkboxes)..
I am re-populating the PAGE (both re-checking any checkboxes...and re-populating the elements in the container DIV to the side.. all based on the SESSION data)
In each checkbox.. I am adding a little PHP function to write in checked="checked" or not.. when the checkboxes instantiate)
like so:
<label><input id="articlesnaming" name="Articles Naming Expert" type="checkbox" value="0.00" <?=sessionCheck($row["id"] ."-A","Articles Naming Expert") ?> onclick=""/> Articles Naming Expert</label>
FYI: on the function being called:
function sessionCheck($recordID, $checkBoxID){
if(isset($_SESSION['userPicks']) && count($_SESSION['userPicks']) != 0){
for($r = 0; $r< count($_SESSION['userPicks']); $r++){
if($_SESSION['userPicks'][$r]['recordid'] == $recordID){
for($z=0; $z < count($_SESSION['userPicks'][$r]['itemsordered']); $z++){
if($_SESSION['userPicks'][$r]['itemsordered'][$z]['name'] == $checkBoxID){
return 'checked="checked"';
}else if($z == (count($_SESSION['userPicks'][$r]['itemsordered']) - 1)){
return "";
}
}
}else if($r == (count($_SESSION['userPicks']) - 1)){
return "";
}
}
}else{
return "";
}
}
Everything up to this point works fine...
Its when I go to dynamically build/add (append) those elements in the container DIV on the side... where problems happen.
I am getting them added just fine and when a user RE-VISITS the page.. previous checkboxes they had selected were/are checked again... -and-.. the elements ARE in the container DIV to the side of the stage/screen)...
PROBLEM: When I un-check one of the checkboxes, it DOES NOT remove the element in the container DIV on the side? I have to re-click the checkbox..(which adds a duplicate).. then I can un-check it.. but it only removes the NEW one..
Everything seems to work fine until a refresh/re-visit of the page (and I have to automatically populate the checkboxes and the elements in the container DIV on the side).. then the checkboxes stop behaving/interacting with the elements that were adding through another function (still same ID's...paths..from what I can tell)....and -not- added through an initial checkbox event/action..
I am grasping at straws here.... it is perhaps because I'm using a PHP function to set the checkboxes on refresh? and it maybe doesn't know its current state? (although the visual state of the checkbox is accurate/correct)
Any ideas are appreciated.
Code used to set/un-set checkboxes & add/remove elements from the side container DIV :
<script>
//var to hold current check box clicked
var targetCheckbox;
//var to hold cumulative total
var totalPrice = 0;
//array to keep track of user picks from returned record results
//try to get SESSION array (if available/set) from PHP into jQuery using json_encode()
<?php if(isset($_SESSION['userPicks'])){ ?>
//overwrite jQuery userPicks MAIN array
var userPicks = <?php echo json_encode($tempArray) ?>;
<? }else{ ?>
//create new jQuery userPicks MAIN array, and populate through user clicks/interaction
var userPicks = [];
<? } ?>
$(document).ready(function() {
//check to see if seesion and populate checks and side column from previous picks
//if existing session, loop through and populate the CHOICES column
if(userPicks.length > 0){
console.log("SESSION EXISTS, POPULATE CHOICES COLUMN FROM ARRAY");
for(i=0; i<userPicks.length; i++){
//build up sub array data first then append at one time.
var subArrayLength = userPicks[i].itemsordered.length;
var subArray = '';
for(s=0; s<subArrayLength; s++){
subArray += '<li id="' + userPicks[i].orderid + userPicks[i].checkboxid + '">' + userPicks[i].itemsordered[s].name + '</li>';
}
$("#choicesWrapper #itemList").append('<div class="recordChoices"><h5>CASE NAME: '+userPicks[i].casename+'</h5><ul id="'+userPicks[i].recordid+'">'+subArray+'</ul></div>');
}
}
//onClick event
$('.orderOptions').on('click', 'input:checkbox', function () {
//routine when checkbox is checked
if ($(this).is(":checked")) {
$(this).prop("checked", true);
console.log("checked");
//console.log('doesnt exist..create it');
$("#choicesWrapper #itemList").append('<div class="recordChoices"><h5>CASE NAME: '+caseName+'</h5><ul id="'+resultsID+'"><li id="'+orderID+targetCheckbox+'">'+itemOrdered+'</li></ul></div>');
}else{
$(this).prop("checked", false);
console.log("un-checked");
//remove the option from right column (li element)
console.log("REMOVE TARGET: #choicesWrapper #itemList #"+resultsID+" "+orderID+targetCheckbox);
$("#choicesWrapper #itemList #"+resultsID+" #"+orderID+targetCheckbox).remove();
//check if no more children and remove parent/title (record container/div)
if ($("#choicesWrapper #itemList #"+resultsID+" li").length > 0) {
//console.log("Still has children...do nothing");
}else{
//console.log("No Children...");
$("#choicesWrapper #itemList #"+resultsID).parent().remove();
}
}
}
}
</script>
Oddly enough, when things are 'auto-populated' from the SESSION data (like on refresh or re-visiting the page) and when things 'break', unchecking the checkboxes doesn't remove things, but when I uncheck the very last checkbox in a group, it does remove the parent (so that parent removal code/routine is being executed...but not then child )
I'm thinking this is a pathing issue? (I believe I am creating things with exactly the same ID's/classes...etc).
Definitely worth the +1 if you answer! :)
The only other thing I can think of is.. HOW the userPicks array gets created.. initial visit to page, I just create an empty JS/jQuery array and wait to push/populate it when a user clicks a checkbox (code above for onClick stuff).
But when a user visits the page (refresh or re-visit) and -HAS- (previous) SESSION data still available.... then I grab the PHP SESSION array.. and pass it to jQuery using json_encode()...
Do I need to add/delete from that array differently than I do if I created normally?

JS checkbox.checked vs manually checking

I have a page which is paginated to 100 results per page by php with checkboxes beside each. I have three functions: one to select all, one to save what was checked, and one to restore what was checked.
I don't understand why my toggle function does not work with the other two.
If I click select all (which performs a toggle()) the checked values are not saved;
however, if I click them by hand they do get saved across pagination.
I am assuming that I have to do something along the lines of persistCheckBox(checkboxes[i].checked) to the last line of my toggle function --which I tried and it did not work; Can someone explain why?
function toggle(source) {
checkboxes = document.getElementsByName('multi_mag[]');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
}
}
function restorePersistedCheckBoxes() {
var aStatus = getPersistedCheckStatus();
for (var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
var el = document.getElementById(aPair[0]);
if (el) {
el.checked = aPair[1] == '1';
}
}
}
function persistCheckBox(el) {
var found = false;
var currentStateFragment = el.id + ':' + (el.checked ? '1' : '0');
var aStatus = getPersistedCheckStatus();
for (var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
if (aPair[0] == el.id) {
// State for this checkbox was already present; replace it
aStatus[i] = currentStateFragment;
found = true;
break;
}
}
if (!found) {
// State for this checkbox wasn't present; add it
aStatus.push(currentStateFragment);
}
// Now that the array has our info stored, persist it
setPersistedCheckStatus(aStatus);
}
Neither the click nor the change events are triggered when changing the checked value programmatically.
Since you tagged your question with jQuery, I will demonstrate using some jQuery code.
It is unclear from your code how you do your persistent storage or what is your HTML structure, so the code will show a general approach.
A word of advice, though: I strongly suggest that you remove styling code out of the structure and use CSS and avoid inline event handling. Pretty much everything that you want to accomplished can be done more cleanly from outside the HTML.
I will be suing a form with several checkboxes, the first of which will change the other checkboxes' state.
HTML:
<form id="boxes">
<input type="checkbox" id="all" name="all" />
<input type="checkbox" name="multi_mag[]" class="normal" />
...
<input type="checkbox" name="multi_mag[]" class="normal" />
</form>
Javascript:
In this example, all of the 'normal' checkboxes have some common property (in this case, I decided on a class), that allow event delegation.
$('#boxes').delegate('.normal', 'change', function (e) {
console.log('changed', e.target.checked);
});
This code sets a function to run every time a checkbox changes, corresponding to your persistCheckBox() method.
Next, the equivalent of your toggle() function:
$('#all').change(function (e) {
var checked = e.target.checked;
console.log('changed checkall box: ', checked);
checkboxes = document.getElementsByName('multi_mag[]');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = checked;
$(checkboxes[i]).change();
}
});
It is executed whenever the "main" checbox changes its state. All of the checkboxes are iterated, their values are changed and the change event is triggered, which causes each to run the aforementioned function.
You can apply this method to your (cleaned) code, and the persistence should be maintained.
Example jsFiddle (check your console for the activity log).
This little piece of code can check / uncheck a checkbox, and will trigger any associated events.
$('input[type=checkbox]').trigger('click');
It could help maybe
I fixed this by adding I fixed this by adding "persistCheckBox(checkboxes[i]);" to the last line of the toggle() function. #MasterAM I appreciate your critiques and will be using them to optimize my code. I also appreciate the JQuery solution you provided.

PHP dynamically created checkboxes with JQuery .toggle()

I have dynamically created an array of checkboxes in PHP for a form, but I don't want the Submit button to appear unless at least one checkbox is checked. Scouring the Internet most people who want the Submit button to only appear after checking a checkbox only have one "I agree" checkbox. Is it the dynamic creation that is preventing my script working?
PHP↴
// Dynamically create checkboxes from database
function print_checkbox($db){
$i = 0;
foreach($db->query('SELECT * FROM hue_flag') as $row) {
if ($i == 0 || $i == 3 || $i== 6 || $i == 9){
echo '<br><br>';
}
$i++;
echo '<span class="'.$row['1'].'"><label for="'.$row['1'].'">'.ucfirst($row['1']).'</label><input type="checkbox" name="hue[]" id="hue" value="'.$row['0'].'"></span> ';
}
}
jQuery↴
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('#hue[]').click(function(){
$('#input_gown').toggle();
});
});
</script>
PHP function call↴
<?php print_checkbox($conn_normas_boudoir);?>
Admittedly I know nothing about jQuery or JavaScript and am still learning PHP. So, if there's a better way to implement this, let me know.
You're giving all your checkboxes the same ID. That's not allowed; IDs have to be unique.
An easy solution to both problems is to assign all the checkboxes a common class:
echo '<span class="'.$row['1'].'"><label for="'.$row['1'].'">'.ucfirst($row['1']).'</label><input type="checkbox" name="hue[]" class="hue" value="'.$row['0'].'"></span> ';
Then select the class in jQuery:
$('.hue').change(function(){
$('#input_gown').toggle();
});
But that may give unexpected results; what if two checkboxes are checked? The #input_gown element will toggle on and off again. Perhaps you only want it shown if at least one checkbox is checked:
$('.hue').change(function(){
var val = false;
$('.hue').each(function() {
val = val || $(this).is(':checked'); // any checked box will change val to true
});
$('#input_gown').toggle(val); // true=show, false=hide
});
http://jsfiddle.net/mblase75/AyY3Z/
Your jQuery selector is looking for elements with id hue[]. But your elements have the id of just hue.
Change this:↴
$(document).ready(function(){
$('#hue[]').click(function(){
$('#input_gown').toggle();
});
});
to this (IDs should really always be unique, and the square brackets will need to be escaped to work with the selector engine), (a demo)):↴
$(document).ready(function(){
$('input[name=hue\\[\\]]').click(function(){
$('#input_gown').toggle();
});
});

Javascript function only outputs value of first check box from a PHP for loop

I have a for loop that forms a list of check boxes based on information received from a mySQL database. Below is the for loop that forms the check boxes (unnecessary code removed).
for ($i = 1; $i <= count($descriptionIDsArray); $i++) {
$statuses = mysql_fetch_assoc(mysql_query(sprintf("SELECT status, description FROM status_descriptions WHERE description_id='$i'")));
$status = $statuses["status"]; ?>
<input type="checkbox" value="<?php echo $status ?>" <?php if ($check == 1) {echo "checked='checked'";} ?> onchange="checkBox()" /><?php echo $description ?><br />
<?php } ?>
Checking or unchecking a box calls the following function:
<script type="text/javascript">
function checkBox() {
var status = $("input:checkbox").val();
document.getElementById("test").innerHTML = status;
}
</script>
The only value that I can get to appear in "test" is the value of the first check box. If I echo $status throughout the initial for loop all the values appear correctly so the problem seems to arise when the Javascript code is retrieving the corresponding value.
If you still want to keep the inline event handlers, change it to:
onclick="checkBox(this);"
And change the function to:
function checkBox(chk) {
var status = chk.value;
document.getElementById("test").innerHTML = status;
}
Note that onclick is better supported with checkboxes and radio buttons than is onchange. Also, the reason for this change I provided is because passing this to the checkBox function references the element that the click was applied to. That way, you know that inside of checkBox, the parameter chk will be the specific checkbox that just changed. Then just get the value with .value because it's a simple DOM node.
Anyways, I'd suggest using jQuery to bind the click event. Something like:
$(document).ready(function () {
$("input:checkbox").on("click", function () {
var status = this.value;
document.getElementById("test").innerHTML = status;
});
});
But you can obviously use $(this).val() instead of this.value, but why bother? If you use jQuery to bind the events, just make sure you take out the onchange/onclick inline event handler in the HTML.
You can look at why to use input:checkbox and not just :checkbox as the jQuery selector here: http://api.jquery.com/checkbox-selector/
When you do
$('input:checkbox').val();
it is returning the first input of type checkbox on your form, not necessarily the one that is clicked.
To return the one that was actually clicked, you need to do something like this:
$(document).ready(function() {
$('input:checkbox').bind('click', function() {
clickBox($(this));
});
});
function clickBox(field) {
$('#test').html(field.val());
}
if you use a jquery, why bother with inline events?
You could write that like:
$(':checkbox').change( function(){
$('#test').html( $(this).val() );
//`this` is the checkbox was changed
//for check if item is checked try:
$(this).is(':checked') // boolean
});
If you pass that code before your checkboxes are placed make sure you invoke that code when document is loaded;
$( function(){
//code from above here
});
jQuery is well documented with lots of samples.
I think you'll like it docs.jquery.com

Get checkboxes on the page with jQuery and put the values into string to send ajax call

What I'm trying to do is use jQuery to grab any checkboxes that are checked on the page. The boxes are dynamically created using a specific ID number of each one for the ID and Value.
What is the easiest way about getting it to grab the values of each checked item? Then check if less than or greater than 3 is checked. If only 3 are checked then send the values of each checkbox to my php script. I'm using a regular button on the page so I will proably have to use the .click method since its not actually part of a form to submit.
I've seen several examples around here but not quite what I'm trying to do.
$('#mybtn').live('click',function(){
$("input[type=checkbox]").each(function() {
// I guess do something here.
)};
)};
the code i believe you are wanting is this
$('#mybtn').live('click',function(){
var num_checked = $("input[type=checkbox]:checked").length;
var checkbox_values = new Array();
if( num_checked > 3 ) {
//its greater than 3
//do what you need to do
} else if( num_checked < 3 ) {
//its less than 3
//do what you need to do
}else {
//it equals 3
//do what you need to do
//go thru and add values to array
$("input[type=checkbox]:checked").each(function() {
checkbox_values.push($(this).val());
});
}
});
if you want to send email of variables you can output array checkbox_values to php
If all your checkboxes are in a form, you can do $('#form_id').serialize();
You can get how many are checked using
$("input[type=checkbox]:checked").length
http://jsfiddle.net/XKRRL/7/
Not really sure what you want to do with the ones that are checked, but the js fiddle loops through the checked ones. From there you could grab id's etc.
full code
$(function() {
$('#mybtn').live('click', function() {
var checkedBoxes = $("input[type=checkbox]:checked"),
checkedNum = checkedBoxes.length;
if(checkedNum === 3){
for(var i=0; i< checkedNum; i++){
alert($(checkedBoxes).eq(i).val());
}
}
});
});
It's simple to grab all checked checkboxes:
var checked = $('input[type=checkbox]:checked'),
count = checked.length;
if (count == 3) {
values = $.map(checked, function(i){
return $(this).val();
});
}
Then do whatever you want on the values array.

Categories