JavaScript creating array with input name and values - javascript

I was formulating this question:
Is it possible to make an array automatically from the .name and .value data used in all the inputs type text?
This is the reference doing manually:
var foo = [];
foo['bar'] = 'foo data';
foo['foo'] = 'bar data';
I got this idea... And it works...
var foo[];
for (var i = 0; i < document.getElementsByTagName('input').length; i++)
{
foo[document.getElementsByTagName("input")[i].name] = document.getElementsByTagName("input")[i].value;
};
The mission was to make it work automatically.
Get the .name of the input and get the .value of that input.
I was editing the question to post it here... When I figured out how to make it. I decided to leave here the reference, it'll be useful for someone, I guess.
Feedback is welcome.

Your code is reasonable enough, except for two things:
Use an object instead of an array.
Create the list of inputs only once.
So you could do:
var values = {};
var inputs = document.getElementsByTagName('input');
for( var i = 0; i < inputs.length; i++ ) {
values[inputs[i].name] = inputs[i].value;
}

Related

How do I create a dictionary out of each user with their current game? Discord.js

I thought of somethinh like this:
var userGames = {};
for (i=0; i< client.getListOfOnlineUsers(); i++) {
var key = client.getListOfOnlineUsers()[i];
userGames.key = client.getListOfOnlineUsers()[i].presence.game;
}
Is this the right way to go?
I haven't used discordjs, so correct me if I got anything wrong. As I understand it, getListOfOnlineUsers returns the array of users and user.presence.game will give you the game. If so, you have the correct idea, just a minor correction on line 4:
var userGames = {};
for (i=0; i< client.getListOfOnlineUsers(); i++) {
var key = client.getListOfOnlineUsers()[i];
userGames[key] = client.getListOfOnlineUsers()[i].presence.game;
}
This should work for you. The [key] is used here because key is a variable and the real value of the dictionary key is computed at run-time.
Also, you should probably avoid calling the same function over and over when it returns the same result. Save the data in a variable. Maybe, use forEach and let too.
let userGames = {};
const userList = client.getListOfOnlineUsers();
userList.forEach(u => userGames[u] = u.presence.game);
Looks a lot cleaner imo.

Making variables assigned HTML ids with a function

I can make variables one by one like this:
var bookName = document.getElementById('bookName').value,
author = document.getElementById('author').value,
translator = document.getElementById('translator').value,
pageCount = document.getElementById('pageCount').value,
publisher = document.getElementById('publisher').value,
isbn = document.getElementById('isbn').value,
printingYear = document.getElementById('printingYear').value;
But it's so hard to write and it doesn't fit with the DRY rule. So I changed the code to this:
function variableMaker(argument) {
var tags = document.getElementsByTagName(argument);
for (var i = 0; i < tags.length; i++) {
var tags[i].name = tags[i].value;
}
}
variableMaker(input);
But I can't understand if it is the true way or if it is working? How do I check if it's true or not?
In this code, I tried to get the computer find all the input tags and make variables with their name property and assign it to its values for each of them.
If I understand correctly then you want to gather data from all <input> elements. If so, then you need to call it like this:
variableMaker('input'); // use quotes!
Still even then your function does not return anything, it just ends.
You'd also better create your own object for the return collection, instead of adding values to an existing object.
Here is a working solution:
function variableMaker(tagName) {
var elements = document.getElementsByTagName(tagName);
var items = {};
for (var i = 0; i < elements.length; i++) {
var elem = elements[i];
items[elem.id] = elem.value; // Use id as key, each points to the corresponding value.
}
return items;
}
var values = variableMaker('input');
console.log(values); // show the entire return object
console.log(values.author); // access individual items from the return object
console.log(values.isbn);
<input type="text" id="author" value="Dahl">
<input type="text" id="isbn" value="1234">
.

How can I dynamically index through datalayer tags in GTM?

