Make Select Sticky

Hi,

I am doing my first project for school, and I am having a small problem with the code. I found a lot of solutions on Google but they are all confusing me, as this is my first PHP program I really don’t understand them.

I have a simple form, that has a few combo boxes. I am supposed to make the form sticky, and it works just fine except on my combo box control.



.. function starts ..

	# temporary storage for current settings
	$current_month = "";
	$current_day = "";
	$current_year = "";
	
	# select option
	$sel = "";
	
	# if the form has been submitted, record the current settings so they can be
	# posted back to the form making it sticky.
	if (isset($_POST['submitted'])) {
	
		# recording current user settings
		$current_month = $_POST['month'];
		$current_day = $_POST['day'];
		$current_year = $_POST['year'];		
	}


 .. generate the select box ...

	# make the months pull-down-menu
	echo '<select name="month">';
	
	foreach ($months as $key => $value) {
		
		# if the current month the user has selected is the same month as the
		# one in $value on this iteration, mark this option as the selected option.
		if ($current_month == $value) {
			$sel = 'selected="selected"';
		}
		else {
			# this option is not selected
			$sel = 'selected=""';
		}
		
		# create the option, and mark it as selected if needed.
		echo "<option value=\\"$key\\" $sel>$value</option>\
";
	}
	
	echo '</select>';

I don’t think you will need the rest of my program. I am basically trying to see if the value (being generated) is the value in the $_POST variable. If it is then that was the value that needs to be sticky so I mark that as selected.

But when I do this December is always selected and all of the code when I view source in the browser has all of the Selected properties as an ampty string.

I’m not even sure if this fires, or if the combo box is regenerated every time the post back is called.

It appears that this line always fires


else {             
# this option is not selected             
$sel = 'selected=""';        
 } 

I’m not sure how to debug it yet, we didnt get that far.

This is what I get when I view source


<select name="month">
<option value="1" selected="">Jan</option>
<option value="2" selected="">Feb</option>
<option value="3" selected="">March</option>
<option value="4" selected="">April</option>
<option value="5" selected="">May</option>
<option value="6" selected="">June</option>
<option value="7" selected="">July</option>
<option value="8" selected="">Aug</option>
<option value="9" selected="">Sept</option>
<option value="10" selected="">Oct</option>
<option value="11" selected="">Nov</option>
<option value="12" selected="">Dec</option>

This is what I expected to get (assuming April was selected)


<select name="month">
<option value="1" selected="">Jan</option>
<option value="2" selected="">Feb</option>
<option value="3" selected="">March</option>
<option value="4" selected="selected">April</option>
<option value="5" selected="">May</option>
<option value="6" selected="">June</option>
<option value="7" selected="">July</option>
<option value="8" selected="">Aug</option>
<option value="9" selected="">Sept</option>
<option value="10" selected="">Oct</option>
<option value="11" selected="">Nov</option>
<option value="12" selected="">Dec</option>

December is not marked as selected but it always ends up being selected, some how.

For one, you should remove the selected=“” attributes if you don’t want to select anything - just don’t put it in at all.

For the problem itself, it entirely depends on your $months array and where that is being passed in or generated, and the value of $current_month as well of course.

You will need to paste the rest of your code in.

This is the entire function that generates the combo boxes. I have not made the day and year sticky yet, I wanted to get the month working first so I know how to do it.


# this function makes 3 pull-down menus
function make_calendar_pulldowns() {

	# temporary storage for current settings
	$current_month = "";
	$current_day = "";
	$current_year = "";
	
	# select option
	$sel = "";
	
	# if the form has been submitted, record the current settings so they can be
	# posted back to the form making it sticky.
	if (isset($_POST['submitted'])) {
	
		# recording current user settings
		$current_month = $_POST['month'];
		$current_day = $_POST['day'];
		$current_year = $_POST['year'];		
	}

	# make the months array
	$months = array( 1 => 	'Jan',
							'Feb',
							'March',
							'April',
							'May',
							'June',
							'July',
							'Aug',
							'Sept',
							'Oct',
							'Nov',
							'Dec' 
					);
							
	# make the months pull-down-menu
	echo '<select name="month">';
	
	foreach ($months as $key => $value) {
		
		# if the current month the user has selected is the same month as the
		# one in $value on this iteration, mark this option as the selected option.
		if ($current_month == $value) {
			$sel = 'selected="selected"';
		}
		else {
			# this option is not selected
			$sel = 'selected=""';
		}
		
		# create the option, and mark it as selected if needed.
		echo "<option value=\\"$key\\" $sel>$value</option>\
";
	}
	
	echo '</select>';
	
	# make the days pull-down menu
	echo '<select name="day">';
	
	for ($day = 1; $day <= 31; $day++) {
		echo "<option value=\\"$day\\">$day</option>\
";
	}
	
	echo '</select>';
	
	# make the years pull-down menu
	echo '<select name="year">';
	
	for ($year = 2008; $year <= 2018; $year++) {
		echo "<option value=\\"$year\\">$year</option>\
";
	}
	
	echo '</select>';

} # End of function Make_Calendar_Pulldowns

