Q: Automatically Changing Background Color of a Table Cell?


A

Arthur Shapiro

I'm the webmaster for a recreational organization. As part of one page of the
site, I have an HTML "Calendar at a Glance" of the organization's events for
the month. It's a simple table of a calendar, 7 across by whatever needed
down, and I manually create it each month - not a big deal.

Every day I go in and darken the background color of the current day's cell
by changing the appropriate <TD> entry to <TD bgcolor="c63800"> and uploading
the page. Takes well under a minute start to finish. Thus the calendar
gradually changes color over the course of the month, with the past dates dark
and the future dates lighter and thus more apparent to the eye.

But I have to ask if there's a nifty way in which this might be done
automatically, based on the current day and the number (the day of the month)
that follows the <TD> entry.

A typical "before" entry is

<TD>23<br>Peet's Coffee, Newport Beach<br><br>8 AM: Don<br>9 AM: Molly</TD>

and an "after" entry is

<TD bgcolor="c63800">23<br>Peet's Coffee, Newport Beach<br><br>8 AM: Don<br>9
AM: Molly</TD>

I don't pretend to be a javascript heavy, but can usually stumble my way
through a task given some words of wisdom. Is this "doable"?







Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
Ad

Advertisements

I

Ivo

Every day I go in and darken the background color of the current day's cell
by changing the appropriate <TD> entry to <TD bgcolor="c63800">
But I have to ask if there's a nifty way in which this might be done
automatically, based on the current day and the number (the day of the
month) that follows the <TD> entry.
A typical "before" entry is

<TD>23<br>Peet's Coffee, Newport Beach<br><br>8 AM: Don<br>9
AM: Molly</TD>

and an "after" entry is

<TD bgcolor="c63800">23<br>Peet's Coffee, Newport Beach<br><br>8
AM: Don<br>9 AM: Molly</TD>

First thought is to automate this on the server of course, but you don't
seem to do anything serverside. Turning to javascript for this will leave
users who have no javascript with a dull calendar where every day looks the
same.
Second thought is to use a class rather than bgcolor and specify the color
in a stylesheet. Not sure about the direct benefit of this tho.

Well, if all days start with the date's number right after the <TD> opening
tag (even whitespace in between may be a problem for some browsers) and the
whole table has an id, such as <table id="calendar">, then you could put
this right after the </table> tag:

<script type="text/javascript">
var now=new Date().getDate();
var td=document.getElementById('calendar').cells, i=td.length;
while ( i-- ) {
if ( td.firstChild.nodeValue <= now ){ td.bgColor = '#c63800'; }
}
</script>

td[n].firstChild would be the textnode, its value the text, ie. everything
up to the first <br>. This is compared to the variable "now", which today
for example is 29, and if smaller or equal (you say you change the current
day), the color is applied to the cell. Marking today in gold would take one
more line:
if ( td.firstChild.nodeValue < now ){ td.bgColor = '#c63800'; }
if ( td.firstChild.nodeValue == now ){ td.bgColor = '#ffd700'; }

hth
 
A

Arthur Shapiro

Well, if all days start with the date's number right after the <TD> opening
tag (even whitespace in between may be a problem for some browsers) and the
whole table has an id, such as <table id="calendar">, then you could put
this right after the </table> tag:

<script type="text/javascript">
var now=new Date().getDate();
var td=document.getElementById('calendar').cells, i=td.length;
while ( i-- ) {
if ( td.firstChild.nodeValue <= now ){ td.bgColor = '#c63800'; }
}
</script>


Very, very interesting...thank you! My only problem is that this script
happens to also change the color of the heading line that spans the top width
of the table ("December at a Glance") and the cells "Sunday"..."Saturday" that
are the top row above the actual date cells. But I think this gives me enough
ammunition to work with, to see if I can avoid affecting cells whose data
doesn't start with numeric tokens.

I'm most appreciative of your excellent suggestions. Clearly I'm going to
have to learn some more of this scripting "magic".

I guess the one laughably silly question is why the script should follow the
table in question; I don't appreciate yet when something goes fairly globally
in the html document, and when it immediately precedes or immediately follows
information in the document.

Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
I

Ivo

