Trouble passing entire two dimensional array as parameters in JavaScript/jQuery - javascript

I am trying to generate divs around each of the elements of a two dimensional array using the methods below. So far the code only outputs the last 3 elements in the array (the 3 elements of third nested array). I am passing the array elements as parameters using .apply. How could I modify this to output each element of the array catArray in order? And why would it only pass the last 3 as it is? Any advice would be appreciated, I am trying to understand this better. I have spent hours on this, hopefully someone can help.
Here is a codepen:
http://codepen.io/anon/pen/kzEdK
function cats(catName, catFur, catEyes) {
$("#row").html('<div>' + catName + '</div>' + '<div>' + catFur + '</div>' + '<div>' + catEyes + '</div>');
}
var catArray = [
["fluffy", "soft", "green"],
["mittens", "coarse", "fire"],
["wiskers", "none", "grey"]
];
function catGenerator() {
for (var i = 0; i < catArray.length; i++) {
var blah = catArray[i];
cats.apply(this, blah);
}
}
catGenerator();

You probably want something like:
function cats(catName, catFur, catEyes) {
// note the difference (append() instead of html())
$("#row").append('<div>' + catName + '</div>' + '<div>' + catFur + '</div>' + '<div>' + catEyes + '</div>');
}
function catGenerator() {
$("#row").html(""); // in case you wish to call catGenerator() multiple times, clear the row before appending to it
for (var i = 0; i < catArray.length; i++) {
var blah = catArray[i];
cats.apply(this, blah);
}
}
It shows only the last 3 elements because $("#row").html("...") overwrites the contents of #row three times and the value set in the last iteration remains visible. I fixed that by replacing html() with append(), which does what you want.

The problem is that you have $("#row").html() which will replace the markup within the div tag after each iteration. Consider using $("#row").append()
function cats(catName, catFur, catEyes) {
$("#row").append('<div>' + catName + '</div>' + '<div>' + catFur + '</div>' + '<div>' + catEyes + '</div>');
}
var catArray = [
["fluffy", "soft", "green"],
["mittens", "coarse", "fire"],
["wiskers", "none", "grey"]
];
function catGenerator() {
for (var i = 0; i < catArray.length; i++) {
var blah = catArray[i];
cats.apply(this, blah);
}
}
catGenerator();

Related

Assign id to div dynamically created from a JSON file

I want to assign dynamic id attributes to the div(s) which are being appended through JavaScript. For example:
function x() {
for (current_list = 0; current_list < data.length; current_list++) {
$("#current").append(
"<div class="card">" +
"" + data[current_list].name + "" +
"</div>");
}
}
Two cards will be appended, so I want to assign them an id which can increase if there are more numbers of arrays present in the JSON.
you probably looking for this.
function x() {
var container=$("#current");
for(var i=1;i<10;i++)
{
var id="card"+i;
var divHtml="<div class='"+id+"'>" +
""+data[current_list].name+"" +
"</div>"
container.append(divHtml);
}
}
As Rory said, here a solution using DOM traversal.
You would have to call this after appending your "cards".
$(".card").each(function(value, index){
$(value).attr("id", "card" + index);
});
if you call x() function one time you can use
function x() {
for (current_list = 0; current_list < data.length; current_list++) {
$("#current").append('<div id="card-'+current_list+'" class="card">' + data[current_list].name + '</div>');
}
}
and if you call it many time you can use this function after every call
$(".card").each(function(value, index){
$(value).attr("id", "card-" + index);
});

Array list display online one result from json

I wrote this code and it works:
function getJsonResult(retrieve) {
var result = retrieve.results;
for (var i = 0; i < result.length; i++) {
responseJson.push({ id: result[i].id, title: result[i].title });
var search = '<a id="' + result[i].id + '">' + result[i].title + '</a><br/>';
document.write(search);
}
}
When I tried to display the results in a div, I change the last line with:
$("#divId").html(search);
But it only displays the first result. How can I make the whole list appear?
That happened because you're overriding the search variable in every iteration :
var search = '<a id="' + result[i].id + '">' + result[i].title + '</a><br/>';
You need to declare the search variable outside of the loop then append the string in every iteration like :
function getJsonResult(retrieve) {
var result = retrieve.results;
var search = "";
___________^^^^
for (var i = 0; i < result.length; i++) {
responseJson.push({ id: result[i].id, title: result[i].title });
var search += '<a id="' + result[i].id + '">' + result[i].title + '</a><br/>';
___________^^
document.write(search);
}
}
Then finally you could put your variable content to the div :
$("#divId").html(search);
$('#divId').append(search);
This appends the element included in search to the div element.