I make the HTML in the same page, at the bottom of the file below all the functions I echo out the HTML tages and in there I call this function so it puts the boxes in the right spot on the page.

It entirely depends on what the $_POST value for month is then - what are you testing it with?

I don’t know what you mean, that’s the only code I have.

Ah, it’s the current select box… sorry, bit of a mix up in my head there!

The problem is you are using the $key as the value for the select box (eg 1, 2, 3… etc) but testing against $value (Jan, Feb, March… etc). Since ‘4’ != ‘April’, it always returns false.

Oh, I don’t know how to fix it but I am going to finish that assignment tomorrow so I will look at that. I’m pretty sure I can figure out how to change it, but I will find out tomorrow.

Thanks for the help.

Edit:
This language is harder for me because my instructor is using Notepad++ to write the programs. When I write in C# or Visual Basic I have the Visual Studio Environment so I can use the debugger. If I would have had a debugger I would have for sure noticed the difference in the values.

With editors like Eclipse or other more advanced text editors (E-Text-Editor and UltraEdit come to mind) you can make use of a PHP debugger as well.

Edit:

A quick google search for notepad++ php debugger shows that there are plenty of those around as well too.

The solution will come to you y studying these two lines


if ($current_month == $value) { 
...
echo "<option value=\\"$key\\" $sel>$value</option>\
"; 

What are you comparing the current month with, and what is the value from the form?

I thought it was because I was comparing the interger to a string, I changed it now so that they should be both integers, but I still get the same issue. I don’t get any errors, but I still get December as the selected month.

I’m going to try this with day and year, and see if that works.

brb.

Edit: I forgot to post the code


if ($current_month == $key) {
			$sel = 'selected="selected"';
		}
		else {
			# this option is not selected
			$sel = 'selected=""';
		}

It should be comparing both numbers now?

Back with this code here:


if ($current_month == $value) { 
...
echo "<option value=\\"$key\\" $sel>$value</option>\
";

$key is 4, and $value is ‘April’

The form option is:


<option value="4">April</option>

When that option is submitted by the form, that string value of ‘4’ is submitted

Back in the code, you are checking:


if ($current_month == $value) { 

Where $current_month from the form is ‘4’, and $value is ‘April’

You should instead be comparing the value from the form with something else. Not $value. Do you recognise what that something else is?

Here’s a hint:

$key is 4, and $value is ‘April’

Did you check that the $current_month variable is receiving its value from the POST?

Can you include the full HTML for the form and submit button?


    if (isset($_POST['submitted'])) {
        # recording current user settings
        $current_month = $_POST['month'];
        $current_day = $_POST['day'];
        $current_year = $_POST['year']; 
   
        print $current_month.' - current month';      

    }

@spiderling:

The problem is with:


if ($current_month == $value) {

I’m hoping to help MrGeeker recognise what the problem is.

Remember - if April is chosen, $current_month is ‘4’, $key is 4 and $value is ‘April’

Thanks,

I changed the code to say


if ($current_month == $key)

I thought that both $current_month and $key would be the same value now, so they could be compared. Before I was comparing with $value and you said that was the string “April”.

I will go look again, its hard without a debugger, but I can’t do anything because the instructor asked us to use Notepad++ and it might have a debugger addon but I don’t have permission to install anything on the computers, so I have to use what the IT department installed at the science lab.

I will post back later.

@pmw57

I realize that and so does MrGeeker. As he / she realized in his / her last post and why the if statement was changed. The array keys and values are correctly being created and looped. The next step would be to check that the input value is received and what it is.

My suggestion will also help MrGeeker recognize what the problem might be.

There’s actually several issues that are getting in the way here.

[list][]$current_month will only be set if the submit button has a name of “submitted”
[
]the comparison with $current_month should be with $key instead of $value
[*]The selected attribute, even when as selected=“”, is considered by the web browser to mean that it’s selected.[/list]

So after resolving all of these issues, the test code should be working.

I’m surprised at the otherwise reasonable quality of the remaining code. Suspicions are raised that these problems are deliberately set, perhaps from a tutor, where the intention is to test how well someone can debug some non-working code.

Its fixed now, I changed the code, and I also modified it to make the day and year sticky. Now the code works fine, when I removed it into two echo statements instead of one. I’m not sure why, but its working.


	# make the months pull-down-menu
	echo '<select name="month">';
	
	foreach ($months as $key => $value) {
		
		# if the current month the user has selected is the same month as the
		# one in $key on this iteration, mark this option as the selected option.
		if ($current_month == $key) {
			echo "<option value=\\"$key\\" selected=\\"selected\\">$value</option>\
";
		}
		else {
			# this option is not selected
			echo "<option value=\\"$key\\">$value</option>\
";
		}
	}
	
	echo '</select>';

Once I commented out $sel it started working, so I removed that line and made two seperate echo statements instead of using $sel to insert the “selected=selected” option.

The code was given to me in a PDF file by the instructor. It was already written. I could not copy and paste out of the PDF file so I had to manually type the code in myself.

It was the first assignment for this class, and it was a working date program already.

My job was to modify the original code so that it did not accept an invalid date. If someone entered 2/31/2010 I would provide a message saying the date was invalid. I also had to check for leap years and make sure that 2/29/2008 was valid, or any other leap year.

Then I was supposed to print out the date in a message “You entered a valid date 2/29/2008.”

Part of the assignment was not to make the form sticky, but the instructor talked about sticky forms earlier so I wanted to try it, but I wasn’t required to do it. Most people just redirected to another blank page with a message on it telling the user if the date was valid or not and made them use the back button to enter it again.

This is the two functions I wrote myself check_for_valid_date and is_leap_year, everything else was done and I hope they are right. I will find out when I get a grade on it.

There was a built in way to do this I think, but we are not allowed to use it. We have to write the function myself.


# checks to see if the users select is a valid date.
function check_for_valid_date($month, $day, $year, &$valid_date) {	
	# constants
	define('ONE', 1);
	define('TWENTY_EIGHT', 28);
	define('TWENTY_NINE', 29);
	define('THIRTY', 30);
	define('THIRTY_ONE', 31);

	# check to see if the month should have 30 days in it...
	 if (($month == 4) || ($month == 6) || ($month == 9) || ($month == 11)) {
		if (($day < ONE) || ($day > THIRTY)) {
			$valid_date = false; # error
		}
	 }
	 
	 # check to see if the month should have 28 days in it...
	 else if ($month == 2) {
		# first, check to see if this is a leap year...
		$leap_year;
		Is_Leap_Year($year, $leap_year);
		
		if (!$leap_year) {
			# this is NOT a leap year...
			if (($day < ONE) || ($day > TWENTY_EIGHT)) {
				$valid_date = false; # error
			}
		}
		else {
			# this IS a leap year...
			if (($day < ONE) || ($day > TWENTY_NINE)) {
				$valid_date = false; # error
			}
		}
	 }
	 
	 # check the rest of the months to make sure they have 31 days in them...
	 else {
		if (($day < ONE) || ($day > THIRTY_ONE)) {
			$valid_date = false; # error, but we will probably never get here
								 # because I am using a combo box control.
		}
	}
} # end of function Check_For_Valid_Date

# Check to see if the passed year is a leap year
function Is_Leap_Year($year, &$is_Leap_Year) {	
	# if its divisable by 4.. 		is it divisable by 100 OR 400
	if (($year % 4 == 0) && ($year % 100 != 0 || $year % 400 == 0)) {
		$is_Leap_Year = true;
	}
	else {
		$is_Leap_Year = false;
	}

} # end of function Is_Leap_Year

Thanks for the help.

Congratulations then on writing comments for your update.


# if the current month the user has selected is the same month as the 
# one in $key on this iteration, mark this option as the selected option. 

You may wish to consider though writing comments that don’t reword the actual code. They incur a high danger of going out of date when the code is updated.
Consider instead on using comments to explain why things happen instead.

If you have the time, a book called Clean Code really helps to demonstrate good an bad ways of doing this.

All the best with your learning.

Some comments on your code, if you don’t mind me poking in again!

# constants
define('ONE', 1);
define('TWENTY_EIGHT', 28);
define('TWENTY_NINE', 29);
define('THIRTY', 30);
define('THIRTY_ONE', 31);

This bit is really unnecessary. When is ‘TWENTY_NINE’ ever going to be redefined as ‘76’ for example?

    # check to see if the month should have 30 days in it...
[...]
     # check to see if the month should have 28 days in it...
[...]
     # check the rest of the months to make sure they have 31 days in them...

For this bit, and to replace the above bit, why not use an array that stores the number of days in each month? Eg:

$daysinmonth = array(1 => 31,
                     2 => 28,
                     3 => 31,
                     [...]
                     12 => 31);

if (is_leap_year($year)) {
  $daysinmonth[2] = 29;
}

Then it is just a simple case of checking the appropriate array element for the number of days - if ($day <= $daysinmonth[$month]) { or something like that.

Finally, I’m not sure why, but you seem to be returned values from functions through variables passed in by reference - a much better way
(and the usual way) to do this would be to use ‘return’:

function Is_Leap_Year($year) {    
    # if its divisable by 4..         is it divisable by 100 OR 400
    if (($year % 4 == 0) && ($year % 100 != 0 || $year % 400 == 0)) {
        return true;
    }
    else {
        return false;
    }

} # end of function Is_Leap_Year

…which can be shortened further to…

function Is_Leap_Year($year) {    
    # if its divisable by 4..         is it divisable by 100 OR 400
    return (($year % 4 == 0) && ($year % 100 != 0 || $year % 400 ==  0));
} # end of function Is_Leap_Year

Then you can use the function within an if statement without having to prepare variables etc first:

if (Is_Leap_Year($year)) {
//code
}