alt attribute keeps getting assigned to last index of nested javascript object - javascript

So I have a series of various JSON objects representing a college class with nested data inside each of them. Each of these objects are stored in an array called classes. Here is an example of how one of the class objects is formatted:
let class_A = {
professor: "Joey Smith",
numberStudents: 25,
courseCode: "COMS 2360",
seating: {
"FirstRow": {
0: {
firstName: "Sarah",
collegeMajor: "English",
},
1: {
firstName: "Bob",
collegeMajor: "Computer Engineering",
},
2: {
firstName: "Dylan",
collegeMajor: "Mathematics",
}
},
"SecondRow": {
3: {
firstName: "Molly",
collegeMajor: "Music"
}
}
}
};
Basically, I have a page with all students across all class objects laid out on a page with an add button next to each name, and the add button will eventually allow me to add students to certain groups for assignments, etc.
The page right now with only class_A would looks something like this:
I displayed the student names and the add button next to each student using code like this:
function loadStudents(){
let page = document.getElementById('page');
page.innerHTML = "";
for(seatRow in class.seating){
for(index in class.seating[seatRow]){
let studentName = class.seating[seatRow][index].studentName;
page.innerHTML += "<p> Name:" + studentName + " <img src='addButImg.png' id = 'addButton' onclick = 'addStudentToGroup()'></p>";
let addButton = document.getElementById("addButton");
addButton.alt = studentName;
console.log(addButton.alt);
}
}
}
function addStudentToGroup(){
let addButton = document.getElementById("addButton");
console.log(addButton.alt);
}
My page displays correctly like the picture, but I'm having trouble printing the name of the specific student I add to a group when I click on the add button next to the student's name. I assign the add button's alt value to the student's name, and tested it by doing "console.log(addButton.alt)" which prints:
Sarah
Bob
Dylan
Molly
If I click on the first add button, it should trigger the addStudentToGroup() function and print "Sarah" to the console. However, clicking on all the buttons seems to only print the last name in the list of students which is "Molly" regardless of whichever student the button is located next to. The alt seems to get saved as whatever the last student is, and I'm struggling to change the alt value based on whatever student's name I choose to click add for. Does anyone know how to fix this? Any help would be appreciated!

You are assigning the same id addButton to all images.
If you just want studentName then just pass it in onclick function.
like using template literal addStudentToGroup('${studentName}')
let class_A = {professor:"Joey Smith",numberStudents:25,courseCode:"COMS 2360",seating:{"FirstRow":{0:{firstName:"Sarah",collegeMajor:"English",},1:{firstName:"Bob",collegeMajor:"Computer Engineering",},2:{firstName:"Dylan",collegeMajor:"Mathematics",}},"SecondRow":{3:{firstName:"Molly",collegeMajor:"Music"}}}};
loadStudents();
function loadStudents(){
let page = document.getElementById('page');
page.innerHTML = "";
for(seatRow in class_A.seating){
for(index in class_A.seating[seatRow]){
//console.log(class_A.seating[seatRow][index]);
let studentName = class_A.seating[seatRow][index].firstName;
page.innerHTML += `<p> Name: ${studentName} <img src="addButImg.png" onclick = "addStudentToGroup('${studentName}')"></p>`;
//let addButton = document.getElementById("addButton");
//addButton.alt = studentName;
// console.log(addButton.alt);
}
}
}
function addStudentToGroup(sname){
console.log(sname);
}
<div id="page">
</div>

The problem is that all of the buttons have the same id "addButton", so when you try to get the button in addStudentToGroup it retrieves the last item with matching id.
Try sending a reference to the button as argument to addStudentToGroup:
onclick = 'addStudentToGroup(this)'
Try the following:
let classes = [class_A, class_B, class_C, class_D];
let classesAvailable = document.getElementById('classes');
let class = classes[classesAvailable.value];
function loadStudents(){
let page = document.getElementById('page');
page.innerHTML = "";
for(seatRow in class.seating){
for(index in class.seating[seatRow]){
let studentName = class.seating[seatRow][index].studentName;
page.innerHTML += "<p> Name:" + studentName + " <img src='addButImg.png' id = 'addButton' onclick = 'addStudentToGroup(this)'></p>";
let addButton = document.getElementById("addButton");
addButton.alt = studentName;
console.log(addButton.alt);
}
}
}
function addStudentToGroup(buttonEl){
console.log(buttonEl.alt);
}

