id names are global variables?

B

Bruce

When I do this:

<input id="someName" type="text">

<script type="text/javascript">
alert(someName.nodeName);
</script>

Both IE6 and Firefox alert("INPUT"). Why isn't "someName" undefined?

Why am I not required to do something like this:

getElementById("someName").nodeName;
 
T

Thomas 'PointedEars' Lahn

Bruce said:
<input id="someName" type="text">

<script type="text/javascript">
alert(someName.nodeName);
</script>

Both IE6 and Firefox alert("INPUT"). Why isn't "someName" undefined?

Why am I not required to do something like this:

getElementById("someName").nodeName;

Backwards compatibility and maybe compatibility to one another. In Firefox
it would work only because you are triggering Quirks Mode by omitting the
DOCTYPE declaration or providing an incomplete one.

<http://validator.w3.org/>


PointedEars
 
B

Bruce

Backwards compatibility and maybe compatibility to one another.  In Firefox
it would work only because you are triggering Quirks Mode by omitting the
DOCTYPE declaration or providing an incomplete one.

Yes, you're right. I forgot the DOCTYPE. That fixes the problem for
Firefox but what a nuisance that the problem persists in IE6.
 
J

Jeremy J Starcher

Yes, you're right. I forgot the DOCTYPE. That fixes the problem for
Firefox but what a nuisance that the problem persists in IE6.

IE6, or rather, all versions of IE to date, are a pain. Some browsers
even go as far as duplicating IE bugs^w features.

My recommendation: Don't pollute the global name space.

All class/instance variables should be declared locally. If, for some
reason, you need two functions to share a group of variables, wrap the
two functions up together.

If you MUST use globals, use just one. Make an object and set properties.

<html>
<head>
<title>Test</title>
</head>
<body>

<script type="text/javascript">

var jjsGlobal = {}; // One variable to rule them all

function w(s)
{
document.write(s + "<br>");
}

(function() {
var onlySeenHere = 0;;

function test1() {
onlySeenHere++;;
}

function test2() {
onlySeenHere++;;
}

test1();
test2();
w("OnlySeenHere = " + onlySeenHere);

jjsGlobal.test = "Test is set.";

})();


w("And our global == " + jjsGlobal.test);


</script>

</body>
</html>
 
B

Bruce

My recommendation:  Don't pollute the global name space.

Of course but I haven't found a better way yet. I'm writing a simple
spreadsheet like calculator.

I want to do the following:

<input id="a1" type="input"> +
<input id="b1" type="input"> =
<input id="c1" type="input" readonly>

Then pass the following to a "class"

"c1 = a1 + b1"

I want to use eval() to do the math. I want to keep 2 copies of the
variables. The displayed value is kept in the input form field, and a
higher precision value is kept in a variable matching the name of the
input form field.

I want to check to see if the variable has been defined. If not I
create it in the global namespace and set it to a default value. With
IE6 the variables are already defined as objects because of the input
form ids so it doesn't work.

In this simple example, if I do this:

var a1;
var b1;

It works, but for larger spreadsheets, I don't want to have to do
that. I want to do it automatically. For every input form id I find, I
want to create a global variable so that the simple math string will
work in an eval()
 
J

Jeremy J Starcher

Of course but I haven't found a better way yet. I'm writing a simple
spreadsheet like calculator.

I want to do the following:

<input id="a1" type="input"> +
<input id="b1" type="input"> =
<input id="c1" type="input" readonly>

Then pass the following to a "class"

"c1 = a1 + b1"

I want to use eval() to do the math. I want to keep 2 copies of the
variables. The displayed value is kept in the input form field, and a
higher precision value is kept in a variable matching the name of the
input form field.

I want to check to see if the variable has been defined. If not I create
it in the global namespace and set it to a default value. With IE6 the
variables are already defined as objects because of the input form ids
so it doesn't work.

In this simple example, if I do this:

var a1;
var b1;

It works, but for larger spreadsheets, I don't want to have to do that.
I want to do it automatically. For every input form id I find, I want to
create a global variable so that the simple math string will work in an
eval()

No global variables! Not here! In other posts I demonstrated how to
avoid using global variables.

You don't want to create a new variable for every field. You _really_
don't.

Without knowing more about how you are planning making this, I can think
of several approaches that would do you MUCH better.

Approach 1:
Simple, easy to understand but not elegant.

2D arrays, [column][row]
A-Z would become 0-26, so a10 would become displayedValue[0][10],
calculatedValue[0][10]


Approach 2:
Objects

