2

I'm working on a little website that houses some resources for one of the departments at my university. Everything is coming along pretty well, so I'm trying to add a little bit of functionality to make things more intuitive.

If you want to see the full HTML structure and everything else, here's the page in question: {link removed to protect personal content}

Basically, it's a table with a row dedicated to each of the camps that we're responsible for this summer. This is all fine and dandy. What I want to do, now, is highlight the rows of any camps currently in session (by adding the class "active" to the row). Given my fairly limited experience with JavaScript, this is what I came up with:

<script type="text/javascript" >
$(document).ready(function() {
    var today = new Date();

    var Traffic_Court_Start = new Date("May 31 2012 12:01 AM");
    var Traffic_Court_Stop = new Date("June 1 2012 11:59 PM");
    var Summer_Enrichment_Start = new Date("June 10 2012 12:01 AM");
    var Summer_Enrichment_Stop = new Date("June 16 2012 11:59 PM");
    var Wbb_Ind_Start = new Date("June 11 2012 12:01 AM");
    var Wbb_ind_Stop = new Date("June 14 2012 11:59 PM");
    var Soccer_Referee_Start = new Date("June 15 2012 12:01 AM");
    var Soccer_Referee_Stop = new Date("June 16 2012 11:59 PM");
    var Broadcast_Start = new Date("June 17 2012 12:01 AM");
    var Broadcast_Stop = new Date("June 21 2012 11:59 PM");
    var Tennis_1_Start = new Date("June 17 2012 12:01 AM");
    var Tennis_1_Stop = new Date("June 21 2012 11:59 PM");
    var Tennis_2_Start = new Date("June 24 2012 12:01 AM");
    var Tennis_2_Stop = new Date("June 28 2012 11:59 PM");
    var Volleyball_Start = new Date("July 8 2012 12:01 AM");
    var Volleyball_Stop = new Date("July 11 2012 11:59 PM");
    var Soccer_1_Start = new Date("July 8 2012 12:01 AM");
    var Soccer_1_Stop = new Date("July 12 2012 11:59 PM");
    var IACAC_Start = new Date("July 9 2012 12:01 AM");
    var IACAC_Stop = new Date("July 11 2012 11:59 PM");
    var Summer_Forensics_Start = new Date("July 15 2012 12:01 AM");
    var Summer_Forensics_Stop = new Date("July 28 2012 11:59 PM");
    var Soccer_2_Start = new Date("July 22 2012 12:01 AM");
    var Soccer_2_Stop = new Date("July 26 2012 11:59 PM");
    var Cross_Country_Start = new Date("July 25 2012 12:01 AM");
    var Cross_Country_Stop = new Date("July 28 2012 11:59 PM");

    if((today <= Traffic_Court_Stop && today >= Traffic_Court_Start))
        {
            document.getElementById('traffic_court').classList.add('active');
        };

    if((today <= Summer_Enrichment_Stop && today >= Summer_Enrichment_Start))
        {
            document.getElementById('summer_enrichment').classList.add('active');
        };

    if((today <= Wbb_Ind_Stop && today >= Wbb_Ind_Start))
        {
            document.getElementById('wbb_ind').classList.add('active');
        };

    if((today <= Soccer_Referee_Stop && today >= Soccer_Referee_Start))
        {
            document.getElementById('soccer_referee').classList.add('active');
        };

    if((today <= Broadcast_Stop && today >= Broadcast_Start))
        {
            document.getElementById('broadcast').classList.add('active');
        };

    if((today <= Tennis_1_Stop && today >= Tennis_1_Start))
        {
            document.getElementById('tennis_1').classList.add('active');
        };

    if((today <= Tennis_2_Stop && today >= Tennis_2_Start))
        {
            document.getElementById('tennis_2').classList.add('active');
        };

    if((today <= Volleyball_Stop && today >= Volleyball_Start))
        {
            document.getElementById('volleyball').classList.add('active');
        };

    if((today <= Soccer_1_Stop && today >= Soccer_1_Start))
        {
            document.getElementById('soccer_1').classList.add('active');
        };

    if((today <= IACAC_Stop && today >= IACAC_Start))
        {
            document.getElementById('IACAC').classList.add('active');
        };

    if((today <= Summer_Forensics_Stop && today >= Summer_Forensics_Start))
        {
            document.getElementById('summer_forensics').classList.add('active');
        };

    if((today <= Soccer_2_Stop && today >= Soccer_2_Start))
        {
            document.getElementById('soccer_2').classList.add('active');
        };

    if((today <= Cross_Country_Stop && today >= Cross_Country_Start))
        {
            document.getElementById('cross_country').classList.add('active');
        };
});
</script>

