This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I've been building an app in jQuery and html 5 that reads rss feed of a blog. I wanted to show a list of titles of rss and when user clicks on the title it goes to a different page where full content is shown. I could get content using ajax and store them in an array. But when I'm clicking on the title, it shows undefined on the next page. I am using jQuery pages.
$(document).ready(function() {
load_posts();
});
function load_posts() {
var PAGINATION = $('#pagination');
var HTML1 = '<li><a href="#post" data-transition="slide" id ="';
var HTML5 = '"><h4>';
var HTML2 = '</h4>';
var HTML3 = '<p>';
var HTML4 = '</p></a></li>';
var btn = "";
var selector = "";
var i = 0;
var title = "";
var pubDate = "";
var dascription = "";
var anchorID = "";
var url = "";
var fullPost = new Array;
var link = new Array;
$.ajax({
type: 'GET',
url: 'http://smushbits.com/feed/',
dataType: 'xml',
error: function() {
alert("An error occured!");
},
success: function(xml) {
$(xml).find('item').each(function() {
title = $(this).find('title').text();
pubDate = $(this).find('pubDate').text();
pubDate = pubDate.substring(5, 16);
description = $(this).find('encoded').text();
url = $(this).find('link').text();
fullPost.push(description);
link.push(url);
anchorID = "btn" + i.toString();
$(HTML1 + anchorID + HTML5 + title + HTML2 + HTML3 + pubDate + HTML4).appendTo(PAGINATION);
i = i + 1;
});
for (var j = 0; j < fullPost.length; j++) {
btn = "#btn" + j.toString();
selector = $(btn);
$(document).on("click", selector, function() {
document.getElementById('entry').innerHTML = fullPost[j];
});
}
PAGINATION.listview("refresh");
}
});
}
It is the infamous for loop issue.
for (var j = 0; j < fullPost.length; j++) {
(function(j) {
var btn = "#btn" + j;
$(document).on("click", btn, function() {
document.getElementById('entry').innerHTML = fullPost[j];
});
}(j));
}
Related
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.
I'm needing to style a table that's dynamically created by javascript. I know how to style it if it were just a static HTML table but this is different and I'm not too familiar with javascript. Here is the javascript code:
[var aryPortalList = \[\];
function getPortalList() {
var wP = window.location.protocol;
var wH = window.location.host;
var wPath = "ibi_apps/rs/ibfs/BIP/Portals?IBIRS_action=get";
//http://webfocusclidev:8080/ibi_apps/rs/ibfs/BIP/Portals?IBIRS_action=get;
var webfocusAPI = wP + "//" + wH + "/" + wPath;
$.ajax({
type: "GET",
async: false,
url: webfocusAPI,
dataType: 'xml',
success: function(xml) {
$(xml).find('children').children().each(function() {
var portal = { Name: $(this).attr('bipName'),
Link: "/ibi_apps/bip/portal" + $(this).attr('bipPath'),
IconLink: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=" + $(this).attr('bipIconPath')
}; //var portal
console.log("portal.name=" + portal.Name);
if (portal.Name != "GlobalBI") aryPortalList.push(portal);
}); //each
console.log("Portals in List = " + aryPortalList.length);
} //success function
}); //ajax
}
function displayPortalList_Icon() {
if (aryPortalList.length == 0) {
var hTxt = "<p>You do not have access to any portals</p>";
$("#portallist").append(hTxt);
} else {
var bRowAdded = false;
var hTbl=$("<table id='tbl_portallist'></table>");
var row = $('<tr></tr>').addClass('ingrPL_row');
console.log("Portals in List = " + aryPortalList.length);
for(var j=0; j < aryPortalList.length; j++) {
var cell = $("<td align = 'center'></td>");
var hTxt = $("<p>" + aryPortalList\[j\].Name + "</p>");
var hLink = $("<a>").attr({"href": aryPortalList\[j\].Link,
"target": "_blank"});
var img = $("<img>").attr("src", aryPortalList\[j\].IconLink);
img.width("100px");
img.height("100px");
console.log("hTxt=" + hTxt);
hLink.append(img);
cell.append(hTxt);
cell.append(hLink);
row.append(cell);
bRowAdded = false;
if ((j+1) % 4 == 0) {
hTbl.append(row);
bRowAdded = true;
var row = $('<tr></tr>').addClass('ingrPL_row');
}
}
if (!bRowAdded) {
hTbl.append(row);
}
$("#portallist").html(hTbl);
}
}
function displayPortalList_List() {
if (aryPortalList.length == 0) {
var hTxt = "<p>You do not have access to any portals</p>";
$("#portallist").append(hTxt);
} else {
var bRowAdded = false;
var hTbl=$("<table id='tbl_portallist'></table>");
console.log("Portals in List = " + aryPortalList.length);
for(var j=0; j < aryPortalList.length; j++) {
var row = $('<tr></tr>').addClass('ingrPL_row');
var cell = $("<td align = 'center'></td>");
var hTxt = $("<p>" + aryPortalList\[j\].Name + "</p>");
var hLink = $("<a>").attr({"href": aryPortalList\[j\].Link,
"target": "_blank"});
console.log("hTxt=" + hTxt);
hLink.append(hTxt);
cell.append(hLink);
row.append(cell);
hTbl.append(row);
}
$("#portallist").html(hTbl);
console.log("portal.name=" + portal.Name);
}
}][1]
And I've attached a photo of how the 'portal' looks.
What I need to do is space out the icons more and have the title's on the bottom of the icons, to look more like an 'iphone app'
Any help is greatly appreciated.
you can style it in the same way you style static elements
looking at your code I can see the table have an ID and the rows have classes
var hTbl=$("<table id='tbl_portallist'></table>");
var row = $('<tr></tr>').addClass('ingrPL_row');
so you can select those in your CSS file
CSS
#tbl_portallist {
/*table style here */
}
#tbl_portallist th {
/*table head style here*/
}
#tbl_portallist tr {
/*table row style here*/
}
#tbl_portallist td {
/*table data (cell) style here*/
}
It's my second day on this project :\
I'm trying to create is : creating a new <a> element with a new href and id attributes in for loop so that I can get each output of the API as a link.
This is my JS Code
var one;
var two;
var hoba;
$(document).ready(function() {
$("#inp").keyup(function() {
hoba = $(this).val();
});
$("#but").on("click", function() {
var app = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&list=search&titles=Main+Page&rvprop=content&origin=*&srsearch=" + hoba;
$.getJSON(app, function(data) {
for (i = 0; i < data.query.search.length; i++) {
console.log(app);
one = $("<a></a>").text(data.query.search[i].title);
//var _href = $("a").attr("href");
$("a").attr("href", 'https://www.wikipedia.org/wiki/' + data.query.search[i].title);
$("a").attr("id", data.query.search[i].title);
two = document.createElement("p");
two.innerHTML = data.query.search[i].snippet;
$("body").append(one, two);
}
});
});
});
Use same object to set attributes
one = $("<a></a>");
one.text(data.query.search[i].title);
one.attr("href", 'https://www.wikipedia.org/wiki/' + data.query.search[i].title);
one.attr("id", data.query.search[i].title);
Use jQuery( html, attributes ) to create HTML element.
var anchor = $("<a></a>", {
"text": data.query.search[i].title,
"href": 'https://www.wikipedia.org/wiki/' + data.query.search[i].title,
"id": data.query.search[i].title
});
$("body").append(anchor);
$(document).ready(function() {
$("#inp").keyup(function() {
hoba = $(this).val();
});
$("#but").on("click", function() {
var app = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&list=search&titles=Main+Page&rvprop=content&origin=*&srsearch=" + hoba;
$.getJSON(app, function(data) {
for (i = 0; i < data.query.search.length; i++) {
var anchor = $("<a></a>", {
"text": data.query.search[i].title,
"href": 'https://www.wikipedia.org/wiki/' + data.query.search[i].title,
"id": data.query.search[i].title
});
var p = $("<p></p>", {
"html": data.query.search[i].snippet
});
$("body").append(anchor);
$("body").append(p);
}
});
});
});
You should to do minor changes in your code as below.
Change code are in between
// Changes Code Start and // Changes Code End
var one;
var two;
var hoba;
$(document).ready(function(){
$("#inp").keyup(function(){
hoba = $(this).val();
});
$("#but").on("click",function(){
var app = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&list=search&titles=Main+Page&rvprop=content&origin=*&srsearch="+hoba;
// Changes Code Start
$.getJSON(app,function(data){
for(i=0; i<data.query.search.length; i++){
console.log(app);
var dataAppend;
var title = data.query.search[i].title;
var href = 'https://www.wikipedia.org/wiki/' + data.query.search[i].title;
var id = data.query.search[i].title;
dataAppend = "<a href='"+href+"' id='"+id+"'>"+title+"</a>";
dataAppend += "<p>"+data.query.search[i].snippet+"</p>";
// \"
$("body").append(dataAppend);
}
});
// Changes Code End
});
});
I am trying to get multiple images from an ajax source and load the on the page when they have all finished loading. The issue I was having that has caused me to try to find a solution was that some of the images weren't loading even though those images existed on the server.
I have tried to add code that now adds the image to an array
design_images.push({cid:designImg});
... and then when all the images have loaded will add that to the page, but I can't get that to work.
var counter = 0;
$(design_images).load(function() { // many or just one image(w) inside body or any other container
counter += 1;
}).each(function(key, value) {
this.complete && $(this).load();
console.log(value);
});
Nothing is outputted from the .each
This is the output of the array design_images
The value of design_images.length is 0 though.
Here is the complete function:
function matte_design_change_design_type(element)
{
var element_value = null;
var mattes_selected_type = get_mattes_selected_type();
matte_design_widths[mattes_selected_type] = [];
var mattes_selected_design = get_mattes_selected_design();
var count_matte_designs = 0;
var found = false;
$(document).ready(function()
{
$.ajax(
{
type: "GET",
url: SITE_URL + "/system/components/xml/" + mattes_selected_type,
dataType: 'xml',
success: function(xml)
{
var output = [];
var design_images = [];
$('component', xml).each(function(i, el)
{
matte_design_widths[mattes_selected_type][i] = 0;
count_matte_designs++;
var thumb = $("thumb", this).text(),
cid = $("cid", this).first().text(),
name = $("name", this).first().text().replace("Collage - ", ""),
alt = name,
description = $("description", this).first().text(),
if (parseInt(cid, 10) === mattes_selected_design)
{
found = true;
$("#matte_design_name").html(name);
$("#matte_design_description").html(description);
}
var designImg = new Image();
designImg.id = 'cid_' + cid;
designImg.alt = alt;
designImg.onclick = function() {
matte_design_change(cid, mattes_selected_type);
};
designImg.onload = function() {
output.push('<span class="matte_design_image_name" id="design_' + cid + '"><img id="cid_' + cid + '" />');
output.push('<br /><span class="matte_design_name" id="matte_design_name_' + mattes_selected_type + '_' + i + '">' + name + '</span></span>');
matte_design_increase_width(mattes_selected_type, this.width, i);
$('#matte_designs_strip_wrapper').html(output.join(''));
};
designImg.src = 'https://example.com/system/components/compimg/' + thumb + '/flashthumb';
});
var counter = 0;
var size = $('img').length;
$(design_images).load(function() {
counter += 1;
}).each(function(key, value) {
this.complete && $(this).load();
console.log(value);
});
}
});
});
}
I have tried waitForImages and imagesLoaded but I couldn't get them to work for me, but I'm not opposed to using either one.
Hide all images by default using CSS
img{
display: none;
}
Use Jquery to check if all loaded, then display images
JQuery
$(window).load(function(){
$('img').fadeIn(800); //or $('img').show('slow');
});
I am trying to make a debugger that will be dynamiaclly created with some variables. The names on the left div need to show a div for the corresponding variables Description,Variable ID, and initial Value as well as another div that will show history and lock status when variables are updated later. Where I am having trouble is properly adding the show/hide to the dom I think. Everything starts hidden and then when I click a name the Variables for that name show up but the next click doesn't hide the values from the former. Also any cleanup/optimization advice?
<script type="text/javascript">
var variableIDArray = {};
function loadVariables(variables) {
if (typeof variables != "object") { alert(variables); return; }
var namearea = document.getElementById('namearea');
var description = document.getElementById('description');
var varid = document.getElementById('varid');
var initialvalue = document.getElementById('initialvalue');
var valuelock = document.getElementById('valuelock');
for (var i = 0; i < variables.length - 1; i++) {
var nameDiv = document.createElement('div');
nameDiv.id = variables[i].variableID + "namearea";
nameDiv.className = "nameDiv";
nameDiv.onclick = (function (varid) {
return function () { showvariable(varid); };
})(variables[i].variableID);
nameDiv.appendChild(document.createTextNode(variables[i].name));
namearea.appendChild(nameDiv);
var descriptionDiv = document.createElement('div');
descriptionDiv.id = variables[i].variableID + "description";
descriptionDiv.className = "descriptionDiv";
descriptionDiv.appendChild(document.createTextNode("Description : " + variables[i].description));
description.appendChild(descriptionDiv);
var varidDiv = document.createElement('div');
varidDiv.id = variables[i].variableID + "varid";
varidDiv.className = "varidDiv";
varidDiv.appendChild(document.createTextNode("Var ID : " + variables[i].variableID));
varid.appendChild(varidDiv);
var initialvalueDiv = document.createElement('div'); ;
initialvalueDiv.id = variables[i].variableID + "initialvalue";
initialvalueDiv.className = "initialvalueDiv";
initialvalueDiv.appendChild(document.createTextNode("Initial Value : " + variables[i].value));
initialvalue.appendChild(initialvalueDiv);
var valuelockDiv = document.createElement('div');
valuelockDiv.id = variables[i].variableID + "valuelock";
valuelockDiv.className = "valuelockDiv ";
valuelockDiv.appendChild(document.createTextNode("Value : " + variables[i].value));
valuelockDiv.appendChild(document.createTextNode("Lock : " + variables[i].locked.toString()));
valuelock.appendChild(valuelockDiv);
variableIDArray[variables[i].variableID];
}
};
function showvariable(varid) {
for (v in variableIDArray)
hide(variableIDArray[v]);
show(varid + "description");
show(varid + "varid");
show(varid + "initialvalue");
show(varid + "valuelock");
}
function show(elemid) {
document.getElementById(elemid).style.display = "block";
}
function hide(elemid) {
document.getElementById(elemid).style.display = "none";
}
Yes. jQuery. Will reduce your code to about 6 lines. :) http://jquery.com