data[ ] in jsonp - what it means? - javascript

I am making an API request to Wikipedia, and everything seems to work but I can't figure out the meaning for the few lines of code, precisely
var articleTitles = data[1];
var articleUrls = data[3];
I have no idea what do index data[1] and data[3] mean and how do I figure out them on my own. This is from the Udacity tutorial but this was not clarified in detail, I only know it has something to do with the response...
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + cityStr + '&format=json';
var wikiRequestTimeout = setTimeout(function () {
$wikiElem.text("Failed to get Wikipedia resources");
}, 5000);
$.ajax({
url: wikiUrl,
dataType: 'jsonp'
}).success(function(data) {
var articleTitles = data[1];
var articleUrls = data[3];
$.each(articleTitles, function(i, title) {
$wikiElem.append('<li>' + title + '</li>');
});
/* .error is not built into jsonp
*/
clearTimeout(wikiRequestTimeout); // clear timeout will stop timeout from happening
});
return false;

data is an object you can perceive it as an array (like) structure. It contains other arrays/objects inside of it, and to answer the question data[0] is the first of those child arrays and data[3] is the 4th one (it is a 0 based notation).
You can check this out - http://www.w3schools.com/json/json_syntax.asp

Related

How to iterate through json arrays

I'm stuck in a script here, not sure how to get it to print in the div I set up. I imagine it's something related to how I'm handling the response.
The response in chrome devtools looks like this:
{
"[\"record one\", \"/description\"]": 0
}
I've attempted to use both each and map to iterate the data out but so far not going anywhere. I'm brand new to js and jquery, so the script is mostly from reading and examples.
Maybe some kind of nested loop? Here is my code -
$(function() {
return $('#myslider').slider({
range: true,
min: 0,
max: 20,
values: [1, 20],
stop: function(event, ui) {
var max, min;
min = ui.values[0];
max = ui.values[1];
$('#range').text(min + ' - ' + max);
$.ajax({
url: '/dir_scan',
type: 'get',
data: {
min: min,
max: max
},
dataType: 'json',
success: function(response) {
var albums;
albums = response;
$.each(albums, function(index, obj) {
var albumname, artist, li_tag;
li_tag = '';
albumname = obj.AlbumName;
artist = obj.Artist;
li_tag += '<li>Artist: ' + artist + ', Album: ' + albumname + '</li>';
$('#result').append($(li_tag));
return console.log;
});
}
});
}
});
});
As Will said in the comments, the JSON looks off.
But, you're on the right track of using .each, as it looks that you're returning an array of objects.
Here's an example of what to do:
var li_tag = '';
$.each(albums, function(index, obj) {
var albumname = obj.AlbumName;
var artist = obj.Artist
li_tag += '<li>Artist: ' + artist + ', Album: ' + albumname + '</li>';
$('#result').append($(li_tag));
return console.log;
});
Additionally, 'albums' should be set to the returned response of the success function. You're potentially creating a bunch of headache to try and decipher from the window.location; especially since the json example looks malformed. And, any work done with the data returned from the ajax call, should occur in the success function.
Here is how iteration worked for this situation. Comments in code -
success: function(response) {
var albums;
// side issue - but I had to clear the div to get a complete refresh
$('#result').empty();
albums = response;
$.each(albums, function(key, value) {
var albumname, li_tag, path;
li_tag = '';
// I found I had to do this parseJSON call otherwise
// I had no correct key/value pair, even though I had set dataType
// to JSON
albumname = jQuery.parseJSON(key);
path = albumname[1];
li_tag += '<li ><a href=/album' + encodeURI(albumname[1]) + '>' + albumname[0] + '</a href></li>';
$('#result').append($(li_tag));
return console.log;
});
Actually, value in the code is just the index number, but I had the actual key/value pair separated by commas, so again the parseJSON seemed to be the only way it would work. This, despite trying things like split and substr. Hope my answer is clear if not I can edit.

Clean way to make Subsequent AJAX Calls to API based on Data

So I have a conceptual question regarding the cleanest way to make subsequent AJAX calls to an API based on the returned data.
A quick example:
A function, which encompasses the call would look like this:
function makeCall(headers, min, max) {
$.ajax({
headers: headers,
url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000",
type: "GET",
dataType: 'JSON'
});
}
makeCall(headers, 0, 20);
The beg / end index (min/max), determine the amount of data I'll get back in the array. The API will only return a maximum of 20 items in the array, but it will also return me a COUNT of how many items total exist in that array. An example of the data returned is below:
{
count = 133;
result = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19];
}
So my next call would be:
makeCall(headers, 20, 40);
and so on so forth, until I got all 133 items from the array.
The question is...what is the cleanest way to continue to make subsequent calls until I've gotten and stored all 133 items from the array? Given that the count could be any number, it's hard to imagine how I can do this. I was thinking of nesting more ajax calls in a "success" function, but it's not scalable if I get back a number like 300.
Does anyone have any advice on how to proceed?
Thanks in advance!
EDIT:
So based on the advice in the comment, I've attemped to make the call recursive--but it doesn't seem to function as intended:
var theData = [];
var minCounter=0;
var maxCounter= minCounter + 20;
function makeCall(headers, min, max) {
$.ajax({
headers: headers,
url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000",
type: "GET",
dataType: 'JSON',
success: function (data) {
theData.push(data.result);
newMin = minCounter + 20;
if (data.count >= theData.length ) {
makeCall(headers, newMin, maxCounter);
}
}
});
}
makeCall(headers, minCounter, maxCounter);
How do properly increment the variable as well as set the flag?
SECOND EDIT:
The method below works using the second comment's suggestion, but there are some issues here as well...
function doAjax(headers, min, dObject) {
var max = min + 20;
$.ajax({
headers: headers,
url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000",
type: "GET",
dataType: 'JSON',
success: function (data) {
results.push(data);
window.count = data.count;
dObject.resolve();
}
});
}
// array that will contain all deferred objects
var deferreds = [];
// array that will contain all results
var results = [];
// make the ajax calls
for (var i = 20; i < 133 ; i+= 20) {
var dObject = new $.Deferred();
deferreds.push(dObject);
doAjax(headers, i, dObject);
}
// check if all ajax calls have finished
$.when.apply($, deferreds).done(function() {
console.log(results);
});
var dObject = new $.Deferred();
doAjax(headers,0, dObject);
First, the data doesn't push to the array in order. There doesn't seem anyway to fix this. Also strangely enough, in the for loop--I have to set the number for it to actually work. Trying to store it in a variable doesn't seem to work as well...Suggestions here?
Here's a working implementation based around the code you started with. Code is commented to help you understand what is happening:
// Change these constants to suit your purposes.
var API_URL = 'https://coolapi.com/data';
var HEADERS = {};
var API_RESULTS_PER_REQUEST = 20;
var MAX_API_CALLS = 20;
// Count API calls to trigger MAX_API_CALLS safety lock.
var apiCalls = 0;
// Function we'll call to get all our data (see bottom).
function collectApiData(begTimestamp, endTimestamp) {
var dataReady = jQuery.Deferred();
var params = {
'begTimestamp': begTimestamp,
'endTimestamp': endTimestamp
};
var datasetsCollected = requestDatasets(params);
jQuery.when(datasetsCollected).then(function(data) {
dataReady.resolve(data);
});
return dataReady;
}
// Makes individual AJAX call to API
function callApi(params, headers) {
var $request = jQuery.ajax({
url: API_URL,
headers: headers,
data: params,
type: 'GET',
dataType: 'JSON'
});
return $request;
}
// Recursive function that makes API calls until data is collected, there is an
// error, or MAX_API_CALLS limit is hit.
function requestDatasets(params, resultsReady, resultsFetched) {
resultsReady = ( resultsReady !== undefined ) ? resultsReady : jQuery.Deferred();
resultsFetched = ( resultsFetched !== undefined ) ? resultsFetched : [];
// Trigger safety to avoid API abuse
if ( apiCalls >= MAX_API_CALLS ) {
console.error('Exceeded max API calls:', MAX_API_CALLS);
resultsReady.resolve(resultsFetched);
}
// Set index data
params.begIndex = resultsFetched.length;
params.endIndex = resultsFetched.length + API_RESULTS_PER_REQUEST;
// Request dataset from API
var apiRequest = callApi(params, HEADERS);
apiCalls += 1;
// Callback once API request has completed and data is ready
jQuery.when(apiRequest).done(function(data) {
var apiResultCount = data.count;
resultsFetched = resultsFetched.concat(data.result);
console.debug('Fetched', resultsFetched.length, 'of', apiResultCount, 'API results');
if ( apiResultCount > resultsFetched.length ) {
console.debug('Making another API call');
requestDatasets(params, resultsReady, resultsFetched);
}
else {
console.debug('Results all fetched!');
resultsReady.resolve(resultsFetched);
}
});
jQuery.when(apiRequest).fail(function(data) {
console.error('API error: returning current results.');
resultsReady.resolve(resultsFetched);
});
return resultsReady;
}
// Run script
var dataReady = collectApiData('1404198000000', '1409554800000');
jQuery.when(dataReady).then(function(data) {
console.log(data);
});
Here's a working fiddle that mocks the API using httpbin.org:
http://jsfiddle.net/klenwell/mfhLxun2/