As you can see, I start by getting today's date, then I specify the start and end dates for each of the camps. Then, I use a bunch of if-statements to determine if 'today' is in between the start and end dates for each camp. If that is true, it adds the class "active" to the row corresponding to that camp.

It seems to work correctly for the first two camps...that is, if I change the value of 'today' to May 31 it highlights the first row. Or if I change it to June 15 it highlights the second row. The problem is that if 'today' is June 15, it should highlight BOTH the summer_enrichment and soccer_referee rows. It only highlights the summer_enrichment row.

I've double-checked the element IDs that I reference, the spelling of my variables, etc. and everything seems to look correct (unless I missed something obvious). Is there any reason why I can't use the script as I've presented it? I don't think this is the case, but is there a problem with using so many if-statements in a row like that? My only thought is that perhaps it thinks they are a bunch of else-cases but I thought I'd escape that with the semi-colon after each if-statement.

Any thoughts? Perhaps a better way to do this? I looked around for some answers but couldn't seem to find something similar anywhere else (though I'm sure this has been done before and with better implementation).

THANKS FOR YOUR HELP!!!

EDIT: After getting everything to work with the help of some of these responses, I figured I'd share the final code for future users who might stumble upon this question.

<script type="text/javascript">
$(document).ready(function() {
    var today = new Date();

    var SCHEDULE = {
        'tc': ['May 31 2012', 'June 1 2012'],
        'se': ['June 10 2012', 'June 16 2012'],
        'wbb': ['June 11 2012', 'June 14 2012'],
        'sr': ['June 15 2012', 'June 16 2012'],
        'broadcast': ['June 17 2012', 'June 21 2012'],
        'ten1': ['June 17 2012', 'June 21 2012'],
        'ten2': ['June 24 2012', 'June 28 2012'],
        'volleyball': ['July 8 2012', 'July 11 2012'],
        'soc1': ['July 8 2012', 'July 12 2012'],
        'iacac': ['July 9 2012', 'July 11 2012'],
        'sf': ['July 15 2012', 'July 28 2012'],
        'soc2': ['July 22 2012', 'July 26 2012'],
        'cc': ['July 25 2012', 'July 28 2012']
    };

    for (var camp in SCHEDULE) {
    console.log('checking ' + camp + ', dates have to be within the ' + SCHEDULE[camp] + ' range');
    //console.log(Date.parse(SCHEDULE[camp][0]));
        if (today >= Date.parse(SCHEDULE[camp][0]) && today <= Date.parse(SCHEDULE[camp][1])) {
            console.log(camp + ' is currently in session!');
            document.getElementById(camp).classList.add('active'); 
        };
    };
});
</script>

THANKS A LOT EVERYONE!!!

3
  • For some reason, the variables for IACAC_Start and IACAC_Stop above aren't highlighted like the rest...I wonder why? Commented May 17, 2012 at 1:08
  • Are your end/start times database-generated at all? Commented May 17, 2012 at 1:34
  • These dates aren't generated by a database...they are hard-coded into the document. Since this site will really only have two pages with this kind of list, I figured a database would be overkill. However, if it was database-related, then I could use the routine that fetches the data to set the class. Commented May 17, 2012 at 1:38

5 Answers 5

2

I'd suggest the logic be done on the server-side so that unhighlighted content does not "flash" plus a marginal improvement in performance. An arguably more important improvement will be consistent rendering regardless of the client's time settings.

While I strongly advocate the above, the JS solution could be made into something more maintainable as well. Structure your code to contain a reusable function to check date against range and apply a class and normalize the way date references are stored:

var TODAY = new Date();

//Individual dates could be organized as objects,
//but using arrays below seems to be more readable and tidy
var SCHEDULE = {
    'some-class': ['May 5 2011', 'June 5 2011'],
    'some-class-a': ['May 5 2012', 'June 5 2012'],
    'some-class-b': ['May 10 2012', 'June 10 2012'],
    'some-class-c': ['May 15 2012', 'June 15 2012'],
    'some-class-d': ['May 20 2012', 'June 20 2012'],
    'some-class-e': ['May 25 2012', 'June 25 2012']
};

for (var camp_ in SCHEDULE) {
    if (TODAY >= Date.parse(SCHEDULE[camp_][0]) && TODAY <= Date.parse(SCHEDULE[camp_][1])) {
        document.getElementById(camp_).classList.add('active');
    }
}