Objects are the perfect tool to store data like this. You would write
code like

var spreadSheet = {}; // Create a new object.
spreadSheet.a10 = {}; // Create a new cell.

var cId = "b10";
spreadSheet[cId] = {}; // Create a new cell

spreadSheet.a10.displayedValue = 10;
spreadSheet.a10.calcValue = 9.9999999999999999999999;


Your approach hints at a background programming in BASIC or some other
earlier language. Languages have moved beyound that.

Before you code any more, do some heavy reading on Javascript, Arrays and
Objects (incorrectly called associative arrays).
 
B

Bruce

Your approach hints at a background programming in BASIC or some other
earlier language.  Languages have moved beyound that.

Before you code any more, do some heavy reading on Javascript, Arrays and
Objects (incorrectly called associative arrays).- Hide quoted text -

I'm not doing it this way because I'm clueless and I like global
variables, nor am I new to Javascript or to Structured Programming or
Object Oriented programming.

I'm trying to keep my equations as simple as "c1 = a1 + b1" just like
in an Excel spreadsheet. The simplest way that I've thought of so far
is to let a1, b1, c1 be global variables so that eval("c1 = a1 + b1")
will work.

I don't want my equations to look like this:

eval("myObj.c1 = myObj.a1 = myObj.b1");

Or

eval("myArray[0][2] = myArray[0][0] = myArray[0][1]");

If I can find a way, short of writing my own equation parser, to do
this without global variables, I'm all for it.
 
T

Thomas 'PointedEars' Lahn

Gregor said:
Bruce meinte:

Since you hardly ever need global variables, there is no spoon^Wproblem.

YMMD :)


\\// PointedEars, who's got a Matrix to fix
 
B

Bruce

I'm trying to keep my equations as simple as "c1 = a1 + b1" just like
in an Excel spreadsheet.
If I can find a way, short of writing my own equation parser, to do
this without global variables, I'm all for it.

Thanks to a suggestion from Jeremy J Starcher in another thread, I
found my solution.

Instead of global variables, I create variables within my "class" like
this:

this["a1"] = 1;
this["b1"] = 2;

then I can do this:

with(this) {
c1 = eval("a1 + b1");
}

Problem solved. No global variables and I get to keep my simple
equations.
 
B

Bruce

Excel is certainly not a programming reference.

I didn't make a programming reference to Exel. I made a reference to
the way equations are entered into Excel.

I'm writing a general purpose "class" where I can configure it with
strings of equations using form id names as variable names that will
update other form fields as the input data changes. I want my
"spreadsheet" calculation to be as unobtrusive as possible so that I
create a form with id names for variable names and my "class"
automates the rest (adds "onchange" events, initializes form field
values ...).
this["a1"] = 1;
this["b1"] = 2;

  this.a1 = 1;
  this.b1 = 2;

I have to do

this["a1"] = 1

because I pass variable names to my "class" as string names. I want to
configure the class with equations in the form of strings. I will pass
something like "c1 = a1 + b1" as a string to my class.

So I'm actually doing something like this (as a trivial example):

setDefaults : function(variableNames,defaultValue) {
for (var i = 0; i < variableNames.length; i++) {
this[variableNames] = defaultValue;
}
}
You rarely ever need eval(), and you certainly don't need it here:

  c1 = a1 + b1;

or

  c1 = this.a1 + this.b1;

Can't. I'm passing variable names as strings. I'm passing equations as
strings. So, yes I need eval() or I need to write my own equation
parser. Eval() already does that for me so I might as well use it.
No, you cannot if the data comes from form controls.

I completely control the equations. Users do not input them so they
won't be able to inject unwanted Javascript.

My application will not look like a spreadsheet. It will look like a
form where users input some data and I perform preconfigured math on
the data and display things like a running total in real time. Since I
want this code to be re-useable on other web sites, I'll configure the
code with an array of equations and variable names as strings and use
eval() to perform the math.
 
T

Thomas 'PointedEars' Lahn

Bruce said:
Thomas said:
Bruce said:
this["a1"] = 1;
this["b1"] = 2;
this.a1 = 1;
this.b1 = 2;

I have to do

this["a1"] = 1

because I pass variable names to my "class" as string names.

In that case you would have to. It would restrict "string names" to unused
property names of the implementation, that you cannot know, though.
Can't. I'm passing variable names as strings. I'm passing equations as
strings.

IOW, you are passing *code* as strings.
So, yes I need eval() or I need to write my own equation parser.
Eval() already does that for me so I might as well use it.

