Jump to content


Photo

Calendar problem


  • Please log in to reply
20 replies to this topic

#1 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 13 October 2006 - 01:14 PM

I've been trying to help out someone on another message board with tweaking a calendar script they have.  The script allows for appointments to be made by passing values into an array within the code itself (not the way I would've done it, but that's neither here nor there).  Originally, any appointments made would turn the days selected red to highlight the span of time they would take.  Since the user is a firefighter, he wants the ability to have different colors available for different watch shifts.  I figured that the easiest way to adapt the existing script to that would be to add another element to the array as a flag, then have a series of switch statements that would see what flag (if any) were set and highlight those dates with the correct color.  Unfortunately, the code is only displaying the first appointment and nothing else.  I think the problem is in checkDate's for-loop, but I can't see it.  I originally thought that the switchs' break statements were ending the loop, but I don't think that's it.

Below is all of the code...it's long.  I don't like that all of the JavaScript is in the head rather than included as an external file.  I also don't like how the calendar is created, but since I can't get the basic functionality of the script to work correctly I don't want to re-invent that part of the wheel just yet.  The comments on every checkDate line were to help me match brackets.  Well, anyway, here's the code:

EDIT: I think I have to put it in a separate post because of its length.
Using 'global' is a sign of doing it wrong

#2 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 13 October 2006 - 01:20 PM

The forum doesn't seem to like the code, so I'll just link to where I posted it on the other message board:

http://www.ozzu.com/ftopic69734.html

I can't link directly to my message, but it's the last one in that thread.
Using 'global' is a sign of doing it wrong

#3 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 13 October 2006 - 03:38 PM

You'll have to post just the relevant code snippets.
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#4 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 13 October 2006 - 04:38 PM

Unfortunately, since I'm not 100% sure where my problem lies, I'll have to post all of the script so you can see how each of the functions are called.  CheckDate is the most important function, and the one that I modified (the switch blocks).  The only other thing I modified was the apps 2-d array.  I merely added a flag as the last element for each array.

var months = ["January","February","March","April","May","June","July","August","Se ptember","October","November","December"];
var daycounts = [31,28,31,30,31,30,31,31,30,31,30,31]; //for leap years, remember to set february to 29 days
//2002 firstdays = [1,4,4,0,2,5,0,3,6,1,4,6];
var firstdays = [0,3,3,6,1,4,6,2,5,0,3,5];
//2004 firstdays = [3,6,7,3,5,1,3,6,2,4,0,2];

// This is where you put in the appointments. follow pattern [fromday,frommonth,today,tomonth,message, flag]
var apps = [
[1,1,2,1,"Red Watch Days", "Holiday"],
[12,6,12,6,"my birthday", "Holiday"],
[28,8,2,9,"Trip to Paris", "Holiday"],
[22,11,22,11,"Party with colleagues", "Holiday"],
[20,12,30,12,"Christmas with family", "Holiday"],
[12, 10, 14, 10, "Watch 1 Test", "Watch1"],
[15, 10, 17, 10, "Watch 2 Test", "Watch2"],
[18, 10, 20, 10, "Watch 3 Test", "Watch3"]
];