Ivo said:
Well, if all days start with the date's number right after the <TD> opening
tag (even whitespace in between may be a problem for some browsers) and the
whole table has an id, such as <table id="calendar">, then you could put
this right after the </table> tag:

<script type="text/javascript">
var now=new Date().getDate();
var td=document.getElementById('calendar').cells, i=td.length;
while ( i-- ) {
if ( td.firstChild.nodeValue <= now ){ td.bgColor = '#c63800'; }
}
</script>


Very, very interesting...thank you! My only problem is that this script
happens to also change the color of the heading line that spans the top width
of the table ("December at a Glance") and the cells "Sunday"..."Saturday"

that

Semantically speaking, shouldn't those cells be TH rather than TD elements?
That would exclude them from the coloring function, and you can style them
separately with CSS.
I guess the one laughably silly question is why the script should follow the
table in question; I don't appreciate yet when something goes fairly globally
in the html document, and when it immediately precedes or immediately follows
information in the document.

The script as is runs when the browsers finds it, because it is not put in a
function. The statements are simply there to be executed straight away. You
could wrap the whole in a function, put that function in the document's head
or an included file and call it onload. The only important thing is that the
element with id 'calendar' has to be there before the script sets off to
avoid error and failure. That is why I suggest putting the script after the
table, that way you can run it *before* the page finishes loading and most
users will never even see the uncolored table.

Ivo
 
A

Arthur Shapiro

Semantically speaking, shouldn't those cells be TH rather than TD elements?
That would exclude them from the coloring function, and you can style them
separately with CSS.

The Day names are, in fact, TH elements. They still seem to have been
affected by the script. But I'll klutz around as time permits - I'm sure this
can be made to work. If you care, the calendar is on the page
http://www.ocrebels.com/rides.htm although that page does not include your
script - I'm obviously going to work with it at my end until it functions as I
desire.



Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
R

Richard Cornford

Ivo wrote:
<script type="text/javascript">
var now=new Date().getDate();
var td=document.getElementById('calendar').cells, i=td.length;
while ( i-- ) {
if ( td.firstChild.nodeValue <= now ){ td.bgColor =
'#c63800';
}
}

<snip>

Doesn't - getDate - return the (client) local date? I would have thought
that there is a time zone problem in this script (that may elude the OP
if not mentioned, as local testing would not expose it).

Richard.
 
Ad

Advertisements

I

Ivo

The Day names are, in fact, TH elements. They still seem to have been
affected by the script.

My mistake. I was mixed up between x.getElementsByTagName('td') and x.cells
which also collects TH elements. The first is the standard way, but the
latter is much faster and better supported among browsers.
But I'll klutz around as time permits - I'm sure this
can be made to work.

Without doubt:

while ( i-- ) {
day=td.firstChild.nodeValue;
if ( /^\d/.test(day) && day <= now ){ td.bgColor = '#c63800'; }
}

The bit that reads /^\d/.test(day) is a regular expression which will
evaluate to true for strings starting with a digit and false otherwise. This
should solve the issue as long the content in the TH cells starts with
letters. I have copied your table together with the script to a temporary
testpage at http://4umi.com/web/javascript/arthur.htm; the changes to the
HTML I made were adding the id to the table, correcting a typo at 8 December
and removing all bgcolors.
hth
 
R

RobG

Ivo said:
My mistake. I was mixed up between x.getElementsByTagName('td') and x.cells
which also collects TH elements. The first is the standard way, but the
latter is much faster and better supported among browsers.

Another way is to put the heading stuff in a thead element, then put
the dates in a tbody. Locate the tbody using the script and go from
there. It will exclude any elements in the thead or tfoot.

Incidentally, tables are supposed to have tbody tags, but since almost
no one puts them in the HTML, browsers just put 'em where it seems
appropriate.
 
A

Arthur Shapiro

Without doubt:

while ( i-- ) {
day=td.firstChild.nodeValue;
if ( /^\d/.test(day) && day <= now ){ td.bgColor = '#c63800'; }
}

Thank you again! I was going to fool with regular expressions after work
today, and you beat me to it.

Your table displays cleanly in IE, but not in Firefox. I'll be checking my
settings later today. And there's some additional corruption in Firefox. But
I'm sure I can reason things out at this point. This has all been very
interesting, and tells me that the more Javascript I can learn, the better
things will be.

