I have a problem with putting a variable into my array. Here is my code:
var info = new Array();
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("http://www.ntvmsnbc.com/id/24927681/device/rss/rss.xml");
feed.setNumEntries(6);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
var html = '';
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var a = " " ;
a += entry.title;
info[i] = a
html += '<p>' + entry.publishedDate + ' ' + entry.title;
}
container.innerHTML = html;
}
alert(info[0]);
});
//alert(info[0]);
}
//alert(info[0]);
google.setOnLoadCallback(initialize);
You see an array called info. I'm trying to add entry.title into it. You can see some places are commented out. There my info[0] is empty. I can display my result only in function(result), except that it doesn't display anything like I never put anything inside my array. I didn't understand why.
Updated:
var info = new Array();
google.load("feeds", "1");
function initialize(cb) {
var feed = new google.feeds.Feed("http://www.ntvmsnbc.com/id/24927681/device/rss/rss.xml");
feed.setNumEntries(6);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
var html = '';
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
html += '<p>' + entry.publishedDate + ' ' + entry.title;
cb(entry.title);
}
container.innerHTML = html;
}
});
}
google.setOnLoadCallback(function(){
initizalize(processInfo);}
);
function processInfo(information){
info[info.length] = information;
alert(info[info.length]);
}
Last Version
var info = new Array();
google.load("feeds", "1");
function initialize(cb) {
var feed = new google.feeds.Feed("http://www.ntvmsnbc.com/id/24927681/device/rss/rss.xml");
feed.setNumEntries(6);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
var html = '';
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var a= " ";
a += entry.title;
info[i] = a;
html += '<p>' + entry.publishedDate + ' ' + entry.title;
}
container.innerHTML = html;
}
cb(info);
});
}
google.setOnLoadCallback(function(){
initizalize(processInfo);}
);
function processInfo(info){
alert(info[0]);
}
That's because AJAX is Asynchronous, basically meaning it won't run until at least the rest of the code has been run. Anything that relies on stuff that's defined an an AJAX call (or any other asynchronous callback) MUST be inside that callback, or itself deferred until later.
Make sure result.feed.entries.length is non-zero and that you are actually executing the for loop. Also (but minor) it wouldn't hurt to have a ; after the info[i] = a
You can't display info in those points because the call to feed.load() is asynchronous, and hasn't finished by that point.
You need to make all processing continue in the .load callback function, e.g. something like:
function initialize(cb) {
feed.load(function(result) {
...
cb(info); // only call the callback once the data is loaded
});
}
// call the above function, passing a callback handler
google.setOnLoadCallback(function() {
initialize(processInfo);
}));
// defer all of your data processing to here
function processInfo(info) {
...
}
Related
This is what I currently have:
var casper = require('casper').create();
var fs = require('fs');
var folderName = 'CARD_DATA';
var fileName = 'allChampionDecks.txt';
var save = fs.pathJoin(fs.workingDirectory, folderName, fileName);
// init jquery
var casper = require('casper').create({
clientScripts: ['jquery.min.js']
});
casper.start(URL, function() {
});
var links = ["http://magic.wizards.com/en/events/coverage/mtgochamp14","http://magic.wizards.com/node/335986","http://magic.wizards.com/en/events/coverage/2014WC"];
var i = -1;
var linkData = '';
// iterate
casper.then(function() {
this.each(links, function() {
i++;
this.thenOpen((links[i]), function() {
linkData += this.evaluate(getLinkDeckData);
});
});
fs.write(save, linkData + '\n', 'w');
});
// scrape
function getLinkDeckData() {
var meta = $('.deck-meta h4');
var event = $('.deck-meta h5');
var allDecks = $('.toggle-text .deck-list-text');
var json = '{';
for(var i = 0; i < meta.length; i++) {
json += '"event": "'+$(event[i]).text().trim()+'",'
+'"deckName": "'+$(meta[i]).text()+'",'
+'"deck": [';
var cardCount = $(allDecks[i]).find('.sorted-by-overview-container .row .card-count');
var cardName = $(allDecks[i]).find('.sorted-by-overview-container .row .card-name');
for(var j = 0; j < cardCount.length; j++) {
if(j < cardCount.length-1)
json += '{"quantity":"'+$(cardCount[j]).text()+'", "name":"'+$(cardName[j]).text()+'"},';
else
json += '{"quantity":"'+$(cardCount[j]).text()+'", "name":"'+$(cardName[j]).text()+'"}';
}
json += '],'
+'"sideboard": [';
var cardCount = $(allDecks[i]).find('.sorted-by-sideboard-container .row .card-count');
var cardName = $(allDecks[i]).find('.sorted-by-sideboard-container .row .card-name');
for(var j = 0; j < cardCount.length; j++) {
if(j < cardCount.length-1)
json += '{"quantity":"'+$(cardCount[j]).text()+'", "name":"'+$(cardName[j]).text()+'"},';
else
json += '{"quantity":"'+$(cardCount[j]).text()+'", "name":"'+$(cardName[j]).text()+'"}';
}
if(i < meta.length-1)
json += '],'
else
json += ']}'
/**/
}
return json;
}
casper.run();
I'm trying to iterate through some links to scrape some data. I'm not getting any errors but linkData is empty and nothing is written to the file.
For a single page I used the following and it works fine:
casper.start(URL, function() {
var data = this.evaluate(getLinkDeckData);
fs.write(save, data + '\n', 'w');
});
All then* (and wait*) functions are asynchronous step functions. When you make a loop and inside the loop call casper.thenOpen() then you schedule an opening step with an accompanying then callback as a separate step.
The problem is that when you try to write linkData, it is not in a separate step. Simply wrap it in casper.then() and it will work.
Fixed snippet:
casper.then(function() {
links.forEach(links, function(link, i) {
this.thenOpen(link, function() {
linkData += this.evaluate(getLinkDeckData);
});
});
this.then(function(){
fs.write(save, linkData + '\n', 'w');
});
});
Instead of using CasperJS' each, you should use Array.prototype.forEach. That way, you don't need a global counter variable.
Hope someone can help - I'm new to js/jQuery so I'm hoping it's something really simple I'm missing here.
I'm trying to populate a dropdownlist with the xml result from below. The parseXML function works great and the result.push(valueid + "," + value) leaves me with the following:
1,Service
2,Breakdown
How do I get this into a dropdownlist please? Using the below, I get the error "Object doesn't support property or method 'split'"
Many thanks
leddy
function testFunction() {
var jobresults = "<resultset morerecords='0'> " +
"<result> " +
"<itt_jobtypeid>1</itt_jobtypeid> " +
"<itt_name>Service</itt_name> " +
"</result> " +
"<result> " +
"<itt_jobtypeid>2</itt_jobtypeid> " +
"<itt_name>Breakdown</itt_name> " +
"</result> " +
"</resultset> ";
var xml = parseXML(jobresults);
var jobid = xml.getElementsByTagName("itt_jobtypeid");
var jobname = xml.getElementsByTagName("itt_name");
var result = [];
for (var i = 0; i < jobid.length; i++) {
var valueid = jobid[i].childNodes[0].nodeValue;
var value = jobname[i].childNodes[0].nodeValue;
// add longitude value to "result" array
result.push(valueid + "," + value);
}
var jobtype = $("#ddlJobType");
$.each(result, function () {
var arr = result.split(',');
for (var i = 0; i < arr.length; i++) {
jobtype.append($("<option />").val(arr[0]).text(arr[1]));
}
});
}
function parseXML(text) {
if (window.DOMParser) {
parser = new DOMParser();
doc = parser.parseFromString(text, "text/xml");
}
else { // Internet Explorer
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(text);
}
return doc;
}
It can be simpler and cleaner if you optimize data structure for result array. Push an object with value and label so that you can simply use attr method directly after:
for (var i = 0; i < jobid.length; i++) {
var valueid = jobid[i].childNodes[0].nodeValue;
var value = jobname[i].childNodes[0].nodeValue;
// add longitude value to "result" array
result.push({value: valueid, label: value});
}
var jobtype = $("#ddlJobType");
$.each(result, function (i, obj) {
$('<option>').attr(obj).appendTo(jobtype);
});
See https://api.jquery.com/jquery.each/. The callback function gets each jobtype as parameter to the function.
Try changing the code to:
$.each(result, function (idx, value) {
var arr = value.split(',');
for (var i = 0; i < arr.length; i++) {
jobtype.append($("<option />").val(arr[0]).text(arr[1]));
}
});
I have the following code:
PHP code:
$data = array();
$data[0]['name'] = "Kj";
$data[0]['age'] = 30;
$data[0]['country'] = "Italy";
$data[1]['name'] = "Dn";
$data[1]['age'] = 18;
$data[1]['country'] = "USA";
$data[2]['name'] = "Jo";
$data[2]['age'] = 22;
$data[2]['country'] = "Switzerland";
$data[3]['name'] = "Ro";
$data[3]['age'] = 34;
$data[3]['country'] = "UAE";
$data[4]['name'] = "Lc";
$data[4]['age'] = 13;
$data[4]['country'] = "UK";
echo json_encode($data);
Javascript code:
var jsonData = {};
$(document).ready(function () {
$.get('page.php', function (data) {
jsonData = jQuery.parseJSON(data);
});
});
for (var i = 0; i < jsonData.length; i++) {
$('ul').append("<li>" + jsonData[i].name + "</li>");
}
The problem is when put the for loop inside the $.get callback works fine like as the following.
$.get('page.php', function (data) {
jsonData = jQuery.parseJSON(data);
for (var i = 0; i < jsonData.length; i++) {
$('ul').append("<li>" + jsonData[i].name + "</li>");
}
});
But when put the for loop outside the $.get callback does not print out anything, but the data has been received successfully, but without print it.
Now, how can store the data that has been received in global variable to print it in anywhere ?
You should change your approach when you work with asynchronous operations (AJAX, timeouts). Something like this:
function GetData(callback) {
$.get('page.php', function (data) {
callback(jQuery.parseJSON(data));
});
}
GetData(function (data) {
for (var i = 0; i < data.length; i++) {
$('ul').append("<li>" + data[i].name + "</li>");
}
});
Your code already stores data in a global variable correctly.
Type jsonData into F12-javascript console and you will see it.
The question is rather about the control flow, what is the other event that will trigger usage of jsonData?
I'm trying to make an image slider that changes the image 'displayMain' every few seconds. My problem is that when I call the displayMain function in setInterval, I continuously get a 'cannot read property 0 of undefined' error. Even when I use the hardcoded value of jsonData[i].name, I receive the same error. The value gets passed in displayThumbs just fine, however. Does anyone know why I can't retain the values in displayMain but can do so in displayThumbs?
window.addEventListener('load', function () {
var mainDiv = document.getElementById('main');
var descDiv = document.getElementById('main-description');
var gallery = document.querySelector('#main-img');
var ul = document.querySelector('ul');
var li;
var i = 0;
var displayThumbs;
var thumbName;
var current = 0;
var images = [];
function displayMain () {
var data = images[i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
}
function displayThumbs () {
for (i = 0; i < images.length; i += 1) {
var data = jsonData[i].name.replace('.jpg', '_thumb.jpg');
// thumbnails use dom to make img tag
li = document.createElement('li');
thumbs[i] = document.createElement('img');
var createThumbNail = thumbs[i].src = 'img/' + data;
thumbs[i].setAttribute('alt', data);
thumbs[i].addEventListener('click', function() {
alert(createThumbNail);
});
ul.appendChild(thumbs[i]);
}
}
// success handler should be called
var getImages = function () {
// create the XHR object
xhr = new XMLHttpRequest();
// prepare the request
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4 && xhr.status == 200) {
// good request ...
jsonData = JSON.parse(xhr.responseText);
for (var i = 0; i < jsonData.length; i += 1) {
var data = [];
data.push(jsonData[i].name);
data.push(jsonData[i].description);
images.push(data);
}
displayMain();
displayThumbs();
setInterval(displayMain, 1000);
}
else {
// error
}
});
xhr.open('GET', 'data/imagedata.json', true);
xhr.send(null);
};
// setInterval(getImages, 2000);
getImages();
// displayThumbs();
});
Your problem is that your displayMain uses whatever value i is at the time, and i never gets incremented, so it'll be equal to images.length after the for loop in displayThumbs. displayThumbs increments it itself, so you won't ever go beyond the end of the array.
In your comment, you mentioned that you want to cycle through the images. This should work a bit better:
function displayMain () {
var data;
// wrap around to the first image
if (i >= images.length) {
i = 0;
}
data = images[i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
i++;
}
Personally, I would use a private i, just in case another function reuses the same variable:
function displayMain () {
var data;
// wrap around to the first image
if (displayMain.i >= images.length || isNaN(displayMain.i)) {
displayMain.i = 0;
}
data = images[displayMain.i];
gallery.src = 'img/' + data[0];
descDiv.innerHTML = '<h2>' + data[1] + '</h2>';
// move to the next image
displayMain.i++;
}
This attaches a variable named i to the function displayMain. It will update this variable each time it is called, and no other function will use the same i variable.
While trying out jQuery, I have a question that is probably a newbie mistake, but I cannot seem to find the solution. This is the code:
$.get("index.html", function() {
var i = 0;
for (; i < 3; i++)
{
var lDiv = document.createElement('div');
lDiv.id = 'body-' + i;
document.getElementById('body').appendChild(lDiv);
$.get('index.html', function(data) {
lDiv.innerHTML = "<p>Hello World " + i + "</p>";
});
}
});
The output seems to be
<div id='body-0'></div>
<div id='body-1'></div>
<div id='body-2'>
<p>Hello World 3</p>
</div>
I expected the lDiv.innerHTML= code to be executed for each i, but apparently it is only executed for the last i? What am I overlooking?
This happens because the loop completes (i is 2) before any of the callbacks are fired.
#thecodeparadox's solution works, but it serializes the HTTP requests. (Makes them fire one-at-a-time.) This allows the requests to execute in parallel, and thus quicker:
for (var i = 0; i < 3; i++)
{
var lDiv = document.createElement('div');
lDiv.id = 'body-' + i;
document.getElementById('body').appendChild(lDiv);
$.get('index.html', function(i,lDiv) { // the current iteration's `i` and `lDiv` are captured...
return function(data) {
lDiv.innerHTML = "<p>Hello World " + i + "</p>";
}
}(i,lDiv)); // ...by passing them as an argument to the self-executing function
}
As $.get() is asynchronous, so you need to execute your append and next call within $.get()'s success() callback function.
var i = 0;
function recursiveLoad() {
if(i == 3) return;
var lDiv = document.createElement('div');
lDiv.id = 'body-' + i;
document.getElementById('body').appendChild(lDiv);
$.get('index.html', function(data) {
lDiv.innerHTML = "<p>Hello World " + i + "</p>";
i++;
recursiveLoad();
});
}
// initial call
recursiveLoad();