How to access DOM properties obscured by form fields? - javascript

Update 1
After getting some answers I came up with even more complex case.
How to access form's ID and other attributes when form has fields named "id" and "getAttribute"? The general question is: how to reliably access form's attributes in any situation?
console.log(document.querySelector("#myform").id)
console.log(document.querySelector("#myform").getAttribute("id"))
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Form</title>
<form id="myform">
<input name="id" type="text" value="myvalue">
<input name="getAttribute" type="text" value="myvalue2">
</form>
Results in:
<input name="id" type="text" value="myvalue">
TypeError: document.querySelector(...).getAttribute is not a function[Learn More]
I was confused how fields of a form overwrite properties of the form. For example, a field named "id" will hide the actual id of the form:
console.log(document.querySelector("#myform").id)
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Form</title>
<form id="myform">
<input name="id" type="text" value="myvalue">
</form>
gives:
<input name="id" type="text" value="myvalue">
How to access form properties without the danger of form fields overwriting them (in case fields can have any possible names)?

With getAttribute() you get the form attributes.
console.log(document.getElementById('myform').getAttribute('id'))
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Form</title>
<form id="myform">
<input name="id" type="text" value="myvalue">
</form>

This has less to do with forms and form fields and more to do with the fact that you've given an element a name that is an actual native HTML attribute and JavaScript property. As a result, you are not getting the reference you wish to.
What's happening with your code is that document.querySelector("#myform") is correctly locating the form element, but then you are asking for the id property of that and so since there is another element with an name that is the same as the id of the form, the console logs the element and not the actual property value because form fields are children of their form parent and therefore considered accessible as properties of the form.
As you can see below, just asking for document.querySelector("#myform") (without the .id after it), returns a reference to the first DOM element that matches the selector.
console.log(document.querySelector("#myform").id);
console.log(document.querySelector("#myform"));
<form id="myform">
<input name="id" type="text" value="myvalue">
</form>
So, stay away from giving elements a name or an id that is the name of a native property or attribute of the HTML element and you'll be fine:
console.log("The value of the id attribue of the form as well as the value of the id property of the form DOM object is: " + document.querySelector("#myform").id); // Now returns the id of the element
console.log("The input element within the form is: ", document.querySelector("input[name='user']"));
<form id="myform">
<input name="user" type="text" value="myvalue">
</form>

EDIT:
The OP has changed the question now to include getAttribute or any arbitrary string as a form element name.
This is simply no different than overwriting any existing variable. For instance, what if I wanted to create a variable named window or document? or perhaps I want to store some data in a variable named forms and place that in the existing document object.
Each of these will work, but not produce the expected outcome. That is the essence of this question. "Can I do this?" Yes. "Should I do this?" No.
It is our obligation as developers to understand these nuances. And now the OP does.
What is most discouraging is the fact the the OP now knows this truth, yet continues to pursue this question by changing the variable being overwritten!
END EDIT (Original answer answering about the use of id as name):
You have confused the difference between an Object property and an HTML attribute.
We access properties using Object access methods (either . operator or [] notation).
We access HTML attributes using .getAttribute('name'). So if you want the value of the attribute as it is written in HTML as your question suggests, you would do that with:
document.querySelector("#myform").getAttribute('id') which would return "myform".
But like most questions pondering the 'what if' without a true problem to solve, this seems a bit silly - after all, the element was queried for using its id.
Now, considering Object properties in the right way, this:
document.querySelector("#myform").id
does exactly what the spec says about evaluating the syntax:
form[name]
Returns the form control (or, if there are several, a RadioNodeList of
the form controls) in the form with the given ID or name (excluding
image buttons for historical reasons); or, if there are none, returns
the img element with the given ID.
Once an element has been referenced using a particular name, that name
will continue being available as a way to reference that element in
this method, even if the element's actual ID or name changes, for as
long as the element remains in the tree.
If there are multiple matching items, then a RadioNodeList object
containing all those elements is returned.
Here: https://html.spec.whatwg.org/multipage/forms.html#the-form-element
Hope that helps.

