How do I save code using loops while accessing json data? - javascript

I recently started my first programming project.
I started noticing that I use the same code over and over again, and would like to save that.
Here is an example:
document.getElementById('Serie1').textContent = showtrend.tv_results[0].title ;
document.getElementById('Serie1ID').textContent = "https://www.imdb.com/title/"+showtrend.tv_results[0].imdb_id ;
document.getElementById('Serie1Year').textContent = showtrend.tv_results[0].year ;
document.getElementById('Serie2').textContent = showtrend.tv_results[1].title ;
document.getElementById('Serie2ID').textContent = "https://www.imdb.com/title/"+showtrend.tv_results[1].imdb_id ;
document.getElementById('Serie2Year').textContent = showtrend.tv_results[1].year ;
I am basically adding the values I get in form of a json from my api to my site.
But how can I put all of this in a loop? It is like that for another 10 series, ant isn't very elegant
Would really appreciate the help

I think this might help you.
for (let i = 1; i < showtrend.tv_results.length; i++) {
var name = 'Serie'+ i;
document.getElementById(name).textContent = showtrend.tv_results[i-1].title ;
document.getElementById(name+'ID').textContent = "https://www.imdb.com/title/"+showtrend.tv_results[i-1].imdb_id ;
document.getElementById(name+'Year').textContent = showtrend.tv_results[i-1].year ;
}

How I would do:
ECMAScript
const BASE_URL = "https://www.imdb.com/title/";
showtrend.tv_results.forEach(function (result, i) {
let count = i + 1;
document.getElementById(`Serie${count}`).textContent = result.title;
document.getElementById(`Serie${count}ID`).textContent = BASE_URL + result.imdb_id;
document.getElementById(`Serie${count}Year`).textContent = result.year;
});
Vanilla JS
const BASE_URL = "https://www.imdb.com/title/";
for(var i = 1; i <= showtrend.tv_results.length; i++) {
document.getElementById('Serie' + i).textContent = result.title;
document.getElementById('Serie' + i + 'ID').textContent = BASE_URL + result.imdb_id;
document.getElementById('Serie' + i + 'Year').textContent = result.year;
});
In addition, maybe as your next challenge, try to get rid of these hard-coded elements in the list of "series" and make it dynamically created by pushing elements to an array in Javascript and populating a table or a list reading from this array. This will keep your code even more elegant.
Good luck with your studies!

