Link to home
Start Free TrialLog in
Avatar of scrathcyboy
scrathcyboyFlag for United States of America

asked on

make object from name?

Here is typical FORM tag (note it is in DIV).  When I make or builda  name from the main name, javascript complains that it is not an object.  How do I make a name into an object?

<DIV id="a"> <FORM name="a"> <INPUT type="checkbox" class="input" id="a" value="no" onclick="runFunction('a')"></FORM><SPAN id="a">Show</SPAN> </DIV>

Note, all items are named 'a', but want to make the form a1, checkbox a2 and span a3.  How to do this in javascript, so they become usable objects to javascript functions?  Please be simple and clear.  Thanks.
Avatar of BogoJoker
BogoJoker

Your <inputs> don't even need names, just your form.
a.elements[]
As seen here:
http://www.w3schools.com/htmldom/dom_obj_form.asp

Joe P
How does this look:

<html>
<head>
<script type="text/javascript">
function tellall()
{
  for (var i = 0; i < document.a.elements.length-1; i++)
    alert("Element " + i + " has a value: " + a.elements[i].value);
}

</script>
</head>

<body>
<form name="a" onsubmit="return false;">
  Name: <input type="text"><br>
  Random: <input type="text"><br>
  TextArea: <textarea rows=10 cols=30></textarea><br>
  <input type="button" value="Tell All" onclick="tellall();">
</form>
</body>
</html>

Joe P

Joe P
Avatar of Roonaan
You can also pass the form object directly:

<INPUT type="checkbox" class="input" id="a" value="no" onclick="runFunction(this.form)">

-r-
@BogoJoker The form does not need names  Just the Fields!!! (form names are actually not even allowed in html validators)


<html>
<head>
<script type="text/javascript">
function tellall(theForm) {
  for (var i = 0; i < theForm.elements.length-1; i++)
    alert("Element " + i + " has a value: " + theForm.elements[i].value);
}

</script>
</head>

<body>
<form onsubmit="return false;">
  Name: <input type="text" name="a"><br>
  Random: <input type="text" name="b"><br>
  TextArea: <textarea name="c" rows=10 cols=30></textarea><br>
  <input type="button" value="Tell All" onclick="tellall(this.form);">
</form>
</body>
</html>
Hi again scrathcyboy!

In your question, you ask:  "How do I make a name into an object?"  What exactly do you mean?  If you have an object, and reference it in as JavaScript function, you can make its name into a string:

var str = obj.name

If the object is an element within another, you can find what it is an element of:

var str = obj.parent.name    // I think that works?
var str = obj.form.name      // if you know it's an element within a form. (I know this works).

In the example you gave:

<DIV id="a"> <FORM name="a"> <INPUT type="checkbox" class="input" id="a" value="no" onclick="runFunction('a')"></FORM><SPAN id="a">Show</SPAN> </DIV>

You said "Note, all items are named 'a', but want to make the form a1, checkbox a2 and span a3.  How to do this in javascript, so they become usable objects to javascript functions?"

I believe if all of your items are named the same, you could be creating more trouble than it's worth to you.  To reference them from JavaScript, then, you'll be depending on order alone, as Joe and Michel discuss above, indexing through the items one at a time.  If you swapped the span and the checkbox in your example, so that 'Show' came before the checkbox, they'd be in a different order in the element array.  You don't want to do that.  That builds too much dependency on order.

Yes, you could refer to the items by type, and only match the "checkbox" type, but again, that's more work than I think it's worth - unless you can find a reason otherwise.

I believe you should do what it takes to create the html code with the ID labels that you want, such as:
 
<DIV id="a"> <FORM name="a1"> <INPUT type="checkbox" class="input" id="a2" value="no" onclick="runFunction(this)"></FORM><SPAN id="a3">Show</SPAN> </DIV>

Then, in your runFunction:

function runFunction(obj) {
//  computer issues ... I'll complete in a later message
}

Peace and joy.
mvan
... continuing ...

I believe you should do what it takes to create the html code in the document with the ID labels that you want, such as:

<DIV id="a"> <FORM name="a1"> <INPUT type="checkbox" class="input" id="a2" value="no" onclick="runFunction(this)"></FORM><SPAN id="a3" style="display:none">Show</SPAN> </DIV>

Then objects (or elements) named "a1" and with ID's "a", "a2", and "a3" exist in the document.

In your function, here are some things you can do, because you passed (this), meaning this checkbox element:

<script>