Related

Use a user input value instead of a parameter

I have this function which works perfectly while I enter parameters, but it's not what I need, so given the code below, how can I use a user input value instead of the parameter to search through the array and return the objects?
Please keep it as simple as possible,I'm new to javaScript.
Please include input and button as html fields as well.
carSelection = [{
manufacturer: "Fiat Automobiles S.p.A.",
type: "Fiat 500",
fuel: "Eurosuper 98",
condition: "New",
enginePower: "101kW"
},
{
manufacturer: "Kia Motors Corporation (KMC)",
type: "Kia Sportage",
fuel: "Euro Diesel",
condition: "Used",
enginePower: "185kW"
},
{
manufacturer: "BMW AG",
type: "BMW X5",
fuel: "Euro Diesel",
condition: "Used",
enginePower: "195kW"
},
{
manufacturer: "Toyota Motor Corporation ",
type: "Toyota Corolla",
fuel: "Eurosuper 95",
condition: "Used",
enginePower: "165kW"
}
];
var bmw = 'BMW X5';
// var n1 = bmw.indexOf("bmw", 0);
var toyota = 'Toyota Corolla';
var fiat = 'Fiat 500';
var kia = 'Kia Sportage';
var input = document.getElementById("input").value;
function findCar(arr, searchProp) {
var rezArr = [];
for (var i = 0; i < arr.length; i++) {
Object.keys(arr[i]).forEach(function(prop) {
if (arr[i][prop] === searchProp) {
rezArr.push(arr[i]);
}
})
}
return rezArr;
}
var item2 = findCar(carSelection, bmw);
console.log(item2);
<input id="input" type="text"/>
Your input html looks fine to me. You should add a button which would look something like <button id="button">.
Now, You'll want to add a click event listener to the button. This is basically a function that will be called whenever the button is clicked. There's a couple ways of adding the event listener but I think the best is
const button = document.getElementById('button'); //get a reference to the button element
button.addEventListener('click', handleClick) // specify a function that should be called whenever the button is clicked
function handleClick(){
var input = document.getElementById("input").value;//get the current value of the input
findCar(carSelection, input) //find the car
}
So whenever the button is clicked, we'll go get the current value of input and pass that to the function you've already written.
The reason your current code won't work is that you grab the value of input as soon as the script loads when, more than likely, the user hasn't had time to type anything into it yet. So it will always be an empty string ("").

Meteor how to pass the data of an array in another array

I am trying to make a form where you have a list with the names of your friends to invite them every name with a checkbox i already get the data and insert the data in a collection as an array but now i added a filter to the friends list and when i check the checkbox --> change the filter --> other name appears --> change the filter so the first name comes again but it isnt checked anymore so the data is lost
Thats the point why i created a event where the last names of this filter input is stored and when you change the filter and select some friends i want to combine the first and the second array to insert it in the collection.
This is it so far:
Template.NeuesEvent.events({
"click .RadioButtonOnClick": function(event){
var Zwischensumme = [];
$.each($('.FreundeCheckbox:checked'), function(){
Zwischensumme.push($(this).val());
});
console.log(Zwischensumme);
Session.set("Zwischensumme", Zwischensumme);
}
});
and here is the other event with the insert and the array I want all of the data go is "eingeladene":
Template.NeuesEvent.events({
"submit .add-event": function(event){
var Name = event.target.name.value;
var Beschreibung = event.target.beschreibung.value;
var Datum = event.target.Datum.value;
var Autor = Meteor.userId();
var Einladender = Meteor.user().username;
var eingeladene = [-----Here the Data have to go-------- ];
if (Name == "")
{
confirm("Das Event braucht einen Namen ;)")
}
else
{
Meteor.call('addEvent', Name, Beschreibung, Datum, eingeladene, Autor, Einladender)
event.target.name.value = "";
event.target.beschreibung.value = "";
FlowRouter.go('/meineEvents');
return false;
}
}
});

