jQuery getJSON never enters its callback function - javascript

I've been sitting with this for hours now, and I cant understand why.
q is working. The URL does give me a proper JSON-response. It shows up as objects and arrays and whatnot under the JSON tab under the Net-tab in Firebug and all is fine. I've also tried with other URLs that i know work. Same thing happens.
I have another function elsewhere in my tiny app, wihch works fine, and is pretty much exactly the same thing, just another API and is called from elsewhere. Works fine, and the data variable is filled when it enters the getJSON-function. Here, data never gets filled with anything.
I've had breakpoints on every single line in Firebug, with no result. Nothing happens. It simply reaches the getJSON-line, and then skips to the debugger-statement after the function.
var usedTagCount = 10;
var searchHits = 20;
var apiKey = "a68277b574f4529ace610c2c8386b0ba";
var searchAPI = "http://www.flickr.com/services/rest/?method=flickr.photos.search&" +
"format=json&api_key=" + apiKey + "&sort=interestingness-desc&per_page="
+ searchHits + "&jsoncallback=?&nojsoncallback=1&tags=";
var tagString = "";
var flickrImageData = new Array();
function search(query) {
for(var i = 0; i < usedTagCount; i++) {
tagString += query[i].key + ",";
}
var q = searchAPI + tagString;
$.getJSON(q, function(data) {
debugger; /* It never gets here! */
$.each(data.photos.photo, function(i, item) {
debugger;
flickrImageData.push(item);
});
});
debugger;
return flickrImageData;
}
Example of request URL (q):
http://www.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=a68277b574f4529ace610c2c8386b0ba&sort=interestingness-desc&per_page=20&jsoncallback=?&tags=london,senior,iphone,royal,year,security,project,records,online,after,
I do wonder, since JSONView (the firefox plugin) cannot format it properly, that it isn't really JSON that is returned - the mime-type is text/html. Firebug, however, interprets it as JSON (as i stated above). And all the tag words come from another part of the app.

I think you might need to remove the
nojsoncallback=1
from your searchAPI string.
Flickr uses JSONP to enable cross domain calls. This method requires the JSON to be wrapped in a json callback, the nojsoncallback=1 parameter removes this wrapping.
EDIT: Apparently it works with nojsoncallback=1, I got this piece of code to work for me. What jQuery version are you using? JSONP is only available from 1.2 and up.
This works for me (slight modifications):
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var usedTagCount = 1;
var searchHits = 20;
var apiKey = "a68277b574f4529ace610c2c8386b0ba";
var searchAPI = "http://www.flickr.com/services/rest/?method=flickr.photos.search&" +
"format=json&api_key=" + apiKey + "&sort=interestingness-desc&per_page="
+ searchHits + "&jsoncallback=?&nojsoncallback=1&tags=";
var tagString = "";
var flickrImageData = new Array();
function search(query) {
tagString = query;
var q = searchAPI + tagString;
$.getJSON(q, function(data) {
$.each(data.photos.photo, function(i, item) {
debugger;
flickrImageData.push(item);
});
});
}
search("cat");
</script>

When I try the url: http://www.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=a68277b574f4529ace610c2c8386b0ba&sort=interestingness-desc&per_page=10&tags=mongo
it returns data, as it should -
try to change the getJSON to an $.ajax() and define a function jsonFlickrApi (data)
with the code you have in you callback function.
If that don't work - please post code to at jsbin.com <- so we can try it live - so much easier to debug.

Related

Access invocation URL in Swagger UI

In a custom JavaScript file in Swagger-UI I was trying to access the request URL because I needed to add it to a header before I submit the request.
After looking at the source for swagger UI, I've not been able to figure out how to access the request URL.
In a my custom JavaScript file I've cheated by stealing from the DOM using:
(function() {
$(function() {
$(".submit").click(function (e) {
// doesn't work
// log(SwaggerUi.Views.OperationView.invocationUrl);
var url = $($(this).parentsUntil(".operations")[3]).find(".path")[0].innerText;
log("URL: " + url);
});
});
})();
But being this is a hack, it will not work if the route had a parameter like so: url/{param}. To find the input param and replace would be another step I would rather not take.
Am I missing some easy way that would allow me to access the request URL something along the lines of: SwaggerUi.requestUrl
Devised solution to traverse the DOM to get the information needed instead of using the information being stored by Swagger-UI.
(note: using the embedded Swagger-UI given by Swashbuckle 5.4 your mileage may vary if you use a different version of Swagger-UI)
$(".submit").click(function (e) {
var originalUrl = $($(this).parentsUntil(".operations")[3]).find(".path")[0].innerText;
log(originalUrl);
var outputUrl = "";
$($(this).parentsUntil(".operations")[3])
.find("tbody.operation-params tr:contains('path')")
.find("input")
.each(function () {
var pathParam = $(this).attr('name');
log(pathParam);
var userInput = $(this).val();
log(userInput);
outputUrl = originalUrl.replace("{" + pathParam + "}", userInput);
log(outputUrl);
});
// final requestUrl or invocationUrl
var requestUrl = $(".footer h4").html().match(/: (\/[\w-]+)/)[1] + outputUrl;
});

