Javascript reading multidimensional form - javascript

This has driven me "doo-lally" this afternoon!
A vendor (Zaxaa) uses a multi-dimentional form thus:
<form method="post" name="zaxaa" action="xxxx">
<input type="text" name="products[0][prod_name]" value="ABC">
<input type="text" name="products[0][prod_type]" id="pt" value="FRONTEND">
</form>
** This is my understanfing of how a multdimentional array is set up, and it seems to pass the variables to the server OK.
However, dependant on what other inputs are set to on the test form, the [prod_type] (and others) may need to change to "OTO" This is obviously going to be a javascript function, (but not the variant that starts with "$" on code lines ... whatever that type is!)
I have tried
document.zaxaa.products[0].prod_type.value
document.getElementById('products[0][prod_type]').value
document.getElementsByName('products[0][prod_type]').value
but in everycase, I get "products is not defined". (I have simplified the form as there are ten product[0] fields)
I've solved it... mainly a glaring error on my part. The getElementById worked fine ... except in my test script I'd used getElementById[xxx] and not getElementById(xxx)!! ie "[" rather than "(" Does help if you get the syntax right!
But I will take notice of those other methods, such as enclosing both array arguments in ["xxx"].

getElementById didn't work because the only one of those elements that has an id is the second input, with id="pt".
On any modern browser, you can use querySelector to get a list of the inputs using a CSS selector:
var nameInput = document.querySelector('input[name="products[0][prod_name]"]');
var typeInput = document.querySelector('input[name="products[0][prod_type]"]');
Then use their value property. So for instance, to set the name to "OTO":
document.querySelector('input[name="products[0][prod_name]"]').value = "OTO";
Use querySelectorAll if you need a list of relevant inputs, e.g.:
var nameInputs = document.querySelectorAll('input[name="products[0][prod_name]"]');
Then loop through them as needed (the list as a length, and you access elements via [n] where n is 0 to length - 1).
Re
* This is my understanfing of how a multdimentional array is set up...
All that HTML does is define input elements with a name property. That name property is sent to the server as-is, repeated as necessary if you have more than one field with that name. Anything turning them into an array for you is server-side, unrelated to JavaScript on the client. (The [0] is unusual, I'm used to seeing simply [], e.g name="products[][prod_name]".)

You can access it in this syntax:
document.zaxaa['products[0][prod_name]'].value

document.zaxaa.products[0].prod_type.value
The name is a single string, not making a nested structure to access the input. It would need to be
document.zaxaa["products[0][prod_type]"].value
// or better:
document.forms.zaxaa.elements["products[0][prod_type]"].value
The complicated name does only serve to parse the data into a (multidimensional) array on the server side, but all data will be sent "flattened".
document.getElementById('products[0][prod_type]').value
The id of your input is pt, so this should work as well:
document.getElementById("pt").value
document.getElementsByName('products[0][prod_type]').value
getElementsByName does return a collection of multiple elements - which does not have a .value property itself. Instead, access the first element in the collection (or iterate it completely):
document.getElementsByName('products[0][prod_type]')[0].value

Related

Alternative Way to Pass Checkbox Array to $_GET - Besides Square Braces

I understand that if I use a checkbox value of name[], then I will receive a data array on the server (when using PHP), named 'name[]'. This has worked fine for me, but I'm running into some URL sizes that could cause issues with less robust IE browsers and all the encoded square braces are killing me in this area, easily causing the URL length to be at least 4-6 times longer than what it could possibly be, if another way were available. Is there a reliable method using javascript (jquery syntax even better) to intercept a checkbox forms values and convert them into something like this:
"&checkboxarray=1-23-45-13-67"
I figure that on the other end I can easily explode $_GET['checkboxarray'] into an actual array and go from there as I usually do with matching the selection array against the options array, etc... I just don't know if it's possible or how to create alter the submit process.
Side note, isn't passing "name[]" to a URL non-standards compliant anyways? Every browser I've used auto encodes it, but not Mozilla, however it seems to work fine.
EDIT: I need to create paginated links, which is why I'm using GET, instead of POST. This is also and industrial search, very comprehensive, lots of power user options.
UPDATE & Answer: I managed to come up with my own answer. For anyone else who wants to take advantage of $_GET's easy pagination workflow but you need to pass large data arrays and are worried about URL length, here's a simplistic way to compact it all down into one variable with dash separated values:
NOTE: I HIGHLY suggest you first make sure any dynamic arrays generated from queries start with 1 rather than 0 if your going to recheck values after submit, here's how, since 0 can be a real pain in the neck to work with in PHP conditional statements:
$your_array= array();
array_unshift($your_array,'');
unset($your_array[0]);
In your HTML code, set all checkbox input names to "something[]" and underneath this set of inputs, create a hidden input with the name "something", I suggest you make them match, but I suppose you could use another name, just make sure the hidden one is missing the square braces, also set the hidden input value to "":
<input type="text" name="something[]" value="1">
.....
<input type="text" name="something[]" value="20">
<input type="hidden" name="something" value="">
Javascript: NOTE, requires jquery... this grabs all the "something[]" input values and forms a dashed array while killing off "something[]" values from being submitted and only submitting "something".
$('#submitbutton').click(function(){
var searchIDs = $('input[name="something[]"]:checked').map(function(){
return $(this).val();
}).get();
var IDstring = searchIDs.toString();
var newvar = IDstring.replace(/,/g, '-');
$('input[name="something"]').val(newvar);
$('input[name="something[]"]:checkbox').prop("checked", false);
});
On the server side, simply explode the 'something' value from $_GET.
$somethingArray = explode('-',$_GET['something']);
There it is! Hope it helps someone in the future make their GET sent arrays more compact. Bonus: Avoids sending unsafe characters in the URL, Mozilla doesn't appear to auto encode square braces, at least not my version of it on Linux Mint ;)
Update:
I just implemented this code on a big country checkbox form with 284 possible selections. With my old code, even using 'c[]' as the name, my character count was around 3100 characters, with the new approach, my character count now rings in at just 1109. Worth the effort.
You can use POST instead of GET method.
GET has URL length limitations.
POST is useful in passing long data, e.g. an array in your case.
There is a default limit of POST method which is 2MB which is way higher than GET. If needed, it can easily be increased in php.ini file post_max_size 10MB.
Replace $_GET with $_POST in your script.

javascript add array item to form value

I have a form with a hidden field:
<input type="hidden" name="newdesc[]" id="newdesc" />
I have an autolookup and a plus button so the plus button adds the field value of the autolookup to an array:
newdesc_a.push(document.getElementById('autocomplete1').value);
var x=document.getElementById("businesslist");
x.innerHTML=newdesc_a;
document.getElementById('newdesc').value = newdesc_a;
(newdesc_a is previously declared as an array)
It updates the div OK (businesslist) but does not assign the value to the newdesc.
I am sure it is simple but it is driving me mad!
Given the name="newdesc[]" attribute, I assume PHP on the server side. When you submit a key two or more times, only the last value is available in the script via $_REQUEST. In the case of a key ending with [] , instead, PHP builds an array and make it available to your script via $_REQUEST['key']. Note that this behavior is application-specific, there's nothing like an array at the HTTP level.
Now, you want to pass an array from the client side (Javascript) to the backend (PHP). You have two options:
Use a proprietary format, eg separate values by commas or colons, and split the string on the server side (or you can use an existing format like JSON, XML, ...)
Take advantage of the PHP syntax for passing arrays
It seems you want to adopt the 2nd way, so you will want to submit a form like the following
<input name="email[]" value="joel#example.com" />
<input name="email[]" value="mark#people.com" />
<input name="email[]" value="bill#hello.com" />
PHP will be able to access a plain array in $_REQUEST if you build your form like this. Now, you have the problem of building the form programmatically on demand. This is the best I can think of (jQuery):
var email = $("#autocomplete").value;
// if you really need to keep emails in an array, just
// emails.push(email);
$('<input type="hidden">').attr({
name: 'email[]',
value: email
}).appendTo('#myForm');
You want to assign a particular value of array to that element?
You can use like this.
document.getElementById('newdesc').value = newdesc_a.index;
where 'index' is the index of array. replace it.

Split to get the text between separators?

I am making a cross domain AJAX request, and because of this, I can't pass the original array from the PHP page to my HTML page. Instead, the request gets the results as a string. I have it set up so that the syntax looks like this:
([SCHOOL] Name [/SCHOOL][STATUS] Status [/STATUS])
([SCHOOL] Other name [/SCHOOL][STATUS] Other status [/STATUS])
On my HTML page, I want to be able to form an array from these different values, in the form of:
Array (
[0] =>
[0] Name
[1] Other
[1] =>
[0] Name
[1] Other status
)
This way, I can use a for loop to get specific values.
The only problem with is that split only does just that, splits things. Is there a way in JS to find the text within separators, and form an array from it? In the example again, it'd find all text within the parenthesis, and form the first array, then within that array, use the text between [SCHOOL][/SCHOOL] for the first object, and use the text between [STATUS][/STATUS] for the second object.
Ideally, you would use something more suited to storing arrays on the server side. I would recommend JSON. This would be trivial to encode using php, and decode using javascript.
If you do not have that option server side, then you can use regex to parse your text. However, you must be sure that the contents does not have your delimiters within in it.
It is not clear how you get your target data structure from your source, but I would expect something like this might work for you:
str = "([SCHOOL] Name [/SCHOOL][STATUS] Status [/STATUS])\n\
([SCHOOL] Other name [/SCHOOL][STATUS] Other status [/STATUS])"
arr =[]
m = str.match(/\(.+?\)/g)
for(i in m){
matches = m[i].match(/\(\[SCHOOL\](.+?)\[\/SCHOOL\]\[STATUS\](.+?)\[\/STATUS\]\)/)
arr.push([matches[1],matches[2]])
}
console.dir(arr)

javascript not getting value

I am wondering just how come the following is giving me hassle, it looks straight forward but I am not sure whats happening.
So I have a input box and I want a user to fill it in, every time i run the following
i get unidentified and I am not sure why.
<input type="numbers" name="price" class="sell" placeholder="$0.00">
Am using the following javascript
var price = document.getElementsByName("price")
alert(price.value);
var price = document.getElementsByName("price")[0];
alert(price.value);
document.getElementsByName will give you HTMLCollection (kind of array) as a return type. This is because a number of elements in your dom may share the same name. So if you have number of checkboxes having same name you can refere each checkbox with the array index.
You have several problems.
The one causing your problem is that getElementsByName returns an HTMLCollection (which is like an array), not a single element. You need to pull the first item off it before trying to access its properties.
var price = document.getElementsByName("price")[0];
Second, numbers it not a type of input. number (singular) is.
Third, if you give the example $0.00 then you are informing people that you expect them to type a value starting with a $ sign. You can't have a $ sign in a number.

getElementById and JQuery not returning same result

I'm not getting the same result when I use JQuery vs javascript functions.
This is the HTML
<form id="testform">
<div id="FormContainerID"></div>
<input type="button" id="y" value="Button" />
<div id="ListContainerID"></div>
</form>
Here is the Javascript
01 var Form = document.getElementById('y').form;
02 //var Form = $('#y').closest('form');
03 alert(Form);
When Activating row 1, I get a legal form object. The Alert says "object HTMLFormElement" and everything works fine.
But if I use row 02 instead, Alert says "object Object" and then I ofcourse get errors becaus it isn't a real Form object.
Why is JQuery not returning the correct Object?
I get the same result with Chrome and IE8.
[EDIT]
I'm using JQuery version: jquery-1.5.1.min
[SOLUTION]
Thank you for clearing this up. I Changed the code to:
var Form = $('#'+fChildID).closest('form')[0];
...and now it works as a charm.
Vivek Goel was the first to answer, so creds to him. I voted up you other guys that explained the JQuery instance model.
Thank you.
jQuery returns a jQuery instance when you use it to look things up, not the raw DOM element. The jQuery instance is a wrapper around the set of matched elements, and allows you to apply set-based operations to the elements. This is one of the absolute fundamentals of using jQuery.
You can also access the raw elements if you like using array-like notation — [0], [1], etc., up to .length - 1. So in your case, since you're getting just one element, it would be Form[0]. If your code matched multiple form elements, it would be Form[1] for the second one, Form[2] for the third one, etc. (Using the [] notation is surprisingly hard to find in the documentation, though, one of the gaps in my view; in the old days you used the get method, but you only need that now if you're using its special handling for negative indexes.)
You frequently don't need to access the raw elements at all. You haven't said what you're going to do with the form once you have it, but if you were to (say) submit it, just call the submit function on the jQuery instance, and it will submit the form. If you wanted to get an attribute from it, there's the attr jQuery function (so for instance, val = Form.attr("action")).
jQuery is very set-based, but it's assymetrical, which feels weird at first but works fairly well in practice. When getting a value, functions usually get the value from the first matched element only. When setting a value, functions usually set it on all the matched elements.
This is because the jquery statement is returning a jquery object and not a form object.
You need something like Form[0] to access the form element.
with jquery use
alert(Form[0]);
http://jsfiddle.net/dvCtr/
Try
var form = $("#y").parent
this should return the parent of yin the DOM tree

Categories