Working fiddle here: http://jsfiddle.net/ovfiddle/bMBcq/

Sign up to request clarification or add additional context in comments.

2 Comments

Hey o.v., thanks for the response. While I agree with the points you make in the first argument, I'm not terribly worried about those issues in my application. It'll be used by 3-4 people who probably wouldn't even notice the cosmetic change of setting a row's class to 'active.' I did, however, end up organizing my dates into the array like you mentioned and made a couple of other little adjustments based on your suggestions. Worked perfectly! Thanks again for your help!
@TomWinchester: I see in your update above you're using jQuery (this was not obvious at first so my answer aspired to be independent from any library methods) - just a quick tip that to add class "active" you may very well choose to do so with $('#'+camp).addClass('active'); api.jquery.com/addClass
1

Comment:

In your code:

> var Traffic_Court_Start = new Date("May 31 2012 12:01 AM"); 

is dependent on regional settings understanding that date string format. Parsing of dates is implementation dependent and there is no reason to believe a US-specific format will work in all browers for all regions. The only format that is specified is ISO8601 in ES5 and not all browsers support that either. No format at all is specified in the earlier ECMAScript ed 3.

Also, the above creates a date object in the local timezone of the client, so two clients with different timezone settings (say one with daylight saving and one without) will resolve it to two different times.

If you must work with dates on the client, far better to do everything in UTC and convert to local date objects only where necessary. Also, confirm with the user that your code has got it right (e.g. display what you think the current date and time is based on the sysetm settings, which might be wrong or not synchronised with its current location).

Creating a local date object from UTC values is simple using Date.UTC():

var date = new Date(Date.UTC (year, month[, date[, hours[, minutes[, seconds[, ms]]]]]);

which can be turned into a simple function that accepts whatever format you like.

1 Comment

Hey RobG, thanks for this info. I completely agree with a lot of the fundamental concepts you're talking about here. However, this web application will only be used by a handful of people...all of which are using computers that are under my personal control. I'm not terribly worried about time-zone or location, either. Like I said, though, in most applications this would be incredibly important. One of your suggestions that I WILL implement, however, is the display of the date/time somewhere on the page so that the user has direct knowledge of what the server thinks the date is. THANKS!
1

Here's an attempt. Since you're not using a database, try storing your dates as data attributes. Convert them to timestamps so you can compare: http://jsfiddle.net/uJEJ7/26/

I'm sure I'm overlooking something, but maybe it'll spark an idea.

I noticed your page is written in PHP, it might be easier to go that route. Store your Camp data in an associative array, loop through it to generat the table rows, and output markup based on if your dates match.

Good luck!

1 Comment

That's a pretty good idea. Ultimately, I chose to go with o.v.'s response, but if I were to start all over again from scratch I'd probably go this route. THANKS!!!
0

I am not sure if you can use the greater/less-than operator on dates, but comparing their time stamps will definitely work as you will be working with numbers (milliseconds)

You can get timestamps like this:

var today = new Date().getTime();

2 Comments

Through my testing, I was able to use the > and < operators to document.write('Success') for a few different test cases. Though, I didn't try to apply it across 12-13 if-statements. If I try to compare the timestamps, will that be milliseconds from some fixed reference so that they can be compared? For instance, is that milliseconds from 1950 or something like that? THANKS!!!
@TomWinchester January 1, 1970, and yes, it a fixed reference. The greater the date, the more milliseconds it has
0

Check out date.js, specifically...

http://code.google.com/p/datejs/wiki/APIDocumentation#compare

Compares the first date to the second date and returns an number indication of their relative values. -1 = this is < date. 0 = values are equal. 1 = this is > date.

The isAfter() and the isBefore() methods might be useful for your problem :)

Download the library here:

http://code.google.com/p/datejs/downloads/detail?name=date.js&can=2&q=


Also, its worth mentioning to checkout moment.js. I think the two libraries complement each other.

3 Comments

Hey Hristo, thanks for this. I'd rather stay away from using third-party scripts if I can avoid it (for learning sake), but I'll look into this to see if there's something I can take from it.
ahhh... well, you could probably look in the source code and figure out how they implemented isAfter() and isBefore(). Also, do mention in your question that you'd like to avoid third-party scripts
Good greif, you don't need a date library to do simlpe arithmetic with dates, like date1 - date2 or date1 < date2.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.