Accessing form by ID - javascript

The line below (allegedly) looks for a form with id frm1 (W3S source).
var x = document.forms["frm1"];
Why should it even work? If you look in the reference, document.forms returns the collection of forms. There are no associative arrays in JS, so document.forms["frm1"] basically asks for a property called frm1 of the returned collection. I think the right way is to use namedItem("frm1").
Is it merely a mistake in this tutorial, maybe something that worked in the past and is no longer valid?

As #Teemu pointed out, the answer you're looking for lies here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
HTMLCollection.namedItem()
Returns the specific node whose ID or, as a fallback, name matches the string specified by name. Matching by name is only done as a last resort, only in HTML, and only if the referenced element supports the name attribute. Returns null if no node exists by the given name.
While this is true and works fine for ID's when given a string, it also supports indices:
HTMLCollection also exposes its members directly as properties by both name and index. HTML IDs may contain : and . as valid characters, which would necessitate using bracket notation for property access. Currently HTMLCollections does not recognize purely numeric IDs, which would cause conflict with the array-style access, though HTML5 does permit these.
As you can see, there are problems present with mixing ID and index together. But this allowed it to have a short and sweet syntax as you can see. HTML5 has eased up the strictness, but conflicts can result.

Related

HTML: Can always the same identifier be used for name and id attributes?

