create variable from string given in array - javascript

Is there any way to create variable from String inside the array with the name of the String?
something like this:
const array = ["type","name","hours","photos","place","price"];
array.forEach(item =>{
let item = document.crea.....
//but it should work like let array[index] = docu.......
})
The reason for this is that I wanted to make this code look a bit nicer and its obvious, that there are quite a lot things repeating.
const type = document.createElement("td");
const name = document.createElement("td");
const hours = document.createElement("td");
const photos = document.createElement("td");
const place = document.createElement("td");
const price = document.createElement("td");
type.innerHTML = element.type;
name.innerHTML = element.name;
hours.innerHTML = element.hours;
photos.innerHTML = element.photos;
place.innerHTML = element.place;
price.innerHTML = element.price;
tr.appendChild(type);
tr.appendChild(name);
tr.appendChild(hours);
tr.appendChild(photos);
tr.appendChild(place);
tr.appendChild(price);

Try use var or let instead const,works for me always.
And remember foreach is a kind of loop means
var mytd = document.createElement("td");mytd.innerHTML = element.{item};tr.appendChild(mytd);

I know this doesn't directly answer your question about variable names, but this should be the code you need to get your result.
array.forEach(item => {
const elem = tr.appendChild(document.createElement("td"));
elem.innerHTML = item;
})
You don't really need to use your array to generate the variable name as the forEach handles each item in the array separately.

Related

Error in my task 4, it seems that .checked and .value doesn't seem to work as intended