Making a URL call again with $.get

I have a question regarding the following code:
var url = "http://apple.accuweather.com/adcbin/apple/Apple_find_city.asp?location="+escape(obj.extraLocCity)+","+obj.extraLocCountryCode;
$.get(url, function(data) {
var us = $(data).find('CityList').attr('us')*1;
var intl = $(data).find('CityList').attr('intl')*1;
var extra_cities = $(data).find('CityList').attr('extra_cities')*1;
var exist = intl + us + extra_cities;
If "exist" is "0", I would like to make the URL call again using a different "url" variable. Specifically, using "obj.extraLocNeighborhood" in place of "obj.extraLocCity". Any help would be greatly appreciated! Happy to provide more information if need be. Thank you in advance!
You might be looking for something like this
var url1 = "http://apple.accuweather.com/adcbin/apple/Apple_find_city.asp?location="+escape(obj.extraLocCity)+","+obj.extraLocCountryCode;
var url2 = "http://apple.accuweather.com/adcbin/apple/Apple_find_city.asp?location="+escape(obj.extraLocNeighborhood)+","+obj.extraLocCountryCode;
$.get(url1, function(data) {
var us = $(data).find('CityList').attr('us')*1;
var intl = $(data).find('CityList').attr('intl')*1;
var extra_cities = $(data).find('CityList').attr('extra_cities')*1;
var exist = intl + us + extra_cities;
if (!exist) {
$.get(url2, function(data) {
// do something here ....
});
}
);
Why make two calls when you can potentially do it in one? Could you add another parameter to your server handler to accept the neighborhood code in addition to the others and return both results and then handle results all in one shot?

Need help turning a jQuery object back into a string

(i am new. please bear with me.) I have a jquery object that I need to convert back to html to use. What I am doing is using jQuery's get to get the HTML DOM of a local file. The data returned is then made into an object and I perform some tweaks on it (like changing hrefs etc.)
$.get(imagePath + "bloghome.aspx", function (data) {
var pageHtml = $(data);
pageHtml.find('a').each(function () {
var longHref = $(this).attr('href');
var tmp = longHref.lastIndexOf('ID=');
var id = longHref.substring(tmp + 3) + '.htm';
var newHref = imagePath.concat(id);
$(this).attr('href', newHref);
});
});
the object is created in the second line and then i change the hrefs. What I need now is to turn that object back into a string so that I can write it to a file.
I am using PhoneGap but any help would be appreciated as I am stumped
You can do this way using pageHtml[0].outerHTML:
$.get(imagePath + "bloghome.aspx", function (data) {
var pageHtml = $(data);
pageHtml.find('a').each(function () {
var longHref = $(this).attr('href');
var tmp = longHref.lastIndexOf('ID=');
var id = longHref.substring(tmp + 3) + '.htm';
var newHref = imagePath.concat(id);
$(this).attr('href', newHref);
var htmlString = pageHtml[0].outerHTML; //<-- Here
});
});
from http://api.jquery.com/html/
console.log(pageHtml.html());
Can you just do
pageHtml.html();
?
EDIT: Using this will only give you the contents inside the main wrapping element, if you want the entire thing, you can use:
pageHtml[0].outerHTML;
instead.

Consuming OData Servie using DataJS

I have this javascript code in MVC view i try to call OData Service using Datajs :
$(document).ready(function() {
var temp = OData.read("http://odata.netflix.com/v1/Catalog/Genres", function (data, response) {
var x = 3;
});
});
i have a break-point on var x = 3; but unfortunately the break-point was never hit! if i put break-point on OData.Read i can see its calling the OData-Service but then the callback function never get fired , i dont know what im doing wrong?
Add this before calling OData.Read():
OData.defaultHttpClient.enableJsonpCallback = true;
Also your request doesn't specify format. Change the request string to: http://odata.netflix.com/v1/Catalog/Genres?$format=json&$callback=?callbackHere

Javascript/jQuery variables not giving expected values

Like others before me I'm struggling with scope in Javascript. (That and trying to read the darn stuff). I have checked some of the previous threads on this question but I cant seem to get them to apply correctly to my issuue.
In the example below, I want to manipulate the values in the tagsArr array, once the array has been fully populated. I declared the tagsArr variable outside the scope of the function in which it is populated in order to access it globally. But the variable doesn't seem to have the scope I expect - tagsArr.length is 0 at the point where I call output it to console on line 16.
$(function(){
var apiKey = [myapikey];
var tags = '';
var tagsArr = new Array();
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&user_id=46206266#N05&extras=date_taken,tags&format=json&jsoncallback=?', function(data){
$.each(data.photos.photo, function(i, item) {
var photoID = item.id;
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?', function(data){
if (data.photo.tags.tag != '') {
$.each(data.photo.tags.tag, function(j, item) {
tagsArr.push(item.raw);
});
}
});
tags = tagsArr.join('<br />');
console.debug(tagsArr.length);
});
$('#total-dragged').append(data.photos.total);
$('#types-dragged').append(tags);
});
});
Your calls to getJSON are asynchronous. Hence all the calls to the inner getJSON will still be outstanding by the time the console.debug line is reached. Hence the array length is still 0.
You need to run some extra code once the final getJSON call has completed.
$(function(){
var apiKey = [myapikey];
var tags = '';
var tagsArr = new Array();
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&user_id=46206266#N05&extras=date_taken,tags&format=json&jsoncallback=?', function(data){
var totalExpected = data.photos.total;
var totalFetched = 0;
$.each(data.photos.photo, function(i, item) {
var photoID = item.id;
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?', function(data){
if (data.photo.tags.tag != '') {
$.each(data.photo.tags.tag, function(j, item) {
tagsArr.push(item.raw);
totalFetched += 1;
if (totalFetched == totalExpected)
fetchComplete();
});
}
});
function fetchComplete()
{
tags = tagsArr.join('<br />');
console.debug(tagsArr.length);
}
});
$('#total-dragged').append(data.photos.total);
$('#types-dragged').append(tags);
});
});
This works assuming the total number of photos doesn't excede the default 100 per page, other wise you would need to tweak it.
That said I don't think using .each to fire off loads of getJSON requests makes a great deal of sense. I would refactor it so that only one call to getJSON is outstanding at any one time. Have the callback of one issue the next getJSON for the next photo until all have been pulled then do your completed code.
$.getJSON is asynchronous (the a in ajax). That means that by the time you get to console.debug(), getJSON is still getting. You'll need to do some extra work in the JSON callback.
The reason for this is that getJSON is an asynchronous request. after the call to $.getJSON, the javascript engine will move immediately on to the following two lines of code, and will output the length of your array, which is by then, zero-length. Not until after that does the getJSON request receive a response, and add items to the array.
The getJSON function is asynchronous, so when you call the debug function the array is still empty because the requests are not completed. Use the $.ajax function and set async:false and it will work.
$.ajax({
type: "GET",
url: 'http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?',
dataType: "json",
async:false,
success:function(data){
if (data.photo.tags.tag != '') {
$.each(data.photo.tags.tag, function(j, item) {
tagsArr.push(item.raw);
});
}
}
});
This isn't a scope issue - the problem is that getJSON is asynchronous, so it continues executing immediately after sending the request to flickr. By the time the browser executes console.debug the request hasn't returned and you haven't finished handling the response (and therefore haven't pushed any items into the array yet).
To solve this, find all the code that should only be executed when the array is full and move it into your getJSON callback method:
if (data.photo.tags.tag != '') {
$.each(data.photo.tags.tag, function(j, item) {
tagsArr.push(item.raw);
});
tags = tagsArr.join('<br />');
console.debug(tagsArr.length);
$('#total-dragged').append(data.photos.total);
$('#types-dragged').append(tags);
}
You may want to check the answer to this question I posted. There is some good information on scope issues in javascript.

Categories