function CheckDate(month,dayno){  //begin function
   var retval = new String(dayno);
   var m = month + 1;

   for(var app = 0; app < apps.length; app++){ //begin for-loop
      if(m == apps[app][1] ){ //first month (if 1)
         if(apps[app][3] - apps[app][1] > 0){ //if 2
            if(dayno >= apps[app][0]){ //if 3
               switch (apps[app][5].toLowerCase()){ //switch
                  case "holiday":
                     retval = "<div class='hol' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch1":
                     retval = "<div class='watch1' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch2":
                     retval = "<div class='watch2' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch3":
                     retval = "<div class='watch3' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  default:
                     retval = "<div class='error' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;
               } //end switch
            } //end if 3

            else { //else 1
               if(dayno >= apps[app][0] && dayno <= apps[app][2]){ //if 3
                  switch (apps[app][5].toLowerCase()){ //switch
                     case "holiday":
                        retval = "<div class='hol' title='" + apps[app][4] + "'>" + dayno + "</div>";
                        break;

                     case "watch1":
                        retval = "<div class='watch1' title='" + apps[app][4] + "'>" + dayno + "</div>";
                        break;

                     case "watch2":
                        retval = "<div class='watch2' title='" + apps[app][4] + "'>" + dayno + "</div>";
                        break;

                     case "watch3":
                        retval = "<div class='watch3' title='" + apps[app][4] + "'>" + dayno + "</div>";
                        break;

                     default:
                        retval = "<div class='error' title='" + apps[app][4] + "'>" + dayno + "</div>";
                        break;
                  } //end switch
               } //end if 3
            } //end else 1
         } // end if 2

         else if(m == apps[app][3]){ // second month (else if 1)
            if(dayno <= apps[app][2]){ //if 2
               switch (apps[app][5].toLowerCase()){ //switch
                  case "holiday":
                     retval = "<div class='hol' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch1":
                     retval = "<div class='watch1' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch2":
                     retval = "<div class='watch2' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  case "watch3":
                     retval = "<div class='watch3' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;

                  default:
                     retval = "<div class='error' title='" + apps[app][4] + "'>" + dayno + "</div>";
                     break;
               } //end switch
            } //end if 2
         } //end else if 1

         else if( m > apps[app][1] && m < apps[app][3] ){ //else if 1
            switch (apps[app][5].toLowerCase()){ //switch
               case "holiday":
                  retval = "<div class='hol' title='" + apps[app][4] + "'>" + dayno + "</div>";
                  break;

               case "watch1":
                  retval = "<div class='watch1' title='" + apps[app][4] + "'>" + dayno + "</div>";
                  break;

               case "watch2":
                  retval = "<div class='watch2' title='" + apps[app][4] + "'>" + dayno + "</div>";
                  break;

               case "watch3":
                  retval = "<div class='watch3' title='" + apps[app][4] + "'>" + dayno + "</div>";
                  break;

               default:
                  retval = "<div class='error' title='" + apps[app][4] + "'>" + dayno + "</div>";
                  break;
            } //end switch
         } //end else if 1
      } //end if 1

   return retval;
   } //end for-loop
}

function PrintMonth(month){
   var done = false;
   var day = 0;

   document.write("<table class='inner'><caption><b>" + months[month] + "</b></caption><thead>");
   document.write("<th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>F r i</th><th>Sat</th><th>Sun</th></thead>");

   while(!done){
      document.write("<tr>");
      PrintWeek(month,day, firstdays[month], daycounts[month]);
      document.write("</tr>");
      day = day + 7;

      if( day > daycounts[month] + firstdays[month]){
         done = true;
      }
   } //end of while-loop

   document.write("</tbody></table><p>");
} //end of function


function PrintWeek(monthno,start,min,max){
   var d;
   var desc;
   for(var j = 0; j < 7; j++){
      document.write("<td>");
      d = start + j;

      if(d >= min && d < max + min){
         desc = CheckDate(monthno,d - min + 1);
         document.write(desc);
      }

      document.write("</td>");
   } //end of for-loop
} //end of function

EDIT: Nope, fixing the first toLowerCase() call didn't help.
Using 'global' is a sign of doing it wrong

#5 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 13 October 2006 - 07:35 PM

And what calls are you issuing to write out the page itself?
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#6 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 13 October 2006 - 09:00 PM

And what calls are you issuing to write out the page itself?


Every time I try posting HTML within the code brackets I get an error, so I can't rewrite the code.  But I can describe it! :)

The page's layout is a table, four rows, three columns.  In every table cell, they used a script element to call PrintMonth(x), where x is the index of the array (0 = January, 1 = February, etc).  Nothing else is within those cells.

Sloppy, and definitely not the way I'd do it.  Once I get the calendars to print the set appointments correctly, I'll try to convince the guy I'm helping to let me change how all of that is handled.
Using 'global' is a sign of doing it wrong

#7 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 13 October 2006 - 10:45 PM

I think I understand, but I really need to see that page... can you put it up somewhere?
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#8 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 14 October 2006 - 12:02 AM

I think I understand, but I really need to see that page... can you put it up somewhere?


I put it up at http://www.nightslyr.com/calendar.html -- all of the code is in that file.
Using 'global' is a sign of doing it wrong

#9 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 14 October 2006 - 05:48 PM

Your return statement for CheckDate() is inside the for loop, so it only runs once... move it one line down, and it'll work.
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#10 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 15 October 2006 - 04:52 PM

Your return statement for CheckDate() is inside the for loop, so it only runs once... move it one line down, and it'll work.


Thanks, that helped a lot! :)