function runFunction(obj) {
  var eleID = obj.id    // returns: 'a2' the string value of the checkbox id that launched this function
    alert('eleID = '+eleID);
  var frmName = obj.form.name  // returns: 'a1' the string value of the form name - in which this function exists
    alert('frmName = '+frmName);
 
  // if your document elements have IDs based off of the form name, let's say, then you can generate the ID of another element:
  var nxtID = frmName.replace(/1/,'3');  // replaces substring '1' in frmName with '3' resulting in 'a3', in this case
    alert('nxtID = "'+nxtID+'"');
  // note: it would have been simpler to use form name="a"
  //       then, to refer to its elements by ID, you could just add the number, as in: var nxtID=frmName+'3';
  // How to use this text string 'a3' to reference an element in the document?
  var nxtEl = document.getElementById(nxtID);  // nxtEl is the object, tied to the element in the document named 'a3' (in this case)
    alert('nxtEl = '+nxtEl);
  // Notice that the <SPAN id='a3' ... is ouside of the form.  In your example, its only reliable tie to the form is by its similar name.
  // It just happens to be the next element in the form, but ... what if you rearrange your document?  You may lose order.

  // You can query and set properties of nxtEl, and you are actually querying and setting properties of the actual object in the document
  // This object, called nxtEl here, only exists while this routine is running, and exchanges values with whatever you pointed it to in the document
  // That's what I meant by 'tied to' above.
  // Now you use nxtEl like an object, and you can query and set properties, and they change in the document
  nxtEl.style.display = "none";  // hide the span, for example

  // Going back to the form, if you want to convert that form name into use here, you can:
  var theForm = document.forms[frmName];
    alert('theForm = '+theForm);    // yes, it's an object
  // Showing how to query a property of the form, how many elements are in theForm?
  var numElements = theForm.elements.length
    alert('numElements = '+numElements);
  // If you need info from the form, Roonan is right, you could have passed the whole form object in your onClick call
}

</script>


Summing it up, your question was, "When I build a name ... how do I make it into an object?"  First, the object must already exist in the document, or frame, or window, or ... etc.  

Technically speaking, you can create objects in the document by using:
  var d = 'c';
  var dF = d+'1';
  var dI = d+'2';
  document.write('<form name="'+dF+'"><input type="text" id="'+dF+'"></form>');    // creates form name="c1" and input id="c2"

and they'll have the IDs or names you built, but I believe that's not what you asked for.

Also, technically speaking, you can rename an object which already exists, in the above JavaScript function you could have done this:
  obj.form.name = 'testing';

would rename form name='a1' to form name='testing'.  Maybe useful somehow, but that could be very confusing!

I think your question is asking "How do I refer to an object, if I have its name in a string?"  I think I've shown a few ways.

Peace and joy to you.
mvan
oops!

I said:
It just happens to be the next element in the form, but ... what if you rearrange your document?

I should have said:
It just happens to be the next element after the form in the document, but ... what if you rearrange your document?

Peace and joy.
mvan
Avatar of scrathcyboy

ASKER

thank you mvan for this detail, you explain it is better to name form elements directly than concoct names in JS and put back into form.  That part you solved.  What is not clear is the passing of a text name and then in JS using it as an object.  I know I can say 'this', or this.form.name, but I dont want to do that in all cases, some function might need to just pass - function('a1','a2','a3') - and when you get these in the JS, they are only text labels, not parts of form, nor other page elements for JS to manipulate.  These need to be made into elements like DIV, SPAN, TD, or TR .. etc...  addressable elements, hope this clearer?
SOLUTION
Avatar of Michel Plungjan
Michel Plungjan
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Actually, both these last posts are SUPER great summaries of a lot of what people struggle with in JS programming.  mplungjan, thanks for super condensed summary of key addressing methods, and yes, Mvan, what you provided was terrific examples of exactly what I was getting at.  Had to up points for 2 great solutions, hope you dont mind, some of best feedback I have got.  Thanks again.
You are welcome.  It's fun, and I'm learning a lot too.  :-)

Peace and joy.  mvan
actually, if you both still there, there is still one nagging issue on 'name' addressing.  Take mplungjans first example -

var elem = document.forms[0].elements[fieldNameVariable]

the [0] addressing ALWAYS work, because it get first element in form.  But that goes against dependence on order mvan talked about, which I agree with.  So assuming JS gets name of element and form, most or even all of these do/do not work, depending on exactly how you phrase it -

var x=form.name
var y=checkbox.name