Link to Scrimba to check on code : https://scrimba.com/scrim/czvrQJcM
Essentially what should happen is that when the details are added and the button is clicked, the data first gets saved into the object, 'student' and pushed into the array. Then the array is run and the students names are displayed on the page.
I just solve your problem. Look:
At your enrolStudent() function you set the following line:
studentList = studentList.push(student);
So, you should change it to:
studentList.push(student);
This is because the push() method returns the length of the array. So, you don't need to attribute the operation result to the array. The method already updated its own value.
Task4 after the change:
function enrolStudent()
{
let firstnameRef = document.getElementById("fname");
let lastnameRef = document.getElementById("lname");
let studentIdRef = document.getElementById("studentid");
let dateRef = document.getElementById("date");
let courseRef = document.getElementById("course");
let genderRef = document.getElementsByName("gender");
for (let i=0; i < genderRef.length; i++)
{
if (genderRef[i].checked)
{
var genderSelection = genderRef[i];
}
}
let student = new Object();
student.firstName = firstnameRef.value;
student.lastName = lastnameRef.value;
student.id = studentIdRef.value;
student.course = studentIdRef.value;
student.gender = genderSelection.value;
student.date = dateRef.value;
studentList.push(student);
var val = studentList.push(student);
studentEnrolSummaryRef.innerHTML = displayStudents(studentList);
console.log(val);
}
```

how to get cell range values with background colors in to single array?

I tried to write the script as shown below. It is necessary to combine the values and background colors in this cell range into a single array. But it does not come as needed.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds();
var c = catList.map((key,index) => ({[key]:catClrs[index]}));
Logger.log(c);
}
The answer comes this way
But I want an outcome like this.
[{Extra,true,#b6d7a8}, {Extra,false,#ffffff}, {Extra,false,#ffffff}, {Ldrain ,false,#ffffff}, {Dish Drain,true,#0c343d}, {U drain,true,#274e13}, {Hard Sholder,true,#00ffff}, {Soft Sholder,true,#cc0000}, {As. wearing,true,#ff9900}, {Tack coat Wearing,true,#fce5cd}, {As.Binder,true,#9900ff}, {Tack Coat binder,true,#46bdc6}, {Prime coat,true,#000000}, {ABC overlay,false,#ffffff}, {Subbase overlay,true,#980000}, {Edgewidning ABC,true,#999999}, {Edgewidning Subbase,false,#ffffff}, {SubGrade Ew,true,#0000ff}, {Embankment 5,true,#9fc5e8}, {Embankment 4,true,#6fa8dc}, {Embankment 3,true,#3d85c6}, {Embankment 2,true,#0b5394}, {Embankment 1,true,#1c4587}, {Subgrade Emb,true,#8e7cc3}, {Soft Ground tratment 1,true,#c27ba0}, {Soft Ground tratment 2,true,#a64d79}, {Clearing & grabbing,true,#f1c232}
I'd do it like this because it will be easier to read the values as you iterate through the array by having property labels for the object
function myobject(){
const ss=SpreadsheetApp.getActive()
var sh = ss.getSheetByName("AddData");
var catList = sh.getRange("I5:J31").getValues();
var catClrs = sh.getRange("J5:J31").getBackgrounds().flat();
let c=[];
catList.forEach((row,i) => {c.push({label:row[0],value:row[1],color:catClrs[i]})});
Logger.log(JSON.stringify(c));
}
With my fake data:
[{"label":3,"value":21,"color":"#ffffff"},{"label":0,"value":17,"color":"#ffffff"},{"label":5,"value":29,"color":"#ffffff"},{"label":29,"value":25,"color":"#ffffff"},{"label":16,"value":24,"color":"#ffffff"},{"label":17,"value":15,"color":"#ffffff"},{"label":22,"value":4,"color":"#ffffff"},{"label":6,"value":1,"color":"#ffffff"},{"label":4,"value":28,"color":"#ffffff"},{"label":14,"value":28,"color":"#ffffff"},{"label":13,"value":1,"color":"#ffffff"},{"label":2,"value":15,"color":"#ffffff"},{"label":23,"value":6,"color":"#ffffff"},{"label":14,"value":24,"color":"#ffffff"},{"label":21,"value":6,"color":"#ffffff"},{"label":12,"value":18,"color":"#ffffff"},{"label":12,"value":7,"color":"#ffffff"},{"label":5,"value":5,"color":"#ffffff"},{"label":2,"value":0,"color":"#ffffff"},{"label":16,"value":16,"color":"#ffffff"},{"label":15,"value":21,"color":"#ffffff"},{"label":0,"value":25,"color":"#ffffff"},{"label":20,"value":6,"color":"#ffffff"},{"label":24,"value":23,"color":"#ffffff"},{"label":22,"value":0,"color":"#ffffff"},{"label":14,"value":15,"color":"#ffffff"},{"label":24,"value":6,"color":"#ffffff"}]
Added flat()
Replaced key by row, index by i and ({[key]:catClrs[index]}) by [row[0],row[1],catClrs[i]]
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
Logger.log(c);
}
The result will be slightly different because {} is used for objects and objects requires a key and a value.
I changed key by row to make the variable name closer to what it's holding as usually a "key" is a string but in this case it's an Array holding the values of two cells in the same row. i is shorter than index.
Nothing new compared to the accepted answer, but just shortening your code and a slighty better performance:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]);
Logger.log(c);
}
If you want to filter on the true values:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]).filter(r=>r[1]);
Logger.log(c);
}
Here is the code that worked correctly. In addition to what is mentioned in the question, the method of filtering is also included.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
//merge arrays
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
//filter "checked" boxes values
var fillterC = c.filter(filterLogic);
}
//create filter logic function
var filterLogic =function(item){
if(item[1] === true){
return true;
}else{
return false;
}
}
Thanks to everyone who helped. I learned a lot.

Creating a loop for inserting data inside the table

I have got a simple loop that puts data from a list to the table:
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
const tdData = document.createElement("td");
const tdData2 = document.createElement("td");
const tdData3 = document.createElement("td");
const tdData4 = document.createElement("td");
const tdData5 = document.createElement("td");
tbody.appendChild(rowData);
tdData.textContent = item.position;
rowData.appendChild(tdData);
tdData2.textContent = `${item.name} ${item.surname}`;
rowData.appendChild(tdData2);
tdData3.textContent = item.data2;
rowData.appendChild(tdData3);
tdData4.textContent = item.point;
rowData.appendChild(tdData4);
tdData5.textContent = item.fruits;
rowData.appendChild(tdData5);
})
Anyone knows how I can automate this process? I don't think, that my way is super efficient, so I am looking for another answer.
I typically break repeating elements down into smaller pieces, and then repeat as needed to make it easier to read. For instance, you are creating a lot of 'td' elements with text inside it, so I would start with something like:
function newElementWithText( innerText )
{
const td = document.createElement("td");
td.textContent = innerText;
return td;
}
to handle that part. If you incorporate that solely into your code, you would have:
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
rowData.appendChild(
newElementWithText(item.position) );
rowData.appendChild(
newElementWithText(`${item.name} ${item.surname}`);
rowData.appendChild( newElementWithText(item.data2);
rowData.appendChild( newElementWithText(item.point);
rowData.appendChild(
newElementWithText(item.fruits) );
tbody.appendChild(rowData);
}
This can be made more readable using an array of the data that is needed, and then mapping it into the new td element, and then finally appending it.
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
const data = [
item.position,
`${item.name} ${item.surname}`,
item.data2,
item.point,
item.fruits
];
//Creates an array of the 'td' elements with text.
var tdElements = data.map( x => newElementWithText(x) );
//Iterates over the new array and appends to the rowData.
tdElements.map( x => rowData.appendChild(x) );
tbody.appendChild(rowData);
}
Full disclaimer, I have not fully tested this code for syntax errors, but it works in theory.

How to create HTML element for JavaScript and not for HTML

I have this simplified code:
const chancesData = ["facebook","twitter","google"];
let inputsArr = [];
const inputsArrFill = chancesData.map((cur, index) => {
const input = (document.createElement("input").value =
chancesData[index]);
inputsArr.push(input); //I want the pushed value to be something like this "<input value"facebook">"
return inputsArr;
//so the returned array (should) be something like this:
//["<input value"facebook">","<input value"twitter">","<input value"google">"]
});
console.dir(inputsArrFill);
as you can see if you opened this coed in your console, the returned array looks like this:
['facebook', 'twiiter', 'google']
I want it to look like this:
['<input value="facebook">','<input value="twitter">','<input value="google">']
You can use setAttribute to put the value into the HTML markup, then retrieve it with outerHTML:
const chancesData = ["facebook", "twitter", "google"];
const inputsArrFill = chancesData.map(str => {
const input = document.createElement("input");
input.setAttribute('value', str);
return input.outerHTML;
});
console.dir(inputsArrFill);
But it'd be easier to use ordinary string concatenation:
const chancesData = ["facebook", "twitter", "google"];
const inputsArrFill = chancesData.map(str => `<input value="${str}">`);
console.dir(inputsArrFill);
The result of an assignment expression, is the assigned value. With
const input = (document.createElement("input").value =
chancesData[index]);
you did not store a reference to the created HTML element into your variable, you stored the assigned value, chancesData[index].
You need to do these two things in separate steps.
const chancesData = ["facebook","twitter","google"];
let inputsArr = [];
const inputsArrFill = chancesData.map((cur, index) => {
const input = document.createElement("input");
input.value = chancesData[index];
inputsArr.push(input); //I want the pushed value to be something like this "<input value"facebook">"
return inputsArr;
//so the returned array (should) be something like this:
//["<input value"facebook">","<input value"twitter">","<input value"google">"]
});
console.dir(inputsArrFill);
But if you really want <input value="facebook"> as a result, then you will probably have to push that in string form to begin with. You have little control over how an HTML element object gets displayed by the console.
Please refer below code.
(function createHTMlString() {
const chancesData = ["facebook", "twitter", "google"];
var outputObj = []
for (var i = 0; i < chancesData.length; i++) {
var inputTag = document.createElement("INPUT");
inputTag.setAttribute("value", chancesData[i]);
outputObj.push(inputTag);
}
console.log(outputObj)
})();

Returning an entire item in an arrray containing a specific value

I'm trying to get an item in array which contains a specific value.
Let's say I have an array
var arr = ["boat.gif", "goat.png", "moat.jpg"];
And I have a variable var imageName = "boat"
Since I do not know the file extension of imageName, I need a way to run it through my array and get "boat.gif" as the output.
I tried this with regular expressions
let filesString = arr.join(" ");
let regExName = new RegExp(imageName, "i");
let fileName = regExName.exec(filesĀ­String),
file = fileName.input.substĀ­r(fileName.index, 5);
It works but I'm hoping there's a better way
I hope this makes sense
Might be easier to filter by .includes or .startsWith instead:
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const found = arr.find(str => str.includes(imageName));
console.log(found);
or
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const found = arr.find(str => str.startsWith(imageName));
console.log(found);
If there might be other files in the directory which start with the same word (like boats.gif), then construct a regular expression like you're doing, but lookahead for a .:
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const pattern = new RegExp(imageName + '(?=\.)');
const found = arr.find(str => pattern.test(str));
console.log(found);

Categories

Resources