Twitter API - no encoding

I'm currently working on a project for university. we are trying to use the twitter api but we are having some trouble with the query. I want to search a complete string, therefore I need to put my string in quote sings.( like "I'm seraching for this whole sting")
the problem is that the command I use to get the array from twitter somehow encodes the whole string but I need the quote sings to not be encoded. I hope you guys understand my problem. in addition i'll post my js code.
JS CODE: first I tryed a json command but it didnt work. afterwards I tryed ajax but I ran into the same problem. I don't get a response when I use quote signs in my query.
$( document ).ready(function()
{
console.log("ready");
// div mit id unique1 - bei klick mache onClick1
$('a#unique1').bind('click', onClick1);
});
function onClick1(elem)
{
var inputString = $("#SearchInput").val();
var EncodedString = encodeURI(inputString);
console.log('test' + inputString);
var endNode = 'search/tweets.json?q=hate%20' + EncodedString + '&result_type=mixed&count=200';
/*
$.getJSON('twitter/twitter-proxy.php?url='+encodeURIComponent(endNode),
*/
$.ajax({
type: "GET",
url: 'twitter/twitter-proxy.php?url='+encodeURIComponent(endNode),
data: " ",
success: function(twitterResponse){
var respStr = "start";
console.log(twitterResponse);
console.log(twitterResponse.statuses);
for(var i = 0; i < twitterResponse.statuses.length; i++)
{
$('.container .apiCall ol').append('<li>'+ twitterResponse.statuses[i].created_at + '</br>' + twitterResponse.statuses[i].text.toLowerCase() + '</li>');
respStr = respStr + twitterResponse.statuses[i].created_at + twitterResponse.statuses[i].text.toLowerCase();
}
}
});
/*
function(twitterResponse)
{
var respStr = "start";
console.log(twitterResponse);
console.log(twitterResponse.statuses);
for(var i = 0; i < twitterResponse.statuses.length; i++)
{
$('.container .apiCall ol').append('<li>'+ twitterResponse.statuses[i].created_at + '</br>' + twitterResponse.statuses[i].text.toLowerCase() + '</li>');
respStr = respStr + twitterResponse.statuses[i].created_at + twitterResponse.statuses[i].text.toLowerCase();
}
*/
/*
// respSgtr = " ";
// write tweets to file
$.post("writer.php", { fileString:respStr},
function(response)
{
//alert("Data Loaded: " + data);
});
});*/
}
Your approach is flawed.
jQuery does all the parameter encoding for you. Don't interfere, just pass an object which contains keys and values. Do not build URLs from individual bits of string.
Important security consideration: Don't build a server-side proxy script that accepts any arbitrary URL. Doing this is plain stupid.
Instead change your PHP script to accept a set of operation verbs, like "search", which are hard-wired to the correct URL on the server side.
I recommend using $.get() and $.post() over $.ajax(), for the benefit of cleaner code.
Further, use $.each() rather than a regular for loop. The resulting code will be cleaner and easier to read.
Avoid building HTML from bits of string. Especially if the bits of string come from a completely untrustworthy source, like Twitter. Use jQuery's capabilities and the DOM to build HTML safely. (read about XSS vulnerabilities if you're not sure why I bring this up)
Suggested solution (appendText() jQuery plugin taken from here):
$.fn.appendText = function(text) {
return this.each(function() {
var textNode = document.createTextNode(text);
$(this).append(textNode);
});
};
$(function () {
$('a#unique1').on('click', function (event) {
$.get('twitter/twitter-proxy.php', {
operation: 'search',
params: {
q: 'hate ' + $("#SearchInput").val(),
result_type: 'mixed',
count: 200
}
}).done(function (twitterResponse) {
$.each(twitterResponse.statuses, function (index, status) {
$("<li>")
.appendText(status.created_at)
.append("<br>")
.appendText(status.text.toLowerCase())
.appendTo(".container .apiCall ol");
});
});
});
});