How to return a variable from a callback after building variable with .getjson and .each

The Problem
I'm trying to figure out how to return HTML that I've built from a JSON file with jQuery.
I seem to have gotten returnLocations() to wait until getLocations() is finished so that the variable locationsBody is finalized with information gathered from my .each loop. The trouble (I think) is my not being able to return that variable to output it to my HTML page.
The Question
How can I return the variable locationsBody?
Note
(there may be errors in the below code as I trimmed it down as best I could but I think it should illustrate the problem with or without them)
The jQuery
the global variables
var locationsFull = 'un d fined';
var locationsOpener = '' +
'<div class="locations-header">places youve been</div>' +
'<div class="locations-container">' +
'<div class="locations-nav left">left</div>' +
'<div class="locations-nav right">right</div>'
;
var locationsBody = '<div class="locations-inner">'; // opening of container
var locationsCloser = '</div>'; // closing of container
the function
function locationsFunction() {
function getLocations() {
var wait = $.Deferred();
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
wait.resolve();
})
return wait;
}
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser; // works, proven in alert and console.log
//alert(locationsFull); // works
console.log(locationsFull); // works
//return locationsFull; // doesnt work
//return 'anything'; // doesnt work
}
getLocations().then(returnLocations);
}
the call
$(function() {
$('.locations-body').html(locationsFunction());
})
The JSON File
{"places":[
{
"area": "Area1",
"location": "Downtown",
"image": "downtown.jpg"
},
{
"area": "Area1",
"location": "Uptown",
"image": "uptown.jpg"
}
]}
The HTML
<div class="locations-body"></div>
Further Note: Questions similar to this have been asked dozens of times on stackoverflow alone and those questions and answers have hundreds of thousands of reads. I have read through all of the top ones and more over the last 2 days. My problem is my inability to thoroughly understand the answers and apply them to my exact situation as seems to be the problem of the dozens (hundreds/thousands?) of people asking these questions and the hundreds of thousands (millions?) of people that have been searching for solutions to asynchronous problems.
You could just call .html() inside the returnLocations() function if that's viable.
the function
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
}
the call
$(function() {
locationsFunction();
}
Otherwise you'll need to look into callbacks, read this, if you need to do it this way I can update my answer with an example later on.
Have you tried
return wait.promise();
instead of returning the Deferred?
Then calling like this:
var deferredChain = $.Deferred();
deferredChain.then(getLocations).then(returnLocations);
deferredChain.resolve();
I discovered today that simply putting a .done at the end of $.getJSON seems to work just the same and is much easier than using $.Deferred and the associated lines of code to make it work.
function locationsFunction() {
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
}).done(function() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
});
}

store ID from listview in localStorage

