Performing an ajax call to a drinks api and I've nested a loop to pull the ingredients out and render them to the page. The nested loop consoles the ingredients correctly but when I use jquery to append the results to the page only the item in the last index is displayed. I know there are null values I was going to remove them with an if statement after I got them to show.
function displayDrinkData(drinkName) {
var queryURL = "https://thecocktaildb.com/api/json/v1/1/search.php?s=" + drinkName
$.ajax({
url: queryURL,
method: "GET"
}).then(function (response) {
console.log(response);
var results = response.drinks;
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
var eachDrink = results[i];
var drinkDiv = $("<div>");
var drinkName = results[i].strDrink;
for (var k = 1; k < 16; k++) {
console.log(eachDrink['strIngredient' + k]);
var ingList = $("<ul>").text("Ingredients: " + eachDrink['strIngredient' + k])
}
var pOne = $("<p>").text("Drink name: " + drinkName);
var drinkInstructions = results[i].strInstructions;
var pTwo = $("<p>").text("Instructions: " + drinkInstructions);
var drinkImage = $("<img>");
drinkImage.attr("src", results[i].strDrinkThumb);
drinkDiv.append(pOne);
drinkDiv.append(ingList);
drinkDiv.append(pTwo);
drinkDiv.append(drinkImage);
$("#drinks-view").append(drinkDiv);
}
})
}
Because var ingList is inside loop, not appending, but creating a new one every time.
var ingList = $("<ul>");
for (var k = 1; k < 16; k++) {
console.log(eachDrink['strIngredient' + k]);
ingList.append($('<li>').text("Ingredients: " + eachDrink['strIngredient' + k]));
}
Declare variable outside loop, and append <li> for each element.
Related
Javascript:
function add_content(count)
{
var result = {};
var row = new Array();
for (i = 0; i < count; i++)
{
result['img_src'] = $("#img_" + i).attr('src');
result['desc'] = $("#desc_" + i).val();
row.push(result);
}
$.ajax({
url: "ajax-functions.php",
data: {json_data: JSON.stringify(row)},
type: 'post',
success: function (output) {
alert(output);
}
})
}
Php:
$img_desc = json_decode($_POST['json_data'],TRUE);
$count = count($img_desc);
echo 'count:'.$count;
print_r($img_desc);
I want to send json to from JS to PHP. This above code works well, but it send the last data of the for loop is set in all the objects.
How to fix it? Is this right way?
Thanks.
Push a new object on each round of the loop into to the array
for (var i = 0; i < count; i++) {
row.push({
"img_src": $("#img_" + i).attr('src'),
"desc": $("#desc_" + i).val()
});
}
fiddle
Move result declaration inside for:
var row = new Array();
for (i = 0; i < count; i++)
{
var result = {};
result['img_src'] = $("#img_" + i).attr('src');
result['desc'] = $("#desc_" + i).val();
row.push(result);
}
or it can be done more elegantly:
var row = new Array();
var result;
for (i = 0; i < 10; i++)
{
result = row[ row.push({}) - 1 ];
result['img_src'] = $("#img_" + i).attr('src');
result['desc'] = $("#desc_" + i).val();
}
You can make the keys of result array also dynamic
Since you are not making it dynmamic, its getting over ridden in the next loop
EDIT:
for (i = 0; i < count; i++)
{
var result = {};
result['img_src'] = $("#img_" + i).attr('src');
result['desc'] = $("#desc_" + i).val();
row.push(result);
}
var select = [];
for (var i = 0; i < nameslots; i += 1) {
select[i] = this.value;
}
This is an extract of my code. I want to generate a list of variables (select1, select2, etc. depending on the length of nameslots in the for.
This doesn't seem to be working. How can I achieve this? If you require the full code I can post it.
EDIT: full code for this specific function.
//name and time slots
function gennametime() {
document.getElementById('slots').innerHTML = '';
var namelist = editnamebox.children, slotnameHtml = '', optionlist;
nameslots = document.getElementById('setpresentslots').value;
for (var f = 0; f < namelist.length; f += 1) {
slotnameHtml += '<option>'
+ namelist[f].children[0].value
+ '</option>';
};
var select = [];
for (var i = 0; i < nameslots; i += 1) {
var slotname = document.createElement('select'),
slottime = document.createElement('select'),
slotlist = document.createElement('li');
slotname.id = 'personname' + i;
slottime.id = 'persontime' + i;
slottime.className = 'persontime';
slotname.innerHTML = slotnameHtml;
slottime.innerHTML = '<optgroup><option value="1">00:01</option><option value="2">00:02</option><option value="3">00:03</option><option value="4">00:04</option><option value="5">00:05</option><option value="6">00:06</option><option value="7">00:07</option><option value="8">00:08</option><option value="9">00:09</option><option value="10">00:10</option><option value="15">00:15</option><option value="20">00:20</option><option value="25">00:25</option><option value="30">00:30</option><option value="35">00:35</option><option value="40">00:40</option><option value="45">00:45</option><option value="50">00:50</option><option value="55">00:55</option><option value="60">1:00</option><option value="75">1:15</option><option value="90">1:30</option><option value="105">1:45</option><option value="120">2:00</option></optgroup>';
slotlist.appendChild(slotname);
slotlist.appendChild(slottime);
document.getElementById('slots').appendChild(slotlist);
(function (slottime) {
slottime.addEventListener("change", function () {
select[i] = this.value;
});
})(slottime);
}
}
You'll have to close in the iterator as well in that IIFE
(function (slottime, j) {
slottime.addEventListener("change", function () {
select[j] = this.value;
});
})(slottime, i);
and it's only updated when the element actually change
The cool thing about JavaScript arrays is that you can add things to them after the fact.
var select = [];
for(var i = 0; i < nameSlots; i++) {
var newValue = this.value;
// Push appends the new value to the end of the array.
select.push(newValue);
}
I am developing a simple add-on with Firefox SDK that allows the user to review the stored data.
I would like to show the items in a panel with a table. The table is created dynamically with the data incoming from the data-base. Firstly, In the JavaScript code I create the items with their properties, then I create a table with the properties as row and I append the items with the value of each properties.
I have some problems: the table has only the item's name as first row and the properties name as first column without the value in the cells. It seems that the code is not executed in order, but it seems that the faster functions are executed first.
This is the code:
self.on('message', function() {
var container = $('#container');
container.empty();
items = [];
self.port.emit('getItem');
});
self.port.on('items', function(response) {
var ok = 0;
var items = [];
var table = $('#tableContainer #table').clone();
var container = $('#container');
table.append("<tr id=first><th> </th></tr>");
var json = eval('('+ response + ')');
for (var i = 0, len = json.length; i < len; ++i) {
var item = {
id: json[i],
properties: []
};
items.push(item);
}
items.forEach ( function(item) {
table.find('#first').append("<th id="+item.id+">"+item.id+"</th>");
self.port.emit('detailsItem', item.id);
self.port.on('details'+item.id, function(response) {
var details = eval('('+ response + ')');
var description = [];
ndet = details.length;
var len = details.length;
for (var i = 0; i < len;) {
var detail = {
dimension : details[i].dimension,
value : details[i].value
}
description.push(detail);
++i;
}
item.properties = description;
});
});
self.port.emit('getDimension');
self.port.on('dimension', function(response) {
var dimensions = eval('('+ response + ')');
for(var cont = 0, l = dimensions.length; cont < l; ++cont) {
table.append("<tr id=dimension"+cont+"><td>"+dimensions[cont]+"</td></tr>");
items.forEach( function(item) {
var prop = [];
prop = item.properties;
var lun = prop.length;
for( var p =0;p < lun;) {
if(item.properties[p].dimension == dimensions[cont]) { table.find('#dimension'+cont).append("<td>"+item.properties[p].value+"</td>");
}
else {
table.find('#dimension'+cont).append("<td> --- </td>");
}
++p; }
});
};
});
container.append(table);
});
I had this code:
$('#testsPane').live("click", function() {//if the secondary ui nav tests is
selected
//Displays the test list
var listOfTests = "";
var subjects = [];
var tests= [];
var titles = [];
var keysplit;
var testSubj;
var key, value;
for (var i = 0; i < localStorage.length; i++) {
key = localStorage.key(i);
value = localStorage.getItem(key);
keysplit = key.split(".");
tests.push(value);
titles.push(keysplit[0]);
subjects.push(keysplit[keysplit.length-1]);
}
for(var i=0; i < tests.length; i++) {
listOfTests += '<div class="testDisplayBox"><div
class="subjColorBar"></div><div class="testListIndiContain"><span
class="testListTitle">' + titles[titles.length-(i+1)] + '</span><span> in
</span><span class="testListSubj">' + subjects[subjects.length-(i+1)] +
'</span></div><div class="testListTags"><span
class="specTags">quiz</span></div></div>';
}
var testsDashboard = '<div id="testsList">' + listOfTests + '</div>';
$('#selectedPane').append(testsDashboard);//adds the html to the pane to make it
into the tests dashboard
})
The above code worked but I wanted to reuse some of it so I put it into a function. When I did that it did not work. Any idea why? The code below is with using a named function.
function grabTestList() {//Displays the test list
var keysplit;
var testSubj;
var key, value;
for (var i = 0; i < localStorage.length; i++) {
key = localStorage.key(i);
value = localStorage.getItem(key);
keysplit = key.split(".");
tests.push(value);
titles.push(keysplit[0]);
subjects.push(keysplit[keysplit.length-1]);
}}
$('#testsPane').live("click", function() {//if the secondary ui nav tests is selected
grabTestList();
var listOfTests = "";
var subjects = [];
var tests= [];
var titles = [];
for(var i=0; i < tests.length; i++) {
listOfTests += '<div class="testDisplayBox"><div class="subjColorBar"></div><div class="testListIndiContain"><span class="testListTitle">' + titles[titles.length-
(i+1)] + '</span><span> in </span><span class="testListSubj">' + subjects[subjects.length-(i+1)] + '</span></div><div class="testListTags"><span
class="specTags">quiz</span></div></div>';
}
var testsDashboard = '<div id="testsList">' + listOfTests + '</div>';
$('#selectedPane').append(testsDashboard);//adds the html to the pane to make it into the tests dashboard
})
Because you are defining variables in the context of the anonymous function which are unknown to the named function. Pass them to grabTestList so the .push methods can mutate those arrays.
function grabTestList(tests, titles, subjects) {
// manipulate tests/titles/subjects
}
$('blah').live('click', function() {
var tests = [], titles = [], subjects = [];
grabTestList( tests, titles, subjects );
// since tests, titles, and subjects are mutated by the function, you can just loop through them here.
})
DEMO:
Here's a sample version which you can base your code on: http://jsfiddle.net/JLK6N/2/
updated with the fix: http://jsfiddle.net/JLK6N/3/
Remember that objects are passed by reference, arrays are objects, and methods like .push are mutator methods.
I'm trying to parse the json grabbed from here. Basically what I do is iterate over the items, sort them, then display them. But I get an error saying data.data.children[i] is undefined.
I can't think why it's doing it though?
var json = 'http://www.reddit.com/reddits/mine/.json';
GM_xmlhttpRequest({
method: "GET",
url: json,
onload: reddits
});
function reddits(response){
var txt = response.responseText;
var data;
var suggested = document.getElementById('suggested-reddits');
if(window.JSON && JSON.parse){
data = JSON.parse(txt);
}
else{
data = eval("("+txt+")");
}
suggested.innerHTML += '<span>reddits you\'re subscribed to </span> <ul id="rsub"></ul>';
GM_addStyle('#rsub{width: 500px;}');
var reddits = new Array();
var rsub = document.getElementById('rsub');
for(i = 0; i <= data.data.children.length; i++){
var r = data.data.children[i].data.display_name;
reddits.push(r);
}
sort(reddits);
for(i = 0; i <= reddits.length; i++){
rsub.innerHTML += '<li>' + reddits[i] + '</li>';
}
}
for(i = 0; i <= data.data.children.length; i++){
var r = data.data.children[i].data.display_name;
reddits.push(r);
}
Clear problem is in the for statement. Change the i <= data.data.children.length to i < data.data.children.length. Note the inequality change.
Since arrays in Javascript are 0-indexed, the element at i = data.data.children.length does not exist.
You should probably do the same things for the reddits.length loop.