iterating over table rows and executing setInterval per row does not seem to work

I'm trying update a value of a cell from Offline to Online (and vice-versa) inside my DataTable by accessing a web service.
var $myTable = $("#my-table").dataTable();
var $myTableRows = $myTable.fnGetNodes();
for(var i=0; i<$myTableRows.length; i++) {
var $currentRowCount = i;
var $interval = $($myTableRows[i]).find("td:eq(9)").html();
var $timeout = $($myTableRows[i]).find("td:eq(10)").html();
var $dataINeedToPass = $($myTableRows[i]).find("td span:eq(4)").html();
setInterval(function() { updateStuffOnTheTable($interval, $timeout, $dataINeedToPass, i); }, 4000);
}
function updateStuffOnTheTable(interval, timeout, dataINeedToPass, row) {
var $stuff = "Offline";
var ajaxCall = $.ajax({
url : "https://localhost:8443/cxf/mywebservice/" + dataINeedToPass,
type : "GET",
dataType : 'text',
timeout: 2000
}).done(function(data) {
$stuff = "Online";
})
.fail(function(data) {
$stuff = "Offline";
})
.always(function(data) {
$myTable.fnUpdate($stuff, row, 2);
})
}
The problem is, the AJAX request only executes once instead of every 4000ms. What am I missing here?
Its probably working as intented, except that the browser will keep obtaining the requested data from cache, because you keep querying the same URL.
To workaround this, its common practice to add a dummy variable to the querystring with the time of the query or a random number, it will change the URL forcing the browser to retrieve it from the server again.
So basically you can declare var now = new Date(); on your function updateStuffOnTheTable and then mount your URL like this:
"https://localhost:8443/cxf/mywebservice/" + dataINeedToPass + '?now=' + now.getTime()
You may also try to solve this by using POST requests, sinse AJAX POST requests are not cached.

