Page refresh throws JavaScript error

C

Chris Beall

(I'm rather inexperienced with JavaScript; the failing page was cobbled
together from multiple sources)...

http://pages.prodigy.net/chris_beall/STL/Timeline.html

If JavaScript is not present, or CSS 2 isn't supported, the page just
shows a complete list of dated entries. That's correct.

If JavaScript is present and CSS 2 is supported, a subset of the list is
shown (Example: 9 Jan 2008 is absent) and a button appears in the upper
right, which the user can press to see the complete list. If the button
is pressed, the complete list is shown and the button text changes,
prompting the user to press it again to hide some entries. Pressing the
button again returns things to the initial state (subset of list).
That's correct.

BUT, on Opera (and reportedly Safari), if the user REFRESHes the page,
it appears with the correct version of the button, but the complete
list, instead of the subset, is shown. That's wrong. (Some entries in
the list are hidden by changing, via script, the display property in the
last entry in the associated style sheet.)

It does not fail on Opera if accessing a local copy of the page.
It does not fail in Firefox.

On a refresh (but not when the page is first loaded) the Opera Error
Console shows:
Inline script thread
Error:
name: TypeError
message: Statement on line 23: Cannot convert undefined or null to Object
Backtrace:
Line 23 of inline#1 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html: In function changeIt
theRules[theRules.length-1].style.display = result;
Line 6 of inline#2 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html
changeIt('none');

It seems to me that either there's a browser bug here (in two browsers)
or there is something I don't know about how JavaScript is processed on
a page refresh from a remote server. I suspect the latter.

Any suggestions would be appreciated.

Thanks,
Chris Beall
 
Á

Álvaro G. Vicario

Chris Beall escribió:
Inline script thread
Error:
name: TypeError
message: Statement on line 23: Cannot convert undefined or null to Object
Backtrace:
Line 23 of inline#1 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html: In function
changeIt
theRules[theRules.length-1].style.display = result;
Line 6 of inline#2 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html
changeIt('none');

In the page you took this code from (the URL is inside a comment), this
is what they say:

"Unfortunately browser incompatibilities are so severe that this script
isn't really usable in practice yet."

You may find it easier to loop all your <li>'s and add or remove a
special class, something like "hide":

..hide{
display: none;
}

Use getElementsByClassName() to find tags with "action" class:

http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/


And then use addClass() and removeClass() to show or hide:

http://dean.edwards.name/IE7/caveats/


I see nothing wrong in your current approach but you'd need a
cross-browser script to do so and I can't help you with it.
 
P

pr

Chris said:
http://pages.prodigy.net/chris_beall/STL/Timeline.html
[...]
On a refresh (but not when the page is first loaded) the Opera Error
Console shows:
Inline script thread
Error:
name: TypeError
message: Statement on line 23: Cannot convert undefined or null to Object
Backtrace:
Line 23 of inline#1 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html: In function
changeIt
theRules[theRules.length-1].style.display = result;
Line 6 of inline#2 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html
changeIt('none');

It seems to me that either there's a browser bug here (in two browsers)
or there is something I don't know about how JavaScript is processed on
a page refresh from a remote server. I suspect the latter.

Neither; you are simply calling the function before the page has fully
loaded, with predictably unpredictable results.

In this case, document.styleSheets[0].cssRules.length alternates between
zero and 22 (in Opera 9.51), the former case making a nonsense of the line

theRules[theRules.length-1].style.display = result;

since theRules[-1] doesn't exist.

Put your call to changeIt() in body onload. As security, check that
theRules.length > 0 before attempting to use its contents.
 
C

Chris Beall

pr said:
Chris said:
http://pages.prodigy.net/chris_beall/STL/Timeline.html
[...]
On a refresh (but not when the page is first loaded) the Opera Error
Console shows:
Inline script thread
Error:
name: TypeError
message: Statement on line 23: Cannot convert undefined or null to
Object
Backtrace:
Line 23 of inline#1 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html: In function
changeIt
theRules[theRules.length-1].style.display = result;
Line 6 of inline#2 script in
http://pages.prodigy.net/chris_beall/STL/Timeline.html
changeIt('none');

It seems to me that either there's a browser bug here (in two
browsers) or there is something I don't know about how JavaScript is
processed on a page refresh from a remote server. I suspect the latter.