I came up with a two quite large constructs that have to work regardless of any possible field name. The idea is to borrow methods from a clean object and accessors from prototypes.
A correct prototype has to be chosen from the prototype chain (you have to know were the property was defined).
// To access obscured methods (and also attributes)
console.log(document.createElement("form").getAttribute.apply(document.querySelector("#myform"), ["id"]))
// To access obscured properties (such as `style`):
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Object.getPrototypeOf(document.createElement("form"))), "style").get.apply(document.querySelector("#myform")).background = "green"
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Form</title>
<form id="myform">
<input name="id" type="text" value="myvalue">
<input name="getAttribute" type="text" value="myvalue2">
<input name="style" type="text" value="myvalue3">
</form>

Related

Struts 2 Form Bind Parameters To Collection Without Using Index

Struts Version: 2.3.16.3
Is there a way to populate a list of objects without having to specify the index? Currently I have to reference the collection like so:
<input name="myCollection[0].myProperty" value="some value" />
I really want to be able to do something like this:
<input name="myCollection[].myProperty" value="some value" />
I am dynamically adding and removing elements on the page with JavaScript and it has been a pain to get the indexing right with the JavaScript. Rather just have the backend add to the end of the collection in the order the elements come across from the form. Similar to how PHP processes it.
The docs for the parameters interceptor say that it is really just a ognl expression that the input name is binding to. I went to the ognl docs and it says you can reference array's like this:
array["length"]
which would be the next element in the array. The parameter interceptor is spitting out a message that it is rejecting this parameter name. I would really like to find a way to make this happen, even if it means extending the parameters interceptor.
Well, since
you are manipulating the page with Javascript
you are having troubles detecting / updating the index of elements when adding / removing them
the simplest solution is:
use the syntax you prefer when manipulating them, for example myCollection[].myProperty, and
convert them into the form desired by Struts in a pre-submit function.
This way you don't have to bother with the indexes while manipulating the elements, but only once, at the end, when you can simply loop them by name or something, and change their name with javascript by assigning the right index.
A kick-off example with jQuery:
$(function() {
$('#myform').submit(function() {
$('[name^="myCollection[]"]').each(function(index) {
var oldV = this.name;
var newV = oldV.replace("myCollection[]", "myCollection[" + index + "]");
console.log("was: " + oldV + " - now is: " + newV);
this.name = newV;
});
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="myform">
Open Javascript Console, then press submit, then inspect input elements
<br>
<input name="myCollection[].myProperty" />
<br>
<input name="myCollection[].myProperty" />
<br>
<input name="myCollection[].myProperty" />
<br>
<input name="myCollection[].myProperty" />
<br>
<input name="myCollection[].myProperty" />
<br>
<button>submit</button>
</form>
You need somehow to identify which object some property belongs to. Indexes are simplest way to do that, so you cannot just remove them.
There are many ways to achieve what you want. Look at Andrea's answer for one possible solution using javascript.
You can also pull object properties to simple lists and later set them to object.
E.g.
private List<String> myProperty;
can be referenced in JSP w/o indexes:
<input name="myProperty" value="first value" />
<input name="myProperty" value="second value" />
Of course you if you have many properties you need to somehow sync them in JSP in such way that order and size of the properties in list is consistent for every property.

Can not copy data of HTML tags to JavaScript

For some reasons I am trying to change functionality of submit button. I am facing problem in copying data from HTML tags to JS. The alert generated by following code prints "Undefined" not the data inside tag.
<html>
<body>
<input class="inputtext" id="email" name="email" type="text"></div>
<input value="Submit" name="v4l" id="login" class="inputsubmit" type="button" onclick="myFunction();return false">
<script>
function myFunction() {
var TestVar =document.getElementsByClassName('login').value;
alert(TestVar);
}
</script>
</body>
</html>
I know it can be done by form but I need it this way.
try
var TestVar = document.getElementById('email').value
alert(TestVar);
this will get value of text field
getElementsByClassName
^
See that s? Elements is plural. getElementsByClassName returns a NodeList (which is like an Array).
You have to either pick an index from it (foo[0]) or loop over it to get the values.
That said, you don't actually have any elements that are a member of the login class, so it is going to return a Node List of zero length.
You do have an element with id="login", so maybe you should use getElementById instead.
There doesn't seem much point in reading the value from an element that you've hard coded the value for. You might actually want to be using document.getElementById('email')

Uncaught TypeError: Cannot set property 'value' of null

I'm trying to pass the entered text to the controller using an ajax request. But i'm getting athe error "Uncaught TypeError: Cannot set property 'value' of null " when I tried to execute JS file..
Here is the HTMLcode:
<form action="">
<input type="text" class="searchbox1" name="search" placeholder="Search for Brand, Store or an Item..." value="text" />
<input type="button" class="searchbox_submit1" name="submit" value="text" onClick="javascript:getSearchText();">
</form>
Here is the JS code:
function getSearchText() {
var searchText = document.getElementByName("search").value;
h_url=document.getElementById("u").value;
var theURL = h_url+'search_all/' + deptid + '/' + searchText + '/1';
$.ajax({
url : theURL,
fail: function(){
},
success : function() {
},
error:function(){
}
});
}
Please help me to fix this.
You don't have an element with the id u.That's why the error occurs.
Note that you are trying to get the value of the input element with the name 'u' and it's not defined in your code.
The problem may where the code is being executed. If you are in the head of a document executing JavaScript, even when you have an element with id="u" in your web page, the code gets executed before the DOM is finished loading, and so none of the HTML really exists yet... You can fix this by moving your code to the end of the page just above the closing html tag. This is one good reason to use jQuery.
In case anyone landed on this page for a similar issue, I found that this error can happen if your JavaScript is running in the HEAD before your form is ready. Moving your JavaScript to the bottom of the page fixed it for my situation.
The problem is that you haven't got any element with the id u so that you are calling something that doesn't exist.
To fix that you have to add an id to the element.
<input id="u" type="text" class="searchbox1" name="search" placeholder="Search for Brand, Store or an Item..." value="text" />
And I've seen too you have added a value for the input, so it means the input is not empty and it will contain text. As result placeholder won't be displayed.
Finally there is a warning that W3Validator will say because of the "/" in the end. :
For the current document, the validator interprets strings like according to legacy rules that break the expectations of most authors and thus cause confusing warnings and error messages from the validator. This interpretation is triggered by HTML 4 documents or other SGML-based HTML documents. To avoid the messages, simply remove the "/" character in such contexts. NB: If you expect <FOO /> to be interpreted as an XML-compatible "self-closing" tag, then you need to use XHTML or HTML5.
In conclusion it says you have to remove the slash. Simply write this:
<input id="u" type="text" class="searchbox1" name="search" placeholder="Search for Brand, Store or an Item...">
I knew that i am too late for this answer, but i hope this will help to other who are facing and who will face.
As you have written h_url is global var like var = h_url; so you can use that variable anywhere in your file.
h_url=document.getElementById("u").value;
Here h_url contain value of your search box text value whatever user has typed.
document.getElementById("u");
This is the identifier of your form field with some specific ID.
Your Search Field without id
<input type="text" class="searchbox1" name="search" placeholder="Search for Brand, Store or an Item..." value="text" />
Alter Search Field with id
<input id="u" type="text" class="searchbox1" name="search" placeholder="Search for Brand, Store or an Item..." value="text" />
When you click on submit that will try to fetch value from document.getElementById("u").value; which is syntactically right but you haven't define id so that will return null.
So, Just make sure while you use form fields first define that ID and do other task letter.
I hope this helps you and never get Cannot set property 'value' of null Error.
guys This error because of Element Id not Visible from js Try to inspect element from UI and paste it on javascript file:
before :
document.getElementById('form:salesoverviewform:ticketstatusid').value =topping;
After :
document.getElementById('form:salesoverviewform:j_idt190:ticketstatusid').value =topping;
Credits to Divya Akka .... :)
It seems to be this function
h_url=document.getElementById("u").value;
You can help yourself using some 'console.log' to see what object is Null.
h_url=document.getElementById("u") is null here
There is no element exist with id as u
Add defer to your script tag, if it's in header. It will allow your script to execute after the DOM is loaded.
<script src="script.js type="text/javascript"></script>
It should look like this:
<script src="script.js type="text/javascript" defer></script>

data-dojo-mixin and id value

I'm trying to add a mixin to our ValidationTextBox using data-dojo-mixin="_MaskedMixin" in the html attribute for use when the parser runs over my document. When I do this, the instance gets an id of "_MaskedMixin_0" instead of "ValidationTextBox_0".
Is there any way to preserve the "ValidationTextBox" identity of the mixed in object?
Not knowing your particular case, my recommendation would be to specify the id in the HTML markup and not let the parser auto generate one. But if you want the id to be auto generated, you can override the declared class.
http://jsfiddle.net/cswing/EQj8G/
<input type="text" data-dojo-type="dijit/form/ValidationTextBox"
data-dojo-mixins="_MaskedMixin"
data-dojo-props="declaredClass:'ValidationTextBox'"
value="" ></input>

Accessing an array of HTML input text boxes using jQuery or plain Javascript

I'm looking to create a form which contains a dynamic number of input text boxes. I would like each text box to form part of an array (this would in theory make it easier for me to loop through them, especially as I won't know the number of text fields that will eventually exist). The HTML code would like something like:
<p>Field 1: <input type="text" name="field[1]" id="field[1]"></p>
<p>Field 2: <input type="text" name="field[2]" id="field[2]"></p>
<p>Field 3: <input type="text" name="field[3]" id="field[3]"></p>
<p>Field 4: <input type="text" name="field[4]" id="field[4]"></p>
<p>Field 5: <input type="text" name="field[5]" id="field[5]"></p>
This data would then be sent to a PHP script and would be represented as an array - or at least, that's the theory.
So my first question is, is this achievable using HTML? Are forms designed to work that way?
If the answer to that is "yes", how would I then go about accessing each of those using jQuery or failing that, plain old JavaScript?
I've attempted to achieve this using the following jQuery code:
someval = $('#field[1]').val();
and
someval = $('#field')[1].val();
and the following JavaScript:
someval = document.getElementById('related_link_url')[1].value;
But I've not had any luck.
Thanks in advance.
Edit:
I should note that from a Javascript point of view, I've had it working where the ID of each element is something like field_1, field_2 etc. However, I feel that if I can achieve it by placing each text box into an array, it would make for tidier and easier to manage code.
Give each element a class and access the group using jQuery:
<p>Field 1: <input type="text" name="field[1]" class="fields"></p>
<p>Field 2: <input type="text" name="field[2]" class="fields"></p>
<!-- etc... -->
jQuery:
$("input.fields").each(function (index)
{
// Your code here
});
This will run the anonymous function on each input element with a classname of "fields", with the this keyword pointing to the current element. See http://api.jquery.com/each/ for more info.
First of all, id attribute cannot contains [ or ] character.
There is lots of ways to get jQuery/plain JavaScript references to these elements. You can use descendant selector:
<fieldset id="list-of-fields">
<!-- your inputs here -->
</fieldset>
$("#list-of-fields input");
document.getElementById("list....").getElementsByTagName("input");
You can also use attribute selector:
$("input[name^=field]");
I'm not sure whether that's the only way but I think in plain JavaScript you'll have to fetch all input elements (document.getElementsByTagName) and then loop through array of these elements and check each element (whether it has name attribute which value starts with field).

Categories

Resources