I have a simple program that stores student objects in an array and then print the students info to the webpage. I have a print method in my program which takes a parameter and access the div element and then sets elements inner html to the parameter passed to print the message. Please consider the code snippet to see where the document.write method working fine but not the print method.
var student;
var message = "";
var students =
[
{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print( msg )
{
var output = document.getElementById("output");
output.innerHTML = msg;
}
for( var i = 0; i < students.length; i++)
{
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
// print(message);
document.write(message);
}
<div id="output">
</div>
It's because your print method replaces the entire output div. So each iteration of the loop overwrites the previous ones output.
You can change:
output.innerHTML = msg;
to:
output.innerHTML += msg;
and it will work correctly.
It works just fine you just need to respect the text currently in the div.
I added a += to the innerHtml call to append the new text
var student;
var message = "";
var students =
[
{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print( msg )
{
var output = document.getElementById("output");
output.innerHTML += msg;
}
for( var i = 0; i < students.length; i++)
{
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
print(message);
// document.write(message);
}
<div id="output">
</div>
In this case, your print method is substituting the innerHTML of output each time you call it.
Therefore, if you call print inside a loop, the only displayed result will be the last item on the loop.
If you add a + to the method, you will get what you want. You will need a method to clear the div later on, though.
var student;
var message = "";
var students = [{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print(msg) {
var output = document.getElementById("output");
output.innerHTML += msg;
}
for (var i = 0; i < students.length; i++) {
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
print(message);
}
<div id="output">
</div>
Related
I am new to Html. This is my first html javascript program and I have an issue with it.
A user puts his/her gpa CS102 A 3, Math101 B 3. Then, I put the data into an Array. The problem is when I create the table. I want to create a table like
THL100 B+ 3
PHL107 A 3
ENG120 C+ 3
MTH245 A 4
CSC221 A 3
What kind of loop I should use? I tried to use a for loop but it just doesn't work.
Here is my code:
function load(){
var data = [];
while(true) {
line = prompt("Enter course name, grade, and credit hours or click OK with no data to terminate");
if(line == null || line == "") {
break;
}
var values = line.split(/\s/);
var citem = values[0];
data.push(citem);
var gpa = parseFloat(values[1]);
var cgpa = [gpa];
data.push(cgpa);
var unit = values[2];
var cunit = [unit];
data.push(cunit);
}
return data;
}
function display(data) {
var table=document.getElementById('result');
table.innerHTML= "<tr><th> COURSE </th><th> GRADE </th><th> HOURS </th></tr>";
for(var i in data){
table.innerHTML +="<tr><td>" + data[i] + "</td><td>" + data[i]+1 + "</td><td>" + data[i]+2 + "</td></tr>";
}
}
data = load();
display(data);
<table id="result" border="1px" class="classy">
</table>
<span id="text"></span>
the problem is with accessing data not the loop, store each line as one element in the array, like object will be easy:
function load(){
var data = [];
while(true) {
line = prompt("Enter course name, grade, and credit hours or click OK with no data to terminate");
if(line == null || line == "") {
break;
}
var values = line.split(/\s/);
var line = {
COURSE: values[0],
GRADE: parseFloat(values[1]),
HOURS: values[2]
};
data.push(line); // now your array is [{COURSE: value, GRADE: value, HOURS: value}, {}, ...]
}
return data;
}
function display(data) {
var table=document.getElementById('result');
table.innerHTML= "<tr><th> COURSE </th><th> GRADE </th><th> HOURS </th> </tr>";
for(var i in data){
table.innerHTML +="<tr><td>" + data[i]["COURSE"] + "</td><td>" + data[i]["GRADE"] + "</td> <td>" + data[i]["HOURS"] + "</td></tr>";
}
}
UPDATE: yes the data is accessible inside the loop but for any variable
function display(data) {
var table = document.getElementById('result');
table.innerHTML = "<tr><th> COURSE </th><th> GRADE </th><th> HOURS </th> </tr>";
let totalgp = 0; // if the total is for all courses define it here
for (var i in data) {
let totalgp = 0; // if total grade for each course separately define it inside the loop
if (data[i]["GRADE"] == "A") {
var gp = 4 * data[i]["HOURS"];
totalgp = totalgp + gp;
}
table.innerHTML += "<tr><td>" + data[i]["COURSE"] + "</td><td>" + data[i]["GRADE"] + "</td> <td>" + data[i]["HOURS"] + "</td></tr>";
}
}
The data should be stored in a 2-dimensional array to easily access the elements. The usage of for loop is right.
To append the first row -
table.innerHTML +="<tr><td>" + data[0][0] + "</td><td>" + data[0][1] + "</td> <td>" + data[0][2] + "</td></tr>";
similarly for 2nd row,
table.innerHTML +="<tr><td>" + data[1][0] + "</td><td>" + data[1][1] + "</td> <td>" + data[1][2] + "</td></tr>";
Currently, I am trying to draw a table using jQuery but its not working. This is the current js code. I tried using append but it didnt work for the table. Can someone help me on this. Thank you.
(function(){
var location = new Array();
var query = '%23CM0655';
var url = "search.php";
$.post(url, {query:query}, function(tweets){
console.log(tweets);
$("#tweetResult").html("");
var geoEnabled = false;
var placeName = "";
var countryName = "";
for(var i=0; i<tweets.statuses.length; i++){
var img = $("<img src='" + tweets.statuses[i].user.profile_image_url + "' class='tweetpic'/>");
$("#tweetResult").append(img);
$("#tweetResult").append('<br/>');
$("#tweetResult").append(tweets.statuses[i].user.screen_name);
$("#tweetResult").append(tweets.statuses[i].text + "<br/>");
geoEnabled = tweets.statuses[i].user.geo_enabled;
if(geoEnabled){
placeName = tweets.statuses[i].place.name;
countryName = tweets.statuses[i].place.country;
if(placeName != null){
$("#tweetResult").append(placeName + ", ");
$("#tweetResult").append(countryName + "<br/>");
}
$("#tweetResult").append("Location: " + tweets.statuses[i].place.bounding_box.coordinates[0][0][0] + ", ");
$("#tweetResult").append(tweets.statuses[i].place.bounding_box.coordinates[0][0][1] + "<br/>");
$("#tweetResult").append(tweets.statuses[i].created_at);
}
$("#tweetResult").append("<br/><br/>");
}
});
setTimeout(arguments.callee, 10000);
})();
Currently this is the output which i am getting after using the append method to create the table
<div id="here_table">
<table> </table> !!!!!!!!!!
<tr><td>result1</td></tr>
<tr><td>result2</td></tr>
<tr><td>result3</td></tr>
</div>
I replicated the issue with some sample data (didn't use every property). But this'll show you how it's done.
Just run the snippet below or check this fiddle out
var tweets = {
statuses: [{
place: {
name: "Oostend",
country: "Belgium"
},
user: {
profile_image_url: "https://jsfiddle.net/img/logo.png",
screen_name: "John Doe",
geo_enabled: true
},
text: "Hello world!",
created_at: "April 7th 2016"
}, {
place: {
name: "Veurne",
country: "Belgium"
},
user: {
profile_image_url: "https://jsfiddle.net/img/logo.png",
screen_name: "Jane Doe",
geo_enabled: false
},
text: "Geo is disabled for me",
created_at: "April 6th 2016"
}]
}
$("#tweetResult").html("");
var table = $("<table></table>");
var thead = $("<thead></thead>");
thead.append($("<th></th>").html("Some header"));
var tbody = $("<tbody></tbody>");
var geoEnabled = false;
var placeName = "";
var countryName = "";
for (var i = 0; i < tweets.statuses.length; i++) {
var row = $("<tr></tr>");
var img = $("<td><img src='" + tweets.statuses[i].user.profile_image_url + "' class='tweetpic'/><br/></td>");
row.append(img);
row.append($("<td></td>").html(tweets.statuses[i].user.screen_name));
row.append($("<td></td>").html(tweets.statuses[i].text + "<br/>"));
geoEnabled = tweets.statuses[i].user.geo_enabled;
if (geoEnabled) {
placeName = tweets.statuses[i].place.name;
countryName = tweets.statuses[i].place.country;
if (placeName != null) {
row.append($("<td></td>").html(placeName + ", " + countryName));
}
//row.append($("<td></td>").html("Location: " + tweets.statuses[i].place.bounding_box.coordinates[0][0][0] + ", " + tweets.statuses[i].place.bounding_box.coordinates[0][0][1] + "<br/>"));
row.append($("<td></td>").html(tweets.statuses[i].created_at));
}
tbody.append(row);
}
table.append(thead).append(tbody);
$("#tweetResult").append(table);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="tweetResult">
</div>
EDIT
I edited the code to your current situation, where as a <table></table> element is created from scratch.
I'm having trouble understanding the condition in the else if statement under the for loop in my code. I'd really appreciate it if you could help.
This is an array of objects containing student information, name, study track, achievements, points. I just need help understanding this condition: i === (students.length) -1
var students = [
{ name: 'Dave', track: 'Front End Development', achievements: 158, points: 14730 },
{ name: 'Jody', track: 'iOS Development with Swift', achievements: 175, points: 16375 },
{ name: 'Jordan', track: 'PHP Development', achievements: 55, points: 2025 },
{ name: 'Jody', track: 'Learn WordPress', achievements: 40, points: 1950 },
{ name: 'Trish', track: 'Rails Development', achievements: 5, points: 350 }
];
var htmlMessage = '';
var student;
var search;
var notFound = [];
function print(message) {
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = message;
}
function getStudentReport( student ) {
var report = '<h2>Student: ' + student.name + '</h2>';
report += '<p>Track: ' + student.track + '</p>';
report += '<p>Points: ' + student.points + '</p>';
report += '<p>Achievements: ' + student.achievements + '</p>';
return report;
}
while (true) {
search = prompt('Search student records:\ntype a name Ex: Jody\n(or type "quit" to end)');
if (search === '') {
alert('Please enter a name to initiate search.')
} else if (search === null || search.toLowerCase() === 'quit') {
print('<h2>Thanks for using our student record search services.</h2><p>These names were not found : ' +
notFound.join(', ') + '</p>');
break;
}
for (var i = 0; i < students.length; i++) {
student = students[i];
if (student.name.toLowerCase() === search.toLowerCase()) {
htmlMessage = getStudentReport(student);
print(htmlMessage);
break;
} else if (i === (students.length) -1){
print('<p>' + search + ' was not found.</p>');
notFound.push(search);
break;
}
}
}
The else if is checking for the end of the loop and considering the search failed:
//if you are at the end of the array (searched through all students)
else if (i === (students.length) -1){
//alert user that their search was not found
print('<p>' + search + ' was not found.</p>');
//push the failed search term into an array
notFound.push(search);
//break out of the loop, necessary because of the way the loop is
//written (while(true)) will go forever if not broken
break;
}
...it is -1 because an arrays first item starts at 0 while the length starts counting at 1 ;-)
So there is a difference oft -1.
I'm relatively new to JavaScript and I'm working on what should be a simple project. I'm stuck though and I'd love some opinions on ways to get a solution.
I have a short products array like:
var products = [
{
name: "paper",
price: 2.00,
description: "White College-ruled Paper, 100 sheets",
location: "Aisle 5"
},
{
name: "pens",
price: 5.00,
description: "10 Pack, Black Ink Ball Point Pens"
location: "Aisle 2"
},
{
name: "paper clips",
price: 0.50,
description: "Silver Paper Clips, 100 count"
location: "Aisle 6"
}
]
I'm looping through this array using JS and printing the results to the page in a DIV with id of "output".
function print(message) {
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = message;
}
for (var i = 0; i < products.length; i += 1) {
product = products[i];
message += '<div class="col-md-4" id="prod-block">';
message += '<p id="prod-description">' + product.name + ' ' + product.description + '</p>';
message += '<h2 id="price">$' + product.price + '</h2>';
message += '</div>'
}
print(message);
All of this works just fine. I have my products on the page. Now, what I want is when the mouse hovers over any of the item divs, to show additional information (such as location) in a separate div.
My question is - how do you identify the index number of the item that is being hovered over? As of now, the index number only exists in my for loop and I can't figure out how to access it in a different function.
Again, my knowledge is limited, so I'm not sure if writing the HTML in a for loop is even the best way to do this. I really appreciate any advice or criticism!!
Here's something that should help.
I updated your list to include an id attribute and I used that to assign a data attribute to the div that is being created. On hover it looks for the data-prodid and displays that in the additional section.
Fiddle
var products = [{
id: 0,
name: "paper",
price: 2.00,
description: "White College-ruled Paper, 100 sheets",
location: "Aisle 5"
}, {
id: 1,
name: "pens",
price: 5.00,
description: "10 Pack, Black Ink Ball Point Pens",
location: "Aisle 2"
}, {
id: 2,
name: "paper clips",
price: 0.50,
description: "Silver Paper Clips, 100 count",
location: "Aisle 6"
}],
message = '';
function print(message) {
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = message;
}
for (var i = 0; i < products.length; i += 1) {
product = products[i];
message += '<div data-prodid="' + product.id + '" class="col-md-4" id="prod-block">';
message += '<p id="prod-description">' + product.name + ' ' + product.description + '</p>';
message += '<h2 id="price">$' + product.price + '</h2>';
message += '</div>'
}
print(message);
$('.col-md-4').hover(function() {
$('#additional').html($(this).data('prodid'));
});
Also
The javascript you posted has an error in your products variable and message was never declared.
try to add a tip tool as and when you create the div with the index number you want.
<div title="The index number">
There is something really wrong in your code: the abuse of id. Many elements will have the id prod-block, prod-description but an id has to be unique.
Doing this, you can easily detect which element is hovered just by checking the id. There is multiple techniques to do that, if you want to learn jQuery this is really easy to start this way.
If you use jQuery, you could use data() to define the data attribute of the DOM element, but you shoudl also use jQuery to add this element to the DOM.
$.each(products, function(i, product) {
// Create DOM element
var _ = $('<div class="col-md-4" id="prod-block">'
+ '<p id="prod-description">' + product.name + ' ' + product.description + '</p>'
+ '<h2 id="price">$' + product.price + '</h2>'
+ '</div>');
// Set product data
_.data("product", product);
// Add element to the DOM
$("#output").append(_);
});
There are multiple options here, such as adding the data as an attribute of the element, but I believe your best option is to create the HTML elements explicitly so you can attach event listeners to them, then append them to the DOM; this would be instead of setting the innerHTML of the output div element to a string representation of the desired HTML.
var output = document.getElementById("output");
var hoverOutput = document.getElementById("hovertext");
for (var i = 0, len = products.length; i < len; i++) {
product = products[i];
var newDiv = document.createElement("div");
newDiv.className = "col-md-4";
newDiv.innerHTML = '<p class="prod-description">' + product.name + ' ' + product.description + '</p><h4 class="price">$' + product.price + '</h4>';
(function() {
var num = i;
var target = hoverOutput;
newDiv.onmouseover = function() {
target.innerHTML = num;
};
})();
output.appendChild(newDiv);
}
Check out the working example below:
var products = [{
name: "paper",
price: 2.00,
description: "blah blah",
location: "aisle 5"
}, {
name: "paper clips",
price: 0.5,
description: "blah bloo blab",
location: "aisle 6"
}];
var output = document.getElementById("output");
var hoverOutput = document.getElementById("hovertext");
for (var i = 0, len = products.length; i < len; i++) {
product = products[i];
var newDiv = document.createElement("div");
newDiv.className = "col-md-4";
newDiv.innerHTML = '<p class="prod-description">' + product.name + ' ' + product.description + '</p><h4 class="price">$' + product.price + '</h4>';
(function() {
var num = i;
var target = hoverOutput;
newDiv.onmouseover = function() {
target.innerHTML = num;
};
})();
output.appendChild(newDiv);
}
#hovertext {
font-weight: bold;
color: red;
min-height: 10px;
}
#output div {
border: 1px solid black;
}
.col-md-4{line-height:.2em;}
<div id="output"></div>
<div id="hovertext">Hover over an item to see its index here</div>
EDITED:
I'm (still) having a little trouble getting values from a nested array in JSON and appending them to generated html.
I'm currently using the following JSON (updated):
{
"OuterArray": [
{
"memberId": "01",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "02",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "03",
"key01": "",
"included": "false",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "04",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
}
]
}
And this js:
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// etc.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i];
for (var j=0; j<outerArray.length; j++) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[j].keyA + "</p>";
}
}
Note that one of the keys in the outer array has a boolean value which determines whether or not it (the outer array member) is - and its nested array stuff are - included in the page.
So just to reiterate, the goal is:
<div class="outer-array-stuff">
<!-- <snip: some outer array key/values here /> -->
<div class="nested-array-stuff">
<div class="nested-array-stuff">
<p>[e.g., nested array key 1 value]</p>
<p>[e.g., nested array key 2 value]</p>
<p>[etc.]</p>
</div>
</div>
If all the outer array members 'included' are 'true', everything outer & nested loads, but this is not exactly what I want; I need to filter so that only those 'included' !== "false". So now my problem is that despite being inside the if 'included'/else loop, the outer array members stop loading at the first excluded outer array member (actually, the next 'true' outer array member does load, but its nested array stuff doesn't, and then nothing further loads, the entire outer array loop dies.
Any insight as to why this is happening?
Many thanks to dreyescat for the help to this point.
P.S. generally I'm trying to minimize my reliance on jQuery.
Many thanks, svs
You are almost there. Here is your code revised with some comments.
// Generally is not a good practice iterate arrays using for..in
//for (var i in outerArray) {
for (var i = 0; i < outerArray.length; i++) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// This should by outerArray array and not jsonData object.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
// getElementsByClassName gets a list of elements that have that class.
// I suppose you want to add the elements to the corresponding outer array.
// Let's use the loop index i to get the proper parent element. You could also
// just get the last one.
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i]; // help?
// Again I recommend you not to use for..in for arrays.
for (var obj in nestedArray) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
}
See demo.
You could also build the entire nested array stuff before adding it to the div element. Then you don't need to query the document to get the nested array stuff element.
for (var i in outerArray) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
var nestedArray = outerArray[i]["nestedArray"];
var nestedArrayStuff = '<div class=\"nested-array-stuff\">';
for (var obj in nestedArray) {
nestedArrayStuff += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
nestedArrayStuff += '</div>';
myDiv.innerHTML += "<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ nestedArrayStuff
+ "</div>"
+ "</div>";
}
See demo
nestedArray is not a string. your nestedArray array loop should be as follows.
var nestedArray = outerArray[i].nestedArray;
for (var j in nestedArray) {
console.log(nestedArray[j].keyA);
console.log(nestedArray[j].keyB);
}
Here is your complete solution, I used lists to output content. It assumes we have one container:
<div id="mydiv"></div>
Than JS would be:
var myDiv = document.getElementById('mydiv');
var outerArray = [
{
"memberId":"01",
"key01":"",
"key02":"key02 exists, ...",
"included":"true",
"nestedArray":[
{
"keyA":"1",
"keyB":"2"
},
{
"keyA":"3",
"keyB":"4"
}
]
},
{
"memberId":"02",
"key01":"key01 value..",
"included":"true",
"nestedArray":[
{
"keyA":"5",
"keyB":""
},
{
"keyA":"",
"keyB":"8"
}
]
},
{
"memberId":"03",
"key02":"",
"included":"false",
"nestedArray":[
{
"keyA":"",
"keyB":"9"
},
{
"keyA":"",
"keyB":""
}
]
},
{
"memberId":"04",
"key01":"value of key01",
"key02":"key02 value ...",
"included":"true",
"nestedArray":[
{
"keyA":"",
"keyB":"10"
},
{
"keyA":"11",
"keyB":"12"
}
]
}
];
var insertHtml = '';
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
insertHtml += "<ul class=\"outer-array-stuff\">";
insertHtml += " <li>";
insertHtml += " <p class=\"memberId\">memberId(" + i + "): " + outerArray[i].memberId + "</p>"
insertHtml += " <p class=\"key01\">key01: " + ( ( typeof outerArray[i].key01!='undefined' && outerArray[i].key01 ) ? outerArray[i].key01 : '') + "</p>"
insertHtml += " <p class=\"key02\">key02: " + ( ( typeof outerArray[i].key02!='undefined' && outerArray[i].key02 ) ? outerArray[i].key02 : '') + "</p>"
var nestedArray = outerArray[i]["nestedArray"];
if ( nestedArray.length>0 ) {
insertHtml += " <ul class=\"nested-array-stuff\">"
for (var j=0; j<nestedArray.length; j++) {
insertHtml += "<li class=\"keyA\">keyA(" + j + "): " + nestedArray[j].keyA + "</li>";
insertHtml += "<li class=\"keyB\">keyB(" + j + "): " + nestedArray[j].keyB + "</li>";
};
insertHtml += " </ul>"
};
insertHtml += " </li>";
insertHtml += "</ul>"
}
}
myDiv.innerHTML = insertHtml;