Storing value from text field in object, Javascript

I want to update my object with values from text fields.
I think the problem is with the click eventhandler on the button but not sure. I've tried a few things, Your help would be amazing.
HTML
<form>
<label><p>Book Name: </p></label>
<input name="booktitle" id="booktitle" type="text" value="I'm a value">
<label><p>Total Pages: </p></label>
<input type="text">
<label><p>Current Page: </p></label>
<input type="text">
<button id="my-Btn" type="button">Add to List</button>
</form>
JS
(function() {
// Create book object
var book = {
name: 'JavaScript & jQuery',
totalPages: 622,
pages: 162,
pagesLeft: function() {
var total = this.totalPages - this.pages;
return total;
},
percentageLeft: function() {
var totalPercentage = this.pagesLeft() / this.totalPages * 100
return Math.round(totalPercentage);
}
};
// write out book name and pages info
var bookName, totalPages, pagesLeft, percentageLeft; //declares variables
bookName = document.getElementById('bookName'); // gets elements from document
totalPages = document.getElementById('totalPages');
pagesLeft = document.getElementById('pagesLeft');
percentageLeft = document.getElementById('percentageLeft');
bookName.textContent = book.name; // write to document
totalPages.textContent = 'Total Pages: ' + book.totalPages;
pagesLeft.textContent = book.pagesLeft();
percentageLeft.textContent = book.percentageLeft() + '%';
// pull value from text field and set to object
document.getElementById("my-Btn").addEventListener("click", function() {
book.name = document.getElementById('booktitle').value;
});
}());
Code Pen of what I have so far.
http://codepen.io/Middi/pen/pRGOVW
Thanks in advance.
Your code already updates an object's property (book.name) with a value from a text field (#booktitle). You can see this by adding alert(book.name); after the line
book.name = document.getElementById('booktitle').value;
As Jazcash noted, if you wanted to display the updated book name everytime it was changed, you'd need to add
bookName.textContent = book.name;
In your eventlistener, so it'd look something like this:
document.getElementById("my-Btn").addEventListener("click", function() {
book.name = document.getElementById('booktitle').value;
bookName.textContent = book.name;
});
The problem is you're setting your divs textContent based on book here: bookName.textContent = book.name;. But then you need to do it again in your event like so:
book.name = bookName.value;
bookName.textContent = book.name;
You'll need to do this for all your fields

JavaScript - Adding an object to the end of an array through a input field

