Javascript for loop variable not working - javascript

I am having a problem with my for loop inside a javascript function. The variable i is not working as an argument for the function showAlbum(i). Why is that happening?
var out = "<table>";
for(i = 0; i < arr.length; i++) {
out += "<tr><td><a href=''onclick='showAlbum(i);' >"+
arr[i].artist +
" - " +
arr[i].title +
"</a></td></tr>";
}
out += "</table>";

Because i wrapped in quotations is the literal character i, not the value held within your i variable. You need to evaluate it outside of the quotations:
out += "<tr><td><a href=''onclick='showAlbum(" + i + ");' >"

The i is within the string literal, so variables are not parsed from the string.
Break out of the string like so:
out += "<tr><td><a href=''onclick='showAlbum(" + i + ");' >"+
// ^^^^^^^^^

Try changing the formatting to:
var i,
out = '<table>';
for (i = 0; i < arr.length; i++) {
out += '<tr><td><a href="" onclick="showAlbum(' + i + ')" >' +
arr[i].artist +
' - ' +
arr[i].title +
'</a></td></tr>';
}
out += '</table>';

Related

string literal contains an unescaped line break

I have an error in console
Uncaught SyntaxError: '' string literal contains an unescaped line break
'<ul>\n' +
'<?php for ($i = 1; $i < 31; $i++){
echo '<li onclick="updateBasket('.$i.','+value['basketID'].')"><?= $i ?></li>';
}
?>'+
'</ul>\n' +
Try this. This will replace your PHP loop with the same thing but in JavaScript. Replace everything including the lines that open and close the <ul>.
// End previous concatenation.
'<ul>\n';
// Insert 30 list items.
for (let i = 0; i < 30; i++)
tr += '<li onclick="updateBasket(' + i + ', ' + value['basketCount'] + ')">' + i + '</li>';
// Continue your concatenation as before.
tr +=
'</ul>\n' +

Javascript Append Function, Need to build a loop