Unfortunately, now I have a logic problem.  None of the appointments are displaying correctly.  For instance, the second appointment is just supposed to highlight June 12 in red.  Instead, it highlights from June 1 to June 12.  The others show the same kind of thing -- highlighting the entire month in the appropriate color until the value stored in the today variable.  I'm not exactly sure where the problem lies.  I'm having a hard time following the for-loop and the myriad if-statements it has.  I thought the problem lied where if-3 and else-1 are in the loop, as both check to see if dayno >= apps[app][0], but commenting it out didn't help.  Any ideas?
Using 'global' is a sign of doing it wrong

#11 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 15 October 2006 - 06:01 PM

Well, to be honest, I have no idea why you have that if/else/switch logic... it's quite confusing.  As for your problem, my guess would be that a variable isn't being reset.
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#12 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 15 October 2006 - 09:55 PM

Well, to be honest, I have no idea why you have that if/else/switch logic... it's quite confusing.  As for your problem, my guess would be that a variable isn't being reset.


Well, like I said before, the vast majority of the script was written before I got to it.  All I did was try to append the switch statements as I was told that the rest worked fine.  Unfortunately, I found that to not be the case (my previous message).

I'm now trying to re-write the script from scratch.  I've written a basic test script to see if I can print out at least one month correctly.  I figure I can modify that to print all months correctly once it works right.  Unfortunately, nothing is being printed to the screen so far, and I'm not sure why.  My code (which is in an external .js file) is:

var W3CDOM = (document.createElement && document.getElementsByTagName);

var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var firstDays = [1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6];

function init(){
   if(!W3CDOM) return;
   printJanuary();
}

function printJanuary(){
   document.write("<table><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thur</th><th>Fri</th><th>Sat</th><tr>");
   var start = firstDays[0];
   var offset = 0;

   while(offset < start){
      document.write("<td></td>");
      offset++;
   }

   for(var i = 1; i < numDays[0]; i++){
      if((i % 7) < 1){
         document.write("<td>" + i + "</td>");
      }

      else{
         document.write("</tr><tr><td>" + i + "</td>");
      }
   }

   document.write("</tr></table>");
}

window.onload = init;

I have other scripts that use the same basic setup.  I've never had a problem with this kind of initialization function being used in the window's onload event handler before, so I'm pretty sure that's not where the problem lies.  The XHTML is basically empty.  There's no structure other than the body.  Any ideas?

EDIT: I know I have a logic problem with the algorithm (the i % 7 bit), but I wouldn't think that would prevent anything from being printed.
Using 'global' is a sign of doing it wrong

#13 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 15 October 2006 - 11:56 PM

Well, first, I would only execute a single document.write() call.. I don't know why you're not seeing anything.  You should alert the string that you're building as you go along.
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#14 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 16 October 2006 - 03:58 PM

Hey, fenway, thanks for your help and patience.  I know it must get frustrating dealing with newbs like me, so I just wanted to let you know that I really do appreciate it. :)

I managed to get the calendars to print, but I seem to have a logic problem.  In my testing, my months beginning on any day but Sunday all printed fine.  But the months that start on a Sunday (April and I believe July) kept being printed as though they started on a Monday, and I'm not 100% sure why.  I have a while-loop (which you'll see below) that prints off the blank days at the beginning of each month, if there are any.  It appears that whenever a month starts on a Sunday, that while-loop still fires one time.  I've tried different conditionals in there (start != 1 && pos < start, pos < (start - 1)), but none have worked so far.  Any ideas?

var W3CDOM = (document.createElement && document.getElementsByTagName);

var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var firstDays = [2, 5, 5, 1, 3, 6, 1, 4, 7, 2, 5, 7]; //1 = Sunday, 2 = Monday, etc.

function init(){
   if(!W3CDOM) return;
   printMonth();
}

function printMonth(){
   bod = document.getElementById('bod'); //My body element has an id of bod
   var output = '<table><br /><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th><br /><tr style="text-align: right;"><br />';
   var start = firstDays[6];
   var pos = 1;

   while(pos < start){
      output += '<td></td>';
      pos++;
   }


   for(var i = 1; i <= numDays[6]; i++){
      if ((pos / 6) <= 1){
         output += '<td>' + i + '</td>';
         pos++;
      }

      else{
         output += '</tr><br /><tr style="text-align: right;"><td>' + i + '</td>';
         pos = 1;
      }
   }

   output += '</tr><br /></table>';
   bod.innerHTML = output;
}

window.onload = init;

Using 'global' is a sign of doing it wrong

#15 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 16 October 2006 - 10:27 PM

Never mind.  I figured it out.  Apparently, I'm an idiot. :lol:
Using 'global' is a sign of doing it wrong

#16 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 18 October 2006 - 03:11 PM