I'm using the DuracellTomi datalayer plugin to push cart data from woocommerce to a GTM model to handle some tracking.
The DuracellTomi plugin pushes content to the transactionProducts[] array in the following format:
transactionProducts: Array[1]
0 : Object
category:""
currency:"USD"
id:8
name:"Test"
price:100
quantity:"1"
sku:8
I'd like to loop through this array and unstack it into three separate arrays, pricelist, skulist, and quantitylist. Currently I anticipate doing so as some variation on
//Get Product Information
if(stack = {{transactionProducts}}){
for(i = 0; i < stack.length; i++) {
if(stack.i.sku){
skulisttemp.i = stack.i.sku;
}
if(stack.i.price){
pricelisttemp.i = stack.i.price;
}
if(stack.i.sku){
quantitylisttemp.i = stack.i.quantity;
}
}
{{skulist}} = skulisttemp;
{{pricelist}} = pricelisttemp;
{{quantitylist}} = quantitylisttemp;
}
Obviously this is not going to work because of how the tag referencing is set up, but I'm wondering if anyone has dealt with this and knows what the best way to index through these arrays might be. (For those who don't know, the square bracket array call doesn't work with GTM variables and instead the . format is used instead.)
You would need to create 3 variable type custom javascript function that picks your required value from dataLayer and returns it in an array.
Something like
function(){
var products = {{transactionProducts}};
var skuArray = [];
for(i = 0; i < products.length; i++) {
if(products[i].sku){
skuArray.push(products[i].sku)
}
}
return skuArray
}
hope this helped you :)

Empty / blank out all fields in a form page

I have the below code, is there a way to put this in a simpler format.
I am having to blank out 50 or more fields when a date in a certain key field is changed or made blank.
if (zEntry ==""){
document.getElementById("Q229I1226").value="";
document.getElementById("DQ230I1227").value="";
document.getElementById("DQ231I1228").value="";
document.getElementById("Q4I1001").value="";
//Date from fall to arrival
document.getElementById("Q232I1229").value="";
document.getElementById("DQ233I1230").value="";
document.getElementById("DQ234I1231").value="";
document.getElementById("Q5I1002").value="";
//Date Time of referral to T&O surgery
document.getElementById("Q238I1235").value="";
document.getElementById("DQ239I1236").value="";
document.getElementById("DQ240I1237").value="";
document.getElementById("Q15I1012").value="";
document.getElementById("Q17I1014").value="";
//Date seen T&O 1st on call
document.getElementById("Q241I1238").value="";
document.getElementById("DQ242I1239").value="";
document.getElementById("DQ243I1240").value="";
document.getElementById("Q16I1013").value="";
}
Thank you
You have to add common class to your inputs.
var array = document.getElementsByClassName('className');
for (var i = 0, lng = array.length; i < lng; i++) {
array[i].value = '';
}
If you want to clear out all fields with same tag you can just use
document.getElementsByTagName(arg) while arg being 'input', 'option' etc.
But if you want specific inputs to be cleared, you have to give them a class and use
document.getElementsByClassName(arg)
Add class to the input fields and try
var array_container = document.getElementsByClassName('example');
for (var i = 0, i < array_container.length; i++) {
array_container[i].value = '';
}
You may try this approach too:
// store all the element ids in an array
var element_ids = ['Q229I1226', 'DQ230I1227', 'DQ231I1228', 'Q4I1001',
'Q232I1229'];
element_ids.forEach(function(element_id){
document.getElementById(element_id).value = '';
});
Here is a solution of how to clear all input boxes/fields by looping.
Loop though all input boxes and clear them

Get value of JSON object with inner objects by HTML form field name without eval