I am trying to dynamically add an object with values from an input field to the end of an array using JavaScript. The only catch is that I'm trying to do it with an input field. Here's what I want to happen:
The user types in something in a text field
My program already adds a unique ID for it
Add it to the end of an array in the form of a object
Keep on adding objects to that array
This is what I want in my JSON file:
{
"list": [{
"id": 0,
"description": "Task #1 Description"
}, {
"id": 1,
"description": "Task #2 Description"
}, {
"id": 3,
"description": "Task #3 Description"
}]
}
What I am currently getting is:
{
"list": [{
"id": 0,
"description": "Task #1 Description"
}, ]
}
Every time I add a new Task, it replaces the one that is already there.
Here is my JavaScript code:
// This is the counter
var indentification = 0;
// This is the submit button
var submit = document.getElementById("submit");
// This is the text field
var content = document.getElementById("text");
submit.onclick = function() {
id = indentification++;
description = content.value;
var task = {
list: []
}
task.list.push({id, description});
var jsonifyTask = JSON.stringify(task);
fs.writeFile("tasks.json", jsonifyTask, "utf8");
}
I would really appreciate it if anyone could help me out. I've spent hours trying to figure it out. Thanks!
The problem is here:
var task = {
list: []
}
task.list.push({id, description});
Each time you do this your list become empty then add new item.
change to this
// This is the counter
var indentification = 0;
// This is the submit button
var submit = document.getElementById("submit");
// This is the text field
var content = document.getElementById("text");
var task = {
list: []
}
submit.onclick = function() {
id = indentification++;
description = content.value;
task.list.push({id, description});
var jsonifyTask = JSON.stringify(task);
fs.writeFile("tasks.json", jsonifyTask, "utf8"); // what're you doing here, browser do not allow write file to disk
}
There are a couple of things that you need to consider here:
Form submit must be refreshing the page and resetting your global variables. Thus you need to prevent default action on click of submit.
(as mentioned in earlier answers) The list is being initiated on every click. You will need to initialize the variable task outside the onClick function
// This is the counter
var indentification = 0;
// This is the submit button
var submit = document.getElementById("submit");
// This is the text field
var content = document.getElementById("text");
//initialize outside the on click function
var task = {
list: []
}
submit.onclick = function(e) {
//This prevents page refresh on form submission and preserves the global variable states
e.preventDefault();
id = indentification++;
description = content.value;
task.list.push({id, description});
var jsonifyTask = JSON.stringify(task);
fs.writeFile("tasks.json", jsonifyTask, "utf8");
}
This should hopefully solve your problem.
// This is the counter
var indentification = 0;
// This is the submit button
var submit = document.getElementById("submit");
// This is the text field
var content = document.getElementById("text");
submit.addEventHandler("click", function() {
id = indentification++;
description = content.value;
task.list.push({id, description});
var jsonifyTask = JSON.stringify(task);
fs.writeFile("tasks.json", jsonifyTask, "utf8");
}

Remove node function on parent element

I'm new to JS. I'm trying to delete the parent node with all the children by clicking a button. But the console tells me that undefined is not a function. What am I missing?
Fiddle:
http://jsfiddle.net/vy0d8bqt/
HTML:
<button type="button" id="output">Get contacts</button>
<button type="button" id="clear_contacts">clear contact</button>
<div id="output_here"></div>
JS:
// contact book, getting data from JSON and outputting via a button
// define a JSON structure
var contacts = {
"friends" :
[
{
"name" : "name1",
"surname" : "surname1"
},
{
"name" : "name2",
"surname" : "surname2"
}
]
};
//get button ID and id of div where content will be shown
var get_contacts_btn = document.getElementById("output");
var output = document.getElementById("output_here");
var clear = document.getElementById("clear_contacts");
var i;
// get length of JSON
var contacts_length = contacts.friends.length;
get_contacts_btn.addEventListener('click', function(){
//console.log("clicked");
for(i = 0; i < contacts_length; i++){
var data = contacts.friends[i];
var name = data.name;
var surname = data.surname;
output.style.display = 'block';
output.innerHTML += "<p> name: " + name + "| surname: " + surname + "</p>";
}
});
//get Children of output div to remove them on clear button
//get output to clear
output_to_clear = document.getElementById("output_here");
clear.addEventListener('click', function(){
output_to_clear.removeNode(true);
});
You should use remove() instead of removeNode()
http://jsfiddle.net/vy0d8bqt/1/
However, this also removes the output_to_clear node itself. You can use output_to_clear.innerHTML = '' if you like to just delete all content of the node, but not removing the node itself (so you can click 'get contacts' button again after clearing it)
http://jsfiddle.net/vy0d8bqt/3/
You want this for broad support:
output_to_clear.parentNode.removeChild(output_to_clear);
Or this in modern browsers only:
output_to_clear.remove();
But either way, make sure you don't try to remove it after it has already been removed. Since you're caching the reference, that could be an issue, so this may be safer:
if (output_to_clear.parentNode != null) {
output_to_clear.remove();
}
If you were hoping to empty its content, then do this:
while (output_to_clear.firstChild) {
output_to_clear.removeChild(output_to_clear.firstChild);
}
I think using jQuery's $.remove() is probably the best choice here. If you can't or don't want to use jQuery, The Mozilla docs for Node provides a function to remove all child nodes.
Element.prototype.removeAll = function () {
while (this.firstChild) { this.removeChild(this.firstChild); }
return this;
};
Which you would use like:
output_to_clear.removeAll();
For a one-off given the example provided:
while (output_to_clear.firstChild) { output_to_clear.removeChild(output_to_clear.firstChild); }

Categories

Resources