I figured I'd use this thread to pose my next question as I'm still writing my calendar/appointments script and I don't want to pollute the board with another new thread.

With my current setup (XHTML at http://www.nightslyr.../calendar3.html), I have the calendars' structure coded directly in the markup.  I give each month's table an id (the month name), and I give each cell of the first week of every month an id based on position (1 = Sunday, 2 = Monday, etc) so I can start outputting my dates at the right spot.

What I'm wondering is this: Say I want to print February, which I believe started on a Thursday this year.  I put the number 1 inside the cell February5 (first Thursday of February).  Is there an easy way for me to print dates 2-28, in this instance, without having to give every cell in my calendars an id, thereby not having to use document.getElementById for every single date?

Thanks. :)
Using 'global' is a sign of doing it wrong

#17 fenway

fenway
  • Staff Alumni
  • MySQL Si-Fu / PHP Resident Alien
  • 16,199 posts
  • LocationToronto, ON

Posted 19 October 2006 - 04:51 PM

I don't see why you can't do this on the fly.
Seriously... if people don't start reading this before posting, I'm going to consider not answering at all.

#18 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 20 October 2006 - 01:29 PM

Actually, I found an even better way to do it -- getElementsByTagName.  Just start the loop at the proper start day of that array, and iterate through it until the end of the month.  For some reason, I always forget about that method until I need to use it.

My script seems to be working properly now.  I just need to tweak some CSS for the legend/key to look good.

Again, thanks for your patience and help! :)
Using 'global' is a sign of doing it wrong

#19 obsidian

obsidian
  • Staff Alumni
  • Advanced Member
  • 3,202 posts
  • LocationSeattle, WA

Posted 20 October 2006 - 01:34 PM

ok, nightslyr, i've got a question for you: why are you completely redrawing the calendar for every month? IMHO, you'd be better off to draw up all your calendars using PHP and then use javascript to simply show the proper month based on what the user supplies. that way, you can simpy have a show/hide function where you pass it the ID of the div or table that contains the calendar you want to show.

is this an option, or could you just explain why you're writing the whole thing up to be written by javascript each month?

also, your link above comes up with a 404 error :(
You can't win, you can't lose, you can't break even... you can't even get out of the game.

<?php
while (count($life->getQuestions()) > 0)
{   $life->study(); } ?>
  LINKS: PHP: Manual MySQL: Manual PostgreSQL: Manual (X)HTML: Validate It! CSS: A List Apart | IE bug fixes | Zen Garden | Validate It! JavaScript: Reference Cards RegEx: Everything RegEx

#20 KevinM1

KevinM1
  • Moderators
  • Snarkimus Prime
  • 5,248 posts

Posted 20 October 2006 - 03:21 PM

ok, nightslyr, i've got a question for you: why are you completely redrawing the calendar for every month? IMHO, you'd be better off to draw up all your calendars using PHP and then use javascript to simply show the proper month based on what the user supplies. that way, you can simpy have a show/hide function where you pass it the ID of the div or table that contains the calendar you want to show.

is this an option, or could you just explain why you're writing the whole thing up to be written by javascript each month?

also, your link above comes up with a 404 error :(


Ah, well, like I originally said, I was doing this to help someone on another message board and to get more experience using JavaScript myself.  If I was doing something like this for myself, PHP would be the only way I'd do it.  I'd have a form that would allow users to input their appointments, rather than to code them directly into the script (which is what the JS script relies on now, which is horrible).  I'd also give it the option to either print out one month (like you suggested) or the entire year at once.

Since the person I was helping had made the original in JS and only wanted to have something that would properly print out different classes of appointments (he's a firefighter, so knowing when each watch is on duty seemed to be his biggest concern), and since I wasn't sure whether or not they have access to a db to store the appointments, I figured I might as well just rewrite it in the same language.  I did PM him with the suggestions I wrote above, though.  There's really no reason for him to be doing it the hard way if they have access to a db.  And now that I have it working in JS, transferring it over shouldn't be much of a problem if they do decide to go that route.  The logic should basically remain the same.

The 404 error stems from me renaming my html file.  I tend to save drafts as I go in case I need something from a previous version, so the one I last linked to was the third draft.  The new, working link is http://www.nightslyr...calendar.html.  Most of the appointments on there were tests to ensure that they printed correctly over multiple months and that the proper color for multiple appointments on the same day printed when needed.  The appointment info itself is displayed when the mouse is hovering over an appointment day...the cell's title property does that, rather than an event handler.

It's not pretty, but it's functional.
Using 'global' is a sign of doing it wrong




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users