Basically the "name" attribute is used in server-side programming (name/value pairs are sent in requests) and the "id" attribute is used in client-side programming (i.e. Javascript and CSS).
But both fulfill essentially the same function - provide a unique identification of an element. And to complicate things not too much, it is useful if a thing has only one identifier.
Therefore the question(s) - for tags that need both "id" and "name":
Is there any reason to choose different identifiers for the name and id attributes? Are there any use-cases for which different identifiers are required? Are there any differences in syntax? (for example you can use "myarray[123]" for the name attribute and PHP will understand that correctly and create an array, can that also be used in a similar manner for id-attributes in Javascript or CSS - and if not, is that a syntax-error or is it simply a valid identifier with brackets in it?) Are both case-sensitive?
Is there any reason to choose different identifiers for the name and id attributes?
Yes. IDs must be unique, names don't have to be. Names must be the same for members of a radio group, so they can't all have the same id—well, they can in practice but accessing the elements by ID will be problematic. And if you don't access them by ID, why have it?
Are there any use-cases for which different identifiers are required?
Yes, radio buttons. Only one can have an id that is the same as its name. But otherwise, there are few restrictions, such as than never give form controls the name or id of a method or property of the form itself, like "submit", as it will mask the same–named property of the form.
Also, names "_charset_" and "isindex" are special.
Are there any differences in syntax? (for example you can use "myarray[123]" for the name attribute and PHP will understand that correctly and create an array, can that also be used in a similar manner for id-attributes in Javascript or CSS - and if not, is that a syntax-error or is it simply a valid identifier with brackets in it?)
Yes. The rules for name and id attribute values are similar but an ID must not contain spaces (and some values for name are special, see above). There were more restrictions on id attributes in HTML4 (e.g. ids couldn't start with a number), but in practice they weren't implemented in browsers.
Some characters that are valid in names and ids must be quoted to use as CSS selectors, e.g. for:
<div id="d[]">
the CSS selector is:
#d\[\]
and for use with the Selectors API:
#d\\[\\]
(e.g. document.querySelector('#d\\[\\]').
Are both case-sensitive?
Yes.
To answer the question in the title: Yes, whenever the syntax of an element allows a name attribute, its value may be identical with the id attribute value. This follows from the declarations of the name attribute: its value is any string, and the only constraint imposed relates to the a element; and for it, the requirement is that the name attribute value must not match the id attribute value of another element (but must match the id attribute value of the same element if present).
To address the assumptions in the question: The name attribute in form field elements is indeed primarily for server-side processing; but various other elements may have a name attribute, for different uses. The id attribute is helpful in client-side programming, but it also has the effect of creating a destination anchor so that the element can be referred to by a link in the same document or another document. There is technically no tag that “needs” both id and name, or even one of them; whether they are used depends on practical purposes. The name attribute is not required to be unique, and it is not meant to provide unique identification. You can, for example, have an arbitrary amount of input elements with the same name attribute.
The syntax of id has traditionally been restricted in HTML specifications, but browsers have been much more permissive, and HTML5 PR imposes no other restrictions than the following: the value must not be empty (i.e. it must contain at least one character), it must not contain space characters, and it must be unique within the document (i.e. no two elements can have the same id attribute value).
The syntax of name has always been free. Apart from the special rules for the a element, the only restriction is that the value must not be empty.
Both id and name attribute values are case-sensitive. The special rules for the a element impose restrictions involving case-insensitivity, for legacy reasons.
There are many possible reasons why you might want to make id and name different for an element. For example, when interfacing to an existing server-side script that requires very long and complicated names for the fields, you have to use them in name attributes, but you are free to choose your id attributes.
The choices made when writing id and name attribute values have their consequences, but they depend on the contexts where the values are used. For example, if an id attribute value starts with a digit, it cannot be directly used in a CSS selector due to CSS syntax (but must be escaped). Similarly, the ways you can use the values in JavaScript depend on the syntax you have used, but you can always refer to them some way.
name attribute usually doesn't need to be unique. A given HTML document may have several forms, and each of them might have elements having names identical to names in the other forms.
If you're using PHP, saying:
<form>
<input type="text" name="foo[]" />
<input type="text" name="foo[]" />
</form>
would cause, PHP to read this name as array and all entries will contained within it. Names could possibly be used as attributes for non-form elements, however, they're most frequently used only within form.
id attribute on the other hand, needs to be able to uniquely identify a given DOM element within the document. You're not forced to use it this way. Browser doesn't blow up if you use same id on two different elements. But if you have two elements with same id, the last one you add prevails over the previous ones. So,
document.getElementById( 'foo' )
// or
$( '#foo' )
will return just one element of several.
id can be used to identify any element within the document and is not constrained to be within a form

How to get control id from Object HTML Collection?

I want to get the control id so that I can attach event to this id,code for this is:
var t=document.getElementsByName('test');
alert(t);
this 't' here returns the Object HTMLCollection but when I run this code on jsfiddle i got Object NodeList and by using t[0].id I got the required id.
I have some requirement so I don't want to use document.getElementById();
Can any one tell me why this is happening and how can I get the id of control through Object HTMLCollection?
So it looks like you have two questions:
1) Can any one tell me why this is happening
and
2) how can I get the id of control through Object HTMLCollection?
First I think you need to understand WHAT an HTMLCollection is. Please read the answer to this stackoverflow question and pay careful attention to what is written, specifically
getElementsByTagName is method of the DOM interface. It accepts a tag
name as input and returns a NodeList (some browsers chose to return
HTMLCollection instead, which is OK, since it is a superset of
NodeList).
So the two share most properties, especially basic properties like id. I recommend reading up on HTMLCollection and NodeList on MDN.
This also contains the answer to your question as to WHY this happens
getElementsByTagName is method of the DOM interface. It accepts a tag
name as input and returns a NodeList (some browsers chose to return
HTMLCollection instead, which is OK, since it is a superset of
NodeList).
Essentially, the answer is simply that different browsers behave differently (when it comes to web development, you will find this is true in MANY ways).
So onto a more deailed answer to the second part of your question. ASSUMING that you have HTML elements with the name 'test' and ASSUMING you want the first one, all you have to do is reference the first element of the returned array, whether it is a NodeList or an HTMLCollection
var element = document.getElementsByName('test')[0];
If you want to make sure you got elements back, just get the array and check that it has > 0 elements
var element;
var elements = document.getElementsByName('test');
if (elements.length > 0)
{
element = elements[0];
}
The method you are using will return an array, so to answer your question you will need to do:
var element = document.getElementsByName('test')[0];

How to read all style properties a browser supports