I've a listview created by a loop:
for(var i = 0; i < data.length; i++) {
var garage = data[i];
$("#content-p").append(
"<ul data-role=\"listview\">" +
"<li><a href=\"#\" id=\"submitID\" >" +
"<h2>"+garage.location+"</h2>" +
"<p><b>"+garage.description+"</b></p>" +
"<p>"+garage.address+"</p>" +
"</a></li>" +
"</ul><br>"
);
$("#submitID").click(function() {
localStorage.setItem("garageID",garage.ID);
$.mobile.changePage("#resP");
});
}
Now the user can click on a listview item and the ID from this item should be stored in the localStorage.
Problem: It first creates the complete listview with all items. If I click now on item#2 from the list, I get the ID from the last item.
the submit function is being overwritten with every iteration of the loop, and every single #submitID is only calling that function. So, of course it will only pull up the last one in the list.
Also, the code is generating all items within data.length, so you'll need to alter that if you don't want everything in the list.
Here's a fix to the first part (assuming no styling is assigned to #submitID):
for(var i = 0; i < data.length; i++) {
var garage = data[i];
$("#content-p").append(
"<ul data-role=\"listview\">" +
"<li><a href=\"#\" id=\"submitID-" + i + "\" >" +
"<h2>"+garage.location+"</h2>" +
"<p><b>"+garage.description+"</b></p>" +
"<p>"+garage.address+"</p>" +
"</a></li>" +
"</ul><br>"
);
$("#submitID-" + i).click(function() {
localStorage.setItem("garageID",garage.ID);
$.mobile.changePage("#resP");
});
}
I think the problem was that the method was trying to reference garage when there wasn't a reference, or something like that. And you should have made the click method for a specific ID, because it just kept getting overridden each time. I fixed it for you by making it one click method for a class, but the ID of each garage element is its actual garage ID.
http://jsfiddle.net/Fq3TF/1/
Also, just a tip, if you're constructing a string which is going to be inserted into an HTML document, you can use an apostrophe instead of a quote to avoid escaping. e.g. "<a class='submitID'>Hello World</a>".
Here is my take on the problem. I use a attribute to save the id in the a element. The registering of the click handler has been moved outside the loop.
var data = [
{
id: "id1",
location: "location1",
description: "description1",
address: "address1"
},
{
id: "id2",
location: "location2",
description: "description2",
address: "address2"
}
];
for (var i = 0; i < data.length; i++) {
var garage = data[i];
$("#content-p").append(
"<ul data-role=\"listview\">" +
"<li><a href=\"#\" class=\"submitClass\" garageid=\"" + garage.id + "\">" +
"<h2>" + garage.location + "</h2>" +
"<p><b>" + garage.description + "</b></p>" +
"<p>" + garage.address + "</p>" +
"</a></li>" +
"</ul><br>"
);
}
$(".submitClass").click(function(e) {
e.stopPropagation();
alert($(this).attr("garageid"));
/*localStorage.setItem("garageID", garage.ID);
$.mobile.changePage("#resP");*/
});

Using a for loop with JSON object/array elements?

I'm trying to create a for() loop with JSON data that's already been decoded, the problem is adding my loop variable (in this case i), to the end of the element that I'm referencing.
For example, my JSON structure, dumped:
{
"url": "http://www.example.com",
"rid": 1,
"rname": "Apple iPhone 4 Rotation",
"rmin": 90,
"rmax": 150,
"blank": 0,
"geo_country_0": "GB",
"geo_url_0": "http://en",
"geo_country_1": "FR",
"geo_url_1": "http://fr",
"geo_country_2": "ES",
"geo_url_2": "http://es"
}
In the case of geo_country_ and and geo_url_ I need to append a number, in this case the loop variable.
My actual for loop, for a better understanding:
for(i = 1; i < count; i++) {
$('#geo-location').append('<div id="glt_' + i + '" class="clone"><select name="g_country['+i+']" class="glt-input-c">' + options + '</select><input type="text" name="g_url[' + i + ']" class="glt-input-c" value="' + data.geo_url_i+ '"/></div>');
$('select[name="g_country['+i+']"').find('option[value="' + data.geo_country_i+ '"]').attr('selected','selected');
}
So far I've tried:
Encasing the the i like [i].
Escaping it like \i. (This was probably a stupid idea).
Adding a pre-fixing + like, + data.geo_country + i +.
What do I need to do to have i interpreted properly?
Any help would be greatly appreciated!
In JavaScript, you may address an object's properties in two ways:
var value = myobject.myproperty;
var value2 = myobject['myproperty'];
Using this knowledge, you can rewrite your code as follows:
for(i = 1; i < count; i++) {
$('#geo-location').append('<div id="glt_' + i + '" class="clone"><select name="g_country['+i+']" class="glt-input-c">' + options + '</select><input type="text" name="g_url[' + i + ']" class="glt-input-c" value="' + data['geo_url_' + i] + '"/></div>');
$('select[name="g_country['+i+']"').find('option[value="' + data['geo_country_' + i] + '"]').attr('selected','selected');
}
Access it like
data['geo_country_' + i]
And you should have no issues

Categories