lkrubner@geocities.com (lawrence) writes:
[color=blue]
> I'm learning Javascript. I downloaded a script for study.[/color]
Bad idea :)
It's not a very good script, and not something you should learn
too much from, perhaps apart from what not to do. So, let's help
you with that :)
[color=blue]
> Please tell me how the variable "loop" can have scope in the first
> function when it is altered in the second function? It is not
> defined in global space, therefore it is not a global variable, yes?[/color]
Actually, in Javascript, a variable that isn't defined previously, and
is assigned to, will be created as a global variable (you still can't
read an undefined variable, only write to it).
However, in this case, "loop" is a *local* variable in the first
function, so the "loop" in the second function definitly isn't
the same variable.
[color=blue]
> Even if it was global, how would it get from one function to
> another?[/color]
If it was global, they would both be referring to the same variable.
[color=blue]
> In PHP variables are copied by value. Are they copied by
> reference in Javascript?[/color]
No. Arguments are passed by value.
So, comments on the script:
[color=blue]
> <SCRIPT LANGUAGE="JavaScript">[/color]
should be:
<script type="text/javascript">
to be correct HTML 4.
[color=blue]
> <!-- Original: Eddie Traversa (psych3@primus.com.au) -->[/color]
I don't recommend using HTML comments inside a script tag. Browsers
accept it, buy it isn't Javascript. A Javascript comment is
/* this is a comment *.
or
// comment to end of line
[color=blue]
> <!-- Begin[/color]
This line is supposed to hide the script from browsers that don't
understand the "script" tag. Browser have understood the script
tag since Netscape 2. It isn't necessary any more.
[color=blue]
> function verScroll(dir, spd, loop) {
> loop = true;[/color]
So, this function takes three arguments, but the value of the third is
immediately set to "true". Didn't he know how to declare a local variable
(that would be:
var loop = true;
but arguments are also local variables).
[color=blue]
> direction = "up";[/color]
Unless another function, outside the scope of this one, uses the
variable, it should be declared as local:
var direction = "up";
[color=blue]
> speed = 10;
> scrolltimer = null;[/color]
ditto, ditto.
[color=blue]
> if (document.layers) {
> var page = eval(document.contentLayer);[/color]
Here he checks whether the "document.layers" object exists. This is
supposed to identify a Netscape 4 browser (although at least one other
browser also has a non-null "document.layers" property).
After that, he uses "eval" to evaluate the string stored as the
property "document.contentLayer". However, I doubt that
"document.contentLayer" refers to a string. More likely it is a positioned,
named element, i.e., and object, so eval just returns that object
and does nothing.
[color=blue]
> } else {
> if (document.getElementById) {
> var page= eval("document.getElementById('contentLayer').styl e");[/color]
Then we test for the existence of "document.getElementById" and
actually try to use the detected method ... badly. The "eval" here
is completely unnecessary. Just do:
var page = document.getElementById('contentLayer').style;
At least the "eval" does something. It's just not a good way to do it. :)
[color=blue]
> } else {
> if (document.all) {[/color]
Then we test for document.all, and if it exists, we use it.
[color=blue]
> var page = eval(document.all.contentLayer.style);[/color]
Again the call to "eval" does nothing and can be omitted.
[color=blue]
> direction = dir;[/color]
Now we overwrite the value of "direction" (set to "up" above, and not
used yet, so that initialization was wasted).
[color=blue]
> speed = parseInt(spd);[/color]
Then we convert "spd" to an integer. The function "parseInt" converts
its argument to a string, and then parses that string. If the argument
"spd" was already a number, using "Math.floor" would probably be better.
If the argument is a string, parseInt should be given a second argument,
the base for the number, to avoid, e.g., the string "024" being inter
preted as octal (giving 30, not 24). So:
speed = Math.floor(spd);
[color=blue]
> var y_pos = parseInt(page.top);[/color]
ditto.
[color=blue]
> if (loop == true) {[/color]
But "loop" *is* true, we set it to that in the first line of the
function.
It's not necessary to compare to a boolean in a test. The comparison
creates a boolean, but we already had one of those, so:
if (loop)
(if "loop" hadn't been true already :)
[color=blue]
> if (direction == "dn") {
> page.top = (y_pos - (speed));[/color]
Here we assign a number value to "page.top". In most cases,
"page" is a style object, so what should be assigned is a
CSS length. It must end in a unit, e.g. "px". However, in
Netscape 4, it shouldn't. So, more tests would be necessary here,
but for standard compliant browsers, this should be:
page.top = (y_pos - speed) + "px";
[color=blue]
> } else {
> if (direction == "up" && y_pos < 10) {
> page.top = (y_pos + (speed));[/color]
ditto.
[color=blue]
> } else {
> if (direction == "top") {
> page.top = 10;[/color]
ditto.
[color=blue]
> }
> }
> }
> scrolltimer = setTimeout("verScroll(direction,speed)", 1);[/color]
This is a reason for "direction" and "speed" to be global, because a
string as first argument to "setTimeout" is evaluated in the global
scope. For modern browsers (Netscape 4 and better), you can use a function
as first argument, which avoids this problem:
scrolltimer = setTimeout(function(){ verScroll(direction,speed); }, 1);
A second argument of "1" means a timeout of one millisecond. That might
not be smart :)
[color=blue]
> }
> }
>
>
> function stopScroll() {
> loop = false;[/color]
So, this assigns to a global variable that isn't used anywhere else.
[color=blue]
> clearTimeout(scrolltimer);[/color]
This clears the timeout stored in the global variable "scrolltimer".
This actually makes sense :)
/L
--
Lasse Reichstein Nielsen -
lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'