I made a simple Javascript routine that reports all the style properties present in a browser.
var list = new Array();
var div = document.createElement('div');
for (var style in div.style)
list.push(style);
And it works. The results are in JavaScript format, so for instance borderTopLeftRadius means the CSS property border-top-left-radius, MozAnimationTimingFunction means -moz-animation-timing-function and so on.
Here is a fiddle where you can see it live.
(The list is flawed, by the way. For instance, in Firefox and IE, the list doesn't even contain float, but it does in Chrome. Firefox and IE have cssFloat. Oh well, I can live with that.)
So far, so good.
However, my goal is to have only a list of CSS property names. But the results also include entries that are not property names at all, like getPropertyPriority and length. And my question is, how can I filter these out? How to differentiate between these entries (some are Javascript functions, some are read-only properties) and the actual CSS property names?
Edit:
I don't mind about the properties that apply to SVG only; it's OK to keep those.
Also, while most of the offending ones can be filtered out by checking if the property has type 'string' as Mr_Green pointed out (see updated fiddle), there are still some entries in the list that are not CSS property names, such as cssText and marks (the latter only in some browsers). I want to filter those out as well, but haven't found a way to do so.
The W3C mentions a function called supports() but I haven't been able to make that work. Can anybody find me an example?
I don't know if your goal is to check whether a property is supported or not but
function isPropertySupported(property)
{
return property in document.body.style;
}
can check whether a property is supported or not. I hope it helps. Correct me if I am wrong.
Check whether a CSS property is supported or not
EDIT:
Check this out CSS Supports
supports(DOMString property, DOMString value), returns boolean
supports(DOMString conditionText), returns boolean
When the supports() method is invoked with two arguments property and value, it must return true if property is a literal match for the name of a CSS property that the UA supports, and value would be successfully parsed as a supported value for that property. (Literal match means that no CSS escape processing is performed, and leading and trailing whitespace are not stripped, so any leading whitespace, trailing whitespace, or CSS escapes equivalent to the name of a property would cause the method to return false.) Otherwise, it must return false.

Why does JavaScript's getElementsByClassName provide an object that is NOT an array?

I'm trying to get a list in JavaScript (not using jQuery) of all the elements on the page with a specific class name. I therefore employ the getElementsByClassName() function as follows:
var expand_buttons = document.getElementsByClassName('expand');
console.log(expand_buttons, expand_buttons.length, expand_buttons[0]);
Note that I have three anchor elements on my page with the class 'expand'. This console.log() outputs
[] 0 undefined
Next, for kicks, I threw expand_buttons into its own array as follows:
var newArray = new Array(expand_buttons);
console.log(newArray, newArray.length);
This suddenly outputs
[NodeList[3]] 1
and I can click through the nodelist and see the attributes of the three 'expand' anchor elements on the page. It's also worth noting that I was able to get my code working in a w3schools test page.
It may also be of note that my use of document.getElementsByName actually does output (to the console) an array of elements, but when I ask for its length, it tells me 0. Similarly, if I try to access an array element using array_name[0] as normal, it outputs 'undefined', despite there clearly being an element inside of an array when I print the object to the console.
Does anybody have any idea why this might be? I just want to loop through DOM elements, and I'm avoiding jQuery at the moment because I'm trying to practice coding with vanilla JavaScript.
Thanks,
ParagonRG
It's not so much a JavaScript thing as it is a web browser thing. That API is supplied by a native object (the document object), and by the DOM spec it returns a NodeList object. You can treat a NodeList like an array, and it's similar, but distinctly different (as you've noticed).
You can always copy a NodeList to a new array:
var nodeArr = Array.prototype.slice.call(theNodeList, 0);
or in modern ES2015 environments:
var nodeArr = Array.from(theNodeList);
JavaScript always exists in some runtime context, and the context can include all sorts of APIs that provide facilities to JavaScript code. A web browser is one of those contexts. The DOM is specified in a way that's not especially partial to JavaScript; it's a language-neutral interface definition.
I guess the short version of this answer would be, "because it just does."
It doesn't return an array because the object it returns is "live", specifically it is a live NodeList:
In most cases, the NodeList is a live collection. This means that changes on the DOM tree are going to be reflected on the collection.

Can a DOM object be an index/key in Javascript array?

Would like to maintain a map/hash of DOM objects. Can they serve as key objects? If not, what are the alternatives, please? If there are better ways - kindly enlist them as well.
You can put anything as the key, but before actual use it is always converted to string, and that string is used as a key.
So, if you look at what domObject.toString() produces, you see it is not a good candidate. If all of your dom objects have an id, you could use that id.
If not, and you still desperately need a key based on DOM object, you probably could do with using, for example, _counter attribute with automatic counter in background putting new unique value in a DOM object if _counter is not yet present.
window already maintains all DOM objects as properties. Instead of putting your own keys for each 'DOM object' try to use window or document object and methods that uses index based on the layout of DOM tree.
No, because object keys are strings.
You'd have to "serialise" your objects by id or something, then perform a lookup later. Probably not worth it, depending on what your actual goal is here.
No, but you can set an attribute on the DOM element that contains a number, which you would have as the index in a numerically-indexed array.
Easiest is to set a data-attribute on the element instead.
Not exact. But I think you want something like below. You can do with jquery,
The .serializeArray() method creates a JavaScript array of objects, ready to be encoded as a JSON string. It operates on a jQuery object representing a set of form elements. The form elements can be of several types
Refer below link :
http://api.jquery.com/serializeArray/

Categories