Instead of having predefined elements in your page that you have to fill, have one container element, and then iterate over the tv_results array and compile the information from each object into divs, or a table, and then insert that HTML as the innerHTML of the container.
This method will allow you to have as many movies in the data as you need.
const json = '{"showtrend": {"tv_results": [{ "title": "Batman", "imdb_id": 1 },{ "title": "Ratman", "imdb_id": 2 }]}}';
const data = JSON.parse(json);
// Pass in the parsed data
function getHTML(data) {
// `map` over the tv_results array
return data.showtrend.tv_results.map(obj => {
// For each object in the iteration return a string of HTML.
// This method uses a template literal, and adds
// a data attribute to the outer div to identify the movie.
return (
`<div data-id="${obj.imdb_id}" class="movie">
<div>${obj.title}</div>
<div>${obj.imdb_id}</div>
</div>`
);
// Finally join the array that `map` returns
// and return that string
}).join('');
}
// Cache the container element
const container = document.querySelector('#container');
// Call `getHTML` and add the returned HTML string
// to the `innerHTML` of the container
container.innerHTML = getHTML(data);
.movie { margin-bottom: 0.5em; background-color: #efefef; padding: 0.2em; }
<div id="container"></div>
Additional documentation
querySelector
Template/string literals
map
join
Data attributes

Related

page doesn't display anything

so I wrote a script to display 5 random arrays, but the page doesn't display anything.
here's the code:
<html>
<head>
<script>
function start(){
var arr(5),result;
result=document.getElementById("arraying");
result="<p>";
for(var i=0; i<5;i++){
arr[i]=Math.floor(Math.random()*10);
result+="arr["+i+"]= "+arr[i]+"</p><p>";
}
result+="</p>";
}
window.addEventListener("load",start,false);
</script>
</head>
<body>
<div id="arraying"></div>
</body>
</html>
I tried removing result=document.getElementById and write document.getElementById.innerHTML=result in the end of the function but didn't work. what's the error?
You cannot use the same variable for different purposes at the same time. First you assign a DOM element to result, and immediately on the next line you overwrite result with a string.
Build a string htmlStr inside your loop, and when that is done, assign this string to result.innerHTML property:
function start() {
let arr = [],
result, htmlStr = '';
result = document.getElementById("arraying");
htmlStr += "<p>";
for (let i = 0; i < 5; i++) {
arr[i] = Math.floor(Math.random() * 10);
htmlStr += "arr[" + i + "]= " + arr[i] + "</p><p>";
}
htmlStr += "</p>";
result.innerHTML = htmlStr;
}
window.addEventListener("load", start, false);
<div id="arraying"></div>
Looking at the code you seem to be missing some basic javascript concepts.
array size
This is probably your main issue:
var arr(5)
This does not make sense in javascript. Array length does not need to be predefined since all arrays are of dynamic length. Simply define an array like this:
var arr = []
Then later when you want to append new elements use push like this:
arr.push( Math.floor(Math.random()*10) )
adding html using innerHTML
There are different ways to dynamically inject html into your page. (It looks like) you tried to append the html as a string to the parent element. This is not possible.
You said you tried using innerHTML. That should work if used correctly.
A working implementation would work like this:
function start() {
var arr = []
var result = "<p>"
for(var i = 0; i < 5; i++) {
arr.push( Math.floor(Math.random()*10) ) // Btw this array isn't actually needed.
result += "arr[" + i + "] = " + arr[i] + "</p><p>"
}
document.getElementById("arraying").innerHTML = result
}
window.addEventListener("load", start, {passive: true});
adding html using createElement
A generally better way of dynamically adding html elements is via createElement.
This way you dont have to write html and are therefore less prone for making errors. It is also more performant and easier to integrate into javascript.
I think the best explaination is a commented implementation:
function start() {
var myDiv = document.getElementById("arraying") // get parent node
var arr = []
for(var i = 0; i < 5; i++) {
arr.push( Math.floor(Math.random()*10) )
var p = document.createElement("p") // create p element
p.innerText = "arr[" + i + "] = " + arr[i] // add text content to p element
myDiv.append(p) // append p element to parent element
}
}
window.addEventListener("load", start, {passive: true});
small tips
The let keyword works mostly the same as the var keyword, but is generally preferred because of some edge cases in which let is superior.
Fusing strings and variables using the plus operator is generally considered bad practice. A better way to do the string concatenation would have been
result += `arr[${i}] = ${arr[i]}</p><p>`

JavaScript loop through JSON data and print in html

I'm new to JavaScript and I'm trying to figure out how-to loop through JSON and print each selected value in HTML. My solution below does everything I want except print "all" rows of the JSON data. It only prints the last one. I've been researching on StackOverflow and elsewhere, but I'm not finding the solution. Sorry if this is a redundant question and thank you for your help!
//Fetch JSON from URL
//https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
fetch('https://s.codetasty.com/toddbenrud/sandBoxToddBenrud/example/songData.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
var songData = (JSON.stringify(myJson));
//https://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript
var index;
var obj = JSON.parse(songData);
for (index = 0; index < obj.length; ++index) {
var student_name = obj[index]['name'];
var student_email = obj[index]['email'];
var song_name = obj[index]['song'];
var song_url = obj[index]['url'];
document.getElementById("studentName").innerHTML = '<br>'+student_name;
document.getElementById("studentEmail").innerHTML = '<br>'+student_email;
document.getElementById("songTitle").innerHTML = '<br>'+song_name;
document.getElementById("songURL").innerHTML = '<br>'+song_url;
}
});
Inside your for loop you are reassigning your elements' content in every Iteration. It means that you fill your elements with the First item of the Array on the First time you run the for, but the Second time you run It, you replace the elements' content with the Second item of the Array. So you get only the Last Item Data.
To solve this problema, you should "increment" your element's content on each Iteration, instead of replace it. To achieve that, you replace the Lines like
document.getElementById("studentName").innerHTML = '<br>'+student_name;
With
document.getElementById("studentName").innerHTML += '<br>'+student_name;
The += operator does a concatenation on strings
Becasue you set string for elements, don't add string.
Replace from:
document.getElementById("studentName").innerHTML = '<br>'+student_name;
document.getElementById("studentEmail").innerHTML = '<br>'+student_email;
document.getElementById("songTitle").innerHTML = '<br>'+song_name;
document.getElementById("songURL").innerHTML = '<br>'+song_url;
To:
document.getElementById("studentName").innerHTML += '<br>'+student_name;
document.getElementById("studentEmail").innerHTML += '<br>'+student_email;
document.getElementById("songTitle").innerHTML += '<br>'+song_name;
document.getElementById("songURL").innerHTML += '<br>'+song_url;

Shorten repetitive/multiple properties using Javascript