I have a problem like this Convert an HTML form field to a JSON object with inner objects but in to the other direction.
This is the JSON Object response from the server:
{
company : "ACME, INC.",
contact : {
firstname : "Daffy",
lastname : "Duck"
}
}
And this is the HTML form:
<form id="myform">
Company: <input type="text" name="company" />
First Name: <input type="text" name="contact.firstname" />
Last Name: <input type="text" name="contact.lastname" />
</form>
And this is the (pseudo)code:
var aFormFields;
for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {
var sFieldName = aFormFields[i].getAttribute('name');
eval("sFieldValue = oResponse."+sFieldName);
}
Ok my solution works, but i looking for a good way to remove the evil eval from the code.
And the solution should also work for form fields with any count of dots in the field name.
Instead of:
eval("sFieldValue = oResponse."+sFieldName);
Use for single dotted fields:
sFieldValue = oResponse[sFieldName];
This will retrieve the value via its key.
Now if you need more than that you need to do the following:
Split sFieldName on .
Loop over that array and go down in oResponse till you reach the value that you desire
Code could look like this:
var node = oResponse, parts = sFieldName.split('.');
while(parts.length > 0) {
node = node[parts.shift()];
}
// node will now have the desired value
Further information on "Member Operators":
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators
This works for a single property:
sFieldValue = oResponse[sFieldName]
But it won't work for nested data like contact.firstname.
For that, split the name by dots, and use loop through each name:
var aFormFields;
for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {
var aFieldNameParts = aFormFields[i].getAttribute('name').split(".");
var oFieldValue = oResponse;
for(var j=0; j<aFieldNameParts.length; j++) {
oFieldValue = oFieldValue[aFieldNameParts[j]];
}
var sFieldValue = oFieldValue;
}
Note: if a property does not exist, an error will occur. You might want to check whether oFieldValue[ aFieldNameParts[j] ] exists or not.
While it is possible, I wouldn't loop over the input fields, but over the JSON object:
function fillForm (form, data, prefix) {
prefix = prefix ? prefix + "." : "";
for (var x in data) {
if (typeof data[x] === "string") {
var input = form.elements[prefix + x];
if (input)
input.value = data[x];
} else
fillForm(form, data[x], prefix + x);
}
}
fillForm(document.getElementById("myform"), oResponse);
(untested)
Assuming your naming scheme is consistent, you can convert the dot-notation into subscripts. You'd have to split the field name on the period and iterate or recurse over the tokens, converting each into a subscript. Of course this assumes that oResponse always contains a value for every field.
for (var i = 0; i < aFormFields.length; i++) {
var sFieldName = aFormFields[i].getAttribute('name');
var tokens = sFieldName.split('.');
var cur = oResponse;
for (var j = 0; j < tokens.length; j++) {
cur = cur[tokens[j]];
}
sFieldValue = cur;
}
please treat this as a combination of answer and question :)
i am currently trying to get my server to jsonify the data that i get sent from a form just like you...
in my case the form will in the end create a json object with multiple subobjects that can have subobjects which can have... as well.
the depth is up to the user so i should be able to support infinite recursion.
my "solution" so far just feels wrong, but it correctly does the job,
the function getRequestBody gets fed a req.body object from expressjs,
this is basically an object with the following mapping:
{
"ridic-ulously-deep-subobject": "value",
"ridic-ulously-deep-subobject2": "value",
"ridic-ulously-deep2-subobject3": "value",
}
the following html is in use:
<form>
<input name="ridic-ulously-long-class-string" value="my value" />
</form>
and the javascript function (that should work genericly, feed it a req.body object like above and it will return a json object):
function getRequestBody(reqB){
var reqBody = {};
for(var keys in reqB) {
var keyArr = keys.split('-');
switch(keyArr.length){
case 1:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
reqBody[keyArr[0]] = reqB[keys];
break;
case 2:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
reqBody[keyArr[0]][keyArr[1]] = reqB[keys];
break;
case 3:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
if(!reqBody[keyArr[0]][keyArr[1]][keyArr[2]]) reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = {};
reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = reqB[keys];
break;
case 4:
// ...
//and so on, always one line longer
}
return reqBody;
}
this just feels wrong and its only covering 5 levels of subobjects right now,
it might happen that an application has enough functionality to reach seven or even ten levels though.
this should be a common problem, but my search effort turned up nothing within 10 minutes,
which usually means that i am missing some keywords
or
that there is no viable solution [yet] (which i cant really imagine in this case).
is there someone out there who has imagination and logic sufficient enough to unspaghettify this or will i just have to expand this function with even more clutter to get me down to 10 possible sublevels?
i think that in the end it wont make a big difference performance wise,
but i would really like NOT to create this awful behemoth :D
have fun
jascha

Categories

Resources