I have a .php file where I am using both HTML and JavaScript to display items from my database. I have a JavaScript append function that is creating cards where each item is display. On my cards, I have a button that will expand the card to show product history. Some products have more history than others so the expansion needs to be dynamic. The historical data is being pulled from database and is initially in a php array. I originally was going to institute php into the javascript append function but I could not figure out how to set the JavaScript index variable 'I' to my php index. So I want to just stay with JavaScript. But I don't know how to write a loop in the middle of this append function that will loop through the historical array and populate the expansion. Below is what I am attempting. I took out a lot of the lines in the append function but you can see what I am trying to do.
function get_products() {
clear_cards();
$.each(productNumbers,
function(i, value) {
$('.main_card_shell').append(
"<div class='card_content card_style' id='card" + i + "'>" +
"<div id='card_tab2" + i + "' class='tabcontent' data-tab='tab-name2'>" +
"<div class='details_tables'>" +
"<table>" +
"<tr>" +
"<th>Item Type</th>" +
"<th>Painted</th>" +
"<th>Last Sold" +
"<a id='_close_tab" + i + "' class='tablinks tab_override' onclick=\"openCity(event,'card_tab4" + i + "')\">" +
"<i class='large angle up icon'></i>" +
"</a>" +
"</th>" +
"</tr>" +
"<tr>" +
var itemdatesplit = itemdate[i].split("$$");
var itemtypesplit = itermtype[i].split("$$");
var itemsplit = item[i].split("$$");
var arraylength = itemsplit.length;
var counter = 0;
while(counter < arraylength)
{
+ "<td>" + itemtypesplit[counter] + "</td>" +
+ "<td>" + itemdatesplit[counter] + "</td>" +
counter = counter + 1;
}
+
"</tr>" +
"</table>" +
"</div>" +
"</div>" +
Please help. I had it working with PHP inserted in, but I just couldn't figure out how to set it to a PHP variable.
Place this code into a function:
function getSomething(i) {
var html = '';
var itemdatesplit = itemdate[i].split("$$");
var itemtypesplit = itermtype[i].split("$$");
var itemsplit = item[i].split("$$");
var arraylength = itemsplit.length;
var counter = 0;
while(counter < arraylength) {
html += "<td>" + itemtypesplit[counter] + "</td>";
html += "<td>" + itemdatesplit[counter] + "</td>";
counter = counter + 1;
}
return html;
}
And then use it in your HTML building block:
'<some html>' + getSomething(i) + '<some other html>'

$.getJSON and for loop with an array and how to get them to work together - for loop completes before JSON is returned

I am trying to cycle through an array and with each value in the array, use $.getJSON to return some JSON and populate an HTML table with the return values.
I have been following this post, but seem not get this to work:
$.getJSON calls misbehaving inside a for loop
Here is my function:
$("#selectProviderTop").click(function() {
var restURL = window.location.protocol + "//" + window.location.hostname + (window.location.port == "" ? "" : (":" + window.location.port)) + "/restGetProvider/";
var selected = [];
var providerKey;
var providerID;
var providerLegacyID;
var providerName;
var finalURL;
var tr;
// First, create an array from the User Provider Keys...
var userProviderKeys = $("#hiddenUserProviderKeys").val();
selected = userProviderKeys.split(",");
console.log("selected: " + selected);
var tableHTML = "";
var focus = $("<div></div>"); // either match an existing element or create one: '<div />'
var arrayLength = selected.length;
for (var i = 0; i < arrayLength; i++) {
(function(i) {
console.log("i: " + i);
providerKey = selected[i];
console.log("providerKey: " + providerKey);
// Get that provider and populate the table...
finalURL = restURL + providerKey;
console.log("finalURL: " + finalURL);
focus.queue('apicalls', function(next) {
$.getJSON(finalURL, function(jsonObject) {
tableHTML += "<tr>";
tableHTML += "<td><a href=\"#\" onclick='selectProvider(\"" + providerKey + "\")'>" + jsonObject["providerName"] + "</a></td>";
tableHTML += "<td>" + jsonObject["providerID"] + "</td>";
tableHTML += "<td>" + jsonObject["providerLegacyID"] + "</td>";
tableHTML += "</tr>";
console.log("tableHTML: " + tableHTML);
next();
});
});
})(i);
}
// Replace table’s tbody html with tableHTML...
console.log("final tableHTML: " + tableHTML);
$("#tableProviderSelect tbody").html(tableHTML);
$('#modalSelectProviderForPTP').modal('show');
});
The userProviderKeys value is 0be32d8057924e718a8b6b4186254756,2dc5f826601e4cc5a9a3424caea4115f
The code never makes the $.getJSON call it just completes the for loop.
How do I update this code to get the first value in the array, grab the JSON, create the HTML, and then cycle through the loop?
I have tried setTimeout but that didn't help me out.
If you have some ideas, could you update my existing code - I understand better when I see the code itself. Thanks.
I don't know why you're doing this using queues. But you are, so I'm not going to rewrite your code to do it some other way.
The last few lines need to be called after all the queued functions have run, which means they should be called asynchronously. (Yes, you could make the whole thing synchronous as Marcus Höglund suggested, but that's no way to write scalable applications in javascript.) You could do this by adding another function to the queue containing these lines. Like this:
$("#selectProviderTop").click(function() {
var restURL = window.location.protocol + "//" + window.location.hostname + (window.location.port == "" ? "" : (":" + window.location.port)) + "/restGetProvider/";
var selected = [];
var providerKey;
var providerID;
var providerLegacyID;
var providerName;
var finalURL;
var tr;
// First, create an array from the User Provider Keys...
var userProviderKeys = $("#hiddenUserProviderKeys").val();
selected = userProviderKeys.split(",");
console.log("selected: " + selected);
var tableHTML = "";
var focus = $("<div></div>"); // either match an existing element or create one: '<div />'
var arrayLength = selected.length;
for (var i = 0; i < arrayLength; i++) {
(function(i) {
console.log("i: " + i);
providerKey = selected[i];
console.log("providerKey: " + providerKey);
// Get that provider and populate the table...
finalURL = restURL + providerKey;
console.log("finalURL: " + finalURL);
focus.queue('apicalls', function(next) {
$.getJSON(finalURL, function(jsonObject) {
tableHTML += "<tr>";
tableHTML += "<td><a href=\"#\" onclick='selectProvider(\"" + providerKey + "\")'>" + jsonObject["providerName"] + "</a></td>";
tableHTML += "<td>" + jsonObject["providerID"] + "</td>";
tableHTML += "<td>" + jsonObject["providerLegacyID"] + "</td>";
tableHTML += "</tr>";
console.log("tableHTML: " + tableHTML);
next();
});
});
})(i);
}
focus.queue('apicalls', function(next) {
// Replace table’s tbody html with tableHTML...
console.log("final tableHTML: " + tableHTML);
$("#tableProviderSelect tbody").html(tableHTML);
$('#modalSelectProviderForPTP').modal('show');
next();
});
});
Edit: Sunshine has pointed out that the linked stackoverflow post has mysterious references to the .dequeue method. In the accepted answer, this method is called explicitly after the tasks have been queued. I don't know whether this was necessary or not. I had thought that the problem was that the $.json bit wasn't happening until after the $("#tableProviderSelect tbody").html(tableHTML); part. But now I realise you wrote: "The code never makes the $.getJSON call it just completes the for loop." In that caseSunshine may have been right, and you need to add focus.dequeue('apicalls'); just after the last focus.queue(...);.

Not able to display the div content in two container

I want to display the randomly displayed values from 'test1' and 'test2' arrays into two different containers "mainone" and "maintwo". Now I am able to get the random values from array but failed to display the whole html content in containers during on click of click me button each time;
My fiddle here:
https://jsfiddle.net/scrumvisualize/yecoqusp/
Page with data on load
var teama = ["one_1", "one_2", "one_3","one_4", "one_5"];
var test1 = [];
var test2 = [];
function startTeam(){
for(var i = teama.length - 1; i >= 0; i--){
var randomIndex =Math.floor(Math.random()*teama.length);
var rand = teama[randomIndex];
teama.splice(randomIndex, 1);
if(i%2){
test1.push(rand);
}else{
test2.push(rand);
}
}
alert(test1);
alert(test2);
for(var j=0; j<test1.length; j++){
$('#mainone').html('<div id="' + test1[j] + '" class="well">' + test1[j] + '</div>');
}
for(var k=0; k<test2.length; k++){
$('#maintwo').html('<div id="' + test2[k] + '" <div class="well"></div>' + test2[k] + '</div>');
}
}
I tried to work on your fiddle, but no avail, as a guesswork, you have this
for(var j=0; j<test1.length; j++){
$('#mainone').html('<div id="' + test1[j] + '" class="well">' + test1[j] + '</div>');
}
for(var k=0; k<test2.length; k++){
$('#maintwo').html('<div id="' + test2[k] + '" <div class="well"></div>' + test2[k] + '</div>');
}
each loop in the two for-loops is overriding the corresponding div's html,
instead create two variables, say main1html and main2html outside the for loops and the for-loops should be something like:
for(var j=0; j<test1.length; j++){
main1html += '<div id="' + test1[j] + '" class="well">' + test1[j] + '</div>');
}
for(var k=0; k<test2.length; k++){
main2html += '<div id="' + test2[k] + '" <div class="well"></div>' + test2[k] + '</div>';
}
and after the two for-loops assign the final html to both divs, like this:
$('#mainone').html(main1html);
$('#maintwo').html(main2html);
Ok, so, as was mentioned elsewhere, using .html() is just overriding the data each time. There are a couple issues in your code, however.
You are not properly closing your div(s) in the second loop.
You need to append the new data to the container (clear the container first if you need to, I do in my example.)
Fiddle
var teama = ["one_1", "one_2", "one_3","one_4", "one_5"];
var test1 = [];
var test2 = [];
function startTeam(){
for(var i = teama.length - 1; i >= 0; i--){
var randomIndex =Math.floor(Math.random()*teama.length);
var rand = teama[randomIndex];
teama.splice(randomIndex, 1);
if(i%2){
test1.push(rand);
}else{
test2.push(rand);
}
}
alert(test1);
alert(test2);
// i'm emptying the containers, you may not need to depending
// on your implementation
$('#mainone').empty();
$('#maintwo').empty();
for(var j=0; j < test1.length; j++){
// use append here, not html
$('#mainone').append('<div id="' + test1[j] + '" class="well">' + test1[j] + '</div>');
}
for(var k=0; k<test2.length; k++){
// use append here, not html
// i also fix your markup ( you were not closing the div properly)
$('#maintwo').append('<div id="' + test2[k] + '" class="well">' + test2[k] + '</div>');
}
}

Referencing an array item in a function (as string) javascript

I created an array of strings, with the format "monthX" where is a number that increases throughout the array.
I have a function where I'm trying to reference a specific item of the array, but it keeps coming in as undefined. Here's my code:
function listCategories() {
categoryList.innerHTML = ""
for (var propertyName in categoryObject) {
var rowHTML = "<div>"
rowHTML += "<span class = 'category'>" + categoryObject[propertyName].name + "</span>"
rowHTML += "<span class = '" + monthList[3] + "'><input/></span>"
rowHTML += "</div>"
categoryList.innerHTML += rowHTML
}
}
//Months to load in
for (var i=0; i<24; i++) {
monthList[i] = "month" + (i + startingMonth)
}
The area I'm interested in is that "monthList[3]" line. That keeps coming in as undefined, even though I console.log(monthList[3]) it correctly says "month6". Any ideas? Do I have bug in my code?
Well, two questions:
WHEN do you call "listCategories()" ?
before or after you set monthList?
And, have you set the global for monthList first?
//globalize monthList array to be usable in functions
var monthList;
function listCategories() {
categoryList.innerHTML = ""
for (var propertyName in categoryObject) {
var rowHTML = "<div>"
rowHTML += "<span class = 'category'>" + categoryObject[propertyName].name + "</span>"
rowHTML += "<span class = '" + monthList[3] + "'><input/></span>"
rowHTML += "</div>"
categoryList.innerHTML += rowHTML
}
}
//Months to load in
for (var i=0; i<24; i++) {
monthList[i] = "month" + (i + startingMonth)
}
//do NOT CALL listCategories prior this line!!
That should do
In the code you show us, you never declare monthList or define it as an array.
function listCategories() {
categoryList.innerHTML = ""
for (var propertyName in categoryObject) {
var rowHTML = "<div>"
rowHTML += "<span class = 'category'>" + categoryObject[propertyName].name + "</span>"
rowHTML += "<span class = '" + monthList[3] + "'><input/></span>"
rowHTML += "</div>"
categoryList.innerHTML += rowHTML
}
}
var monthList = [],
startingMonth = 1;
//Months to load in
for (var i=0; i<24; i++) {
monthList[i] = "month" + (i + startingMonth)
}
Notice the additional lines I added after the function definition, but before the loop.

Categories