Plain eval() constitutes a security leak. The least you have to do is
removing potentially harmful code from the passed string. And CMIIW,
the halting problem is not yet solved.
No, you cannot if the data comes from form controls.

I completely control the equations. Users do not input them so they
won't be able to inject unwanted Javascript. [...]

If users do not input the equations, there is no need to use eval().


PointedEars
 
B

Bruce

In that case you would have to.  It would restrict "string names" to unused
property names of the implementation, that you cannot know, though.

I can know, because I choose the variable names. I choose the id names
in the form fields. I also choose the equations. The only thing chosen
by the user is the data.
IOW, you are passing *code* as strings.

Here's something I don't know. Can code be injected if I parseFloat()
on user input? I suspect not but I'm not a determined hacker. The
value of the variables is input by the user. The equations that go
through eval() and the variable names, are coded by me.
If users do not input the equations, there is no need to use eval().

I pass an array of equations in the form of strings to my "class". For
example:

var myMath = [ "c1=a1+b1","d2=(c1+c2)*10" ];
myClass.performMath(myMath);

I could modify the code of my "class" every time I need a new set of
equations for a new web site but I'd rather keep the "class" read only
and just pass it new equations as data.
 
T

Thomas 'PointedEars' Lahn

Bruce said:
Thomas said:
In that case you would have to. It would restrict "string names" to
unused property names of the implementation, that you cannot know,
though.

I can know, because I choose the variable names. [...]
OK.
IOW, you are passing *code* as strings.

Here's something I don't know. Can code be injected if I parseFloat() on
user input? [...]

In theory, yes, as the argument is converted to string which would call the
toString() or valueOf() method of an object that the argument refers to
(ES3F, 15.1.2.3, 9.8, 9.1):

function foo(bar)
{
// alerts 42
var baz = parseFloat(bar);
}

foo({
toString: function() {
window.alert(42);
return "0";
}
});

However, form control values are represented as strings, and type conversion
of a string to string does not call any of the aforementioned methods.
If users do not input the equations, there is no need to use eval().

I pass an array of equations in the form of strings to my "class". For
example:

var myMath = [ "c1=a1+b1","d2=(c1+c2)*10" ];
myClass.performMath(myMath);

I could modify the code of my "class" every time I need a new set of
equations for a new web site but I'd rather keep the "class" read only
and just pass it new equations as data.

You can pass Function object references instead, and your object
(let's get rid of `"class"') can call it as one of its methods.
Quick hack:

function Earth()
{
this.a2 = 7;
}

Earth.prototype.compute = function(f) {
if (f && typeof f == "function")
{
if (typeof f.call == "function")
{
return f.call(this);
}
else
{
this.tmp = f;
return this.tmp();
}
}
};

var earth1 = new Earth();

// thanks to the Golgafrinchams
earth1.a2 = 9;

// alas, it does not show fourty-two
window.alert(
earth1.compute(
function() {
this.a1 = 6;
return this.a1 * this.a2;
}));

// let's try again ;-)
earth1 = null;
var earth2 = new Earth();


PointedEars
 
D

dhtml

Bruce said:
When I do this:

<input id="someName" type="text">

<script type="text/javascript">
alert(someName.nodeName);
</script>

Both IE6 and Firefox alert("INPUT"). Why isn't "someName" undefined?

Why am I not required to do something like this:

getElementById("someName").nodeName;

There seems to be some sort of object that resolves element IDs in
various browsers.

http://groups.google.com/group/comp.lang.javascript/msg/aed8ecf1660e1dd1

I have updated the relevant section of the FAQ:
http://jibbering.com/faq/#globalPollution

It used to read:-

| 4.41 Why doesn't the global variable "divId" always refer to the
| element with id="divId"?
|
| Microsoft introduced a shortcut that can be used to reference elements
| which include an ID attribute where the ID becomes a global variable.
| Some browsers reproduce this behaviours but some, most notably
| Gecko-based browsers (Netscape and Mozilla), do not. The best approach
| is the document.getElementById method, which is part of the W3C DOM
| standard and implemented in modern browsers (including IE from version
| 5.0). So an element with id="foo" can be referenced with:-
|
| var el = document.getElementById("foo");

Replaced "global variable" with globally accessible property. Changed
"Gecko-based browsers (Netscape and Mozilla), do not." to "Gecko-based
browsers (Netscape and Mozilla), do so only in "quirks" mode."
 

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

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,351
Latest member
LolaD32479

Latest Threads

Top