Store items in array with using them later

I have code, which get json file from server and then render some if its elements on the page. In this code i also skip items with duplicate value of key "points". My question is, how do i make these skipped items to store somewhere, so if i click on item that has duplicate, it would link me to some other page with list of these duplicates?
Here is my code
var request = $.ajax({
type: "GET",
url: "example.com/rewards.json"
dataType: "json",
error: function (data, textStatus){
console.log( "it`s error" );
console.log( status );
console.log( data );},
success: function (data, textStatus){
console.log( "success" );
console.log( status );
console.log( data );
}
})
request.success(function(data, textStatus){
var lis = "";
var arr = [];
var iter = 0;
$.each(data.rewards, function(key, val){
if ($.inArray(val.points, arr) == -1)
{
lis += "<div class = 'ui-block-" + String.fromCharCode(97 + iter%3) + "'><a href ='#' class ='ui-link-inherit'>" + val.points + "</a></div>";
arr.push(val.points);
iter += 1;
}
});
$("#rewards_table").html(lis);
})
Description of what i want might be a little confusable, so feel free to ask me anything
You just do exactly that: Store them somewhere for use later.
For example, put this line at the top of your code:
var duplicates = [];
...and add this else to the if inside your $.each iterator function:
else
{
duplicates.push(val.points);
}
(I think I got your bracing style right there, a bit alien to me. :-) )
The above assumes all of your code is held in some kind of containing function, to avoid creating globals, and so duplicates (like your existing request variable) won't end up becoming a global.

Categories