The comment about time zones was valid, but fortunately not a realistic
concern for our local organization.

I'm most appreciative of the assistance.

Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
F

Fred Oz

Arthur Shapiro wrote:
[...]
Your table displays cleanly in IE, but not in Firefox. I'll be checking my
settings later today. And there's some additional corruption in Firefox. But

Try:

if ( /^\d/.test(day) && day <= now ) {
td.style.backgroundColor = '#c63800';
}
 
L

Lee

Fred Oz said:
Arthur Shapiro wrote:
[...]
Your table displays cleanly in IE, but not in Firefox. I'll be checking my
settings later today. And there's some additional corruption in Firefox. But

Try:

if ( /^\d/.test(day) && day <= now ) {
td.style.backgroundColor = '#c63800';
}


I may have overlooked something, but isn't (day <= now) going to be evaluated as
a string comparison? That would give surprising results on January 2.
 
Ad

Advertisements

D

Dr John Stockton

JRS: In article <[email protected]>, dated Wed, 29
Dec 2004 07:26:53, seen in Richard Cornford
Ivo wrote:
<script type="text/javascript">
var now=new Date().getDate();
var td=document.getElementById('calendar').cells, i=td.length;
while ( i-- ) {
if ( td.firstChild.nodeValue <= now ){ td.bgColor =
'#c63800';
}
}

<snip>

Doesn't - getDate - return the (client) local date? I would have thought
that there is a time zone problem in this script (that may elude the OP
if not mentioned, as local testing would not expose it).


An American recreational organisation probably ignores distant parts of
the country, let alone the rest of the world.

But one wonders whether the code includes 864e5 or the equivalent; and,
if so, whether it does so safely.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Wed, 29 Dec 2004
08:28:07, seen in Lee
Fred Oz said:
Arthur Shapiro wrote:
[...]
Your table displays cleanly in IE, but not in Firefox. I'll be checking my
settings later today. And there's some additional corruption in Firefox. But

Try:

if ( /^\d/.test(day) && day <= now ) {
td.style.backgroundColor = '#c63800';
}


I may have overlooked something, but isn't (day <= now) going to be evaluated as
a string comparison? That would give surprising results on January 2.



If so, assuming variable now to be an integer, using +day should
suffice; also untested.
 
A

Arthur Shapiro

I've been poking around on the web for a couple days, and aside from a few
vauge reports of folks having trouble with firstchild with Mozilla and
Firefox, I haven't really gotten anywhere. Do any of you "heavies" have some
advice? Again, the suggested constructs seem to work as expected in IE, but
not in Mozilla/Firefox. I haven't tried Opera but this is sufficiently a
show-stopper to not proceed further. Am I doomed?

A second question. I went to my bookshelf, which includes both HTML and
Javascript references, and found absolutely nothing on FirstChild and its
various methods and subfields such as NodeValue. Does anyone have any
favorite references? I'm happy to purchase a couple of books that might be
recommended.


Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
R

Richard Cornford

Arthur Shapiro wrote:
... . Do any of you "heavies"
have some advice? ...
<snip>

If you like: Stop vaguely talking about problems you are having and
instead create and present a functional minimal test-case that
demonstrates it in isolation (along with an exact and specific
description of what it is intended to demonstrate).

Richard.
 
A

Arthur Shapiro

instead create and present a functional minimal test-case that
demonstrates it in isolation (along with an exact and specific
description of what it is intended to demonstrate).[/QUOTE]

OK, fair enough - as it had only been a couple of days I was working under the
assumption that it was a "current" topic.

Take a look at the minimal test case:

http://www.ocrebels.com/javascripttest.htm

This is one row of an html table-based calendar, with javascript courtesy of a
very helpful participant in this forum. The script is intended to change the
bgcolor of cells representing dates prior to today's date.

It does, in Internet Explorer.

It doesn't in Mozilla or Firefox. About the only obvious curiosity is that
the Mozilla javascript console reports "td has no properties" - which is
certainly true.

So the apparent question is: "is there something I need to know about
Javascript as implemented for Mozilla/Firefox, so I can achieve the same
functionality as seems to occur with IE?"






Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 
Ad

Advertisements

I

Ivo