I am trying to disseminate the values over a repetitive property to set the contents of certain nodes. The way I'm doing it is effective. However, as I've mentioned, it's repetitive and kind of frustrating to look at. Is there any other way to shorten my codes?
for (var i = 0; i < 1; i++) {
var title = document.querySelector("h1.title"),
date = document.querySelector(".article-date"),
tme = document.querySelector(".article-tme"),
src = document.querySelector(".source"),
user = document.querySelector(".user"),
tip = document.querySelector(".tip");
//.....some other variables...
title.innerHTML = post[i].titles;
date.innerHTML = post[i].dates;
src.innerHTML = post[i].sources;
tme.innerHTML = post[i].times;
user.innerHTML = post[i].authors;
tip.innerHTML = post[i].excerpts;
//....some other HTML content setting...
}
...where "post" = JSON.parse(this.response);
Any kind of help to shorten this burden is appreciated. Thank you.
I'd use an object that maps the property names to selectors:
const selectorsByProp = {
titles: 'h1.title',
dates: '.article-date',
sources: '.source',
// ...
}
Object.entries(selectorsByProp).forEach(([prop, selector]) => {
document.querySelector(selector).innerHTML = post[i][prop];
});
Note that if the object values happen to contain plain text only, it would make a lot more sense to assign to the textContent of the element, rather than the innerHTML:
document.querySelector(selector).textContent = post[i][prop];
There's no need for the loop either, since you're just doing this once.

Why does my for loop return only one result

The value of the search is supposed to append to the nyt api and the for loop is supposed to list all the links. I'm only getting one result for some reason but when looked through console I see that there 100s of links.
function myFunction(){
var citySearch = $("#city").val();
var NYTurl = "https://api.nytimes.com/svc/search/v2/articlesearch.json?q=" + citySearch +
"$sort=newest&api-key=xxxxxxxxxxxxxxxxxxxxxxxx"
jQuery.getJSON(NYTurl, function (data){
var headlines = $("#headlines")
var contentUrl = data.response.docs
for(var i = 0; i < contentUrl.length; i++ ){
contentUrlLoop = contentUrl[i];
headlines.html('Link' );
}
console.log(data)
})
return false;
}
headlines.html( assigns the passed HTML string to headlines's inner HTML. So, on each iteration, you're overwriting whatever headlines had previously. Use append instead if you want to insert an <a> for every item in the response:
headlines.append('Link' );
Or, rather than making hundreds of DOM changes, you might consider coming up with a single HTML string and then appending it:
jQuery.getJSON(NYTurl, function(data) {
var headlines = $("#headlines");
var contentUrl = data.response.docs;
var htmlStr = contentUrl.reduce(
(a, { web_url }) => a + 'Link',
''
);
headlines.html('Link');
});
(perhaps enclose them in divs as well so that each link is on a new line, or make the as block, so that the HTML is readable)

Pushing object to array results in same value

I have the following javascript code that does not work as I would expect it to. I have a list of checkboxes of which two of the items are "TestDuration" and "AssessmentScores". I'm trying to iterate through the list (which works fine) and have it add the values that are checked to the array.
var SAIndex = 0;
var SSIndex = 0;
var ScoresIndex = 0;
var SubAssessments = [];
var SubAssessmentScores = [];
//Get to the container element
var SSList = document.getElementById("islSubAssessmentScore_container");
//turn it into an array of the checkbox inputs
SSList = SSList.getElementsByTagName("input");
//create a temporary object to store my values
var tempPair = new Object();
//iterate through the checkbox lists
for(var i = 1; i < SSList.length;i++)
{
//if the value is checked add it to the array
if (SSList[i].checked)
{
var P = SubAssessments[SAIndex];
var V = SSList[i].value;
//tempPair.Parent = SubAssessments[SAIndex];
tempPair.Parent = P;
//tempPair.Value = SSList[i].value;
tempPair.Value = V;
//show me the values as they exist on the page
alert(tempPair.Parent + "|" + tempPair.Value);
SubAssessmentScores.push(tempPair);
//show me the values I just added to the array
alert(SubAssessmentScores.length-1 + "|" + SubAssessmentScores[SubAssessmentScores.length-1].Parent + "|" + SubAssessmentScores[SubAssessmentScores.length-1].Value);
//uncheck the values so when I refresh that section of the page the list is empty
SSList[i].checked = false;
}
}
//output the list of objects I just created
for (i = 0;i < SubAssessmentScores.length;i++)
alert(i + "|" + SubAssessmentScores[i].Parent + "|" + SubAssessmentScores[i].Value)
Now what happens is that when I iterate through the list I get the following alerts:
-first pass-
StudentID|TestDuration
0|StudentID|TestDuration
-second pass-
StudentID|AssessmentScores
1|StudentID|AssessmentScores
This is what I expect to output... However at the end of the code snippet when it runs the for loops to spit out all the values I get the following alerts...
0|StudentID|AssessmentScores
1|StudentID|AssessmentScores
I can't for the life of me figure out why it's replacing the first value with the second value. I thought it might be using a reference variable which is why I added in the P and V variables to try to get around that if that was the case, but the results are the same.
This is because you are adding the same variable every iteration of the loop.
Try changing your push like this:
SubAssessmentScores.push({
Parent: P,
Value: V
});
That said, I recommend you study a little more javascript and conventions in the language, for example your variable naming is frowned upon because you should only use capital letters on the beginning of a name for constructor functions.
A good book is Javascript the good parts by Douglas Crockford.

Categories