Neither; you are simply calling the function before the page has fully
loaded, with predictably unpredictable results.

In this case, document.styleSheets[0].cssRules.length alternates between
zero and 22 (in Opera 9.51), the former case making a nonsense of the line

theRules[theRules.length-1].style.display = result;

since theRules[-1] doesn't exist.

Put your call to changeIt() in body onload. As security, check that
theRules.length > 0 before attempting to use its contents.


pr,

Thanks, I suspected something like that. So, although both my
JavaScript functions and the <link> to the stylesheet are within the
<head> of the page, there is no guarantee that they will be completely
processed before the contents of <body>. So it's a race condition and
sometimes I win and sometimes I lose.

If I understand your suggestion, using onload guarantees that the onload
function will not be kicked off until everything else has stabilized, as
loosely documented at
http://www.w3.org/TR/html401/interact/scripts.html#adef-onload

Also, how did you determine the (varying) value of
document.styleSheets[0].cssRules.length? I'd probably add a statement
to display it via a document.write, but perhaps there's another way that
I should know about.

Many thanks,
Chris Beall
 
P

pr

Chris said:
If I understand your suggestion, using onload guarantees that the onload
function will not be kicked off until everything else has stabilized, as
loosely documented at
http://www.w3.org/TR/html401/interact/scripts.html#adef-onload

Putting it generally, yes. The important thing is that putting the call
in body onload guarantees that DOM collections like document.images and
document.stylesheets have been populated and that methods you expect to
work across all the nodes in a document, like getElementsByTagName() are
in a position to do so.
Also, how did you determine the (varying) value of
document.styleSheets[0].cssRules.length? I'd probably add a statement
to display it via a document.write, but perhaps there's another way that
I should know about.

Just the trusty window.alert():

if (document.styleSheets[0].cssRules){
theRules = document.styleSheets[0].cssRules
alert("cssRules " + document.styleSheets[0].cssRules.length);
}

You'll be using that a lot :)
 
H

Henry

Chris Beall wrote:
Also, how did you determine the (varying) value of
document.styleSheets[0].cssRules.length? ...
Just the trusty window.alert():

if (document.styleSheets[0].cssRules){
theRules = document.styleSheets[0].cssRules
alert("cssRules " + document.styleSheets[0].cssRules.length);
}

You'll be using that a lot :)

This is true, but the drawbacks of using - alert - for testing/
reporting/debugging could be mentioned. They can tell you the state at
the point when they open but opening the alert has consequences. It
blocks the execution of the code that opens it, but in doing that
frees to browser to do other things (so race conditions where a script
is racing the browser will be radically altered).

Also, they take the input focus, and so events such as onfocus, onblur
and onchnage may be triggered wherever the focus had been when the -
alert - opened. Making - alerts - problematic when examining
interactions. This problem is quite well illustrated by this page by
John Resig:-

<URL: http://ejohn.org/blog/most-bizarre-ie-quirk >

- where totally bogus conclusions have been drawn as a result of
attempting to examine features of browser/mouse interactions using an
- alert -; Replacing his test code with:-

var count = 0;
setInterval(function(){
window.status = ++count;
}, -1);

- makes an obvious nonsense of all of the conclusions drawn.

Non-blocking reporting that does not take focus used to be commonly
achieved by writing the - window.status - property, which resulted in
the written message appearing in the browser's status bar. Modern
browsers increasingly default to not allowing status bar writing by
scripts, and so need it to be enabled by the user if that technique is
to be used.

However, modern browsers (at least while using an HTML DOM) also allow
writing the innerHTML of elements, giving another easy option for non-
blocking reporting. Though more use while learning and formal testing
than in debugging a 'finished' project (as adding an element to write
into may not be practical or consequence free).
 
J

Jorge

Non-blocking reporting that does not take focus used to be commonly
achieved by writing the - window.status - property, which resulted in
the written message appearing in the browser's status bar. Modern
browsers increasingly default to not allowing status bar writing by
scripts, and so need it to be enabled by the user if that technique is
to be used.

However, modern browsers (at least while using an HTML DOM) also allow
writing the innerHTML of elements, giving another easy option for non-
blocking reporting. Though more use while learning and formal testing
than in debugging a 'finished' project (as adding an element to write
into may not be practical or consequence free).

javascript:document.title= "now debugging";

--Jorge.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top