I've been poking around on the web for a couple days, and aside from a few
vauge reports of folks having trouble with firstchild with Mozilla and
Firefox, I haven't really gotten anywhere.
Again, the suggested constructs seem to work as expected in IE,
but not in Mozilla/Firefox. I haven't tried Opera.

Changing
document.getElementById('calendar').cells
to
document.getElementById('calendar').getElementsByTagName('td')

has made also Mozilla 1.0 understand the idea. Haven't tried other browsers.
I find it strange that we must resort to getElementsByTagName when the good
ol' TABLE DOM provides such excellent collections as x.rows and x.cells.
Perhaps they only exist if you access the calendar not by its id but as a
table:

document.getElementsByTagName('table')[0].cells // or 1 or 2 or ..

Perhaps the problem lies with the fact that the code dicussed earlier here
doesnot currently include proper feature detection or any error trapping.
Using getElementById, one should always test not only the id in question,
but also the existence of the method:

if( document.getElementById && document.getElementById('someid') )

Likewise, using firstChild.NodeValue, we should perhaps test the existence
of the firstChild before accessing its nodeValue. In our case, an empty cell
such as the days in November might lead Mozila to believe it should error
because td.firstChild is null and it has no nodeValue property to look
into. The syntax:

day=td.firstChild && td.firstChild.nodeValue;

because tests /evaluate/ to true or false, but /return/ the actual test
value. Here the outcome might become either a variable of type 'string' with
some text from the cell, or a variable of type 'null' if that 's what
td.firstChild is. And comparing null with the date number is just fine in
this table. After all:

(null < 1) === true;
A second question. I went to my bookshelf, which includes both HTML and
Javascript references, and found absolutely nothing on FirstChild and its
various methods and subfields such as NodeValue. Does anyone have any
favorite references?

Note that javascript is case-sensitive. This means firstchild and FirstChild
are not the same thing. In fact, neither is anything by default. The element
known to the DOM as x.firstChild (small f, capital C) is shorthand for
x.childNodes[0], ie. the first element -- or node -- that is a sub-element
of x. Look for javascript+firstChild on the web, plenty of examples can be
found, including <
http://www.zvon.org/xxl/DOM2reference/DOM2/Output/data/examples/Node_firstCh
ild.html >. The specification about nodes and their properties can be found
at < http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247 >.

Strictly speaking, elements and nodes are not the same thing. Nodes can be
of type element (say HTML tags), in which they may contain other nodes, or
they are the bits of text between the actual tags. And also:

x.lastChild === x.childNodes[x.childNodes.length-1];

I updated the tstpage < http://4umi.com/web/javascript/arthur.htm > with the
Mozilla1.0 code.

Happy '05,
 
R

Richard Cornford

Ivo wrote:
Changing
document.getElementById('calendar').cells
to
document.getElementById('calendar').
getElementsByTagName('td')

has made also Mozilla 1.0 understand the idea. Haven't tried
other browsers. I find it strange that we must resort to
getElementsByTagName when the good ol' TABLE DOM provides
such excellent collections as x.rows and x.cells. ...
<snip>

The 'TABLE DOM'? The W3C HTML DOM specifies a - rows - property of the
HTMLTableElement interface but a - cells - collection is only to be
found on HTMLTableRowElement. A usual Mozilla/FireFox is following the
specification, but not providing all of the 'convenience' properties
that IE implements in addition.

Richard.
 
Ad

Advertisements

A

Arthur Shapiro

Changing
document.getElementById('calendar').cells
to
document.getElementById('calendar').getElementsByTagName('td')

has made also Mozilla 1.0 understand the idea.


Thank you once again, and I'm going to carefully consider the remainder of
your message. I feel the absence of having a good, accessible reference
forced me to request help where it might not otherwise have been necessitated.
The URL you suggested will be scrutinized.

A general question: as you can tell, I'm a javascript novice (although a
software engineer with decades of experience). What sort of tools are
available for stepping through and otherwise debugging a small script such as
the one in question? That seems like a practical way to pick up this stuff.
Clearly it takes time and a lot of false steps to reach your obvious level of
proficiency.

Art
Temporary usercode - to be deleted when spam starts. Use MyBrainHurts at this ISP to reach me
 

Top