Friends,
Currently I'm implementing twitch.tv app using json as my part of my freecodecamp course. Using twitch api, I have to call json twice, to get user and stream data. I also do this in the loop, as I have multiple streamers I want to follow. Here you can see my code.
$(document).ready(function() {
var streamerList = ["MisterRogers","freecodecamp"];
getStream(streamerList);
});
function getStream(streamerList) {
for (var k = 0; k < streamerList.length; k++) {
var userURL = makeURL("users", streamerList[k]);
var streamURL = makeURL("streams", streamerList[k]);
$.getJSON(userURL, function(data) {
var displayName = data.display_name;
var logo = data.logo;
$.getJSON(streamURL, function(data){
var status, game;
console.log(data);
if (data.stream === null){
status = 'Offline';
game = 'No Content Available';
} else if (data.stream === undefined){
status = 'Not available'
game = 'Channel Closed';
} else {
status = 'Online';
game = data.stream.game;
}
addRow(displayName, logo, status, game);
});
});
}
}
In the example I use two streamers (freecodecamp and Mister Rogers), one of them is online, and the other offline. However, the data at the second json call is being messed up and in my app I see them both as offline. Its working fine if I remove freecodecamp or Mister Rogers and leave only one streamer. But two or more are not working. I'm quite new to js, so if you could explain the gaps in my logic, I would be very grateful. Cheers.
I managed to solve this problem by myself with some examples I found on internet. The problem with this code was that in the $(document).ready(function(){}) I pass string array streamerList as an argument for getStream() function, however, the streamerList variable is not seen within the second call of JSON (look at the code above). Because that call is in the function of first JSON call. Due to this reason, streamURL in the second call becomes undefined. To solve this issue I had to make variable streamerList global and run foreach loop. Here is my working solution:
var streamerList = ["MisterRogers", "freecodecamp"];
function getStream() {
streamerList.forEach(function(channel) {
function makeURL(type, streamer) {
return (
"https://wind-bow.gomix.me/twitch-api/" +
type +
"/" +
streamer +
"?callback=?"
);
}
$.getJSON(makeURL("streams", channel), function(data) {
var status, game;
if (data.stream === null) {
status = "Offline";
game = "No Content Available";
} else if (data.stream === undefined) {
status = "Not available";
game = "Channel Closed";
} else {
status = "Online";
game = data.stream.game;
}
console.log(status, game);
$.getJSON(makeURL("users", channel), function(result) {
var displayName = result.display_name;
var logo = result.logo;
addRow(displayName, logo, status, game);
});
});
});
}
function addRow(displayName, logo, status, game) {
var divRow = document.createElement("div");
divRow.className = "row";
divRow.innerHTML =
'<div class="col-md-4"></div>\
<div class="col-md-1"><img src="' +
logo +
'"/></div>\
<div class="col-md-3"><blockquote>\<p>\
<a href="http://www.twitch.tv/' +
displayName +
'" target="_blank">' +
displayName +
'</a></p>\
<footer><cite title="Source Title">' +
status +
": " +
game +
'</cite></footer></blockquote></div>\
<div class="col-md-1></div>';
document.getElementById("content").appendChild(divRow);
}
$(document).ready(function() {
getStream();
});
Related
I've got a problem with JSON in JavaScipt. I've got 2 different JSON URL. One of them contains data about users and the second one about posts. And in posts JSON I've got a field userId.
I want to find a way to connect them somehow. I need to get users and their posts and then count how many posts every user wrote.
var postRequest = new XMLHttpRequest();
postRequest.open('GET', 'https://jsonplaceholder.typicode.com/posts');
postRequest.onload = function() {
var posts = JSON.parse(postRequest.responseText);
var userRequest = new XMLHttpRequest();
userRequest.open('GET', 'https://jsonplaceholder.typicode.com/users');
userRequest.onload = function (){
var users = JSON.parse(userRequest.responseText);
for(k in users){
document.write("</br></br>"+ users[k].name +", " + users[k].username + ", " + users[k].email + "</br>" + "-------------------------------------------------------------------------------------" + "</br>");
for(k1 in posts){
if(posts[k1].userId===users[k].id){
document.write(posts[k1].body + "</br>");
}
}
}
};
userRequest.send();
};
postRequest.send();
but I think it doesn't look good. I want to get data from JSON to variable to use them later, in function for example.
Anyone help? I've never connected data from 2 JSON files and want to do it in a good way and getting good practice.
Use this instead
for(k in users){
for(k1 in posts){
if(posts[k1].userId===users[k].id){
if(!users[k].hasOwnProperty('posts')) {
users[k].posts = [];
}
users[k].posts.push(posts[k1].body);
}
}
}
if you could you jquery
$.when($.ajax({
url: "https://jsonplaceholder.typicode.com/users"
})).then(function(data, textStatus, jqXHR) {
$.each(data, function(index, value) {
$.ajax({
url: "https://jsonplaceholder.typicode.com/posts?userId=" + value.id
}).then(function(data, textStatus, jqXHR) {
console.log("UserID:" + data[0].userId + " Nos Posts:" + data.length);
});
});
});
You can try above code and let me know if it solve your purpose
Steps you can use :
1. You can add a body property in to the objects in users array as per the id and userid match.
2. Later you can iterate the users array whenever you want to use.
DEMO
var postRequest = new XMLHttpRequest();
postRequest.open('GET', 'https://jsonplaceholder.typicode.com/posts');
postRequest.onload = function() {
var posts = JSON.parse(postRequest.responseText);
var userRequest = new XMLHttpRequest();
userRequest.open('GET', 'https://jsonplaceholder.typicode.com/users');
userRequest.onload = function (){
var users = JSON.parse(userRequest.responseText);
for(k in users) {
for(k1 in posts) {
if(posts[k1].userId===users[k].id){
users[k].body = posts[k1].body;
}
}
}
console.log("users", users);
};
userRequest.send();
};
postRequest.send();
I want to develop an app for Pebble. This app is going to tell you how long it takes from one place you set in options to another one taking in account traffic jams and stuff.
To achieve this I need to make a page that will return JSON. Pebble retrieves information using code like that:
var cityName = 'London';
var URL = 'http://api.openweathermap.org/data/2.5/weather?q=' + cityName;
ajax(
{
url: URL,
type: 'json'
},
function(data) {
// Success!
console.log('Successfully fetched weather data!');
},
function(error) {
// Failure!
console.log('Failed fetching weather data: ' + error);
}
);
I created a small page with a js script that gets needed information from Yandex API:
var route;
ymaps.ready(init);
var myMap;
function init(){
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var time = 0;
var home = getParameterByName("h");
var work = getParameterByName("w");
ymaps.route([home, work],{avoidTrafficJams: true}).then(
function (router) {
route=router;
time = ((route.getTime())/60).toFixed(2);
var info = new Object;
info["home"] = home;
info["work"] = work;
info["time"] = ~~time+"m"+~~((time%1)*60)+"s";
JSON.stringify(info);
},
function (error) {
alert('Возникла ошибка: ' + error.message);
}
);
}
As you can see I can get a JSON string in the end. But how do I send it to clients when a request with right parameters is made?
I ended up using phantomjs and executing this js script on my php page.
I am getting a very strange issue whereby when I try to extract the word document as a compressed file for processing in my MS Word Task Pane MVC app the third time, it will blow up.
Here is the code:
Office.context.document.getFileAsync(Office.FileType.Compressed, function (result) {
if (result.status == "succeeded") {
var file = result.value;
file.getSliceAsync(0, function (resultSlice) {
//DO SOMETHING
});
} else {
//TODO: Service fault handling?
}
});
The error code that comes up is 5001. I am not sure how to fix this.
Please let me know if you have any thoughts on this.
Additional Details:
From MSDN:
No more than two documents are allowed to be in memory; otherwise the
getFileAsync operation will fail. Use the File.closeAsync method to
close the file when you are finished working with it.
Make sure you call File.closeAsync before you read the file again - that could explain the issue you are seeing.
More at: https://msdn.microsoft.com/en-us/library/office/jj715284.aspx
I have an example about how to use this API correctly. Actually the current example in the MSDN is not very correct. This code is tested in Word.
// Usually we encode the data in base64 format before sending it to server.
function encodeBase64(docData) {
var s = "";
for (var i = 0; i < docData.length; i++)
s += String.fromCharCode(docData[i]);
return window.btoa(s);
}
// Call getFileAsync() to start the retrieving file process.
function getFileAsyncInternal() {
Office.context.document.getFileAsync("compressed", { sliceSize: 10240 }, function (asyncResult) {
if (asyncResult.status == Office.AsyncResultStatus.Failed) {
document.getElementById("log").textContent = JSON.stringify(asyncResult);
}
else {
getAllSlices(asyncResult.value);
}
});
}
// Get all the slices of file from the host after "getFileAsync" is done.
function getAllSlices(file) {
var sliceCount = file.sliceCount;
var sliceIndex = 0;
var docdata = [];
var getSlice = function () {
file.getSliceAsync(sliceIndex, function (asyncResult) {
if (asyncResult.status == "succeeded") {
docdata = docdata.concat(asyncResult.value.data);
sliceIndex++;
if (sliceIndex == sliceCount) {
file.closeAsync();
onGetAllSlicesSucceeded(docdata);
}
else {
getSlice();
}
}
else {
file.closeAsync();
document.getElementById("log").textContent = JSON.stringify(asyncResult);
}
});
};
getSlice();
}
// Upload the docx file to server after obtaining all the bits from host.
function onGetAllSlicesSucceeded(docxData) {
$.ajax({
type: "POST",
url: "Handler.ashx",
data: encodeBase64(docxData),
contentType: "application/json; charset=utf-8",
}).done(function (data) {
document.getElementById("documentXmlContent").textContent = data;
}).fail(function (jqXHR, textStatus) {
});
}
You may find more information from here:
https://github.com/pkkj/AppForOfficeSample/tree/master/GetFileAsync
Hope this could help.
Additional to Keyjing Peng's answer (which I found very helpful, thanks!) I thought I'd share a variation on the encodeBase64, which you don't want to do if you are uploading via REST to SharePoint. In that case you want to convert the byte array to a Uint8Array. Only then could I get it into a SharePoint library without file corruption.
var uArray = new Uint8Array(docdata);
Hope this helps someone, couldn't find this info anywhere else online...
See this link
http://msdn.microsoft.com/en-us/library/office/jj715284(v=office.1501401).aspx
it contains this example method:
var i = 0;
var slices = 0;
function getDocumentAsPDF() {
Office.context.document.getFileAsync("pdf",{sliceSize: 2097152}, function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then
// result.value will return a valid File Object.
myFile = result.value;
slices = myFile.sliceCount;
document.getElementById("result").innerText = " File size:" + myFile.size + " #Slices: " + slices;
// Iterate over the file slices.
for ( i = 0; i < slices; i++) {
var slice = myFile.getSliceAsync(i, function (result) {
if (result.status == "succeeded") {
doSomethingWithChunk(result.value.data);
if (slices == i) // Means it's done traversing...
{
SendFileComplete();
}
}
else
document.getElementById("result").innerText = result.error.message;
});
}
myFile.closeAsync();
}
else
document.getElementById("result2").innerText = result.error.message;
});
}
change "pdf" to "compressed" and the method call doSomethingWithChunk() needs to be created and should probably do something like this:
function base64Encode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
I use this technique to successfully save to Azure blob storage.
Obviously you should rename the method as well.
I am trying to get the hereNow parameter from FourSquare using a checkins query on a specific user, unfrotunately I can't seem to get that parameter using checkins, I am seeing all other data regarding a venue except for the hereNow parameter.
Does anyone know how I can get that parameter using checkins? Otherwise, how can I incorporate venue objects and tie into my current code?
Here is my JavaScript to set hereNow as a variable:
var count;
getVenueStatus = function() {
var hereNowUrl = 'https://api.foursquare.com/v2/venues/VENUE_ID?&oauth_token=OAUTH_TOKEN&v=20140303';
$.getJSON(hereNowUrl, {format: "json"}, function(data) {
$(data.response.venue).each(function(index) {
$(this).each(function(index) {
var venue = this;
var hereNowCount = venue.hereNow.count;
count = hereNowCount;
console.log(count);
});
});
});
}
Here is my JavaScript to display the results on a map:
findFoodTrucks = function (param) {
getVenueStatus();
$.mobile.pageLoading();
var url = 'https://api.foursquare.com/v2/users/80507329/checkins?oauth_token=OAUTH_TOKEN&v=20140303';
var mapBounds = new google.maps.LatLngBounds();
if (param.userloc) mapBounds.extend(param.userloc);
$.getJSON(url, function(data) {
$(data.response.checkins).each(function(index) { // groups: nearby, trending
$(this.items).each(function(index) {
var foodtruck = this;
var foodtruckPosition = new google.maps.LatLng(foodtruck.venue.location.lat, foodtruck.venue.location.lng);
var foodtruckIcon = (count > 0) ? 'foodtruck_active.png' : 'foodtruck_inactive.png';
var foodtruckStreet = (foodtruck.venue.location.address) ? '<br>' + foodtruck.venue.location.address : '';
var foodtruckContent = '<strong>' + foodtruck.venue.name + '</strong>' + foodtruckStreet + '<br>';
mapBounds.extend(foodtruckPosition);
addFoodTruckMarker(foodtruckPosition, foodtruckIcon, foodtruckContent);
console.log(foodtruck);
});
if (param.zoomtotrucks) $('#map_canvas').gmap('getMap').fitBounds(mapBounds);
});
})
.error( function() {
loadFoodTrucks(param); //try again
})
.complete( function() {
$.mobile.pageLoading( true );
});
}
Thanks in advance!
The check-in response includes a compact venue, which is only sometimes guaranteed to have a hereNow field. To get the hereNow count, it's probably best to make a second venue detail API call.
PS: also noticed that you seemed to be passing an OAuth token and client ID/secret—in this case, you only need the OAuth token! Take a look at https://developer.foursquare.com/overview/auth for more info.
Hopefully there is an easy way to do this and my Javascript skills are just lacking. I am wanting to call a function that will get some Facebook posts, add them to an array and return to use elsewhere. Current code is below.
function GetFaceBookStream(name, max) {
FB.init({ apiKey: 'removed for post' });
var lastDate = '2011-04-29Z00:00:00';
var faceBookArray = [];
var faceBookString;
FB.api("/" + name + "/feed", { limit: max, since: lastDate }, function (response) {
var sb = string_buffer();
for (var i = 0; i < response.data.length; i++) {
var post = response.data[i];
sb.append("<li class='facebook'>");
sb.append("<img alt=\"Facebook\" src='Images\\Carousel\\fbIcon.png\' />");
sb.append("<h4>FACEBOOK</h4>\n");
sb.append("<div class=\"from-name\">" + post.from.name + "</div>");
sb.append("<div class=\"time\">" + post.created_time + "</div>");
if (post.message != undefined) {
sb.append("<div class=\"message\">" + post.message + "</div>");
}
sb.append("</li>stringSplitMarker");
}
faceBookString = sb.toString();
faceBookArray = faceBookString.split('stringSplitMarker');
});
return faceBookArray;
}
I realize this set up won't work due to variable scope in Javascript, but this is basically what I'm trying to achieve. Any help will be greatly appreciated!
You're making an asynchronous AJAX request.
The callback only runs after your code finishes.
You need to pass the data back using a callback.
For example:
function GetFaceBookStream(name, max, callback) {
...
FB.api(..., function(response) {
...
callback(something, else);
});
}
You can call the function by supplying a callback to receive the response:
GetFaceBookStream(name, max, function(param1, param2) {
//This code runs later and can use the response.
});