var elem = document.forms['a1'].elements['a2']
var elem = this.forms[x].elements[y]
var elem = document.forms.x.elements.y
var elem = forms['x'].elements['y']

Realize some of these are deliberately wrong, like last, but it prove point, correct addressing of forms and elements has so many different possibilities, it is very confusing, and most dont work at all.

Also, mvan, please be "less local" when you give examples.  Too many people assume JS spawns from within form, but many cases not true (you will see in my next question) -- so "this" or this.form.name is not usable.  If you always assume the passing and receiving of JS variables is always "remote", you give much better examples.  Not criticism, just ways to improve.  ALSO, too many people give "alert" examples, which are fairly useless.  Assume what you want to do is change a span tag color or name, or text, with the variable for the span only passed as a "text name", then the examples more useful.

My next question requires sync of data in main window to a popup it spawn, so popup must check status of parent opener before it completes page.  This is very tough, haven't got it to work yet, so you see, examples ALWAYS with "virtual" or "remote" addressing -- never the "this" are always best.

Thank you again, mplungjan or mvan, any "rule" to avoid my example pitfalls above with names?

<form id="form1" onSubmit="return validate(this)"><!-- validate this form -->

<input type="checkbox" onClick="calc(this.form)"><!-- calculate values inside this button's form -->

Using forms[someNumber] is to avoid the name="..." which will not validate (http://www.codehelp.co.uk/code/validation.html)

<a href="sorrynojs.html"
onClick="frm = document.forms[1];
if (validate(frm)) {
  frm.submit();
  return false; // cancel the href
}
else {
  this.href='pleasedosomething.html';
  return true; // do NOT cancel the href
}
">Submit the second form on the page if it is ok and cancel the href,
else show page pleasedosomething.html by changing this link's href
If js is not enabled, show sorrynojs.html instead

Alternative for newer browsers:
onClick="frm = document.getElementById('form1');...

So the syntax is not that difficult:

Each form element has a form object
this.form

Each page has  a forms array if you use the forms tag
document.forms[indexOfForm]
or
document.forms[NAMEOfForm]; // name of form is not valid html but understood by all browsers

Also giving the form a name will add the name to the document attributes:
document.NAMEOfForm is the same as document.forms[NAMEOfForm]

So to take yoru syntax:

var x="myFormName"
var y="myCheckboxName"

var elem = document.forms[x].elements[y] is the same as
var elem = document.forms["myFormName"].elements["myCheckboxName"]

var elem = this.forms[x].elements[y] <<<<<<< not valid - there is no this that has a forms array unless you add the forms array to an element yourself

var elem = document.forms.x.elements.y wrong, should be: document.myFormName.myCheckboxName or
document.myFormName.elements["myCheckboxName"]

So to sum up.
1. I ALWAYS pass the form object from inside the form
2. I ALWAYS use document.forms[0] since it is understood by ALL browsers since NS2 and IE3 and it passes the validators
(see http://www.codehelp.co.uk/code/validation.html how to use name="..." anyway)
3. I ALWAYS use document.getElementById('someId') or document.getElementById(variableContainingSomeId)
when I want to show or hide something or change the innerHTML - I NEVER use innerText since it is IE only


Michel
Thank you Michel, that is SO clear, I think its the first time Ive really understood this addressing properly, most important is to know what is not valid, that helps immensely - is the best description of this problem I have seen anywhere (other sites all use the ['formname'], hardly anyone realize it is not valid), but thats what I have always had trouble with, it often doesnt work and I didnt know why.

Your reply deserves another 500 point just for this last comment alone, but I suppose everyone would object.  Well, it is BEST description of this problem anywhere on internet, as far as I can discover.
If you reload you will see a link to how to validate using form name.
All browsers understand document.forms['formName'] and document.formName - I am not sure when you had problems with that...
perhaps what you have problems with is

<form ID="myFormId">

document.forms["myFormId"] or

<form NAME="myForm">
document.getElementByID('myFormName') << works in IE but not in FF because getElementById is rightly looking for an ID

and lastly document.formName will fail in NS4 when you have your form inside an absolutely positioned DIV (which is considered a layer in NS4)

Michel
Hi Michel,

... and I thank you as well.

Peace and joy.  mvan
Michel, please look in on this new question, same issue, remote addressing with only name.  help please?
https://www.experts-exchange.com/questions/21794385/Synchronize-checkboxes-state-and-SPAN-display-between-2-windows-parent-child.html